Files
obs-studio-nobara/hevc-vaapi.patch
2022-08-01 18:02:01 -06:00

333 lines
12 KiB
Diff

diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c
index 53beb0f96..87338f61f 100644
--- a/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c
+++ b/plugins/obs-ffmpeg/obs-ffmpeg-vaapi.c
@@ -74,10 +74,35 @@ struct vaapi_encoder {
bool initialized;
};
-static const char *vaapi_getname(void *unused)
+/* Identify codecs, and some default values */
+struct type_data {
+ const int id;
+ const int profile;
+ const int level;
+ const char *name;
+ const char *rate_control;
+};
+
+static struct type_data h264_type = {
+ .id = AV_CODEC_ID_H264,
+ .profile = FF_PROFILE_H264_CONSTRAINED_BASELINE,
+ .level = 40,
+ .rate_control = "CBR",
+ .name = "AMD/INTEL GPU VAAPI H.264 (via FFmpeg)",
+};
+
+static struct type_data hevc_type = {
+ .id = AV_CODEC_ID_HEVC,
+ .profile = FF_PROFILE_HEVC_MAIN,
+ .level = 120,
+ .rate_control = "CBR",
+ .name = "AMD/INTEL GPU VAAPI H.265 (via FFmpeg)",
+};
+
+static const char *vaapi_getname(void *type_data)
{
- UNUSED_PARAMETER(unused);
- return "FFMPEG VAAPI H.264";
+ struct type_data *data = type_data;
+ return data->name;
}
static inline bool valid_format(enum video_format format)
@@ -177,15 +202,15 @@ typedef struct {
bool maxrate;
} rc_mode_t;
+/* Set "allowed" options per Rate Control */
+static const rc_mode_t RC_MODES[] = {
+ {.name = "CBR", .qp = false, .bitrate = true, .maxrate = false},
+ {.name = "CQP", .qp = true, .bitrate = false, .maxrate = false},
+ {.name = "VBR", .qp = false, .bitrate = true, .maxrate = true},
+ NULL};
+
static const rc_mode_t *get_rc_mode(const char *name)
{
- /* Set "allowed" options per Rate Control */
- static const rc_mode_t RC_MODES[] = {
- {.name = "CBR", .qp = false, .bitrate = true, .maxrate = false},
- {.name = "CQP", .qp = true, .bitrate = false, .maxrate = false},
- {.name = "VBR", .qp = false, .bitrate = true, .maxrate = true},
- NULL};
-
const rc_mode_t *rc_mode = RC_MODES;
while (!!rc_mode && strcmp(rc_mode->name, name) != 0)
@@ -285,6 +310,7 @@ static bool vaapi_update(void *data, obs_data_t *settings)
info("settings:\n"
"\tdevice: %s\n"
+ "\tcodec: %s\n"
"\trate_control: %s\n"
"\tprofile: %d\n"
"\tlevel: %d\n"
@@ -295,9 +321,9 @@ static bool vaapi_update(void *data, obs_data_t *settings)
"\twidth: %d\n"
"\theight: %d\n"
"\tb-frames: %d\n",
- device, rate_control, profile, level, qp, bitrate, maxrate,
- enc->context->gop_size, enc->context->width, enc->context->height,
- enc->context->max_b_frames);
+ device, enc->vaapi->name, rate_control, profile, level, qp,
+ bitrate, maxrate, enc->context->gop_size, enc->context->width,
+ enc->context->height, enc->context->max_b_frames);
return vaapi_init_codec(enc, device);
}
@@ -350,10 +376,18 @@ static void *vaapi_create(obs_data_t *settings, obs_encoder_t *encoder)
enc = bzalloc(sizeof(*enc));
enc->encoder = encoder;
+
+ int vaapi_codec = (int)obs_data_get_int(settings, "vaapi_codec");
- enc->vaapi = avcodec_find_encoder_by_name("h264_vaapi");
+ if (vaapi_codec == AV_CODEC_ID_H264) {
+ enc->vaapi = avcodec_find_encoder_by_name("h264_vaapi");
+ enc->first_packet = true;
+ }
- enc->first_packet = true;
+ if (vaapi_codec == AV_CODEC_ID_HEVC) {
+ enc->vaapi = avcodec_find_encoder_by_name("hevc_vaapi");
+ enc->first_packet = false;
+ }
blog(LOG_INFO, "---------------------------------");
@@ -488,7 +522,10 @@ static bool vaapi_encode(void *data, struct encoder_frame *frame,
packet->data = enc->buffer.array;
packet->size = enc->buffer.num;
packet->type = OBS_ENCODER_VIDEO;
- packet->keyframe = obs_avc_keyframe(packet->data, packet->size);
+ packet->keyframe =
+ enc->vaapi->id == AV_CODEC_ID_H264
+ ? obs_avc_keyframe(packet->data, packet->size)
+ : enc->packet->flags & AV_PKT_FLAG_KEY;
*received_packet = true;
} else {
*received_packet = false;
@@ -509,18 +546,20 @@ static void set_visible(obs_properties_t *ppts, const char *name, bool visible)
obs_property_set_visible(p, visible);
}
-static void vaapi_defaults(obs_data_t *settings)
+static void vaapi_defaults(obs_data_t *settings, void *type_data)
{
+ struct type_data *codec = type_data;
+
obs_data_set_default_string(settings, "vaapi_device",
"/dev/dri/renderD128");
- obs_data_set_default_int(settings, "profile",
- FF_PROFILE_H264_CONSTRAINED_BASELINE);
- obs_data_set_default_int(settings, "level", 40);
+ obs_data_set_default_int(settings, "vaapi_codec", codec->id);
+ obs_data_set_default_int(settings, "profile", codec->profile);
+ obs_data_set_default_int(settings, "level", codec->level);
obs_data_set_default_int(settings, "bitrate", 2500);
obs_data_set_default_int(settings, "keyint_sec", 0);
obs_data_set_default_int(settings, "bf", 0);
- obs_data_set_default_int(settings, "rendermode", 0);
- obs_data_set_default_string(settings, "rate_control", "CBR");
+ obs_data_set_default_string(settings, "rate_control",
+ codec->rate_control);
obs_data_set_default_int(settings, "qp", 20);
obs_data_set_default_int(settings, "maxrate", 0);
}
@@ -568,9 +607,13 @@ static bool get_device_name_from_pci(struct pci_access *pacc, char *pci_slot,
return false;
}
-static obs_properties_t *vaapi_properties(void *unused)
+static obs_properties_t *vaapi_properties(void *unused, void *type_data)
{
UNUSED_PARAMETER(unused);
+ struct type_data *codec = type_data;
+ struct dstr name;
+
+ dstr_init(&name);
obs_properties_t *props = obs_properties_create();
obs_property_t *list;
@@ -642,33 +685,63 @@ static obs_properties_t *vaapi_properties(void *unused)
}
}
- list = obs_properties_add_list(props, "profile",
- obs_module_text("Profile"),
- OBS_COMBO_TYPE_LIST,
- OBS_COMBO_FORMAT_INT);
- obs_property_list_add_int(list, "Constrained Baseline (default)",
- FF_PROFILE_H264_CONSTRAINED_BASELINE);
- obs_property_list_add_int(list, "Main", FF_PROFILE_H264_MAIN);
- obs_property_list_add_int(list, "High", FF_PROFILE_H264_HIGH);
+ if (codec->id == AV_CODEC_ID_H264) {
+ list = obs_properties_add_list(props, "profile",
+ obs_module_text("Profile"),
+ OBS_COMBO_TYPE_LIST,
+ OBS_COMBO_FORMAT_INT);
+ obs_property_list_add_int(list, "Constrained Baseline (default)",
+ FF_PROFILE_H264_CONSTRAINED_BASELINE);
+ obs_property_list_add_int(list, "Main", FF_PROFILE_H264_MAIN);
+ obs_property_list_add_int(list, "High", FF_PROFILE_H264_HIGH);
+
+ list = obs_properties_add_list(props, "level",
+ obs_module_text("Level"),
+ OBS_COMBO_TYPE_LIST,
+ OBS_COMBO_FORMAT_INT);
+ obs_property_list_add_int(list, "Auto", FF_LEVEL_UNKNOWN);
+ obs_property_list_add_int(list, "3.0", 30);
+ obs_property_list_add_int(list, "3.1", 31);
+ obs_property_list_add_int(list, "4.0 (default) (Compatibility mode)",
+ 40);
+ obs_property_list_add_int(list, "4.1", 41);
+ obs_property_list_add_int(list, "4.2", 42);
+ obs_property_list_add_int(list, "5.0", 50);
+ obs_property_list_add_int(list, "5.1", 51);
+ obs_property_list_add_int(list, "5.2", 52);
+ } else if (codec->id == AV_CODEC_ID_HEVC) {
+ list = obs_properties_add_list(props, "profile",
+ obs_module_text("Profile"),
+ OBS_COMBO_TYPE_LIST,
+ OBS_COMBO_FORMAT_INT);
+ obs_property_list_add_int(list, "Main", FF_PROFILE_HEVC_MAIN);
+ obs_property_list_add_int(list, "Main10", FF_PROFILE_HEVC_MAIN_10);
+ obs_property_list_add_int(list, "Rext", FF_PROFILE_HEVC_REXT);
+
+ list = obs_properties_add_list(props, "level",
+ obs_module_text("Level"),
+ OBS_COMBO_TYPE_LIST,
+ OBS_COMBO_FORMAT_INT);
+ obs_property_list_add_int(list, "Auto", FF_LEVEL_UNKNOWN);
+ obs_property_list_add_int(list, "1", 30);
+ obs_property_list_add_int(list, "2", 60);
+ obs_property_list_add_int(list, "2.1", 63);
+ obs_property_list_add_int(list, "3", 90);
+ obs_property_list_add_int(list, "3.1", 93);
+ obs_property_list_add_int(list, "4", 120);
+ obs_property_list_add_int(list, "4.1", 123);
+ obs_property_list_add_int(list, "5", 150);
+ obs_property_list_add_int(list, "5.1", 153);
+ obs_property_list_add_int(list, "5.2", 156);
+ obs_property_list_add_int(list, "6", 180);
+ obs_property_list_add_int(list, "6.1", 183);
+ obs_property_list_add_int(list, "6.2", 186);
+ }
- list = obs_properties_add_list(props, "level", obs_module_text("Level"),
- OBS_COMBO_TYPE_LIST,
- OBS_COMBO_FORMAT_INT);
- obs_property_list_add_int(list, "Auto", FF_LEVEL_UNKNOWN);
- obs_property_list_add_int(list, "3.0", 30);
- obs_property_list_add_int(list, "3.1", 31);
- obs_property_list_add_int(list, "4.0 (default) (Compatibility mode)",
- 40);
- obs_property_list_add_int(list, "4.1", 41);
- obs_property_list_add_int(list, "4.2", 42);
- obs_property_list_add_int(list, "5.0", 50);
- obs_property_list_add_int(list, "5.1", 51);
- obs_property_list_add_int(list, "5.2", 52);
-
- list = obs_properties_add_list(props, "rate_control",
- obs_module_text("RateControl"),
- OBS_COMBO_TYPE_LIST,
- OBS_COMBO_FORMAT_STRING);
+ list = obs_properties_add_list(props, "rate_control",
+ obs_module_text("RateControl"),
+ OBS_COMBO_TYPE_LIST,
+ OBS_COMBO_FORMAT_STRING);
obs_property_list_add_string(list, "CBR (default)", "CBR");
obs_property_list_add_string(list, "CQP", "CQP");
obs_property_list_add_string(list, "VBR", "VBR");
@@ -691,6 +764,7 @@ static obs_properties_t *vaapi_properties(void *unused)
20, 1);
obs_property_int_set_suffix(p, " s");
+ dstr_free(&name);
return props;
}
@@ -720,11 +794,28 @@ struct obs_encoder_info vaapi_encoder_info = {
.create = vaapi_create,
.destroy = vaapi_destroy,
.encode = vaapi_encode,
- .get_defaults = vaapi_defaults,
- .get_properties = vaapi_properties,
+ .get_defaults2 = vaapi_defaults,
+ .get_properties2 = vaapi_properties,
+ .get_extra_data = vaapi_extra_data,
+ .get_sei_data = vaapi_sei_data,
+ .get_video_info = vaapi_video_info,
+ .type_data = &h264_type,
+};
+
+struct obs_encoder_info vaapi_hevc_encoder_info = {
+ .id = "ffmpeg_vaapi_hevc",
+ .type = OBS_ENCODER_VIDEO,
+ .codec = "hevc",
+ .get_name = vaapi_getname,
+ .create = vaapi_create,
+ .destroy = vaapi_destroy,
+ .encode = vaapi_encode,
+ .get_defaults2 = vaapi_defaults,
+ .get_properties2 = vaapi_properties,
.get_extra_data = vaapi_extra_data,
.get_sei_data = vaapi_sei_data,
.get_video_info = vaapi_video_info,
+ .type_data = &hevc_type,
};
#endif
diff --git a/plugins/obs-ffmpeg/obs-ffmpeg.c b/plugins/obs-ffmpeg/obs-ffmpeg.c
index 1d1131d13..382958c7b 100644
--- a/plugins/obs-ffmpeg/obs-ffmpeg.c
+++ b/plugins/obs-ffmpeg/obs-ffmpeg.c
@@ -40,6 +40,7 @@ extern struct obs_encoder_info aom_av1_encoder_info;
#ifdef LIBAVUTIL_VAAPI_AVAILABLE
extern struct obs_encoder_info vaapi_encoder_info;
+extern struct obs_encoder_info vaapi_hevc_encoder_info;
#endif
#ifndef __APPLE__
@@ -284,9 +285,9 @@ static bool nvenc_supported(bool *out_h264, bool *out_hevc)
#endif
#ifdef LIBAVUTIL_VAAPI_AVAILABLE
-static bool vaapi_supported(void)
+static bool vaapi_supported(const char *codec_name)
{
- const AVCodec *vaenc = avcodec_find_encoder_by_name("h264_vaapi");
+ const AVCodec *vaenc = avcodec_find_encoder_by_name(codec_name);
return !!vaenc;
}
#endif
@@ -361,9 +362,13 @@ bool obs_module_load(void)
#endif
#if !defined(_WIN32) && defined(LIBAVUTIL_VAAPI_AVAILABLE)
- if (vaapi_supported()) {
- blog(LOG_INFO, "FFMPEG VAAPI supported");
- obs_register_encoder(&vaapi_encoder_info);
+ if (vaapi_supported("h264_vaapi")) {
+ blog(LOG_INFO, "FFMPEG VAAPI supported");
+ obs_register_encoder(&vaapi_encoder_info);
+ }
+ if (vaapi_supported("hevc_vaapi")) {
+ blog(LOG_INFO, "FFMPEG HEVC VAAPI supported");
+ obs_register_encoder(&vaapi_hevc_encoder_info);
}
#endif
#endif