1 // Copyright (c) 2012- PPSSPP Project.
2 
3 // This program is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, version 2.0 or later versions.
6 
7 // This program is distributed in the hope that it will be useful,
8 // but WITHOUT ANY WARRANTY; without even the implied warranty of
9 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10 // GNU General Public License 2.0 for more details.
11 
12 // A copy of the GPL 2.0 should have been included with the program.
13 // If not, see http://www.gnu.org/licenses/
14 
15 // Official git repository and contact information can be found at
16 // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.
17 
18 // This code is part shamelessly "inspired" from JPSCP.
19 #include <map>
20 #include <algorithm>
21 #include <memory>
22 
23 #include "Common/Serialize/SerializeFuncs.h"
24 #include "Common/Serialize/SerializeMap.h"
25 #include "Common/Swap.h"
26 #include "Core/HLE/sceMpeg.h"
27 #include "Core/HLE/sceKernelModule.h"
28 #include "Core/HLE/sceKernelThread.h"
29 #include "Core/HLE/HLE.h"
30 #include "Core/HLE/FunctionWrappers.h"
31 #include "Core/HW/MediaEngine.h"
32 #include "Core/Config.h"
33 #include "Core/MemMapHelpers.h"
34 #include "Core/Reporting.h"
35 #include "GPU/GPUInterface.h"
36 #include "GPU/GPUState.h"
37 #include "Core/HLE/sceKernelMemory.h"
38 #include "Core/Core.h"
39 
40 // MPEG AVC elementary stream.
41 static const int MPEG_AVC_ES_SIZE = 2048;          // MPEG packet size.
42 
43 // MPEG ATRAC elementary stream.
44 static const int MPEG_ATRAC_ES_SIZE = 2112;
45 static const int MPEG_ATRAC_ES_OUTPUT_SIZE = 8192;
46 
47 // MPEG PCM elementary stream.
48 static const int MPEG_PCM_ES_SIZE = 320;
49 static const int MPEG_PCM_ES_OUTPUT_SIZE = 320;
50 
51 // MPEG Userdata elementary stream.
52 static const int MPEG_DATA_ES_SIZE = 0xA0000;
53 static const int MPEG_DATA_ES_OUTPUT_SIZE = 0xA0000;
54 static const int MPEG_DATA_ES_BUFFERS = 2;
55 
56 // MPEG analysis results.
57 static const int MPEG_VERSION_0012 = 0;
58 static const int MPEG_VERSION_0013 = 1;
59 static const int MPEG_VERSION_0014 = 2;
60 static const int MPEG_VERSION_0015 = 3;
61 
62 // PSMF analysis results.
63 static const int PSMF_VERSION_0012 = 0x32313030;
64 static const int PSMF_VERSION_0013 = 0x33313030;
65 static const int PSMF_VERSION_0014 = 0x34313030;
66 static const int PSMF_VERSION_0015 = 0x35313030;
67 
68 // MPEG streams.
69 static const int MPEG_AVC_STREAM = 0;
70 static const int MPEG_ATRAC_STREAM = 1;
71 static const int MPEG_PCM_STREAM = 2;
72 static const int MPEG_DATA_STREAM = 3;      // Arbitrary user defined type. Can represent audio or video.
73 static const int MPEG_AUDIO_STREAM = 15;
74 static const int MPEG_AU_MODE_DECODE = 0;
75 static const int MPEG_AU_MODE_SKIP = 1;
76 static const u32 MPEG_MEMSIZE_0104 = 0x0b3DB;
77 static const u32 MPEG_MEMSIZE_0105 = 0x10000;     // 64k.
78 static const int MPEG_AVC_DECODE_SUCCESS = 1;     // Internal value.
79 static const int MPEG_WARMUP_FRAMES = 1;
80 
81 static const int atracDecodeDelayMs = 3000;
82 static const int avcFirstDelayMs = 3600;
83 static const int avcCscDelayMs = 4000;
84 static const int avcDecodeDelayMs = 5400;         // Varies between 4700 and 6000.
85 static const int avcEmptyDelayMs = 320;
86 static const int mpegDecodeErrorDelayMs = 100;
87 static const int mpegTimestampPerSecond = 90000;  // How many MPEG Timestamp units in a second.
88 static const int videoTimestampStep = 3003;       // Value based on pmfplayer (mpegTimestampPerSecond / 29.970 (fps)).
89 static const int audioTimestampStep = 4180;       // For audio play at 44100 Hz (2048 samples / 44100 * mpegTimestampPerSecond == 4180)
90 static const int audioFirstTimestamp = 90000;     // The first MPEG audio AU has always this timestamp
91 static const int maxAheadTimestamp = 40000;
92 static const s64 UNKNOWN_TIMESTAMP = -1;
93 
94 // At least 2048 bytes of MPEG data is provided when analysing the MPEG header
95 static const int MPEG_HEADER_BUFFER_MINIMUM_SIZE = 2048;
96 
97 // For PMP media
98 static u32 pmp_videoSource = 0; //pointer to the video source (SceMpegLLi structure)
99 static int pmp_nBlocks = 0; //number of blocks received in the last sceMpegbase_BEA18F91 call
100 static std::list<AVFrame*> pmp_queue; //list of pmp video frames have been decoded and will be played
101 static std::list<u32> pmp_ContextList; //list of pmp media contexts
102 static bool pmp_oldStateLoaded = false; // for dostate
103 
104 // Calculate the number of total packets added to the ringbuffer by calling the sceMpegRingbufferPut() once.
105 static int ringbufferPutPacketsAdded = 0;
106 static bool useRingbufferPutCallbackMulti = true;
107 
108 #ifdef USE_FFMPEG
109 
110 extern "C" {
111 #include "libavformat/avformat.h"
112 #include "libavutil/imgutils.h"
113 #include "libswscale/swscale.h"
114 }
115 static AVPixelFormat pmp_want_pix_fmt;
116 
117 #endif
118 
119 struct SceMpegLLI
120 {
121 	u32 pSrc;
122 	u32 pDst;
123 	u32 Next;
124 	int iSize;
125 };
126 
read(u32 addr)127 void SceMpegAu::read(u32 addr) {
128 	Memory::ReadStruct(addr, this);
129 	pts = (pts & 0xFFFFFFFFULL) << 32 | (((u64)pts) >> 32);
130 	dts = (dts & 0xFFFFFFFFULL) << 32 | (((u64)dts) >> 32);
131 }
132 
write(u32 addr)133 void SceMpegAu::write(u32 addr) {
134 	pts = (pts & 0xFFFFFFFFULL) << 32 | (((u64)pts) >> 32);
135 	dts = (dts & 0xFFFFFFFFULL) << 32 | (((u64)dts) >> 32);
136 	Memory::WriteStruct(addr, this);
137 }
138 
139 /*
140 // Currently unused
141 static int getMaxAheadTimestamp(const SceMpegRingBuffer &ringbuf) {
142 	return std::max(maxAheadTimestamp, 700 * ringbuf.packets);  // empiric value from JPCSP, thanks!
143 }
144 */
145 
146 const u8 defaultMpegheader[2048] = {0x50,0x53,0x4d,0x46,0x30,0x30,0x31,0x35,0x00,0x00,0x08,0x00,0x00,
147 	0x10,0xc8,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
148 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
149 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
150 	0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x4e,0x00,
151 	0x00,0x00,0x01,0x5f,0x90,0x00,0x00,0x00,0x0d,0xbe,0xca,0x00,0x00,0x61,0xa8,0x00,0x01,0x5f,
152 	0x90,0x02,0x01,0x00,0x00,0x00,0x34,0x00,0x00,0x00,0x01,0x5f,0x90,0x00,0x00,0x00,0x0d,0xbe,
153 	0xca,0x00,0x01,0x00,0x00,0x00,0x22,0x00,0x02,0xe0,0x00,0x20,0xfb,0x00,0x00,0x00,0x00,0x00,
154 	0x00,0x00,0x00,0x1e,0x11,0x00,0x00,0xbd,0x00,0x20,0x04,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
155 0x00,0x00,0x00,0x02,0x02};
156 
157 // Internal structure
158 struct AvcContext {
159 	int avcDetailFrameWidth;
160 	int avcDetailFrameHeight;
161 	int avcDecodeResult;
162 	int avcFrameStatus;
163 };
164 
165 struct StreamInfo {
166 	int type;
167 	int num;
168 	int sid;
169 	bool needsReset;
170 };
171 
172 typedef std::map<u32, StreamInfo> StreamInfoMap;
173 
174 // Internal structure
175 struct MpegContext {
MpegContextMpegContext176 	MpegContext() : ringbufferNeedsReverse(false), mediaengine(nullptr) {
177 		memcpy(mpegheader, defaultMpegheader, 2048);
178 	}
~MpegContextMpegContext179 	~MpegContext() {
180 		delete mediaengine;
181 	}
182 
DoStateMpegContext183 	void DoState(PointerWrap &p) {
184 		auto s = p.Section("MpegContext", 1, 3);
185 		if (!s)
186 			return;
187 		if (s >= 3)
188 			Do(p, mpegwarmUp);
189 		else
190 			mpegwarmUp = 1000;
191 		DoArray(p, mpegheader, 2048);
192 		Do(p, defaultFrameWidth);
193 		Do(p, videoFrameCount);
194 		Do(p, audioFrameCount);
195 		Do(p, endOfAudioReached);
196 		Do(p, endOfVideoReached);
197 		Do(p, videoPixelMode);
198 		Do(p, mpegMagic);
199 		Do(p, mpegVersion);
200 		Do(p, mpegRawVersion);
201 		Do(p, mpegOffset);
202 		Do(p, mpegStreamSize);
203 		Do(p, mpegFirstTimestamp);
204 		Do(p, mpegLastTimestamp);
205 		Do(p, mpegFirstDate);
206 		Do(p, mpegLastDate);
207 		Do(p, mpegRingbufferAddr);
208 		DoArray(p, esBuffers, MPEG_DATA_ES_BUFFERS);
209 		Do(p, avc);
210 		Do(p, avcRegistered);
211 		Do(p, atracRegistered);
212 		Do(p, pcmRegistered);
213 		Do(p, dataRegistered);
214 		Do(p, ignoreAtrac);
215 		Do(p, ignorePcm);
216 		Do(p, ignoreAvc);
217 		Do(p, isAnalyzed);
218 		Do<u32, StreamInfo>(p, streamMap);
219 		DoClass(p, mediaengine);
220 		ringbufferNeedsReverse = s < 2;
221 	}
222 
223 	u8 mpegheader[2048];
224 	u32 defaultFrameWidth;
225 	int videoFrameCount;
226 	int audioFrameCount;
227 	bool endOfAudioReached;
228 	bool endOfVideoReached;
229 	int videoPixelMode;
230 	u32 mpegMagic;
231 	int mpegVersion;
232 	u32 mpegRawVersion;
233 	u32 mpegOffset;
234 	u32 mpegStreamSize;
235 	s64 mpegFirstTimestamp;
236 	s64 mpegLastTimestamp;
237 	u32 mpegFirstDate;
238 	u32 mpegLastDate;
239 	u32 mpegRingbufferAddr;
240 	int mpegwarmUp;
241 	bool esBuffers[MPEG_DATA_ES_BUFFERS];
242 	AvcContext avc;
243 
244 	bool avcRegistered;
245 	bool atracRegistered;
246 	bool pcmRegistered;
247 	bool dataRegistered;
248 
249 	bool ignoreAtrac;
250 	bool ignorePcm;
251 	bool ignoreAvc;
252 
253 	bool isAnalyzed;
254 	bool ringbufferNeedsReverse;
255 
256 	StreamInfoMap streamMap;
257 	MediaEngine *mediaengine;
258 };
259 
260 static bool isMpegInit;
261 static int mpegLibVersion;
262 static u32 streamIdGen;
263 static int actionPostPut;
264 static std::map<u32, MpegContext *> mpegMap;
265 
getMpegCtx(u32 mpegAddr)266 static MpegContext *getMpegCtx(u32 mpegAddr) {
267 	if (!Memory::IsValidAddress(mpegAddr))
268 		return nullptr;
269 
270 	u32 mpeg = Memory::Read_U32(mpegAddr);
271 	auto found = mpegMap.find(mpeg);
272 	if (found == mpegMap.end())
273 		return nullptr;
274 
275 	MpegContext *res = found->second;
276 	// Take this opportunity to upgrade savestates if necessary.
277 	if (res->ringbufferNeedsReverse) {
278 		auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(res->mpegRingbufferAddr);
279 		ringbuffer->packetsAvail = ringbuffer->packets - ringbuffer->packetsAvail;
280 		res->ringbufferNeedsReverse = false;
281 	}
282 	return res;
283 }
284 
InitRingbuffer(SceMpegRingBuffer * buf,int packets,int data,int size,int callback_addr,int callback_args)285 static void InitRingbuffer(SceMpegRingBuffer *buf, int packets, int data, int size, int callback_addr, int callback_args) {
286 	buf->packets = packets;
287 	buf->packetsRead = 0;
288 	buf->packetsWritePos = 0;
289 	buf->packetsAvail = 0;
290 	buf->packetSize = 2048;
291 	buf->data = data;
292 	buf->callback_addr = callback_addr;
293 	buf->callback_args = callback_args;
294 	buf->dataUpperBound = data + packets * 2048;
295 	buf->semaID = 0;
296 	buf->mpeg = 0;
297 	// This isn't in ver 0104, but it is in 0105.
298 	if (mpegLibVersion >= 0x0105)
299 		buf->gp = __KernelGetModuleGP(__KernelGetCurThreadModuleId());
300 }
301 
convertTimestampToDate(u32 ts)302 static u32 convertTimestampToDate(u32 ts) {
303 	return ts;  // TODO
304 }
305 
getMpegVersion(u32 mpegRawVersion)306 static u32 getMpegVersion(u32 mpegRawVersion) {
307 	switch (mpegRawVersion) {
308 		case PSMF_VERSION_0012: return MPEG_VERSION_0012;
309 		case PSMF_VERSION_0013: return MPEG_VERSION_0013;
310 		case PSMF_VERSION_0014: return MPEG_VERSION_0014;
311 		case PSMF_VERSION_0015: return MPEG_VERSION_0015;
312 		default: return -1;
313 	}
314 }
315 
AnalyzeMpeg(u8 * buffer,u32 validSize,MpegContext * ctx)316 static void AnalyzeMpeg(u8 *buffer, u32 validSize, MpegContext *ctx) {
317 	ctx->mpegMagic = *(u32_le*)buffer;
318 	ctx->mpegRawVersion = *(u32_le*)(buffer + PSMF_STREAM_VERSION_OFFSET);
319 	ctx->mpegVersion = getMpegVersion(ctx->mpegRawVersion);
320 	ctx->mpegOffset = bswap32(*(u32_le*)(buffer + PSMF_STREAM_OFFSET_OFFSET));
321 	ctx->mpegStreamSize = bswap32(*(u32_le*)(buffer + PSMF_STREAM_SIZE_OFFSET));
322 	ctx->mpegFirstTimestamp = getMpegTimeStamp(buffer + PSMF_FIRST_TIMESTAMP_OFFSET);
323 	ctx->mpegLastTimestamp = getMpegTimeStamp(buffer + PSMF_LAST_TIMESTAMP_OFFSET);
324 	ctx->mpegFirstDate = convertTimestampToDate(ctx->mpegFirstTimestamp);
325 	ctx->mpegLastDate = convertTimestampToDate(ctx->mpegLastTimestamp);
326 	ctx->mpegwarmUp = 0;
327 	ctx->avc.avcDetailFrameWidth = (*(u8*)(buffer + 142)) * 0x10;
328 	ctx->avc.avcDetailFrameHeight = (*(u8*)(buffer + 143)) * 0x10;
329 	ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS;
330 	ctx->avc.avcFrameStatus = 0;
331 	ctx->videoFrameCount = 0;
332 	ctx->audioFrameCount = 0;
333 	ctx->endOfAudioReached = false;
334 	ctx->endOfVideoReached = false;
335 
336 	// Sanity Check ctx->mpegFirstTimestamp
337 	if (ctx->mpegFirstTimestamp != 90000) {
338 		WARN_LOG_REPORT(ME, "Unexpected mpeg first timestamp: %llx / %lld", ctx->mpegFirstTimestamp, ctx->mpegFirstTimestamp);
339 	}
340 
341 	if (ctx->mpegMagic != PSMF_MAGIC || ctx->mpegVersion < 0 ||
342 		(ctx->mpegOffset & 2047) != 0 || ctx->mpegOffset == 0) {
343 		// mpeg header is invalid!
344 		return;
345 	}
346 
347 	if (!ctx->isAnalyzed && ctx->mediaengine && ctx->mpegStreamSize > 0 && validSize >= ctx->mpegOffset) {
348 		// init mediaEngine
349 		auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ctx->mpegRingbufferAddr);
350 		if (ringbuffer.IsValid()) {
351 			ctx->mediaengine->loadStream(buffer, ctx->mpegOffset, ringbuffer->packets * ringbuffer->packetSize);
352 		} else {
353 			// TODO: Does this make any sense?
354 			ctx->mediaengine->loadStream(buffer, ctx->mpegOffset, 0);
355 		}
356 
357 		// When used with scePsmf, some applications attempt to use sceMpegQueryStreamOffset
358 		// and sceMpegQueryStreamSize, which forces a packet overwrite in the Media Engine and in
359 		// the MPEG ringbuffer.
360 		// Mark the current MPEG as analyzed to filter this, and restore it at sceMpegFinish.
361 		ctx->isAnalyzed = true;
362 	}
363 
364 	// copy header struct to mpeg header.
365 	memcpy(ctx->mpegheader, buffer, validSize >= 2048 ? 2048 : validSize);
366 	*(u32_le*)(ctx->mpegheader + PSMF_STREAM_OFFSET_OFFSET) = 0x80000;
367 
368 	INFO_LOG(ME, "Stream offset: %d, Stream size: 0x%X", ctx->mpegOffset, ctx->mpegStreamSize);
369 	INFO_LOG(ME, "First timestamp: %lld, Last timestamp: %lld", ctx->mpegFirstTimestamp, ctx->mpegLastTimestamp);
370 }
371 
372 class PostPutAction : public PSPAction {
373 public:
PostPutAction()374 	PostPutAction() {}
setRingAddr(u32 ringAddr)375 	void setRingAddr(u32 ringAddr) { ringAddr_ = ringAddr; }
Create()376 	static PSPAction *Create() { return new PostPutAction; }
DoState(PointerWrap & p)377 	void DoState(PointerWrap &p) override {
378 		auto s = p.Section("PostPutAction", 1);
379 		if (!s)
380 			return;
381 
382 		Do(p, ringAddr_);
383 	}
384 	void run(MipsCall &call) override;
385 private:
386 	u32 ringAddr_;
387 };
388 
__MpegInit()389 void __MpegInit() {
390 	isMpegInit = false;
391 	mpegLibVersion = 0x010A;
392 	streamIdGen = 1;
393 	actionPostPut = __KernelRegisterActionType(PostPutAction::Create);
394 
395 #ifdef USE_FFMPEG
396 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 18, 100)
397 	avcodec_register_all();
398 #endif
399 #if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 12, 100)
400 	av_register_all();
401 #endif
402 #endif
403 }
404 
__MpegDoState(PointerWrap & p)405 void __MpegDoState(PointerWrap &p) {
406 	auto s = p.Section("sceMpeg", 1, 3);
407 	if (!s)
408 		return;
409 
410 	if (s < 2) {
411 		int oldLastMpeg = -1;
412 		bool oldIsMpegAnalyzed = false;
413 		Do(p, oldLastMpeg);
414 		Do(p, streamIdGen);
415 		Do(p, oldIsMpegAnalyzed);
416 		// Let's assume the oldest version.
417 		mpegLibVersion = 0x0101;
418 	} else {
419 		if (s < 3) {
420 			useRingbufferPutCallbackMulti = false;
421 			ringbufferPutPacketsAdded = 0;
422 		} else {
423 			Do(p, ringbufferPutPacketsAdded);
424 		}
425 		Do(p, streamIdGen);
426 		Do(p, mpegLibVersion);
427 	}
428 	Do(p, isMpegInit);
429 	Do(p, actionPostPut);
430 	__KernelRestoreActionType(actionPostPut, PostPutAction::Create);
431 
432 	Do(p, mpegMap);
433 }
434 
__MpegShutdown()435 void __MpegShutdown() {
436 	std::map<u32, MpegContext *>::iterator it, end;
437 	for (it = mpegMap.begin(), end = mpegMap.end(); it != end; ++it) {
438 		delete it->second;
439 	}
440 	mpegMap.clear();
441 }
442 
__MpegLoadModule(int version)443 void __MpegLoadModule(int version) {
444 	mpegLibVersion = version;
445 }
446 
sceMpegInit()447 static u32 sceMpegInit() {
448 	if (isMpegInit) {
449 		WARN_LOG(ME, "sceMpegInit(): already initialized");
450 		// TODO: Need to properly hook module load/unload for this to work right.
451 		//return ERROR_MPEG_ALREADY_INIT;
452 	} else {
453 		INFO_LOG(ME, "sceMpegInit()");
454 	}
455 	isMpegInit = true;
456 	return hleDelayResult(0, "mpeg init", 750);
457 }
458 
__MpegRingbufferQueryMemSize(int packets)459 static u32 __MpegRingbufferQueryMemSize(int packets) {
460 	return packets * (104 + 2048);
461 }
462 
sceMpegRingbufferQueryMemSize(int packets)463 static u32 sceMpegRingbufferQueryMemSize(int packets) {
464 	u32 size = __MpegRingbufferQueryMemSize(packets);
465 	DEBUG_LOG(ME, "%i = sceMpegRingbufferQueryMemSize(%i)", size, packets);
466 	return size;
467 }
468 
469 
sceMpegRingbufferConstruct(u32 ringbufferAddr,u32 numPackets,u32 data,u32 size,u32 callbackAddr,u32 callbackArg)470 static u32 sceMpegRingbufferConstruct(u32 ringbufferAddr, u32 numPackets, u32 data, u32 size, u32 callbackAddr, u32 callbackArg) {
471 	if (!Memory::IsValidAddress(ringbufferAddr)) {
472 		ERROR_LOG_REPORT(ME, "sceMpegRingbufferConstruct(%08x, %i, %08x, %08x, %08x, %08x): bad ringbuffer, should crash", ringbufferAddr, numPackets, data, size, callbackAddr, callbackArg);
473 		return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS;
474 	}
475 
476 	if ((int)size < 0) {
477 		ERROR_LOG_REPORT(ME, "sceMpegRingbufferConstruct(%08x, %i, %08x, %08x, %08x, %08x): invalid size", ringbufferAddr, numPackets, data, size, callbackAddr, callbackArg);
478 		return ERROR_MPEG_NO_MEMORY;
479 	}
480 
481 	if (__MpegRingbufferQueryMemSize(numPackets) > size) {
482 		if (numPackets < 0x00100000) {
483 			ERROR_LOG_REPORT(ME, "sceMpegRingbufferConstruct(%08x, %i, %08x, %08x, %08x, %08x): too many packets for buffer", ringbufferAddr, numPackets, data, size, callbackAddr, callbackArg);
484 			return ERROR_MPEG_NO_MEMORY;
485 		} else {
486 			// The PSP's firmware allows some cases here, due to a bug in its validation.
487 			ERROR_LOG_REPORT(ME, "sceMpegRingbufferConstruct(%08x, %i, %08x, %08x, %08x, %08x): too many packets for buffer, bogus size", ringbufferAddr, numPackets, data, size, callbackAddr, callbackArg);
488 		}
489 	}
490 
491 	DEBUG_LOG(ME, "sceMpegRingbufferConstruct(%08x, %i, %08x, %08x, %08x, %08x)", ringbufferAddr, numPackets, data, size, callbackAddr, callbackArg);
492 	auto ring = PSPPointer<SceMpegRingBuffer>::Create(ringbufferAddr);
493 	InitRingbuffer(ring, numPackets, data, size, callbackAddr, callbackArg);
494 	return 0;
495 }
496 
MpegRequiredMem()497 static u32 MpegRequiredMem() {
498 	if (mpegLibVersion < 0x0105) {
499 		return MPEG_MEMSIZE_0104;
500 	}
501 	return MPEG_MEMSIZE_0105;
502 }
503 
sceMpegCreate(u32 mpegAddr,u32 dataPtr,u32 size,u32 ringbufferAddr,u32 frameWidth,u32 mode,u32 ddrTop)504 static u32 sceMpegCreate(u32 mpegAddr, u32 dataPtr, u32 size, u32 ringbufferAddr, u32 frameWidth, u32 mode, u32 ddrTop)
505 {
506 	if (!Memory::IsValidAddress(mpegAddr)) {
507 		WARN_LOG(ME, "sceMpegCreate(%08x, %08x, %i, %08x, %i, %i, %i): invalid addresses", mpegAddr, dataPtr, size, ringbufferAddr, frameWidth, mode, ddrTop);
508 		return -1;
509 	}
510 
511 	if (size < MpegRequiredMem()) {
512 		WARN_LOG(ME, "ERROR_MPEG_NO_MEMORY=sceMpegCreate(%08x, %08x, %i, %08x, %i, %i, %i)", mpegAddr, dataPtr, size, ringbufferAddr, frameWidth, mode, ddrTop);
513 		return ERROR_MPEG_NO_MEMORY;
514 	}
515 
516 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ringbufferAddr);
517 	if (ringbuffer.IsValid()) {
518 		if (ringbuffer->packetSize == 0) {
519 			ringbuffer->packetsAvail = 0;
520 		} else {
521 			ringbuffer->packetsAvail = ringbuffer->packets - (ringbuffer->dataUpperBound - ringbuffer->data) / ringbuffer->packetSize;
522 		}
523 		ringbuffer->mpeg = mpegAddr;
524 	}
525 
526 	// Generate, and write mpeg handle into mpeg data, for some reason
527 	int mpegHandle = dataPtr + 0x30;
528 	Memory::Write_U32(mpegHandle, mpegAddr);
529 
530 	// Initialize fake mpeg struct.
531 	Memory::Memcpy(mpegHandle, "LIBMPEG\0", 8, "Mpeg");
532 	Memory::Memcpy(mpegHandle + 8, "001\0", 4, "Mpeg");
533 	Memory::Write_U32(-1, mpegHandle + 12);
534 	if (ringbuffer.IsValid()) {
535 		Memory::Write_U32(ringbufferAddr, mpegHandle + 16);
536 		Memory::Write_U32(ringbuffer->dataUpperBound, mpegHandle + 20);
537 	}
538 	MpegContext *ctx = new MpegContext();
539 	if (mpegMap.find(mpegHandle) != mpegMap.end()) {
540 		WARN_LOG_REPORT(HLE, "Replacing existing mpeg context at %08x", mpegAddr);
541 		// Otherwise, it would leak.
542 		delete mpegMap[mpegHandle];
543 	}
544 	mpegMap[mpegHandle] = ctx;
545 
546 	// Initialize mpeg values.
547 	ctx->mpegRingbufferAddr = ringbufferAddr;
548 	ctx->videoFrameCount = 0;
549 	ctx->audioFrameCount = 0;
550 	ctx->videoPixelMode = GE_CMODE_32BIT_ABGR8888; // TODO: What's the actual default?
551 	ctx->avcRegistered = false;
552 	ctx->atracRegistered = false;
553 	ctx->pcmRegistered = false;
554 	ctx->dataRegistered = false;
555 	ctx->ignoreAtrac = false;
556 	ctx->ignorePcm = false;
557 	ctx->ignoreAvc = false;
558 	ctx->defaultFrameWidth = frameWidth;
559 	ctx->mpegStreamSize = 0;
560 	ctx->mpegOffset = 0;
561 	for (int i = 0; i < MPEG_DATA_ES_BUFFERS; i++) {
562 		ctx->esBuffers[i] = false;
563 	}
564 
565 	// Detailed "analysis" is done later in Query* for some reason.
566 	ctx->isAnalyzed = false;
567 	ctx->mediaengine = new MediaEngine();
568 
569 	INFO_LOG(ME, "%08x=sceMpegCreate(%08x, %08x, %i, %08x, %i, %i, %i)", mpegHandle, mpegAddr, dataPtr, size, ringbufferAddr, frameWidth, mode, ddrTop);
570 	return hleDelayResult(0, "mpeg create", 29000);
571 }
572 
sceMpegDelete(u32 mpeg)573 static int sceMpegDelete(u32 mpeg)
574 {
575 	MpegContext *ctx = getMpegCtx(mpeg);
576 	if (!ctx) {
577 		WARN_LOG(ME, "sceMpegDelete(%08x): bad mpeg handle", mpeg);
578 		return -1;
579 	}
580 
581 	DEBUG_LOG(ME, "sceMpegDelete(%08x)", mpeg);
582 
583 	delete ctx;
584 	mpegMap.erase(Memory::Read_U32(mpeg));
585 
586 	return hleDelayResult(0, "mpeg delete", 40000);
587 }
588 
589 
sceMpegAvcDecodeMode(u32 mpeg,u32 modeAddr)590 static int sceMpegAvcDecodeMode(u32 mpeg, u32 modeAddr)
591 {
592 	if (!Memory::IsValidAddress(modeAddr)) {
593 		WARN_LOG(ME, "sceMpegAvcDecodeMode(%08x, %08x): invalid addresses", mpeg, modeAddr);
594 		return -1;
595 	}
596 
597 	MpegContext *ctx = getMpegCtx(mpeg);
598 	if (!ctx) {
599 		WARN_LOG(ME, "sceMpegAvcDecodeMode(%08x, %08x): bad mpeg handle", mpeg, modeAddr);
600 		return -1;
601 	}
602 
603 	DEBUG_LOG(ME, "sceMpegAvcDecodeMode(%08x, %08x)", mpeg, modeAddr);
604 
605 	int mode = Memory::Read_U32(modeAddr);
606 	int pixelMode = Memory::Read_U32(modeAddr + 4);
607 	if (pixelMode >= GE_CMODE_16BIT_BGR5650 && pixelMode <= GE_CMODE_32BIT_ABGR8888) {
608 		ctx->videoPixelMode = pixelMode;
609 	} else {
610 		ERROR_LOG(ME, "sceMpegAvcDecodeMode(%i, %i): unknown pixelMode ", mode, pixelMode);
611 	}
612 	return 0;
613 }
614 
sceMpegQueryStreamOffset(u32 mpeg,u32 bufferAddr,u32 offsetAddr)615 static int sceMpegQueryStreamOffset(u32 mpeg, u32 bufferAddr, u32 offsetAddr)
616 {
617 	if (!Memory::IsValidAddress(bufferAddr) || !Memory::IsValidAddress(offsetAddr)) {
618 		ERROR_LOG(ME, "sceMpegQueryStreamOffset(%08x, %08x, %08x): invalid addresses", mpeg, bufferAddr, offsetAddr);
619 		return -1;
620 	}
621 
622 	MpegContext *ctx = getMpegCtx(mpeg);
623 	if (!ctx) {
624 		WARN_LOG(ME, "sceMpegQueryStreamOffset(%08x, %08x, %08x): bad mpeg handle", mpeg, bufferAddr, offsetAddr);
625 		return -1;
626 	}
627 
628 	DEBUG_LOG(ME, "sceMpegQueryStreamOffset(%08x, %08x, %08x)", mpeg, bufferAddr, offsetAddr);
629 
630 	// Kinda destructive, no?
631 	AnalyzeMpeg(Memory::GetPointer(bufferAddr), Memory::ValidSize(bufferAddr, 32768), ctx);
632 
633 	if (ctx->mpegMagic != PSMF_MAGIC) {
634 		ERROR_LOG(ME, "sceMpegQueryStreamOffset: Bad PSMF magic");
635 		Memory::Write_U32(0, offsetAddr);
636 		return ERROR_MPEG_INVALID_VALUE;
637 	} else if (ctx->mpegVersion < 0) {
638 		ERROR_LOG(ME, "sceMpegQueryStreamOffset: Bad version");
639 		Memory::Write_U32(0, offsetAddr);
640 		return ERROR_MPEG_BAD_VERSION;
641 	} else if ((ctx->mpegOffset & 2047) != 0 || ctx->mpegOffset == 0) {
642 		ERROR_LOG(ME, "sceMpegQueryStreamOffset: Bad offset");
643 		Memory::Write_U32(0, offsetAddr);
644 		return ERROR_MPEG_INVALID_VALUE;
645 	}
646 
647 	Memory::Write_U32(ctx->mpegOffset, offsetAddr);
648 	return 0;
649 }
650 
sceMpegQueryStreamSize(u32 bufferAddr,u32 sizeAddr)651 static u32 sceMpegQueryStreamSize(u32 bufferAddr, u32 sizeAddr)
652 {
653 	if (!Memory::IsValidAddress(bufferAddr) || !Memory::IsValidAddress(sizeAddr)) {
654 		ERROR_LOG(ME, "sceMpegQueryStreamSize(%08x, %08x): invalid addresses", bufferAddr, sizeAddr);
655 		return -1;
656 	}
657 
658 	DEBUG_LOG(ME, "sceMpegQueryStreamSize(%08x, %08x)", bufferAddr, sizeAddr);
659 
660 	MpegContext ctx;
661 	ctx.mediaengine = 0;
662 
663 	AnalyzeMpeg(Memory::GetPointer(bufferAddr), Memory::ValidSize(bufferAddr, 32768), &ctx);
664 
665 	if (ctx.mpegMagic != PSMF_MAGIC) {
666 		ERROR_LOG(ME, "sceMpegQueryStreamSize: Bad PSMF magic");
667 		Memory::Write_U32(0, sizeAddr);
668 		return ERROR_MPEG_INVALID_VALUE;
669 	} else if ((ctx.mpegOffset & 2047) != 0 ) {
670 		ERROR_LOG(ME, "sceMpegQueryStreamSize: Bad offset");
671 		Memory::Write_U32(0, sizeAddr);
672 		return ERROR_MPEG_INVALID_VALUE;
673 	}
674 
675 	Memory::Write_U32(ctx.mpegStreamSize, sizeAddr);
676 	return 0;
677 }
678 
sceMpegRegistStream(u32 mpeg,u32 streamType,u32 streamNum)679 static int sceMpegRegistStream(u32 mpeg, u32 streamType, u32 streamNum)
680 {
681 	MpegContext *ctx = getMpegCtx(mpeg);
682 	if (!ctx) {
683 		WARN_LOG(ME, "sceMpegRegistStream(%08x, %i, %i): bad mpeg handle", mpeg, streamType, streamNum);
684 		return -1;
685 	}
686 
687 	INFO_LOG(ME, "sceMpegRegistStream(%08x, %i, %i)", mpeg, streamType, streamNum);
688 
689 	switch (streamType) {
690 	case MPEG_AVC_STREAM:
691 		ctx->avcRegistered = true;
692 		ctx->mediaengine->addVideoStream(streamNum);
693 		// TODO: Probably incorrect?
694 		ctx->mediaengine->setVideoStream(streamNum);
695 		break;
696 	case MPEG_AUDIO_STREAM:
697 	case MPEG_ATRAC_STREAM:
698 		ctx->atracRegistered = true;
699 		// TODO: Probably incorrect?
700 		ctx->mediaengine->setAudioStream(streamNum);
701 		break;
702 	case MPEG_PCM_STREAM:
703 		ctx->pcmRegistered = true;
704 		break;
705 	case MPEG_DATA_STREAM:
706 		ctx->dataRegistered = true;
707 		break;
708 	default :
709 		DEBUG_LOG(ME, "sceMpegRegistStream(%i) : unknown stream type", streamType);
710 		break;
711 	}
712 	// ...
713 	u32 sid = streamIdGen++;
714 	StreamInfo info;
715 	info.type = streamType;
716 	info.num = streamNum;
717 	info.sid = sid;
718 	info.needsReset = true;
719 	ctx->streamMap[sid] = info;
720 	return sid;
721 }
722 
sceMpegMallocAvcEsBuf(u32 mpeg)723 static int sceMpegMallocAvcEsBuf(u32 mpeg)
724 {
725 	MpegContext *ctx = getMpegCtx(mpeg);
726 	if (!ctx) {
727 		WARN_LOG(ME, "sceMpegMallocAvcEsBuf(%08x): bad mpeg handle", mpeg);
728 		return -1;
729 	}
730 
731 	DEBUG_LOG(ME, "sceMpegMallocAvcEsBuf(%08x)", mpeg);
732 
733 	// Doesn't actually malloc, just keeps track of a couple of flags
734 	for (int i = 0; i < MPEG_DATA_ES_BUFFERS; i++) {
735 		if (!ctx->esBuffers[i]) {
736 			ctx->esBuffers[i] = true;
737 			return i + 1;
738 		}
739 	}
740 	// No es buffer
741 	return 0;
742 }
743 
sceMpegFreeAvcEsBuf(u32 mpeg,int esBuf)744 static int sceMpegFreeAvcEsBuf(u32 mpeg, int esBuf)
745 {
746 	MpegContext *ctx = getMpegCtx(mpeg);
747 	if (!ctx) {
748 		WARN_LOG(ME, "sceMpegFreeAvcEsBuf(%08x, %i): bad mpeg handle", mpeg, esBuf);
749 		return -1;
750 	}
751 
752 	DEBUG_LOG(ME, "sceMpegFreeAvcEsBuf(%08x, %i)", mpeg, esBuf);
753 
754 	if (esBuf == 0) {
755 		return ERROR_MPEG_INVALID_VALUE;
756 	}
757 
758 	if (esBuf >= 1 && esBuf <= MPEG_DATA_ES_BUFFERS) {
759 		// TODO: Check if it's already been free'd?
760 		ctx->esBuffers[esBuf - 1] = false;
761 	}
762 	return 0;
763 }
764 
765 // check the existence of pmp media context
isContextExist(u32 ctxAddr)766 static bool isContextExist(u32 ctxAddr){
767 	for (auto it = pmp_ContextList.begin(); it != pmp_ContextList.end(); ++it){
768 		if (*it == ctxAddr){
769 			return true;
770 		}
771 	}
772 	return false;
773 }
774 
775 // Initialize Pmp video parameters and decoder.
InitPmp(MpegContext * ctx)776 static bool InitPmp(MpegContext * ctx){
777 #ifdef USE_FFMPEG
778 	InitFFmpeg();
779 	auto mediaengine = ctx->mediaengine;
780 	mediaengine->m_isVideoEnd = false;
781 	mediaengine->m_firstTimeStamp = 0;
782 	mediaengine->m_lastTimeStamp = 0;
783 	ctx->mpegFirstTimestamp = 0;
784 	ctx->mpegLastTimestamp = 0;
785 
786 	// wanted output pixel format
787 	// reference values for pix_fmt:
788 	// GE_CMODE_16BIT_BGR5650 <--> AV_PIX_FMT_BGR565LE
789 	// GE_CMODE_16BIT_ABGR5551 <--> AV_PIX_FMT_BGR555LE;
790 	// GE_CMODE_16BIT_ABGR4444 <--> AV_PIX_FMT_BGR444LE;
791 	// GE_CMODE_32BIT_ABGR8888 <--> AV_PIX_FMT_RGBA;
792 	pmp_want_pix_fmt = AV_PIX_FMT_RGBA;
793 
794 	// Create H264 video codec
795 	AVCodec * pmp_Codec = avcodec_find_decoder(AV_CODEC_ID_H264);
796 	if (pmp_Codec == NULL){
797 		ERROR_LOG(ME, "Can not find H264 codec, please update ffmpeg");
798 		return false;
799 	}
800 
801 	// Create CodecContext
802 	AVCodecContext * pmp_CodecCtx = avcodec_alloc_context3(pmp_Codec);
803 	if (pmp_CodecCtx == NULL){
804 		ERROR_LOG(ME, "Can not allocate pmp Codec Context");
805 		return false;
806 	}
807 
808 	pmp_CodecCtx->flags |= AV_CODEC_FLAG_OUTPUT_CORRUPT | AV_CODEC_FLAG_LOW_DELAY;
809 
810 	// each pmp video context is corresponding to one pmp video codec
811 	mediaengine->m_pCodecCtxs[0] = pmp_CodecCtx;
812 
813 	// initialize H264 video parameters
814 	// set pmp video size. Better to get from pmp file directly if possible. Any idea?
815 	pmp_CodecCtx->width = 480;
816 	pmp_CodecCtx->height = 272;
817 	mediaengine->m_desHeight = pmp_CodecCtx->height;
818 	mediaengine->m_desWidth = pmp_CodecCtx->width;
819 
820 	// Open pmp video codec
821 	if (avcodec_open2(pmp_CodecCtx, pmp_Codec, NULL) < 0){
822 		ERROR_LOG(ME, "Can not open pmp video codec");
823 		return false;
824 	}
825 
826 	// initialize ctx->mediaengine->m_pFrame and ctx->mediaengine->m_pFrameRGB
827 	if (!mediaengine->m_pFrame){
828 		mediaengine->m_pFrame = av_frame_alloc();
829 	}
830 	if (!mediaengine->m_pFrameRGB){
831 		mediaengine->m_pFrameRGB = av_frame_alloc();
832 	}
833 
834 	// get RGBA picture buffer
835 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
836 	mediaengine->m_bufSize = av_image_get_buffer_size(pmp_want_pix_fmt, pmp_CodecCtx->width, pmp_CodecCtx->height, 1);
837 #else
838 	mediaengine->m_bufSize = avpicture_get_size(pmp_want_pix_fmt, pmp_CodecCtx->width, pmp_CodecCtx->height);
839 #endif
840 	mediaengine->m_buffer = (u8*)av_malloc(mediaengine->m_bufSize);
841 
842 	return true;
843 #else
844 	// we can not play pmp video without ffmpeg
845 	return false;
846 #endif
847 }
848 
849 // This class H264Frames is used for collecting small pieces of frames into larger frames for ffmpeg to decode
850 // Basically, this will avoid incomplete frame decoding issue and improve much better the video quality.
851 class H264Frames{
852 public:
853 	int size;
854 	u8* stream;
855 
H264Frames()856 	H264Frames() :size(0), stream(NULL){};
857 
H264Frames(u8 * str,int sz)858 	H264Frames(u8* str, int sz) :size(sz){
859 		stream = new u8[size];
860 		memcpy(stream, str, size);
861 	};
862 
H264Frames(H264Frames * frame)863 	H264Frames(H264Frames *frame){
864 		size = frame->size;
865 		stream = new u8[size];
866 		memcpy(stream, frame->stream, size);
867 	};
868 
~H264Frames()869 	~H264Frames(){
870 		size = 0;
871 		if (stream){
872 			delete[] stream;
873 			stream = NULL;
874 		}
875 	};
876 
add(H264Frames * p)877 	void add(H264Frames *p){
878 		add(p->stream, p->size);
879 	};
880 
add(u8 * str,int sz)881 	void add(u8* str, int sz){
882 		int newsize = size + sz;
883 		u8* newstream = new u8[newsize];
884 		// join two streams
885 		memcpy(newstream, stream, size);
886 		memcpy(newstream + size, str, sz);
887 		// delete old stream
888 		delete[] stream;
889 		// replace with new stream
890 		stream = newstream;
891 		size = newsize;
892 	};
893 
remove(int pos)894 	void remove(int pos){
895 		// remove stream from begining to pos
896 		if (pos == 0){
897 			// nothing to remove
898 		}
899 		else if (pos >= size){
900 			// we remove all
901 			size = 0;
902 			if (stream){
903 				delete[] stream;
904 				stream = NULL;
905 			}
906 		}
907 		else{
908 			// we remove the front part
909 			size -= pos;
910 			u8* str = new u8[size];
911 			memcpy(str, stream + pos, size);
912 			delete[] stream;
913 			stream = str;
914 		}
915 	};
916 #ifndef USE_FFMPEG
917 #define AV_INPUT_BUFFER_PADDING_SIZE 16
918 #endif
919 #ifndef AV_INPUT_BUFFER_PADDING_SIZE
920 #define AV_INPUT_BUFFER_PADDING_SIZE FF_INPUT_BUFFER_PADDING_SIZE
921 #endif
addpadding()922 	void addpadding(){
923 		u8* str = new u8[size + AV_INPUT_BUFFER_PADDING_SIZE];
924 		memcpy(str, stream, size);
925 		memset(str + size, 0, AV_INPUT_BUFFER_PADDING_SIZE);
926 		size += AV_INPUT_BUFFER_PADDING_SIZE;
927 		delete[] stream;
928 		stream = str;
929 	}
930 };
931 
932 // collect pmp video frames
933 static H264Frames *pmpframes;
934 
935 // decode pmp video to RGBA format
decodePmpVideo(PSPPointer<SceMpegRingBuffer> ringbuffer,u32 pmpctxAddr)936 static bool decodePmpVideo(PSPPointer<SceMpegRingBuffer> ringbuffer, u32 pmpctxAddr){
937 
938 #ifdef USE_FFMPEG
939 	// the current video is pmp iff pmp_videoSource is a valid addresse
940 	MpegContext* ctx = getMpegCtx(pmpctxAddr);
941 	if (Memory::IsValidAddress(pmp_videoSource)){
942 		// We should initialize pmp codec for each pmp context
943 		if (isContextExist(pmpctxAddr) == false){
944 			bool ret = InitPmp(ctx);
945 			if (!ret){
946 				ERROR_LOG(ME, "Pmp video initialization failed");
947 				return false;
948 			}
949 			// add the initialized context into ContextList
950 			pmp_ContextList.push_front(pmpctxAddr);
951 		}
952 
953 		ringbuffer->packetsRead = pmp_nBlocks;
954 
955 		MediaEngine* mediaengine = ctx->mediaengine;
956 		AVFrame* pFrame = mediaengine->m_pFrame;
957 		AVFrame* pFrameRGB = mediaengine->m_pFrameRGB;
958 		auto pCodecCtx = mediaengine->m_pCodecCtxs[0];
959 
960 		// pmpframes could be destroied when close a video to load another one
961 		if (!pmpframes)
962 			pmpframes = new H264Frames;
963 
964 		// joint all blocks into H264Frames
965 		for (int i = 0; i < pmp_nBlocks; i++){
966 			auto lli = PSPPointer<SceMpegLLI>::Create(pmp_videoSource);
967 			// add source block into pmpframes
968 			pmpframes->add(Memory::GetPointer(lli->pSrc), lli->iSize);
969 			// get next block
970 			pmp_videoSource += sizeof(SceMpegLLI);
971 		}
972 
973 		pmpframes->addpadding();
974 
975 		// initialize packet
976 		AVPacket packet;
977 		av_new_packet(&packet, pCodecCtx->width*pCodecCtx->height);
978 
979 		// set packet to source block
980 		packet.data = pmpframes->stream;
981 		packet.size = pmpframes->size;
982 
983 		// reuse pFrame and pFrameRGB
984 		int got_picture = 0;
985 		av_frame_unref(pFrame);
986 		av_frame_unref(pFrameRGB);
987 
988 		// hook pFrameRGB output to buffer
989 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
990 		av_image_fill_arrays(pFrameRGB->data, pFrameRGB->linesize, mediaengine->m_buffer, pmp_want_pix_fmt, pCodecCtx->width, pCodecCtx->height, 1);
991 #else
992 		avpicture_fill((AVPicture *)pFrameRGB, mediaengine->m_buffer, pmp_want_pix_fmt, pCodecCtx->width, pCodecCtx->height);
993 #endif
994 
995 
996 		// decode video frame
997 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
998 		if (packet.size != 0)
999 			avcodec_send_packet(pCodecCtx, &packet);
1000 		int len = avcodec_receive_frame(pCodecCtx, pFrame);
1001 		if (len == 0) {
1002 			len = pFrame->pkt_size;
1003 			got_picture = 1;
1004 		} else if (len == AVERROR(EAGAIN)) {
1005 			len = 0;
1006 			got_picture = 0;
1007 		} else {
1008 			got_picture = 0;
1009 		}
1010 #else
1011 		int len = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);
1012 #endif
1013 		DEBUG_LOG(ME, "got_picture %d", got_picture);
1014 		if (got_picture){
1015 			SwsContext *img_convert_ctx = NULL;
1016 			img_convert_ctx = sws_getContext(
1017 				pCodecCtx->width,
1018 				pCodecCtx->height,
1019 				pCodecCtx->pix_fmt,
1020 				pCodecCtx->width,
1021 				pCodecCtx->height,
1022 				pmp_want_pix_fmt,
1023 				SWS_BILINEAR,
1024 				NULL, NULL, NULL);
1025 
1026 			if (!img_convert_ctx) {
1027 				ERROR_LOG(ME, "Cannot initialize sws conversion context");
1028 				return false;
1029 			}
1030 
1031 			// Convert to RGBA
1032 			int swsRet = sws_scale(img_convert_ctx, (const uint8_t* const*)pFrame->data,
1033 				pFrame->linesize, 0, pCodecCtx->height, pFrameRGB->data, pFrameRGB->linesize);
1034 			if (swsRet < 0){
1035 				ERROR_LOG(ME, "sws_scale: Error while converting %d", swsRet);
1036 				return false;
1037 			}
1038 			// free sws context
1039 			sws_freeContext(img_convert_ctx);
1040 
1041 			// update timestamp
1042 #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 58, 100)
1043 			int64_t bestPts = mediaengine->m_pFrame->best_effort_timestamp;
1044 			int64_t ptsDuration = mediaengine->m_pFrame->pkt_duration;
1045 #else
1046 			int64_t bestPts = av_frame_get_best_effort_timestamp(mediaengine->m_pFrame);
1047 			int64_t ptsDuration = av_frame_get_pkt_duration(mediaengine->m_pFrame);
1048 #endif
1049 			if (bestPts != AV_NOPTS_VALUE)
1050 				mediaengine->m_videopts = bestPts + ptsDuration - mediaengine->m_firstTimeStamp;
1051 			else
1052 				mediaengine->m_videopts += ptsDuration;
1053 
1054 			// push the decoded frame into pmp_queue
1055 			pmp_queue.push_back(pFrameRGB);
1056 
1057 			// write frame into ppm file
1058 			// SaveFrame(pNewFrameRGB, pCodecCtx->width, pCodecCtx->height);
1059 		}
1060 		// free some pointers
1061 #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
1062 		av_packet_unref(&packet);
1063 #else
1064 		av_free_packet(&packet);
1065 #endif
1066 		pmpframes->~H264Frames();
1067 		// must reset pmp_VideoSource address to zero after decoding.
1068 		pmp_videoSource = 0;
1069 		return true;
1070 	}
1071 	// not a pmp video, return false
1072 	return false;
1073 #else
1074 	return false;
1075 #endif
1076 }
1077 
1078 
__VideoPmpInit()1079 void __VideoPmpInit() {
1080 	pmp_oldStateLoaded = false;
1081 	pmpframes = new H264Frames();
1082 }
1083 
__VideoPmpShutdown()1084 void __VideoPmpShutdown() {
1085 #ifdef USE_FFMPEG
1086 	// We need to empty pmp_queue to not leak memory.
1087 	for (auto it = pmp_queue.begin(); it != pmp_queue.end(); ++it){
1088 		av_free(*it);
1089 	}
1090 	pmp_queue.clear();
1091 	pmp_ContextList.clear();
1092 	delete pmpframes;
1093 	pmpframes = NULL;
1094 #endif
1095 }
1096 
__VideoPmpDoState(PointerWrap & p)1097 void __VideoPmpDoState(PointerWrap &p){
1098 	auto s = p.Section("PMPVideo", 0, 1);
1099 	if (!s) {
1100 		if (p.mode == PointerWrap::MODE_READ)
1101 			pmp_oldStateLoaded = true;
1102 		return;
1103 	}
1104 
1105 	Do(p, pmp_videoSource);
1106 	Do(p, pmp_nBlocks);
1107 	if (p.mode == PointerWrap::MODE_READ){
1108 		// for loadstate, we will reinitialize the pmp codec
1109 		__VideoPmpShutdown();
1110 	}
1111 }
1112 
sceMpegAvcDecode(u32 mpeg,u32 auAddr,u32 frameWidth,u32 bufferAddr,u32 initAddr)1113 static u32 sceMpegAvcDecode(u32 mpeg, u32 auAddr, u32 frameWidth, u32 bufferAddr, u32 initAddr)
1114 {
1115 	MpegContext *ctx = getMpegCtx(mpeg);
1116 	if (!ctx) {
1117 		WARN_LOG(ME, "sceMpegAvcDecode(%08x, %08x, %d, %08x, %08x): bad mpeg handle", mpeg, auAddr, frameWidth, bufferAddr, initAddr);
1118 		return -1;
1119 	}
1120 
1121 	if (frameWidth == 0) {  // wtf, go sudoku passes in 0xcccccccc
1122 		if (!ctx->defaultFrameWidth) {
1123 			frameWidth = ctx->avc.avcDetailFrameWidth;
1124 		} else {
1125 			frameWidth = ctx->defaultFrameWidth;
1126 		}
1127 	}
1128 
1129 	SceMpegAu avcAu;
1130 	avcAu.read(auAddr);
1131 
1132 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ctx->mpegRingbufferAddr);
1133 	if (!ringbuffer.IsValid()) {
1134 		ERROR_LOG(ME, "Bogus mpegringbufferaddr");
1135 		return -1;
1136 	}
1137 
1138 	u32 buffer = Memory::Read_U32(bufferAddr);
1139 	u32 init = Memory::Read_U32(initAddr);
1140 	DEBUG_LOG(ME, "video: bufferAddr = %08x, *buffer = %08x, *init = %08x", bufferAddr, buffer, init);
1141 
1142 	// check and decode pmp video
1143 	bool ispmp = false;
1144 	if (decodePmpVideo(ringbuffer, mpeg)){
1145 		DEBUG_LOG(ME, "Using ffmpeg to decode pmp video");
1146 		ispmp = true;
1147 	}
1148 
1149 	if (ringbuffer->packetsRead == 0 || ctx->mediaengine->IsVideoEnd()) {
1150 		WARN_LOG(ME, "sceMpegAvcDecode(%08x, %08x, %d, %08x, %08x): mpeg buffer empty", mpeg, auAddr, frameWidth, bufferAddr, initAddr);
1151 		return hleDelayResult(ERROR_MPEG_AVC_DECODE_FATAL, "mpeg buffer empty", avcEmptyDelayMs);
1152 	}
1153 
1154 	s32 beforeAvail = ringbuffer->packets - ctx->mediaengine->getRemainSize() / 2048;
1155 
1156 	// We stored the video stream id here in sceMpegGetAvcAu().
1157 	ctx->mediaengine->setVideoStream(avcAu.esBuffer);
1158 
1159 	if (ispmp){
1160 #ifdef USE_FFMPEG
1161 		while (pmp_queue.size() != 0){
1162 			// playing all pmp_queue frames
1163 			ctx->mediaengine->m_pFrameRGB = pmp_queue.front();
1164 			int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode);
1165 			gpu->NotifyVideoUpload(buffer, bufferSize, frameWidth, ctx->videoPixelMode);
1166 			ctx->avc.avcFrameStatus = 1;
1167 			ctx->videoFrameCount++;
1168 
1169 			// free front frame
1170 			hleDelayResult(0, "pmp video decode", 30);
1171 			pmp_queue.pop_front();
1172 		}
1173 #endif
1174 	}
1175 	else if(ctx->mediaengine->stepVideo(ctx->videoPixelMode)) {
1176 		int bufferSize = ctx->mediaengine->writeVideoImage(buffer, frameWidth, ctx->videoPixelMode);
1177 		gpu->NotifyVideoUpload(buffer, bufferSize, frameWidth, ctx->videoPixelMode);
1178 		ctx->avc.avcFrameStatus = 1;
1179 		ctx->videoFrameCount++;
1180 	} else {
1181 		ctx->avc.avcFrameStatus = 0;
1182 	}
1183 	s32 afterAvail = ringbuffer->packets - ctx->mediaengine->getRemainSize() / 2048;
1184 	// Don't actually reset avail, we only change it by what was decoded.
1185 	// Garbage frames can cause this to be incorrect, but some games expect that.
1186 	if (mpegLibVersion <= 0x0103) {
1187 		ringbuffer->packetsAvail += afterAvail - beforeAvail;
1188 	} else {
1189 		ringbuffer->packetsAvail = afterAvail;
1190 	}
1191 
1192 	avcAu.pts = ctx->mediaengine->getVideoTimeStamp() + ctx->mpegFirstTimestamp;
1193 
1194 	// Flush structs back to memory
1195 	avcAu.write(auAddr);
1196 
1197 	// Save the current frame's status to initAddr
1198 	Memory::Write_U32(ctx->avc.avcFrameStatus, initAddr);
1199 	ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS;
1200 
1201 	DEBUG_LOG(ME, "sceMpegAvcDecode(%08x, %08x, %i, %08x, %08x)", mpeg, auAddr, frameWidth, bufferAddr, initAddr);
1202 
1203 	if (ctx->videoFrameCount <= 1)
1204 		return hleDelayResult(0, "mpeg decode", avcFirstDelayMs);
1205 	else
1206 		return hleDelayResult(0, "mpeg decode", avcDecodeDelayMs);
1207 	//hleEatMicro(3300);
1208 	//return hleDelayResult(0, "mpeg decode", 200);
1209 }
1210 
sceMpegAvcDecodeStop(u32 mpeg,u32 frameWidth,u32 bufferAddr,u32 statusAddr)1211 static u32 sceMpegAvcDecodeStop(u32 mpeg, u32 frameWidth, u32 bufferAddr, u32 statusAddr)
1212 {
1213 	if (!Memory::IsValidAddress(bufferAddr) || !Memory::IsValidAddress(statusAddr)){
1214 		ERROR_LOG(ME, "sceMpegAvcDecodeStop(%08x, %08x, %08x, %08x): invalid addresses", mpeg, frameWidth, bufferAddr, statusAddr);
1215 		return -1;
1216 	}
1217 
1218 	MpegContext *ctx = getMpegCtx(mpeg);
1219 	if (!ctx) {
1220 		WARN_LOG(ME, "sceMpegAvcDecodeStop(%08x, %08x, %08x, %08x): bad mpeg handle", mpeg, frameWidth, bufferAddr, statusAddr);
1221 		return -1;
1222 	}
1223 
1224 	DEBUG_LOG(ME, "sceMpegAvcDecodeStop(%08x, %08x, %08x, %08x)", mpeg, frameWidth, bufferAddr, statusAddr);
1225 
1226 	// No last frame generated
1227 	Memory::Write_U32(0, statusAddr);
1228 	return 0;
1229 }
1230 
sceMpegUnRegistStream(u32 mpeg,int streamUid)1231 static u32 sceMpegUnRegistStream(u32 mpeg, int streamUid)
1232 {
1233 	MpegContext *ctx = getMpegCtx(mpeg);
1234 	if (!ctx) {
1235 		WARN_LOG(ME, "sceMpegUnRegistStream(%08x, %i): bad mpeg handle", mpeg, streamUid);
1236 		return -1;
1237 	}
1238 
1239 	StreamInfo info = {0};
1240 
1241 	switch (info.type) {
1242 	case MPEG_AVC_STREAM:
1243 		ctx->avcRegistered = false;
1244 		break;
1245 	case MPEG_AUDIO_STREAM:
1246 	case MPEG_ATRAC_STREAM:
1247 		ctx->atracRegistered = false;
1248 		break;
1249 	case MPEG_PCM_STREAM:
1250 		ctx->pcmRegistered = false;
1251 		break;
1252 	case MPEG_DATA_STREAM:
1253 		ctx->dataRegistered = false;
1254 		break;
1255 	default :
1256 		DEBUG_LOG(ME, "sceMpegUnRegistStream(%i) : unknown streamID ", streamUid);
1257 		break;
1258 	}
1259 	ctx->streamMap[streamUid] = info;
1260 	info.type = -1;
1261 	info.sid = -1 ;
1262 	info.needsReset = true;
1263 	ctx->isAnalyzed = false;
1264 	return 0;
1265 }
1266 
sceMpegAvcDecodeDetail(u32 mpeg,u32 detailAddr)1267 static int sceMpegAvcDecodeDetail(u32 mpeg, u32 detailAddr)
1268 {
1269 	if (!Memory::IsValidAddress(detailAddr)){
1270 		WARN_LOG(ME, "sceMpegAvcDecodeDetail(%08x, %08x): invalid addresses", mpeg, detailAddr);
1271 		return -1;
1272 	}
1273 
1274 	MpegContext *ctx = getMpegCtx(mpeg);
1275 	if (!ctx) {
1276 		WARN_LOG(ME, "sceMpegAvcDecodeDetail(%08x, %08x): bad mpeg handle", mpeg, detailAddr);
1277 		return -1;
1278 	}
1279 
1280 	DEBUG_LOG(ME, "sceMpegAvcDecodeDetail(%08x, %08x)", mpeg, detailAddr);
1281 
1282 	Memory::Write_U32(ctx->avc.avcDecodeResult, detailAddr + 0);
1283 	Memory::Write_U32(ctx->videoFrameCount, detailAddr + 4);
1284 	Memory::Write_U32(ctx->avc.avcDetailFrameWidth, detailAddr + 8);
1285 	Memory::Write_U32(ctx->avc.avcDetailFrameHeight, detailAddr + 12);
1286 	Memory::Write_U32(0, detailAddr + 16);
1287 	Memory::Write_U32(0, detailAddr + 20);
1288 	Memory::Write_U32(0, detailAddr + 24);
1289 	Memory::Write_U32(0, detailAddr + 28);
1290 	Memory::Write_U32(ctx->avc.avcFrameStatus, detailAddr + 32);
1291 	return 0;
1292 }
1293 
sceMpegAvcDecodeStopYCbCr(u32 mpeg,u32 bufferAddr,u32 statusAddr)1294 static u32 sceMpegAvcDecodeStopYCbCr(u32 mpeg, u32 bufferAddr, u32 statusAddr)
1295 {
1296 	if (!Memory::IsValidAddress(bufferAddr) || !Memory::IsValidAddress(statusAddr)) {
1297 		ERROR_LOG(ME, "UNIMPL sceMpegAvcDecodeStopYCbCr(%08x, %08x, %08x): invalid addresses", mpeg, bufferAddr, statusAddr);
1298 		return -1;
1299 	}
1300 
1301 	MpegContext *ctx = getMpegCtx(mpeg);
1302 	if (!ctx) {
1303 		WARN_LOG(ME, "UNIMPL sceMpegAvcDecodeStopYCbCr(%08x, %08x, %08x): bad mpeg handle", mpeg, bufferAddr, statusAddr);
1304 		return -1;
1305 	}
1306 
1307 	ERROR_LOG(ME, "UNIMPL sceMpegAvcDecodeStopYCbCr(%08x, %08x, %08x)", mpeg, bufferAddr, statusAddr);
1308 	Memory::Write_U32(0, statusAddr);
1309 	return 0;
1310 }
1311 
sceMpegAvcDecodeYCbCr(u32 mpeg,u32 auAddr,u32 bufferAddr,u32 initAddr)1312 static int sceMpegAvcDecodeYCbCr(u32 mpeg, u32 auAddr, u32 bufferAddr, u32 initAddr)
1313 {
1314 	MpegContext *ctx = getMpegCtx(mpeg);
1315 	if (!ctx) {
1316 		WARN_LOG(ME, "sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x): bad mpeg handle", mpeg, auAddr, bufferAddr, initAddr);
1317 		return -1;
1318 	}
1319 
1320 	SceMpegAu avcAu;
1321 	avcAu.read(auAddr);
1322 
1323 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ctx->mpegRingbufferAddr);
1324 	if (!ringbuffer.IsValid()) {
1325 		ERROR_LOG(ME, "Bogus mpegringbufferaddr");
1326 		return -1;
1327 	}
1328 
1329 	if (ringbuffer->packetsRead == 0 || ctx->mediaengine->IsVideoEnd()) {
1330 		WARN_LOG(ME, "sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x): mpeg buffer empty", mpeg, auAddr, bufferAddr, initAddr);
1331 		return hleDelayResult(ERROR_MPEG_AVC_DECODE_FATAL, "mpeg buffer empty", avcEmptyDelayMs);
1332 	}
1333 
1334 	s32 beforeAvail = ringbuffer->packets - ctx->mediaengine->getRemainSize() / 2048;
1335 
1336 	// We stored the video stream id here in sceMpegGetAvcAu().
1337 	ctx->mediaengine->setVideoStream(avcAu.esBuffer);
1338 
1339 	u32 buffer = Memory::Read_U32(bufferAddr);
1340 	u32 init = Memory::Read_U32(initAddr);
1341 	DEBUG_LOG(ME, "*buffer = %08x, *init = %08x", buffer, init);
1342 
1343 	if (ctx->mediaengine->stepVideo(ctx->videoPixelMode)) {
1344 		// Don't draw here, we'll draw in the Csc func.
1345 		ctx->avc.avcFrameStatus = 1;
1346 		ctx->videoFrameCount++;
1347 	} else {
1348 		ctx->avc.avcFrameStatus = 0;
1349 	}
1350 	s32 afterAvail = ringbuffer->packets - ctx->mediaengine->getRemainSize() / 2048;
1351 	// Don't actually reset avail, we only change it by what was decoded.
1352 	// Garbage frames can cause this to be incorrect, but some games expect that.
1353 	if (mpegLibVersion <= 0x0103) {
1354 		ringbuffer->packetsAvail += afterAvail - beforeAvail;
1355 	} else {
1356 		ringbuffer->packetsAvail = afterAvail;
1357 	}
1358 
1359 	avcAu.pts = ctx->mediaengine->getVideoTimeStamp() + ctx->mpegFirstTimestamp;
1360 
1361 	// Flush structs back to memory
1362 	avcAu.write(auAddr);
1363 
1364 	// Save the current frame's status to initAddr
1365 	Memory::Write_U32(ctx->avc.avcFrameStatus, initAddr);
1366 	ctx->avc.avcDecodeResult = MPEG_AVC_DECODE_SUCCESS;
1367 
1368 	DEBUG_LOG(ME, "sceMpegAvcDecodeYCbCr(%08x, %08x, %08x, %08x)", mpeg, auAddr, bufferAddr, initAddr);
1369 
1370 	if (ctx->videoFrameCount <= 1)
1371 		return hleDelayResult(0, "mpeg decode", avcFirstDelayMs);
1372 	else
1373 		return hleDelayResult(0, "mpeg decode", avcDecodeDelayMs);
1374 	//hleEatMicro(3300);
1375 	//return hleDelayResult(0, "mpeg decode", 200);
1376 }
1377 
sceMpegAvcDecodeFlush(u32 mpeg)1378 static u32 sceMpegAvcDecodeFlush(u32 mpeg)
1379 {
1380 	MpegContext *ctx = getMpegCtx(mpeg);
1381 	if (!ctx) {
1382 		WARN_LOG(ME, "UNIMPL sceMpegAvcDecodeFlush(%08x): bad mpeg handle", mpeg);
1383 		return -1;
1384 	}
1385 
1386 	ERROR_LOG(ME, "UNIMPL sceMpegAvcDecodeFlush(%08x)", mpeg);
1387 	if ( ctx->videoFrameCount > 0 || ctx->audioFrameCount > 0) {
1388 		//__MpegFinish();
1389 	}
1390 	return 0;
1391 }
1392 
sceMpegInitAu(u32 mpeg,u32 bufferAddr,u32 auPointer)1393 static int sceMpegInitAu(u32 mpeg, u32 bufferAddr, u32 auPointer)
1394 {
1395 	MpegContext *ctx = getMpegCtx(mpeg);
1396 	if (!ctx) {
1397 		WARN_LOG(ME, "sceMpegInitAu(%08x, %i, %08x): bad mpeg handle", mpeg, bufferAddr, auPointer);
1398 		return -1;
1399 	}
1400 
1401 	DEBUG_LOG(ME, "sceMpegInitAu(%08x, %i, %08x)", mpeg, bufferAddr, auPointer);
1402 
1403 	SceMpegAu sceAu;
1404 	sceAu.read(auPointer);
1405 
1406 	if (bufferAddr >= 1 && bufferAddr <= (u32)MPEG_DATA_ES_BUFFERS && ctx->esBuffers[bufferAddr - 1]) {
1407 		// This esbuffer has been allocated for Avc.
1408 		// Default to 0, since we stuff the stream id in here.  Technically, we shouldn't.
1409 		// TODO: Do something better to track the AU data.  This used to be bufferAddr.
1410 		sceAu.esBuffer = 0;
1411 		sceAu.esSize = MPEG_AVC_ES_SIZE;
1412 		sceAu.dts = 0;
1413 		sceAu.pts = 0;
1414 
1415 		sceAu.write(auPointer);
1416 	} else {
1417 		// This esbuffer has been left as Atrac.
1418 		// Default to 0, since we stuff the stream id in here.  Technically, we shouldn't.
1419 		// TODO: Do something better to track the AU data.  This used to be bufferAddr.
1420 		sceAu.esBuffer = 0;
1421 		sceAu.esSize = MPEG_ATRAC_ES_SIZE;
1422 		sceAu.pts = 0;
1423 		sceAu.dts = UNKNOWN_TIMESTAMP;
1424 
1425 		sceAu.write(auPointer);
1426 	}
1427 	return 0;
1428 }
1429 
sceMpegQueryAtracEsSize(u32 mpeg,u32 esSizeAddr,u32 outSizeAddr)1430 static int sceMpegQueryAtracEsSize(u32 mpeg, u32 esSizeAddr, u32 outSizeAddr)
1431 {
1432 	if (!Memory::IsValidAddress(esSizeAddr) || !Memory::IsValidAddress(outSizeAddr)) {
1433 		ERROR_LOG(ME, "sceMpegQueryAtracEsSize(%08x, %08x, %08x): invalid addresses", mpeg, esSizeAddr, outSizeAddr);
1434 		return -1;
1435 	}
1436 
1437 	MpegContext *ctx = getMpegCtx(mpeg);
1438 	if (!ctx) {
1439 		WARN_LOG(ME, "sceMpegQueryAtracEsSize(%08x, %08x, %08x): bad mpeg handle", mpeg, esSizeAddr, outSizeAddr);
1440 		return -1;
1441 	}
1442 
1443 	DEBUG_LOG(ME, "sceMpegQueryAtracEsSize(%08x, %08x, %08x)", mpeg, esSizeAddr, outSizeAddr);
1444 
1445 	Memory::Write_U32(MPEG_ATRAC_ES_SIZE, esSizeAddr);
1446 	Memory::Write_U32(MPEG_ATRAC_ES_OUTPUT_SIZE, outSizeAddr);
1447 	return 0;
1448 }
1449 
sceMpegRingbufferAvailableSize(u32 ringbufferAddr)1450 static int sceMpegRingbufferAvailableSize(u32 ringbufferAddr)
1451 {
1452 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ringbufferAddr);
1453 
1454 	if (!ringbuffer.IsValid()) {
1455 		ERROR_LOG(ME, "sceMpegRingbufferAvailableSize(%08x): invalid ringbuffer, should crash", ringbufferAddr);
1456 		return SCE_KERNEL_ERROR_ILLEGAL_ADDRESS;
1457 	}
1458 
1459 	MpegContext *ctx = getMpegCtx(ringbuffer->mpeg);
1460 	if (!ctx) {
1461 		ERROR_LOG(ME, "sceMpegRingbufferAvailableSize(%08x): bad mpeg handle", ringbufferAddr);
1462 		return ERROR_MPEG_NOT_YET_INIT;
1463 	}
1464 
1465 	ctx->mpegRingbufferAddr = ringbufferAddr;
1466 	hleEatCycles(2020);
1467 	hleReSchedule("mpeg ringbuffer avail");
1468 
1469 	static int lastAvail = 0;
1470 	if (lastAvail != ringbuffer->packetsAvail) {
1471 		DEBUG_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packets - ringbuffer->packetsAvail, ringbufferAddr);
1472 		lastAvail = ringbuffer->packetsAvail;
1473 	} else {
1474 		VERBOSE_LOG(ME, "%i=sceMpegRingbufferAvailableSize(%08x)", ringbuffer->packets - ringbuffer->packetsAvail, ringbufferAddr);
1475 	}
1476 	return ringbuffer->packets - ringbuffer->packetsAvail;
1477 }
1478 
run(MipsCall & call)1479 void PostPutAction::run(MipsCall &call) {
1480 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ringAddr_);
1481 
1482 	MpegContext *ctx = getMpegCtx(ringbuffer->mpeg);
1483 	int writeOffset = ringbuffer->packetsWritePos % (s32)ringbuffer->packets;
1484 	const u8 *data = Memory::GetPointer(ringbuffer->data + writeOffset * 2048);
1485 
1486 	int packetsAddedThisRound = currentMIPS->r[MIPS_REG_V0];
1487 	if (packetsAddedThisRound > 0) {
1488 		ringbufferPutPacketsAdded += packetsAddedThisRound;
1489 	}
1490 
1491 	// It seems validation is done only by older mpeg libs.
1492 	if (mpegLibVersion < 0x0105 && packetsAddedThisRound > 0) {
1493 		// TODO: Faster / less wasteful validation.
1494 		std::unique_ptr<MpegDemux> demuxer(new MpegDemux(packetsAddedThisRound * 2048, 0));
1495 		int readOffset = ringbuffer->packetsRead % (s32)ringbuffer->packets;
1496 		const u8 *buf = Memory::GetPointer(ringbuffer->data + readOffset * 2048);
1497 		bool invalid = false;
1498 		for (int i = 0; i < packetsAddedThisRound; ++i) {
1499 			demuxer->addStreamData(buf, 2048);
1500 			buf += 2048;
1501 
1502 			if (!demuxer->demux(0xFFFF)) {
1503 				invalid = true;
1504 			}
1505 		}
1506 		if (invalid) {
1507 			// Bail out early - don't accept any of the packets, even the good ones.
1508 			ERROR_LOG_REPORT(ME, "sceMpegRingbufferPut(): invalid mpeg data");
1509 			call.setReturnValue(ERROR_MPEG_INVALID_VALUE);
1510 
1511 			if (mpegLibVersion <= 0x0103) {
1512 				// Act like they were actually added, but don't increment read pos.
1513 				ringbuffer->packetsWritePos += packetsAddedThisRound;
1514 				ringbuffer->packetsAvail += packetsAddedThisRound;
1515 			}
1516 			return;
1517 		}
1518 	}
1519 
1520 	if (ringbuffer->packetsRead == 0 && ctx->mediaengine && packetsAddedThisRound > 0) {
1521 		// init mediaEngine
1522 		AnalyzeMpeg(ctx->mpegheader, 2048, ctx);
1523 		ctx->mediaengine->loadStream(ctx->mpegheader, 2048, ringbuffer->packets * ringbuffer->packetSize);
1524 	}
1525 	if (packetsAddedThisRound > 0) {
1526 		if (packetsAddedThisRound > ringbuffer->packets - ringbuffer->packetsAvail) {
1527 			WARN_LOG(ME, "sceMpegRingbufferPut clamping packetsAdded old=%i new=%i", packetsAddedThisRound, ringbuffer->packets - ringbuffer->packetsAvail);
1528 			packetsAddedThisRound = ringbuffer->packets - ringbuffer->packetsAvail;
1529 		}
1530 		int actuallyAdded = ctx->mediaengine == NULL ? 8 : ctx->mediaengine->addStreamData(data, packetsAddedThisRound * 2048) / 2048;
1531 		if (actuallyAdded != packetsAddedThisRound) {
1532 			WARN_LOG_REPORT(ME, "sceMpegRingbufferPut(): unable to enqueue all added packets, going to overwrite some frames.");
1533 		}
1534 		ringbuffer->packetsRead += packetsAddedThisRound;
1535 		ringbuffer->packetsWritePos += packetsAddedThisRound;
1536 		ringbuffer->packetsAvail += packetsAddedThisRound;
1537 	}
1538 	DEBUG_LOG(ME, "packetAdded: %i packetsRead: %i packetsTotal: %i", packetsAddedThisRound, ringbuffer->packetsRead, ringbuffer->packets);
1539 
1540 	if (packetsAddedThisRound < 0 && ringbufferPutPacketsAdded == 0) {
1541 		// Return an error.
1542 		call.setReturnValue(packetsAddedThisRound);
1543 	} else {
1544 		call.setReturnValue(ringbufferPutPacketsAdded);
1545 	}
1546 }
1547 
1548 
1549 // Program signals that it has written data to the ringbuffer and gets a callback ?
sceMpegRingbufferPut(u32 ringbufferAddr,int numPackets,int available)1550 static u32 sceMpegRingbufferPut(u32 ringbufferAddr, int numPackets, int available)
1551 {
1552 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ringbufferAddr);
1553 	if (!ringbuffer.IsValid()) {
1554 		// Would have crashed before, TODO test behavior.
1555 		ERROR_LOG_REPORT(ME, "sceMpegRingbufferPut(%08x, %i, %i): invalid ringbuffer address", ringbufferAddr, numPackets, available);
1556 		return -1;
1557 	}
1558 
1559 	numPackets = std::min(numPackets, available);
1560 	// Generally, program will call sceMpegRingbufferAvailableSize() before this func.
1561 	// Seems still need to check actual available, Patapon 3 for example.
1562 	numPackets = std::min(numPackets, ringbuffer->packets - ringbuffer->packetsAvail);
1563 	if (numPackets <= 0) {
1564 		DEBUG_LOG(ME, "sceMpegRingbufferPut(%08x, %i, %i): no packets to enqueue", ringbufferAddr, numPackets, available);
1565 		return 0;
1566 	}
1567 
1568 	MpegContext *ctx = getMpegCtx(ringbuffer->mpeg);
1569 	if (!ctx) {
1570 		WARN_LOG(ME, "sceMpegRingbufferPut(%08x, %i, %i): bad mpeg handle %08x", ringbufferAddr, numPackets, available, ringbuffer->mpeg);
1571 		return -1;
1572 	}
1573 	ringbufferPutPacketsAdded = 0;
1574 	// Execute callback function as a direct MipsCall, no blocking here so no messing around with wait states etc
1575 	if (ringbuffer->callback_addr != 0) {
1576 		DEBUG_LOG(ME, "sceMpegRingbufferPut(%08x, %i, %i)", ringbufferAddr, numPackets, available);
1577 
1578 		// Call this multiple times until we get numPackets.
1579 		// Normally this would be if it did not read enough, but also if available > packets.
1580 		// Should ultimately return the TOTAL number of returned packets.
1581 		int writeOffset = ringbuffer->packetsWritePos % (s32)ringbuffer->packets;
1582 		u32 packetsThisRound = 0;
1583 		while (numPackets) {
1584 			PostPutAction *action = (PostPutAction *)__KernelCreateAction(actionPostPut);
1585 			action->setRingAddr(ringbufferAddr);
1586 
1587 			packetsThisRound = std::min(numPackets, (s32)ringbuffer->packets - writeOffset);
1588 			numPackets -= packetsThisRound;
1589 			u32 args[3] = { (u32)ringbuffer->data + (u32)writeOffset * 2048, packetsThisRound, (u32)ringbuffer->callback_args };
1590 			hleEnqueueCall(ringbuffer->callback_addr, 3, args, action);
1591 			writeOffset = (writeOffset + packetsThisRound) % (s32)ringbuffer->packets;
1592 			// Old savestate don't use this feature, just for compatibility.
1593 			if (!useRingbufferPutCallbackMulti)
1594 				break;
1595 		}
1596 	} else {
1597 		ERROR_LOG_REPORT(ME, "sceMpegRingbufferPut: callback_addr zero");
1598 	}
1599 	return 0;
1600 }
1601 
sceMpegGetAvcAu(u32 mpeg,u32 streamId,u32 auAddr,u32 attrAddr)1602 static int sceMpegGetAvcAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr)
1603 {
1604 	MpegContext *ctx = getMpegCtx(mpeg);
1605 	if (!ctx) {
1606 		WARN_LOG(ME, "sceMpegGetAvcAu(%08x, %08x, %08x, %08x): bad mpeg handle", mpeg, streamId, auAddr, attrAddr);
1607 		return -1;
1608 	}
1609 
1610 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ctx->mpegRingbufferAddr);
1611 	if (!ringbuffer.IsValid()) {
1612 		// Would have crashed before, TODO test behavior.
1613 		ERROR_LOG_REPORT(ME, "sceMpegGetAvcAu(%08x, %08x, %08x, %08x): invalid ringbuffer address", mpeg, streamId, auAddr, attrAddr);
1614 		return -1;
1615 	}
1616 
1617 	if (PSP_CoreParameter().compat.flags().MpegAvcWarmUp) {
1618 		if (ctx->mpegwarmUp == 0) {
1619 			DEBUG_LOG(ME, "sceMpegGetAvcAu(%08x, %08x, %08x, %08x): warming up", mpeg, streamId, auAddr, attrAddr);
1620 			ctx->mpegwarmUp++;
1621 			return ERROR_MPEG_NO_DATA;
1622 		}
1623 	}
1624 
1625 	SceMpegAu avcAu;
1626 	avcAu.read(auAddr);
1627 
1628 	if (ringbuffer->packetsRead == 0 || ringbuffer->packetsAvail == 0) {
1629 		DEBUG_LOG(ME, "ERROR_MPEG_NO_DATA=sceMpegGetAvcAu(%08x, %08x, %08x, %08x)", mpeg, streamId, auAddr, attrAddr);
1630 		avcAu.pts = -1;
1631 		avcAu.dts = -1;
1632 		avcAu.write(auAddr);
1633 		// TODO: Does this really reschedule?
1634 		return hleDelayResult(ERROR_MPEG_NO_DATA, "mpeg get avc", mpegDecodeErrorDelayMs);
1635 	}
1636 
1637 	auto streamInfo = ctx->streamMap.find(streamId);
1638 	if (streamInfo == ctx->streamMap.end())	{
1639 		WARN_LOG_REPORT(ME, "sceMpegGetAvcAu: invalid video stream %08x", streamId);
1640 		return -1;
1641 	}
1642 
1643 	if (streamInfo->second.needsReset) {
1644 		avcAu.pts = 0;
1645 		streamInfo->second.needsReset = false;
1646 	}
1647 
1648 	// esBuffer is the memory where this au data goes.  We don't write the data to memory.
1649 	// Instead, let's abuse it to keep track of the stream number.
1650 	avcAu.esBuffer = streamInfo->second.num;
1651 
1652 	/*// Wait for audio if too much ahead
1653 	if (ctx->atracRegistered && (ctx->mediaengine->getVideoTimeStamp() > ctx->mediaengine->getAudioTimeStamp() + getMaxAheadTimestamp(mpegRingbuffer)))
1654 	{
1655 		ERROR_LOG(ME, "sceMpegGetAvcAu - video too much ahead");
1656 		// TODO: Does this really reschedule?
1657 		return hleDelayResult(ERROR_MPEG_NO_DATA, "mpeg get avc", mpegDecodeErrorDelayMs);
1658 	}*/
1659 
1660 	int result = 0;
1661 
1662 	avcAu.pts = ctx->mediaengine->getVideoTimeStamp() + ctx->mpegFirstTimestamp;
1663 	avcAu.dts = avcAu.pts - videoTimestampStep;
1664 
1665 	if (ctx->mediaengine->IsVideoEnd()) {
1666 		INFO_LOG(ME, "video end reach. pts: %i dts: %i", (int)avcAu.pts, (int)ctx->mediaengine->getLastTimeStamp());
1667 		ringbuffer->packetsAvail = 0;
1668 
1669 		result = ERROR_MPEG_NO_DATA;
1670 	}
1671 
1672 	// The avcau struct may have been modified by mediaengine, write it back.
1673 	avcAu.write(auAddr);
1674 
1675 	// Jeanne d'Arc return 00000000 as attrAddr here and cause WriteToHardware error
1676 	if (Memory::IsValidAddress(attrAddr)) {
1677 		Memory::Write_U32(1, attrAddr);
1678 	}
1679 
1680 	DEBUG_LOG(ME, "%x=sceMpegGetAvcAu(%08x, %08x, %08x, %08x)", result, mpeg, streamId, auAddr, attrAddr);
1681 	// TODO: sceMpegGetAvcAu seems to modify esSize, and delay when it's > 1000 or something.
1682 	// There's definitely more to it, but ultimately it seems games should expect it to delay randomly.
1683 	return hleDelayResult(result, "mpeg get avc", 100);
1684 }
1685 
sceMpegFinish()1686 static u32 sceMpegFinish()
1687 {
1688 	if (!isMpegInit) {
1689 		WARN_LOG(ME, "sceMpegFinish(...): not initialized");
1690 		// TODO: Need to properly hook module load/unload for this to work right.
1691 		//return ERROR_MPEG_NOT_YET_INIT;
1692 	} else {
1693 		INFO_LOG(ME, "sceMpegFinish(...)");
1694 		__VideoPmpShutdown();
1695 	}
1696 	isMpegInit = false;
1697 	//__MpegFinish();
1698 	return hleDelayResult(0, "mpeg finish", 250);
1699 }
1700 
sceMpegQueryMemSize()1701 static u32 sceMpegQueryMemSize() {
1702 	return hleLogSuccessX(ME, MpegRequiredMem());
1703 }
1704 
sceMpegGetAtracAu(u32 mpeg,u32 streamId,u32 auAddr,u32 attrAddr)1705 static int sceMpegGetAtracAu(u32 mpeg, u32 streamId, u32 auAddr, u32 attrAddr)
1706 {
1707 	MpegContext *ctx = getMpegCtx(mpeg);
1708 	if (!ctx) {
1709 		WARN_LOG(ME, "sceMpegGetAtracAu(%08x, %08x, %08x, %08x): bad mpeg handle", mpeg, streamId, auAddr, attrAddr);
1710 		return -1;
1711 	}
1712 
1713 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ctx->mpegRingbufferAddr);
1714 	if (!ringbuffer.IsValid()) {
1715 		// Would have crashed before, TODO test behavior.
1716 		WARN_LOG(ME, "sceMpegGetAtracAu(%08x, %08x, %08x, %08x): invalid ringbuffer address", mpeg, streamId, auAddr, attrAddr);
1717 		return -1;
1718 	}
1719 
1720 	SceMpegAu atracAu;
1721 	atracAu.read(auAddr);
1722 
1723 	auto streamInfo = ctx->streamMap.find(streamId);
1724 	if (streamInfo != ctx->streamMap.end() && streamInfo->second.needsReset) {
1725 		atracAu.pts = 0;
1726 		streamInfo->second.needsReset = false;
1727 	}
1728 	if (streamInfo == ctx->streamMap.end()) {
1729 		WARN_LOG_REPORT(ME, "sceMpegGetAtracAu: invalid audio stream %08x", streamId);
1730 		// TODO: Why was this changed to not return an error?
1731 	}
1732 
1733 	// The audio can end earlier than the video does.
1734 	if (ringbuffer->packetsAvail == 0) {
1735 		DEBUG_LOG(ME, "ERROR_MPEG_NO_DATA=sceMpegGetAtracAu(%08x, %08x, %08x, %08x)", mpeg, streamId, auAddr, attrAddr);
1736 		// TODO: Does this really delay?
1737 		return hleDelayResult(ERROR_MPEG_NO_DATA, "mpeg get atrac", mpegDecodeErrorDelayMs);
1738 	}
1739 
1740 	// esBuffer is the memory where this au data goes.  We don't write the data to memory.
1741 	// Instead, let's abuse it to keep track of the stream number.
1742 	if (streamInfo != ctx->streamMap.end()) {
1743 		atracAu.esBuffer = streamInfo->second.num;
1744 		ctx->mediaengine->setAudioStream(streamInfo->second.num);
1745 	}
1746 
1747 	int result = 0;
1748 	atracAu.pts = ctx->mediaengine->getAudioTimeStamp() + ctx->mpegFirstTimestamp;
1749 
1750 	if (ctx->mediaengine->IsVideoEnd()) {
1751 		INFO_LOG(ME, "video end reach. pts: %i dts: %i", (int)atracAu.pts, (int)ctx->mediaengine->getLastTimeStamp());
1752 		ringbuffer->packetsAvail = 0;
1753 		// TODO: Is this correct?
1754 		if (!ctx->mediaengine->IsNoAudioData()) {
1755 			WARN_LOG_REPORT(ME, "Video end without audio end, potentially skipping some audio?");
1756 		}
1757 		result = ERROR_MPEG_NO_DATA;
1758 	}
1759 
1760 	if (ctx->atracRegistered && ctx->mediaengine->IsNoAudioData() && !ctx->endOfAudioReached) {
1761 		WARN_LOG(ME, "Audio end reach. pts: %i dts: %i", (int)atracAu.pts, (int)ctx->mediaengine->getLastTimeStamp());
1762 		ctx->endOfAudioReached = true;
1763 	}
1764 	if (ctx->mediaengine->IsNoAudioData()) {
1765 		result = ERROR_MPEG_NO_DATA;
1766 	}
1767 
1768 	atracAu.write(auAddr);
1769 
1770 	// 3rd birthday return 00000000 as attrAddr here and cause WriteToHardware error
1771 	if (Memory::IsValidAddress(attrAddr)) {
1772 		Memory::Write_U32(0, attrAddr);
1773 	}
1774 
1775 	DEBUG_LOG(ME, "%x=sceMpegGetAtracAu(%08x, %08x, %08x, %08x)", result, mpeg, streamId, auAddr, attrAddr);
1776 	// TODO: Not clear on exactly when this delays.
1777 	return hleDelayResult(result, "mpeg get atrac", 100);
1778 }
1779 
sceMpegQueryPcmEsSize(u32 mpeg,u32 esSizeAddr,u32 outSizeAddr)1780 static int sceMpegQueryPcmEsSize(u32 mpeg, u32 esSizeAddr, u32 outSizeAddr)
1781 {
1782 	if (!Memory::IsValidAddress(esSizeAddr) || !Memory::IsValidAddress(outSizeAddr)) {
1783 		ERROR_LOG(ME, "sceMpegQueryPcmEsSize(%08x, %08x, %08x): invalid addresses", mpeg, esSizeAddr, outSizeAddr);
1784 		return -1;
1785 	}
1786 
1787 	MpegContext *ctx = getMpegCtx(mpeg);
1788 	if (!ctx) {
1789 		WARN_LOG(ME, "sceMpegQueryPcmEsSize(%08x, %08x, %08x): bad mpeg handle", mpeg, esSizeAddr, outSizeAddr);
1790 		return -1;
1791 	}
1792 
1793 	ERROR_LOG(ME, "sceMpegQueryPcmEsSize(%08x, %08x, %08x)", mpeg, esSizeAddr, outSizeAddr);
1794 
1795 	Memory::Write_U32(MPEG_PCM_ES_SIZE, esSizeAddr);
1796 	Memory::Write_U32(MPEG_PCM_ES_OUTPUT_SIZE, outSizeAddr);
1797 	return 0;
1798 }
1799 
1800 
sceMpegChangeGetAuMode(u32 mpeg,int streamUid,int mode)1801 static u32 sceMpegChangeGetAuMode(u32 mpeg, int streamUid, int mode)
1802 {
1803 	MpegContext *ctx = getMpegCtx(mpeg);
1804 	if (!ctx) {
1805 		WARN_LOG(ME, "sceMpegChangeGetAuMode(%08x, %i, %i): bad mpeg handle", mpeg, streamUid, mode);
1806 		return ERROR_MPEG_INVALID_VALUE;
1807 	}
1808 	if (mode != MPEG_AU_MODE_DECODE && mode != MPEG_AU_MODE_SKIP) {
1809 		ERROR_LOG(ME, "UNIMPL sceMpegChangeGetAuMode(%08x, %i, %i): bad mode", mpeg, streamUid, mode);
1810 		return ERROR_MPEG_INVALID_VALUE;
1811 	}
1812 
1813 	auto stream = ctx->streamMap.find(streamUid);
1814 	if (stream == ctx->streamMap.end()) {
1815 		ERROR_LOG(ME, "UNIMPL sceMpegChangeGetAuMode(%08x, %i, %i): unknown streamID", mpeg, streamUid, mode);
1816 		return ERROR_MPEG_INVALID_VALUE;
1817 	} else {
1818 		StreamInfo &info = stream->second;
1819 		DEBUG_LOG(ME, "UNIMPL sceMpegChangeGetAuMode(%08x, %i, %i): changing type=%d", mpeg, streamUid, mode, info.type);
1820 		switch (info.type) {
1821 		case MPEG_AVC_STREAM:
1822 			if (mode == MPEG_AU_MODE_DECODE) {
1823 				ctx->ignoreAvc = false;
1824 			} else if (mode == MPEG_AU_MODE_SKIP) {
1825 				ctx->ignoreAvc = true;
1826 			}
1827 			break;
1828 		case MPEG_AUDIO_STREAM:
1829 		case MPEG_ATRAC_STREAM:
1830 			if (mode == MPEG_AU_MODE_DECODE) {
1831 				ctx->ignoreAtrac = false;
1832 			} else if (mode == MPEG_AU_MODE_SKIP) {
1833 				ctx->ignoreAtrac = true;
1834 			}
1835 			break;
1836 		case MPEG_PCM_STREAM:
1837 			if (mode == MPEG_AU_MODE_DECODE) {
1838 				ctx->ignorePcm = false;
1839 			} else if (mode == MPEG_AU_MODE_SKIP) {
1840 				ctx->ignorePcm = true;
1841 			}
1842 			break;
1843 		default:
1844 			ERROR_LOG(ME, "UNIMPL sceMpegChangeGetAuMode(%08x, %i, %i): unknown streamID", mpeg, streamUid, mode);
1845 			break;
1846 		}
1847 	}
1848 	return 0;
1849 }
1850 
sceMpegChangeGetAvcAuMode(u32 mpeg,u32 stream_addr,int mode)1851 static u32 sceMpegChangeGetAvcAuMode(u32 mpeg, u32 stream_addr, int mode)
1852 {
1853 	if (!Memory::IsValidAddress(stream_addr)) {
1854 		ERROR_LOG(ME, "UNIMPL sceMpegChangeGetAvcAuMode(%08x, %08x, %i): invalid addresses", mpeg, stream_addr, mode);
1855 		return -1;
1856 	}
1857 
1858 	MpegContext *ctx = getMpegCtx(mpeg);
1859 	if (!ctx) {
1860 		WARN_LOG(ME, "UNIMPL sceMpegChangeGetAvcAuMode(%08x, %08x, %i): bad mpeg handle", mpeg, stream_addr, mode);
1861 		return -1;
1862 	}
1863 
1864 	ERROR_LOG_REPORT_ONCE(mpegChangeAvcAu, ME, "UNIMPL sceMpegChangeGetAvcAuMode(%08x, %08x, %i)", mpeg, stream_addr, mode);
1865 	return 0;
1866 }
1867 
sceMpegGetPcmAu(u32 mpeg,int streamUid,u32 auAddr,u32 attrAddr)1868 static u32 sceMpegGetPcmAu(u32 mpeg, int streamUid, u32 auAddr, u32 attrAddr)
1869 {
1870 	MpegContext *ctx = getMpegCtx(mpeg);
1871 	if (!ctx) {
1872 		WARN_LOG(ME, "UNIMPL sceMpegGetPcmAu(%08x, %i, %08x, %08x): bad mpeg handle", mpeg, streamUid, auAddr, attrAddr);
1873 		return -1;
1874 	}
1875 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ctx->mpegRingbufferAddr);
1876 	if (!ringbuffer.IsValid()) {
1877 		// Would have crashed before, TODO test behavior
1878 		WARN_LOG(ME, "sceMpegGetPcmAu(%08x, %08x, %08x, %08x): invalid ringbuffer address", mpeg, streamUid, auAddr, attrAddr);
1879 		return -1;
1880 	}
1881 	if (!Memory::IsValidAddress(streamUid)) {
1882 		WARN_LOG(ME, "sceMpegGetPcmAu(%08x, %08x, %08x, %08x):  didn't get a fake stream", mpeg, streamUid, auAddr, attrAddr);
1883 		return ERROR_MPEG_INVALID_ADDR;
1884 	}
1885 	SceMpegAu atracAu;
1886 	atracAu.read(auAddr);
1887 	auto streamInfo = ctx->streamMap.find(streamUid);
1888 	if (streamInfo == ctx->streamMap.end()) {
1889 		WARN_LOG(ME, "sceMpegGetPcmAu(%08x, %08x, %08x, %08x):  bad streamUid ", mpeg, streamUid, auAddr, attrAddr);
1890 		return -1;
1891 	}
1892 
1893 	atracAu.write(auAddr);
1894 	u32 attr = 1 << 7; // Sampling rate (1 = 44.1kHz).
1895 	attr |= 2;         // Number of channels (1 - MONO / 2 - STEREO).
1896 	if (Memory::IsValidAddress(attrAddr))
1897 		Memory::Write_U32(attr, attrAddr);
1898 
1899 	ERROR_LOG_REPORT_ONCE(mpegPcmAu, ME, "UNIMPL sceMpegGetPcmAu(%08x, %i, %08x, %08x)", mpeg, streamUid, auAddr, attrAddr);
1900 	return 0;
1901 }
1902 
__MpegRingbufferQueryPackNum(u32 memorySize)1903 static int __MpegRingbufferQueryPackNum(u32 memorySize) {
1904 	return memorySize / (2048 + 104);
1905 }
1906 
sceMpegRingbufferQueryPackNum(u32 memorySize)1907 static int sceMpegRingbufferQueryPackNum(u32 memorySize) {
1908 	DEBUG_LOG(ME, "sceMpegRingbufferQueryPackNum(%i)", memorySize);
1909 	return __MpegRingbufferQueryPackNum(memorySize);
1910 }
1911 
sceMpegFlushAllStream(u32 mpeg)1912 static u32 sceMpegFlushAllStream(u32 mpeg)
1913 {
1914 	MpegContext *ctx = getMpegCtx(mpeg);
1915 	if (!ctx) {
1916 		WARN_LOG(ME, "sceMpegFlushAllStream(%08x): bad mpeg handle", mpeg);
1917 		return -1;
1918 	}
1919 
1920 	WARN_LOG(ME, "UNIMPL sceMpegFlushAllStream(%08x)", mpeg);
1921 
1922 	ctx->isAnalyzed = false;
1923 
1924 	auto ringbuffer = PSPPointer<SceMpegRingBuffer>::Create(ctx->mpegRingbufferAddr);
1925 	if (ringbuffer.IsValid()) {
1926 		ringbuffer->packetsAvail = 0;
1927 		ringbuffer->packetsRead = 0;
1928 		ringbuffer->packetsWritePos = 0;
1929 	}
1930 
1931 	return 0;
1932 }
1933 
sceMpegFlushStream(u32 mpeg,int stream_addr)1934 static u32 sceMpegFlushStream(u32 mpeg, int stream_addr)
1935 {
1936 	if (!Memory::IsValidAddress(stream_addr)) {
1937 		ERROR_LOG(ME, "UNIMPL sceMpegFlushStream(%08x, %i): invalid addresses", mpeg , stream_addr);
1938 		return -1;
1939 	}
1940 
1941 	MpegContext *ctx = getMpegCtx(mpeg);
1942 	if (!ctx) {
1943 		WARN_LOG(ME, "UNIMPL sceMpegFlushStream(%08x, %i): bad mpeg handle", mpeg , stream_addr);
1944 		return -1;
1945 	}
1946 
1947 	ERROR_LOG(ME, "UNIMPL sceMpegFlushStream(%08x, %i)", mpeg , stream_addr);
1948 	//__MpegFinish();
1949 	return 0;
1950 }
1951 
sceMpegAvcCopyYCbCr(u32 mpeg,u32 sourceAddr,u32 YCbCrAddr)1952 static u32 sceMpegAvcCopyYCbCr(u32 mpeg, u32 sourceAddr, u32 YCbCrAddr)
1953 {
1954 	if (!Memory::IsValidAddress(sourceAddr) || !Memory::IsValidAddress(YCbCrAddr)) {
1955 		ERROR_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x): invalid addresses", mpeg, sourceAddr, YCbCrAddr);
1956 		return -1;
1957 	}
1958 
1959 	MpegContext *ctx = getMpegCtx(mpeg);
1960 	if (!ctx) {
1961 		ERROR_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x): bad mpeg handle", mpeg, sourceAddr, YCbCrAddr);
1962 		return -1;
1963 	}
1964 
1965 	WARN_LOG(ME, "UNIMPL sceMpegAvcCopyYCbCr(%08x, %08x, %08x)", mpeg, sourceAddr, YCbCrAddr);
1966 	return 0;
1967 }
1968 
sceMpegAtracDecode(u32 mpeg,u32 auAddr,u32 bufferAddr,int init)1969 static u32 sceMpegAtracDecode(u32 mpeg, u32 auAddr, u32 bufferAddr, int init)
1970 {
1971 	MpegContext *ctx = getMpegCtx(mpeg);
1972 	if (!ctx) {
1973 		WARN_LOG(ME, "sceMpegAtracDecode(%08x, %08x, %08x, %i): bad mpeg handle", mpeg, auAddr, bufferAddr, init);
1974 		return -1;
1975 	}
1976 
1977 	if (!Memory::IsValidAddress(bufferAddr)) {
1978 		WARN_LOG(ME, "sceMpegAtracDecode(%08x, %08x, %08x, %i): invalid addresses", mpeg, auAddr, bufferAddr, init);
1979 		return -1;
1980 	}
1981 
1982 	DEBUG_LOG(ME, "sceMpegAtracDecode(%08x, %08x, %08x, %i)", mpeg, auAddr, bufferAddr, init);
1983 
1984 	SceMpegAu atracAu;
1985 	atracAu.read(auAddr);
1986 
1987 	// We kept track of the stream number here in sceMpegGetAtracAu().
1988 	ctx->mediaengine->setAudioStream(atracAu.esBuffer);
1989 
1990 	Memory::Memset(bufferAddr, 0, MPEG_ATRAC_ES_OUTPUT_SIZE, "MpegAtracClear");
1991 	ctx->mediaengine->getAudioSamples(bufferAddr);
1992 	atracAu.pts = ctx->mediaengine->getAudioTimeStamp() + ctx->mpegFirstTimestamp;
1993 
1994 	atracAu.write(auAddr);
1995 
1996 
1997 	return hleDelayResult(0, "mpeg atrac decode", atracDecodeDelayMs);
1998 	//hleEatMicro(4000);
1999 	//return hleDelayResult(0, "mpeg atrac decode", 200);
2000 }
2001 
2002 // YCbCr -> RGB color space conversion
sceMpegAvcCsc(u32 mpeg,u32 sourceAddr,u32 rangeAddr,int frameWidth,u32 destAddr)2003 static u32 sceMpegAvcCsc(u32 mpeg, u32 sourceAddr, u32 rangeAddr, int frameWidth, u32 destAddr)
2004 {
2005 	if (!Memory::IsValidAddress(sourceAddr) || !Memory::IsValidAddress(rangeAddr) || !Memory::IsValidAddress(destAddr)) {
2006 		ERROR_LOG(ME, "sceMpegAvcCsc(%08x, %08x, %08x, %i, %08x): invalid addresses", mpeg, sourceAddr, rangeAddr, frameWidth, destAddr);
2007 		return -1;
2008 	}
2009 
2010 	MpegContext *ctx = getMpegCtx(mpeg);
2011 	if (!ctx) {
2012 		WARN_LOG(ME, "sceMpegAvcCsc(%08x, %08x, %08x, %i, %08x): bad mpeg handle", mpeg, sourceAddr, rangeAddr, frameWidth, destAddr);
2013 		return -1;
2014 	}
2015 
2016 	DEBUG_LOG(ME, "sceMpegAvcCsc(%08x, %08x, %08x, %i, %08x)", mpeg, sourceAddr, rangeAddr, frameWidth, destAddr);
2017 
2018 	if (frameWidth == 0) {
2019 		if (!ctx->defaultFrameWidth) {
2020 			frameWidth = ctx->avc.avcDetailFrameWidth;
2021 		} else {
2022 			frameWidth = ctx->defaultFrameWidth;
2023 		}
2024 	}
2025 
2026 	int x = Memory::Read_U32(rangeAddr);
2027 	int y = Memory::Read_U32(rangeAddr + 4);
2028 	int width = Memory::Read_U32(rangeAddr + 8);
2029 	int height = Memory::Read_U32(rangeAddr + 12);
2030 
2031 	if (x < 0 || y < 0 || width < 0 || height < 0) {
2032 		WARN_LOG(ME, "sceMpegAvcCsc(%08x, %08x, %08x, %i, %08x) returning ERROR_INVALID_VALUE", mpeg, sourceAddr, rangeAddr, frameWidth, destAddr);
2033 		return SCE_KERNEL_ERROR_INVALID_VALUE;
2034 	}
2035 
2036 	int destSize = ctx->mediaengine->writeVideoImageWithRange(destAddr, frameWidth, ctx->videoPixelMode, x, y, width, height);
2037 	gpu->NotifyVideoUpload(destAddr, destSize, frameWidth, ctx->videoPixelMode);
2038 
2039 	// Do not use avcDecodeDelayMs 's value
2040 	// Will cause video 's screen dislocation in Bleach heat of soul 6
2041 	// https://github.com/hrydgard/ppsspp/issues/5535
2042 	// If do not use DelayResult,Wil cause flickering in Dengeki no Pilot: Tenkuu no Kizuna
2043 	// https://github.com/hrydgard/ppsspp/issues/7549
2044 
2045 	return hleDelayResult(0, "mpeg avc csc", avcCscDelayMs);
2046 }
2047 
sceMpegRingbufferDestruct(u32 ringbufferAddr)2048 static u32 sceMpegRingbufferDestruct(u32 ringbufferAddr)
2049 {
2050 	DEBUG_LOG(ME, "sceMpegRingbufferDestruct(%08x)", ringbufferAddr);
2051 	// Apparently, does nothing.
2052 	return 0;
2053 }
2054 
sceMpegAvcInitYCbCr(u32 mpeg,int mode,int width,int height,u32 ycbcr_addr)2055 static u32 sceMpegAvcInitYCbCr(u32 mpeg, int mode, int width, int height, u32 ycbcr_addr)
2056 {
2057 	if (!Memory::IsValidAddress(ycbcr_addr)) {
2058 		ERROR_LOG(ME, "UNIMPL sceMpegAvcInitYCbCr(%08x, %i, %i, %i, %08x): invalid addresses", mpeg, mode, width, height, ycbcr_addr);
2059 		return -1;
2060 	}
2061 
2062 	MpegContext *ctx = getMpegCtx(mpeg);
2063 	if (!ctx) {
2064 		WARN_LOG(ME, "UNIMPL sceMpegAvcInitYCbCr(%08x, %i, %i, %i, %08x): bad mpeg handle", mpeg, mode, width, height, ycbcr_addr);
2065 		return -1;
2066 	}
2067 
2068 	ERROR_LOG(ME, "UNIMPL sceMpegAvcInitYCbCr(%08x, %i, %i, %i, %08x)", mpeg, mode, width, height, ycbcr_addr);
2069 	return 0;
2070 }
2071 
sceMpegAvcQueryYCbCrSize(u32 mpeg,u32 mode,u32 width,u32 height,u32 resultAddr)2072 static int sceMpegAvcQueryYCbCrSize(u32 mpeg, u32 mode, u32 width, u32 height, u32 resultAddr)
2073 {
2074 	if ((width & 15) != 0 || (height & 15) != 0 || height > 272 || width > 480)	{
2075 		ERROR_LOG(ME, "sceMpegAvcQueryYCbCrSize: bad w/h %i x %i", width, height);
2076 		return ERROR_MPEG_INVALID_VALUE;
2077 	}
2078 
2079 	DEBUG_LOG(ME, "sceMpegAvcQueryYCbCrSize(%08x, %i, %i, %i, %08x)", mpeg, mode, width, height, resultAddr);
2080 
2081 	int size = (width / 2) * (height / 2) * 6 + 128;
2082 	Memory::Write_U32(size, resultAddr);
2083 	return 0;
2084 }
2085 
sceMpegQueryUserdataEsSize(u32 mpeg,u32 esSizeAddr,u32 outSizeAddr)2086 static u32 sceMpegQueryUserdataEsSize(u32 mpeg, u32 esSizeAddr, u32 outSizeAddr)
2087 {
2088 	if (!Memory::IsValidAddress(esSizeAddr) || !Memory::IsValidAddress(outSizeAddr)) {
2089 		ERROR_LOG(ME, "sceMpegQueryUserdataEsSize(%08x, %08x, %08x): invalid addresses", mpeg, esSizeAddr, outSizeAddr);
2090 		return -1;
2091 	}
2092 
2093 	MpegContext *ctx = getMpegCtx(mpeg);
2094 	if (!ctx) {
2095 		WARN_LOG(ME, "sceMpegQueryUserdataEsSize(%08x, %08x, %08x): bad mpeg handle", mpeg, esSizeAddr, outSizeAddr);
2096 		return -1;
2097 	}
2098 
2099 	DEBUG_LOG(ME, "sceMpegQueryUserdataEsSize(%08x, %08x, %08x)", mpeg, esSizeAddr, outSizeAddr);
2100 
2101 	Memory::Write_U32(MPEG_DATA_ES_SIZE, esSizeAddr);
2102 	Memory::Write_U32(MPEG_DATA_ES_OUTPUT_SIZE, outSizeAddr);
2103 	return 0;
2104 }
2105 
sceMpegAvcResourceGetAvcDecTopAddr(u32 mpeg)2106 static u32 sceMpegAvcResourceGetAvcDecTopAddr(u32 mpeg)
2107 {
2108 	ERROR_LOG(ME, "UNIMPL sceMpegAvcResourceGetAvcDecTopAddr(%08x)", mpeg);
2109 	// it's just a random address
2110 	return 0x12345678;
2111 }
2112 
sceMpegAvcResourceFinish(u32 mpeg)2113 static u32 sceMpegAvcResourceFinish(u32 mpeg)
2114 {
2115 	DEBUG_LOG(ME,"UNIMPL sceMpegAvcResourceFinish(%08x)", mpeg);
2116 	return 0;
2117 }
2118 
sceMpegAvcResourceGetAvcEsBuf(u32 mpeg)2119 static u32 sceMpegAvcResourceGetAvcEsBuf(u32 mpeg)
2120 {
2121 	ERROR_LOG_REPORT_ONCE(mpegResourceEsBuf, ME, "UNIMPL sceMpegAvcResourceGetAvcEsBuf(%08x)", mpeg);
2122 	return 0;
2123 }
2124 
sceMpegAvcResourceInit(u32 mpeg)2125 static u32 sceMpegAvcResourceInit(u32 mpeg)
2126 {
2127 	if (mpeg != 1) {
2128 		return ERROR_MPEG_INVALID_VALUE;
2129 	}
2130 
2131 	ERROR_LOG(ME, "UNIMPL sceMpegAvcResourceInit(%08x)", mpeg);
2132 	return 0;
2133 }
2134 
convertABGRToYCbCr(u32 abgr)2135 static u32 convertABGRToYCbCr(u32 abgr) {
2136 	//see http://en.wikipedia.org/wiki/Yuv#Y.27UV444_to_RGB888_conversion for more information.
2137 	u8  r = (abgr >>  0) & 0xFF;
2138 	u8  g = (abgr >>  8) & 0xFF;
2139 	u8  b = (abgr >> 16) & 0xFF;
2140 	int  y = 0.299f * r + 0.587f * g + 0.114f * b + 0;
2141 	int cb = -0.169f * r - 0.331f * g + 0.499f * b + 128.0f;
2142 	int cr = 0.499f * r - 0.418f * g - 0.0813f * b + 128.0f;
2143 
2144 	// check yCbCr value
2145 	if ( y > 0xFF)  y = 0xFF; if ( y < 0)  y = 0;
2146 	if (cb > 0xFF) cb = 0xFF; if (cb < 0) cb = 0;
2147 	if (cr > 0xFF) cr = 0xFF; if (cr < 0) cr = 0;
2148 
2149 	return (y << 16) | (cb << 8) | cr;
2150 }
2151 
__MpegAvcConvertToYuv420(const void * data,u32 bufferOutputAddr,int width,int height)2152 static int __MpegAvcConvertToYuv420(const void *data, u32 bufferOutputAddr, int width, int height) {
2153 	u32 *imageBuffer = (u32*)data;
2154 	int sizeY = width * height;
2155 	int sizeCb = sizeY >> 2;
2156 	u8 *Y = (u8*)Memory::GetPointer(bufferOutputAddr);
2157 	u8 *Cb = Y + sizeY;
2158 	u8 *Cr = Cb + sizeCb;
2159 
2160 	for (int y = 0; y < height; ++y) {
2161 		for (int x = 0; x < width; x += 4) {
2162 			u32 abgr0 = imageBuffer[x + 0];
2163 			u32 abgr1 = imageBuffer[x + 1];
2164 			u32 abgr2 = imageBuffer[x + 2];
2165 			u32 abgr3 = imageBuffer[x + 3];
2166 
2167 			u32 yCbCr0 = convertABGRToYCbCr(abgr0);
2168 			u32 yCbCr1 = convertABGRToYCbCr(abgr1);
2169 			u32 yCbCr2 = convertABGRToYCbCr(abgr2);
2170 			u32 yCbCr3 = convertABGRToYCbCr(abgr3);
2171 
2172 			Y[x + 0] = (yCbCr0 >> 16) & 0xFF;
2173 			Y[x + 1] = (yCbCr1 >> 16) & 0xFF;
2174 			Y[x + 2] = (yCbCr2 >> 16) & 0xFF;
2175 			Y[x + 3] = (yCbCr3 >> 16) & 0xFF;
2176 
2177 			*Cb++ = (yCbCr0 >> 8) & 0xFF;
2178 			*Cr++ = yCbCr0 & 0xFF;
2179 		}
2180 		imageBuffer += width;
2181 		Y += width ;
2182 	}
2183 	return (width << 16) | height;
2184 }
2185 
sceMpegAvcConvertToYuv420(u32 mpeg,u32 bufferOutputAddr,u32 unknown1,int unknown2)2186 static int sceMpegAvcConvertToYuv420(u32 mpeg, u32 bufferOutputAddr, u32 unknown1, int unknown2)
2187 {
2188 	if (!Memory::IsValidAddress(bufferOutputAddr)) {
2189 		ERROR_LOG(ME, "sceMpegAvcConvertToYuv420(%08x, %08x, %08x, %08x): invalid addresses", mpeg, bufferOutputAddr, unknown1, unknown2);
2190 		return -1;
2191 	}
2192 
2193 	MpegContext *ctx = getMpegCtx(mpeg);
2194 	if (!ctx) {
2195 		WARN_LOG(ME, "sceMpegAvcConvertToYuv420(%08x, %08x, %08x, %08x): bad mpeg handle", mpeg, bufferOutputAddr, unknown1, unknown2);
2196 		return -1;
2197 	}
2198 
2199 	if (ctx->mediaengine->m_buffer == 0){
2200 		WARN_LOG(ME, "sceMpegAvcConvertToYuv420(%08x, %08x, %08x, %08x): m_buffer is zero ", mpeg, bufferOutputAddr, unknown1, unknown2);
2201 		return ERROR_MPEG_AVC_INVALID_VALUE;
2202 	}
2203 
2204 	DEBUG_LOG(ME, "sceMpegAvcConvertToYuv420(%08x, %08x, %08x, %08x)", mpeg, bufferOutputAddr, unknown1, unknown2);
2205 	const u8 *data = ctx->mediaengine->getFrameImage();
2206 	int width = ctx->mediaengine->m_desWidth;
2207 	int height = ctx->mediaengine->m_desHeight;
2208 
2209 	if (data) {
2210 		__MpegAvcConvertToYuv420(data, bufferOutputAddr, width, height);
2211 	}
2212 	return 0;
2213 }
2214 
sceMpegGetUserdataAu(u32 mpeg,u32 streamUid,u32 auAddr,u32 resultAddr)2215 static int sceMpegGetUserdataAu(u32 mpeg, u32 streamUid, u32 auAddr, u32 resultAddr)
2216 {
2217 	MpegContext *ctx = getMpegCtx(mpeg);
2218 	if (!ctx) {
2219 		WARN_LOG(ME, "sceMpegGetUserdataAu(%08x, %08x, %08x, %08x): bad mpeg handle", mpeg, streamUid, auAddr, resultAddr);
2220 		return -1;
2221 	}
2222 
2223 	DEBUG_LOG(ME, "sceMpegGetUserdataAu(%08x, %08x, %08x, %08x)", mpeg, streamUid, auAddr, resultAddr);
2224 
2225 	// TODO: Are these at all right?  Seen in Phantasy Star Portable 2.
2226 	Memory::Write_U32(0, resultAddr);
2227 	Memory::Write_U32(0, resultAddr + 4);
2228 
2229 	// We currently can't demux userdata so this seems like the best thing to return in the meantime..
2230 	// Then we probably shouldn't do the above writes? but it works...
2231 	return ERROR_MPEG_NO_DATA;
2232 }
2233 
sceMpegNextAvcRpAu(u32 mpeg,u32 streamUid)2234 static u32 sceMpegNextAvcRpAu(u32 mpeg, u32 streamUid)
2235 {
2236 	MpegContext *ctx = getMpegCtx(mpeg);
2237 	if (!ctx) {
2238 		WARN_LOG(ME, "UNIMPL sceMpegNextAvcRpAu(%08x, %08x): bad mpeg handle", mpeg, streamUid);
2239 		return -1;
2240 	}
2241 
2242 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegNextAvcRpAu(%08x, %08x)", mpeg, streamUid);
2243 
2244 	return 0;
2245 }
2246 
sceMpegGetAvcNalAu(u32 mpeg)2247 static u32 sceMpegGetAvcNalAu(u32 mpeg)
2248 {
2249 	MpegContext *ctx = getMpegCtx(mpeg);
2250 	if (!ctx) {
2251 		WARN_LOG(ME, "UNIMPL sceMpegGetAvcNalAu(%08x): bad mpeg handle", mpeg);
2252 		return -1;
2253 	}
2254 
2255 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegGetAvcNalAu(%08x)", mpeg);
2256 
2257 	return 0;
2258 }
2259 
sceMpegAvcDecodeDetailIndex(u32 mpeg)2260 static u32 sceMpegAvcDecodeDetailIndex(u32 mpeg)
2261 {
2262 	MpegContext *ctx = getMpegCtx(mpeg);
2263 	if (!ctx) {
2264 		WARN_LOG(ME, "UNIMPL sceMpegAvcDecodeDetailIndex(%08x): bad mpeg handle", mpeg);
2265 		return -1;
2266 	}
2267 
2268 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegAvcDecodeDetailIndex(%08x)", mpeg);
2269 
2270 	return 0;
2271 }
2272 
sceMpegAvcDecodeDetail2(u32 mpeg)2273 static u32 sceMpegAvcDecodeDetail2(u32 mpeg)
2274 {
2275 	MpegContext *ctx = getMpegCtx(mpeg);
2276 	if (!ctx) {
2277 		WARN_LOG(ME, "UNIMPL sceMpegAvcDecodeDetail2(%08x): bad mpeg handle", mpeg);
2278 		return -1;
2279 	}
2280 
2281 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegAvcDecodeDetail2(%08x)", mpeg);
2282 
2283 	return 0;
2284 }
2285 
sceMpegGetAvcEsAu(u32 mpeg)2286 static u32 sceMpegGetAvcEsAu(u32 mpeg)
2287 {
2288 	MpegContext *ctx = getMpegCtx(mpeg);
2289 	if (!ctx) {
2290 		WARN_LOG(ME, "UNIMPL sceMpegGetAvcEsAu(%08x): bad mpeg handle", mpeg);
2291 		return -1;
2292 	}
2293 
2294 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegGetAvcEsAu(%08x)", mpeg);
2295 
2296 	return 0;
2297 }
2298 
sceMpegAvcCscInfo(u32 mpeg)2299 static u32 sceMpegAvcCscInfo(u32 mpeg)
2300 {
2301 	MpegContext *ctx = getMpegCtx(mpeg);
2302 	if (!ctx) {
2303 		WARN_LOG(ME, "UNIMPL sceMpegAvcCscInfo(%08x): bad mpeg handle", mpeg);
2304 		return -1;
2305 	}
2306 
2307 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegAvcCscInfo(%08x)", mpeg);
2308 
2309 	return 0;
2310 }
2311 
sceMpegAvcCscMode(u32 mpeg)2312 static u32 sceMpegAvcCscMode(u32 mpeg)
2313 {
2314 	MpegContext *ctx = getMpegCtx(mpeg);
2315 	if (!ctx) {
2316 		WARN_LOG(ME, "UNIMPL sceMpegAvcCscMode(%08x): bad mpeg handle", mpeg);
2317 		return -1;
2318 	}
2319 
2320 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegAvcCscMode(%08x)", mpeg);
2321 
2322 	return 0;
2323 }
2324 
sceMpegFlushAu(u32 mpeg)2325 static u32 sceMpegFlushAu(u32 mpeg)
2326 {
2327 	MpegContext *ctx = getMpegCtx(mpeg);
2328 	if (!ctx) {
2329 		WARN_LOG(ME, "UNIMPL sceMpegFlushAu(%08x): bad mpeg handle", mpeg);
2330 		return -1;
2331 	}
2332 
2333 	ERROR_LOG_REPORT(ME, "UNIMPL sceMpegFlushAu(%08x)", mpeg);
2334 
2335 	return 0;
2336 }
2337 
2338 const HLEFunction sceMpeg[] =
2339 {
2340 	{0XE1CE83A7, &WrapI_UUUU<sceMpegGetAtracAu>,               "sceMpegGetAtracAu",                  'i', "xxxx"   },
2341 	{0XFE246728, &WrapI_UUUU<sceMpegGetAvcAu>,                 "sceMpegGetAvcAu",                    'i', "xxxx"   },
2342 	{0XD8C5F121, &WrapU_UUUUUUU<sceMpegCreate>,                "sceMpegCreate",                      'x', "xxxxxxx" ,HLE_CLEAR_STACK_BYTES, 0xA8},
2343 	{0XF8DCB679, &WrapI_UUU<sceMpegQueryAtracEsSize>,          "sceMpegQueryAtracEsSize",            'i', "xxx"    },
2344 	{0XC132E22F, &WrapU_V<sceMpegQueryMemSize>,                "sceMpegQueryMemSize",                'x', "" ,HLE_CLEAR_STACK_BYTES, 0x18},
2345 	{0X21FF80E4, &WrapI_UUU<sceMpegQueryStreamOffset>,         "sceMpegQueryStreamOffset",           'i', "xxx",HLE_CLEAR_STACK_BYTES, 0x18},
2346 	{0X611E9E11, &WrapU_UU<sceMpegQueryStreamSize>,            "sceMpegQueryStreamSize",             'x', "xx",HLE_CLEAR_STACK_BYTES, 0x8},
2347 	{0X42560F23, &WrapI_UUU<sceMpegRegistStream>,              "sceMpegRegistStream",                'i', "xxx" ,HLE_CLEAR_STACK_BYTES, 0x48},
2348 	{0X591A4AA2, &WrapU_UI<sceMpegUnRegistStream>,             "sceMpegUnRegistStream",              'x', "xi" ,HLE_CLEAR_STACK_BYTES, 0x18 },
2349 	{0X707B7629, &WrapU_U<sceMpegFlushAllStream>,              "sceMpegFlushAllStream",              'x', "x"      },
2350 	{0X500F0429, &WrapU_UI<sceMpegFlushStream>,                "sceMpegFlushStream",                 'x', "xi"     },
2351 	{0XA780CF7E, &WrapI_U<sceMpegMallocAvcEsBuf>,              "sceMpegMallocAvcEsBuf",              'i', "x"      },
2352 	{0XCEB870B1, &WrapI_UI<sceMpegFreeAvcEsBuf>,               "sceMpegFreeAvcEsBuf",                'i', "xi"     },
2353 	{0X167AFD9E, &WrapI_UUU<sceMpegInitAu>,                    "sceMpegInitAu",                      'i', "xxx"    },
2354 	{0X682A619B, &WrapU_V<sceMpegInit>,                        "sceMpegInit",                        'x', "" ,HLE_CLEAR_STACK_BYTES, 0x48},
2355 	{0X606A4649, &WrapI_U<sceMpegDelete>,                      "sceMpegDelete",                      'i', "x",HLE_CLEAR_STACK_BYTES, 0x18},
2356 	{0X874624D6, &WrapU_V<sceMpegFinish>,                      "sceMpegFinish",                      'x', "" ,HLE_CLEAR_STACK_BYTES, 0x18},
2357 	{0X800C44DF, &WrapU_UUUI<sceMpegAtracDecode>,              "sceMpegAtracDecode",                 'x', "xxxi"   },
2358 	{0X0E3C2E9D, &WrapU_UUUUU<sceMpegAvcDecode>,               "sceMpegAvcDecode",                   'x', "xxxxx"  },
2359 	{0X740FCCD1, &WrapU_UUUU<sceMpegAvcDecodeStop>,            "sceMpegAvcDecodeStop",               'x', "xxxx"   },
2360 	{0X4571CC64, &WrapU_U<sceMpegAvcDecodeFlush>,              "sceMpegAvcDecodeFlush",              'x', "x"      },
2361 	{0X0F6C18D7, &WrapI_UU<sceMpegAvcDecodeDetail>,            "sceMpegAvcDecodeDetail",             'i', "xx"     },
2362 	{0XA11C7026, &WrapI_UU<sceMpegAvcDecodeMode>,              "sceMpegAvcDecodeMode",               'i', "xx"     },
2363 	{0X37295ED8, &WrapU_UUUUUU<sceMpegRingbufferConstruct>,    "sceMpegRingbufferConstruct",         'x', "xxxxxx" },
2364 	{0X13407F13, &WrapU_U<sceMpegRingbufferDestruct>,          "sceMpegRingbufferDestruct",          'x', "x"      },
2365 	{0XB240A59E, &WrapU_UII<sceMpegRingbufferPut>,             "sceMpegRingbufferPut",               'x', "xxx"    },
2366 	{0XB5F6DC87, &WrapI_U<sceMpegRingbufferAvailableSize>,     "sceMpegRingbufferAvailableSize",     'i', "x"      },
2367 	{0XD7A29F46, &WrapU_I<sceMpegRingbufferQueryMemSize>,      "sceMpegRingbufferQueryMemSize",      'x', "i"      },
2368 	{0X769BEBB6, &WrapI_U<sceMpegRingbufferQueryPackNum>,      "sceMpegRingbufferQueryPackNum",      'i', "x"      },
2369 	{0X211A057C, &WrapI_UUUUU<sceMpegAvcQueryYCbCrSize>,       "sceMpegAvcQueryYCbCrSize",           'i', "xxxxx"  },
2370 	{0XF0EB1125, &WrapI_UUUU<sceMpegAvcDecodeYCbCr>,           "sceMpegAvcDecodeYCbCr",              'i', "xxxx"   },
2371 	{0XF2930C9C, &WrapU_UUU<sceMpegAvcDecodeStopYCbCr>,        "sceMpegAvcDecodeStopYCbCr",          'x', "xxx"    },
2372 	{0X67179B1B, &WrapU_UIIIU<sceMpegAvcInitYCbCr>,            "sceMpegAvcInitYCbCr",                'x', "xiiix"  },
2373 	{0X0558B075, &WrapU_UUU<sceMpegAvcCopyYCbCr>,              "sceMpegAvcCopyYCbCr",                'x', "xxx"    },
2374 	{0X31BD0272, &WrapU_UUUIU<sceMpegAvcCsc>,                  "sceMpegAvcCsc",                      'x', "xxxix"  },
2375 	{0X9DCFB7EA, &WrapU_UII<sceMpegChangeGetAuMode>,           "sceMpegChangeGetAuMode",             'x', "xii"    },
2376 	{0X8C1E027D, &WrapU_UIUU<sceMpegGetPcmAu>,                 "sceMpegGetPcmAu",                    'x', "xixx"   },
2377 	{0XC02CF6B5, &WrapI_UUU<sceMpegQueryPcmEsSize>,            "sceMpegQueryPcmEsSize",              'i', "xxx"    },
2378 	{0XC45C99CC, &WrapU_UUU<sceMpegQueryUserdataEsSize>,       "sceMpegQueryUserdataEsSize",         'x', "xxx"    },
2379 	{0X234586AE, &WrapU_UUI<sceMpegChangeGetAvcAuMode>,        "sceMpegChangeGetAvcAuMode",          'x', "xxi"    },
2380 	{0X63B9536A, &WrapU_U<sceMpegAvcResourceGetAvcDecTopAddr>, "sceMpegAvcResourceGetAvcDecTopAddr", 'x', "x"      },
2381 	{0X8160A2FE, &WrapU_U<sceMpegAvcResourceFinish>,           "sceMpegAvcResourceFinish",           'x', "x"      },
2382 	{0XAF26BB01, &WrapU_U<sceMpegAvcResourceGetAvcEsBuf>,      "sceMpegAvcResourceGetAvcEsBuf",      'x', "x"      },
2383 	{0XFCBDB5AD, &WrapU_U<sceMpegAvcResourceInit>,             "sceMpegAvcResourceInit",             'x', "x"      },
2384 	{0XF5E7EA31, &WrapI_UUUI<sceMpegAvcConvertToYuv420>,       "sceMpegAvcConvertToYuv420",          'i', "xxxi"   },
2385 	{0X01977054, &WrapI_UUUU<sceMpegGetUserdataAu>,            "sceMpegGetUserdataAu",               'i', "xxxx"   },
2386 	{0X3C37A7A6, &WrapU_UU<sceMpegNextAvcRpAu>,                "sceMpegNextAvcRpAu",                 'x', "xx"     },
2387 	{0X11F95CF1, &WrapU_U<sceMpegGetAvcNalAu>,                 "sceMpegGetAvcNalAu",                 'x', "x"      },
2388 	{0XAB0E9556, &WrapU_U<sceMpegAvcDecodeDetailIndex>,        "sceMpegAvcDecodeDetailIndex",        'x', "x"      },
2389 	{0XCF3547A2, &WrapU_U<sceMpegAvcDecodeDetail2>,            "sceMpegAvcDecodeDetail2",            'x', "x"      },
2390 	{0X921FCCCF, &WrapU_U<sceMpegGetAvcEsAu>,                  "sceMpegGetAvcEsAu",                  'x', "x"      },
2391 	{0XE95838F6, &WrapU_U<sceMpegAvcCscInfo>,                  "sceMpegAvcCscInfo",                  'x', "x"      },
2392 	{0XD1CE4950, &WrapU_U<sceMpegAvcCscMode>,                  "sceMpegAvcCscMode",                  'x', "x"      },
2393 	{0XDBB60658, &WrapU_U<sceMpegFlushAu>,                     "sceMpegFlushAu",                     'x', "x"      },
2394 	{0XD4DD6E75, nullptr,                                      "sceMpeg_D4DD6E75",                   '?', ""       },
2395 	{0X11CAB459, nullptr,                                      "sceMpeg_11CAB459",                   '?', ""       },
2396 	{0XC345DED2, nullptr,                                      "sceMpeg_C345DED2",                   '?', ""       },
2397 	{0XB27711A8, nullptr,                                      "sceMpeg_B27711A8",                   '?', ""       },
2398 	{0X988E9E12, nullptr,                                      "sceMpeg_988E9E12",                   '?', ""       },
2399 };
2400 
Register_sceMpeg()2401 void Register_sceMpeg()
2402 {
2403 	RegisterModule("sceMpeg", ARRAY_SIZE(sceMpeg), sceMpeg);
2404 }
2405 
2406 // This function is currently only been used for PMP videos
2407 // p pointing to a SceMpegLLI structure consists of video frame blocks.
sceMpegbase_BEA18F91(u32 p)2408 static u32 sceMpegbase_BEA18F91(u32 p)
2409 {
2410 	pmp_videoSource = p;
2411 	pmp_nBlocks = 0;
2412 	SceMpegLLI lli;
2413 	while (1){
2414 		Memory::ReadStruct(p, &lli);
2415 		pmp_nBlocks++;
2416 		// lli.Next ==0 for last block
2417 		if (lli.Next == 0){
2418 			break;
2419 		}
2420 		p = p + sizeof(SceMpegLLI);
2421 	}
2422 
2423 	DEBUG_LOG(ME, "sceMpegbase_BEA18F91(%08x), received %d block(s)", pmp_videoSource, pmp_nBlocks);
2424 	return 0;
2425 }
2426 
2427 const HLEFunction sceMpegbase[] =
2428 {
2429 	{0XBEA18F91, &WrapU_U<sceMpegbase_BEA18F91>,               "sceMpegbase_BEA18F91",               'x', "x"      },
2430 	{0X492B5E4B, nullptr,                                      "sceMpegBaseCscInit",                 '?', ""       },
2431 	{0X0530BE4E, nullptr,                                      "sceMpegbase_0530BE4E",               '?', ""       },
2432 	{0X91929A21, nullptr,                                      "sceMpegBaseCscAvc",                  '?', ""       },
2433 	{0X304882E1, nullptr,                                      "sceMpegBaseCscAvcRange",             '?', ""       },
2434 	{0X7AC0321A, nullptr,                                      "sceMpegBaseYCrCbCopy",               '?', ""       }
2435 };
2436 
Register_sceMpegbase()2437 void Register_sceMpegbase()
2438 {
2439 	RegisterModule("sceMpegbase", ARRAY_SIZE(sceMpegbase), sceMpegbase);
2440 };
2441