Download raw body.
emulators/citra: compatibility with ffmpeg 9.0
ports@,
Here another mehanical fix for ffmpeg 9.0 compatibility for emulators/citra
Build tested against ffmpeg-9.0 and ffmpeg-8.1.2
Ok?
Index: Makefile
===================================================================
RCS file: /home/cvs/ports/emulators/citra/Makefile,v
diff -u -p -r1.43 Makefile
--- Makefile 11 Aug 2026 09:16:14 -0000 1.43
+++ Makefile 12 Aug 2026 23:52:57 -0000
@@ -9,7 +9,7 @@ DISTNAME = citra-unified-source-20240303
V = 2104
PKGNAME = citra-0.0.0.${V}
-REVISION = 7
+REVISION = 8
CATEGORIES = emulators
Index: patches/patch-src_common_dynamic_library_ffmpeg_cpp
===================================================================
RCS file: patches/patch-src_common_dynamic_library_ffmpeg_cpp
diff -N patches/patch-src_common_dynamic_library_ffmpeg_cpp
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_common_dynamic_library_ffmpeg_cpp 13 Aug 2026 00:14:44 -0000
@@ -0,0 +1,53 @@
+ffmpeg-9.0
+
+Index: src/common/dynamic_library/ffmpeg.cpp
+--- src/common/dynamic_library/ffmpeg.cpp.orig
++++ src/common/dynamic_library/ffmpeg.cpp
+@@ -33,14 +33,13 @@ av_hwframe_ctx_alloc_func av_hwframe_ctx_alloc;
+ av_hwframe_ctx_init_func av_hwframe_ctx_init;
+ av_hwframe_get_buffer_func av_hwframe_get_buffer;
+ av_hwframe_transfer_data_func av_hwframe_transfer_data;
+-av_int_list_length_for_size_func av_int_list_length_for_size;
+ #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 53, 100) // lavu 56.53.100
+ av_opt_child_class_iterate_func av_opt_child_class_iterate;
+ #else
+ av_opt_child_class_next_func av_opt_child_class_next;
+ #endif
+ av_opt_next_func av_opt_next;
+-av_opt_set_bin_func av_opt_set_bin;
++av_opt_set_array_func av_opt_set_array;
+ av_pix_fmt_desc_get_func av_pix_fmt_desc_get;
+ av_pix_fmt_desc_next_func av_pix_fmt_desc_next;
+ av_sample_fmt_is_planar_func av_sample_fmt_is_planar;
+@@ -65,6 +64,7 @@ avcodec_find_encoder_by_name_func avcodec_find_encoder
+ avcodec_free_context_func avcodec_free_context;
+ avcodec_get_class_func avcodec_get_class;
+ avcodec_get_hw_config_func avcodec_get_hw_config;
++avcodec_get_supported_config_func avcodec_get_supported_config;
+ avcodec_open2_func avcodec_open2;
+ avcodec_parameters_from_context_func avcodec_parameters_from_context;
+ avcodec_receive_frame_func avcodec_receive_frame;
+@@ -168,14 +168,13 @@ static bool LoadAVUtil() {
+ LOAD_SYMBOL(avutil, av_hwframe_ctx_init);
+ LOAD_SYMBOL(avutil, av_hwframe_get_buffer);
+ LOAD_SYMBOL(avutil, av_hwframe_transfer_data);
+- LOAD_SYMBOL(avutil, av_int_list_length_for_size);
+ #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 53, 100) // lavu 56.53.100
+ LOAD_SYMBOL(avutil, av_opt_child_class_iterate);
+ #else
+ LOAD_SYMBOL(avutil, av_opt_child_class_next);
+ #endif
+ LOAD_SYMBOL(avutil, av_opt_next);
+- LOAD_SYMBOL(avutil, av_opt_set_bin);
++ LOAD_SYMBOL(avutil, av_opt_set_array);
+ LOAD_SYMBOL(avutil, av_pix_fmt_desc_get);
+ LOAD_SYMBOL(avutil, av_pix_fmt_desc_next);
+ LOAD_SYMBOL(avutil, av_sample_fmt_is_planar);
+@@ -232,6 +231,7 @@ static bool LoadAVCodec() {
+ LOAD_SYMBOL(avcodec, avcodec_free_context);
+ LOAD_SYMBOL(avcodec, avcodec_get_class);
+ LOAD_SYMBOL(avcodec, avcodec_get_hw_config);
++ LOAD_SYMBOL(avcodec, avcodec_get_supported_config);
+ LOAD_SYMBOL(avcodec, avcodec_open2);
+ LOAD_SYMBOL(avcodec, avcodec_parameters_from_context);
+ LOAD_SYMBOL(avcodec, avcodec_receive_frame);
Index: patches/patch-src_common_dynamic_library_ffmpeg_h
===================================================================
RCS file: patches/patch-src_common_dynamic_library_ffmpeg_h
diff -N patches/patch-src_common_dynamic_library_ffmpeg_h
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ patches/patch-src_common_dynamic_library_ffmpeg_h 13 Aug 2026 00:14:44 -0000
@@ -0,0 +1,55 @@
+ffmpeg-9.0
+
+Index: src/common/dynamic_library/ffmpeg.h
+--- src/common/dynamic_library/ffmpeg.h.orig
++++ src/common/dynamic_library/ffmpeg.h
+@@ -43,14 +43,14 @@ typedef AVBufferRef* (*av_hwframe_ctx_alloc_func)(AVBu
+ typedef int (*av_hwframe_ctx_init_func)(AVBufferRef*);
+ typedef int (*av_hwframe_get_buffer_func)(AVBufferRef*, AVFrame*, int);
+ typedef int (*av_hwframe_transfer_data_func)(AVFrame*, const AVFrame*, int);
+-typedef unsigned (*av_int_list_length_for_size_func)(unsigned, const void*, uint64_t);
+ #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 53, 100) // lavu 56.53.100
+ typedef const AVClass* (*av_opt_child_class_iterate_func)(const AVClass*, void**);
+ #else
+ typedef const AVClass* (*av_opt_child_class_next_func)(const AVClass*, const AVClass*);
+ #endif
+ typedef const AVOption* (*av_opt_next_func)(const void*, const AVOption*);
+-typedef int (*av_opt_set_bin_func)(void*, const char*, const uint8_t*, int, int);
++typedef int (*av_opt_set_array_func)(void*, const char*, int, unsigned, unsigned, AVOptionType,
++ const void*);
+ typedef const AVPixFmtDescriptor* (*av_pix_fmt_desc_get_func)(AVPixelFormat);
+ typedef const AVPixFmtDescriptor* (*av_pix_fmt_desc_next_func)(const AVPixFmtDescriptor*);
+ typedef int (*av_sample_fmt_is_planar_func)(AVSampleFormat);
+@@ -81,14 +81,13 @@ extern av_hwframe_ctx_alloc_func av_hwframe_ctx_alloc;
+ extern av_hwframe_ctx_init_func av_hwframe_ctx_init;
+ extern av_hwframe_get_buffer_func av_hwframe_get_buffer;
+ extern av_hwframe_transfer_data_func av_hwframe_transfer_data;
+-extern av_int_list_length_for_size_func av_int_list_length_for_size;
+ #if LIBAVUTIL_VERSION_INT >= AV_VERSION_INT(56, 53, 100) // lavu 56.53.100
+ extern av_opt_child_class_iterate_func av_opt_child_class_iterate;
+ #else
+ extern av_opt_child_class_next_func av_opt_child_class_next;
+ #endif
+ extern av_opt_next_func av_opt_next;
+-extern av_opt_set_bin_func av_opt_set_bin;
++extern av_opt_set_array_func av_opt_set_array;
+ extern av_pix_fmt_desc_get_func av_pix_fmt_desc_get;
+ extern av_pix_fmt_desc_next_func av_pix_fmt_desc_next;
+ extern av_sample_fmt_is_planar_func av_sample_fmt_is_planar;
+@@ -114,6 +113,8 @@ typedef const AVCodec* (*avcodec_find_encoder_by_name_
+ typedef void (*avcodec_free_context_func)(AVCodecContext**);
+ typedef const AVClass* (*avcodec_get_class_func)();
+ typedef const AVCodecHWConfig* (*avcodec_get_hw_config_func)(const AVCodec*, int);
++typedef int (*avcodec_get_supported_config_func)(const AVCodecContext*, const AVCodec*,
++ enum AVCodecConfig, unsigned, const void**, int*);
+ typedef int (*avcodec_open2_func)(AVCodecContext*, const AVCodec*, AVDictionary**);
+ typedef int (*avcodec_parameters_from_context_func)(AVCodecParameters* par, const AVCodecContext*);
+ typedef int (*avcodec_receive_frame_func)(AVCodecContext*, AVFrame*);
+@@ -138,6 +139,7 @@ extern avcodec_find_encoder_by_name_func avcodec_find_
+ extern avcodec_free_context_func avcodec_free_context;
+ extern avcodec_get_class_func avcodec_get_class;
+ extern avcodec_get_hw_config_func avcodec_get_hw_config;
++extern avcodec_get_supported_config_func avcodec_get_supported_config;
+ extern avcodec_open2_func avcodec_open2;
+ extern avcodec_parameters_from_context_func avcodec_parameters_from_context;
+ extern avcodec_receive_frame_func avcodec_receive_frame;
Index: patches/patch-src_core_dumping_ffmpeg_backend_cpp
===================================================================
RCS file: /home/cvs/ports/emulators/citra/patches/patch-src_core_dumping_ffmpeg_backend_cpp,v
diff -u -p -r1.1 patch-src_core_dumping_ffmpeg_backend_cpp
--- patches/patch-src_core_dumping_ffmpeg_backend_cpp 21 Oct 2025 12:50:42 -0000 1.1
+++ patches/patch-src_core_dumping_ffmpeg_backend_cpp 13 Aug 2026 00:14:44 -0000
@@ -1,7 +1,187 @@
+ffmpeg-9.0
+
Index: src/core/dumping/ffmpeg_backend.cpp
--- src/core/dumping/ffmpeg_backend.cpp.orig
+++ src/core/dumping/ffmpeg_backend.cpp
-@@ -956,7 +956,11 @@ std::string FormatDefaultValue(const AVOption* option,
+@@ -106,9 +106,10 @@ FFmpegVideoStream::~FFmpegVideoStream() {
+
+ // This is modified from libavcodec/decode.c
+ // The original version was broken
+-static AVPixelFormat GetPixelFormat(AVCodecContext* avctx, const AVPixelFormat* fmt) {
++static AVPixelFormat GetPixelFormat(AVCodecContext* avctx, const AVPixelFormat* fmt,
++ int num_formats) {
+ // Choose a software pixel format if any, prefering those in the front of the list
+- for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
++ for (int i = 0; i < num_formats; i++) {
+ const AVPixFmtDescriptor* desc = FFmpeg::av_pix_fmt_desc_get(fmt[i]);
+ if (!(desc->flags & AV_PIX_FMT_FLAG_HWACCEL)) {
+ return fmt[i];
+@@ -118,7 +119,7 @@ static AVPixelFormat GetPixelFormat(AVCodecContext* av
+ // Finally, traverse the list in order and choose the first entry
+ // with no external dependencies (if there is no hardware configuration
+ // information available then this just picks the first entry).
+- for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) {
++ for (int i = 0; i < num_formats; i++) {
+ const AVCodecHWConfig* config;
+ for (int j = 0;; j++) {
+ config = FFmpeg::avcodec_get_hw_config(avctx->codec, j);
+@@ -142,6 +143,9 @@ static AVPixelFormat GetPixelFormat(AVCodecContext* av
+ }
+
+ bool FFmpegVideoStream::Init(FFmpegMuxer& muxer, const Layout::FramebufferLayout& layout_) {
++ const AVPixelFormat* pixel_formats;
++ int num_pixel_formats, ret;
++
+ InitializeFFmpegLibraries();
+
+ if (!FFmpegStream::Init(muxer)) {
+@@ -160,6 +164,14 @@ bool FFmpegVideoStream::Init(FFmpegMuxer& muxer, const
+ return false;
+ }
+
++ ret = FFmpeg::avcodec_get_supported_config(codec_context.get(), nullptr,
++ AV_CODEC_CONFIG_PIX_FORMAT, 0,
++ (const void**)&pixel_formats, &num_pixel_formats);
++ if (ret < 0) {
++ LOG_ERROR(Render, "Could not query video encoder pixel formats");
++ return false;
++ }
++
+ // Configure video codec context
+ codec_context->codec_type = AVMEDIA_TYPE_VIDEO;
+ codec_context->bit_rate = Settings::values.video_bitrate;
+@@ -175,8 +187,8 @@ bool FFmpegVideoStream::Init(FFmpegMuxer& muxer, const
+ auto pixel_format_opt = FFmpeg::av_dict_get(options, "pixel_format", nullptr, 0);
+ if (pixel_format_opt) {
+ sw_pixel_format = FFmpeg::av_get_pix_fmt(pixel_format_opt->value);
+- } else if (codec->pix_fmts) {
+- sw_pixel_format = GetPixelFormat(codec_context.get(), codec->pix_fmts);
++ } else if (pixel_formats) {
++ sw_pixel_format = GetPixelFormat(codec_context.get(), pixel_formats, num_pixel_formats);
+ } else {
+ sw_pixel_format = AV_PIX_FMT_YUV420P;
+ }
+@@ -285,11 +297,22 @@ void FFmpegVideoStream::ProcessFrame(VideoFrame& frame
+ }
+
+ bool FFmpegVideoStream::InitHWContext(const AVCodec* codec) {
+- for (std::size_t i = 0; codec->pix_fmts[i] != AV_PIX_FMT_NONE; ++i) {
++ const AVPixelFormat* pixel_formats;
++ int num_pixel_formats, ret;
++
++ ret = FFmpeg::avcodec_get_supported_config(codec_context.get(), nullptr,
++ AV_CODEC_CONFIG_PIX_FORMAT, 0,
++ (const void**)&pixel_formats, &num_pixel_formats);
++ if (ret < 0 || !pixel_formats) {
++ LOG_ERROR(Render, "Failed to query HW pixel formats");
++ return false;
++ }
++
++ for (int i = 0; i < num_pixel_formats; ++i) {
+ const AVCodecHWConfig* config;
+ for (int j = 0;; ++j) {
+ config = FFmpeg::avcodec_get_hw_config(codec, j);
+- if (!config || config->pix_fmt == codec->pix_fmts[i]) {
++ if (!config || config->pix_fmt == pixel_formats[i]) {
+ break;
+ }
+ }
+@@ -303,7 +326,7 @@ bool FFmpegVideoStream::InitHWContext(const AVCodec* c
+ continue;
+ }
+
+- codec_context->pix_fmt = codec->pix_fmts[i];
++ codec_context->pix_fmt = pixel_formats[i];
+
+ // Create HW device context
+ AVBufferRef* hw_device_context;
+@@ -351,7 +374,7 @@ bool FFmpegVideoStream::InitHWContext(const AVCodec* c
+
+ AVHWFramesContext* hw_frames_context =
+ reinterpret_cast<AVHWFramesContext*>(hw_frames_context_ref->data);
+- hw_frames_context->format = codec->pix_fmts[i];
++ hw_frames_context->format = pixel_formats[i];
+ hw_frames_context->sw_format = sw_pixel_format;
+ hw_frames_context->width = codec_context->width;
+ hw_frames_context->height = codec_context->height;
+@@ -399,13 +422,9 @@ bool FFmpegVideoStream::InitFilters() {
+ return false;
+ }
+
+- // Point av_opt_set_int_list to correct functions.
+-#define av_int_list_length_for_size FFmpeg::av_int_list_length_for_size
+-#define av_opt_set_bin FFmpeg::av_opt_set_bin
+-
+- const AVPixelFormat pix_fmts[] = {sw_pixel_format, AV_PIX_FMT_NONE};
+- if (av_opt_set_int_list(sink_context, "pix_fmts", pix_fmts, AV_PIX_FMT_NONE,
+- AV_OPT_SEARCH_CHILDREN) < 0) {
++ const AVPixelFormat pixel_formats[] = {sw_pixel_format};
++ if (FFmpeg::av_opt_set_array(sink_context, "pixel_formats", AV_OPT_SEARCH_CHILDREN, 0, 1,
++ AV_OPT_TYPE_PIXEL_FMT, pixel_formats) < 0) {
+ LOG_ERROR(Render, "Could not set output pixel format");
+ return false;
+ }
+@@ -448,6 +467,10 @@ FFmpegAudioStream::~FFmpegAudioStream() {
+ }
+
+ bool FFmpegAudioStream::Init(FFmpegMuxer& muxer) {
++ const AVSampleFormat* sample_formats;
++ const int* supported_sample_rates;
++ int num_sample_formats, num_supported_sample_rates, ret;
++
+ InitializeFFmpegLibraries();
+
+ if (!FFmpegStream::Init(muxer)) {
+@@ -465,25 +488,40 @@ bool FFmpegAudioStream::Init(FFmpegMuxer& muxer) {
+ return false;
+ }
+
++ ret = FFmpeg::avcodec_get_supported_config(codec_context.get(), nullptr,
++ AV_CODEC_CONFIG_SAMPLE_FORMAT, 0,
++ (const void**)&sample_formats, &num_sample_formats);
++ if (ret < 0) {
++ LOG_ERROR(Render, "Could not query audio encoder sample formats");
++ return false;
++ }
++
++ ret = FFmpeg::avcodec_get_supported_config(codec_context.get(), nullptr,
++ AV_CODEC_CONFIG_SAMPLE_RATE, 0,
++ (const void**)&supported_sample_rates,
++ &num_supported_sample_rates);
++ if (ret < 0) {
++ LOG_ERROR(Render, "Could not query audio encoder sample rates");
++ return false;
++ }
++
+ // Configure audio codec context
+ codec_context->codec_type = AVMEDIA_TYPE_AUDIO;
+ codec_context->bit_rate = Settings::values.audio_bitrate;
+- if (codec->sample_fmts) {
+- codec_context->sample_fmt = codec->sample_fmts[0];
++ if (sample_formats && num_sample_formats > 0) {
++ codec_context->sample_fmt = sample_formats[0];
+ } else {
+ codec_context->sample_fmt = AV_SAMPLE_FMT_S16P;
+ }
+
+- if (codec->supported_samplerates) {
+- codec_context->sample_rate = codec->supported_samplerates[0];
++ if (supported_sample_rates && num_supported_sample_rates > 0) {
++ codec_context->sample_rate = supported_sample_rates[0];
+ // Prefer native sample rate if supported
+- const int* ptr = codec->supported_samplerates;
+- while ((*ptr)) {
+- if ((*ptr) == AudioCore::native_sample_rate) {
++ for (int i = 0; i < num_supported_sample_rates; i++) {
++ if (supported_sample_rates[i] == AudioCore::native_sample_rate) {
+ codec_context->sample_rate = AudioCore::native_sample_rate;
+ break;
+ }
+- ptr++;
+ }
+ } else {
+ codec_context->sample_rate = AudioCore::native_sample_rate;
+@@ -956,7 +994,11 @@ std::string FormatDefaultValue(const AVOption* option,
case AV_OPT_TYPE_VIDEO_RATE: {
return ToStdString(option->default_val.str);
}
--
wbr, Kirill
emulators/citra: compatibility with ffmpeg 9.0