diff --git a/rpcs3/Emu/CPU/CPUThread.cpp b/rpcs3/Emu/CPU/CPUThread.cpp index ec21cc80a1..9df0cc6a9e 100644 --- a/rpcs3/Emu/CPU/CPUThread.cpp +++ b/rpcs3/Emu/CPU/CPUThread.cpp @@ -393,7 +393,7 @@ s64 CPUThread::ExecAsCallback(u64 pc, bool wait, u64 a1, u64 a2, u64 a3, u64 a4) { if (Emu.IsStopped()) { - ConLog.Warning("ExecAsCallback(wait=%s) aborted", wxString(wait ? "true" : false).wx_str()); + ConLog.Warning("ExecAsCallback(wait=%s) aborted", wxString(wait ? "true" : "false").wx_str()); return CELL_EABORT; // doesn't mean anything } Sleep(1); diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 94a754d8e4..4147d21aaa 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -20,14 +20,66 @@ int adecRead(void* opaque, u8* buf, int buf_size) { AudioDecoder& adec = *(AudioDecoder*)opaque; - if (adec.reader.size < (u32)buf_size) + int res = 0; + +next: + if (adec.reader.size < (u32)buf_size /*&& !vdec.just_started*/) + { + while (adec.job.IsEmpty()) + { + if (Emu.IsStopped()) + { + ConLog.Warning("vdecRead() aborted"); + return 0; + } + Sleep(1); + } + + switch (adec.job.Peek().type) + { + case adecEndSeq: + { + buf_size = adec.reader.size; + } + break; + case adecDecodeAu: + { + if (!Memory.CopyToReal(buf, adec.reader.addr, adec.reader.size)) + { + ConLog.Error("adecRead: data reading failed (reader.size=0x%x)", adec.reader.size); + Emu.Pause(); + return 0; + } + + buf += adec.reader.size; + buf_size -= adec.reader.size; + res += adec.reader.size; + + adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_AUDONE, adec.task.au.auInfo_addr, adec.cbArg); + + adec.job.Pop(adec.task); + + adec.reader.addr = adec.task.au.addr; + adec.reader.size = adec.task.au.size; + + adec.last_pts = adec.task.au.pts; + } + break; + default: + ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type); + return 0; + } + + goto next; + } + else if (adec.reader.size < (u32)buf_size) { buf_size = adec.reader.size; } if (!buf_size) { - return 0; + return res; } else if (!Memory.CopyToReal(buf, adec.reader.addr, buf_size)) { @@ -39,7 +91,7 @@ int adecRead(void* opaque, u8* buf, int buf_size) { adec.reader.addr += buf_size; adec.reader.size -= buf_size; - return 0 + buf_size; + return res + buf_size; } } @@ -59,7 +111,7 @@ u32 adecOpen(AudioDecoder* data) { ConLog.Write("Audio Decoder enter()"); - AdecTask task; + AdecTask& task = adec.task; while (true) { @@ -119,12 +171,12 @@ u32 adecOpen(AudioDecoder* data) case adecDecodeAu: { - int err; + int err = 0; adec.reader.addr = task.au.addr; adec.reader.size = task.au.size; - u64 last_pts = task.au.pts; + adec.last_pts = task.au.pts; struct AVPacketHolder : AVPacket { @@ -160,7 +212,7 @@ u32 adecOpen(AudioDecoder* data) if (Memory.CopyToReal(buf, task.au.addr, task.au.size)) dump.Write(buf, task.au.size); free(buf); dump.Close(); - } + }*/ if (adec.just_started) // deferred initialization { @@ -171,6 +223,13 @@ u32 adecOpen(AudioDecoder* data) Emu.Pause(); break; } + AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_ATRAC3P); // ??? + if (!codec) + { + ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed"); + Emu.Pause(); + break; + } err = avformat_find_stream_info(adec.fmt, NULL); if (err) { @@ -185,16 +244,8 @@ u32 adecOpen(AudioDecoder* data) break; } adec.ctx = adec.fmt->streams[0]->codec; // TODO: check data - - AVCodec* codec = avcodec_find_decoder(adec.ctx->codec_id); // ??? - if (!codec) - { - ConLog.Error("adecDecodeAu: avcodec_find_decoder() failed"); - Emu.Pause(); - break; - } - AVDictionary* opts; + AVDictionary* opts = nullptr; av_dict_set(&opts, "refcounted_frames", "1", 0); { SMutexGeneralLocker lock(g_mutex_avcodec_open2); @@ -210,9 +261,17 @@ u32 adecOpen(AudioDecoder* data) adec.just_started = false; } - while (av_read_frame(adec.fmt, &au) >= 0)*/ while (true) + bool last_frame = false; + + while (true) { - if (!adec.ctx) // fake + if (Emu.IsStopped()) + { + ConLog.Warning("adecDecodeAu aborted"); + return; + } + + /*if (!adec.ctx) // fake { AdecFrame frame; frame.pts = task.au.pts; @@ -223,13 +282,18 @@ u32 adecOpen(AudioDecoder* data) frame.data = nullptr; adec.frames.Push(frame); - /*Callback cb; - cb.SetAddr(adec.cbFunc); - cb.Handle(adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); - cb.Branch(false);*/ adec.adecCb->ExecAsCallback(adec.cbFunc, false, adec.id, CELL_ADEC_MSG_TYPE_PCMOUT, CELL_OK, adec.cbArg); break; + }*/ + + last_frame = av_read_frame(adec.fmt, &au) < 0; + if (last_frame) + { + //break; + av_free(au.data); + au.data = NULL; + au.size = 0; } struct VdecFrameHolder : AdecFrame @@ -261,10 +325,13 @@ u32 adecOpen(AudioDecoder* data) int decode = avcodec_decode_audio4(adec.ctx, frame.data, &got_frame, &au); - if (decode < 0) + if (decode <= 0) { - ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode); - break; + if (!last_frame && decode < 0) + { + ConLog.Error("adecDecodeAu: AU decoding error(0x%x)", decode); + } + if (!got_frame && adec.reader.size == 0) break; } if (got_frame) diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.h b/rpcs3/Emu/SysCalls/Modules/cellAdec.h index bab8ccd6c9..793a78905a 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.h +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.h @@ -1064,6 +1064,9 @@ public: const u32 cbArg; u32 memBias; + AdecTask task; + u64 last_pts; + CPUThread* adecCb; AudioDecoder(AudioCodecType type, u32 addr, u32 size, u32 func, u32 arg) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 36b8ffef44..bc09f6777b 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -18,7 +18,7 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t attr) { if (esFilterId->filterIdMajor >= 0xe0) - attr->memSize = 0x1000000; // 0x45fa49 from ps3 + attr->memSize = 0x3000000; // 0x45fa49 from ps3 else attr->memSize = 0x200000; // 0x73d9 from ps3 @@ -156,6 +156,16 @@ u32 dmuxOpen(Demuxer* data) //ConLog.Write("*** AT3+ AU sent (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts); + stream.skip(4); + len -= 4; + u32 abc; + stream.peek(abc); + if (abc == 0x5548D00F) + { + stream.skip(8); + len -= 8; + } + es.push(stream, len - pes.size - 3, pes); es.finish(stream); @@ -231,7 +241,7 @@ u32 dmuxOpen(Demuxer* data) continue; } - //hack: reconstruction of MPEG2-PS stream for vdec module (seems it works without it too) + //reconstruction of MPEG2-PS stream for vdec module stream = backup; es.push(stream, len + 6 /*- pes.size - 3*/, pes); } @@ -288,18 +298,32 @@ u32 dmuxOpen(Demuxer* data) { case dmuxSetStream: { + if (stream.discontinuity) + { + for (u32 i = 0; i < 192; i++) + { + if (esALL[i]) + { + esALL[i]->reset(); + } + } + updates_count = 0; + updates_signaled = 0; + } + + if (updates_count != updates_signaled) + { + ConLog.Error("dmuxSetStream: stream update inconsistency (input=%d, signaled=%d)", updates_count, updates_signaled); + return; + } + + updates_count++; stream = task.stream; ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", stream.addr, stream.size, stream.discontinuity, stream.userdata); - if (stream.discontinuity) for (u32 i = 0; i < 192; i++) - { - if (esALL[i]) - { - esALL[i]->reset(); - } - } - updates_count++; + dmux.is_running = true; + dmux.fbSetStream.Push(task.stream.addr); // feedback } break; @@ -592,12 +616,12 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize return CELL_DMUX_ERROR_FATAL; } - while (dmux->is_running) // !!! + if (dmux->is_running) { if (Emu.IsStopped()) { ConLog.Warning("cellDmuxSetStream(%d) aborted (waiting)", demuxerHandle); - break; + return CELL_OK; } Sleep(1); return CELL_DMUX_ERROR_BUSY; @@ -612,14 +636,16 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize dmux->job.Push(task); - while (!dmux->is_running) + u32 addr; + if (!dmux->fbSetStream.Pop(addr)) { - if (Emu.IsStopped()) - { - ConLog.Warning("cellDmuxSetStream(%d) aborted", demuxerHandle); - break; - } - Sleep(1); + ConLog.Warning("cellDmuxSetStream(%d) aborted (fbSetStream.Pop())", demuxerHandle); + return CELL_OK; + } + if (addr != info.addr) + { + ConLog.Error("cellDmuxSetStream(%d): wrong stream queued (right=0x%x, queued=0x%x)", demuxerHandle, info.addr, addr); + Emu.Pause(); } return CELL_OK; } @@ -921,7 +947,7 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_ int cellDmuxReleaseAu(u32 esHandle) { - cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); + cellDmux.Log("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle); return CELL_OK; @@ -931,21 +957,8 @@ int cellDmuxReleaseAu(u32 esHandle) return CELL_DMUX_ERROR_ARG; } - if (!es->canrelease()) - { - cellDmux.Error("cellDmuxReleaseAu: no AU"); - return CELL_DMUX_ERROR_SEQ; - } - - /*DemuxerTask task(dmuxReleaseAu); - task.es.es = esHandle; - task.es.es_ptr = es; - - es->dmux->job.Push(task);*/ - if (!es->release()) { - cellDmux.Error("cellDmuxReleaseAu failed"); return CELL_DMUX_ERROR_SEQ; } return CELL_OK; @@ -953,7 +966,7 @@ int cellDmuxReleaseAu(u32 esHandle) int cellDmuxFlushEs(u32 esHandle) { - cellDmux.Log("cellDmuxFlushEs(esHandle=0x%x)", esHandle); + cellDmux.Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle); ElementaryStream* es; if (!Emu.GetIdManager().GetIDData(esHandle, es)) diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.h b/rpcs3/Emu/SysCalls/Modules/cellDmux.h index cc504fe2f0..ce55c27eb5 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -304,11 +304,6 @@ enum PRIVATE_STREAM_2 = 0x000001bf, }; -enum -{ - MAX_AU = 640 * 1024 + 128, // 640 KB -}; - struct DemuxerStream { u32 addr; @@ -385,7 +380,7 @@ struct PesHeader stream.get(v); if (v != 0xFF) break; // skip padding bytes empty++; - if (empty = size) return; + if (empty == size) return; }; if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only @@ -460,7 +455,8 @@ struct DemuxerTask class Demuxer { public: - SQueue job; + SQueue job; + SQueue fbSetStream; const u32 memAddr; const u32 memSize; const u32 cbFunc; @@ -491,6 +487,26 @@ class ElementaryStream u32 last_addr; // AU that is being written now u32 last_size; // number of bytes written (after 128b header) u32 peek_addr; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex) + + bool is_full() + { + if (first_addr) + { + if (first_addr >= last_addr) + { + return (first_addr - last_addr) <= GetMaxAU(); + } + else + { + // probably, always false + return (last_addr + GetMaxAU()) > (memAddr + memSize); + } + } + else + { + return false; + } + } public: Demuxer* dmux; @@ -523,6 +539,11 @@ public: { } + const u32 GetMaxAU() const + { + return 640 * 1024 + 128; + } + volatile bool hasunseen() { return peek_addr; @@ -536,21 +557,7 @@ public: bool isfull() { SMutexLocker lock(mutex); - if (first_addr) - { - if (first_addr > last_addr) - { - return (first_addr - last_addr) < MAX_AU; - } - else - { - return (first_addr + MAX_AU) > (memAddr + memSize); - } - } - else - { - return false; - } + return is_full(); } void finish(DemuxerStream& stream) // not multithread-safe @@ -565,8 +572,9 @@ public: { peek_addr = last_addr; } + u32 new_addr = a128(last_addr + 128 + last_size); - if ((new_addr + MAX_AU) > (memAddr + memSize)) + if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { last_addr = memAddr; } @@ -581,24 +589,8 @@ public: { SMutexLocker lock(mutex); //ConLog.Write("es::push(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); - bool is_full; - if (first_addr) - { - if (first_addr > last_addr) - { - is_full = (first_addr - last_addr) < MAX_AU; - } - else - { - is_full = (first_addr + MAX_AU) > (memAddr + memSize); - } - } - else - { - is_full = false; - } - if (is_full) + if (is_full()) { ConLog.Error("ElementaryStream::push(): buffer is full"); Emu.Pause(); @@ -646,16 +638,11 @@ public: } } - volatile bool canrelease() - { - return first_addr; - } - bool release() { SMutexLocker lock(mutex); //ConLog.Write("es::release(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); - if (!canrelease()) + if (!first_addr) { ConLog.Error("ElementaryStream::release(): buffer is empty"); return false; @@ -675,7 +662,7 @@ public: { first_addr = 0; } - else if ((new_addr + MAX_AU) > (memAddr + memSize)) + else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { first_addr = memAddr; } @@ -706,7 +693,7 @@ public: { peek_addr = 0; } - else if ((new_addr + MAX_AU) > (memAddr + memSize)) + else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { peek_addr = memAddr; } diff --git a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp index 31fab366d6..5ea762662f 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellVdec.cpp @@ -23,7 +23,8 @@ int vdecRead(void* opaque, u8* buf, int buf_size) int res = 0; - if (vdec.reader.size < (u32)buf_size && !vdec.just_started) +next: + if (vdec.reader.size < (u32)buf_size /*&& !vdec.just_started*/) { while (vdec.job.IsEmpty()) { @@ -74,6 +75,8 @@ int vdecRead(void* opaque, u8* buf, int buf_size) ConLog.Error("vdecRead(): sequence error (task %d)", vdec.job.Peek().type); return 0; } + + goto next; } else if (vdec.reader.size < (u32)buf_size) { @@ -235,14 +238,21 @@ u32 vdecOpen(VideoDecoder* data) if (vdec.just_started) // deferred initialization { - err = avformat_open_input(&vdec.fmt, NULL, NULL, NULL); + err = avformat_open_input(&vdec.fmt, NULL, av_find_input_format("mpeg"), NULL); if (err) { ConLog.Error("vdecDecodeAu: avformat_open_input() failed"); Emu.Pause(); break; } - err = avformat_find_stream_info(vdec.fmt, NULL); + AVCodec* codec = avcodec_find_decoder(AV_CODEC_ID_H264); // ??? + if (!codec) + { + ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed"); + Emu.Pause(); + break; + } + /*err = avformat_find_stream_info(vdec.fmt, NULL); if (err) { ConLog.Error("vdecDecodeAu: avformat_find_stream_info() failed"); @@ -254,17 +264,15 @@ u32 vdecOpen(VideoDecoder* data) ConLog.Error("vdecDecodeAu: no stream found"); Emu.Pause(); break; - } - vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data - - AVCodec* codec = avcodec_find_decoder(vdec.ctx->codec_id); // ??? - if (!codec) + }*/ + if (!avformat_new_stream(vdec.fmt, codec)) { - ConLog.Error("vdecDecodeAu: avcodec_find_decoder() failed"); + ConLog.Error("vdecDecodeAu: avformat_new_stream() failed"); Emu.Pause(); break; } - + vdec.ctx = vdec.fmt->streams[0]->codec; // TODO: check data + AVDictionary* opts = nullptr; av_dict_set(&opts, "refcounted_frames", "1", 0); { @@ -292,6 +300,7 @@ u32 vdecOpen(VideoDecoder* data) ConLog.Warning("vdecDecodeAu aborted"); return; } + last_frame = av_read_frame(vdec.fmt, &au) < 0; if (last_frame) { @@ -335,7 +344,6 @@ u32 vdecOpen(VideoDecoder* data) if (!last_frame && decode < 0) { ConLog.Error("vdecDecodeAu: AU decoding error(0x%x)", decode); - break; } if (!got_picture && vdec.reader.size == 0) break; // video end? } diff --git a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp index 10cd0af5ff..ab987cb8cd 100644 --- a/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp +++ b/rpcs3/Emu/SysCalls/lv2/SC_Lwmutex.cpp @@ -198,6 +198,7 @@ bool SleepQueue::finalize() } } + m_mutex.unlock(); return true; }