From 169fcd098b02b44dd991bb76e8a5c499c084f71a Mon Sep 17 00:00:00 2001 From: Nekotekina Date: Sat, 22 Mar 2014 05:08:25 +0400 Subject: [PATCH] Demuxer improvement --- Utilities/SQueue.h | 27 ++- rpcs3/Emu/FS/VFS.cpp | 18 +- rpcs3/Emu/SysCalls/Modules/cellAdec.cpp | 32 ++-- rpcs3/Emu/SysCalls/Modules/cellDmux.cpp | 17 +- rpcs3/Emu/SysCalls/Modules/cellDmux.h | 227 +++++++++++++++--------- 5 files changed, 203 insertions(+), 118 deletions(-) diff --git a/Utilities/SQueue.h b/Utilities/SQueue.h index 8c0201d257..d98f13d793 100644 --- a/Utilities/SQueue.h +++ b/Utilities/SQueue.h @@ -79,12 +79,12 @@ public: } } - volatile u32 GetCount() + volatile u32 GetCount() // may be not safe { return m_count; } - volatile bool IsEmpty() + volatile bool IsEmpty() // may be not safe { return !m_count; } @@ -97,7 +97,28 @@ public: T& Peek(u32 pos = 0) { - SMutexLocker lock(m_mutex); + while (true) + { + if (m_mutex.GetOwner() == m_mutex.GetDeadValue()) + { + break; + } + + if (!m_count) + { + if (Emu.IsStopped()) + { + break; + } + Sleep(1); + continue; + } + + { + SMutexLocker lock(m_mutex); + if (m_count) break; + } + } return m_data[(m_pos + pos) % SQSize]; } }; diff --git a/rpcs3/Emu/FS/VFS.cpp b/rpcs3/Emu/FS/VFS.cpp index 130ad04fde..fc2c69f7e5 100644 --- a/rpcs3/Emu/FS/VFS.cpp +++ b/rpcs3/Emu/FS/VFS.cpp @@ -298,37 +298,31 @@ void VFS::SaveLoadDevices(Array& res, bool is_load) { count = entries_count.LoadValue(count); -#ifdef _WIN32 -#define DL "\\" -#else -#define DL "/" -#endif - if(!count) { int idx; idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(EmulatorDir)" DL "dev_hdd0" DL; + res[idx].path = "$(EmulatorDir)/dev_hdd0/"; res[idx].mount = "/dev_hdd0/"; res[idx].device = vfsDevice_LocalFile; idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(EmulatorDir)" DL "dev_hdd1" DL; + res[idx].path = "$(EmulatorDir)/dev_hdd1/"; res[idx].mount = "/dev_hdd1/"; res[idx].device = vfsDevice_LocalFile; idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(EmulatorDir)" DL "dev_flash" DL; + res[idx].path = "$(EmulatorDir)/dev_flash/"; res[idx].mount = "/dev_flash/"; res[idx].device = vfsDevice_LocalFile; idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(EmulatorDir)" DL "dev_usb000" DL; + res[idx].path = "$(EmulatorDir)/dev_usb000/"; res[idx].mount = "/dev_usb000/"; res[idx].device = vfsDevice_LocalFile; idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(EmulatorDir)" DL "dev_usb000" DL; + res[idx].path = "$(EmulatorDir)/dev_usb000/"; res[idx].mount = "/dev_usb/"; res[idx].device = vfsDevice_LocalFile; @@ -338,7 +332,7 @@ void VFS::SaveLoadDevices(Array& res, bool is_load) res[idx].device = vfsDevice_LocalFile; idx = res.Move(new VFSManagerEntry()); - res[idx].path = "$(GameDir)" DL ".." DL; + res[idx].path = "$(GameDir)/../"; res[idx].mount = "/dev_bdvd/"; res[idx].device = vfsDevice_LocalFile; diff --git a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp index 2db1e956df..ebd9f2f6bf 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellAdec.cpp @@ -69,7 +69,7 @@ next: break; default: ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type); - return 0; + return -1; } goto next; @@ -129,7 +129,7 @@ int adecRead(void* opaque, u8* buf, int buf_size) { ConLog.Error("adecRead: 0x0FD0 header not found"); Emu.Pause(); - return 0; + return -1; } if (!adec.reader.init) @@ -433,14 +433,28 @@ u32 adecOpen(AudioDecoder* data) if (got_frame) { frame.pts = adec.last_pts; - adec.last_pts += (u64)frame.data->nb_samples * 90000 / 48000; // ??? + adec.last_pts += ((u64)frame.data->nb_samples) * 90000 / 48000; // ??? frame.auAddr = task.au.addr; frame.auSize = task.au.size; frame.userdata = task.au.userdata; frame.size = frame.data->nb_samples * frame.data->channels * sizeof(float); - //ConLog.Write("got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d)", - //frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate); + if (frame.data->format != AV_SAMPLE_FMT_FLTP) + { + ConLog.Error("adecDecodeaAu: unsupported frame format(%d)", frame.data->format); + Emu.Pause(); + break; + } + if (frame.data->channels != 2) + { + ConLog.Error("adecDecodeAu: unsupported channel count (%d)", frame.data->channels); + Emu.Pause(); + break; + } + + //ConLog.Write("got audio frame (pts=0x%llx, nb_samples=%d, ch=%d, sample_rate=%d, nbps=%d)", + //frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate, + //av_get_bytes_per_sample((AVSampleFormat)frame.data->format)); adec.frames.Push(frame); frame.data = nullptr; // to prevent destruction @@ -690,13 +704,6 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr) SwrContext* swr = nullptr; u8* out = nullptr; - if (frame->format != AV_SAMPLE_FMT_FLTP) - { - ConLog.Error("cellAdecGetPcm(%d): unsupported frame format(%d)", handle, frame->format); - Emu.Pause(); - goto end; - } - out = (u8*)malloc(af.size); /*swr = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, 48000, @@ -787,7 +794,6 @@ int cellAdecGetPcmItem(u32 handle, mem32_t pcmItem_ptr) atx->samplingFreq = frame->sample_rate; // ??? atx->nbytes = frame->nb_samples * frame->channels * sizeof(float); // ??? atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ??? - if (frame->channels != 2) ConLog.Error("cellAdecGetPcmItem: unsupported channel count (%d)", frame->channels); pcmItem_ptr = pcm.GetAddr(); diff --git a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp index 93617de1ed..f40a3238f9 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.cpp @@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t attr) { if (esFilterId->filterIdMajor >= 0xe0) - attr->memSize = 0x2000000/2; // 0x45fa49 from ps3 + attr->memSize = 0x400000/2; // 0x45fa49 from ps3 else - attr->memSize = 0x80000; // 0x73d9 from ps3 + attr->memSize = 0x6000; // 0x73d9 from ps3 cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor, (u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2); @@ -203,6 +203,11 @@ u32 dmuxOpen(Demuxer* data) stream.get(len); PesHeader pes(stream); + if (es.freespace() < (u32)(len + 6)) + { + pes.new_au = true; + } + if (pes.new_au && es.hasdata()) // new AU detected { if (es.hasunseen()) // hack, probably useless @@ -311,8 +316,8 @@ u32 dmuxOpen(Demuxer* data) 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); + //ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", + //stream.addr, stream.size, stream.discontinuity, stream.userdata); dmux.is_running = true; dmux.fbSetStream.Push(task.stream.addr); // feedback @@ -939,9 +944,9 @@ int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_ int cellDmuxReleaseAu(u32 esHandle) { - cellDmux.Log("(disabled) cellDmuxReleaseAu(esHandle=0x%x)", esHandle); + cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle); - return CELL_OK; + //return CELL_OK; 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 5d0efac76f..f138d56db6 100644 --- a/rpcs3/Emu/SysCalls/Modules/cellDmux.h +++ b/rpcs3/Emu/SysCalls/Modules/cellDmux.h @@ -483,23 +483,29 @@ class ElementaryStream { SMutex mutex; - u32 first_addr; // AU that will be released - 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) + SQueue entries; // AU starting addresses + u32 put_count; // number of AU written + u32 released; // number of AU released + u32 peek_count; // number of AU obtained by GetAu(Ex) + + u32 put; // AU that is being written now + u32 size; // number of bytes written (after 128b header) + //u32 first; // AU that will be released + //u32 peek; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex) bool is_full() { - if (first_addr) + if (released < put_count) { - if (first_addr >= last_addr) + u32 first = entries.Peek(); + if (first >= put) { - return (first_addr - last_addr) <= GetMaxAU(); + return (first - put) < GetMaxAU(); } else { // probably, always false - return (last_addr + GetMaxAU()) > (memAddr + memSize); + return (put + GetMaxAU()) > (memAddr + memSize); } } else @@ -532,26 +538,42 @@ public: , cbFunc(cbFunc) , cbArg(cbArg) , spec(spec) - , first_addr(0) - , peek_addr(0) - , last_addr(memAddr) - , last_size(0) + //, first(0) + //, peek(0) + , put(memAddr) + , size(0) + , put_count(0) + , released(0) + , peek_count(0) { } const u32 GetMaxAU() const { - return (fidMajor == 0xbd) ? 2048 : 640 * 1024 + 128; + return (fidMajor == 0xbd) ? 4096 : 640 * 1024 + 128; // TODO } - volatile bool hasunseen() + u32 freespace() { - return peek_addr; + if (size > GetMaxAU()) + { + ConLog.Error("es::freespace(): last_size too big (size=0x%x, max_au=0x%x)", size, GetMaxAU()); + Emu.Pause(); + return 0; + } + return GetMaxAU() - size; } - volatile bool hasdata() + bool hasunseen() { - return last_size; + SMutexLocker lock(mutex); + return peek_count < put_count; + } + + bool hasdata() + { + SMutexLocker lock(mutex); + return size; } bool isfull() @@ -562,59 +584,70 @@ public: void finish(DemuxerStream& stream) // not multithread-safe { - SMutexLocker lock(mutex); - //ConLog.Write("es::finish(): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", peek_addr, first_addr, last_addr, last_size); - if (!first_addr) + u32 addr; { - first_addr = last_addr; - } - if (!peek_addr) - { - peek_addr = last_addr; - } + SMutexLocker lock(mutex); + //if (fidMajor != 0xbd) ConLog.Write(">>> es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); - mem_ptr_t info(last_addr); - /*if (fidMajor == 0xbd) ConLog.Warning("es::finish(): (%s) size = 0x%x, info_addr=0x%x, pts = 0x%x", - wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), - (u32)info->auSize, last_addr, (u32)info->ptsLower);*/ + addr = put; + /*if (!first) + { + first = put; + } + if (!peek) + { + peek = put; + }*/ - u32 new_addr = a128(last_addr + 128 + last_size); - if ((new_addr + GetMaxAU()) > (memAddr + memSize)) - { - last_addr = memAddr; + mem_ptr_t info(put); + //if (fidMajor != 0xbd) ConLog.Warning("es::finish(): (%s) size = 0x%x, info_addr=0x%x, pts = 0x%x", + //wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), + //(u32)info->auSize, put, (u32)info->ptsLower); + + u32 new_addr = a128(put + 128 + size); + if ((new_addr + GetMaxAU()) > (memAddr + memSize)) + { + put = memAddr; + } + else + { + put = new_addr; + } + size = 0; + + put_count++; + //if (fidMajor != 0xbd) ConLog.Write("<<< es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); } - else + if (!entries.Push(addr)) { - last_addr = new_addr; + ConLog.Error("es::finish() aborted (no space)"); } - last_size = 0; } - void push(DemuxerStream& stream, u32 size, PesHeader& pes) + void push(DemuxerStream& stream, u32 sz, PesHeader& pes) { 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); if (is_full()) { - ConLog.Error("ElementaryStream::push(): buffer is full"); + ConLog.Error("es::push(): buffer is full"); Emu.Pause(); return; } - u32 data_addr = last_addr + 128 + last_size; - last_size += size; - if (!Memory.Copy(data_addr, stream.addr, size)) + u32 data_addr = put + 128 + size; + size += sz; + if (!Memory.Copy(data_addr, stream.addr, sz)) { - ConLog.Error("ElementaryStream::push(): data copying failed"); + ConLog.Error("es::push(): data copying failed"); Emu.Pause(); return; } - stream.skip(size); + stream.skip(sz); - mem_ptr_t info(last_addr); - info->auAddr = last_addr + 128; - info->auSize = last_size; + mem_ptr_t info(put); + info->auAddr = put + 128; + info->auSize = size; if (pes.new_au) { info->dts.lower = (u32)pes.dts; @@ -626,12 +659,12 @@ public: info->userData = stream.userdata; } - mem_ptr_t tail(last_addr + sizeof(CellDmuxAuInfoEx)); + mem_ptr_t tail(put + sizeof(CellDmuxAuInfoEx)); tail->reserved1 = 0; - mem_ptr_t inf(last_addr + 64); - inf->auAddr = last_addr + 128; - inf->auSize = last_size; + mem_ptr_t inf(put + 64); + inf->auAddr = put + 128; + inf->auSize = size; if (pes.new_au) { inf->dtsLower = (u32)pes.dts; @@ -646,81 +679,107 @@ public: 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 (!first_addr) + //if (fidMajor != 0xbd) ConLog.Write(">>> es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); + if (released >= put_count) { - ConLog.Error("ElementaryStream::release(): buffer is empty"); + ConLog.Error("es::release(): buffer is empty"); return false; } - u32 size = a128(Memory.Read32(first_addr + 4) + 128); - u32 new_addr = first_addr + size; + u32 addr = entries.Peek(); - if (peek_addr == first_addr) + mem_ptr_t info(addr); + //if (fidMajor != 0xbd) ConLog.Warning("es::release(): (%s) size = 0x%x, info = 0x%x, pts = 0x%x", + //wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, first, (u32)info->ptsLower); + + if (released >= peek_count) { - ConLog.Error("ElementaryStream::release(): buffer has not been seen yet"); + ConLog.Error("es::release(): buffer has not been seen yet"); return false; } - //if (peek_addr <= first_addr) peek_addr = new_addr; - if (new_addr == last_addr) + /*u32 new_addr = a128(info.GetAddr() + 128 + info->auSize); + + if (new_addr == put) { - first_addr = 0; + first = 0; } else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { - first_addr = memAddr; + first = memAddr; } else { - first_addr = new_addr; - } + first = new_addr; + }*/ + released++; + if (!entries.Pop(addr)) + { + ConLog.Error("es::release(): entries.Pop() aborted (no entries found)"); + return false; + } + //if (fidMajor != 0xbd) ConLog.Write("<<< es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size); return true; } bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index) { SMutexLocker lock(mutex); - /*ConLog.Write("es::peek(%sAu%s): peek=0x%x, first=0x%x, last=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(), - wxString(no_ex ? "" : "Ex").wx_str(), peek_addr, first_addr, last_addr, last_size);*/ - if (!peek_addr) return false; + //if (fidMajor != 0xbd) ConLog.Write(">>> es::peek(%sAu%s): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(), + //wxString(no_ex ? "" : "Ex").wx_str(), peek, first, put, size); + if (peek_count >= put_count) return false; - mem_ptr_t info(peek_addr); - /*if (fidMajor == 0xbd) ConLog.Warning("es::peek(%sAu(Ex)): (%s) size = 0x%x, info = 0x%x, pts = 0x%x", - wxString(update_index ? "Get" : "Peek").wx_str(), - wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, peek_addr, (u32)info->ptsLower);*/ + if (peek_count < released) + { + ConLog.Error("es::peek(): sequence error: peek_count < released (peek_count=%d, released=%d)", peek_count, released); + Emu.Pause(); + return false; + } - out_data = peek_addr; + u32 addr = entries.Peek(peek_count - released); + mem_ptr_t info(addr); + //if (fidMajor != 0xbd) ConLog.Warning("es::peek(%sAu(Ex)): (%s) size = 0x%x, info = 0x%x, pts = 0x%x", + //wxString(update_index ? "Get" : "Peek").wx_str(), + //wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, peek, (u32)info->ptsLower); + + out_data = addr; out_spec = out_data + sizeof(CellDmuxAuInfoEx); if (no_ex) out_data += 64; if (update_index) { - u32 size = a128(Memory.Read32(peek_addr + 4) + 128); - u32 new_addr = peek_addr + size; - if (new_addr = last_addr) + /*u32 new_addr = a128(peek + 128 + info->auSize); + if (new_addr = put) { - peek_addr = 0; + peek = 0; } else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) { - peek_addr = memAddr; + peek = memAddr; } else { - peek_addr = new_addr; - } + peek = new_addr; + }*/ + peek_count++; } + + //if (fidMajor != 0xbd) ConLog.Write("<<< es::peek(%sAu%s): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", wxString(update_index ? "Get" : "Peek").wx_str(), + //wxString(no_ex ? "" : "Ex").wx_str(), peek, first, put, size); return true; } void reset() { SMutexLocker lock(mutex); - first_addr = 0; - peek_addr = 0; - last_addr = memAddr; - last_size = 0; + //first = 0; + //peek = 0; + put = memAddr; + size = 0; + entries.Clear(); + put_count = 0; + released = 0; + peek_count = 0; } };