diff --git a/plugins/win-dshow/libdshowcapture b/plugins/win-dshow/libdshowcapture index ed02c3541..8f2ef910b 160000 --- a/plugins/win-dshow/libdshowcapture +++ b/plugins/win-dshow/libdshowcapture @@ -1 +1 @@ -Subproject commit ed02c3541eaf6c61127669882168f7e8b17e3af0 +Subproject commit 8f2ef910bae88163abd904dd0eeaf027fd09c10a diff --git a/plugins/win-dshow/win-dshow.cpp b/plugins/win-dshow/win-dshow.cpp index 7c527d321..304888312 100644 --- a/plugins/win-dshow/win-dshow.cpp +++ b/plugins/win-dshow/win-dshow.cpp @@ -177,6 +177,7 @@ enum class Action { ConfigAudio, ConfigCrossbar1, ConfigCrossbar2, + SaveSettings, }; static DWORD CALLBACK DShowThread(LPVOID ptr); @@ -204,6 +205,7 @@ struct DShowInput { WinHandle semaphore; WinHandle activated_event; + WinHandle saved_event; WinHandle thread; CriticalSection mutex; vector actions; @@ -243,6 +245,10 @@ struct DShowInput { if (!activated_event) throw "Failed to create activated_event"; + saved_event = CreateEvent(nullptr, false, false, nullptr); + if (!saved_event) + throw "Failed to create saved_event"; + thread = CreateThread(nullptr, 0, DShowThread, this, 0, nullptr); if (!thread) @@ -287,6 +293,8 @@ struct DShowInput { bool UpdateVideoConfig(obs_data_t *settings); bool UpdateAudioConfig(obs_data_t *settings); + bool UpdateVideoProperties(obs_data_t *settings); + void SaveVideoProperties(); void SetActive(bool active); inline enum video_colorspace GetColorSpace(obs_data_t *settings) const; inline enum video_range_type GetColorRange(obs_data_t *settings) const; @@ -381,6 +389,9 @@ void DShowInput::DShowLoop() device.OpenDialog(nullptr, DialogType::ConfigCrossbar2); break; + case Action::SaveSettings: + SaveVideoProperties(); + break; case Action::None:; } } @@ -1018,6 +1029,102 @@ bool DShowInput::UpdateVideoConfig(obs_data_t *settings) return true; } +bool DShowInput::UpdateVideoProperties(obs_data_t *settings) +{ + OBSDataArrayAutoRelease cca = + obs_data_get_array(settings, "CameraControl"); + + if (cca) { + std::vector properties; + const auto count = obs_data_array_count(cca); + + for (size_t i = 0; i < count; i++) { + OBSDataAutoRelease item = obs_data_array_item(cca, i); + if (!item) + continue; + + VideoDeviceProperty prop{}; + prop.property = + (long)obs_data_get_int(item, "property"); + prop.flags = (long)obs_data_get_int(item, "flags"); + prop.val = (long)obs_data_get_int(item, "val"); + properties.push_back(prop); + } + + if (!properties.empty()) { + device.SetCameraControlProperties(&properties); + } + } + + OBSDataArrayAutoRelease vpaa = + obs_data_get_array(settings, "VideoProcAmp"); + + if (vpaa) { + std::vector properties; + const auto count = obs_data_array_count(vpaa); + + for (size_t i = 0; i < count; i++) { + OBSDataAutoRelease item = obs_data_array_item(vpaa, i); + if (!item) + continue; + + VideoDeviceProperty prop{}; + prop.property = + (long)obs_data_get_int(item, "property"); + prop.flags = (long)obs_data_get_int(item, "flags"); + prop.val = (long)obs_data_get_int(item, "val"); + properties.push_back(prop); + } + + if (!properties.empty()) { + device.SetVideoProcAmpProperties(&properties); + } + } + + return true; +} + +void DShowInput::SaveVideoProperties() +{ + OBSDataAutoRelease settings = obs_source_get_settings(source); + if (!settings) { + SetEvent(saved_event); + return; + } + + std::vector properties; + OBSDataArrayAutoRelease ccp = obs_data_array_create(); + + if (device.GetCameraControlProperties(properties)) { + for (const auto property : properties) { + OBSDataAutoRelease obj = obs_data_create(); + obs_data_set_int(obj, "property", property.property); + obs_data_set_int(obj, "flags", property.flags); + obs_data_set_int(obj, "val", property.val); + obs_data_array_push_back(ccp, obj); + } + } + + obs_data_set_array(settings, "CameraControl", ccp); + properties.clear(); + + OBSDataArrayAutoRelease vpap = obs_data_array_create(); + + if (device.GetVideoProcAmpProperties(properties)) { + for (const auto property : properties) { + OBSDataAutoRelease obj = obs_data_create(); + obs_data_set_int(obj, "property", property.property); + obs_data_set_int(obj, "flags", property.flags); + obs_data_set_int(obj, "val", property.val); + obs_data_array_push_back(vpap, obj); + } + } + + obs_data_set_array(settings, "VideoProcAmp", vpap); + + SetEvent(saved_event); +} + bool DShowInput::UpdateAudioConfig(obs_data_t *settings) { string audio_device_id = obs_data_get_string(settings, AUDIO_DEVICE_ID); @@ -1155,6 +1262,11 @@ inline bool DShowInput::Activate(obs_data_t *settings) if (device.Start() != Result::Success) return false; + if (!UpdateVideoProperties(settings)) { + blog(LOG_WARNING, "%s: Setting video device properties failed", + obs_source_get_name(source)); + } + const enum video_colorspace cs = GetColorSpace(settings); const enum video_range_type range = GetColorRange(settings); @@ -1239,6 +1351,16 @@ static void UpdateDShowInput(void *data, obs_data_t *settings) input->QueueActivate(settings); } +static void SaveDShowInput(void *data, obs_data_t *settings) +{ + DShowInput *input = reinterpret_cast(data); + if (!input->active) + return; + + input->QueueAction(Action::SaveSettings); + WaitForSingleObject(input->saved_event, INFINITE); +} + static void GetDShowDefaults(obs_data_t *settings) { obs_data_set_default_int(settings, FRAME_INTERVAL, FPS_MATCHING); @@ -2102,6 +2224,7 @@ void RegisterDShowSource() info.update = UpdateDShowInput; info.get_defaults = GetDShowDefaults; info.get_properties = GetDShowProperties; + info.save = SaveDShowInput; info.icon_type = OBS_ICON_TYPE_CAMERA; obs_register_source(&info); }