mirror of
https://github.com/RPCS3/rpcs3.git
synced 2025-03-16 07:20:59 +00:00
Going to fix demuxer
This commit is contained in:
parent
b942da3f68
commit
8cb8298c03
@ -5,7 +5,7 @@ static const volatile bool sq_no_wait = true;
|
|||||||
template<typename T, u32 SQSize = 666>
|
template<typename T, u32 SQSize = 666>
|
||||||
class SQueue
|
class SQueue
|
||||||
{
|
{
|
||||||
std::mutex m_mutex;
|
mutable std::mutex m_mutex;
|
||||||
u32 m_pos;
|
u32 m_pos;
|
||||||
u32 m_count;
|
u32 m_count;
|
||||||
T m_data[SQSize];
|
T m_data[SQSize];
|
||||||
@ -17,11 +17,16 @@ public:
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 GetSize() const
|
u32 GetSize() const
|
||||||
{
|
{
|
||||||
return SQSize;
|
return SQSize;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool IsFull() const volatile
|
||||||
|
{
|
||||||
|
return m_count == SQSize;
|
||||||
|
}
|
||||||
|
|
||||||
bool Push(const T& data, const volatile bool* do_exit)
|
bool Push(const T& data, const volatile bool* do_exit)
|
||||||
{
|
{
|
||||||
while (true)
|
while (true)
|
||||||
|
@ -97,7 +97,7 @@ next:
|
|||||||
{
|
{
|
||||||
u8 code1 = vm::read8(adec.reader.addr + 2);
|
u8 code1 = vm::read8(adec.reader.addr + 2);
|
||||||
u8 code2 = vm::read8(adec.reader.addr + 3);
|
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.frame_size = ((((u32)code1 & 0x3) << 8) | (u32)code2) * 8 + 8;
|
||||||
adec.sample_rate = at3freq[code1 >> 5];
|
adec.sample_rate = at3freq[code1 >> 5];
|
||||||
|
|
||||||
|
@ -14,7 +14,7 @@ PesHeader::PesHeader(DemuxerStream& stream)
|
|||||||
: pts(0xffffffffffffffffull)
|
: pts(0xffffffffffffffffull)
|
||||||
, dts(0xffffffffffffffffull)
|
, dts(0xffffffffffffffffull)
|
||||||
, size(0)
|
, size(0)
|
||||||
, new_au(false)
|
, has_ts(false)
|
||||||
{
|
{
|
||||||
u16 header;
|
u16 header;
|
||||||
stream.get(header);
|
stream.get(header);
|
||||||
@ -33,13 +33,13 @@ PesHeader::PesHeader(DemuxerStream& stream)
|
|||||||
|
|
||||||
if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only
|
if ((v & 0xF0) == 0x20 && (size - empty) >= 5) // pts only
|
||||||
{
|
{
|
||||||
new_au = true;
|
has_ts = true;
|
||||||
pts = stream.get_ts(v);
|
pts = stream.get_ts(v);
|
||||||
stream.skip(size - empty - 5);
|
stream.skip(size - empty - 5);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
new_au = true;
|
has_ts = true;
|
||||||
if ((v & 0xF0) != 0x30 || (size - empty) < 10)
|
if ((v & 0xF0) != 0x30 || (size - empty) < 10)
|
||||||
{
|
{
|
||||||
cellDmux->Error("PesHeader(): pts not found");
|
cellDmux->Error("PesHeader(): pts not found");
|
||||||
@ -88,110 +88,83 @@ const u32 ElementaryStream::GetMaxAU() const
|
|||||||
return (fidMajor == 0xbd) ? 4096 : 640 * 1024 + 128; // TODO
|
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::hasunseen()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
return peek_count < put_count;
|
return peek_count < put_count;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElementaryStream::hasdata()
|
|
||||||
{
|
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
|
||||||
return size != 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool ElementaryStream::isfull()
|
bool ElementaryStream::isfull()
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
std::lock_guard<std::mutex> lock(m_mutex);
|
||||||
return is_full();
|
return is_full() || entries.IsFull();
|
||||||
}
|
}
|
||||||
|
|
||||||
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;
|
u32 addr;
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lock(m_mutex);
|
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())
|
||||||
|
{
|
||||||
|
cellDmux->Error("es::push_au(): buffer is full");
|
||||||
|
Emu.Pause();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
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;
|
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);
|
u32 new_addr = a128(put + 128 + size);
|
||||||
put = ((new_addr + GetMaxAU()) > (memAddr + memSize))
|
put = ((new_addr + GetMaxAU()) > (memAddr + memSize)) ? memAddr : new_addr;
|
||||||
? memAddr : new_addr;
|
|
||||||
|
|
||||||
size = 0;
|
size = 0;
|
||||||
|
|
||||||
put_count++;
|
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, &sq_no_wait))
|
||||||
{
|
{
|
||||||
cellDmux->Error("es::finish() aborted (no space)");
|
cellDmux->Error("es::push_au() aborted (no space)");
|
||||||
Emu.Pause();
|
Emu.Pause();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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())
|
raw_data.resize(old_size + size);
|
||||||
{
|
|
||||||
cellDmux->Error("es::push(): buffer is full");
|
|
||||||
Emu.Pause();
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
u32 data_addr = put + 128 + size;
|
memcpy(raw_data.data() + old_size, vm::get_ptr<void>(stream.addr), size); // append bytes
|
||||||
size += sz;
|
|
||||||
memcpy(vm::get_ptr<void>(data_addr), vm::get_ptr<void>(stream.addr), sz);
|
|
||||||
stream.skip(sz);
|
|
||||||
|
|
||||||
auto info = vm::ptr<CellDmuxAuInfoEx>::make(put);
|
stream.skip(size);
|
||||||
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;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool ElementaryStream::release()
|
bool ElementaryStream::release()
|
||||||
@ -278,7 +251,7 @@ void ElementaryStream::reset()
|
|||||||
//first = 0;
|
//first = 0;
|
||||||
//peek = 0;
|
//peek = 0;
|
||||||
put = memAddr;
|
put = memAddr;
|
||||||
size = 0;
|
//size = 0;
|
||||||
entries.Clear();
|
entries.Clear();
|
||||||
put_count = 0;
|
put_count = 0;
|
||||||
released = 0;
|
released = 0;
|
||||||
@ -419,14 +392,33 @@ u32 dmuxOpen(Demuxer* data)
|
|||||||
stream.skip(4);
|
stream.skip(4);
|
||||||
len -= 4;
|
len -= 4;
|
||||||
|
|
||||||
es.push(stream, len - pes.size - 3, pes);
|
es.push(stream, len - pes.size - 3);
|
||||||
es.finish(stream);
|
|
||||||
//LOG_NOTICE(HLE, "*** AT3+ AU sent (len=0x%x, pts=0x%llx)", len - pes.size - 3, pes.pts);
|
while (!es.isfull())
|
||||||
|
{
|
||||||
|
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
|
||||||
|
|
||||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
es.push_au(frame_size + 8, pes.dts, pes.pts, stream.userdata, true /* TODO: set correct value */, 0);
|
||||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
|
||||||
esMsg->supplementalInfo = stream.userdata;
|
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||||
es.cbFunc.call(*dmux.dmuxCb, dmux.id, es.id, esMsg, es.cbArg);
|
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
|
else
|
||||||
{
|
{
|
||||||
@ -457,26 +449,6 @@ 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
|
|
||||||
{
|
|
||||||
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())
|
if (es.isfull())
|
||||||
{
|
{
|
||||||
stream = backup;
|
stream = backup;
|
||||||
@ -484,9 +456,28 @@ u32 dmuxOpen(Demuxer* data)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (pes.has_ts && es.raw_data.size())
|
||||||
|
{
|
||||||
|
es.push_au((u32)es.raw_data.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
|
//reconstruction of MPEG2-PS stream for vdec module
|
||||||
|
const u32 size = len + 6 /*- pes.size - 3*/;
|
||||||
stream = backup;
|
stream = backup;
|
||||||
es.push(stream, len + 6 /*- pes.size - 3*/, pes);
|
es.push(stream, size);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -624,9 +615,11 @@ u32 dmuxOpen(Demuxer* data)
|
|||||||
{
|
{
|
||||||
ElementaryStream& es = *task.es.es_ptr;
|
ElementaryStream& es = *task.es.es_ptr;
|
||||||
|
|
||||||
if (es.hasdata())
|
if (es.raw_data.size())
|
||||||
{
|
{
|
||||||
es.finish(stream);
|
// TODO (it's only for AVC, but may cause problems with ATX)
|
||||||
|
es.push_au((u32)es.raw_data.size(), es.last_dts, es.last_pts, stream.userdata, false, 0);
|
||||||
|
|
||||||
// callback
|
// callback
|
||||||
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
auto esMsg = vm::ptr<CellDmuxEsMsg>::make(a128(dmux.memAddr) + (cb_add ^= 16));
|
||||||
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
esMsg->msgType = CELL_DMUX_ES_MSG_TYPE_AU_FOUND;
|
||||||
|
@ -358,7 +358,7 @@ struct PesHeader
|
|||||||
u64 pts;
|
u64 pts;
|
||||||
u64 dts;
|
u64 dts;
|
||||||
u8 size;
|
u8 size;
|
||||||
bool new_au;
|
bool has_ts;
|
||||||
|
|
||||||
PesHeader(DemuxerStream& stream);
|
PesHeader(DemuxerStream& stream);
|
||||||
};
|
};
|
||||||
@ -442,7 +442,7 @@ class ElementaryStream
|
|||||||
u32 peek_count; // number of AU obtained by GetAu(Ex)
|
u32 peek_count; // number of AU obtained by GetAu(Ex)
|
||||||
|
|
||||||
u32 put; // AU that is being written now
|
u32 put; // AU that is being written now
|
||||||
u32 size; // number of bytes written (after 128b header)
|
//u32 size; // number of bytes written (after 128b header)
|
||||||
//u32 first; // AU that will be released
|
//u32 first; // AU that will be released
|
||||||
//u32 peek; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex)
|
//u32 peek; // AU that will be obtained by GetAu(Ex)/PeekAu(Ex)
|
||||||
|
|
||||||
@ -461,6 +461,13 @@ public:
|
|||||||
const u32 cbArg;
|
const u32 cbArg;
|
||||||
const u32 spec; //addr
|
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)
|
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)
|
: dmux(dmux)
|
||||||
, memAddr(a128(addr))
|
, memAddr(a128(addr))
|
||||||
@ -475,26 +482,23 @@ public:
|
|||||||
//, first(0)
|
//, first(0)
|
||||||
//, peek(0)
|
//, peek(0)
|
||||||
, put(memAddr)
|
, put(memAddr)
|
||||||
, size(0)
|
//, size(0)
|
||||||
, put_count(0)
|
, put_count(0)
|
||||||
, released(0)
|
, released(0)
|
||||||
, peek_count(0)
|
, peek_count(0)
|
||||||
|
, raw_pos(0)
|
||||||
|
, last_dts(0xffffffffffffffffull)
|
||||||
|
, last_pts(0xffffffffffffffffull)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
const u32 GetMaxAU() const;
|
const u32 GetMaxAU() const;
|
||||||
|
|
||||||
u32 freespace();
|
|
||||||
|
|
||||||
bool hasunseen();
|
bool hasunseen();
|
||||||
|
|
||||||
bool hasdata();
|
|
||||||
|
|
||||||
bool isfull();
|
bool isfull();
|
||||||
|
|
||||||
void finish(DemuxerStream& stream);
|
void push_au(u32 size, u64 dts, u64 pts, u64 userdata, bool rap, u32 specific);
|
||||||
|
|
||||||
void push(DemuxerStream& stream, u32 sz, PesHeader& pes);
|
|
||||||
|
|
||||||
bool release();
|
bool release();
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user