#include "DecklinkInput.hpp" #include DeckLinkInput::DeckLinkInput(obs_source_t *source, DeckLinkDeviceDiscovery *discovery_) : DecklinkBase(discovery_), source(source) { discovery->AddCallback(DeckLinkInput::DevicesChanged, this); } DeckLinkInput::~DeckLinkInput(void) { discovery->RemoveCallback(DeckLinkInput::DevicesChanged, this); Deactivate(); } void DeckLinkInput::DevicesChanged(void *param, DeckLinkDevice *device, bool added) { DeckLinkInput *decklink = reinterpret_cast(param); std::lock_guard lock(decklink->deviceMutex); obs_source_update_properties(decklink->source); if (added && !decklink->instance) { const char *hash; long long mode; obs_data_t *settings; BMDVideoConnection videoConnection; BMDAudioConnection audioConnection; settings = obs_source_get_settings(decklink->source); hash = obs_data_get_string(settings, "device_hash"); videoConnection = (BMDVideoConnection) obs_data_get_int(settings, "video_connection"); audioConnection = (BMDAudioConnection) obs_data_get_int(settings, "audio_connection"); mode = obs_data_get_int(settings, "mode_id"); obs_data_release(settings); if (device->GetHash().compare(hash) == 0) { if (!decklink->activateRefs) return; if (decklink->Activate(device, mode, videoConnection, audioConnection)) os_atomic_dec_long(&decklink->activateRefs); } } else if (!added && decklink->instance) { if (decklink->instance->GetDevice() == device) { os_atomic_inc_long(&decklink->activateRefs); decklink->Deactivate(); } } } bool DeckLinkInput::Activate(DeckLinkDevice *device, long long modeId, BMDVideoConnection bmdVideoConnection, BMDAudioConnection bmdAudioConnection) { std::lock_guard lock(deviceMutex); DeckLinkDevice *curDevice = GetDevice(); const bool same = device == curDevice; const bool isActive = instance != nullptr; if (same) { if (!isActive) return false; if (instance->GetActiveModeId() == modeId && instance->GetVideoConnection() == bmdVideoConnection && instance->GetAudioConnection() == bmdAudioConnection && instance->GetActivePixelFormat() == pixelFormat && instance->GetActiveColorSpace() == colorSpace && instance->GetActiveColorRange() == colorRange && instance->GetActiveChannelFormat() == channelFormat && instance->GetActiveSwapState() == swap) return false; } if (isActive) instance->StopCapture(); isCapturing = false; if (!same) instance.Set(new DeckLinkDeviceInstance(this, device)); if (instance == nullptr) return false; if (GetDevice() == nullptr) { LOG(LOG_ERROR, "Tried to activate an input with nullptr device."); return false; } DeckLinkDeviceMode *mode = GetDevice()->FindInputMode(modeId); if (mode == nullptr) { instance = nullptr; return false; } if (!instance->StartCapture(mode, bmdVideoConnection, bmdAudioConnection)) { instance = nullptr; return false; } os_atomic_inc_long(&activateRefs); SaveSettings(); id = modeId; isCapturing = true; return true; } void DeckLinkInput::Deactivate(void) { std::lock_guard lock(deviceMutex); if (instance) instance->StopCapture(); isCapturing = false; instance = nullptr; os_atomic_dec_long(&activateRefs); } bool DeckLinkInput::Capturing(void) { return isCapturing; } void DeckLinkInput::SaveSettings() { if (!instance) return; DeckLinkDevice *device = instance->GetDevice(); DeckLinkDeviceMode *mode = instance->GetMode(); obs_data_t *settings = obs_source_get_settings(source); obs_data_set_string(settings, "device_hash", device->GetHash().c_str()); obs_data_set_string(settings, "device_name", device->GetDisplayName().c_str()); obs_data_set_int(settings, "mode_id", instance->GetActiveModeId()); obs_data_set_string(settings, "mode_name", mode->GetName().c_str()); obs_data_release(settings); } obs_source_t *DeckLinkInput::GetSource(void) const { return source; }