From 7f1cabd81b57d0fa2588a5b9b40a07cee304e8e9 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sun, 8 May 2016 11:16:36 -0700 Subject: [PATCH] obs-x264: Add rate control, deprecate "use cbr" setting Instead of having a "cbr" setting that turns CBR on and off, adds a "rate_control" parameter that sets the rate control method, which can be one of the following: CBR, ABR, VBR, CRF. If the "cbr" setting is used, it will throw a deprecation warning to the log. --- plugins/obs-x264/data/locale/en-US.ini | 2 +- plugins/obs-x264/obs-x264.c | 114 +++++++++++++++++++------ 2 files changed, 87 insertions(+), 29 deletions(-) diff --git a/plugins/obs-x264/data/locale/en-US.ini b/plugins/obs-x264/data/locale/en-US.ini index 8b0eff9bd..fa11b9965 100644 --- a/plugins/obs-x264/data/locale/en-US.ini +++ b/plugins/obs-x264/data/locale/en-US.ini @@ -1,7 +1,7 @@ Bitrate="Bitrate" CustomBufsize="Use Custom Buffer Size" BufferSize="Buffer Size" -UseCBR="Use CBR" +RateControl="Rate Control" CRF="CRF" KeyframeIntervalSec="Keyframe Interval (seconds, 0=auto)" CPUPreset="CPU Usage Preset (higher = less CPU)" diff --git a/plugins/obs-x264/obs-x264.c b/plugins/obs-x264/obs-x264.c index 1c7db3158..193e4457a 100644 --- a/plugins/obs-x264/obs-x264.c +++ b/plugins/obs-x264/obs-x264.c @@ -97,7 +97,7 @@ static void obs_x264_defaults(obs_data_t *settings) obs_data_set_default_int (settings, "keyint_sec", 0); obs_data_set_default_int (settings, "crf", 23); obs_data_set_default_bool (settings, "vfr", false); - obs_data_set_default_bool (settings, "cbr", true); + obs_data_set_default_bool (settings, "rate_control","CBR"); obs_data_set_default_string(settings, "preset", "veryfast"); obs_data_set_default_string(settings, "profile", ""); @@ -113,10 +113,10 @@ static inline void add_strings(obs_property_t *list, const char *const *strings) } } +#define TEXT_RATE_CONTROL obs_module_text("RateControl") #define TEXT_BITRATE obs_module_text("Bitrate") #define TEXT_CUSTOM_BUF obs_module_text("CustomBufsize") #define TEXT_BUF_SIZE obs_module_text("BufferSize") -#define TEXT_USE_CBR obs_module_text("UseCBR") #define TEXT_VFR obs_module_text("VFR") #define TEXT_CRF obs_module_text("CRF") #define TEXT_KEYINT_SEC obs_module_text("KeyframeIntervalSec") @@ -130,17 +130,30 @@ static bool use_bufsize_modified(obs_properties_t *ppts, obs_property_t *p, obs_data_t *settings) { bool use_bufsize = obs_data_get_bool(settings, "use_bufsize"); + const char *rc = obs_data_get_string(settings, "rate_control"); + bool rc_crf = astrcmpi(rc, "CRF") == 0; + p = obs_properties_get(ppts, "buffer_size"); - obs_property_set_visible(p, use_bufsize); + obs_property_set_visible(p, use_bufsize && !rc_crf); return true; } -static bool use_cbr_modified(obs_properties_t *ppts, obs_property_t *p, +static bool rate_control_modified(obs_properties_t *ppts, obs_property_t *p, obs_data_t *settings) { - bool cbr = obs_data_get_bool(settings, "cbr"); + const char *rc = obs_data_get_string(settings, "rate_control"); + bool abr = astrcmpi(rc, "CBR") == 0 || astrcmpi(rc, "ABR") == 0; + bool rc_crf = astrcmpi(rc, "CRF") == 0; + p = obs_properties_get(ppts, "crf"); - obs_property_set_visible(p, !cbr); + obs_property_set_visible(p, !abr); + + p = obs_properties_get(ppts, "bitrate"); + obs_property_set_visible(p, !rc_crf); + p = obs_properties_get(ppts, "use_bufsize"); + obs_property_set_visible(p, !rc_crf); + p = obs_properties_get(ppts, "buffse_size"); + obs_property_set_visible(p, !rc_crf); return true; } @@ -152,6 +165,15 @@ static obs_properties_t *obs_x264_props(void *unused) obs_property_t *list; obs_property_t *p; + list = obs_properties_add_list(props, "rate_control", TEXT_RATE_CONTROL, + OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); + obs_property_list_add_string(list, "CBR", "CBR"); + obs_property_list_add_string(list, "ABR", "ABR"); + obs_property_list_add_string(list, "VBR", "VBR"); + obs_property_list_add_string(list, "CRF", "CRF"); + + obs_property_set_modified_callback(list, rate_control_modified); + obs_properties_add_int(props, "bitrate", TEXT_BITRATE, 50, 10000000, 1); p = obs_properties_add_bool(props, "use_bufsize", TEXT_CUSTOM_BUF); @@ -159,11 +181,9 @@ static obs_properties_t *obs_x264_props(void *unused) obs_properties_add_int(props, "buffer_size", TEXT_BUF_SIZE, 0, 10000000, 1); - obs_properties_add_int(props, "keyint_sec", TEXT_KEYINT_SEC, 0, 20, 1); - p = obs_properties_add_bool(props, "cbr", TEXT_USE_CBR); obs_properties_add_int(props, "crf", TEXT_CRF, 0, 51, 1); - obs_property_set_modified_callback(p, use_cbr_modified); + obs_properties_add_int(props, "keyint_sec", TEXT_KEYINT_SEC, 0, 20, 1); list = obs_properties_add_list(props, "preset", TEXT_PRESET, OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING); @@ -353,6 +373,13 @@ static inline int get_x264_cs_val(enum video_colorspace cs, static void obs_x264_video_info(void *data, struct video_scale_info *info); +enum rate_control { + RATE_CONTROL_CBR, + RATE_CONTROL_VBR, + RATE_CONTROL_ABR, + RATE_CONTROL_CRF +}; + static void update_params(struct obs_x264 *obsx264, obs_data_t *settings, char **params) { @@ -366,6 +393,8 @@ static void update_params(struct obs_x264 *obsx264, obs_data_t *settings, obs_x264_video_info(obsx264, &info); + const char *rate_control = obs_data_get_string(settings, "rate_control"); + int bitrate = (int)obs_data_get_int(settings, "bitrate"); int buffer_size = (int)obs_data_get_int(settings, "buffer_size"); int keyint_sec = (int)obs_data_get_int(settings, "keyint_sec"); @@ -374,7 +403,35 @@ static void update_params(struct obs_x264 *obsx264, obs_data_t *settings, int height = (int)obs_encoder_get_height(obsx264->encoder); bool use_bufsize = obs_data_get_bool(settings, "use_bufsize"); bool vfr = obs_data_get_bool(settings, "vfr"); - bool cbr = obs_data_get_bool(settings, "cbr"); + bool cbr_override= obs_data_get_bool(settings, "cbr"); + enum rate_control rc; + + /* XXX: "cbr" setting has been deprecated */ + if (cbr_override) { + warn("\"cbr\" setting has been deprecated for all encoders! " + "Please set \"rate_control\" to \"CBR\" instead. " + "Forcing CBR mode. " + "(Note to all: this is why you shouldn't use strings for " + "common settings)"); + rate_control = "CBR"; + } + + if (astrcmpi(rate_control, "CBR") == 0) { + rc = RATE_CONTROL_CBR; + crf = 0; + + } else if (astrcmpi(rate_control, "ABR") == 0) { + rc = RATE_CONTROL_ABR; + crf = 0; + + } else if (astrcmpi(rate_control, "VBR") == 0) { + rc = RATE_CONTROL_VBR; + + } else if (astrcmpi(rate_control, "CRF") == 0) { + rc = RATE_CONTROL_CRF; + bitrate = 0; + buffer_size = 0; + } if (keyint_sec) obsx264->params.i_keyint_max = @@ -406,20 +463,22 @@ static void update_params(struct obs_x264 *obsx264, obs_data_t *settings, /* use the new filler method for CBR to allow real-time adjusting of * the bitrate */ - if (cbr) { - obsx264->params.rc.f_rf_constant = 0.0f; + if (rc == RATE_CONTROL_CBR || rc == RATE_CONTROL_ABR) { obsx264->params.rc.i_rc_method = X264_RC_ABR; + if (rc == RATE_CONTROL_CBR) { #if X264_BUILD >= 139 - obsx264->params.rc.b_filler = true; + obsx264->params.rc.b_filler = true; #else - obsx264->params.i_nal_hrd = X264_NAL_HRD_CBR; + obsx264->params.i_nal_hrd = X264_NAL_HRD_CBR; #endif + } } else { obsx264->params.rc.i_rc_method = X264_RC_CRF; - obsx264->params.rc.f_rf_constant = (float)crf; } + obsx264->params.rc.f_rf_constant = (float)crf; + if (info.format == VIDEO_FORMAT_NV12) obsx264->params.i_csp = X264_CSP_NV12; else if (info.format == VIDEO_FORMAT_I420) @@ -433,25 +492,24 @@ static void update_params(struct obs_x264 *obsx264, obs_data_t *settings, set_param(obsx264, *(params++)); info("settings:\n" - "\tbitrate: %d\n" - "\tbuffer size: %d\n" - "\tcrf: %d%s\n" - "\tfps_num: %d\n" - "\tfps_den: %d\n" - "\twidth: %d\n" - "\theight: %d\n" - "\tkeyint: %d\n" - "\tvfr: %s\n" - "\tcbr: %s", + "\trate_control: %s\n" + "\tbitrate: %d\n" + "\tbuffer size: %d\n" + "\tcrf: %d\n" + "\tfps_num: %d\n" + "\tfps_den: %d\n" + "\twidth: %d\n" + "\theight: %d\n" + "\tkeyint: %d\n" + "\tvfr: %s\n", + rate_control, obsx264->params.rc.i_vbv_max_bitrate, obsx264->params.rc.i_vbv_buffer_size, (int)obsx264->params.rc.f_rf_constant, - cbr ? " (0 when CBR is enabled)" : "", voi->fps_num, voi->fps_den, width, height, obsx264->params.i_keyint_max, - vfr ? "on" : "off", - cbr ? "on" : "off"); + vfr ? "on" : "off"); } static bool update_settings(struct obs_x264 *obsx264, obs_data_t *settings)