From db1de4b298c44204caafa9aa691136246f3060b6 Mon Sep 17 00:00:00 2001 From: "Huts, Roman" Date: Mon, 11 Nov 2024 14:08:26 -0500 Subject: [PATCH] obs-ffmpeg: Add AMD AV1 B-frame support --- plugins/obs-ffmpeg/texture-amf.cpp | 29 +++++++++++++++++++++++++++-- 1 file changed, 27 insertions(+), 2 deletions(-) diff --git a/plugins/obs-ffmpeg/texture-amf.cpp b/plugins/obs-ffmpeg/texture-amf.cpp index efe2d154f37eda..19db9fb2239d8e 100644 --- a/plugins/obs-ffmpeg/texture-amf.cpp +++ b/plugins/obs-ffmpeg/texture-amf.cpp @@ -1156,7 +1156,7 @@ static obs_properties_t *amf_properties_internal(amf_codec_type codec) #undef add_profile } - if (amf_codec_type::AVC == codec) { + if (amf_codec_type::AVC == codec || amf_codec_type::AV1 == codec) { obs_properties_add_int(props, "bf", obs_module_text("BFrames"), 0, 5, 1); } @@ -1969,6 +1969,17 @@ static bool amf_av1_init(void *data, obs_data_t *settings) const char *preset = obs_data_get_string(settings, "preset"); const char *profile = obs_data_get_string(settings, "profile"); const char *rc_str = obs_data_get_string(settings, "rate_control"); + int64_t bf = obs_data_get_int(settings, "bf"); + + if (enc->bframes_supported) { + set_av1_property(enc, MAX_CONSECUTIVE_BPICTURES, bf); + set_av1_property(enc, B_PIC_PATTERN, bf); + } else if (bf != 0) { + warn("B-Frames set to %lld but b-frames are not " + "supported by this device", + bf); + bf = 0; + } int rc = get_av1_rate_control(rc_str); set_av1_property(enc, RATE_CONTROL_METHOD, rc); @@ -2002,10 +2013,11 @@ static bool amf_av1_init(void *data, obs_data_t *settings) "\tkeyint: %d\n" "\tpreset: %s\n" "\tprofile: %s\n" + "\tb-frames: %d\n" "\twidth: %d\n" "\theight: %d\n" "\tparams: %s", - rc_str, bitrate, qp, gop_size, preset, profile, enc->cx, enc->cy, ffmpeg_opts); + rc_str, bitrate, qp, gop_size, preset, profile, bf, enc->cx, enc->cy, ffmpeg_opts); return true; } @@ -2020,6 +2032,7 @@ static void amf_av1_create_internal(amf_base *enc, obs_data_t *settings) AMFCapsPtr caps; AMF_RESULT res = enc->amf_encoder->GetCaps(&caps); if (res == AMF_OK) { + caps->GetProperty(AMF_VIDEO_ENCODER_AV1_CAP_BFRAMES, &enc->bframes_supported); caps->GetProperty(AMF_VIDEO_ENCODER_AV1_CAP_MAX_THROUGHPUT, &enc->max_throughput); caps->GetProperty(AMF_VIDEO_ENCODER_AV1_CAP_REQUESTED_THROUGHPUT, &enc->requested_throughput); /* For some reason there's no specific CAP for AV1, but should always be supported */ @@ -2052,6 +2065,17 @@ static void amf_av1_create_internal(amf_base *enc, obs_data_t *settings) res = enc->amf_encoder->GetProperty(AMF_VIDEO_ENCODER_AV1_EXTRA_DATA, &p); if (res == AMF_OK && p.type == AMF_VARIANT_INTERFACE) enc->header = AMFBufferPtr(p.pInterface); + + if (enc->bframes_supported) { + amf_int64 b_frames = 0; + amf_int64 b_max = 0; + + if (get_av1_property(enc, B_PIC_PATTERN, &b_frames) && + get_av1_property(enc, MAX_CONSECUTIVE_BPICTURES, &b_max)) + enc->dts_offset = b_frames + 1; + else + enc->dts_offset = 0; + } } static void *amf_av1_create_texencode(obs_data_t *settings, obs_encoder_t *encoder) @@ -2126,6 +2150,7 @@ static void amf_av1_defaults(obs_data_t *settings) obs_data_set_default_string(settings, "rate_control", "CBR"); obs_data_set_default_string(settings, "preset", "quality"); obs_data_set_default_string(settings, "profile", "high"); + obs_data_set_default_int(settings, "bf", 2); } static void register_av1()