commit 3edeaf3cfbf2543b9389700c67f4a49656d178c0
Author: Antonio T <sagitter(a)fedoraproject.org>
Date: Sat Feb 20 19:55:46 2021 +0100
Unbundle FFmpeg (upstream bug #13849)
ppsspp-upstream_bug_14176.patch | 733 ++++++++++++++++++++++++++++++++++++++++
ppsspp.spec | 17 +-
2 files changed, 747 insertions(+), 3 deletions(-)
---
diff --git a/ppsspp-upstream_bug_14176.patch b/ppsspp-upstream_bug_14176.patch
new file mode 100644
index 0000000..3276a9d
--- /dev/null
+++ b/ppsspp-upstream_bug_14176.patch
@@ -0,0 +1,733 @@
+From 2362d71d70adb8bf99e960b78a04d2ead4c8db57 Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Tue, 16 Feb 2021 00:03:56 -0800
+Subject: [PATCH 1/9] Mpeg: Remove deprecated codec register calls.
+
+---
+ Core/AVIDump.cpp | 2 ++
+ Core/HLE/sceAtrac.cpp | 4 ++++
+ Core/HLE/sceMpeg.cpp | 4 ++++
+ Core/HW/SimpleAudioDec.cpp | 4 ++++
+ 4 files changed, 14 insertions(+)
+
+diff --git a/Core/AVIDump.cpp b/Core/AVIDump.cpp
+index 19cbcf1227..4e7d7f40ec 100644
+--- a/Core/AVIDump.cpp
++++ b/Core/AVIDump.cpp
+@@ -65,7 +65,9 @@ static void InitAVCodec() {
+ static bool first_run = true;
+ if (first_run) {
+ #ifdef USE_FFMPEG
++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 12, 100)
+ av_register_all();
++#endif
+ #endif
+ first_run = false;
+ }
+diff --git a/Core/HLE/sceAtrac.cpp b/Core/HLE/sceAtrac.cpp
+index bdaeea8b98..1c6a1fb664 100644
+--- a/Core/HLE/sceAtrac.cpp
++++ b/Core/HLE/sceAtrac.cpp
+@@ -636,8 +636,12 @@ void __AtracInit() {
+ atracIDTypes[5] = 0;
+
+ #ifdef USE_FFMPEG
++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 18, 100)
+ avcodec_register_all();
++#endif
++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 12, 100)
+ av_register_all();
++#endif
+ #endif // USE_FFMPEG
+ }
+
+diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp
+index b98f57d7b4..f2dbb8a0d0 100644
+--- a/Core/HLE/sceMpeg.cpp
++++ b/Core/HLE/sceMpeg.cpp
+@@ -393,9 +393,13 @@ void __MpegInit() {
+ actionPostPut = __KernelRegisterActionType(PostPutAction::Create);
+
+ #ifdef USE_FFMPEG
++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 18, 100)
+ avcodec_register_all();
++#endif
++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 12, 100)
+ av_register_all();
+ #endif
++#endif
+ }
+
+ void __MpegDoState(PointerWrap &p) {
+diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp
+index 2e9ac873d4..12bac4ba18 100644
+--- a/Core/HW/SimpleAudioDec.cpp
++++ b/Core/HW/SimpleAudioDec.cpp
+@@ -62,8 +62,12 @@ SimpleAudio::SimpleAudio(int audioType, int sample_rate, int
channels)
+
+ void SimpleAudio::Init() {
+ #ifdef USE_FFMPEG
++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 18, 100)
+ avcodec_register_all();
++#endif
++#if LIBAVFORMAT_VERSION_INT < AV_VERSION_INT(58, 12, 100)
+ av_register_all();
++#endif
+ InitFFmpeg();
+
+ frame_ = av_frame_alloc();
+
+From 26eca0ba3dc087daeb4da54267ae8fc459e988b4 Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Tue, 16 Feb 2021 00:12:27 -0800
+Subject: [PATCH 2/9] AVI: Avoid deprecated ffmpeg context usage.
+
+---
+ Core/AVIDump.cpp | 121 +++++++++++++++++++++++++++--------------------
+ 1 file changed, 70 insertions(+), 51 deletions(-)
+
+diff --git a/Core/AVIDump.cpp b/Core/AVIDump.cpp
+index 4e7d7f40ec..898288b0f1 100644
+--- a/Core/AVIDump.cpp
++++ b/Core/AVIDump.cpp
+@@ -44,11 +44,12 @@ extern "C" {
+ #define av_frame_free avcodec_free_frame
+ #endif
+
+-static AVFormatContext* s_format_context = nullptr;
+-static AVStream* s_stream = nullptr;
+-static AVFrame* s_src_frame = nullptr;
+-static AVFrame* s_scaled_frame = nullptr;
+-static SwsContext* s_sws_context = nullptr;
++static AVFormatContext *s_format_context = nullptr;
++static AVCodecContext *s_codec_context = nullptr;
++static AVStream *s_stream = nullptr;
++static AVFrame *s_src_frame = nullptr;
++static AVFrame *s_scaled_frame = nullptr;
++static SwsContext *s_sws_context = nullptr;
+
+ #endif
+
+@@ -89,51 +90,70 @@ bool AVIDump::Start(int w, int h)
+
+ bool AVIDump::CreateAVI() {
+ #ifdef USE_FFMPEG
+- AVCodec* codec = nullptr;
++ AVCodec *codec = nullptr;
+
+ // Use gameID_EmulatedTimestamp for filename
+ std::string discID = g_paramSFO.GetDiscID();
+ std::string video_file_name = StringFromFormat("%s%s_%s.avi",
GetSysDirectory(DIRECTORY_VIDEO).c_str(), discID.c_str(),
KernelTimeNowFormatted().c_str()).c_str();
+
+ s_format_context = avformat_alloc_context();
+- std::stringstream s_file_index_str;
+- s_file_index_str << video_file_name;
+
+- snprintf(s_format_context->filename, sizeof(s_format_context->filename),
"%s", s_file_index_str.str().c_str());
+- INFO_LOG(COMMON, "Recording Video to: %s", s_format_context->filename);
++#if LIBAVFORMAT_VERSION_INT >= AV_VERSION_INT(58, 7, 0)
++ char *filename = av_strdup(video_file_name.c_str());
++ // Freed when the context is freed.
++ s_format_context->url = filename;
++#else
++ const char *filename = s_format_context->filename;
++ snprintf(s_format_context->filename, sizeof(s_format_context->filename),
"%s", video_file_name.c_str());
++#endif
++ INFO_LOG(COMMON, "Recording Video to: %s", filename);
++
+ // Make sure that the path exists
+ if (!File::Exists(GetSysDirectory(DIRECTORY_VIDEO)))
+ File::CreateDir(GetSysDirectory(DIRECTORY_VIDEO));
+
+- if (File::Exists(s_format_context->filename))
+- File::Delete(s_format_context->filename);
++ if (File::Exists(filename))
++ File::Delete(filename);
+
+- if (!(s_format_context->oformat = av_guess_format("avi", nullptr,
nullptr)) || !(s_stream = avformat_new_stream(s_format_context, codec)))
+- {
++ s_format_context->oformat = av_guess_format("avi", nullptr, nullptr);
++ if (!s_format_context->oformat)
++ return false;
++ s_stream = avformat_new_stream(s_format_context, codec);
++ if (!s_stream)
+ return false;
+- }
+
+- s_stream->codec->codec_id = g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 :
s_format_context->oformat->video_codec;
++#if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(57, 48, 101)
++ s_codec_context = s_stream->codec;
++#else
++ s_codec_context = avcodec_alloc_context3(codec);
++#endif
++ s_codec_context->codec_id = g_Config.bUseFFV1 ? AV_CODEC_ID_FFV1 :
s_format_context->oformat->video_codec;
+ if (!g_Config.bUseFFV1)
+- s_stream->codec->codec_tag = MKTAG('X', 'V', 'I',
'D'); // Force XVID FourCC for better compatibility
+- s_stream->codec->codec_type = AVMEDIA_TYPE_VIDEO;
+- s_stream->codec->bit_rate = 400000;
+- s_stream->codec->width = s_width;
+- s_stream->codec->height = s_height;
+- s_stream->codec->time_base.num = 1001;
+- s_stream->codec->time_base.den = 60000;
+- s_stream->codec->gop_size = 12;
+- s_stream->codec->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA :
AV_PIX_FMT_YUV420P;
+-
+- if (!(codec = avcodec_find_encoder(s_stream->codec->codec_id)) ||
(avcodec_open2(s_stream->codec, codec, nullptr) < 0))
+- {
++ s_codec_context->codec_tag = MKTAG('X', 'V', 'I',
'D'); // Force XVID FourCC for better compatibility
++ s_codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
++ s_codec_context->bit_rate = 400000;
++ s_codec_context->width = s_width;
++ s_codec_context->height = s_height;
++ s_codec_context->time_base.num = 1001;
++ s_codec_context->time_base.den = 60000;
++ s_codec_context->gop_size = 12;
++ s_codec_context->pix_fmt = g_Config.bUseFFV1 ? AV_PIX_FMT_BGRA :
AV_PIX_FMT_YUV420P;
++
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ if (avcodec_parameters_from_context(s_stream->codecpar, s_codec_context) < 0)
++ return false;
++#endif
++
++ codec = avcodec_find_encoder(s_codec_context->codec_id);
++ if (!codec)
++ return false;
++ if (avcodec_open2(s_codec_context, codec, nullptr) < 0)
+ return false;
+- }
+
+ s_src_frame = av_frame_alloc();
+ s_scaled_frame = av_frame_alloc();
+
+- s_scaled_frame->format = s_stream->codec->pix_fmt;
++ s_scaled_frame->format = s_codec_context->pix_fmt;
+ s_scaled_frame->width = s_width;
+ s_scaled_frame->height = s_height;
+
+@@ -141,14 +161,13 @@ bool AVIDump::CreateAVI() {
+ if (av_frame_get_buffer(s_scaled_frame, 1))
+ return false;
+ #else
+- if (avcodec_default_get_buffer(s_stream->codec, s_scaled_frame))
++ if (avcodec_default_get_buffer(s_codec_context, s_scaled_frame))
+ return false;
+ #endif
+
+- NOTICE_LOG(G3D, "Opening file %s for dumping",
s_format_context->filename);
+- if (avio_open(&s_format_context->pb, s_format_context->filename,
AVIO_FLAG_WRITE) < 0 || avformat_write_header(s_format_context, nullptr))
+- {
+- WARN_LOG(G3D, "Could not open %s", s_format_context->filename);
++ NOTICE_LOG(G3D, "Opening file %s for dumping", filename);
++ if (avio_open(&s_format_context->pb, filename, AVIO_FLAG_WRITE) < 0 ||
avformat_write_header(s_format_context, nullptr)) {
++ WARN_LOG(G3D, "Could not open %s", filename);
+ return false;
+ }
+
+@@ -194,12 +213,12 @@ void AVIDump::AddFrame()
+ s_src_frame->height = s_height;
+
+ // Convert image from BGR24 to desired pixel format, and scale to initial width and
height
+- if ((s_sws_context = sws_getCachedContext(s_sws_context, w, h, AV_PIX_FMT_RGB24,
s_width, s_height, s_stream->codec->pix_fmt, SWS_BICUBIC, nullptr, nullptr,
nullptr)))
++ if ((s_sws_context = sws_getCachedContext(s_sws_context, w, h, AV_PIX_FMT_RGB24,
s_width, s_height, s_codec_context->pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr)))
+ {
+ sws_scale(s_sws_context, s_src_frame->data, s_src_frame->linesize, 0, h,
s_scaled_frame->data, s_scaled_frame->linesize);
+ }
+
+- s_scaled_frame->format = s_stream->codec->pix_fmt;
++ s_scaled_frame->format = s_codec_context->pix_fmt;
+ s_scaled_frame->width = s_width;
+ s_scaled_frame->height = s_height;
+
+@@ -207,20 +226,20 @@ void AVIDump::AddFrame()
+ AVPacket pkt;
+ PreparePacket(&pkt);
+ int got_packet;
+- int error = avcodec_encode_video2(s_stream->codec, &pkt, s_scaled_frame,
&got_packet);
++ int error = avcodec_encode_video2(s_codec_context, &pkt, s_scaled_frame,
&got_packet);
+ while (!error && got_packet)
+ {
+ // Write the compressed frame in the media file.
+ if (pkt.pts != (s64)AV_NOPTS_VALUE)
+ {
+- pkt.pts = av_rescale_q(pkt.pts, s_stream->codec->time_base,
s_stream->time_base);
++ pkt.pts = av_rescale_q(pkt.pts, s_codec_context->time_base,
s_stream->time_base);
+ }
+ if (pkt.dts != (s64)AV_NOPTS_VALUE)
+ {
+- pkt.dts = av_rescale_q(pkt.dts, s_stream->codec->time_base,
s_stream->time_base);
++ pkt.dts = av_rescale_q(pkt.dts, s_codec_context->time_base,
s_stream->time_base);
+ }
+ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 60, 100)
+- if (s_stream->codec->coded_frame->key_frame)
++ if (s_codec_context->coded_frame->key_frame)
+ pkt.flags |= AV_PKT_FLAG_KEY;
+ #endif
+ pkt.stream_index = s_stream->index;
+@@ -228,7 +247,7 @@ void AVIDump::AddFrame()
+
+ // Handle delayed frames.
+ PreparePacket(&pkt);
+- error = avcodec_encode_video2(s_stream->codec, &pkt, nullptr,
&got_packet);
++ error = avcodec_encode_video2(s_codec_context, &pkt, nullptr, &got_packet);
+ }
+ if (error)
+ ERROR_LOG(G3D, "Error while encoding video: %d", error);
+@@ -248,18 +267,18 @@ void AVIDump::Stop() {
+
+ void AVIDump::CloseFile() {
+ #ifdef USE_FFMPEG
+-
+- if (s_stream)
+- {
+- if (s_stream->codec)
+- {
++ if (s_codec_context) {
+ #if LIBAVCODEC_VERSION_MAJOR < 55
+- avcodec_default_release_buffer(s_stream->codec, s_src_frame);
++ avcodec_default_release_buffer(s_codec_context, s_src_frame);
++#endif
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ avcodec_free_context(&s_codec_context);
++#else
++ avcodec_close(s_codec_context);
++ s_codec_context = nullptr;
+ #endif
+- avcodec_close(s_stream->codec);
+- }
+- av_freep(&s_stream);
+ }
++ av_freep(&s_stream);
+
+ av_frame_free(&s_src_frame);
+ av_frame_free(&s_scaled_frame);
+
+From 6656c8a533ee2816defe4522e071fe2f1e2718b4 Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Tue, 16 Feb 2021 00:46:42 -0800
+Subject: [PATCH 3/9] AVI: Update to latest FFmpeg packet pump.
+
+---
+ Core/AVIDump.cpp | 37 ++++++++++++++++++++++++++-----------
+ 1 file changed, 26 insertions(+), 11 deletions(-)
+
+diff --git a/Core/AVIDump.cpp b/Core/AVIDump.cpp
+index 898288b0f1..1e3f1803d5 100644
+--- a/Core/AVIDump.cpp
++++ b/Core/AVIDump.cpp
+@@ -187,8 +187,7 @@ static void PreparePacket(AVPacket* pkt) {
+
+ #endif
+
+-void AVIDump::AddFrame()
+-{
++void AVIDump::AddFrame() {
+ u32 w = 0;
+ u32 h = 0;
+ if (g_Config.bDumpVideoOutput) {
+@@ -213,8 +212,7 @@ void AVIDump::AddFrame()
+ s_src_frame->height = s_height;
+
+ // Convert image from BGR24 to desired pixel format, and scale to initial width and
height
+- if ((s_sws_context = sws_getCachedContext(s_sws_context, w, h, AV_PIX_FMT_RGB24,
s_width, s_height, s_codec_context->pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr)))
+- {
++ if ((s_sws_context = sws_getCachedContext(s_sws_context, w, h, AV_PIX_FMT_RGB24,
s_width, s_height, s_codec_context->pix_fmt, SWS_BICUBIC, nullptr, nullptr, nullptr)))
{
+ sws_scale(s_sws_context, s_src_frame->data, s_src_frame->linesize, 0, h,
s_scaled_frame->data, s_scaled_frame->linesize);
+ }
+
+@@ -225,17 +223,22 @@ void AVIDump::AddFrame()
+ // Encode and write the image.
+ AVPacket pkt;
+ PreparePacket(&pkt);
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ int error = avcodec_send_frame(s_codec_context, s_scaled_frame);
++ int got_packet = 0;
++ if (avcodec_receive_packet(s_codec_context, &pkt) >= 0) {
++ got_packet = 1;
++ }
++#else
+ int got_packet;
+ int error = avcodec_encode_video2(s_codec_context, &pkt, s_scaled_frame,
&got_packet);
+- while (!error && got_packet)
+- {
++#endif
++ while (error >= 0 && got_packet) {
+ // Write the compressed frame in the media file.
+- if (pkt.pts != (s64)AV_NOPTS_VALUE)
+- {
++ if (pkt.pts != (s64)AV_NOPTS_VALUE) {
+ pkt.pts = av_rescale_q(pkt.pts, s_codec_context->time_base,
s_stream->time_base);
+ }
+- if (pkt.dts != (s64)AV_NOPTS_VALUE)
+- {
++ if (pkt.dts != (s64)AV_NOPTS_VALUE) {
+ pkt.dts = av_rescale_q(pkt.dts, s_codec_context->time_base,
s_stream->time_base);
+ }
+ #if LIBAVCODEC_VERSION_INT < AV_VERSION_INT(56, 60, 100)
+@@ -246,11 +249,23 @@ void AVIDump::AddFrame()
+ av_interleaved_write_frame(s_format_context, &pkt);
+
+ // Handle delayed frames.
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ av_packet_unref(&pkt);
++ error = avcodec_receive_packet(s_codec_context, &pkt);
++ got_packet = error >= 0 ? 1 : 0;
++#else
+ PreparePacket(&pkt);
+ error = avcodec_encode_video2(s_codec_context, &pkt, nullptr, &got_packet);
++#endif
+ }
+- if (error)
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ av_packet_unref(&pkt);
++ if (error < 0 && error != AVERROR(EAGAIN) && error != AVERROR_EOF)
+ ERROR_LOG(G3D, "Error while encoding video: %d", error);
++#else
++ if (error < 0)
++ ERROR_LOG(G3D, "Error while encoding video: %d", error);
++#endif
+ #endif
+ delete[] flipbuffer;
+ }
+
+From 2b2dae60d316b321e084eac7e0bb96d682e4ea37 Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Wed, 17 Feb 2021 22:28:32 -0800
+Subject: [PATCH 4/9] Mpeg: Use direct pts value checks in newer FFmpeg.
+
+---
+ Core/HLE/sceMpeg.cpp | 13 ++++++++++---
+ Core/HW/MediaEngine.cpp | 13 ++++++++++---
+ 2 files changed, 20 insertions(+), 6 deletions(-)
+
+diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp
+index f2dbb8a0d0..4c4a4b0e59 100644
+--- a/Core/HLE/sceMpeg.cpp
++++ b/Core/HLE/sceMpeg.cpp
+@@ -1023,10 +1023,17 @@ static bool decodePmpVideo(PSPPointer<SceMpegRingBuffer>
ringbuffer, u32 pmpctxA
+ sws_freeContext(img_convert_ctx);
+
+ // update timestamp
+- if (av_frame_get_best_effort_timestamp(mediaengine->m_pFrame) != AV_NOPTS_VALUE)
+- mediaengine->m_videopts =
av_frame_get_best_effort_timestamp(mediaengine->m_pFrame) +
av_frame_get_pkt_duration(mediaengine->m_pFrame) - mediaengine->m_firstTimeStamp;
++#if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(55, 58, 100)
++ int64_t bestPts = mediaengine->m_pFrame->best_effort_timestamp;
++ int64_t ptsDuration = mediaengine->m_pFrame->pkt_duration;
++#else
++ int64_t bestPts = av_frame_get_best_effort_timestamp(mediaengine->m_pFrame);
++ int64_t ptsDuration = av_frame_get_pkt_duration(mediaengine->m_pFrame);
++#endif
++ if (bestPts != AV_NOPTS_VALUE)
++ mediaengine->m_videopts = bestPts + ptsDuration -
mediaengine->m_firstTimeStamp;
+ else
+- mediaengine->m_videopts += av_frame_get_pkt_duration(mediaengine->m_pFrame);
++ mediaengine->m_videopts += ptsDuration;
+
+ // push the decoded frame into pmp_queue
+ pmp_queue.push_back(pFrameRGB);
+diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp
+index 0a1e50f527..2da0792edf 100644
+--- a/Core/HW/MediaEngine.cpp
++++ b/Core/HW/MediaEngine.cpp
+@@ -666,10 +666,17 @@ bool MediaEngine::stepVideo(int videoPixelMode, bool skipFrame) {
+ 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;
++#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
++ if (bestPts != AV_NOPTS_VALUE)
++ m_videopts = bestPts + ptsDuration - m_firstTimeStamp;
+ else
+- m_videopts += av_frame_get_pkt_duration(m_pFrame);
++ m_videopts += ptsDuration;
+ bGetFrame = true;
+ }
+ if (result <= 0 && dataEnd) {
+
+From b19e39efb0caf044ce93ceac03e83343a1eaf00e Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Wed, 17 Feb 2021 23:30:33 -0800
+Subject: [PATCH 5/9] Audiocodec: Update to latest FFmpeg packet pump.
+
+---
+ Core/HW/SimpleAudioDec.cpp | 18 ++++++++++++++++++
+ 1 file changed, 18 insertions(+)
+
+diff --git a/Core/HW/SimpleAudioDec.cpp b/Core/HW/SimpleAudioDec.cpp
+index 12bac4ba18..990d6f233b 100644
+--- a/Core/HW/SimpleAudioDec.cpp
++++ b/Core/HW/SimpleAudioDec.cpp
+@@ -192,7 +192,25 @@ bool SimpleAudio::Decode(void *inbuf, int inbytes, uint8_t *outbuf,
int *outbyte
+
+ *outbytes = 0;
+ srcPos = 0;
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ if (inbytes != 0) {
++ int err = avcodec_send_packet(codecCtx_, &packet);
++ if (err < 0) {
++ ERROR_LOG(ME, "Error sending audio frame to decoder (%d bytes): %d (%08x)",
inbytes, err, err);
++ return false;
++ }
++ }
++ int err = avcodec_receive_frame(codecCtx_, frame_);
++ int len = 0;
++ if (err >= 0) {
++ len = frame_->pkt_size;
++ got_frame = 1;
++ } else if (err != AVERROR(EAGAIN)) {
++ len = err;
++ }
++#else
+ int len = avcodec_decode_audio4(codecCtx_, frame_, &got_frame, &packet);
++#endif
+ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
+ av_packet_unref(&packet);
+ #else
+
+From e5849d109dc25ecf8874f7bb4e0079a8dbc6d4db Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Thu, 18 Feb 2021 00:04:58 -0800
+Subject: [PATCH 6/9] Mpeg: Correct stream detection in newer FFmpeg.
+
+---
+ Core/HW/MediaEngine.cpp | 50 +++++++++++++++++++++++++++++------------
+ 1 file changed, 36 insertions(+), 14 deletions(-)
+
+diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp
+index 2da0792edf..7d3ccee417 100644
+--- a/Core/HW/MediaEngine.cpp
++++ b/Core/HW/MediaEngine.cpp
+@@ -280,9 +280,8 @@ bool MediaEngine::SetupStreams() {
+ for (int i = videoStreamNum + 1; i < m_expectedVideoStreams; i++) {
+ addVideoStream(i);
+ }
+-
+-
+ #endif
++
+ return true;
+ }
+
+@@ -328,13 +327,19 @@ 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;
+ }
+ }
+- if(m_videoStream == -1)
++ if (m_videoStream == -1)
+ return false;
+ }
+
+@@ -361,8 +366,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);
+@@ -411,6 +421,10 @@ bool MediaEngine::addVideoStream(int streamNum, int streamId) {
+ 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;
++#endif
+ stream->request_probe = 0;
+ stream->need_parsing = AVSTREAM_PARSE_FULL;
+ // We could set the width here, but we don't need to.
+@@ -496,21 +510,29 @@ bool MediaEngine::setVideoStream(int streamNum, bool force) {
+ 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];
++ int err;
++#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);
++ err = avcodec_parameters_to_context(m_pCodecCtx, stream->codecpar);
++ if (err < 0) {
++ WARN_LOG_REPORT(ME, "Failed to prepare context parameters: %08x", err);
++ 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
+
+ AVDictionary *opt = nullptr;
+ // Allow ffmpeg to use any number of threads it wants. Without this, it doesn't
use threads.
+
+From e3be3d5f7b0ed7fff6cfbdfb2d7b820e123cfc2f Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Thu, 18 Feb 2021 00:08:00 -0800
+Subject: [PATCH 7/9] Mpeg: Clarify fallback problems.
+
+Also, modify it in case some packager was patching, so they see this.
+---
+ Core/HW/MediaEngine.cpp | 6 ++++--
+ 1 file changed, 4 insertions(+), 2 deletions(-)
+
+diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp
+index 7d3ccee417..f8f008f73d 100644
+--- a/Core/HW/MediaEngine.cpp
++++ b/Core/HW/MediaEngine.cpp
+@@ -313,8 +313,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 should work for newer FFmpeg 3.1+ now.
++ 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;
+ }
+
+From 0ab6f1d0804cd8d68a00a1afeee7b70b463dc2a9 Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Thu, 18 Feb 2021 00:18:35 -0800
+Subject: [PATCH 8/9] Mpeg: Update videos to latest FFmpeg packet pump.
+
+---
+ Core/HLE/sceMpeg.cpp | 14 ++++++++++++++
+ Core/HW/MediaEngine.cpp | 18 ++++++++++++++++--
+ 2 files changed, 30 insertions(+), 2 deletions(-)
+
+diff --git a/Core/HLE/sceMpeg.cpp b/Core/HLE/sceMpeg.cpp
+index 4c4a4b0e59..3701f08a47 100644
+--- a/Core/HLE/sceMpeg.cpp
++++ b/Core/HLE/sceMpeg.cpp
+@@ -993,7 +993,21 @@ static bool decodePmpVideo(PSPPointer<SceMpegRingBuffer>
ringbuffer, u32 pmpctxA
+
+
+ // decode video frame
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ avcodec_send_packet(pCodecCtx, &packet);
++ int len = avcodec_receive_frame(pCodecCtx, pFrame);
++ if (len == 0) {
++ len = pFrame->pkt_size;
++ got_picture = 1;
++ } else if (len == AVERROR(EAGAIN)) {
++ len = 0;
++ got_picture = 0;
++ } else {
++ got_picture = 0;
++ }
++#else
+ int len = avcodec_decode_video2(pCodecCtx, pFrame, &got_picture, &packet);
++#endif
+ DEBUG_LOG(ME, "got_picture %d", got_picture);
+ if (got_picture){
+ SwsContext *img_convert_ctx = NULL;
+diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp
+index f8f008f73d..2dfddfdc89 100644
+--- a/Core/HW/MediaEngine.cpp
++++ b/Core/HW/MediaEngine.cpp
+@@ -664,9 +664,9 @@ bool MediaEngine::stepVideo(int videoPixelMode, bool skipFrame) {
+ while (!bGetFrame) {
+ bool dataEnd = av_read_frame(m_pFormatCtx, &packet) < 0;
+ // Even if we've read all frames, some may have been re-ordered frames at the
end.
+- // Still need to decode those, so keep calling avcodec_decode_video2().
++ // Still need to decode those, so keep calling avcodec_decode_video2() /
avcodec_receive_frame().
+ if (dataEnd || packet.stream_index == m_videoStream) {
+- // avcodec_decode_video2() gives us the re-ordered frames with a NULL packet.
++ // avcodec_decode_video2() / avcodec_send_packet() gives us the re-ordered frames
with a NULL packet.
+ #if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 12, 100)
+ if (dataEnd)
+ av_packet_unref(&packet);
+@@ -675,7 +675,21 @@ bool MediaEngine::stepVideo(int videoPixelMode, bool skipFrame) {
+ av_free_packet(&packet);
+ #endif
+
++#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(57, 48, 101)
++ 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();
+
+From 54dd4e4c0cd7d5d42347a8eb976f8638022e451f Mon Sep 17 00:00:00 2001
+From: "Unknown W. Brackets" <checkins(a)unknownbrackets.org>
+Date: Thu, 18 Feb 2021 00:31:50 -0800
+Subject: [PATCH 9/9] Mpeg: Remove request_probe usage in newer FFmpeg.
+
+No longer needed.
+---
+ Core/HW/MediaEngine.cpp | 3 ++-
+ 1 file changed, 2 insertions(+), 1 deletion(-)
+
+diff --git a/Core/HW/MediaEngine.cpp b/Core/HW/MediaEngine.cpp
+index 2dfddfdc89..4f7b213e5d 100644
+--- a/Core/HW/MediaEngine.cpp
++++ b/Core/HW/MediaEngine.cpp
+@@ -426,8 +426,9 @@ bool MediaEngine::addVideoStream(int streamNum, int 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;
+-#endif
++#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) {
+
diff --git a/ppsspp.spec b/ppsspp.spec
index 8afc3f6..f27f154 100644
--- a/ppsspp.spec
+++ b/ppsspp.spec
@@ -11,13 +11,13 @@ ExcludeArch: %{power64}
# lto1: internal compiler error: Segmentation fault
%define _lto_cflags %{nil}
-# -Wl,--as-needed breaks linking on fedora 30+
+# -Wl,--as-needed breaks linking
%undefine _ld_as_needed
# Use bundled FFMpeg-3.0.2
# See RPM Fusion bz#5889
%if 0%{?fedora} > 33
-%bcond_without ffmpeg
+%bcond_with ffmpeg
%else
%bcond_with ffmpeg
%endif
@@ -77,7 +77,7 @@ ExcludeArch: %{power64}
Name: ppsspp
Version: 1.11
-Release: 2%{?dist}
+Release: 3%{?dist}
Summary: A PSP emulator
License: BSD and GPLv2+
URL:
https://www.ppsspp.org/
@@ -116,6 +116,10 @@ Patch2: %{name}-ffmpeg-set_x64_build_flags.patch
Patch3: %{name}-ffmpeg-set_aarch64_build_flags.patch
Patch4: %{name}-ffmpeg-set_arm_build_flags.patch
+# Remove deprecated API calls for new FFmpeg 4.3.x
+# This patch permits FFMpeg unbundling
+Patch5: %{name}-upstream_bug_14176.patch
+
BuildRequires: pkgconfig(egl)
BuildRequires: pkgconfig(glesv2)
BuildRequires: pkgconfig(opengl)
@@ -199,6 +203,10 @@ PPSSPP with Qt5 frontend wrapper.
%patch3 -p1 -b .backup
%patch4 -p1 -b .backup
+%if %{without ffmpeg}
+%patch5 -p1 -b .backup
+%endif
+
# Remove bundled libraries
rm -rf /ext/native/ext/libzip
rm -rf /ext/native/tools/prebuilt/win64
@@ -415,6 +423,9 @@ fi
%{_datadir}/icons/%{name}/
%changelog
+* Sat Feb 20 2021 Antonio Trande <sagitter(a)fedoraproject.org> - 1.11-3
+- Unbundle FFmpeg (upstream bug #13849)
+
* Mon Feb 08 2021 Antonio Trande <sagitter(a)fedoraproject.org> - 1.11-2
- Change filtering method of private libraries