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;

Reply via email to