Demuxer improvement

This commit is contained in:
Nekotekina 2014-03-22 05:08:25 +04:00
parent 5ea58d9451
commit 169fcd098b
5 changed files with 203 additions and 118 deletions

View file

@ -79,12 +79,12 @@ public:
} }
} }
volatile u32 GetCount() volatile u32 GetCount() // may be not safe
{ {
return m_count; return m_count;
} }
volatile bool IsEmpty() volatile bool IsEmpty() // may be not safe
{ {
return !m_count; return !m_count;
} }
@ -96,8 +96,29 @@ public:
} }
T& Peek(u32 pos = 0) T& Peek(u32 pos = 0)
{
while (true)
{
if (m_mutex.GetOwner() == m_mutex.GetDeadValue())
{
break;
}
if (!m_count)
{
if (Emu.IsStopped())
{
break;
}
Sleep(1);
continue;
}
{ {
SMutexLocker lock(m_mutex); SMutexLocker lock(m_mutex);
if (m_count) break;
}
}
return m_data[(m_pos + pos) % SQSize]; return m_data[(m_pos + pos) % SQSize];
} }
}; };

View file

@ -298,37 +298,31 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
{ {
count = entries_count.LoadValue(count); count = entries_count.LoadValue(count);
#ifdef _WIN32
#define DL "\\"
#else
#define DL "/"
#endif
if(!count) if(!count)
{ {
int idx; int idx;
idx = res.Move(new VFSManagerEntry()); 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].mount = "/dev_hdd0/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); 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].mount = "/dev_hdd1/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); 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].mount = "/dev_flash/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); 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].mount = "/dev_usb000/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); 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].mount = "/dev_usb/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
@ -338,7 +332,7 @@ void VFS::SaveLoadDevices(Array<VFSManagerEntry>& res, bool is_load)
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;
idx = res.Move(new VFSManagerEntry()); idx = res.Move(new VFSManagerEntry());
res[idx].path = "$(GameDir)" DL ".." DL; res[idx].path = "$(GameDir)/../";
res[idx].mount = "/dev_bdvd/"; res[idx].mount = "/dev_bdvd/";
res[idx].device = vfsDevice_LocalFile; res[idx].device = vfsDevice_LocalFile;

View file

@ -69,7 +69,7 @@ next:
break; break;
default: default:
ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type); ConLog.Error("adecRead(): sequence error (task %d)", adec.job.Peek().type);
return 0; return -1;
} }
goto next; goto next;
@ -129,7 +129,7 @@ int adecRead(void* opaque, u8* buf, int buf_size)
{ {
ConLog.Error("adecRead: 0x0FD0 header not found"); ConLog.Error("adecRead: 0x0FD0 header not found");
Emu.Pause(); Emu.Pause();
return 0; return -1;
} }
if (!adec.reader.init) if (!adec.reader.init)
@ -433,14 +433,28 @@ u32 adecOpen(AudioDecoder* data)
if (got_frame) if (got_frame)
{ {
frame.pts = adec.last_pts; 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.auAddr = task.au.addr;
frame.auSize = task.au.size; frame.auSize = task.au.size;
frame.userdata = task.au.userdata; frame.userdata = task.au.userdata;
frame.size = frame.data->nb_samples * frame.data->channels * sizeof(float); 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)", if (frame.data->format != AV_SAMPLE_FMT_FLTP)
//frame.pts, frame.data->nb_samples, frame.data->channels, frame.data->sample_rate); {
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); adec.frames.Push(frame);
frame.data = nullptr; // to prevent destruction frame.data = nullptr; // to prevent destruction
@ -690,13 +704,6 @@ int cellAdecGetPcm(u32 handle, u32 outBuffer_addr)
SwrContext* swr = nullptr; SwrContext* swr = nullptr;
u8* out = 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); out = (u8*)malloc(af.size);
/*swr = swr_alloc_set_opts(NULL, AV_CH_LAYOUT_STEREO, AV_SAMPLE_FMT_FLT, 48000, /*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->samplingFreq = frame->sample_rate; // ???
atx->nbytes = frame->nb_samples * frame->channels * sizeof(float); // ??? atx->nbytes = frame->nb_samples * frame->channels * sizeof(float); // ???
atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ??? atx->channelConfigIndex = CELL_ADEC_CH_STEREO; // ???
if (frame->channels != 2) ConLog.Error("cellAdecGetPcmItem: unsupported channel count (%d)", frame->channels);
pcmItem_ptr = pcm.GetAddr(); pcmItem_ptr = pcm.GetAddr();

View file

@ -18,9 +18,9 @@ void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFi
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr) const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
{ {
if (esFilterId->filterIdMajor >= 0xe0) if (esFilterId->filterIdMajor >= 0xe0)
attr->memSize = 0x2000000/2; // 0x45fa49 from ps3 attr->memSize = 0x400000/2; // 0x45fa49 from ps3
else 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, cellDmux.Warning("*** filter(0x%x, 0x%x, 0x%x, 0x%x)", (u32)esFilterId->filterIdMajor, (u32)esFilterId->filterIdMinor,
(u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2); (u32)esFilterId->supplementalInfo1, (u32)esFilterId->supplementalInfo2);
@ -203,6 +203,11 @@ u32 dmuxOpen(Demuxer* data)
stream.get(len); stream.get(len);
PesHeader pes(stream); PesHeader pes(stream);
if (es.freespace() < (u32)(len + 6))
{
pes.new_au = true;
}
if (pes.new_au && es.hasdata()) // new AU detected if (pes.new_au && es.hasdata()) // new AU detected
{ {
if (es.hasunseen()) // hack, probably useless if (es.hasunseen()) // hack, probably useless
@ -311,8 +316,8 @@ u32 dmuxOpen(Demuxer* data)
updates_count++; updates_count++;
stream = task.stream; stream = task.stream;
ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)", //ConLog.Write("*** stream updated(addr=0x%x, size=0x%x, discont=%d, userdata=0x%llx)",
stream.addr, stream.size, stream.discontinuity, stream.userdata); //stream.addr, stream.size, stream.discontinuity, stream.userdata);
dmux.is_running = true; dmux.is_running = true;
dmux.fbSetStream.Push(task.stream.addr); // feedback 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) 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; ElementaryStream* es;
if (!Emu.GetIdManager().GetIDData(esHandle, es)) if (!Emu.GetIdManager().GetIDData(esHandle, es))

View file

@ -483,23 +483,29 @@ class ElementaryStream
{ {
SMutex mutex; SMutex mutex;
u32 first_addr; // AU that will be released SQueue<u32> entries; // AU starting addresses
u32 last_addr; // AU that is being written now u32 put_count; // number of AU written
u32 last_size; // number of bytes written (after 128b header) u32 released; // number of AU released
u32 peek_addr; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex) 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() 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 else
{ {
// probably, always false // probably, always false
return (last_addr + GetMaxAU()) > (memAddr + memSize); return (put + GetMaxAU()) > (memAddr + memSize);
} }
} }
else else
@ -532,26 +538,42 @@ public:
, cbFunc(cbFunc) , cbFunc(cbFunc)
, cbArg(cbArg) , cbArg(cbArg)
, spec(spec) , spec(spec)
, first_addr(0) //, first(0)
, peek_addr(0) //, peek(0)
, last_addr(memAddr) , put(memAddr)
, last_size(0) , size(0)
, put_count(0)
, released(0)
, peek_count(0)
{ {
} }
const u32 GetMaxAU() const 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() bool isfull()
@ -561,60 +583,71 @@ public:
} }
void finish(DemuxerStream& stream) // not multithread-safe void finish(DemuxerStream& stream) // not multithread-safe
{
u32 addr;
{ {
SMutexLocker lock(mutex); 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 (fidMajor != 0xbd) ConLog.Write(">>> es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
if (!first_addr)
{
first_addr = last_addr;
}
if (!peek_addr)
{
peek_addr = last_addr;
}
mem_ptr_t<CellDmuxAuInfo> info(last_addr); addr = put;
/*if (fidMajor == 0xbd) ConLog.Warning("es::finish(): (%s) size = 0x%x, info_addr=0x%x, pts = 0x%x", /*if (!first)
wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), {
(u32)info->auSize, last_addr, (u32)info->ptsLower);*/ first = put;
}
if (!peek)
{
peek = put;
}*/
u32 new_addr = a128(last_addr + 128 + last_size); mem_ptr_t<CellDmuxAuInfo> 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)) if ((new_addr + GetMaxAU()) > (memAddr + memSize))
{ {
last_addr = memAddr; put = memAddr;
} }
else else
{ {
last_addr = new_addr; 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);
}
if (!entries.Push(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); 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()) if (is_full())
{ {
ConLog.Error("ElementaryStream::push(): buffer is full"); ConLog.Error("es::push(): buffer is full");
Emu.Pause(); Emu.Pause();
return; return;
} }
u32 data_addr = last_addr + 128 + last_size; u32 data_addr = put + 128 + size;
last_size += size; size += sz;
if (!Memory.Copy(data_addr, stream.addr, size)) if (!Memory.Copy(data_addr, stream.addr, sz))
{ {
ConLog.Error("ElementaryStream::push(): data copying failed"); ConLog.Error("es::push(): data copying failed");
Emu.Pause(); Emu.Pause();
return; return;
} }
stream.skip(size); stream.skip(sz);
mem_ptr_t<CellDmuxAuInfoEx> info(last_addr); mem_ptr_t<CellDmuxAuInfoEx> info(put);
info->auAddr = last_addr + 128; info->auAddr = put + 128;
info->auSize = last_size; info->auSize = size;
if (pes.new_au) if (pes.new_au)
{ {
info->dts.lower = (u32)pes.dts; info->dts.lower = (u32)pes.dts;
@ -626,12 +659,12 @@ public:
info->userData = stream.userdata; info->userData = stream.userdata;
} }
mem_ptr_t<CellDmuxPamfAuSpecificInfoAvc> tail(last_addr + sizeof(CellDmuxAuInfoEx)); mem_ptr_t<CellDmuxPamfAuSpecificInfoAvc> tail(put + sizeof(CellDmuxAuInfoEx));
tail->reserved1 = 0; tail->reserved1 = 0;
mem_ptr_t<CellDmuxAuInfo> inf(last_addr + 64); mem_ptr_t<CellDmuxAuInfo> inf(put + 64);
inf->auAddr = last_addr + 128; inf->auAddr = put + 128;
inf->auSize = last_size; inf->auSize = size;
if (pes.new_au) if (pes.new_au)
{ {
inf->dtsLower = (u32)pes.dts; inf->dtsLower = (u32)pes.dts;
@ -646,81 +679,107 @@ public:
bool release() bool release()
{ {
SMutexLocker lock(mutex); 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 (fidMajor != 0xbd) ConLog.Write(">>> es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
if (!first_addr) if (released >= put_count)
{ {
ConLog.Error("ElementaryStream::release(): buffer is empty"); ConLog.Error("es::release(): buffer is empty");
return false; return false;
} }
u32 size = a128(Memory.Read32(first_addr + 4) + 128); u32 addr = entries.Peek();
u32 new_addr = first_addr + size;
if (peek_addr == first_addr) mem_ptr_t<CellDmuxAuInfo> 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; return false;
} }
//if (peek_addr <= first_addr) peek_addr = new_addr; /*u32 new_addr = a128(info.GetAddr() + 128 + info->auSize);
if (new_addr == last_addr)
if (new_addr == put)
{ {
first_addr = 0; first = 0;
} }
else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
{ {
first_addr = memAddr; first = memAddr;
} }
else 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; return true;
} }
bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index) bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index)
{ {
SMutexLocker lock(mutex); 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(), //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_addr, first_addr, last_addr, last_size);*/ //wxString(no_ex ? "" : "Ex").wx_str(), peek, first, put, size);
if (!peek_addr) return false; if (peek_count >= put_count) return false;
mem_ptr_t<CellDmuxAuInfo> info(peek_addr); if (peek_count < released)
/*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(), ConLog.Error("es::peek(): sequence error: peek_count < released (peek_count=%d, released=%d)", peek_count, released);
wxString(fidMajor == 0xbd ? "ATRAC3P Audio" : "Video AVC").wx_str(), (u32)info->auSize, peek_addr, (u32)info->ptsLower);*/ Emu.Pause();
return false;
}
out_data = peek_addr; u32 addr = entries.Peek(peek_count - released);
mem_ptr_t<CellDmuxAuInfo> 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); out_spec = out_data + sizeof(CellDmuxAuInfoEx);
if (no_ex) out_data += 64; if (no_ex) out_data += 64;
if (update_index) if (update_index)
{ {
u32 size = a128(Memory.Read32(peek_addr + 4) + 128); /*u32 new_addr = a128(peek + 128 + info->auSize);
u32 new_addr = peek_addr + size; if (new_addr = put)
if (new_addr = last_addr)
{ {
peek_addr = 0; peek = 0;
} }
else if ((new_addr + GetMaxAU()) > (memAddr + memSize)) else if ((new_addr + GetMaxAU()) > (memAddr + memSize))
{ {
peek_addr = memAddr; peek = memAddr;
} }
else 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; return true;
} }
void reset() void reset()
{ {
SMutexLocker lock(mutex); SMutexLocker lock(mutex);
first_addr = 0; //first = 0;
peek_addr = 0; //peek = 0;
last_addr = memAddr; put = memAddr;
last_size = 0; size = 0;
entries.Clear();
put_count = 0;
released = 0;
peek_count = 0;
} }
}; };