Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Mpeg:Improves the support of multiple streams video. #13659

Merged
merged 2 commits into from
Nov 15, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
22 changes: 16 additions & 6 deletions Core/HLE/sceMpeg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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?
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

See #978. I think we should test this, though, for the correct behavior. Ideally we should replicate (as far as is visible) what firmware does.

-[Unknown]


numPackets = std::min(numPackets, available);
if (numPackets <= 0) {
DEBUG_LOG(ME, "sceMpegRingbufferPut(%08x, %i, %i): no packets to enqueue", ringbufferAddr, numPackets, available);
Expand All @@ -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");
}
Expand Down
55 changes: 48 additions & 7 deletions Core/HW/MediaEngine.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;

Expand All @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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) {
Expand Down
2 changes: 2 additions & 0 deletions Core/HW/MediaEngine.h
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ class MediaEngine
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();
Expand Down Expand Up @@ -114,6 +115,7 @@ class MediaEngine
int m_sws_fmt;
u8 *m_buffer;
int m_videoStream;
int m_expectedVideoStreams;

// Used by the demuxer.
int m_audioStream;
Expand Down