Forráskód Böngészése

decklink: Don't show incompatible formats

Changes the formats dropdown for decklink output to only show formats
using the same framerate as OBS does. OBS cannot perform framerate
conversions, meaning that if OBS's framerate is set to 45fps, and
decklink output is set to 60fps, the output will either lag heavily
or simply not function.
tt2468 4 éve
szülő
commit
0698eeda94

+ 18 - 0
plugins/decklink/decklink-device-mode.cpp

@@ -66,6 +66,24 @@ const std::string &DeckLinkDeviceMode::GetName(void) const
 	return name;
 }
 
+bool DeckLinkDeviceMode::IsEqualFrameRate(int64_t num, int64_t den)
+{
+	if (!mode)
+		return false;
+
+	BMDTimeValue timeValue;
+	BMDTimeScale timeScale;
+	if (mode->GetFrameRate(&timeValue, &timeScale) != S_OK)
+		return false;
+
+	// Calculate greatest common divisor of both values to properly compare framerates
+	int decklinkGcd = std::gcd(timeScale, timeValue);
+	int inputGcd = std::gcd(num, den);
+
+	return ((timeScale / decklinkGcd) == (num / inputGcd) &&
+		(timeValue / decklinkGcd) == (den / inputGcd));
+}
+
 void DeckLinkDeviceMode::SetMode(IDeckLinkDisplayMode *mode_)
 {
 	IDeckLinkDisplayMode *old = mode;

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

@@ -3,6 +3,7 @@
 #include "platform.hpp"
 
 #include <string>
+#include <numeric>
 
 #define MODE_ID_AUTO -1
 
@@ -21,6 +22,7 @@ public:
 	BMDDisplayModeFlags GetDisplayModeFlags(void) const;
 	long long GetId(void) const;
 	const std::string &GetName(void) const;
+	bool IsEqualFrameRate(int64_t num, int64_t den);
 
 	void SetMode(IDeckLinkDisplayMode *mode);
 

+ 23 - 4
plugins/decklink/decklink-output.cpp

@@ -66,6 +66,18 @@ static bool decklink_output_start(void *data)
 
 	DeckLinkDeviceMode *mode = device->FindOutputMode(decklink->modeID);
 
+	struct obs_video_info ovi;
+	if (!obs_get_video_info(&ovi)) {
+		LOG(LOG_ERROR,
+		    "Start failed: could not retrieve obs_video_info!");
+		return false;
+	}
+
+	if (!mode->IsEqualFrameRate(ovi.fps_num, ovi.fps_den)) {
+		LOG(LOG_ERROR, "Start failed: FPS mismatch!");
+		return false;
+	}
+
 	decklink->SetSize(mode->GetWidth(), mode->GetHeight());
 
 	struct video_scale_info to = {};
@@ -204,10 +216,17 @@ static bool decklink_output_device_changed(obs_properties_t *props,
 		const std::vector<DeckLinkDeviceMode *> &modes =
 			device->GetOutputModes();
 
-		for (DeckLinkDeviceMode *mode : modes) {
-			obs_property_list_add_int(modeList,
-						  mode->GetName().c_str(),
-						  mode->GetId());
+		struct obs_video_info ovi;
+		if (obs_get_video_info(&ovi)) {
+			for (DeckLinkDeviceMode *mode : modes) {
+				if (mode->IsEqualFrameRate(ovi.fps_num,
+							   ovi.fps_den)) {
+					obs_property_list_add_int(
+						modeList,
+						mode->GetName().c_str(),
+						mode->GetId());
+				}
+			}
 		}
 
 		obs_property_list_add_int(keyerList, "Disabled", 0);