Browse Source

decklink: Add option to select pixel format

This replaces the name-based detection of the 4K intensity pro, and
allows other devices to be able to use the BGRA pixel format, if the
user so chooses.
jp9000 10 years ago
parent
commit
c77544f546

+ 1 - 0
plugins/decklink/data/locale/en-US.ini

@@ -2,3 +2,4 @@ BlackmagicDevice="Blackmagic Device"
 Device="Device"
 Mode="Mode"
 Buffering="Use Buffering"
+PixelFormat="Pixel Format"

+ 15 - 11
plugins/decklink/decklink-device-instance.cpp

@@ -8,21 +8,22 @@
 #define LOG(level, message, ...) blog(level, "%s: " message, \
 		obs_source_get_name(this->decklink->GetSource()), ##__VA_ARGS__)
 
+static inline enum video_format ConvertPixelFormat(BMDPixelFormat format)
+{
+	switch (format) {
+	case bmdFormat8BitBGRA: return VIDEO_FORMAT_BGRX;
+
+	default:
+	case bmdFormat8BitYUV:;
+	}
+
+	return VIDEO_FORMAT_UYVY;
+}
+
 DeckLinkDeviceInstance::DeckLinkDeviceInstance(DeckLink *decklink_,
 		DeckLinkDevice *device_) :
 	currentFrame(), currentPacket(), decklink(decklink_), device(device_)
 {
-	// use BGRA mode if the device is a BMI intensity pro 4K... wish there
-	// was a better way to check the device model, but older cards don't
-	// implement BMDDeckLinkPersistentID
-	if (std::string("Intensity Pro 4K").compare(device_->GetName()) == 0) {
-		currentFrame.format = VIDEO_FORMAT_BGRX;
-		pixelFormat = bmdFormat8BitBGRA;
-	} else {
-		currentFrame.format = VIDEO_FORMAT_UYVY;
-		pixelFormat = bmdFormat8BitYUV;
-	}
-
 	currentPacket.samples_per_sec = 48000;
 	currentPacket.speakers        = SPEAKERS_STEREO;
 	currentPacket.format          = AUDIO_FORMAT_16BIT;
@@ -89,6 +90,9 @@ bool DeckLinkDeviceInstance::StartCapture(DeckLinkDeviceMode *mode_)
 	if (!device->GetInput(&input))
 		return false;
 
+	pixelFormat = decklink->GetPixelFormat();
+	currentFrame.format = ConvertPixelFormat(pixelFormat);
+
 	input->SetCallback(this);
 
 	const BMDDisplayMode displayMode = mode_->GetDisplayMode();

+ 2 - 0
plugins/decklink/decklink-device-instance.hpp

@@ -28,6 +28,8 @@ public:
 		return mode ? mode->GetId() : 0;
 	}
 
+	inline BMDPixelFormat GetActivePixelFormat() const {return pixelFormat;}
+
 	inline DeckLinkDeviceMode *GetMode() const {return mode;}
 
 	bool StartCapture(DeckLinkDeviceMode *mode);

+ 7 - 2
plugins/decklink/decklink.cpp

@@ -61,8 +61,13 @@ bool DeckLink::Activate(DeckLinkDevice *device, long long modeId)
 	const bool same = device == curDevice;
 	const bool isActive = instance != nullptr;
 
-	if (same && (!isActive || instance->GetActiveModeId() == modeId))
-		return false;
+	if (same) {
+		if (!isActive)
+			return false;
+		if (instance->GetActiveModeId() == modeId &&
+		    instance->GetActivePixelFormat() == pixelFormat)
+			return false;
+	}
 
 	if (isActive)
 		instance->StopCapture();

+ 7 - 0
plugins/decklink/decklink.hpp

@@ -21,6 +21,7 @@ protected:
 	obs_source_t                          *source;
 	volatile long                         activateRefs = 0;
 	std::recursive_mutex                  deviceMutex;
+	BMDPixelFormat                        pixelFormat = bmdFormat8BitYUV;
 
 	void SaveSettings();
 	static void DevicesChanged(void *param, DeckLinkDevice *device,
@@ -35,6 +36,12 @@ public:
 	long long GetActiveModeId(void) const;
 	obs_source_t *GetSource(void) const;
 
+	inline BMDPixelFormat GetPixelFormat() const {return pixelFormat;}
+	inline void SetPixelFormat(BMDPixelFormat format)
+	{
+		pixelFormat = format;
+	}
+
 	bool Activate(DeckLinkDevice *device, long long modeId);
 	void Deactivate();
 };

+ 11 - 0
plugins/decklink/plugin-main.cpp

@@ -42,6 +42,8 @@ static void decklink_update(void *data, obs_data_t *settings)
 	DeckLink *decklink = (DeckLink *)data;
 	const char *hash = obs_data_get_string(settings, "device_hash");
 	long long id = obs_data_get_int(settings, "mode_id");
+	BMDPixelFormat format = (BMDPixelFormat)obs_data_get_int(settings,
+			"pixel_format");
 
 	decklink_enable_buffering(decklink,
 			obs_data_get_bool(settings, "buffering"));
@@ -49,12 +51,14 @@ static void decklink_update(void *data, obs_data_t *settings)
 	ComPtr<DeckLinkDevice> device;
 	device.Set(deviceEnum->FindByHash(hash));
 
+	decklink->SetPixelFormat(format);
 	decklink->Activate(device, id);
 }
 
 static void decklink_get_defaults(obs_data_t *settings)
 {
 	obs_data_set_default_bool(settings, "buffering", true);
+	obs_data_set_default_int(settings, "pixel_format", bmdFormat8BitYUV);
 }
 
 static const char *decklink_get_name(void*)
@@ -139,6 +143,13 @@ static obs_properties_t *decklink_get_properties(void *data)
 			obs_module_text("Mode"), OBS_COMBO_TYPE_LIST,
 			OBS_COMBO_FORMAT_INT);
 
+	list = obs_properties_add_list(props, "pixel_format",
+			obs_module_text("PixelFormat"), OBS_COMBO_TYPE_LIST,
+			OBS_COMBO_FORMAT_INT);
+
+	obs_property_list_add_int(list, "8-bit YUV", bmdFormat8BitYUV);
+	obs_property_list_add_int(list, "8-bit BGRA", bmdFormat8BitBGRA);
+
 	obs_properties_add_bool(props, "buffering",
 			obs_module_text("Buffering"));