Browse Source

win-dshow: Save and restore video device config props

Exeldro 4 years ago
parent
commit
e52018f210
2 changed files with 124 additions and 1 deletions
  1. 1 1
      plugins/win-dshow/libdshowcapture
  2. 123 0
      plugins/win-dshow/win-dshow.cpp

+ 1 - 1
plugins/win-dshow/libdshowcapture

@@ -1 +1 @@
-Subproject commit ed02c3541eaf6c61127669882168f7e8b17e3af0
+Subproject commit 8f2ef910bae88163abd904dd0eeaf027fd09c10a

+ 123 - 0
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<Action> 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<VideoDeviceProperty> 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<VideoDeviceProperty> 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<VideoDeviceProperty> 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<DShowInput *>(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);
 }