diff --git a/externals/library-headers b/externals/library-headers index 3b3e28dbe..9fb99108e 160000 --- a/externals/library-headers +++ b/externals/library-headers @@ -1 +1 @@ -Subproject commit 3b3e28dbe6d033395ce2967fa8030825e7b89de7 +Subproject commit 9fb99108ee5c630ca365c8fa4a11087b84e1f58b diff --git a/src/citra_qt/dumping/option_set_dialog.cpp b/src/citra_qt/dumping/option_set_dialog.cpp index f6d6e4af7..f166973cf 100644 --- a/src/citra_qt/dumping/option_set_dialog.cpp +++ b/src/citra_qt/dumping/option_set_dialog.cpp @@ -27,7 +27,7 @@ static const std::unordered_map TypeNameMap{{ {AV_OPT_TYPE_STRING, QT_TR_NOOP("string")}, {AV_OPT_TYPE_DICT, QT_TR_NOOP("dictionary")}, {AV_OPT_TYPE_VIDEO_RATE, QT_TR_NOOP("video rate")}, - {AV_OPT_TYPE_CHANNEL_LAYOUT, QT_TR_NOOP("channel layout")}, + {AV_OPT_TYPE_CHLAYOUT, QT_TR_NOOP("channel layout")}, }}; static const std::unordered_map TypeDescriptionMap{{ @@ -39,7 +39,7 @@ static const std::unordered_map TypeDescriptionMap{{ {AV_OPT_TYPE_DICT, QT_TR_NOOP("Comma-splitted list of <key>=<value>. Do not put spaces.")}, {AV_OPT_TYPE_VIDEO_RATE, QT_TR_NOOP("<num>/<den>, or preset values like 'pal'.")}, - {AV_OPT_TYPE_CHANNEL_LAYOUT, QT_TR_NOOP("Hexadecimal channel layout mask starting with '0x'.")}, + {AV_OPT_TYPE_CHLAYOUT, QT_TR_NOOP("Hexadecimal channel layout mask starting with '0x'.")}, }}; /// Get the preset values of an option. returns {display value, real value} diff --git a/src/common/dynamic_library/ffmpeg.cpp b/src/common/dynamic_library/ffmpeg.cpp index 709f887a5..fd00db337 100644 --- a/src/common/dynamic_library/ffmpeg.cpp +++ b/src/common/dynamic_library/ffmpeg.cpp @@ -65,6 +65,9 @@ avcodec_find_encoder_by_name_func avcodec_find_encoder_by_name; avcodec_free_context_func avcodec_free_context; avcodec_get_class_func avcodec_get_class; avcodec_get_hw_config_func avcodec_get_hw_config; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 +avcodec_get_supported_config_func avcodec_get_supported_config; +#endif avcodec_open2_func avcodec_open2; avcodec_parameters_from_context_func avcodec_parameters_from_context; avcodec_receive_frame_func avcodec_receive_frame; @@ -232,6 +235,9 @@ static bool LoadAVCodec() { LOAD_SYMBOL(avcodec, avcodec_free_context); LOAD_SYMBOL(avcodec, avcodec_get_class); LOAD_SYMBOL(avcodec, avcodec_get_hw_config); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 + LOAD_SYMBOL(avcodec, avcodec_get_supported_config); +#endif LOAD_SYMBOL(avcodec, avcodec_open2); LOAD_SYMBOL(avcodec, avcodec_parameters_from_context); LOAD_SYMBOL(avcodec, avcodec_receive_frame); diff --git a/src/common/dynamic_library/ffmpeg.h b/src/common/dynamic_library/ffmpeg.h index f79fef8da..69df01ede 100644 --- a/src/common/dynamic_library/ffmpeg.h +++ b/src/common/dynamic_library/ffmpeg.h @@ -114,6 +114,10 @@ typedef const AVCodec* (*avcodec_find_encoder_by_name_func)(const char*); 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); +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 +typedef int (*avcodec_get_supported_config_func)(const AVCodecContext*, const AVCodec*, + enum AVCodecConfig, unsigned, const void**, int*); +#endif 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 +142,9 @@ extern avcodec_find_encoder_by_name_func avcodec_find_encoder_by_name; 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; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 +extern avcodec_get_supported_config_func avcodec_get_supported_config; +#endif extern avcodec_open2_func avcodec_open2; extern avcodec_parameters_from_context_func avcodec_parameters_from_context; extern avcodec_receive_frame_func avcodec_receive_frame; diff --git a/src/core/dumping/ffmpeg_backend.cpp b/src/core/dumping/ffmpeg_backend.cpp index b38116ed3..6fcbe7708 100644 --- a/src/core/dumping/ffmpeg_backend.cpp +++ b/src/core/dumping/ffmpeg_backend.cpp @@ -171,12 +171,21 @@ bool FFmpegVideoStream::Init(FFmpegMuxer& muxer, const Layout::FramebufferLayout codec_context->gop_size = 12; // Get pixel format for codec +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 + const enum AVPixelFormat* pix_fmts = NULL; + int ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, + (const void**)&pix_fmts, NULL); +#else + const enum AVPixelFormat* pix_fmts = codec->pix_fmts; + int ret = 0; +#endif + auto options = ToAVDictionary(Settings::values.video_encoder_options); 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 (ret >= 0 && pix_fmts) { + sw_pixel_format = GetPixelFormat(codec_context.get(), pix_fmts); } else { sw_pixel_format = AV_PIX_FMT_YUV420P; } @@ -285,11 +294,20 @@ 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) { +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 + const enum AVPixelFormat* pix_fmts = NULL; + int ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_PIX_FORMAT, 0, + (const void**)&pix_fmts, NULL); +#else + const enum AVPixelFormat* pix_fmts = codec->pix_fmts; + int ret = 0; +#endif + + for (std::size_t i = 0; (ret >= 0 && pix_fmts) && (pix_fmts[i] != AV_PIX_FMT_NONE); ++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 == pix_fmts[i]) { break; } } @@ -303,7 +321,7 @@ bool FFmpegVideoStream::InitHWContext(const AVCodec* codec) { continue; } - codec_context->pix_fmt = codec->pix_fmts[i]; + codec_context->pix_fmt = pix_fmts[i]; // Create HW device context AVBufferRef* hw_device_context; @@ -351,7 +369,7 @@ bool FFmpegVideoStream::InitHWContext(const AVCodec* codec) { AVHWFramesContext* hw_frames_context = reinterpret_cast(hw_frames_context_ref->data); - hw_frames_context->format = codec->pix_fmts[i]; + hw_frames_context->format = pix_fmts[i]; hw_frames_context->sw_format = sw_pixel_format; hw_frames_context->width = codec_context->width; hw_frames_context->height = codec_context->height; @@ -455,6 +473,7 @@ bool FFmpegAudioStream::Init(FFmpegMuxer& muxer) { } frame_count = 0; + int ret; // Initialize audio codec const AVCodec* codec = @@ -468,16 +487,33 @@ bool FFmpegAudioStream::Init(FFmpegMuxer& muxer) { // 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 LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 + const enum AVSampleFormat* sample_fmts = NULL; + ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_FORMAT, 0, + (const void**)&sample_fmts, NULL); +#else + const enum AVSampleFormat* sample_fmts = codec->sample_fmts; + ret = 0; +#endif + if (ret >= 0 && sample_fmts) { + codec_context->sample_fmt = sample_fmts[0]; } else { codec_context->sample_fmt = AV_SAMPLE_FMT_S16P; } - if (codec->supported_samplerates) { - codec_context->sample_rate = codec->supported_samplerates[0]; +#if LIBAVCODEC_VERSION_INT >= AV_VERSION_INT(61, 13, 100) // lavc 61.13.100 + const int* supported_samplerates = NULL; + ret = FFmpeg::avcodec_get_supported_config(NULL, codec, AV_CODEC_CONFIG_SAMPLE_RATE, 0, + (const void**)&supported_samplerates, NULL); +#else + const int* supported_samplerates = codec->supported_samplerates; + ret = 0; +#endif + if (ret >= 0 && supported_samplerates) { + codec_context->sample_rate = supported_samplerates[0]; // Prefer native sample rate if supported - const int* ptr = codec->supported_samplerates; + const int* ptr = supported_samplerates; while ((*ptr)) { if ((*ptr) == AudioCore::native_sample_rate) { codec_context->sample_rate = AudioCore::native_sample_rate; @@ -956,7 +992,7 @@ std::string FormatDefaultValue(const AVOption* option, case AV_OPT_TYPE_VIDEO_RATE: { return ToStdString(option->default_val.str); } - case AV_OPT_TYPE_CHANNEL_LAYOUT: { + case AV_OPT_TYPE_CHLAYOUT: { return fmt::format("{:#x}", option->default_val.i64); } default: