diff --git a/.gitignore b/.gitignore index 1776a9544..747a7c65a 100644 --- a/.gitignore +++ b/.gitignore @@ -27,6 +27,7 @@ #clion .idea/ +cmake-build-debug/ #other stuff (windows stuff, qt moc stuff, etc) Release_MD/ @@ -39,6 +40,8 @@ GeneratedFiles/ /UI/obs.rc .vscode/ + + /other/ #make stuff diff --git a/plugins/linux-v4l2/data/locale/en-US.ini b/plugins/linux-v4l2/data/locale/en-US.ini index 985226177..df11f93dc 100644 --- a/plugins/linux-v4l2/data/locale/en-US.ini +++ b/plugins/linux-v4l2/data/locale/en-US.ini @@ -12,3 +12,4 @@ ColorRange="Color Range" ColorRange.Default="Default" ColorRange.Partial="Partial" ColorRange.Full="Full" +CameraCtrls="Camera Controls" diff --git a/plugins/linux-v4l2/v4l2-input.c b/plugins/linux-v4l2/v4l2-input.c index 5c7957bb5..47448c233 100644 --- a/plugins/linux-v4l2/v4l2-input.c +++ b/plugins/linux-v4l2/v4l2-input.c @@ -81,6 +81,8 @@ struct v4l2_data { pthread_t thread; os_event_t *event; + bool framerateUnchanged; + bool resolutionUnchanged; int_fast32_t dev; int width; int height; @@ -91,6 +93,7 @@ struct v4l2_data { /* forward declarations */ static void v4l2_init(struct v4l2_data *data); static void v4l2_terminate(struct v4l2_data *data); +static void v4l2_update(void *vptr, obs_data_t *settings); /** * Prepare the output frame structure for obs and compute plane offsets @@ -579,10 +582,18 @@ static bool device_selected(obs_properties_t *props, obs_property_t *p, return false; obs_property_t *prop = obs_properties_get(props, "input"); + obs_properties_t *ctrl_props_new = obs_properties_create(); + + obs_properties_remove_by_name(props, "controls"); + v4l2_input_list(dev, prop); - v4l2_update_controls(dev, props, settings); + v4l2_update_controls(dev, ctrl_props_new, settings); v4l2_close(dev); + obs_properties_add_group(props, "controls", + obs_module_text("CameraCtrls"), + OBS_GROUP_NORMAL, ctrl_props_new); + obs_property_modified(prop, settings); return true; @@ -785,6 +796,12 @@ static obs_properties_t *v4l2_properties(void *vptr) obs_properties_add_bool(props, "buffering", obs_module_text("UseBuffering")); + // a group to contain the camera control + obs_properties_t *ctrl_props = obs_properties_create(); + obs_properties_add_group(props, "controls", + obs_module_text("CameraCtrls"), + OBS_GROUP_NORMAL, ctrl_props); + obs_data_t *settings = obs_source_get_settings(data->source); v4l2_device_list(device_list, settings); obs_data_release(settings); @@ -939,19 +956,78 @@ static void v4l2_update_source_flags(struct v4l2_data *data, data->source, !obs_data_get_bool(settings, "buffering")); } +/** + * Checking if any of the settings have changed so that we can restart the + * stream + */ +static bool v4l2_settings_changed(struct v4l2_data *data, obs_data_t *settings) +{ + bool res = false; + + if (obs_data_get_string(settings, "device_id") != NULL && + data->device_id != NULL) { + res |= strcmp(data->device_id, + obs_data_get_string(settings, "device_id")) != 0; + res |= data->input != obs_data_get_int(settings, "input"); + res |= data->pixfmt != + obs_data_get_int(settings, "pixelformat"); + res |= data->standard != obs_data_get_int(settings, "standard"); + res |= data->dv_timing != + obs_data_get_int(settings, "dv_timing"); + + if (obs_data_get_int(settings, "resolution") == -1 && + !data->resolutionUnchanged) { + data->resolutionUnchanged = true; + res |= true; + } else if (obs_data_get_int(settings, "resolution") == -1 && + data->resolutionUnchanged) { + res |= false; + } else { + data->resolutionUnchanged = false; + res |= (data->resolution != + obs_data_get_int(settings, "resolution")) && + (obs_data_get_int(settings, "resolution") != -1); + } + + if (obs_data_get_int(settings, "framerate") == -1 && + !data->framerateUnchanged) { + data->framerateUnchanged = true; + res |= true; + } else if (obs_data_get_int(settings, "framerate") == -1 && + data->framerateUnchanged) { + res |= false; + } else { + data->framerateUnchanged = false; + res |= (data->framerate != + obs_data_get_int(settings, "framerate")) && + (obs_data_get_int(settings, "framerate") != -1); + } + + res |= data->color_range != + obs_data_get_int(settings, "color_range"); + } else { + res = true; + } + + return res; +} + /** * Update the settings for the v4l2 source * - * Since there are very few settings that can be changed without restarting the - * stream we don't bother to even try. Whenever this is called the currently - * active stream (if exists) is stopped, the settings are updated and finally - * the new stream is started. + * There are a few settings that can be changed without restarting the stream + * Whenever this is called the currently active stream (if exists) is stopped, + * the settings are updated and finally the new stream is started. */ static void v4l2_update(void *vptr, obs_data_t *settings) { + V4L2_DATA(vptr); - v4l2_terminate(data); + bool needs_restart = v4l2_settings_changed(data, settings); + + if (needs_restart) + v4l2_terminate(data); if (data->device_id) bfree(data->device_id); @@ -967,7 +1043,8 @@ static void v4l2_update(void *vptr, obs_data_t *settings) v4l2_update_source_flags(data, settings); - v4l2_init(data); + if (needs_restart) + v4l2_init(data); } static void *v4l2_create(obs_data_t *settings, obs_source_t *source) @@ -975,6 +1052,8 @@ static void *v4l2_create(obs_data_t *settings, obs_source_t *source) struct v4l2_data *data = bzalloc(sizeof(struct v4l2_data)); data->dev = -1; data->source = source; + data->resolutionUnchanged = false; + data->framerateUnchanged = false; /* Bitch about build problems ... */ #ifndef V4L2_CAP_DEVICE_CAPS