Antoine pointed out that the ffmpeg-4.4v1 breaks ppsspp. There is a patch which merge the ffmpeg bits from upstream.
bin/PPSSPPSDL starts fine, could someone confirm that it works? Rafael Index: patches/patch-Core_HW_MediaEngine_cpp =================================================================== RCS file: patches/patch-Core_HW_MediaEngine_cpp diff -N patches/patch-Core_HW_MediaEngine_cpp --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-Core_HW_MediaEngine_cpp 1 May 2021 19:55:06 -0000 @@ -0,0 +1,225 @@ +$OpenBSD$ + +Fix build with ffmpeg-4.4 from upstream + +Index: Core/HW/MediaEngine.cpp +--- Core/HW/MediaEngine.cpp.orig ++++ Core/HW/MediaEngine.cpp +@@ -131,6 +131,7 @@ MediaEngine::MediaEngine(): m_pdata(0) { + m_videoStream = -1; + m_audioStream = -1; + ++ m_expectedVideoStreams = 0; + m_desWidth = 0; + m_desHeight = 0; + m_decodingsize = 0; +@@ -186,6 +187,11 @@ void MediaEngine::DoState(PointerWrap &p) { + } else { + m_mpegheaderReadPos = m_mpegheaderSize; + } ++ if (s >= 6) { ++ p.Do(m_expectedVideoStreams); ++ } else { ++ m_expectedVideoStreams = 0; ++ } + + p.Do(m_ringbuffersize); + +@@ -257,21 +263,21 @@ 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; + } +@@ -304,8 +310,10 @@ bool MediaEngine::openContext(bool keepReadPos) { + av_dict_free(&open_opt); + + if (!SetupStreams()) { +- // Fallback to old behavior. +- if (avformat_find_stream_info(m_pFormatCtx, NULL) < 0) { ++ // Fallback to old behavior. Reads too much and corrupts when game doesn't read fast enough. ++ // SetupStreams sometimes work for newer FFmpeg 3.1+ now, but sometimes framerate is missing. ++ WARN_LOG_REPORT_ONCE(setupStreams, ME, "Failed to read valid video stream data from header"); ++ if (avformat_find_stream_info(m_pFormatCtx, nullptr) < 0) { + closeContext(); + return false; + } +@@ -318,8 +326,14 @@ bool MediaEngine::openContext(bool keepReadPos) { + + if (m_videoStream == -1) { + // Find the first video stream +- for(int i = 0; i < (int)m_pFormatCtx->nb_streams; i++) { +- if(m_pFormatCtx->streams[i]->codec->codec_type == AVMEDIA_TYPE_VIDEO) { ++ for (int i = 0; i < (int)m_pFormatCtx->nb_streams; i++) { ++ const AVStream *s = m_pFormatCtx->streams[i]; ++#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) ++ AVMediaType type = s->codecpar->codec_type; ++#else ++ AVMediaType type = s->codec->codec_type; ++#endif ++ if (type == AVMEDIA_TYPE_VIDEO) { + m_videoStream = i; + break; + } +@@ -351,8 +365,13 @@ void MediaEngine::closeContext() + av_free(m_pIOContext->buffer); + if (m_pIOContext) + av_free(m_pIOContext); +- for (auto it = m_pCodecCtxs.begin(), end = m_pCodecCtxs.end(); it != end; ++it) +- avcodec_close(it->second); ++ for (auto it : m_pCodecCtxs) { ++#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) ++ avcodec_free_context(&it.second); ++#else ++ avcodec_close(it.second); ++#endif ++ } + m_pCodecCtxs.clear(); + if (m_pFormatCtx) + avformat_close_input(&m_pFormatCtx); +@@ -385,6 +404,42 @@ 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; ++#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) ++ stream->codecpar->codec_type = AVMEDIA_TYPE_VIDEO; ++ stream->codecpar->codec_id = AV_CODEC_ID_H264; ++#else ++ stream->request_probe = 0; ++#endif ++ 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) { +@@ -454,22 +509,31 @@ bool MediaEngine::setVideoStream(int streamNum, bool f + if ((u32)streamNum >= m_pFormatCtx->nb_streams) { + return false; + } +- AVCodecContext *m_pCodecCtx = m_pFormatCtx->streams[streamNum]->codec; +-#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57,33,100) +- AVCodecParameters *m_pCodecPar = m_pFormatCtx->streams[streamNum]->codecpar; + +- // Update from deprecated public codec context +- if (avcodec_parameters_from_context(m_pCodecPar, m_pCodecCtx) < 0) { ++ AVStream *stream = m_pFormatCtx->streams[streamNum]; ++#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(57, 33, 100) ++ AVCodec *pCodec = avcodec_find_decoder(stream->codecpar->codec_id); ++ if (!pCodec) { ++ WARN_LOG_REPORT(ME, "Could not find decoder for %d", (int)stream->codecpar->codec_id); + return false; + } +-#endif +- ++ AVCodecContext *m_pCodecCtx = avcodec_alloc_context3(pCodec); ++ int paramResult = avcodec_parameters_to_context(m_pCodecCtx, stream->codecpar); ++ if (paramResult < 0) { ++ WARN_LOG_REPORT(ME, "Failed to prepare context parameters: %08x", paramResult); ++ return false; ++ } ++#else ++ AVCodecContext *m_pCodecCtx = stream->codec; + // Find the decoder for the video stream + AVCodec *pCodec = avcodec_find_decoder(m_pCodecCtx->codec_id); + if (pCodec == nullptr) { + return false; + } ++#endif + ++ m_pCodecCtx->flags |= AV_CODEC_FLAG_OUTPUT_CORRUPT | AV_CODEC_FLAG_LOW_DELAY; ++ + AVDictionary *opt = nullptr; + // Allow ffmpeg to use any number of threads it wants. Without this, it doesn't use threads. + av_dict_set(&opt, "threads", "0", 0); +@@ -609,7 +673,22 @@ bool MediaEngine::stepVideo(int videoPixelMode, bool s + av_free_packet(&packet); + #endif + ++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101) ++ if (packet.size != 0) ++ avcodec_send_packet(m_pCodecCtx, &packet); ++ int result = avcodec_receive_frame(m_pCodecCtx, m_pFrame); ++ if (result == 0) { ++ result = m_pFrame->pkt_size; ++ frameFinished = 1; ++ } else if (result == AVERROR(EAGAIN)) { ++ result = 0; ++ frameFinished = 0; ++ } else { ++ frameFinished = 0; ++ } ++#else + int result = avcodec_decode_video2(m_pCodecCtx, m_pFrame, &frameFinished, &packet); ++#endif + if (frameFinished) { + if (!m_pFrameRGB) { + setVideoDim(); +@@ -624,10 +703,13 @@ bool MediaEngine::stepVideo(int videoPixelMode, bool s + m_pCodecCtx->height, m_pFrameRGB->data, m_pFrameRGB->linesize); + } + +- if (av_frame_get_best_effort_timestamp(m_pFrame) != AV_NOPTS_VALUE) +- m_videopts = av_frame_get_best_effort_timestamp(m_pFrame) + av_frame_get_pkt_duration(m_pFrame) - m_firstTimeStamp; +- else +- m_videopts += av_frame_get_pkt_duration(m_pFrame); ++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 58, 100) ++ int64_t bestPts = m_pFrame->best_effort_timestamp; ++ int64_t ptsDuration = m_pFrame->pkt_duration; ++#else ++ int64_t bestPts = av_frame_get_best_effort_timestamp(m_pFrame); ++ int64_t ptsDuration = av_frame_get_pkt_duration(m_pFrame); ++#endif + bGetFrame = true; + } + if (result <= 0 && dataEnd) { Index: patches/patch-Core_HW_MediaEngine_h =================================================================== RCS file: patches/patch-Core_HW_MediaEngine_h diff -N patches/patch-Core_HW_MediaEngine_h --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ patches/patch-Core_HW_MediaEngine_h 1 May 2021 19:55:06 -0000 @@ -0,0 +1,23 @@ +$OpenBSD$ + +Fix build with ffmpeg-4.4 from upstream + +Index: Core/HW/MediaEngine.h +--- Core/HW/MediaEngine.h.orig ++++ Core/HW/MediaEngine.h +@@ -59,6 +59,7 @@ class MediaEngine (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 @@ class MediaEngine (public) + int m_sws_fmt; + u8 *m_buffer; + int m_videoStream; ++ int m_expectedVideoStreams; + + // Used by the demuxer. + int m_audioStream;