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;