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);