mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-04-20 03:25:16 +00:00
commit
f241a63e86
8 changed files with 332 additions and 241 deletions
|
@ -5,7 +5,7 @@ static const volatile bool sq_no_wait = true;
|
|||
template<typename T, u32 SQSize = 666>
|
||||
class SQueue
|
||||
{
|
||||
std::mutex m_mutex;
|
||||
mutable std::mutex m_mutex;
|
||||
u32 m_pos;
|
||||
u32 m_count;
|
||||
T m_data[SQSize];
|
||||
|
@ -17,11 +17,16 @@ public:
|
|||
{
|
||||
}
|
||||
|
||||
const u32 GetSize() const
|
||||
u32 GetSize() const
|
||||
{
|
||||
return SQSize;
|
||||
}
|
||||
|
||||
bool IsFull() const volatile
|
||||
{
|
||||
return m_count == SQSize;
|
||||
}
|
||||
|
||||
bool Push(const T& data, const volatile bool* do_exit)
|
||||
{
|
||||
while (true)
|
||||
|
|
|
@ -3,6 +3,38 @@
|
|||
#include "Log.h"
|
||||
#include "Thread.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
void SetCurrentThreadDebugName(const char* threadName)
|
||||
{
|
||||
#ifdef _WIN32 // this is VS-specific way to set thread names for the debugger
|
||||
#pragma pack(push,8)
|
||||
struct THREADNAME_INFO
|
||||
{
|
||||
DWORD dwType;
|
||||
LPCSTR szName;
|
||||
DWORD dwThreadID;
|
||||
DWORD dwFlags;
|
||||
} info;
|
||||
#pragma pack(pop)
|
||||
|
||||
info.dwType = 0x1000;
|
||||
info.szName = threadName;
|
||||
info.dwThreadID = -1;
|
||||
info.dwFlags = 0;
|
||||
|
||||
__try
|
||||
{
|
||||
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(ULONG_PTR), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except (EXCEPTION_EXECUTE_HANDLER)
|
||||
{
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
thread_local NamedThreadBase* g_tls_this_thread = nullptr;
|
||||
std::atomic<u32> g_thread_count(0);
|
||||
|
||||
|
@ -85,6 +117,8 @@ void ThreadBase::Start()
|
|||
|
||||
m_executor = new std::thread([this]()
|
||||
{
|
||||
SetCurrentThreadDebugName(GetThreadName().c_str());
|
||||
|
||||
SetCurrentNamedThread(this);
|
||||
g_thread_count++;
|
||||
|
||||
|
@ -172,6 +206,8 @@ void thread::start(std::function<void()> func)
|
|||
|
||||
m_thr = std::thread([func, name]()
|
||||
{
|
||||
SetCurrentThreadDebugName(name.c_str());
|
||||
|
||||
NamedThreadBase info(name);
|
||||
SetCurrentNamedThread(&info);
|
||||
g_thread_count++;
|
||||
|
|
|
@ -97,7 +97,7 @@ next:
|
|||
{
|
||||
u8 code1 = vm::read8(adec.reader.addr + 2);
|
||||
u8 code2 = vm::read8(adec.reader.addr + 3);
|
||||
adec.channels = code1 >> 2;
|
||||
adec.channels = (code1 >> 2) & 0x7;
|
||||
adec.frame_size = ((((u32)code1 & 0x3) << 8) | (u32)code2) * 8 + 8;
|
||||
adec.sample_rate = at3freq[code1 >> 5];
|
||||
|
||||
|
|
|
@ -14,7 +14,7 @@ PesHeader::PesHeader(DemuxerStream& stream)
|
|||
: pts(0xffffffffffffffffull)
|
||||
, dts(0xffffffffffffffffull)
|
||||
, size(0)
|
||||
, new_au(false)
|
||||
, has_ts(false)
|
||||
{
|
||||
u16 header;
|
||||
stream.get(header);
|
||||
|
@ -33,13 +33,13 @@ PesHeader::PesHeader(DemuxerStream& stream)
|
|||
|
||||
if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only
|
||||
{
|
||||
new_au = true;
|
||||
has_ts = true;
|
||||
pts = stream.get_ts(v);
|
||||
stream.skip(size - empty - 5);
|
||||
}
|
||||
else
|
||||
{
|
||||
new_au = true;
|
||||
has_ts = true;
|
||||
if ((v & 0xF0) != 0x30 || (size - empty) < 10)
|
||||
{
|
||||
cellDmux->Error("PesHeader(): pts not found");
|
||||
|
@ -58,23 +58,31 @@ PesHeader::PesHeader(DemuxerStream& stream)
|
|||
}
|
||||
}
|
||||
|
||||
bool ElementaryStream::is_full()
|
||||
bool ElementaryStream::is_full(u32 space)
|
||||
{
|
||||
if (released < put_count)
|
||||
{
|
||||
u32 first;
|
||||
if (!entries.Peek(first, &dmux->is_closed))
|
||||
if (entries.IsFull())
|
||||
{
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
if (first >= put)
|
||||
|
||||
u32 first = 0;
|
||||
if (!entries.Peek(first, &dmux->is_closed) || !first)
|
||||
{
|
||||
return (first - put) < GetMaxAU();
|
||||
throw "es::is_full() error: entries.Peek() failed";
|
||||
}
|
||||
else if (first >= put)
|
||||
{
|
||||
return first - put < space + 128;
|
||||
}
|
||||
else if (put + space + 128 > memAddr + memSize)
|
||||
{
|
||||
return first - memAddr < space + 128;
|
||||
}
|
||||
else
|
||||
{
|
||||
// probably, always false
|
||||
return (put + GetMaxAU()) > (memAddr + memSize);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -83,206 +91,148 @@ bool ElementaryStream::is_full()
|
|||
}
|
||||
}
|
||||
|
||||
const u32 ElementaryStream::GetMaxAU() const
|
||||
{
|
||||
return (fidMajor == 0xbd) ? 4096 : 640 * 1024 + 128; // TODO
|
||||
}
|
||||
|
||||
u32 ElementaryStream::freespace()
|
||||
{
|
||||
if (size > GetMaxAU())
|
||||
{
|
||||
cellDmux->Error("es::freespace(): last_size too big (size=0x%x, max_au=0x%x)", size, GetMaxAU());
|
||||
Emu.Pause();
|
||||
return 0;
|
||||
}
|
||||
return GetMaxAU() - size;
|
||||
}
|
||||
|
||||
bool ElementaryStream::hasunseen()
|
||||
bool ElementaryStream::isfull(u32 space)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return peek_count < put_count;
|
||||
return is_full(space);
|
||||
}
|
||||
|
||||
bool ElementaryStream::hasdata()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return size != 0;
|
||||
}
|
||||
|
||||
bool ElementaryStream::isfull()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
return is_full();
|
||||
}
|
||||
|
||||
void ElementaryStream::finish(DemuxerStream& stream) // not multithread-safe (or safe?)
|
||||
void ElementaryStream::push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool rap, u32 specific)
|
||||
{
|
||||
u32 addr;
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, ">>> es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
|
||||
if (is_full(size))
|
||||
{
|
||||
throw "es::push_au() error: buffer is full";
|
||||
}
|
||||
|
||||
if (put + size + 128 > memAddr + memSize)
|
||||
{
|
||||
put = memAddr;
|
||||
}
|
||||
|
||||
memcpy(vm::get_ptr<void>(put + 128), raw_data.data(), size);
|
||||
raw_data.erase(raw_data.begin(), raw_data.begin() + size);
|
||||
|
||||
auto info = vm::ptr<CellDmuxAuInfoEx>::make(put);
|
||||
info->auAddr = put + 128;
|
||||
info->auSize = size;
|
||||
info->dts.lower = (u32)(dts);
|
||||
info->dts.upper = (u32)(dts >> 32);
|
||||
info->pts.lower = (u32)(pts);
|
||||
info->pts.upper = (u32)(pts >> 32);
|
||||
info->isRap = rap;
|
||||
info->reserved = 0;
|
||||
info->userData = userdata;
|
||||
|
||||
auto spec = vm::ptr<u32>::make(put + sizeof(CellDmuxAuInfoEx));
|
||||
*spec = specific;
|
||||
|
||||
auto inf = vm::ptr<CellDmuxAuInfo>::make(put + 64);
|
||||
inf->auAddr = put + 128;
|
||||
inf->auSize = size;
|
||||
inf->dtsLower = (u32)(dts);
|
||||
inf->dtsUpper = (u32)(dts >> 32);
|
||||
inf->ptsLower = (u32)(pts);
|
||||
inf->ptsUpper = (u32)(pts >> 32);
|
||||
inf->auMaxSize = 0; // ?????
|
||||
inf->userData = userdata;
|
||||
|
||||
addr = put;
|
||||
|
||||
auto info = vm::ptr<CellDmuxAuInfo>::make(put);
|
||||
//if (fidMajor != 0xbd) LOG_WARNING(HLE, "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);
|
||||
put = ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
||||
? memAddr : new_addr;
|
||||
|
||||
size = 0;
|
||||
put = a128(put + 128 + size);
|
||||
|
||||
put_count++;
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, "<<< es::finish(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
}
|
||||
if (!entries.Push(addr, &sq_no_wait))
|
||||
if (!entries.Push(addr, &dmux->is_closed))
|
||||
{
|
||||
cellDmux->Error("es::finish() aborted (no space)");
|
||||
Emu.Pause();
|
||||
throw "es::push_au() error: entries.Push() failed";
|
||||
}
|
||||
}
|
||||
|
||||
void ElementaryStream::push(DemuxerStream& stream, u32 sz, PesHeader& pes)
|
||||
void ElementaryStream::push(DemuxerStream& stream, u32 size)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
auto const old_size = raw_data.size();
|
||||
|
||||
if (is_full())
|
||||
{
|
||||
cellDmux->Error("es::push(): buffer is full");
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
raw_data.resize(old_size + size);
|
||||
|
||||
u32 data_addr = put + 128 + size;
|
||||
size += sz;
|
||||
memcpy(vm::get_ptr<void>(data_addr), vm::get_ptr<void>(stream.addr), sz);
|
||||
stream.skip(sz);
|
||||
memcpy(raw_data.data() + old_size, vm::get_ptr<void>(stream.addr), size); // append bytes
|
||||
|
||||
auto info = vm::ptr<CellDmuxAuInfoEx>::make(put);
|
||||
info->auAddr = put + 128;
|
||||
info->auSize = size;
|
||||
if (pes.new_au)
|
||||
{
|
||||
info->dts.lower = (u32)pes.dts;
|
||||
info->dts.upper = (u32)(pes.dts >> 32);
|
||||
info->pts.lower = (u32)pes.pts;
|
||||
info->pts.upper = (u32)(pes.pts >> 32);
|
||||
info->isRap = false; // TODO: set valid value
|
||||
info->reserved = 0;
|
||||
info->userData = stream.userdata;
|
||||
}
|
||||
|
||||
auto tail = vm::ptr<CellDmuxPamfAuSpecificInfoAvc>::make(put + sizeof(CellDmuxAuInfoEx));
|
||||
tail->reserved1 = 0;
|
||||
|
||||
auto inf = vm::ptr<CellDmuxAuInfo>::make(put + 64);
|
||||
inf->auAddr = put + 128;
|
||||
inf->auSize = size;
|
||||
if (pes.new_au)
|
||||
{
|
||||
inf->dtsLower = (u32)pes.dts;
|
||||
inf->dtsUpper = (u32)(pes.dts >> 32);
|
||||
inf->ptsLower = (u32)pes.pts;
|
||||
inf->ptsUpper = (u32)(pes.pts >> 32);
|
||||
inf->auMaxSize = 0; // ?????
|
||||
inf->userData = stream.userdata;
|
||||
}
|
||||
stream.skip(size);
|
||||
}
|
||||
|
||||
bool ElementaryStream::release()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, ">>> es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
if (released >= put_count)
|
||||
{
|
||||
cellDmux->Error("es::release(): buffer is empty");
|
||||
cellDmux->Error("es::release() error: buffer is empty");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
if (released >= got_count)
|
||||
{
|
||||
cellDmux->Error("es::release() error: buffer has not been seen yet");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 addr;
|
||||
if (!entries.Peek(addr, &dmux->is_closed))
|
||||
u32 addr = 0;
|
||||
if (!entries.Pop(addr, &dmux->is_closed) || !addr)
|
||||
{
|
||||
return false; // ???
|
||||
}
|
||||
|
||||
auto info = vm::ptr<CellDmuxAuInfo>::make(addr);
|
||||
//if (fidMajor != 0xbd) LOG_WARNING(HLE, "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)
|
||||
{
|
||||
cellDmux->Error("es::release(): buffer has not been seen yet");
|
||||
cellDmux->Error("es::release() error: entries.Pop() failed");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
|
||||
released++;
|
||||
if (!entries.Pop(addr, &sq_no_wait))
|
||||
{
|
||||
cellDmux->Error("es::release(): entries.Pop() aborted (no entries found)");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, "<<< es::release(): peek=0x%x, first=0x%x, put=0x%x, size=0x%x", peek, first, put, size);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool ElementaryStream::peek(u32& out_data, bool no_ex, u32& out_spec, bool update_index)
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, ">>> 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;
|
||||
|
||||
if (peek_count < released)
|
||||
if (got_count < released)
|
||||
{
|
||||
cellDmux->Error("es::peek(): sequence error: peek_count < released (peek_count=%d, released=%d)", peek_count, released);
|
||||
cellDmux->Error("es::peek() error: got_count(%d) < released(%d) (put_count=%d)", got_count, released, put_count);
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
if (got_count >= put_count)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 addr = 0;
|
||||
if (!entries.Peek(addr, &dmux->is_closed, got_count - released) || !addr)
|
||||
{
|
||||
cellDmux->Error("es::peek() error: entries.Peek() failed");
|
||||
Emu.Pause();
|
||||
return false;
|
||||
}
|
||||
|
||||
u32 addr;
|
||||
if (!entries.Peek(addr, &dmux->is_closed, peek_count - released))
|
||||
{
|
||||
return false; // ???
|
||||
}
|
||||
|
||||
auto info = vm::ptr<CellDmuxAuInfo>::make(addr);
|
||||
//if (fidMajor != 0xbd) LOG_WARNING(HLE, "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;
|
||||
out_data = no_ex ? addr + 64 : addr;
|
||||
out_spec = addr + sizeof(CellDmuxAuInfoEx);
|
||||
|
||||
if (update_index)
|
||||
{
|
||||
peek_count++;
|
||||
got_count++;
|
||||
}
|
||||
|
||||
//if (fidMajor != 0xbd) LOG_NOTICE(HLE, "<<< 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 ElementaryStream::reset()
|
||||
{
|
||||
std::lock_guard<std::mutex> lock(m_mutex);
|
||||
//first = 0;
|
||||
//peek = 0;
|
||||
put = memAddr;
|
||||
size = 0;
|
||||
entries.Clear();
|
||||
put_count = 0;
|
||||
got_count = 0;
|
||||
released = 0;
|
||||
peek_count = 0;
|
||||
raw_data.clear();
|
||||
raw_pos = 0;
|
||||
}
|
||||
|
||||
void dmuxQueryAttr(u32 info_addr /* may be 0 */, vm::ptr<CellDmuxAttr> attr)
|
||||
|
@ -409,7 +359,7 @@ u32 dmuxOpen(Demuxer* data)
|
|||
if (esATX[ch])
|
||||
{
|
||||
ElementaryStream& es = *esATX[ch];
|
||||
if (es.isfull())
|
||||
if (es.raw_data.size() > 1024 * 1024)
|
||||
{
|
||||
stream = backup;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
|
@ -419,14 +369,41 @@ u32 dmuxOpen(Demuxer* data)
|
|||
stream.skip(4);
|
||||
len -= 4;
|
||||
|
||||
es.push(stream, len - pes.size - 3, pes);
|
||||
es.finish(stream);
|
||||
//LOG_NOTICE(HLE, "*** AT3+ AU sent (len=0x%x, pts=0x%llx)", len - pes.size - 3, pes.pts);
|
||||
if (pes.has_ts)
|
||||
{
|
||||
es.last_dts = pes.dts;
|
||||
es.last_pts = pes.pts;
|
||||
}
|
||||
|
||||
es.push(stream, len - pes.size - 3);
|
||||
|
||||
while (true)
|
||||
{
|
||||
auto const size = es.raw_data.size() - es.raw_pos; // size of available new data
|
||||
auto const data = es.raw_data.data() + es.raw_pos; // pointer to available data
|
||||
|
||||
if (size < 8) break; // skip if cannot read ATS header
|
||||
|
||||
if (data[0] != 0x0f || data[1] != 0xd0)
|
||||
{
|
||||
cellDmux->Error("ATX: 0x0fd0 header not found (ats=0x%llx)", ((be_t<u64>*)data)->ToLE());
|
||||
Emu.Pause();
|
||||
return;
|
||||
}
|
||||
|
||||
u32 frame_size = ((((u32)data[2] & 0x3) << 8) | (u32)data[3]) * 8 + 8;
|
||||
|
||||
if (size < frame_size + 8) break; // skip non-complete AU
|
||||
|
||||
if (es.isfull(frame_size + 8)) break; // skip if cannot push AU
|
||||
|
||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||
esMsg->supplementalInfo = stream.userdata;
|
||||
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
|
||||
es.push_au(frame_size + 8, es.last_dts, es.last_pts, stream.userdata, false /* TODO: set correct value */, 0);
|
||||
|
||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||
esMsg->supplementalInfo = stream.userdata;
|
||||
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -445,48 +422,43 @@ u32 dmuxOpen(Demuxer* data)
|
|||
if (esAVC[ch])
|
||||
{
|
||||
ElementaryStream& es = *esAVC[ch];
|
||||
if (es.isfull())
|
||||
{
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
DemuxerStream backup = stream;
|
||||
|
||||
stream.skip(4);
|
||||
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
|
||||
{
|
||||
es.finish(stream);
|
||||
// callback
|
||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||
esMsg->supplementalInfo = stream.userdata;
|
||||
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
|
||||
}
|
||||
|
||||
if (pes.new_au)
|
||||
{
|
||||
//LOG_NOTICE(HLE, "*** AVC AU detected (pts=0x%llx, dts=0x%llx)", pes.pts, pes.dts);
|
||||
}
|
||||
|
||||
if (es.isfull())
|
||||
const u32 old_size = (u32)es.raw_data.size();
|
||||
if (es.isfull(old_size))
|
||||
{
|
||||
stream = backup;
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
continue;
|
||||
}
|
||||
|
||||
//reconstruction of MPEG2-PS stream for vdec module
|
||||
if ((pes.has_ts && old_size) || old_size >= 0x70000)
|
||||
{
|
||||
// push AU if it becomes too big or the next packet contains ts data
|
||||
es.push_au(old_size, es.last_dts, es.last_pts, stream.userdata, false /* TODO: set correct value */, 0);
|
||||
|
||||
// callback
|
||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||
esMsg->supplementalInfo = stream.userdata;
|
||||
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
|
||||
}
|
||||
|
||||
if (pes.has_ts)
|
||||
{
|
||||
// preserve dts/pts for next AU
|
||||
es.last_dts = pes.dts;
|
||||
es.last_pts = pes.pts;
|
||||
}
|
||||
|
||||
// reconstruction of MPEG2-PS stream for vdec module
|
||||
const u32 size = len + 6 /*- pes.size - 3*/;
|
||||
stream = backup;
|
||||
es.push(stream, len + 6 /*- pes.size - 3*/, pes);
|
||||
es.push(stream, size);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -624,15 +596,30 @@ u32 dmuxOpen(Demuxer* data)
|
|||
{
|
||||
ElementaryStream& es = *task.es.es_ptr;
|
||||
|
||||
if (es.hasdata())
|
||||
const u32 old_size = (u32)es.raw_data.size();
|
||||
if (old_size && (es.fidMajor & 0xf0) == 0xe0)
|
||||
{
|
||||
es.finish(stream);
|
||||
// TODO (it's only for AVC, some ATX data may be lost)
|
||||
while (es.isfull(old_size))
|
||||
{
|
||||
if (Emu.IsStopped() || dmux.is_closed) break;
|
||||
|
||||
std::this_thread::sleep_for(std::chrono::milliseconds(1));
|
||||
}
|
||||
|
||||
es.push_au(old_size, es.last_dts, es.last_pts, stream.userdata, false, 0);
|
||||
|
||||
// callback
|
||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||
esMsg->supplementalInfo = stream.userdata;
|
||||
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
|
||||
}
|
||||
|
||||
if (es.raw_data.size())
|
||||
{
|
||||
cellDmux->Error("dmuxFlushEs: 0x%x bytes lost (es_id=%d)", (u32)es.raw_data.size(), es.id);
|
||||
}
|
||||
|
||||
// callback
|
||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||
|
|
|
@ -358,7 +358,7 @@ struct PesHeader
|
|||
u64 pts;
|
||||
u64 dts;
|
||||
u8 size;
|
||||
bool new_au;
|
||||
bool has_ts;
|
||||
|
||||
PesHeader(DemuxerStream& stream);
|
||||
};
|
||||
|
@ -438,15 +438,12 @@ class ElementaryStream
|
|||
|
||||
SQueue<u32> entries; // AU starting addresses
|
||||
u32 put_count; // number of AU written
|
||||
u32 got_count; // number of AU obtained by GetAu(Ex)
|
||||
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();
|
||||
bool is_full(u32 space);
|
||||
|
||||
public:
|
||||
Demuxer* dmux;
|
||||
|
@ -461,6 +458,13 @@ public:
|
|||
const u32 cbArg;
|
||||
const u32 spec; //addr
|
||||
|
||||
std::vector<u8> raw_data; // demultiplexed data stream (managed by demuxer thread)
|
||||
size_t raw_pos; // should be <= raw_data.size()
|
||||
u64 last_dts;
|
||||
u64 last_pts;
|
||||
|
||||
void push(DemuxerStream& stream, u32 size); // called by demuxer thread (not multithread-safe)
|
||||
|
||||
ElementaryStream(Demuxer* dmux, u32 addr, u32 size, u32 fidMajor, u32 fidMinor, u32 sup1, u32 sup2, vm::ptr<CellDmuxCbEsMsg> cbFunc, u32 cbArg, u32 spec)
|
||||
: dmux(dmux)
|
||||
, memAddr(a128(addr))
|
||||
|
@ -472,29 +476,19 @@ public:
|
|||
, cbFunc(cbFunc)
|
||||
, cbArg(cbArg)
|
||||
, spec(spec)
|
||||
//, first(0)
|
||||
//, peek(0)
|
||||
, put(memAddr)
|
||||
, size(0)
|
||||
, put_count(0)
|
||||
, got_count(0)
|
||||
, released(0)
|
||||
, peek_count(0)
|
||||
, raw_pos(0)
|
||||
, last_dts(0xffffffffffffffffull)
|
||||
, last_pts(0xffffffffffffffffull)
|
||||
{
|
||||
}
|
||||
|
||||
const u32 GetMaxAU() const;
|
||||
bool isfull(u32 space);
|
||||
|
||||
u32 freespace();
|
||||
|
||||
bool hasunseen();
|
||||
|
||||
bool hasdata();
|
||||
|
||||
bool isfull();
|
||||
|
||||
void finish(DemuxerStream& stream);
|
||||
|
||||
void push(DemuxerStream& stream, u32 sz, PesHeader& pes);
|
||||
void push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool rap, u32 specific);
|
||||
|
||||
bool release();
|
||||
|
||||
|
|
|
@ -37,7 +37,10 @@ s64 spursCreateLv2EventQueue(vm::ptr<CellSpurs> spurs, u32& queue_id, vm::ptr<u8
|
|||
return CELL_EAGAIN; // rough
|
||||
}
|
||||
|
||||
assert(spursAttachLv2EventQueue(spurs, queue_id, port, 1, true) == CELL_OK);
|
||||
if (s32 res = spursAttachLv2EventQueue(spurs, queue_id, port, 1, true))
|
||||
{
|
||||
assert(!"spursAttachLv2EventQueue() failed");
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -138,7 +141,10 @@ s64 spursInit(
|
|||
spurs->m.nSpus = nSpus;
|
||||
spurs->m.spuPriority = spuPriority;
|
||||
#ifdef PRX_DEBUG
|
||||
assert(spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1) == CELL_OK);
|
||||
if (s32 res = spu_image_import(spurs->m.spuImg, vm::read32(libsre_rtoc - (isSecond ? 0x7E94 : 0x7E98)), 1))
|
||||
{
|
||||
assert(!"spu_image_import() failed");
|
||||
}
|
||||
#else
|
||||
spurs->m.spuImg.addr = Memory.Alloc(0x40000, 4096);
|
||||
#endif
|
||||
|
@ -492,8 +498,14 @@ s64 spursInit(
|
|||
}
|
||||
}
|
||||
|
||||
assert(lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv") == CELL_OK);
|
||||
assert(lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv") == CELL_OK);
|
||||
if (s32 res = lwmutex_create(spurs->m.mutex, SYS_SYNC_PRIORITY, SYS_SYNC_NOT_RECURSIVE, *(u64*)"_spuPrv"))
|
||||
{
|
||||
assert(!"lwmutex_create() failed");
|
||||
}
|
||||
if (s32 res = lwcond_create(spurs->m.cond, spurs->m.mutex, *(u64*)"_spuPrv"))
|
||||
{
|
||||
assert(!"lwcond_create() failed");
|
||||
}
|
||||
|
||||
spurs->m.flags1 = (flags & SAF_EXIT_IF_NO_WORK ? SF1_EXIT_IF_NO_WORK : 0) | (isSecond ? SF1_IS_SECOND : 0);
|
||||
spurs->m.flagRecv.write_relaxed(0xff);
|
||||
|
@ -504,14 +516,20 @@ s64 spursInit(
|
|||
spurs->m.ppuPriority = ppuPriority;
|
||||
|
||||
u32 queue;
|
||||
assert(spursCreateLv2EventQueue(spurs, queue, vm::ptr<u8>::make(spurs.addr() + 0xc9), 0x2a, *(u64*)"_spuPrv") == CELL_OK);
|
||||
if (s32 res = spursCreateLv2EventQueue(spurs, queue, vm::ptr<u8>::make(spurs.addr() + 0xc9), 0x2a, *(u64*)"_spuPrv"))
|
||||
{
|
||||
assert(!"spursCreateLv2EventQueue() failed");
|
||||
}
|
||||
spurs->m.queue = queue;
|
||||
|
||||
u32 port = event_port_create(0);
|
||||
assert(port && ~port);
|
||||
spurs->m.port = port;
|
||||
|
||||
assert(sys_event_port_connect_local(port, queue) == CELL_OK);
|
||||
if (s32 res = sys_event_port_connect_local(port, queue))
|
||||
{
|
||||
assert(!"sys_event_port_connect_local() failed");
|
||||
}
|
||||
|
||||
name = std::string(prefix, prefixSize);
|
||||
|
||||
|
@ -536,10 +554,16 @@ s64 spursInit(
|
|||
|
||||
if (spurs->m.flags1 & SF1_EXIT_IF_NO_WORK)
|
||||
{
|
||||
assert(sys_lwmutex_lock(spurs->get_lwmutex(), 0) == CELL_OK);
|
||||
if (s32 res = sys_lwmutex_lock(spurs->get_lwmutex(), 0))
|
||||
{
|
||||
assert(!"sys_lwmutex_lock() failed");
|
||||
}
|
||||
if (spurs->m.xD66.read_relaxed())
|
||||
{
|
||||
assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == CELL_OK);
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
else while (true)
|
||||
|
@ -590,28 +614,40 @@ s64 spursInit(
|
|||
spurs->m.xD65.exchange(1);
|
||||
if (spurs->m.xD64.read_relaxed() == 0)
|
||||
{
|
||||
assert(sys_lwcond_wait(spurs->get_lwcond(), 0) == CELL_OK);
|
||||
if (s32 res = sys_lwcond_wait(spurs->get_lwcond(), 0))
|
||||
{
|
||||
assert(!"sys_lwcond_wait() failed");
|
||||
}
|
||||
}
|
||||
spurs->m.xD65.exchange(0);
|
||||
if (spurs->m.xD66.read_relaxed())
|
||||
{
|
||||
assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == CELL_OK);
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == CELL_OK);
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
}
|
||||
|
||||
if (Emu.IsStopped()) continue;
|
||||
|
||||
assert(sys_spu_thread_group_start(spurs->m.spuTG) == CELL_OK);
|
||||
if (s32 res = sys_spu_thread_group_start(spurs->m.spuTG))
|
||||
{
|
||||
assert(!"sys_spu_thread_group_start() failed");
|
||||
}
|
||||
if (s32 res = sys_spu_thread_group_join(spurs->m.spuTG, vm::ptr<u32>::make(0), vm::ptr<u32>::make(0)))
|
||||
{
|
||||
if (res == CELL_ESTAT)
|
||||
{
|
||||
return;
|
||||
}
|
||||
assert(res == CELL_OK);
|
||||
assert(!"sys_spu_thread_group_join() failed");
|
||||
}
|
||||
|
||||
if (Emu.IsStopped()) continue;
|
||||
|
@ -635,7 +671,10 @@ s64 spursInit(
|
|||
// enable exception event handler
|
||||
if (spurs->m.enableEH.compare_and_swap_test(be_t<u32>::make(0), be_t<u32>::make(1)))
|
||||
{
|
||||
assert(sys_spu_thread_group_connect_event(spurs->m.spuTG, spurs->m.queue, SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION) == CELL_OK);
|
||||
if (s32 res = sys_spu_thread_group_connect_event(spurs->m.spuTG, spurs->m.queue, SYS_SPU_THREAD_GROUP_EVENT_EXCEPTION))
|
||||
{
|
||||
assert(!"sys_spu_thread_group_connect_event() failed");
|
||||
}
|
||||
}
|
||||
|
||||
spurs->m.unk22 = 0;
|
||||
|
@ -997,7 +1036,10 @@ s64 spursAttachLv2EventQueue(vm::ptr<CellSpurs> spurs, u32 queue, vm::ptr<u8> po
|
|||
}
|
||||
|
||||
s32 sdk_ver;
|
||||
assert(process_get_sdk_version(process_getpid(), sdk_ver) == CELL_OK);
|
||||
if (s32 res = process_get_sdk_version(process_getpid(), sdk_ver))
|
||||
{
|
||||
assert(!"process_get_sdk_version() failed");
|
||||
}
|
||||
if (sdk_ver == -1) sdk_ver = 0x460000;
|
||||
|
||||
u8 _port = 0x3f;
|
||||
|
@ -1236,9 +1278,18 @@ s64 spursWakeUp(vm::ptr<CellSpurs> spurs)
|
|||
spurs->m.xD64.exchange(1);
|
||||
if (spurs->m.xD65.read_sync())
|
||||
{
|
||||
assert(sys_lwmutex_lock(spurs->get_lwmutex(), 0) == 0);
|
||||
assert(sys_lwcond_signal(spurs->get_lwcond()) == 0);
|
||||
assert(sys_lwmutex_unlock(spurs->get_lwmutex()) == 0);
|
||||
if (s32 res = sys_lwmutex_lock(spurs->get_lwmutex(), 0))
|
||||
{
|
||||
assert(!"sys_lwmutex_lock() failed");
|
||||
}
|
||||
if (s32 res = sys_lwcond_signal(spurs->get_lwcond()))
|
||||
{
|
||||
assert(!"sys_lwcond_signal() failed");
|
||||
}
|
||||
if (s32 res = sys_lwmutex_unlock(spurs->get_lwmutex()))
|
||||
{
|
||||
assert(!"sys_lwmutex_unlock() failed");
|
||||
}
|
||||
}
|
||||
return CELL_OK;
|
||||
}
|
||||
|
|
|
@ -1086,7 +1086,10 @@ s32 syncLFQueueGetPushPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
|
|||
}
|
||||
}
|
||||
|
||||
assert(sys_event_queue_receive(queue->m_eq_id, vm::ptr<sys_event_data>::make(0), 0) == CELL_OK);
|
||||
if (s32 res = sys_event_queue_receive(queue->m_eq_id, vm::ptr<sys_event_data>::make(0), 0))
|
||||
{
|
||||
assert(!"sys_event_queue_receive() failed");
|
||||
}
|
||||
var1 = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1106,7 +1109,7 @@ s32 syncLFQueueGetPushPointer2(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
|
|||
{
|
||||
// TODO
|
||||
//pointer = 0;
|
||||
assert(0);
|
||||
assert(!"syncLFQueueGetPushPointer2()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1268,7 +1271,7 @@ s32 syncLFQueueCompletePushPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer,
|
|||
{
|
||||
// TODO
|
||||
//if (fpSendSignal) return fpSendSignal(0, 0);
|
||||
assert(0);
|
||||
assert(!"syncLFQueueCompletePushPointer2()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1465,7 +1468,10 @@ s32 syncLFQueueGetPopPointer(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32 i
|
|||
}
|
||||
}
|
||||
|
||||
assert(sys_event_queue_receive(queue->m_eq_id, vm::ptr<sys_event_data>::make(0), 0) == CELL_OK);
|
||||
if (s32 res = sys_event_queue_receive(queue->m_eq_id, vm::ptr<sys_event_data>::make(0), 0))
|
||||
{
|
||||
assert(!"sys_event_queue_receive() failed");
|
||||
}
|
||||
var1 = 1;
|
||||
}
|
||||
}
|
||||
|
@ -1485,7 +1491,7 @@ s32 syncLFQueueGetPopPointer2(vm::ptr<CellSyncLFQueue> queue, s32& pointer, u32
|
|||
{
|
||||
// TODO
|
||||
//pointer = 0;
|
||||
assert(0);
|
||||
assert(!"syncLFQueueGetPopPointer2()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1647,7 +1653,7 @@ s32 syncLFQueueCompletePopPointer2(vm::ptr<CellSyncLFQueue> queue, s32 pointer,
|
|||
{
|
||||
// TODO
|
||||
//if (fpSendSignal) fpSendSignal(0, 0);
|
||||
assert(0);
|
||||
assert(!"syncLFQueueCompletePopPointer2()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1906,7 +1912,7 @@ s32 syncLFQueueAttachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncL
|
|||
spus, num, queue);
|
||||
#endif
|
||||
|
||||
assert(!"syncLFQueueAttachLv2EventQueue");
|
||||
assert(!"syncLFQueueAttachLv2EventQueue()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
@ -1924,7 +1930,7 @@ s32 syncLFQueueDetachLv2EventQueue(vm::ptr<u32> spus, u32 num, vm::ptr<CellSyncL
|
|||
spus, num, queue);
|
||||
#endif
|
||||
|
||||
assert(!"syncLFQueueDetachLv2EventQueue");
|
||||
assert(!"syncLFQueueDetachLv2EventQueue()");
|
||||
return CELL_OK;
|
||||
}
|
||||
|
||||
|
|
|
@ -205,7 +205,10 @@ vm::ptr<char> _sys_strcat(vm::ptr<char> dest, vm::ptr<const char> source)
|
|||
{
|
||||
sysPrxForUser->Log("_sys_strcat(dest_addr=0x%x, source_addr=0x%x)", dest.addr(), source.addr());
|
||||
|
||||
assert(strcat(dest.get_ptr(), source.get_ptr()) == dest.get_ptr());
|
||||
if (strcat(dest.get_ptr(), source.get_ptr()) != dest.get_ptr())
|
||||
{
|
||||
assert(!"strcat(): unexpected result");
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -213,7 +216,10 @@ vm::ptr<char> _sys_strncat(vm::ptr<char> dest, vm::ptr<const char> source, u32 l
|
|||
{
|
||||
sysPrxForUser->Log("_sys_strncat(dest_addr=0x%x, source_addr=0x%x, len=%d)", dest.addr(), source.addr(), len);
|
||||
|
||||
assert(strncat(dest.get_ptr(), source.get_ptr(), len) == dest.get_ptr());
|
||||
if (strncat(dest.get_ptr(), source.get_ptr(), len) != dest.get_ptr())
|
||||
{
|
||||
assert(!"strncat(): unexpected result");
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -221,7 +227,10 @@ vm::ptr<char> _sys_strcpy(vm::ptr<char> dest, vm::ptr<const char> source)
|
|||
{
|
||||
sysPrxForUser->Log("_sys_strcpy(dest_addr=0x%x, source_addr=0x%x)", dest.addr(), source.addr());
|
||||
|
||||
assert(strcpy(dest.get_ptr(), source.get_ptr()) == dest.get_ptr());
|
||||
if (strcpy(dest.get_ptr(), source.get_ptr()) != dest.get_ptr())
|
||||
{
|
||||
assert(!"strcpy(): unexpected result");
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
@ -234,7 +243,10 @@ vm::ptr<char> _sys_strncpy(vm::ptr<char> dest, vm::ptr<const char> source, u32 l
|
|||
return vm::ptr<char>::make(0);
|
||||
}
|
||||
|
||||
assert(strncpy(dest.get_ptr(), source.get_ptr(), len) == dest.get_ptr());
|
||||
if (strncpy(dest.get_ptr(), source.get_ptr(), len) != dest.get_ptr())
|
||||
{
|
||||
assert(!"strncpy(): unexpected result");
|
||||
}
|
||||
return dest;
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue