From 419d6b1a2217fc703077f523b3711f75577661f6 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Sat, 23 Jan 2016 02:31:45 -0800 Subject: [PATCH] obs-ffmpeg: Refactor media source properties Reactors a bit of code related to starting up FFmpeg and makes it so the initial view for the media source's properties displays the most commonly desired settings. Instead of the media source properties showing the URL mode by default along with a whole bunch of properties that are confusing to most users, starts on file mode and changes defaults to be a bit more sensible related to file input. Also, as a temporary measure for fixing color format issues (some video files would display their color information incorrectly), forced format conversion is now enabled by default, and has been moved to advanced settings. Ideally, the actual bug causing color format issues in either media-io or libff should be fixed at some point. --- plugins/obs-ffmpeg/obs-ffmpeg-source.c | 178 +++++++++++++++---------- 1 file changed, 108 insertions(+), 70 deletions(-) diff --git a/plugins/obs-ffmpeg/obs-ffmpeg-source.c b/plugins/obs-ffmpeg/obs-ffmpeg-source.c index 0a55019af..90d199319 100644 --- a/plugins/obs-ffmpeg/obs-ffmpeg-source.c +++ b/plugins/obs-ffmpeg/obs-ffmpeg-source.c @@ -45,6 +45,14 @@ struct ffmpeg_source { uint8_t *sws_data; int sws_linesize; obs_source_t *source; + + char *input; + char *input_format; + enum AVDiscard frame_drop; + int audio_buffer_size; + int video_buffer_size; + bool is_advanced; + bool is_looping; bool is_forcing_scale; bool is_hw_decoding; bool is_clear_on_media_end; @@ -303,9 +311,11 @@ static bool is_advanced_modified(obs_properties_t *props, UNUSED_PARAMETER(prop); bool enabled = obs_data_get_bool(settings, "advanced"); + obs_property_t *fscale = obs_properties_get(props, "force_scale"); obs_property_t *abuf = obs_properties_get(props, "audio_buffer_size"); obs_property_t *vbuf = obs_properties_get(props, "video_buffer_size"); obs_property_t *frame_drop = obs_properties_get(props, "frame_drop"); + obs_property_set_visible(fscale, enabled); obs_property_set_visible(abuf, enabled); obs_property_set_visible(vbuf, enabled); obs_property_set_visible(frame_drop, enabled); @@ -313,6 +323,17 @@ static bool is_advanced_modified(obs_properties_t *props, return true; } +static void ffmpeg_source_defaults(obs_data_t *settings) +{ + obs_data_set_default_bool(settings, "is_local_file", true); + obs_data_set_default_bool(settings, "looping", false); + obs_data_set_default_bool(settings, "clear_on_media_end", true); + obs_data_set_default_bool(settings, "force_scale", true); +#if defined(_WIN32) || defined(__APPLE__) + obs_data_set_default_bool(settings, "hw_decode", true); +#endif +} + static const char *media_filter = " (*.mp4 *.ts *.mov *.flv *.mkv *.avi *.mp3 *.ogg *.aac *.wav *.gif *.webm);;"; static const char *video_filter = @@ -358,9 +379,6 @@ static obs_properties_t *ffmpeg_source_getproperties(void *data) obs_properties_add_text(props, "input_format", obs_module_text("InputFormat"), OBS_TEXT_DEFAULT); - obs_properties_add_bool(props, "force_scale", - obs_module_text("ForceFormat")); - obs_properties_add_bool(props, "hw_decode", obs_module_text("HardwareDecode")); @@ -372,6 +390,9 @@ static obs_properties_t *ffmpeg_source_getproperties(void *data) obs_property_set_modified_callback(prop, is_advanced_modified); + obs_properties_add_bool(props, "force_scale", + obs_module_text("ForceFormat")); + prop = obs_properties_add_int(props, "audio_buffer_size", obs_module_text("AudioBufferSize"), 1, 9999, 1); @@ -440,7 +461,7 @@ static void dump_source_info(struct ffmpeg_source *s, const char *input, "\tis_clear_on_media_end: %s", input ? input : "(null)", input_format ? input_format : "(null)", - s->demuxer->options.is_looping ? "yes" : "no", + s->is_looping ? "yes" : "no", s->is_forcing_scale ? "yes" : "no", s->is_hw_decoding ? "yes" : "no", s->is_clear_on_media_end ? "yes" : "no"); @@ -453,74 +474,19 @@ static void dump_source_info(struct ffmpeg_source *s, const char *input, "\taudio_buffer_size: %d\n" "\tvideo_buffer_size: %d\n" "\tframe_drop: %s", - s->demuxer->options.audio_frame_queue_size, - s->demuxer->options.video_frame_queue_size, - frame_drop_to_str(s->demuxer->options.frame_drop)); + s->audio_buffer_size, + s->video_buffer_size, + frame_drop_to_str(s->frame_drop)); } -static void ffmpeg_source_update(void *data, obs_data_t *settings) +static void ffmpeg_source_start(struct ffmpeg_source *s) { - struct ffmpeg_source *s = data; - - bool is_local_file = obs_data_get_bool(settings, "is_local_file"); - bool is_advanced = obs_data_get_bool(settings, "advanced"); - - bool is_looping; - char *input; - char *input_format; - - if (is_local_file) { - input = (char *)obs_data_get_string(settings, "local_file"); - input_format = NULL; - is_looping = obs_data_get_bool(settings, "looping"); - } else { - input = (char *)obs_data_get_string(settings, "input"); - input_format = (char *)obs_data_get_string(settings, - "input_format"); - is_looping = false; - } - - s->is_forcing_scale = obs_data_get_bool(settings, "force_scale"); - s->is_hw_decoding = obs_data_get_bool(settings, "hw_decode"); - s->is_clear_on_media_end = obs_data_get_bool(settings, - "clear_on_media_end"); - if (s->demuxer != NULL) ff_demuxer_free(s->demuxer); s->demuxer = ff_demuxer_init(); s->demuxer->options.is_hw_decoding = s->is_hw_decoding; - s->demuxer->options.is_looping = is_looping; - - if (is_advanced) { - int audio_buffer_size = (int)obs_data_get_int(settings, - "audio_buffer_size"); - int video_buffer_size = (int)obs_data_get_int(settings, - "video_buffer_size"); - enum AVDiscard frame_drop = - (enum AVDiscard)obs_data_get_int(settings, - "frame_drop"); - - if (audio_buffer_size < 1) { - audio_buffer_size = 1; - FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", - audio_buffer_size); - } - if (video_buffer_size < 1) { - video_buffer_size = 1; - FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", - audio_buffer_size); - } - s->demuxer->options.audio_frame_queue_size = audio_buffer_size; - s->demuxer->options.video_frame_queue_size = video_buffer_size; - - if (frame_drop < AVDISCARD_NONE || frame_drop > AVDISCARD_ALL) { - frame_drop = AVDISCARD_NONE; - FF_BLOG(LOG_WARNING, "invalid frame_drop %d", - frame_drop); - } - s->demuxer->options.frame_drop = frame_drop; - } + s->demuxer->options.is_looping = s->is_looping; ff_demuxer_set_callbacks(&s->demuxer->video_callbacks, video_frame, NULL, @@ -530,11 +496,81 @@ static void ffmpeg_source_update(void *data, obs_data_t *settings) audio_frame, NULL, NULL, NULL, NULL, s); - dump_source_info(s, input, input_format, is_advanced); + if (s->is_advanced) { + s->demuxer->options.audio_frame_queue_size = + s->audio_buffer_size; + s->demuxer->options.video_frame_queue_size = + s->video_buffer_size; + s->demuxer->options.frame_drop = s->frame_drop; + } - ff_demuxer_open(s->demuxer, input, input_format); + ff_demuxer_open(s->demuxer, s->input, s->input_format); } +static void ffmpeg_source_update(void *data, obs_data_t *settings) +{ + struct ffmpeg_source *s = data; + + bool is_local_file = obs_data_get_bool(settings, "is_local_file"); + bool is_advanced = obs_data_get_bool(settings, "advanced"); + + char *input; + char *input_format; + + bfree(s->input); + bfree(s->input_format); + + if (is_local_file) { + input = (char *)obs_data_get_string(settings, "local_file"); + input_format = NULL; + s->is_looping = obs_data_get_bool(settings, "looping"); + } else { + input = (char *)obs_data_get_string(settings, "input"); + input_format = (char *)obs_data_get_string(settings, + "input_format"); + s->is_looping = false; + } + + s->input = input ? bstrdup(input) : NULL; + s->input_format = input_format ? bstrdup(input_format) : NULL; + s->is_advanced = is_advanced; + s->is_hw_decoding = obs_data_get_bool(settings, "hw_decode"); + s->is_clear_on_media_end = obs_data_get_bool(settings, + "clear_on_media_end"); + s->is_forcing_scale = true; + + if (is_advanced) { + s->audio_buffer_size = (int)obs_data_get_int(settings, + "audio_buffer_size"); + s->video_buffer_size = (int)obs_data_get_int(settings, + "video_buffer_size"); + s->frame_drop = (enum AVDiscard)obs_data_get_int(settings, + "frame_drop"); + s->is_forcing_scale = obs_data_get_bool(settings, + "force_scale"); + + if (s->audio_buffer_size < 1) { + s->audio_buffer_size = 1; + FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", + s->audio_buffer_size); + } + if (s->video_buffer_size < 1) { + s->video_buffer_size = 1; + FF_BLOG(LOG_WARNING, "invalid audio_buffer_size %d", + s->audio_buffer_size); + } + + if (s->frame_drop < AVDISCARD_NONE || + s->frame_drop > AVDISCARD_ALL) { + s->frame_drop = AVDISCARD_DEFAULT; + FF_BLOG(LOG_WARNING, "invalid frame_drop %d", + s->frame_drop); + } + } + + dump_source_info(s, input, input_format, is_advanced); + ffmpeg_source_start(s); +} static const char *ffmpeg_source_getname(void *unused) { @@ -557,13 +593,14 @@ static void ffmpeg_source_destroy(void *data) { struct ffmpeg_source *s = data; - ff_demuxer_free(s->demuxer); + if (s->demuxer) + ff_demuxer_free(s->demuxer); if (s->sws_ctx != NULL) sws_freeContext(s->sws_ctx); - if (s->sws_data != NULL) - bfree(s->sws_data); - + bfree(s->sws_data); + bfree(s->input); + bfree(s->input_format); bfree(s); } @@ -574,6 +611,7 @@ struct obs_source_info ffmpeg_source = { .get_name = ffmpeg_source_getname, .create = ffmpeg_source_create, .destroy = ffmpeg_source_destroy, + .get_defaults = ffmpeg_source_defaults, .get_properties = ffmpeg_source_getproperties, .update = ffmpeg_source_update };