From ebbe8d1bf9bdafd0794d4feb5167fc82830a1501 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Fri, 13 Nov 2020 09:15:41 -0800 Subject: [PATCH] libobs: Change service max res. to res. list (This commit also modifies rtmp-services and UI) Changes the maximum resolution size to a resolution list, and splits the maximum FPS to its own function. (Note: ABI has not been modified because the last changes still haven't been released yet, so it's safe to modify this as long as the changes haven't been officially released) --- UI/window-basic-auto-config-test.cpp | 38 ++++++++++++--- libobs/obs-service.c | 40 +++++++++++----- libobs/obs-service.h | 10 +++- libobs/obs.h | 6 ++- plugins/rtmp-services/data/package.json | 4 +- plugins/rtmp-services/data/services.json | 7 ++- plugins/rtmp-services/rtmp-common.c | 61 ++++++++++++++++++------ 7 files changed, 126 insertions(+), 40 deletions(-) diff --git a/UI/window-basic-auto-config-test.cpp b/UI/window-basic-auto-config-test.cpp index cfa6d8647..a5ba9bda0 100644 --- a/UI/window-basic-auto-config-test.cpp +++ b/UI/window-basic-auto-config-test.cpp @@ -963,6 +963,27 @@ void AutoConfigTestPage::TestRecordingEncoderThread() #define QUALITY_SAME "Basic.Settings.Output.Simple.RecordingQuality.Stream" #define QUALITY_HIGH "Basic.Settings.Output.Simple.RecordingQuality.Small" +void set_closest_res(int &cx, int &cy, struct obs_service_resolution *res_list, + size_t count) +{ + int best_pixel_diff = 0x7FFFFFFF; + int start_cx = cx; + int start_cy = cy; + + for (size_t i = 0; i < count; i++) { + struct obs_service_resolution &res = res_list[i]; + int pixel_cx_diff = abs(start_cx - res.cx); + int pixel_cy_diff = abs(start_cy - res.cy); + int pixel_diff = pixel_cx_diff + pixel_cy_diff; + + if (pixel_diff < best_pixel_diff) { + best_pixel_diff = pixel_diff; + cx = res.cx; + cy = res.cy; + } + } +} + void AutoConfigTestPage::FinalizeResults() { ui->stackedWidget->setCurrentIndex(1); @@ -1013,13 +1034,18 @@ void AutoConfigTestPage::FinalizeResults() obs_service_apply_encoder_settings(service, vencoder_settings, nullptr); - int maxCX, maxCY, maxFPS; - obs_service_get_max_res_fps(service, &maxCX, &maxCY, &maxFPS); + struct obs_service_resolution *res_list; + size_t res_count; + int maxFPS; + obs_service_get_supported_resolutions(service, &res_list, + &res_count); + obs_service_get_max_fps(service, &maxFPS); - if (maxCX && wiz->idealResolutionCX > maxCX) - wiz->idealResolutionCX = maxCX; - if (maxCY && wiz->idealResolutionCY > maxCY) - wiz->idealResolutionCY = maxCY; + if (res_list) { + set_closest_res(wiz->idealResolutionCX, + wiz->idealResolutionCY, res_list, + res_count); + } if (maxFPS) { double idealFPS = (double)wiz->idealFPSNum / (double)wiz->idealFPSDen; diff --git a/libobs/obs-service.c b/libobs/obs-service.c index 02bb686de..e2fb0e8ec 100644 --- a/libobs/obs-service.c +++ b/libobs/obs-service.c @@ -419,22 +419,36 @@ const char *obs_service_get_output_type(const obs_service_t *service) return NULL; } -void obs_service_get_max_res_fps(const obs_service_t *service, int *cx, int *cy, - int *fps) +void obs_service_get_supported_resolutions( + const obs_service_t *service, + struct obs_service_resolution **resolutions, size_t *count) { - if (cx) - *cx = 0; - if (cy) - *cy = 0; - if (fps) - *fps = 0; - - if (!obs_service_valid(service, "obs_service_get_max_res_fps")) + if (!obs_service_valid(service, "obs_service_supported_resolutions")) + return; + if (!obs_ptr_valid(resolutions, "obs_service_supported_resolutions")) + return; + if (!obs_ptr_valid(count, "obs_service_supported_resolutions")) return; - if (service->info.get_max_res_fps) - service->info.get_max_res_fps(service->context.data, cx, cy, - fps); + *resolutions = NULL; + *count = 0; + + if (service->info.get_supported_resolutions) + service->info.get_supported_resolutions(service->context.data, + resolutions, count); +} + +void obs_service_get_max_fps(const obs_service_t *service, int *fps) +{ + if (!obs_service_valid(service, "obs_service_get_max_fps")) + return; + if (!obs_ptr_valid(fps, "obs_service_get_max_fps")) + return; + + *fps = 0; + + if (service->info.get_max_fps) + service->info.get_max_fps(service->context.data, fps); } void obs_service_get_max_bitrate(const obs_service_t *service, diff --git a/libobs/obs-service.h b/libobs/obs-service.h index 88c7bd0cb..697ccb39e 100644 --- a/libobs/obs-service.h +++ b/libobs/obs-service.h @@ -28,6 +28,11 @@ extern "C" { #endif +struct obs_service_resolution { + int cx; + int cy; +}; + struct obs_service_info { /* required */ const char *id; @@ -74,7 +79,10 @@ struct obs_service_info { const char *(*get_output_type)(void *data); - void (*get_max_res_fps)(void *data, int *cx, int *cy, int *fps); + void (*get_supported_resolutions)( + void *data, struct obs_service_resolution **resolutions, + size_t *count); + void (*get_max_fps)(void *data, int *fps); void (*get_max_bitrate)(void *data, int *video_bitrate, int *audio_bitrate); diff --git a/libobs/obs.h b/libobs/obs.h index 35b5fab29..6ad9712f3 100644 --- a/libobs/obs.h +++ b/libobs/obs.h @@ -2231,8 +2231,10 @@ EXPORT void *obs_service_get_type_data(obs_service_t *service); EXPORT const char *obs_service_get_id(const obs_service_t *service); -EXPORT void obs_service_get_max_res_fps(const obs_service_t *service, int *cx, - int *cy, int *fps); +EXPORT void obs_service_get_supported_resolutions( + const obs_service_t *service, + struct obs_service_resolution **resolutions, size_t *count); +EXPORT void obs_service_get_max_fps(const obs_service_t *service, int *fps); EXPORT void obs_service_get_max_bitrate(const obs_service_t *service, int *video_bitrate, int *audio_bitrate); diff --git a/plugins/rtmp-services/data/package.json b/plugins/rtmp-services/data/package.json index 5c3d9bb7c..01024e09b 100644 --- a/plugins/rtmp-services/data/package.json +++ b/plugins/rtmp-services/data/package.json @@ -1,10 +1,10 @@ { "url": "https://obsproject.com/obs2_update/rtmp-services", - "version": 151, + "version": 160, "files": [ { "name": "services.json", - "version": 151 + "version": 160 } ] } diff --git a/plugins/rtmp-services/data/services.json b/plugins/rtmp-services/data/services.json index dccdec08f..68a536c74 100644 --- a/plugins/rtmp-services/data/services.json +++ b/plugins/rtmp-services/data/services.json @@ -477,8 +477,11 @@ "recommended": { "keyint": 2, "profile": "main", - "max width": 1280, - "max height": 720, + "supported resolutions": [ + "1280x720", + "852x480", + "480x360" + ], "max fps": 30, "max video bitrate": 6000, "max audio bitrate": 128 diff --git a/plugins/rtmp-services/rtmp-common.c b/plugins/rtmp-services/rtmp-common.c index 3144ea5a7..2284a6c54 100644 --- a/plugins/rtmp-services/rtmp-common.c +++ b/plugins/rtmp-services/rtmp-common.c @@ -16,8 +16,8 @@ struct rtmp_common { char *key; char *output; - int max_cx; - int max_cy; + struct obs_service_resolution *supported_resolutions; + size_t supported_resolutions_count; int max_fps; bool supports_additional_audio_track; @@ -77,8 +77,34 @@ static void update_recommendations(struct rtmp_common *service, json_t *rec) if (out) service->output = bstrdup(out); - service->max_cx = get_int_val(rec, "max width"); - service->max_cy = get_int_val(rec, "max height"); + json_t *sr = json_object_get(rec, "supported resolutions"); + if (sr && json_is_array(sr)) { + DARRAY(struct obs_service_resolution) res_list; + json_t *res_obj; + size_t index; + + da_init(res_list); + + json_array_foreach (sr, index, res_obj) { + if (!json_is_string(res_obj)) + continue; + + const char *res_str = json_string_value(res_obj); + struct obs_service_resolution res; + if (sscanf(res_str, "%dx%d", &res.cx, &res.cy) != 2) + continue; + if (res.cx <= 0 || res.cy <= 0) + continue; + + da_push_back(res_list, &res); + } + + if (res_list.num) { + service->supported_resolutions = res_list.array; + service->supported_resolutions_count = res_list.num; + } + } + service->max_fps = get_int_val(rec, "max fps"); } @@ -90,14 +116,15 @@ static void rtmp_common_update(void *data, obs_data_t *settings) bfree(service->server); bfree(service->output); bfree(service->key); + bfree(service->supported_resolutions); service->service = bstrdup(obs_data_get_string(settings, "service")); service->server = bstrdup(obs_data_get_string(settings, "server")); service->key = bstrdup(obs_data_get_string(settings, "key")); service->supports_additional_audio_track = false; service->output = NULL; - service->max_cx = 0; - service->max_cy = 0; + service->supported_resolutions = NULL; + service->supported_resolutions_count = 0; service->max_fps = 0; json_t *root = open_services_file(); @@ -131,6 +158,7 @@ static void rtmp_common_destroy(void *data) { struct rtmp_common *service = data; + bfree(service->supported_resolutions); bfree(service->service); bfree(service->server); bfree(service->output); @@ -679,15 +707,19 @@ static bool supports_multitrack(void *data) return service->supports_additional_audio_track; } -static void rtmp_common_get_max_res_fps(void *data, int *cx, int *cy, int *fps) +static void rtmp_common_get_supported_resolutions( + void *data, struct obs_service_resolution **resolutions, size_t *count) { struct rtmp_common *service = data; - if (cx) - *cx = service->max_cx; - if (cy) - *cy = service->max_cy; - if (fps) - *fps = service->max_fps; + *count = service->supported_resolutions_count; + *resolutions = bmemdup(service->supported_resolutions, + *count * sizeof(struct obs_service_resolution)); +} + +static void rtmp_common_get_max_fps(void *data, int *fps) +{ + struct rtmp_common *service = data; + *fps = service->max_fps; } static void rtmp_common_get_max_bitrate(void *data, int *video_bitrate, @@ -737,6 +769,7 @@ struct obs_service_info rtmp_common_service = { .get_key = rtmp_common_key, .apply_encoder_settings = rtmp_common_apply_settings, .get_output_type = rtmp_common_get_output_type, - .get_max_res_fps = rtmp_common_get_max_res_fps, + .get_supported_resolutions = rtmp_common_get_supported_resolutions, + .get_max_fps = rtmp_common_get_max_fps, .get_max_bitrate = rtmp_common_get_max_bitrate, };