From 0698eeda948bbc9b1c7505d534dec4f08e8a7771 Mon Sep 17 00:00:00 2001 From: tt2468 Date: Tue, 20 Apr 2021 22:24:33 -0700 Subject: [PATCH] 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. --- plugins/decklink/decklink-device-mode.cpp | 18 +++++++++++++++ plugins/decklink/decklink-device-mode.hpp | 2 ++ plugins/decklink/decklink-output.cpp | 27 +++++++++++++++++++---- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/plugins/decklink/decklink-device-mode.cpp b/plugins/decklink/decklink-device-mode.cpp index b2f210713..805284e4d 100644 --- a/plugins/decklink/decklink-device-mode.cpp +++ b/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; diff --git a/plugins/decklink/decklink-device-mode.hpp b/plugins/decklink/decklink-device-mode.hpp index 51e1f8bb6..8e796d5d8 100644 --- a/plugins/decklink/decklink-device-mode.hpp +++ b/plugins/decklink/decklink-device-mode.hpp @@ -3,6 +3,7 @@ #include "platform.hpp" #include +#include #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); diff --git a/plugins/decklink/decklink-output.cpp b/plugins/decklink/decklink-output.cpp index 46b42da4b..4f3f81dd2 100644 --- a/plugins/decklink/decklink-output.cpp +++ b/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 &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);