Merge pull request #2220 from dionney/rate_control_vaapi
obs-ffmpeg: Enable VAAPI Rate Control
This commit is contained in:
commit
9ebc3d1352
@ -160,19 +160,69 @@ static bool vaapi_init_codec(struct vaapi_encoder *enc, const char *path)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* "Allowed" options per Rate Control
|
||||
* See FFMPEG libavcodec/vaapi_encode.c (vaapi_encode_rc_modes)
|
||||
*/
|
||||
typedef struct {
|
||||
const char *name;
|
||||
bool qp;
|
||||
bool bitrate;
|
||||
bool maxrate;
|
||||
} rc_mode_t;
|
||||
|
||||
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)
|
||||
rc_mode++;
|
||||
|
||||
return rc_mode ? rc_mode : RC_MODES;
|
||||
}
|
||||
|
||||
static bool vaapi_update(void *data, obs_data_t *settings)
|
||||
{
|
||||
struct vaapi_encoder *enc = data;
|
||||
|
||||
const char *device = obs_data_get_string(settings, "vaapi_device");
|
||||
|
||||
const char *rate_control =
|
||||
obs_data_get_string(settings, "rate_control");
|
||||
const rc_mode_t *rc_mode = get_rc_mode(rate_control);
|
||||
bool cbr = strcmp(rc_mode->name, "CBR") == 0;
|
||||
|
||||
int profile = (int)obs_data_get_int(settings, "profile");
|
||||
int bf = (int)obs_data_get_int(settings, "bf");
|
||||
int qp = rc_mode->qp ? (int)obs_data_get_int(settings, "qp") : 0;
|
||||
|
||||
av_opt_set_int(enc->context->priv_data, "qp", qp, 0);
|
||||
|
||||
int level = (int)obs_data_get_int(settings, "level");
|
||||
int bitrate = (int)obs_data_get_int(settings, "bitrate");
|
||||
int bitrate = rc_mode->bitrate
|
||||
? (int)obs_data_get_int(settings, "bitrate")
|
||||
: 0;
|
||||
int maxrate = rc_mode->maxrate
|
||||
? (int)obs_data_get_int(settings, "maxrate")
|
||||
: 0;
|
||||
int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec");
|
||||
|
||||
/* For Rate Control which allows maxrate, FFMPEG will give
|
||||
* an error if maxrate > bitrate. To prevent that set maxrate
|
||||
* to 0.
|
||||
* For CBR, maxrate = bitrate
|
||||
*/
|
||||
if (cbr)
|
||||
maxrate = bitrate;
|
||||
else if (rc_mode->maxrate && maxrate && maxrate < bitrate)
|
||||
maxrate = 0;
|
||||
|
||||
video_t *video = obs_encoder_video(enc->encoder);
|
||||
const struct video_output_info *voi = video_output_get_info(video);
|
||||
struct video_scale_info info;
|
||||
@ -187,7 +237,7 @@ static bool vaapi_update(void *data, obs_data_t *settings)
|
||||
enc->context->max_b_frames = bf;
|
||||
enc->context->level = level;
|
||||
enc->context->bit_rate = bitrate * 1000;
|
||||
enc->context->rc_max_rate = bitrate * 1000;
|
||||
enc->context->rc_max_rate = maxrate * 1000;
|
||||
|
||||
enc->context->width = obs_encoder_get_width(enc->encoder);
|
||||
enc->context->height = obs_encoder_get_height(enc->encoder);
|
||||
@ -212,15 +262,18 @@ static bool vaapi_update(void *data, obs_data_t *settings)
|
||||
|
||||
info("settings:\n"
|
||||
"\tdevice: %s\n"
|
||||
"\trate_control: %s\n"
|
||||
"\tprofile: %d\n"
|
||||
"\tlevel: %d\n"
|
||||
"\tqp: %d\n"
|
||||
"\tbitrate: %d\n"
|
||||
"\tmaxrate: %d\n"
|
||||
"\tkeyint: %d\n"
|
||||
"\twidth: %d\n"
|
||||
"\theight: %d\n"
|
||||
"\tb-frames: %d\n",
|
||||
device, profile, level, bitrate, enc->context->gop_size,
|
||||
enc->context->width, enc->context->height,
|
||||
device, 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);
|
||||
@ -446,6 +499,27 @@ static void vaapi_defaults(obs_data_t *settings)
|
||||
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_int(settings, "qp", 20);
|
||||
obs_data_set_default_int(settings, "maxrate", 0);
|
||||
}
|
||||
|
||||
static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p,
|
||||
obs_data_t *settings)
|
||||
{
|
||||
UNUSED_PARAMETER(p);
|
||||
|
||||
const char *rate_control =
|
||||
obs_data_get_string(settings, "rate_control");
|
||||
|
||||
const rc_mode_t *rc_mode = get_rc_mode(rate_control);
|
||||
|
||||
/* Set options visibility per Rate Control */
|
||||
set_visible(ppts, "qp", rc_mode->qp);
|
||||
set_visible(ppts, "bitrate", rc_mode->bitrate);
|
||||
set_visible(ppts, "maxrate", rc_mode->maxrate);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static obs_properties_t *vaapi_properties(void *unused)
|
||||
@ -486,14 +560,30 @@ static obs_properties_t *vaapi_properties(void *unused)
|
||||
obs_property_list_add_int(list, "720p60/1080p30 (4.1)", 41);
|
||||
obs_property_list_add_int(list, "1080p60 (4.2)", 42);
|
||||
|
||||
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");
|
||||
|
||||
obs_property_set_modified_callback(list, rate_control_modified);
|
||||
|
||||
obs_property_t *p;
|
||||
p = obs_properties_add_int(props, "bitrate", obs_module_text("Bitrate"),
|
||||
0, 300000, 50);
|
||||
obs_property_int_set_suffix(p, " Kbps");
|
||||
|
||||
p = obs_properties_add_int(
|
||||
props, "maxrate", obs_module_text("MaxBitrate"), 0, 300000, 50);
|
||||
obs_property_int_set_suffix(p, " Kbps");
|
||||
|
||||
obs_properties_add_int(props, "qp", "QP", 0, 51, 1);
|
||||
|
||||
obs_properties_add_int(props, "keyint_sec",
|
||||
obs_module_text("Keyframe Interval (seconds)"),
|
||||
0, 20, 1);
|
||||
obs_module_text("KeyframeIntervalSec"), 0, 20,
|
||||
1);
|
||||
|
||||
return props;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user