From 7c8ef6f6efca06387705d6347cbd244f47db3f5e Mon Sep 17 00:00:00 2001 From: jp9000 Date: Mon, 16 Jun 2014 21:31:36 -0700 Subject: [PATCH] rtmp-common: Apply service encoder settings Common services that require specific encoder settings (specified in the 'recommended' section of the json file) will now have those encoder settings applied before the encoders start up. This fixes the issue with services like twitch that weren't getting their required 2-second keyframe maximum interval set. --- plugins/rtmp-services/rtmp-common.c | 106 +++++++++++++++++++++++++++- 1 file changed, 104 insertions(+), 2 deletions(-) diff --git a/plugins/rtmp-services/rtmp-common.c b/plugins/rtmp-services/rtmp-common.c index 4cadb990db3da..a6cb2bc197ce5 100644 --- a/plugins/rtmp-services/rtmp-common.c +++ b/plugins/rtmp-services/rtmp-common.c @@ -101,7 +101,7 @@ static void add_services(obs_property_t list, const char *file, json_t *root) } } -static json_t *build_service_list(obs_property_t list, const char *file) +static json_t *open_json_file(const char *file) { char *file_data = os_quick_read_utf8_file(file); json_error_t error; @@ -114,12 +114,18 @@ static json_t *build_service_list(obs_property_t list, const char *file) bfree(file_data); if (!root) { - blog(LOG_WARNING, "rtmp-common.c: [build_service_list] " + blog(LOG_WARNING, "rtmp-common.c: [open_json_file] " "Error reading JSON file '%s' (%d): %s", file, error.line, error.text); return NULL; } + return root; +} + +static json_t *build_service_list(obs_property_t list, const char *file) +{ + json_t *root = open_json_file(file); add_services(list, file, root); return root; } @@ -220,6 +226,101 @@ static obs_properties_t rtmp_common_properties(const char *locale) return ppts; } +static void apply_video_encoder_settings(obs_encoder_t encoder, + json_t *recommended) +{ + obs_data_t settings = obs_encoder_get_settings(encoder); + + json_t *item = json_object_get(recommended, "keyint"); + if (item && json_is_integer(item)) { + int keyint = (int)json_integer_value(item); + obs_data_setint(settings, "keyint_sec", keyint); + } + + item = json_object_get(recommended, "cbr"); + if (item && json_is_boolean(item)) { + bool cbr = json_boolean_value(item); + obs_data_setbool(settings, "cbr", cbr); + } + + item = json_object_get(recommended, "profile"); + if (item && json_is_string(item)) { + const char *profile = json_string_value(item); + obs_data_setbool(settings, "profile", profile); + } + + item = json_object_get(recommended, "max video bitrate"); + if (item && json_is_integer(item)) { + int max_bitrate = (int)json_integer_value(item); + if (obs_data_getint(settings, "bitrate") > max_bitrate) { + obs_data_setint(settings, "bitrate", max_bitrate); + obs_data_setint(settings, "buffer_size", max_bitrate); + } + } + + obs_encoder_update(encoder, settings); + obs_data_release(settings); +} + +static void apply_audio_encoder_settings(obs_encoder_t encoder, + json_t *recommended) +{ + obs_data_t settings = obs_encoder_get_settings(encoder); + + json_t *item = json_object_get(recommended, "max audio bitrate"); + if (item && json_is_integer(item)) { + int max_bitrate = (int)json_integer_value(item); + if (obs_data_getint(settings, "bitrate") > max_bitrate) + obs_data_setint(settings, "bitrate", max_bitrate); + } + + obs_encoder_update(encoder, settings); + obs_data_release(settings); +} + +static void initialize_output(struct rtmp_common *service, obs_output_t output, + json_t *root) +{ + obs_encoder_t video_encoder = obs_output_get_video_encoder(output); + obs_encoder_t audio_encoder = obs_output_get_audio_encoder(output); + json_t *json_service = find_service(root, service->service); + json_t *recommended; + + if (!json_service) { + blog(LOG_WARNING, "rtmp-common.c: [initialize_output] " + "Could not find service '%s'", + service->service); + return; + } + + recommended = json_object_get(json_service, "recommended"); + if (!recommended) + return; + + if (video_encoder) + apply_video_encoder_settings(video_encoder, recommended); + if (audio_encoder) + apply_audio_encoder_settings(audio_encoder, recommended); +} + +static bool rtmp_common_initialize(void *data, obs_output_t output) +{ + struct rtmp_common *service = data; + char *file; + + file = obs_find_plugin_file("rtmp-services/services.json"); + if (file) { + json_t *root = open_json_file(file); + if (root) { + initialize_output(service, output, root); + json_decref(root); + } + bfree(file); + } + + return true; +} + static const char *rtmp_common_url(void *data) { struct rtmp_common *service = data; @@ -239,6 +340,7 @@ struct obs_service_info rtmp_common_service = { .destroy = rtmp_common_destroy, .update = rtmp_common_update, .properties = rtmp_common_properties, + .initialize = rtmp_common_initialize, .get_url = rtmp_common_url, .get_key = rtmp_common_key };