Merge pull request #13659 from shenweip/mpeg-multi_streams

Mpeg:Improves the support of multiple streams video.
This commit is contained in:
Henrik Rydgård 2020-11-15 09:41:39 +01:00 committed by GitHub
commit e01d538707
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 66 additions and 13 deletions

View file

@ -667,6 +667,7 @@ static int sceMpegRegistStream(u32 mpeg, u32 streamType, u32 streamNum)
switch (streamType) {
case MPEG_AVC_STREAM:
ctx->avcRegistered = true;
ctx->mediaengine->addVideoStream(streamNum);
// TODO: Probably incorrect?
ctx->mediaengine->setVideoStream(streamNum);
break;
@ -1495,6 +1496,9 @@ void PostPutAction::run(MipsCall &call) {
// Program signals that it has written data to the ringbuffer and gets a callback ?
static u32 sceMpegRingbufferPut(u32 ringbufferAddr, int numPackets, int available)
{
// Generally, program will call sceMpegRingbufferAvailableSize() before this func.
// Still need to check available?
numPackets = std::min(numPackets, available);
if (numPackets <= 0) {
DEBUG_LOG(ME, "sceMpegRingbufferPut(%08x, %i, %i): no packets to enqueue", ringbufferAddr, numPackets, available);
@ -1518,15 +1522,21 @@ static u32 sceMpegRingbufferPut(u32 ringbufferAddr, int numPackets, int availabl
if (ringbuffer->callback_addr != 0) {
DEBUG_LOG(ME, "sceMpegRingbufferPut(%08x, %i, %i)", ringbufferAddr, numPackets, available);
PostPutAction *action = (PostPutAction *)__KernelCreateAction(actionPostPut);
action->setRingAddr(ringbufferAddr);
// TODO: Should call this multiple times until we get numPackets.
// Call this multiple times until we get numPackets.
// Normally this would be if it did not read enough, but also if available > packets.
// Should ultimately return the TOTAL number of returned packets.
int writeOffset = ringbuffer->packetsWritePos % (s32)ringbuffer->packets;
u32 packetsThisRound = std::min(numPackets, (s32)ringbuffer->packets - writeOffset);
u32 args[3] = {(u32)ringbuffer->data + (u32)writeOffset * 2048, packetsThisRound, (u32)ringbuffer->callback_args};
hleEnqueueCall(ringbuffer->callback_addr, 3, args, action);
u32 packetsThisRound = 0;
while (numPackets) {
PostPutAction *action = (PostPutAction *)__KernelCreateAction(actionPostPut);
action->setRingAddr(ringbufferAddr);
packetsThisRound = std::min(numPackets, (s32)ringbuffer->packets - writeOffset);
numPackets -= packetsThisRound;
u32 args[3] = { (u32)ringbuffer->data + (u32)writeOffset * 2048, packetsThisRound, (u32)ringbuffer->callback_args };
hleEnqueueCall(ringbuffer->callback_addr, 3, args, action);
writeOffset = (writeOffset + packetsThisRound) % (s32)ringbuffer->packets;
}
} else {
ERROR_LOG_REPORT(ME, "sceMpegRingbufferPut: callback_addr zero");
}

View file

@ -132,6 +132,8 @@ MediaEngine::MediaEngine(): m_pdata(0) {
m_videoStream = -1;
m_audioStream = -1;
m_expectedVideoStreams = 0;
m_desWidth = 0;
m_desHeight = 0;
m_decodingsize = 0;
@ -169,7 +171,7 @@ void MediaEngine::closeMedia() {
}
void MediaEngine::DoState(PointerWrap &p) {
auto s = p.Section("MediaEngine", 1, 5);
auto s = p.Section("MediaEngine", 1, 6);
if (!s)
return;
@ -187,6 +189,11 @@ void MediaEngine::DoState(PointerWrap &p) {
} else {
m_mpegheaderReadPos = m_mpegheaderSize;
}
if (s >= 6) {
Do(p, m_expectedVideoStreams);
} else {
m_expectedVideoStreams = 0;
}
Do(p, m_ringbuffersize);
@ -258,20 +265,22 @@ bool MediaEngine::SetupStreams() {
}
// Looking good. Let's add those streams.
const AVCodec *h264_codec = avcodec_find_decoder(AV_CODEC_ID_H264);
int videoStreamNum = -1;
for (int i = 0; i < numStreams; i++) {
const u8 *const currentStreamAddr = m_mpegheader + 0x82 + i * 16;
int streamId = currentStreamAddr[0];
// We only set video streams. We demux the audio stream separately.
if ((streamId & PSMF_VIDEO_STREAM_ID) == PSMF_VIDEO_STREAM_ID) {
AVStream *stream = avformat_new_stream(m_pFormatCtx, h264_codec);
stream->id = 0x00000100 | streamId;
stream->request_probe = 0;
stream->need_parsing = AVSTREAM_PARSE_FULL;
// We could set the width here, but we don't need to.
++videoStreamNum;
addVideoStream(videoStreamNum, streamId);
}
}
// Add the streams to meet the expectation.
for (int i = videoStreamNum + 1; i < m_expectedVideoStreams; i++) {
addVideoStream(i);
}
#endif
return true;
@ -386,6 +395,38 @@ bool MediaEngine::reloadStream()
return loadStream(m_mpegheader, 2048, m_ringbuffersize);
}
bool MediaEngine::addVideoStream(int streamNum, int streamId) {
#ifdef USE_FFMPEG
if (m_pFormatCtx) {
// no need to add an existing stream.
if ((u32)streamNum < m_pFormatCtx->nb_streams)
return true;
const AVCodec *h264_codec = avcodec_find_decoder(AV_CODEC_ID_H264);
if (!h264_codec)
return false;
AVStream *stream = avformat_new_stream(m_pFormatCtx, h264_codec);
if (stream) {
// Reference ISO/IEC 13818-1.
if (streamId == -1)
streamId = PSMF_VIDEO_STREAM_ID | streamNum;
stream->id = 0x00000100 | streamId;
stream->request_probe = 0;
stream->need_parsing = AVSTREAM_PARSE_FULL;
// We could set the width here, but we don't need to.
if (streamNum >= m_expectedVideoStreams) {
++m_expectedVideoStreams;
}
return true;
}
}
#endif
if (streamNum >= m_expectedVideoStreams) {
++m_expectedVideoStreams;
}
return false;
}
int MediaEngine::addStreamData(const u8 *buffer, int addSize) {
int size = addSize;
if (size > 0 && m_pdata) {

View file

@ -59,6 +59,7 @@ public:
void closeMedia();
bool loadStream(const u8 *buffer, int readSize, int RingbufferSize);
bool reloadStream();
bool addVideoStream(int streamNum, int streamId = -1);
// open the mpeg context
bool openContext(bool keepReadPos = false);
void closeContext();
@ -114,6 +115,7 @@ public: // TODO: Very little of this below should be public.
int m_sws_fmt;
u8 *m_buffer;
int m_videoStream;
int m_expectedVideoStreams;
// Used by the demuxer.
int m_audioStream;