#include #include "decklink-device.hpp" #include DeckLinkDevice::DeckLinkDevice(IDeckLink *device_) : device(device_) {} DeckLinkDevice::~DeckLinkDevice(void) { for (DeckLinkDeviceMode *mode : inputModes) delete mode; for (DeckLinkDeviceMode *mode : outputModes) delete mode; } ULONG DeckLinkDevice::AddRef() { return os_atomic_inc_long(&refCount); } ULONG DeckLinkDevice::Release() { long ret = os_atomic_dec_long(&refCount); if (ret == 0) delete this; return ret; } bool DeckLinkDevice::Init() { ComPtr attributes; const HRESULT result = device->QueryInterface( IID_IDeckLinkProfileAttributes, (void **)&attributes); if (result == S_OK) { decklink_bool_t detectable = false; if (attributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &detectable) == S_OK && !!detectable) { DeckLinkDeviceMode *mode = new DeckLinkDeviceMode("Auto", MODE_ID_AUTO); inputModes.push_back(mode); inputModeIdMap[MODE_ID_AUTO] = mode; } } // Find input modes ComPtr input; if (device->QueryInterface(IID_IDeckLinkInput, (void **)&input) == S_OK) { ComPtr modeIterator; if (input->GetDisplayModeIterator(&modeIterator) == S_OK) { ComPtr displayMode; long long modeId = 1; while (modeIterator->Next(&displayMode) == S_OK) { if (displayMode == nullptr) continue; DeckLinkDeviceMode *mode = new DeckLinkDeviceMode(displayMode, modeId); inputModes.push_back(mode); inputModeIdMap[modeId] = mode; ++modeId; } } } // Get supported video connections attributes->GetInt(BMDDeckLinkVideoInputConnections, &supportedVideoInputConnections); attributes->GetInt(BMDDeckLinkVideoOutputConnections, &supportedVideoOutputConnections); // Get supported audio connections attributes->GetInt(BMDDeckLinkAudioInputConnections, &supportedAudioInputConnections); attributes->GetInt(BMDDeckLinkAudioOutputConnections, &supportedAudioOutputConnections); // find output modes ComPtr output; if (device->QueryInterface(IID_IDeckLinkOutput, (void **)&output) == S_OK) { ComPtr modeIterator; if (output->GetDisplayModeIterator(&modeIterator) == S_OK) { ComPtr displayMode; long long modeId = 1; while (modeIterator->Next(&displayMode) == S_OK) { if (displayMode == nullptr) continue; DeckLinkDeviceMode *mode = new DeckLinkDeviceMode(displayMode, modeId); outputModes.push_back(mode); outputModeIdMap[modeId] = mode; ++modeId; } } } // get keyer support attributes->GetFlag(BMDDeckLinkSupportsExternalKeying, &supportsExternalKeyer); attributes->GetFlag(BMDDeckLinkSupportsInternalKeying, &supportsInternalKeyer); attributes->GetFlag(BMDDeckLinkSupportsHDRMetadata, &supportsHDRMetadata); // Sub Device Counts attributes->GetInt(BMDDeckLinkSubDeviceIndex, &subDeviceIndex); attributes->GetInt(BMDDeckLinkNumberOfSubDevices, &numSubDevices); if (FAILED(attributes->GetInt(BMDDeckLinkMinimumPrerollFrames, &minimumPrerollFrames))) { minimumPrerollFrames = 3; } decklink_string_t decklinkModelName; decklink_string_t decklinkDisplayName; if (device->GetModelName(&decklinkModelName) != S_OK) return false; DeckLinkStringToStdString(decklinkModelName, name); if (device->GetDisplayName(&decklinkDisplayName) != S_OK) return false; DeckLinkStringToStdString(decklinkDisplayName, displayName); hash = displayName; if (result != S_OK) return true; int64_t channels; /* Intensity Shuttle for Thunderbolt return 2; however, it supports 8 channels */ if (name == "Intensity Shuttle Thunderbolt") maxChannel = 8; else if (attributes->GetInt(BMDDeckLinkMaximumAudioChannels, &channels) == S_OK) maxChannel = (int32_t)channels; else maxChannel = 2; /* http://forum.blackmagicdesign.com/viewtopic.php?f=12&t=33967 * BMDDeckLinkTopologicalID for older devices * BMDDeckLinkPersistentID for newer ones */ int64_t value; if (attributes->GetInt(BMDDeckLinkPersistentID, &value) != S_OK && attributes->GetInt(BMDDeckLinkTopologicalID, &value) != S_OK) return true; std::ostringstream os; os << value << "_" << name; hash = os.str(); return true; } bool DeckLinkDevice::GetInput(IDeckLinkInput **input) { if (device->QueryInterface(IID_IDeckLinkInput, (void **)input) != S_OK) return false; return true; } bool DeckLinkDevice::GetOutput(IDeckLinkOutput **output) { if (device->QueryInterface(IID_IDeckLinkOutput, (void **)output) != S_OK) return false; return true; } bool DeckLinkDevice::GetKeyer(IDeckLinkKeyer **deckLinkKeyer) { if (device->QueryInterface(IID_IDeckLinkKeyer, (void **)deckLinkKeyer) != S_OK) { fprintf(stderr, "Could not obtain the IDeckLinkKeyer interface\n"); return false; } return true; } void DeckLinkDevice::SetKeyerMode(int newKeyerMode) { keyerMode = newKeyerMode; } int DeckLinkDevice::GetKeyerMode(void) { return keyerMode; } DeckLinkDeviceMode *DeckLinkDevice::FindInputMode(long long id) { return inputModeIdMap[id]; } DeckLinkDeviceMode *DeckLinkDevice::FindOutputMode(long long id) { return outputModeIdMap[id]; } const std::string &DeckLinkDevice::GetDisplayName(void) { return displayName; } const std::string &DeckLinkDevice::GetHash(void) const { return hash; } const std::vector & DeckLinkDevice::GetInputModes(void) const { return inputModes; } const std::vector & DeckLinkDevice::GetOutputModes(void) const { return outputModes; } int64_t DeckLinkDevice::GetVideoInputConnections() { return supportedVideoInputConnections; } int64_t DeckLinkDevice::GetAudioInputConnections() { return supportedAudioInputConnections; } bool DeckLinkDevice::GetSupportsExternalKeyer(void) const { return supportsExternalKeyer; } bool DeckLinkDevice::GetSupportsInternalKeyer(void) const { return supportsInternalKeyer; } bool DeckLinkDevice::GetSupportsHDRMetadata(void) const { return supportsHDRMetadata; } int64_t DeckLinkDevice::GetSubDeviceCount() { return numSubDevices; } int64_t DeckLinkDevice::GetSubDeviceIndex() { return subDeviceIndex; } int64_t DeckLinkDevice::GetMinimumPrerollFrames() { return minimumPrerollFrames; } const std::string &DeckLinkDevice::GetName(void) const { return name; } int32_t DeckLinkDevice::GetMaxChannel(void) const { return maxChannel; }