mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-07-09 16:31:28 +12:00
Demuxer improved, cellPamf improved
File reading improved
This commit is contained in:
parent
a14276abf1
commit
0bd5dc5363
11 changed files with 928 additions and 199 deletions
|
@ -81,15 +81,13 @@ public:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetCount()
|
volatile u32 GetCount()
|
||||||
{
|
{
|
||||||
SMutexLocker lock(m_mutex);
|
|
||||||
return m_count;
|
return m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool IsEmpty()
|
volatile bool IsEmpty()
|
||||||
{
|
{
|
||||||
SMutexLocker lock(m_mutex);
|
|
||||||
return !m_count;
|
return !m_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -296,7 +296,7 @@ void CPUThread::ExecOnce()
|
||||||
|
|
||||||
void CPUThread::Task()
|
void CPUThread::Task()
|
||||||
{
|
{
|
||||||
ConLog.Write("%s enter", CPUThread::GetFName().wx_str());
|
if (Ini.HLELogging.GetValue()) ConLog.Write("%s enter", CPUThread::GetFName().wx_str());
|
||||||
|
|
||||||
const Array<u64>& bp = Emu.GetBreakPoints();
|
const Array<u64>& bp = Emu.GetBreakPoints();
|
||||||
|
|
||||||
|
@ -358,5 +358,5 @@ void CPUThread::Task()
|
||||||
ConLog.Success("Exit Code: %d", exitcode);
|
ConLog.Success("Exit Code: %d", exitcode);
|
||||||
}
|
}
|
||||||
|
|
||||||
ConLog.Write("%s leave", CPUThread::GetFName().wx_str());
|
if (Ini.HLELogging.GetValue()) ConLog.Write("%s leave", CPUThread::GetFName().wx_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -251,7 +251,7 @@ u32 RawSPUThread::GetIndex() const
|
||||||
|
|
||||||
void RawSPUThread::Task()
|
void RawSPUThread::Task()
|
||||||
{
|
{
|
||||||
ConLog.Write("%s enter", PPCThread::GetFName().wx_str());
|
if (Ini.HLELogging.GetValue()) ConLog.Write("%s enter", PPCThread::GetFName().wx_str());
|
||||||
|
|
||||||
const Array<u64>& bp = Emu.GetBreakPoints();
|
const Array<u64>& bp = Emu.GetBreakPoints();
|
||||||
|
|
||||||
|
@ -334,5 +334,5 @@ void RawSPUThread::Task()
|
||||||
ConLog.Error("Exception: %s", wxString(e).wx_str());
|
ConLog.Error("Exception: %s", wxString(e).wx_str());
|
||||||
}
|
}
|
||||||
|
|
||||||
ConLog.Write("%s leave", PPCThread::GetFName().wx_str());
|
if (Ini.HLELogging.GetValue()) ConLog.Write("%s leave", PPCThread::GetFName().wx_str());
|
||||||
}
|
}
|
||||||
|
|
|
@ -53,10 +53,33 @@ void Callback::Branch(bool wait)
|
||||||
{
|
{
|
||||||
m_has_data = false;
|
m_has_data = false;
|
||||||
|
|
||||||
|
static SMutexGeneral cb_mutex;
|
||||||
|
|
||||||
CPUThread& thr = Emu.GetCallbackThread();
|
CPUThread& thr = Emu.GetCallbackThread();
|
||||||
|
|
||||||
while(Emu.IsRunning() && thr.IsAlive())
|
again:
|
||||||
|
|
||||||
|
while (thr.IsAlive())
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("Callback::Branch() aborted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
SMutexGeneralLocker lock(cb_mutex);
|
||||||
|
|
||||||
|
if (thr.IsAlive())
|
||||||
|
{
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("Callback::Branch() aborted");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
thr.Stop();
|
thr.Stop();
|
||||||
thr.Reset();
|
thr.Reset();
|
||||||
|
@ -74,8 +97,20 @@ void Callback::Branch(bool wait)
|
||||||
|
|
||||||
thr.Exec();
|
thr.Exec();
|
||||||
|
|
||||||
if(wait)
|
if (!wait)
|
||||||
GetCurrentPPCThread()->Wait(thr);
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (thr.IsAlive())
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("Callback::Branch(true) aborted (end)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void Callback::SetName(const std::string& name)
|
void Callback::SetName(const std::string& name)
|
||||||
|
|
|
@ -4,25 +4,334 @@
|
||||||
#include "cellPamf.h"
|
#include "cellPamf.h"
|
||||||
#include "cellDmux.h"
|
#include "cellDmux.h"
|
||||||
|
|
||||||
extern "C"
|
|
||||||
{
|
|
||||||
#include "libavformat\avformat.h"
|
|
||||||
}
|
|
||||||
|
|
||||||
void cellDmux_init();
|
void cellDmux_init();
|
||||||
Module cellDmux(0x0007, cellDmux_init);
|
Module cellDmux(0x0007, cellDmux_init);
|
||||||
|
|
||||||
void dmuxQueryAttr(u32 info_addr /* may be 0 */, mem_ptr_t<CellDmuxAttr> attr)
|
void dmuxQueryAttr(u32 info_addr /* may be 0 */, mem_ptr_t<CellDmuxAttr> attr)
|
||||||
{
|
{
|
||||||
attr->demuxerVerLower = 0; // TODO: check values
|
attr->demuxerVerLower = 0x280000; // TODO: check values
|
||||||
attr->demuxerVerUpper = 0;
|
attr->demuxerVerUpper = 0x260000;
|
||||||
attr->memSize = 1024 * 1024; // 1M
|
attr->memSize = 0x10000; // 0x3e8e6 from ps3
|
||||||
}
|
}
|
||||||
|
|
||||||
void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFilterId> esFilterId,
|
void dmuxQueryEsAttr(u32 info_addr /* may be 0 */, const mem_ptr_t<CellCodecEsFilterId> esFilterId,
|
||||||
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
|
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> attr)
|
||||||
{
|
{
|
||||||
attr->memSize = 1024 * 1024;
|
if (esFilterId->filterIdMajor >= 0xe0)
|
||||||
|
attr->memSize = 0x500000; // 0x45fa49 from ps3
|
||||||
|
else
|
||||||
|
attr->memSize = 0x10000; // 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);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 dmuxOpen(Demuxer* data)
|
||||||
|
{
|
||||||
|
Demuxer& dmux = *data;
|
||||||
|
|
||||||
|
u32 dmux_id = cellDmux.GetNewId(data);
|
||||||
|
|
||||||
|
dmux.id = dmux_id;
|
||||||
|
|
||||||
|
thread t("Demuxer[" + std::to_string(dmux_id) + "] Thread", [&]()
|
||||||
|
{
|
||||||
|
ConLog.Write("Demuxer enter (mem=0x%x, size=0x%x, cb=0x%x, arg=0x%x)", dmux.memAddr, dmux.memSize, dmux.cbFunc, dmux.cbArg);
|
||||||
|
|
||||||
|
DemuxerTask task;
|
||||||
|
DemuxerStream stream;
|
||||||
|
/*
|
||||||
|
ElementaryStream* esAVC[16]; memset(esAVC, 0, sizeof(esAVC));
|
||||||
|
ElementaryStream* esM2V[16]; memset(esM2V, 0, sizeof(esM2V));
|
||||||
|
ElementaryStream* esDATA[16]; memset(esDATA, 0, sizeof(esDATA));
|
||||||
|
ElementaryStream* esATRAX[48]; memset(esATRAX, 0, sizeof(esATRAX));
|
||||||
|
ElementaryStream* esAC3[48]; memset(esAC3, 0, sizeof(esAC3));
|
||||||
|
ElementaryStream* esLPCM[48]; memset(esLPCM, 0, sizeof(esLPCM));
|
||||||
|
*/
|
||||||
|
ElementaryStream* esALL[192]; memset(esALL, 0, sizeof(esALL));
|
||||||
|
ElementaryStream** esAVC = &esALL[0];
|
||||||
|
|
||||||
|
u32 cb_add = 0;
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (dmux.job.IsEmpty() && dmux.is_running)
|
||||||
|
{
|
||||||
|
// default task (demuxing) (if there is no other work)
|
||||||
|
be_t<u32> code;
|
||||||
|
be_t<u16> len;
|
||||||
|
u8 ch;
|
||||||
|
|
||||||
|
if (!stream.peek(code))
|
||||||
|
{
|
||||||
|
// demuxing finished
|
||||||
|
task.type = dmuxResetStream;
|
||||||
|
goto task;
|
||||||
|
}
|
||||||
|
else switch (code.ToLE())
|
||||||
|
{
|
||||||
|
case PACK_START_CODE:
|
||||||
|
{
|
||||||
|
stream.skip(14);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case SYSTEM_HEADER_START_CODE:
|
||||||
|
{
|
||||||
|
stream.skip(18);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PADDING_STREAM:
|
||||||
|
case PRIVATE_STREAM_2:
|
||||||
|
{
|
||||||
|
// unknown
|
||||||
|
stream.skip(4);
|
||||||
|
stream.get(len);
|
||||||
|
stream.skip(len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case PRIVATE_STREAM_1:
|
||||||
|
{
|
||||||
|
// audio AT3+ (and probably LPCM or user data)
|
||||||
|
stream.skip(4);
|
||||||
|
stream.get(len);
|
||||||
|
|
||||||
|
// skipping...
|
||||||
|
stream.skip(len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1e0: case 0x1e1: case 0x1e2: case 0x1e3:
|
||||||
|
case 0x1e4: case 0x1e5: case 0x1e6: case 0x1e7:
|
||||||
|
case 0x1e8: case 0x1e9: case 0x1ea: case 0x1eb:
|
||||||
|
case 0x1ec: case 0x1ed: case 0x1ee: case 0x1ef:
|
||||||
|
{
|
||||||
|
// video AVC
|
||||||
|
ch = code - 0x1e0;
|
||||||
|
if (esAVC[ch])
|
||||||
|
{
|
||||||
|
ElementaryStream& es = *esAVC[ch];
|
||||||
|
if (es.isfull())
|
||||||
|
{
|
||||||
|
Sleep(1);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
stream.skip(4);
|
||||||
|
stream.get(len);
|
||||||
|
PesHeader pes(stream);
|
||||||
|
|
||||||
|
if (!pes.size && !es.hasdata()) // fatal error
|
||||||
|
{
|
||||||
|
ConLog.Error("PES not found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pes.size && es.hasdata()) // new AU detected
|
||||||
|
{
|
||||||
|
es.finish(stream);
|
||||||
|
// callback
|
||||||
|
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||||
|
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||||
|
esMsg->supplementalInfo = stream.userdata;
|
||||||
|
Callback cb;
|
||||||
|
cb.SetAddr(es.cbFunc);
|
||||||
|
cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg);
|
||||||
|
cb.Branch(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (pes.size)
|
||||||
|
{
|
||||||
|
//ConLog.Write("*** AVC AU detected (pts=0x%x, dts=0x%x)", pes.pts, pes.dts);
|
||||||
|
}
|
||||||
|
|
||||||
|
es.push(stream, len - pes.size - 3, pes);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
stream.skip(4);
|
||||||
|
stream.get(len);
|
||||||
|
stream.skip(len);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x1c0: case 0x1c1: case 0x1c2: case 0x1c3:
|
||||||
|
case 0x1c4: case 0x1c5: case 0x1c6: case 0x1c7:
|
||||||
|
case 0x1c8: case 0x1c9: case 0x1ca: case 0x1cb:
|
||||||
|
case 0x1cc: case 0x1cd: case 0x1ce: case 0x1cf:
|
||||||
|
case 0x1d0: case 0x1d1: case 0x1d2: case 0x1d3:
|
||||||
|
case 0x1d4: case 0x1d5: case 0x1d6: case 0x1d7:
|
||||||
|
case 0x1d8: case 0x1d9: case 0x1da: case 0x1db:
|
||||||
|
case 0x1dc: case 0x1dd: case 0x1de: case 0x1df:
|
||||||
|
{
|
||||||
|
// unknown
|
||||||
|
stream.skip(4);
|
||||||
|
stream.get(len);
|
||||||
|
stream.skip(len);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case USER_DATA_START_CODE:
|
||||||
|
{
|
||||||
|
ConLog.Error("USER_DATA_START_CODE found");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
// search
|
||||||
|
stream.skip(1);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
}
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// wait for task with yielding (if no default work)
|
||||||
|
if (!dmux.job.Pop(task))
|
||||||
|
{
|
||||||
|
break; // Emu is stopped
|
||||||
|
}
|
||||||
|
task:
|
||||||
|
switch (task.type)
|
||||||
|
{
|
||||||
|
case dmuxSetStream:
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
dmux.is_running = true;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dmuxResetStream:
|
||||||
|
case dmuxResetStreamAndWaitDone:
|
||||||
|
{
|
||||||
|
// TODO: send CELL_DMUX_MSG_TYPE_DEMUX_DONE callback and provide waiting condition
|
||||||
|
mem_ptr_t<CellDmuxMsg> dmuxMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||||
|
dmuxMsg->msgType = CELL_DMUX_MSG_TYPE_DEMUX_DONE;
|
||||||
|
dmuxMsg->supplementalInfo = stream.userdata;
|
||||||
|
Callback cb;
|
||||||
|
cb.SetAddr(dmux.cbFunc);
|
||||||
|
cb.Handle(dmux.id, dmuxMsg.GetAddr(), dmux.cbArg);
|
||||||
|
cb.Branch(task.type == dmuxResetStreamAndWaitDone);
|
||||||
|
dmux.is_running = false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dmuxClose:
|
||||||
|
{
|
||||||
|
dmux.is_finished = true;
|
||||||
|
ConLog.Write("Demuxer exit");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
case dmuxEnableEs:
|
||||||
|
{
|
||||||
|
ElementaryStream& es = *task.es.es_ptr;
|
||||||
|
if (es.fidMajor >= 0xe0 &&
|
||||||
|
es.fidMajor <= 0xef &&
|
||||||
|
es.fidMinor == 0 &&
|
||||||
|
es.sup1 == 1 &&
|
||||||
|
es.sup2 == 0)
|
||||||
|
{
|
||||||
|
esAVC[es.fidMajor - 0xe0] = task.es.es_ptr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConLog.Warning("dmuxEnableEs: (TODO) unsupported filter (0x%x, 0x%x, 0x%x, 0x%x)", es.fidMajor, es.fidMinor, es.sup1, es.sup2);
|
||||||
|
}
|
||||||
|
es.dmux = &dmux;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dmuxDisableEs:
|
||||||
|
{
|
||||||
|
ElementaryStream& es = *task.es.es_ptr;
|
||||||
|
if (es.dmux != &dmux)
|
||||||
|
{
|
||||||
|
ConLog.Warning("dmuxDisableEs: invalid elementary stream");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
for (u32 i = 0; i < 192; i++)
|
||||||
|
{
|
||||||
|
if (esALL[i] == &es)
|
||||||
|
{
|
||||||
|
esALL[i] = nullptr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
es.dmux = nullptr;
|
||||||
|
Emu.GetIdManager().RemoveID(task.es.es);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dmuxReleaseAu:
|
||||||
|
{
|
||||||
|
task.es.es_ptr->release();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dmuxFlushEs:
|
||||||
|
{
|
||||||
|
ElementaryStream& es = *task.es.es_ptr;
|
||||||
|
|
||||||
|
if (es.hasdata())
|
||||||
|
{
|
||||||
|
es.finish(stream);
|
||||||
|
// callback
|
||||||
|
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||||
|
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||||
|
esMsg->supplementalInfo = stream.userdata;
|
||||||
|
Callback cb;
|
||||||
|
cb.SetAddr(es.cbFunc);
|
||||||
|
cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg);
|
||||||
|
cb.Branch(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
// callback
|
||||||
|
mem_ptr_t<CellDmuxEsMsg> esMsg(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||||
|
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_FLUSH_DONE;
|
||||||
|
esMsg->supplementalInfo = stream.userdata;
|
||||||
|
Callback cb;
|
||||||
|
cb.SetAddr(es.cbFunc);
|
||||||
|
cb.Handle(dmux.id, es.id, esMsg.GetAddr(), es.cbArg);
|
||||||
|
cb.Branch(false);
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case dmuxResetEs:
|
||||||
|
{
|
||||||
|
task.es.es_ptr->reset();
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
ConLog.Error("Demuxer error: unknown task(%d)", task.type);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ConLog.Warning("Demuxer aborted");
|
||||||
|
});
|
||||||
|
|
||||||
|
t.detach();
|
||||||
|
|
||||||
|
return dmux_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellDmuxQueryAttr(const mem_ptr_t<CellDmuxType> demuxerType, mem_ptr_t<CellDmuxAttr> demuxerAttr)
|
int cellDmuxQueryAttr(const mem_ptr_t<CellDmuxType> demuxerType, mem_ptr_t<CellDmuxAttr> demuxerAttr)
|
||||||
|
@ -61,53 +370,6 @@ int cellDmuxQueryAttr2(const mem_ptr_t<CellDmuxType2> demuxerType2, mem_ptr_t<Ce
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 dmuxOpen(Demuxer* data)
|
|
||||||
{
|
|
||||||
Demuxer& dmux = *data;
|
|
||||||
|
|
||||||
u32 id = cellDmux.GetNewId(data);
|
|
||||||
|
|
||||||
thread t("Demuxer [" + std::to_string(id) + "] Thread", [&]()
|
|
||||||
{
|
|
||||||
ConLog.Write("Demuxer enter (mem=0x%x, size=0x%x, cb=0x%x, arg=0x%x)", dmux.memAddr, dmux.memSize, dmux.cbFunc, dmux.cbArg);
|
|
||||||
|
|
||||||
DemuxerTask task;
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
if (!dmux.job.Pop(task))
|
|
||||||
{
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch (task.type)
|
|
||||||
{
|
|
||||||
case dmuxSetStream:
|
|
||||||
case dmuxResetStream:
|
|
||||||
case dmuxEnableEs:
|
|
||||||
case dmuxDisableEs:
|
|
||||||
case dmuxResetEs:
|
|
||||||
case dmuxGetAu:
|
|
||||||
case dmuxPeekAu:
|
|
||||||
case dmuxReleaseAu:
|
|
||||||
case dmuxFlushEs:
|
|
||||||
case dmuxClose:
|
|
||||||
dmux.is_finished = true;
|
|
||||||
ConLog.Write("Demuxer exit");
|
|
||||||
return;
|
|
||||||
default:
|
|
||||||
ConLog.Error("Demuxer error: unknown task(%d)", task.type);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ConLog.Warning("Demuxer aborted");
|
|
||||||
});
|
|
||||||
|
|
||||||
t.detach();
|
|
||||||
|
|
||||||
return id;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cellDmuxOpen(const mem_ptr_t<CellDmuxType> demuxerType, const mem_ptr_t<CellDmuxResource> demuxerResource,
|
int cellDmuxOpen(const mem_ptr_t<CellDmuxType> demuxerType, const mem_ptr_t<CellDmuxResource> demuxerResource,
|
||||||
const mem_ptr_t<CellDmuxCb> demuxerCb, mem32_t demuxerHandle)
|
const mem_ptr_t<CellDmuxCb> demuxerCb, mem32_t demuxerHandle)
|
||||||
{
|
{
|
||||||
|
@ -131,7 +393,7 @@ int cellDmuxOpen(const mem_ptr_t<CellDmuxType> demuxerType, const mem_ptr_t<Cell
|
||||||
|
|
||||||
// TODO: check demuxerResource and demuxerCb arguments
|
// TODO: check demuxerResource and demuxerCb arguments
|
||||||
|
|
||||||
demuxerHandle = dmuxOpen(new Demuxer(demuxerResource->memAddr, demuxerResource->memSize, (CellDmuxCbMsg&)demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr));
|
demuxerHandle = dmuxOpen(new Demuxer(demuxerResource->memAddr, demuxerResource->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr));
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -159,7 +421,7 @@ int cellDmuxOpenEx(const mem_ptr_t<CellDmuxType> demuxerType, const mem_ptr_t<Ce
|
||||||
|
|
||||||
// TODO: check demuxerResourceEx and demuxerCb arguments
|
// TODO: check demuxerResourceEx and demuxerCb arguments
|
||||||
|
|
||||||
demuxerHandle = dmuxOpen(new Demuxer(demuxerResourceEx->memAddr, demuxerResourceEx->memSize, (CellDmuxCbMsg&)demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr));
|
demuxerHandle = dmuxOpen(new Demuxer(demuxerResourceEx->memAddr, demuxerResourceEx->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr));
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -187,7 +449,7 @@ int cellDmuxOpen2(const mem_ptr_t<CellDmuxType2> demuxerType2, const mem_ptr_t<C
|
||||||
|
|
||||||
// TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments
|
// TODO: check demuxerType2, demuxerResource2 and demuxerCb arguments
|
||||||
|
|
||||||
demuxerHandle = dmuxOpen(new Demuxer(demuxerResource2->memAddr, demuxerResource2->memSize, (CellDmuxCbMsg&)demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr));
|
demuxerHandle = dmuxOpen(new Demuxer(demuxerResource2->memAddr, demuxerResource2->memSize, demuxerCb->cbMsgFunc, demuxerCb->cbArg_addr));
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -221,7 +483,7 @@ int cellDmuxClose(u32 demuxerHandle)
|
||||||
|
|
||||||
int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize, bool discontinuity, u64 userData)
|
int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize, bool discontinuity, u64 userData)
|
||||||
{
|
{
|
||||||
cellDmux.Warning("cellDmuxSetStream(demuxerHandle=%d, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx",
|
cellDmux.Log("cellDmuxSetStream(demuxerHandle=%d, streamAddress=0x%x, streamSize=%d, discontinuity=%d, userData=0x%llx",
|
||||||
demuxerHandle, streamAddress, streamSize, discontinuity, userData);
|
demuxerHandle, streamAddress, streamSize, discontinuity, userData);
|
||||||
|
|
||||||
Demuxer* dmux;
|
Demuxer* dmux;
|
||||||
|
@ -235,8 +497,9 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
||||||
return CELL_DMUX_ERROR_FATAL;
|
return CELL_DMUX_ERROR_FATAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!dmux->job.IsEmpty())
|
if (dmux->is_running)
|
||||||
{
|
{
|
||||||
|
Sleep(1); // performance hack
|
||||||
return CELL_DMUX_ERROR_BUSY;
|
return CELL_DMUX_ERROR_BUSY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,12 +511,22 @@ int cellDmuxSetStream(u32 demuxerHandle, const u32 streamAddress, u32 streamSize
|
||||||
info.userdata = userData;
|
info.userdata = userData;
|
||||||
|
|
||||||
dmux->job.Push(task);
|
dmux->job.Push(task);
|
||||||
|
|
||||||
|
while (!dmux->is_running)
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("cellDmuxSetStream(%d) aborted", demuxerHandle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellDmuxResetStream(u32 demuxerHandle)
|
int cellDmuxResetStream(u32 demuxerHandle)
|
||||||
{
|
{
|
||||||
cellDmux.Warning("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle);
|
cellDmux.Log("cellDmuxResetStream(demuxerHandle=%d)", demuxerHandle);
|
||||||
|
|
||||||
Demuxer* dmux;
|
Demuxer* dmux;
|
||||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||||
|
@ -268,7 +541,7 @@ int cellDmuxResetStream(u32 demuxerHandle)
|
||||||
|
|
||||||
int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
|
int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
|
||||||
{
|
{
|
||||||
cellDmux.Error("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle);
|
cellDmux.Log("cellDmuxResetStreamAndWaitDone(demuxerHandle=%d)", demuxerHandle);
|
||||||
|
|
||||||
Demuxer* dmux;
|
Demuxer* dmux;
|
||||||
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
if (!Emu.GetIdManager().GetIDData(demuxerHandle, dmux))
|
||||||
|
@ -276,9 +549,17 @@ int cellDmuxResetStreamAndWaitDone(u32 demuxerHandle)
|
||||||
return CELL_DMUX_ERROR_ARG;
|
return CELL_DMUX_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
dmux->job.Push(DemuxerTask(dmuxResetStream));
|
dmux->job.Push(DemuxerTask(dmuxResetStreamAndWaitDone));
|
||||||
|
|
||||||
// TODO: wait done
|
while (dmux->is_running)
|
||||||
|
{
|
||||||
|
if (Emu.IsStopped())
|
||||||
|
{
|
||||||
|
ConLog.Warning("cellDmuxResetStreamAndWaitDone(%d) aborted", demuxerHandle);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
Sleep(1);
|
||||||
|
}
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
@ -314,7 +595,7 @@ int cellDmuxQueryEsAttr(const mem_ptr_t<CellDmuxType> demuxerType, const mem_ptr
|
||||||
int cellDmuxQueryEsAttr2(const mem_ptr_t<CellDmuxType2> demuxerType2, const mem_ptr_t<CellCodecEsFilterId> esFilterId,
|
int cellDmuxQueryEsAttr2(const mem_ptr_t<CellDmuxType2> demuxerType2, const mem_ptr_t<CellCodecEsFilterId> esFilterId,
|
||||||
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> esAttr)
|
const u32 esSpecificInfo_addr, mem_ptr_t<CellDmuxEsAttr> esAttr)
|
||||||
{
|
{
|
||||||
cellDmux.Error("cellDmuxQueryEsAttr2(demuxerType2_addr=0x%x, esFilterId_addr=0x%x, esSpecificInfo_addr=0x%x, esAttr_addr=0x%x)",
|
cellDmux.Warning("cellDmuxQueryEsAttr2(demuxerType2_addr=0x%x, esFilterId_addr=0x%x, esSpecificInfo_addr=0x%x, esAttr_addr=0x%x)",
|
||||||
demuxerType2.GetAddr(), esFilterId.GetAddr(), esSpecificInfo_addr, esAttr.GetAddr());
|
demuxerType2.GetAddr(), esFilterId.GetAddr(), esSpecificInfo_addr, esAttr.GetAddr());
|
||||||
|
|
||||||
if (!demuxerType2.IsGood() || !esFilterId.IsGood() || !esAttr.IsGood())
|
if (!demuxerType2.IsGood() || !esFilterId.IsGood() || !esAttr.IsGood())
|
||||||
|
@ -373,13 +654,17 @@ int cellDmuxEnableEs(u32 demuxerHandle, const mem_ptr_t<CellCodecEsFilterId> esF
|
||||||
|
|
||||||
ElementaryStream* es = new ElementaryStream(dmux, esResourceInfo->memAddr, esResourceInfo->memSize,
|
ElementaryStream* es = new ElementaryStream(dmux, esResourceInfo->memAddr, esResourceInfo->memSize,
|
||||||
esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2,
|
esFilterId->filterIdMajor, esFilterId->filterIdMinor, esFilterId->supplementalInfo1, esFilterId->supplementalInfo2,
|
||||||
(CellDmuxCbEsMsg&)esCb->cbEsMsgFunc, esCb->cbArg_addr, esSpecificInfo_addr);
|
esCb->cbEsMsgFunc, esCb->cbArg_addr, esSpecificInfo_addr);
|
||||||
|
|
||||||
u32 id = cellDmux.GetNewId(es);
|
u32 id = cellDmux.GetNewId(es);
|
||||||
|
es->id = id;
|
||||||
|
|
||||||
|
cellDmux.Warning("*** New ES(dmux=%d, addr=0x%x, size=0x%x, filter(0x%x, 0x%x, 0x%x, 0x%x), cb=0x%x(arg=0x%x), spec=0x%x): id = %d",
|
||||||
|
demuxerHandle, es->memAddr, es->memSize, es->fidMajor, es->fidMinor, es->sup1, es->sup2, (u32)esCb->cbEsMsgFunc, es->cbArg, es->spec, id);
|
||||||
|
|
||||||
DemuxerTask task(dmuxEnableEs);
|
DemuxerTask task(dmuxEnableEs);
|
||||||
task.au.es = id;
|
task.es.es = id;
|
||||||
task.au.es_ptr = es;
|
task.es.es_ptr = es;
|
||||||
|
|
||||||
dmux->job.Push(task);
|
dmux->job.Push(task);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -396,8 +681,8 @@ int cellDmuxDisableEs(u32 esHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
DemuxerTask task(dmuxDisableEs);
|
DemuxerTask task(dmuxDisableEs);
|
||||||
task.esHandle = esHandle;
|
task.es.es = esHandle;
|
||||||
task.au.es_ptr = es;
|
task.es.es_ptr = es;
|
||||||
|
|
||||||
es->dmux->job.Push(task);
|
es->dmux->job.Push(task);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -405,7 +690,7 @@ int cellDmuxDisableEs(u32 esHandle)
|
||||||
|
|
||||||
int cellDmuxResetEs(u32 esHandle)
|
int cellDmuxResetEs(u32 esHandle)
|
||||||
{
|
{
|
||||||
cellDmux.Warning("cellDmuxResetEs(esHandle=0x%x)", esHandle);
|
cellDmux.Log("cellDmuxResetEs(esHandle=0x%x)", esHandle);
|
||||||
|
|
||||||
ElementaryStream* es;
|
ElementaryStream* es;
|
||||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
@ -414,44 +699,17 @@ int cellDmuxResetEs(u32 esHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
DemuxerTask task(dmuxResetEs);
|
DemuxerTask task(dmuxResetEs);
|
||||||
task.esHandle = esHandle;
|
task.es.es = esHandle;
|
||||||
task.au.es_ptr = es;
|
task.es.es_ptr = es;
|
||||||
|
|
||||||
es->dmux->job.Push(task);
|
es->dmux->job.Push(task);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
int cellDmuxGetAu(u32 esHandle, const u32 auInfo_ptr_addr, u32 auSpecificInfo_ptr_addr)
|
int cellDmuxGetAu(u32 esHandle, mem32_t auInfo_ptr, mem32_t auSpecificInfo_ptr)
|
||||||
{
|
{
|
||||||
cellDmux.Error("cellDmuxGetAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
cellDmux.Log("cellDmuxGetAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||||
esHandle, auInfo_ptr_addr, auSpecificInfo_ptr_addr);
|
esHandle, auInfo_ptr.GetAddr(), auSpecificInfo_ptr.GetAddr());
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cellDmuxPeekAu(u32 esHandle, const u32 auInfo_ptr_addr, u32 auSpecificInfo_ptr_addr)
|
|
||||||
{
|
|
||||||
cellDmux.Error("cellDmuxPeekAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
|
||||||
esHandle, auInfo_ptr_addr, auSpecificInfo_ptr_addr);
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cellDmuxGetAuEx(u32 esHandle, const u32 auInfoEx_ptr_addr, u32 auSpecificInfo_ptr_addr)
|
|
||||||
{
|
|
||||||
cellDmux.Error("cellDmuxGetAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
|
||||||
esHandle, auInfoEx_ptr_addr, auSpecificInfo_ptr_addr);
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cellDmuxPeekAuEx(u32 esHandle, const u32 auInfoEx_ptr_addr, u32 auSpecificInfo_ptr_addr)
|
|
||||||
{
|
|
||||||
cellDmux.Error("cellDmuxPeekAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
|
||||||
esHandle, auInfoEx_ptr_addr, auSpecificInfo_ptr_addr);
|
|
||||||
return CELL_OK;
|
|
||||||
}
|
|
||||||
|
|
||||||
int cellDmuxReleaseAu(u32 esHandle)
|
|
||||||
{
|
|
||||||
cellDmux.Warning("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
|
||||||
|
|
||||||
ElementaryStream* es;
|
ElementaryStream* es;
|
||||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
@ -459,9 +717,125 @@ int cellDmuxReleaseAu(u32 esHandle)
|
||||||
return CELL_DMUX_ERROR_ARG;
|
return CELL_DMUX_ERROR_ARG;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (!auInfo_ptr.IsGood() || !auSpecificInfo_ptr.IsGood())
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 info;
|
||||||
|
u32 spec;
|
||||||
|
if (!es->peek(info, true, spec, true))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
auInfo_ptr = info;
|
||||||
|
auSpecificInfo_ptr = spec;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cellDmuxPeekAu(u32 esHandle, mem32_t auInfo_ptr, mem32_t auSpecificInfo_ptr)
|
||||||
|
{
|
||||||
|
cellDmux.Log("cellDmuxPeekAu(esHandle=0x%x, auInfo_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||||
|
esHandle, auInfo_ptr.GetAddr(), auSpecificInfo_ptr.GetAddr());
|
||||||
|
|
||||||
|
ElementaryStream* es;
|
||||||
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!auInfo_ptr.IsGood() || !auSpecificInfo_ptr.IsGood())
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 info;
|
||||||
|
u32 spec;
|
||||||
|
if (!es->peek(info, true, spec, false))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
auInfo_ptr = info;
|
||||||
|
auSpecificInfo_ptr = spec;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cellDmuxGetAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_ptr)
|
||||||
|
{
|
||||||
|
cellDmux.Log("cellDmuxGetAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||||
|
esHandle, auInfoEx_ptr.GetAddr(), auSpecificInfo_ptr.GetAddr());
|
||||||
|
|
||||||
|
ElementaryStream* es;
|
||||||
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!auInfoEx_ptr.IsGood() || !auSpecificInfo_ptr.IsGood())
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 info;
|
||||||
|
u32 spec;
|
||||||
|
if (!es->peek(info, false, spec, true))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
auInfoEx_ptr = info;
|
||||||
|
auSpecificInfo_ptr = spec;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cellDmuxPeekAuEx(u32 esHandle, mem32_t auInfoEx_ptr, mem32_t auSpecificInfo_ptr)
|
||||||
|
{
|
||||||
|
cellDmux.Log("cellDmuxPeekAuEx(esHandle=0x%x, auInfoEx_ptr_addr=0x%x, auSpecificInfo_ptr_addr=0x%x)",
|
||||||
|
esHandle, auInfoEx_ptr.GetAddr(), auSpecificInfo_ptr.GetAddr());
|
||||||
|
|
||||||
|
ElementaryStream* es;
|
||||||
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!auInfoEx_ptr.IsGood() || !auSpecificInfo_ptr.IsGood())
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_FATAL;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 info;
|
||||||
|
u32 spec;
|
||||||
|
if (!es->peek(info, false, spec, false))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_EMPTY;
|
||||||
|
}
|
||||||
|
|
||||||
|
auInfoEx_ptr = info;
|
||||||
|
auSpecificInfo_ptr = spec;
|
||||||
|
return CELL_OK;
|
||||||
|
}
|
||||||
|
|
||||||
|
int cellDmuxReleaseAu(u32 esHandle)
|
||||||
|
{
|
||||||
|
cellDmux.Log("cellDmuxReleaseAu(esHandle=0x%x)", esHandle);
|
||||||
|
|
||||||
|
ElementaryStream* es;
|
||||||
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_ARG;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!es->canrelease())
|
||||||
|
{
|
||||||
|
return CELL_DMUX_ERROR_SEQ;
|
||||||
|
}
|
||||||
|
|
||||||
DemuxerTask task(dmuxReleaseAu);
|
DemuxerTask task(dmuxReleaseAu);
|
||||||
task.esHandle = esHandle;
|
task.es.es = esHandle;
|
||||||
task.au.es_ptr = es;
|
task.es.es_ptr = es;
|
||||||
|
|
||||||
es->dmux->job.Push(task);
|
es->dmux->job.Push(task);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
@ -469,7 +843,7 @@ int cellDmuxReleaseAu(u32 esHandle)
|
||||||
|
|
||||||
int cellDmuxFlushEs(u32 esHandle)
|
int cellDmuxFlushEs(u32 esHandle)
|
||||||
{
|
{
|
||||||
cellDmux.Warning("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
|
cellDmux.Log("cellDmuxFlushEs(esHandle=0x%x)", esHandle);
|
||||||
|
|
||||||
ElementaryStream* es;
|
ElementaryStream* es;
|
||||||
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
if (!Emu.GetIdManager().GetIDData(esHandle, es))
|
||||||
|
@ -478,8 +852,8 @@ int cellDmuxFlushEs(u32 esHandle)
|
||||||
}
|
}
|
||||||
|
|
||||||
DemuxerTask task(dmuxFlushEs);
|
DemuxerTask task(dmuxFlushEs);
|
||||||
task.esHandle = esHandle;
|
task.es.es = esHandle;
|
||||||
task.au.es_ptr = es;
|
task.es.es_ptr = es;
|
||||||
|
|
||||||
es->dmux->job.Push(task);
|
es->dmux->job.Push(task);
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
|
|
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
#include "Utilities/SQueue.h"
|
#include "Utilities/SQueue.h"
|
||||||
|
|
||||||
|
// align size or address to 128
|
||||||
|
#define a128(x) ((x + 127) & (~127))
|
||||||
|
|
||||||
// Error Codes
|
// Error Codes
|
||||||
enum
|
enum
|
||||||
{
|
{
|
||||||
|
@ -232,7 +235,7 @@ struct CellDmuxResource2
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, mem_ptr_t<CellDmuxMsg> demuxerMsg, u32 cbArg_addr)> CellDmuxCbMsg;
|
typedef mem_func_ptr_t<void (*)(u32 demuxerHandle, mem_ptr_t<CellDmuxMsg> demuxerMsg, u32 cbArg_addr)> CellDmuxCbMsg;
|
||||||
|
|
||||||
struct CellDmuxCb
|
struct CellDmuxCb
|
||||||
{
|
{
|
||||||
|
@ -241,7 +244,7 @@ struct CellDmuxCb
|
||||||
be_t<u32> cbArg_addr;
|
be_t<u32> cbArg_addr;
|
||||||
};
|
};
|
||||||
|
|
||||||
typedef mem_func_ptr_t<void (*)(u32 demuxerHandle_addr, u32 esHandle_addr, mem_ptr_t<CellDmuxEsMsg> esMsg, u32 cbArg_addr)> CellDmuxCbEsMsg;
|
typedef mem_func_ptr_t<void (*)(u32 demuxerHandle, u32 esHandle, mem_ptr_t<CellDmuxEsMsg> esMsg, u32 cbArg_addr)> CellDmuxCbEsMsg;
|
||||||
|
|
||||||
struct CellDmuxEsCb
|
struct CellDmuxEsCb
|
||||||
{
|
{
|
||||||
|
@ -293,16 +296,120 @@ struct CellDmuxAuInfoEx
|
||||||
|
|
||||||
/* Demuxer Thread Classes */
|
/* Demuxer Thread Classes */
|
||||||
|
|
||||||
struct AccessUnit
|
enum
|
||||||
|
{
|
||||||
|
/* http://dvd.sourceforge.net/dvdinfo/mpeghdrs.html */
|
||||||
|
|
||||||
|
PACKET_START_CODE_MASK = 0xffffff00,
|
||||||
|
PACKET_START_CODE_PREFIX = 0x00000100,
|
||||||
|
|
||||||
|
USER_DATA_START_CODE = 0x000001b2,
|
||||||
|
SEQUENCE_START_CODE = 0x000001b3,
|
||||||
|
EXT_START_CODE = 0x000001b5,
|
||||||
|
SEQUENCE_END_CODE = 0x000001b7,
|
||||||
|
GOP_START_CODE = 0x000001b8,
|
||||||
|
ISO_11172_END_CODE = 0x000001b9,
|
||||||
|
PACK_START_CODE = 0x000001ba,
|
||||||
|
SYSTEM_HEADER_START_CODE = 0x000001bb,
|
||||||
|
PROGRAM_STREAM_MAP = 0x000001bc,
|
||||||
|
PRIVATE_STREAM_1 = 0x000001bd,
|
||||||
|
PADDING_STREAM = 0x000001be,
|
||||||
|
PRIVATE_STREAM_2 = 0x000001bf,
|
||||||
|
};
|
||||||
|
|
||||||
|
enum
|
||||||
|
{
|
||||||
|
MAX_AU = 640 * 1024 + 128, // 640 KB
|
||||||
|
};
|
||||||
|
|
||||||
|
struct DemuxerStream
|
||||||
{
|
{
|
||||||
u32 addr;
|
u32 addr;
|
||||||
u32 size;
|
u32 size;
|
||||||
u32 ptsUpper;
|
u64 userdata;
|
||||||
u32 ptsLower;
|
bool discontinuity;
|
||||||
u32 dtsUpper;
|
|
||||||
u32 dtsLower;
|
template<typename T>
|
||||||
u64 userData;
|
bool get(T& out)
|
||||||
bool isRap;
|
{
|
||||||
|
if (sizeof(T) > size) return false;
|
||||||
|
|
||||||
|
out = *mem_ptr_t<T>(addr);
|
||||||
|
addr += sizeof(T);
|
||||||
|
size -= sizeof(T);
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
template<typename T>
|
||||||
|
bool peek(T& out)
|
||||||
|
{
|
||||||
|
if (sizeof(T) > size) return false;
|
||||||
|
|
||||||
|
out = *mem_ptr_t<T>(addr);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void skip(u32 count)
|
||||||
|
{
|
||||||
|
addr += count;
|
||||||
|
size = size > count ? size - count : 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 get_ts(u8 c)
|
||||||
|
{
|
||||||
|
u16 v1, v2; get(v1); get(v2);
|
||||||
|
return (((u32) (c & 0x0E)) << 29) | ((v1 >> 1) << 15) | (v2 >> 1);
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 get_ts()
|
||||||
|
{
|
||||||
|
u8 v; get(v);
|
||||||
|
return get_ts(v);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
struct PesHeader
|
||||||
|
{
|
||||||
|
u32 pts;
|
||||||
|
u32 dts;
|
||||||
|
u8 ch;
|
||||||
|
u8 size;
|
||||||
|
|
||||||
|
PesHeader(DemuxerStream& stream)
|
||||||
|
: pts(0)
|
||||||
|
, dts(0)
|
||||||
|
, ch(0)
|
||||||
|
, size(0)
|
||||||
|
{
|
||||||
|
u16 header;
|
||||||
|
stream.get(header);
|
||||||
|
stream.get(size);
|
||||||
|
if (size)
|
||||||
|
{
|
||||||
|
if (size < 10)
|
||||||
|
{
|
||||||
|
ConLog.Error("Unknown PesHeader size");
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
|
u8 v;
|
||||||
|
stream.get(v);
|
||||||
|
if ((v & 0xF0) != 0x30)
|
||||||
|
{
|
||||||
|
ConLog.Error("Pts not found");
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
|
pts = stream.get_ts(v);
|
||||||
|
stream.get(v);
|
||||||
|
if ((v & 0xF0) != 0x10)
|
||||||
|
{
|
||||||
|
ConLog.Error("Dts not found");
|
||||||
|
Emu.Pause();
|
||||||
|
}
|
||||||
|
dts = stream.get_ts(v);
|
||||||
|
stream.skip(size - 10);
|
||||||
|
}
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ElementaryStream;
|
class ElementaryStream;
|
||||||
|
@ -311,32 +418,22 @@ enum DemuxerJobType
|
||||||
{
|
{
|
||||||
dmuxSetStream,
|
dmuxSetStream,
|
||||||
dmuxResetStream,
|
dmuxResetStream,
|
||||||
|
dmuxResetStreamAndWaitDone,
|
||||||
dmuxEnableEs,
|
dmuxEnableEs,
|
||||||
dmuxDisableEs,
|
dmuxDisableEs,
|
||||||
dmuxResetEs,
|
dmuxResetEs,
|
||||||
dmuxGetAu,
|
|
||||||
dmuxPeekAu,
|
|
||||||
dmuxReleaseAu,
|
dmuxReleaseAu,
|
||||||
dmuxFlushEs,
|
dmuxFlushEs,
|
||||||
dmuxClose,
|
dmuxClose,
|
||||||
};
|
};
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
|
||||||
struct DemuxerTask
|
struct DemuxerTask
|
||||||
{
|
{
|
||||||
DemuxerJobType type;
|
DemuxerJobType type;
|
||||||
|
|
||||||
union
|
union
|
||||||
{
|
{
|
||||||
struct
|
DemuxerStream stream;
|
||||||
{
|
|
||||||
u32 addr;
|
|
||||||
u64 userdata;
|
|
||||||
u32 size;
|
|
||||||
/*bool*/u32 discontinuity;
|
|
||||||
} stream;
|
|
||||||
|
|
||||||
u32 esHandle;
|
|
||||||
|
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
@ -344,7 +441,7 @@ struct DemuxerTask
|
||||||
u32 auInfo_ptr_addr;
|
u32 auInfo_ptr_addr;
|
||||||
u32 auSpec_ptr_addr;
|
u32 auSpec_ptr_addr;
|
||||||
ElementaryStream* es_ptr;
|
ElementaryStream* es_ptr;
|
||||||
} au;
|
} es;
|
||||||
};
|
};
|
||||||
|
|
||||||
DemuxerTask()
|
DemuxerTask()
|
||||||
|
@ -356,8 +453,6 @@ struct DemuxerTask
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static_assert(sizeof(DemuxerTask) == 24, "");
|
|
||||||
#pragma pack(pop)
|
|
||||||
|
|
||||||
class Demuxer
|
class Demuxer
|
||||||
{
|
{
|
||||||
|
@ -365,13 +460,16 @@ public:
|
||||||
SQueue<DemuxerTask> job;
|
SQueue<DemuxerTask> job;
|
||||||
const u32 memAddr;
|
const u32 memAddr;
|
||||||
const u32 memSize;
|
const u32 memSize;
|
||||||
const CellDmuxCbMsg cbFunc;
|
const u32 cbFunc;
|
||||||
const u32 cbArg;
|
const u32 cbArg;
|
||||||
|
u32 id;
|
||||||
bool is_finished;
|
bool is_finished;
|
||||||
|
bool is_running;
|
||||||
|
|
||||||
|
|
||||||
Demuxer(u32 addr, u32 size, CellDmuxCbMsg func, u32 arg)
|
Demuxer(u32 addr, u32 size, u32 func, u32 arg)
|
||||||
: is_finished(false)
|
: is_finished(false)
|
||||||
|
, is_running(false)
|
||||||
, memAddr(addr)
|
, memAddr(addr)
|
||||||
, memSize(size)
|
, memSize(size)
|
||||||
, cbFunc(func)
|
, cbFunc(func)
|
||||||
|
@ -382,19 +480,27 @@ public:
|
||||||
|
|
||||||
class ElementaryStream
|
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)
|
||||||
|
|
||||||
public:
|
public:
|
||||||
Demuxer* dmux;
|
Demuxer* dmux;
|
||||||
|
u32 id;
|
||||||
const u32 memAddr;
|
const u32 memAddr;
|
||||||
const u32 memSize;
|
const u32 memSize;
|
||||||
const u32 fidMajor;
|
const u32 fidMajor;
|
||||||
const u32 fidMinor;
|
const u32 fidMinor;
|
||||||
const u32 sup1;
|
const u32 sup1;
|
||||||
const u32 sup2;
|
const u32 sup2;
|
||||||
const CellDmuxCbEsMsg cbFunc;
|
const u32 cbFunc;
|
||||||
const u32 cbArg;
|
const u32 cbArg;
|
||||||
const u32 spec; //addr
|
const u32 spec; //addr
|
||||||
|
|
||||||
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, CellDmuxCbEsMsg cbFunc, u32 cbArg, u32 spec)
|
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, u32 cbFunc, u32 cbArg, u32 spec)
|
||||||
: dmux(dmux)
|
: dmux(dmux)
|
||||||
, memAddr(addr)
|
, memAddr(addr)
|
||||||
, memSize(size)
|
, memSize(size)
|
||||||
|
@ -405,6 +511,175 @@ public:
|
||||||
, cbFunc(cbFunc)
|
, cbFunc(cbFunc)
|
||||||
, cbArg(cbArg)
|
, cbArg(cbArg)
|
||||||
, spec(spec)
|
, spec(spec)
|
||||||
|
, first_addr(0)
|
||||||
|
, peek_addr(0)
|
||||||
|
, last_addr(a128(addr))
|
||||||
|
, last_size(0)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
volatile bool hasdata()
|
||||||
|
{
|
||||||
|
return last_size;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool isfull() // not multithread-safe
|
||||||
|
{
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void finish(DemuxerStream& stream) // not multithread-safe
|
||||||
|
{
|
||||||
|
SMutexLocker lock(mutex);
|
||||||
|
|
||||||
|
if (!first_addr)
|
||||||
|
{
|
||||||
|
first_addr = last_addr;
|
||||||
|
}
|
||||||
|
if (!peek_addr)
|
||||||
|
{
|
||||||
|
peek_addr = last_addr;
|
||||||
|
}
|
||||||
|
u32 new_addr = a128(last_addr + 128 + last_size);
|
||||||
|
if ((new_addr + MAX_AU) > (memAddr + memSize))
|
||||||
|
{
|
||||||
|
last_addr = memAddr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
last_addr = new_addr;
|
||||||
|
}
|
||||||
|
last_size = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void push(DemuxerStream& stream, u32 size, PesHeader& pes)
|
||||||
|
{
|
||||||
|
SMutexLocker lock(mutex);
|
||||||
|
if (isfull())
|
||||||
|
{
|
||||||
|
ConLog.Error("ElementaryStream::push(): buffer is full");
|
||||||
|
Emu.Pause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 data_addr = last_addr + 128 + last_size;
|
||||||
|
last_size += size;
|
||||||
|
memcpy(Memory + data_addr, Memory + stream.addr, size);
|
||||||
|
stream.skip(size);
|
||||||
|
|
||||||
|
mem_ptr_t<CellDmuxAuInfoEx> info(last_addr);
|
||||||
|
info->auAddr = last_addr + 128;
|
||||||
|
info->auSize = last_size;
|
||||||
|
if (pes.size)
|
||||||
|
{
|
||||||
|
info->dts.lower = pes.dts;
|
||||||
|
info->dts.upper = 0;
|
||||||
|
info->pts.lower = pes.pts;
|
||||||
|
info->pts.upper = 0;
|
||||||
|
info->isRap = false; // TODO: set valid value
|
||||||
|
info->reserved = 0;
|
||||||
|
info->userData = stream.userdata;
|
||||||
|
}
|
||||||
|
|
||||||
|
mem_ptr_t<CellDmuxPamfAuSpecificInfoAvc> tail(last_addr + sizeof(CellDmuxAuInfoEx));
|
||||||
|
tail->reserved1 = 0;
|
||||||
|
|
||||||
|
mem_ptr_t<CellDmuxAuInfo> inf(last_addr + 64);
|
||||||
|
inf->auAddr = last_addr + 128;
|
||||||
|
inf->auSize = last_size;
|
||||||
|
if (pes.size)
|
||||||
|
{
|
||||||
|
inf->dtsLower = pes.dts;
|
||||||
|
inf->dtsUpper = 0;
|
||||||
|
inf->ptsLower = pes.pts;
|
||||||
|
inf->ptsUpper = 0;
|
||||||
|
inf->auMaxSize = 0; // ?????
|
||||||
|
inf->userData = stream.userdata;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
volatile bool canrelease()
|
||||||
|
{
|
||||||
|
return first_addr;
|
||||||
|
}
|
||||||
|
|
||||||
|
void release()
|
||||||
|
{
|
||||||
|
SMutexLocker lock(mutex);
|
||||||
|
if (!canrelease())
|
||||||
|
{
|
||||||
|
ConLog.Error("ElementaryStream::release(): buffer is empty");
|
||||||
|
Emu.Pause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
u32 size = a128(Memory.Read32(first_addr + 4) + 128);
|
||||||
|
u32 new_addr = first_addr + size;
|
||||||
|
if (peek_addr <= first_addr) peek_addr = new_addr;
|
||||||
|
if (new_addr == last_addr)
|
||||||
|
{
|
||||||
|
first_addr = 0;
|
||||||
|
}
|
||||||
|
else if ((new_addr + MAX_AU) > (memAddr + memSize))
|
||||||
|
{
|
||||||
|
first_addr = memAddr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
first_addr = new_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
bool peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index)
|
||||||
|
{
|
||||||
|
SMutexLocker lock(mutex);
|
||||||
|
ConLog.Write("es::peek(): peek_addr=0x%x", peek_addr);
|
||||||
|
if (!peek_addr) return false;
|
||||||
|
|
||||||
|
out_data = peek_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)
|
||||||
|
{
|
||||||
|
peek_addr = 0;
|
||||||
|
}
|
||||||
|
else if ((new_addr + MAX_AU) > (memAddr + memSize))
|
||||||
|
{
|
||||||
|
peek_addr = memAddr;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
peek_addr = new_addr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void reset()
|
||||||
|
{
|
||||||
|
SMutexLocker lock(mutex);
|
||||||
|
first_addr = 0;
|
||||||
|
peek_addr = 0;
|
||||||
|
last_addr = a128(memAddr);
|
||||||
|
last_size = 0;
|
||||||
|
}
|
||||||
};
|
};
|
|
@ -17,26 +17,16 @@ int pamfStreamTypeToEsFilterId(u8 type, u8 ch, mem_ptr_t<CellCodecEsFilterId> pE
|
||||||
switch (type)
|
switch (type)
|
||||||
{
|
{
|
||||||
case CELL_PAMF_STREAM_TYPE_AVC:
|
case CELL_PAMF_STREAM_TYPE_AVC:
|
||||||
switch (ch)
|
|
||||||
{
|
{
|
||||||
case 0:
|
if (ch < 16)
|
||||||
{
|
{
|
||||||
pEsFilterId->filterIdMajor = 0xe0; //fake info
|
pEsFilterId->filterIdMajor = 0xe0 + ch;
|
||||||
pEsFilterId->filterIdMinor = 0;
|
pEsFilterId->filterIdMinor = 0;
|
||||||
pEsFilterId->supplementalInfo1 = 0x01;
|
pEsFilterId->supplementalInfo1 = 0x01;
|
||||||
pEsFilterId->supplementalInfo2 = 0;
|
pEsFilterId->supplementalInfo2 = 0;
|
||||||
}
|
}
|
||||||
break;
|
else
|
||||||
case 1:
|
cellPamf.Error("pamfStreamTypeToEsFilterId: invalid CELL_PAMF_STREAM_TYPE_AVC channel (ch=%d)", ch);
|
||||||
{
|
|
||||||
pEsFilterId->filterIdMajor = 0xe1;
|
|
||||||
pEsFilterId->filterIdMinor = 0;
|
|
||||||
pEsFilterId->supplementalInfo1 = 0x01;
|
|
||||||
pEsFilterId->supplementalInfo2 = 0;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
cellPamf.Error("*** TODO: pamfStreamTypeToEsFilterId: CELL_PAMF_STREAM_TYPE_AVC (ch=%d)", ch);
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS:
|
case CELL_PAMF_STREAM_TYPE_ATRAC3PLUS:
|
||||||
|
@ -96,7 +86,7 @@ u8 pamfGetStreamType(mem_ptr_t<CellPamfReader> pSelf, u8 stream)
|
||||||
case 0x80: return CELL_PAMF_STREAM_TYPE_PAMF_LPCM;
|
case 0x80: return CELL_PAMF_STREAM_TYPE_PAMF_LPCM;
|
||||||
case 0xdd: return CELL_PAMF_STREAM_TYPE_USER_DATA;
|
case 0xdd: return CELL_PAMF_STREAM_TYPE_USER_DATA;
|
||||||
default:
|
default:
|
||||||
cellPamf.Error("pamfGetStreamType: unsupported stream type found(0x%x)",
|
cellPamf.Error("pamfGetStreamType: (TODO) unsupported stream type found(0x%x)",
|
||||||
pAddr->stream_headers[stream].type);
|
pAddr->stream_headers[stream].type);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -104,12 +94,16 @@ u8 pamfGetStreamType(mem_ptr_t<CellPamfReader> pSelf, u8 stream)
|
||||||
|
|
||||||
u8 pamfGetStreamChannel(mem_ptr_t<CellPamfReader> pSelf, u8 stream)
|
u8 pamfGetStreamChannel(mem_ptr_t<CellPamfReader> pSelf, u8 stream)
|
||||||
{
|
{
|
||||||
cellPamf.Warning("TODO: pamfGetStreamChannel");
|
|
||||||
//TODO: get stream channel correctly
|
//TODO: get stream channel correctly
|
||||||
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
|
const mem_ptr_t<PamfHeader> pAddr(pSelf->pAddr);
|
||||||
|
|
||||||
if ((pAddr->stream_headers[stream].type == 0x1b) &&
|
if ((pAddr->stream_headers[stream].type == 0x1b) &&
|
||||||
(pAddr->stream_headers[stream].stream_id == 0xe1)) return 1;
|
(pAddr->stream_headers[stream].stream_id >= 0xe0) &&
|
||||||
|
(pAddr->stream_headers[stream].stream_id <= 0xef))
|
||||||
|
{
|
||||||
|
return pAddr->stream_headers[stream].stream_id - 0xe0;
|
||||||
|
}
|
||||||
|
cellPamf.Error("TODO: pamfGetStreamChannel (-> 0)");
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,11 @@
|
||||||
#include "Emu/SysCalls/SC_FUNC.h"
|
#include "Emu/SysCalls/SC_FUNC.h"
|
||||||
#include "cellVdec.h"
|
#include "cellVdec.h"
|
||||||
|
|
||||||
|
extern "C"
|
||||||
|
{
|
||||||
|
#include "libavformat\avformat.h"
|
||||||
|
}
|
||||||
|
|
||||||
void cellVdec_init();
|
void cellVdec_init();
|
||||||
Module cellVdec(0x0005, cellVdec_init);
|
Module cellVdec(0x0005, cellVdec_init);
|
||||||
|
|
||||||
|
|
|
@ -150,46 +150,67 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
||||||
|
|
||||||
const wxString path = orig_file->GetPath().AfterFirst('/');
|
const wxString path = orig_file->GetPath().AfterFirst('/');
|
||||||
|
|
||||||
u64 nbytes = (u64)aio->size;
|
u64 nbytes = aio->size;
|
||||||
const u32 buf_addr = (u32)aio->buf_addr;
|
u32 buf_addr = aio->buf_addr;
|
||||||
|
|
||||||
u64 res;
|
u32 res = 0;
|
||||||
u32 error;
|
u32 error = CELL_OK;
|
||||||
|
|
||||||
if(Memory.IsGoodAddr(buf_addr))
|
|
||||||
{
|
|
||||||
/*
|
|
||||||
//open the file again (to prevent access conflicts roughly)
|
|
||||||
vfsLocalFile file(path, vfsRead);
|
|
||||||
*/
|
|
||||||
vfsStream& file = *(vfsStream*)orig_file;
|
vfsStream& file = *(vfsStream*)orig_file;
|
||||||
if(!Memory.IsGoodAddr(buf_addr, nbytes))
|
|
||||||
{
|
|
||||||
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
|
|
||||||
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
|
|
||||||
}
|
|
||||||
|
|
||||||
const u64 old_pos = file.Tell();
|
const u64 old_pos = file.Tell();
|
||||||
file.Seek((u64)aio->offset);
|
file.Seek((u64)aio->offset);
|
||||||
res = nbytes ? file.Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
|
|
||||||
file.Seek(old_pos);
|
u32 count = nbytes;
|
||||||
error = CELL_OK;
|
if (nbytes != (u64)count)
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
res = 0;
|
error = CELL_ENOMEM;
|
||||||
error = CELL_EFAULT;
|
goto fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, res=0x%x, xid=0x%x [%s])",
|
if (!Memory.IsGoodAddr(buf_addr))
|
||||||
fd, (u64)aio->offset, buf_addr, (u64)aio->size, res, xid, path.wx_str());
|
{
|
||||||
|
error = CELL_EFAULT;
|
||||||
|
goto fin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count) if (u32 frag = buf_addr & 4095) // memory page fragment
|
||||||
|
{
|
||||||
|
u32 req = min(count, 4096 - frag);
|
||||||
|
u32 read = file.Read(Memory + buf_addr, req);
|
||||||
|
buf_addr += req;
|
||||||
|
res += read;
|
||||||
|
count -= req;
|
||||||
|
if (read < req) goto fin;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (u32 pages = count / 4096; pages > 0; pages--) // full pages
|
||||||
|
{
|
||||||
|
if (!Memory.IsGoodAddr(buf_addr)) goto fin; // ??? (probably EFAULT)
|
||||||
|
u32 read = file.Read(Memory + buf_addr, 4096);
|
||||||
|
buf_addr += 4096;
|
||||||
|
res += read;
|
||||||
|
count -= 4096;
|
||||||
|
if (read < 4096) goto fin;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (count) // last fragment
|
||||||
|
{
|
||||||
|
if (!Memory.IsGoodAddr(buf_addr)) goto fin;
|
||||||
|
res += file.Read(Memory + buf_addr, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
fin:
|
||||||
|
file.Seek(old_pos);
|
||||||
|
|
||||||
|
ConLog.Warning("*** fsAioRead(fd=%d, offset=0x%llx, buf_addr=0x%x, size=0x%x, error=0x%x, res=0x%x, xid=0x%x [%s])",
|
||||||
|
fd, (u64)aio->offset, buf_addr, (u64)aio->size, error, res, xid, path.wx_str());
|
||||||
|
|
||||||
if (func) // start callback thread
|
if (func) // start callback thread
|
||||||
{
|
{
|
||||||
func.async(aio, error, xid, res);
|
func.async(aio, error, xid, res);
|
||||||
}
|
}
|
||||||
|
|
||||||
CPUThread& thr = Emu.GetCallbackThread();
|
/*CPUThread& thr = Emu.GetCallbackThread();
|
||||||
while (thr.IsAlive())
|
while (thr.IsAlive())
|
||||||
{
|
{
|
||||||
Sleep(1);
|
Sleep(1);
|
||||||
|
@ -198,7 +219,7 @@ void fsAioRead(u32 fd, mem_ptr_t<CellFsAio> aio, int xid, mem_func_ptr_t<void (*
|
||||||
ConLog.Warning("fsAioRead() aborted");
|
ConLog.Warning("fsAioRead() aborted");
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}*/
|
||||||
|
|
||||||
g_FsAioReadCur++;
|
g_FsAioReadCur++;
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,7 +6,7 @@ SysCallBase sys_cond("sys_cond");
|
||||||
|
|
||||||
int sys_cond_create(mem32_t cond_id, u32 mutex_id, mem_ptr_t<sys_cond_attribute> attr)
|
int sys_cond_create(mem32_t cond_id, u32 mutex_id, mem_ptr_t<sys_cond_attribute> attr)
|
||||||
{
|
{
|
||||||
sys_cond.Log("sys_cond_create(cond_id_addr=0x%x, mutex_id=%d, attr_addr=%d)",
|
sys_cond.Log("sys_cond_create(cond_id_addr=0x%x, mutex_id=%d, attr_addr=0x%x)",
|
||||||
cond_id.GetAddr(), mutex_id, attr.GetAddr());
|
cond_id.GetAddr(), mutex_id, attr.GetAddr());
|
||||||
|
|
||||||
if (!cond_id.IsGood() || !attr.IsGood())
|
if (!cond_id.IsGood() || !attr.IsGood())
|
||||||
|
|
|
@ -94,16 +94,43 @@ int cellFsRead(u32 fd, u32 buf_addr, u64 nbytes, mem64_t nread)
|
||||||
vfsStream* file;
|
vfsStream* file;
|
||||||
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
|
if(!sys_fs.CheckId(fd, file)) return CELL_ESRCH;
|
||||||
|
|
||||||
if(Memory.IsGoodAddr(buf_addr) && !Memory.IsGoodAddr(buf_addr, nbytes))
|
if (nread.GetAddr() && !nread.IsGood()) return CELL_EFAULT;
|
||||||
|
|
||||||
|
u32 res = 0;
|
||||||
|
u32 count = nbytes;
|
||||||
|
if (nbytes != (u64)count) return CELL_ENOMEM;
|
||||||
|
|
||||||
|
if (!Memory.IsGoodAddr(buf_addr)) return CELL_EFAULT;
|
||||||
|
|
||||||
|
if (count) if (u32 frag = buf_addr & 4095) // memory page fragment
|
||||||
{
|
{
|
||||||
MemoryBlock& block = Memory.GetMemByAddr(buf_addr);
|
u32 req = min(count, 4096 - frag);
|
||||||
nbytes = block.GetSize() - (buf_addr - block.GetStartAddr());
|
u32 read = file->Read(Memory + buf_addr, req);
|
||||||
|
buf_addr += req;
|
||||||
|
res += read;
|
||||||
|
count -= req;
|
||||||
|
if (read < req) goto fin;
|
||||||
}
|
}
|
||||||
|
|
||||||
const u64 res = nbytes ? file->Read(Memory.GetMemFromAddr(buf_addr), nbytes) : 0;
|
for (u32 pages = count / 4096; pages > 0; pages--) // full pages
|
||||||
|
{
|
||||||
|
if (!Memory.IsGoodAddr(buf_addr)) goto fin; // ??? (probably EFAULT)
|
||||||
|
u32 read = file->Read(Memory + buf_addr, 4096);
|
||||||
|
buf_addr += 4096;
|
||||||
|
res += read;
|
||||||
|
count -= 4096;
|
||||||
|
if (read < 4096) goto fin;
|
||||||
|
}
|
||||||
|
|
||||||
if(nread.IsGood())
|
if (count) // last fragment
|
||||||
nread = res;
|
{
|
||||||
|
if (!Memory.IsGoodAddr(buf_addr)) goto fin;
|
||||||
|
res += file->Read(Memory + buf_addr, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
fin:
|
||||||
|
|
||||||
|
if (nread.GetAddr()) nread = res; // write value if not NULL
|
||||||
|
|
||||||
return CELL_OK;
|
return CELL_OK;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue