aja: Refactor, clean-up and fix bugs in the signal routing system, and add SDITransport UI option to assist signal routing.

master
Paul Hindt 2022-01-07 18:45:08 -08:00 committed by Colin Edwards
parent d78971b4db
commit f09137a2e0
32 changed files with 2806 additions and 3297 deletions

View File

@ -42,15 +42,22 @@ void AJAOutputUI::SetupPropertiesView()
obs_data_apply(settings, data);
} else {
// apply default settings
obs_data_set_int(settings, kUIPropOutput.id,
static_cast<long long>(IOSelection::Invalid));
obs_data_set_int(settings, kUIPropVideoFormatSelect.id,
static_cast<long long>(NTV2_FORMAT_720p_5994));
obs_data_set_int(settings, kUIPropPixelFormatSelect.id,
static_cast<long long>(NTV2_FBF_8BIT_YCBCR));
obs_data_set_int(settings, kUIPropSDI4KTransport.id,
static_cast<long long>(
SDI4KTransport::TwoSampleInterleave));
obs_data_set_default_int(
settings, kUIPropOutput.id,
static_cast<long long>(IOSelection::Invalid));
obs_data_set_default_int(
settings, kUIPropVideoFormatSelect.id,
static_cast<long long>(NTV2_FORMAT_720p_5994));
obs_data_set_default_int(
settings, kUIPropPixelFormatSelect.id,
static_cast<long long>(NTV2_FBF_8BIT_YCBCR));
obs_data_set_default_int(
settings, kUIPropSDITransport.id,
static_cast<long long>(SDITransport::SingleLink));
obs_data_set_default_int(
settings, kUIPropSDITransport4K.id,
static_cast<long long>(
SDITransport4K::TwoSampleInterleave));
}
// Assign an ID to the program output plugin instance for channel usage tracking
@ -93,15 +100,22 @@ void AJAOutputUI::SetupPreviewPropertiesView()
obs_data_apply(settings, data);
} else {
// apply default settings
obs_data_set_int(settings, kUIPropOutput.id,
static_cast<long long>(IOSelection::Invalid));
obs_data_set_int(settings, kUIPropVideoFormatSelect.id,
static_cast<long long>(NTV2_FORMAT_720p_5994));
obs_data_set_int(settings, kUIPropPixelFormatSelect.id,
static_cast<long long>(NTV2_FBF_8BIT_YCBCR));
obs_data_set_int(settings, kUIPropSDI4KTransport.id,
static_cast<long long>(
SDI4KTransport::TwoSampleInterleave));
obs_data_set_default_int(
settings, kUIPropOutput.id,
static_cast<long long>(IOSelection::Invalid));
obs_data_set_default_int(
settings, kUIPropVideoFormatSelect.id,
static_cast<long long>(NTV2_FORMAT_720p_5994));
obs_data_set_default_int(
settings, kUIPropPixelFormatSelect.id,
static_cast<long long>(NTV2_FBF_8BIT_YCBCR));
obs_data_set_default_int(
settings, kUIPropSDITransport.id,
static_cast<long long>(SDITransport::SingleLink));
obs_data_set_default_int(
settings, kUIPropSDITransport4K.id,
static_cast<long long>(
SDITransport4K::TwoSampleInterleave));
}
// Assign an ID to the program output plugin instance for channel usage tracking

View File

@ -31,9 +31,11 @@ set(aja_SOURCES
aja-card-manager.cpp
aja-common.cpp
aja-output.cpp
aja-presets.cpp
aja-props.cpp
aja-routing.cpp
aja-source.cpp
aja-vpid-data.cpp
aja-widget-io.cpp)
set(aja_HEADERS
@ -42,9 +44,11 @@ set(aja_HEADERS
aja-enums.hpp
aja-ui-props.hpp
aja-output.hpp
aja-presets.hpp
aja-props.hpp
aja-routing.hpp
aja-source.hpp
aja-vpid-data.hpp
aja-widget-io.hpp)
# macOS

View File

@ -589,6 +589,14 @@ size_t CardManager::NumCardEntries() const
return mCardEntries.size();
}
CNTV2Card *CardManager::GetCard(const std::string &cardID)
{
auto entry = GetCardEntry(cardID);
if (entry)
return entry->GetCard();
return nullptr;
}
const CardEntryPtr CardManager::GetCardEntry(const std::string &cardID) const
{
const std::lock_guard<std::mutex> lock(mMutex);
@ -605,4 +613,16 @@ const CardEntries &CardManager::GetCardEntries() const
return mCardEntries;
}
const CardEntries::iterator CardManager::begin()
{
const std::lock_guard<std::mutex> lock(mMutex);
return mCardEntries.begin();
}
const CardEntries::iterator CardManager::end()
{
const std::lock_guard<std::mutex> lock(mMutex);
return mCardEntries.end();
}
} // aja

View File

@ -85,8 +85,11 @@ public:
void EnumerateCards();
size_t NumCardEntries() const;
CNTV2Card *GetCard(const std::string &cardID);
const CardEntryPtr GetCardEntry(const std::string &cardID) const;
const CardEntries &GetCardEntries() const;
const CardEntries::iterator begin();
const CardEntries::iterator end();
private:
CardManager() = default;

View File

@ -3,6 +3,7 @@
#include "aja-ui-props.hpp"
#include "aja-props.hpp"
#include <ajantv2/includes/ntv2debug.h>
#include <ajantv2/includes/ntv2devicescanner.h>
#include <ajantv2/includes/ntv2devicefeatures.h>
#include <ajantv2/includes/ntv2utils.h>
@ -160,8 +161,6 @@ void populate_video_format_list(NTV2DeviceID deviceID, obs_property_t *list,
orderedStandards.push_back(NTV2_STANDARD_720);
orderedStandards.push_back(NTV2_STANDARD_1080);
orderedStandards.push_back(NTV2_STANDARD_1080p);
}
if (NTV2DeviceCanDo2KVideo(deviceID)) {
orderedStandards.push_back(NTV2_STANDARD_2K);
orderedStandards.push_back(NTV2_STANDARD_2Kx1080p);
orderedStandards.push_back(NTV2_STANDARD_2Kx1080i);
@ -205,17 +204,27 @@ void populate_pixel_format_list(NTV2DeviceID deviceID, obs_property_t *list)
}
}
void populate_sdi_transport_list(obs_property_t *list, IOSelection io)
{
for (int i = 0; i < (int)SDITransport::Unknown; i++) {
SDITransport sdi_trx = static_cast<SDITransport>(i);
obs_property_list_add_int(
list, aja::SDITransportToString(sdi_trx).c_str(),
static_cast<long long>(sdi_trx));
}
}
void populate_sdi_4k_transport_list(obs_property_t *list)
{
obs_property_list_add_int(
list,
aja::SDI4KTransportToString(SDI4KTransport::Squares).c_str(),
static_cast<long long>(SDI4KTransport::Squares));
aja::SDITransport4KToString(SDITransport4K::Squares).c_str(),
static_cast<long long>(SDITransport4K::Squares));
obs_property_list_add_int(
list,
aja::SDI4KTransportToString(SDI4KTransport::TwoSampleInterleave)
aja::SDITransport4KToString(SDITransport4K::TwoSampleInterleave)
.c_str(),
static_cast<long long>(SDI4KTransport::TwoSampleInterleave));
static_cast<long long>(SDITransport4K::TwoSampleInterleave));
}
bool aja_video_format_changed(obs_properties_t *props, obs_property_t *list,
@ -244,8 +253,7 @@ bool aja_video_format_changed(obs_properties_t *props, obs_property_t *list,
}
obs_property_t *sdi_4k_trx =
obs_properties_get(props, kUIPropSDI4KTransport.id);
obs_properties_get(props, kUIPropSDITransport4K.id);
obs_property_set_visible(sdi_4k_trx, NTV2_IS_4K_VIDEO_FORMAT(vid_fmt));
return true;
@ -316,21 +324,13 @@ void GetSortedVideoFormats(NTV2DeviceID id, const VideoStandardList &standards,
i < (size_t)NTV2_MAX_NUM_VIDEO_FORMATS; i++) {
NTV2VideoFormat fmt = (NTV2VideoFormat)i;
NTV2Standard standard = GetNTV2StandardFromVideoFormat(fmt);
bool addFmt = true;
if (id != DEVICE_ID_NOTFOUND) {
addFmt = NTV2DeviceCanDoVideoFormat(id, fmt);
}
if (addFmt) {
if (id != DEVICE_ID_NOTFOUND &&
NTV2DeviceCanDoVideoFormat(id, fmt)) {
if (videoFormatMap.count(standard)) {
videoFormatMap.at(standard).push_back(fmt);
} else {
std::vector<NTV2VideoFormat> v;
v.push_back(fmt);
videoFormatMap.insert(
std::pair<NTV2Standard,
std::vector<NTV2VideoFormat>>(
@ -371,6 +371,28 @@ void GetSortedVideoFormats(NTV2DeviceID id, const VideoStandardList &standards,
}
}
NTV2VideoFormat HandleSpecialCaseFormats(IOSelection io, NTV2VideoFormat vf,
NTV2DeviceID id)
{
// 1080p Level-B formats and ST372M
if (NTV2_VIDEO_FORMAT_IS_B(vf) &&
!(IsSDITwoWireIOSelection(io) && NTV2_IS_HD_VIDEO_FORMAT(vf))) {
vf = aja::GetLevelAFormatForLevelBFormat(vf);
}
// UHD/4K Square Division auto-detect
if ((io == IOSelection::SDI1__4 || io == IOSelection::SDI5__8) &&
NTV2_IS_HD_VIDEO_FORMAT(vf)) {
vf = GetQuadSizedVideoFormat(vf, true);
}
// Kona5/io4K+ auto-detection of UHD/4K 6G/12G SDI formats.
if (aja::IsSDIOneWireIOSelection(io) && NTV2_IS_4K_VIDEO_FORMAT(vf) &&
!NTV2_IS_SQUARE_DIVISION_FORMAT(vf) &&
!NTV2DeviceCanDo12gRouting(id)) {
vf = GetQuadSizedVideoFormat(GetQuarterSizedVideoFormat(vf));
}
return vf;
}
uint32_t CardNumFramestores(NTV2DeviceID id)
{
auto numFramestores = NTV2DeviceGetNumFrameStores(id);
@ -495,7 +517,10 @@ bool IsIODevice(NTV2DeviceID id)
id == DEVICE_ID_IOIP_2022 || id == DEVICE_ID_IOIP_2110);
}
bool IsRetailSDI12G(NTV2DeviceID id)
/* Kona5 retail firmware and io4K+ have limited support for 6G/12G SDI
* where SDI 1 is capable of capture and SDI 3 is capable of output.
*/
bool IsRetail12GSDICard(NTV2DeviceID id)
{
return (id == DEVICE_ID_KONA5 || id == DEVICE_ID_IO4KPLUS);
}
@ -505,18 +530,47 @@ bool IsOutputOnlyDevice(NTV2DeviceID id)
return id == DEVICE_ID_TTAP_PRO;
}
std::string SDI4KTransportToString(SDI4KTransport mode)
std::string SDITransportToString(SDITransport mode)
{
std::string str = "";
switch (mode) {
case SDI4KTransport::Squares:
case SDITransport::SingleLink:
str = "SD/HD Single Link";
break;
case SDITransport::HDDualLink:
str = "HD Dual-Link";
break;
case SDITransport::SDI3Ga:
str = "3G Level-A (3Ga)";
break;
case SDITransport::SDI3Gb:
str = "3G Level-B (3Gb)";
break;
case SDITransport::SDI6G:
str = "6G";
break;
case SDITransport::SDI12G:
str = "12G";
break;
case SDITransport::Unknown:
str = "Unknown";
break;
}
return str;
}
std::string SDITransport4KToString(SDITransport4K mode)
{
std::string str = "";
switch (mode) {
case SDITransport4K::Squares:
str = "Squares";
break;
case SDI4KTransport::TwoSampleInterleave:
case SDITransport4K::TwoSampleInterleave:
str = "2SI";
break;
default:
case SDI4KTransport::Unknown:
case SDITransport4K::Unknown:
str = "Unknown";
break;
}
@ -892,6 +946,21 @@ bool IsMonitorOutputSelection(NTV2DeviceID id, IOSelection io)
return false;
}
bool IsIOSelectionSDI(IOSelection io)
{
if (io == IOSelection::SDI1 || io == IOSelection::SDI2 ||
io == IOSelection::SDI3 || io == IOSelection::SDI4 ||
io == IOSelection::SDI5 || io == IOSelection::SDI6 ||
io == IOSelection::SDI7 || io == IOSelection::SDI8 ||
io == IOSelection::SDI1_2 || io == IOSelection::SDI1_2_Squares ||
io == IOSelection::SDI3_4 || io == IOSelection::SDI3_4_Squares ||
io == IOSelection::SDI5_6 || io == IOSelection::SDI7_8 ||
io == IOSelection::SDI1__4 || io == IOSelection::SDI5__8) {
return true;
}
return false;
}
std::string MakeCardID(CNTV2Card &card)
{
std::string cardID;
@ -906,4 +975,164 @@ std::string MakeCardID(CNTV2Card &card)
return cardID;
}
RasterDefinition DetermineRasterDefinition(NTV2VideoFormat vf)
{
RasterDefinition def = RasterDefinition::Unknown;
if (NTV2_IS_SD_VIDEO_FORMAT(vf)) {
def = RasterDefinition::SD;
} else if (NTV2_IS_HD_VIDEO_FORMAT(vf)) {
def = RasterDefinition::HD;
} else if (NTV2_IS_QUAD_FRAME_FORMAT(vf)) {
def = RasterDefinition::UHD_4K;
} else if (NTV2_IS_QUAD_QUAD_FORMAT(vf)) {
def = RasterDefinition::UHD2_8K;
} else {
def = RasterDefinition::Unknown;
}
return def;
}
inline bool IsStandard1080i(NTV2Standard standard)
{
if (standard == NTV2_STANDARD_1080 ||
standard == NTV2_STANDARD_2Kx1080i) {
return true;
}
return false;
}
inline bool IsStandard1080p(NTV2Standard standard)
{
if (standard == NTV2_STANDARD_1080p || standard == NTV2_STANDARD_2K ||
standard == NTV2_STANDARD_2Kx1080p) {
return true;
}
return false;
}
VPIDStandard DetermineVPIDStandard(NTV2DeviceID id, IOSelection io,
NTV2VideoFormat vf, NTV2PixelFormat pf,
SDITransport trx, SDITransport4K t4k)
{
VPIDStandard vpid = VPIDStandard_Unknown;
auto rd = aja::DetermineRasterDefinition(vf);
auto standard = GetNTV2StandardFromVideoFormat(vf);
bool is_rgb = NTV2_IS_FBF_RGB(pf);
if (rd == RasterDefinition::SD) {
vpid = VPIDStandard_483_576;
} else if (rd == RasterDefinition::HD) {
vpid = VPIDStandard_1080;
if (aja::IsSDIOneWireIOSelection(io)) {
if (is_rgb) {
if (standard == NTV2_STANDARD_720) {
if (trx == SDITransport::SingleLink) {
vpid = VPIDStandard_720;
} else if (trx ==
SDITransport::SDI3Ga) {
vpid = VPIDStandard_720_3Ga;
} else if (trx ==
SDITransport::SDI3Gb) {
vpid = VPIDStandard_720_3Gb;
}
} else if (IsStandard1080p(standard)) {
if (trx == SDITransport::SingleLink) {
vpid = VPIDStandard_1080;
} else if (trx ==
SDITransport::SDI3Ga) {
vpid = VPIDStandard_1080_3Ga;
} else if (trx ==
SDITransport::SDI3Gb) {
vpid = VPIDStandard_1080_3Gb;
}
}
} else {
if (standard == NTV2_STANDARD_720) {
vpid = VPIDStandard_720;
} else if (IsStandard1080i(standard)) {
vpid = VPIDStandard_1080;
} else if (IsStandard1080p(standard) &&
trx == SDITransport::SDI3Ga) {
vpid = VPIDStandard_1080_3Ga;
} else if (IsStandard1080p(standard) &&
trx == SDITransport::SDI3Gb) {
vpid = VPIDStandard_1080_3Gb;
}
}
} else if (aja::IsSDITwoWireIOSelection(io)) {
if (is_rgb) {
if (standard == NTV2_STANDARD_720) {
if (trx == SDITransport::SDI3Ga)
vpid = VPIDStandard_720_3Ga;
else if (trx == SDITransport::SDI3Gb)
vpid = VPIDStandard_720_3Gb;
} else if (IsStandard1080p(standard)) {
if (trx == SDITransport::SDI3Ga)
vpid = VPIDStandard_1080_Dual_3Ga;
else if (trx == SDITransport::SDI3Gb)
vpid = VPIDStandard_1080_Dual_3Gb;
}
} else {
if (IsStandard1080p(standard) &&
trx == SDITransport::HDDualLink) {
vpid = VPIDStandard_1080_DualLink;
}
}
}
} else if (rd == RasterDefinition::UHD_4K) {
if (aja::IsSDIOneWireIOSelection(io)) {
if (is_rgb) {
if (trx == SDITransport::SDI6G) {
vpid = VPIDStandard_2160_DualLink;
} else if (trx == SDITransport::SDI12G) {
vpid = VPIDStandard_2160_DualLink_12Gb;
}
} else {
// YCbCr
if (trx == SDITransport::SDI6G) {
vpid = VPIDStandard_2160_Single_6Gb;
} else if (trx == SDITransport::SDI12G) {
vpid = VPIDStandard_2160_Single_12Gb;
} else {
vpid = VPIDStandard_2160_Single_6Gb; // fallback
}
}
} else if (aja::IsSDITwoWireIOSelection(io)) {
if (is_rgb) {
} else {
// YCbCr
if (t4k == SDITransport4K::Squares) {
vpid = VPIDStandard_1080;
} else if (t4k ==
SDITransport4K::TwoSampleInterleave) {
vpid = VPIDStandard_2160_DualLink;
}
}
} else if (aja::IsSDIFourWireIOSelection(io)) {
if (is_rgb) {
} else {
// YCbCr
if (t4k == SDITransport4K::Squares) {
if (trx == SDITransport::SDI3Ga) {
vpid = VPIDStandard_1080_3Ga;
} else if (trx ==
SDITransport::SDI3Gb) {
vpid = VPIDStandard_1080_DualLink_3Gb;
} else {
vpid = VPIDStandard_1080;
}
} else if (t4k ==
SDITransport4K::TwoSampleInterleave) {
if (trx == SDITransport::SDI3Ga) {
vpid = VPIDStandard_2160_QuadLink_3Ga;
} else if (trx ==
SDITransport::SDI3Gb) {
vpid = VPIDStandard_2160_QuadDualLink_3Gb;
}
}
}
}
} else if (rd == RasterDefinition::UHD2_8K) {
}
return vpid;
}
} // aja

View File

@ -17,8 +17,7 @@ using VideoStandardList = std::vector<NTV2Standard>;
static const uint32_t kDefaultAudioChannels = 8;
static const uint32_t kDefaultAudioSampleRate = 48000;
static const uint32_t kDefaultAudioSampleSize = 4;
static const int kVideoFormatAuto = -1;
static const int kPixelFormatAuto = -1;
static const int kAutoDetect = -1;
static const NTV2PixelFormat kDefaultAJAPixelFormat = NTV2_FBF_8BIT_YCBCR;
// Common OBS property helpers used by both the capture and output plugins
@ -41,6 +40,7 @@ populate_video_format_list(NTV2DeviceID deviceID, obs_property_t *list,
NTV2VideoFormat genlockFormat = NTV2_FORMAT_UNKNOWN);
extern void populate_pixel_format_list(NTV2DeviceID deviceID,
obs_property_t *list);
extern void populate_sdi_transport_list(obs_property_t *list, IOSelection io);
extern void populate_sdi_4k_transport_list(obs_property_t *list);
extern bool aja_video_format_changed(obs_properties_t *props,
obs_property_t *list,
@ -59,6 +59,8 @@ extern video_format AJAPixelFormatToOBSVideoFormat(NTV2PixelFormat pf);
extern void GetSortedVideoFormats(NTV2DeviceID id,
const VideoStandardList &standards,
VideoFormatList &videoFormats);
extern NTV2VideoFormat
HandleSpecialCaseFormats(IOSelection io, NTV2VideoFormat vf, NTV2DeviceID id);
extern uint32_t CardNumFramestores(NTV2DeviceID id);
extern uint32_t CardNumAudioSystems(NTV2DeviceID id);
@ -70,10 +72,11 @@ extern NTV2VideoFormat GetLevelAFormatForLevelBFormat(NTV2VideoFormat vf);
extern NTV2VideoFormat InterlacedFormatForPsfFormat(NTV2VideoFormat vf);
extern bool IsSingleSDIDevice(NTV2DeviceID id);
extern bool IsIODevice(NTV2DeviceID id);
extern bool IsRetailSDI12G(NTV2DeviceID id);
extern bool IsRetail12GSDICard(NTV2DeviceID id);
extern bool IsOutputOnlyDevice(NTV2DeviceID id);
extern std::string SDI4KTransportToString(SDI4KTransport mode);
extern std::string SDITransportToString(SDITransport mode);
extern std::string SDITransport4KToString(SDITransport4K mode);
extern std::string IOSelectionToString(IOSelection io);
extern void IOSelectionToInputSources(IOSelection io,
@ -86,7 +89,13 @@ extern bool IsSDIOneWireIOSelection(IOSelection io);
extern bool IsSDITwoWireIOSelection(IOSelection io);
extern bool IsSDIFourWireIOSelection(IOSelection io);
extern bool IsMonitorOutputSelection(NTV2DeviceID id, IOSelection io);
extern bool IsIOSelectionSDI(IOSelection io);
extern std::string MakeCardID(CNTV2Card &card);
extern RasterDefinition DetermineRasterDefinition(NTV2VideoFormat vf);
extern VPIDStandard DetermineVPIDStandard(NTV2DeviceID id, IOSelection io,
NTV2VideoFormat vf,
NTV2PixelFormat pf, SDITransport trx,
SDITransport4K t4k);
} // aja

View File

@ -1,6 +1,24 @@
#pragma once
// Additional enums used throughout the AJA plugins for signal routing configuration.
#include <ajantv2/includes/ntv2vpid.h>
#include <utility>
// Flags corresponding to card register enables
typedef enum {
kEnable3GOut = 1 << 0,
kEnable6GOut = 1 << 1,
kEnable12GOut = 1 << 2,
kConvert3GIn = 1 << 3,
kConvert3GOut = 1 << 4,
kConvert3GaRGBOut = 1 << 5,
kEnable3GbOut = 1 << 6,
kEnable4KSquares = 1 << 7,
kEnable8KSquares = 1 << 8,
kEnable4KTSI = 1 << 9,
} RoutingPresetFlags;
enum class ConnectionKind { SDI = 0, HDMI = 1, Analog = 2, Unknown };
enum class IOSelection {
SDI1 = 0,
@ -33,44 +51,24 @@ enum class IOSelection {
NumIOSelections = Invalid
};
enum class SDI4KTransport { Squares = 0, TwoSampleInterleave = 1, Unknown = 2 };
enum class SDITransport {
SingleLink = 0, // SD/HD up to 1.5Gbps link
HDDualLink = 1, // HD Dual-1.5Gbps Links
SDI3Ga = 2, // 3Gbps Level-A
SDI3Gb = 3, // 3Gbps Level-B
SDI6G = 4, // 6Gbps
SDI12G = 5, // 12Gbps
Unknown
};
enum class SDITransport4K { Squares = 0, TwoSampleInterleave = 1, Unknown = 2 };
enum class RasterDefinition {
SD = 0,
HD = 1,
UHD_4K = 2,
UHD_4K_Retail_12G = 3,
UHD2_8K = 4,
Unknown = 5
};
enum class SDIWireFormat {
SD_ST352 = 0,
HD_720p_ST292 = 1,
HD_1080_ST292 = 2,
HD_1080_ST372_Dual = 3,
HD_720p_ST425_3Ga = 4,
HD_1080p_ST425_3Ga = 5,
HD_1080p_ST425_3Gb_DL = 6,
HD_720p_ST425_3Gb = 7,
HD_1080p_ST425_3Gb = 8,
HD_1080p_ST425_Dual_3Ga = 9,
HD_1080p_ST425_Dual_3Gb = 10,
UHD4K_ST292_Dual_1_5_Squares = 11,
UHD4K_ST292_Quad_1_5_Squares = 12,
UHD4K_ST425_Quad_3Ga_Squares = 13,
UHD4K_ST425_Quad_3Gb_Squares = 14,
UHD4K_ST425_Dual_3Gb_2SI = 15,
UHD4K_ST425_Quad_3Ga_2SI = 16,
UHD4K_ST425_Quad_3Gb_2SI = 17,
UHD4K_ST2018_6G_Squares_2SI = 18,
UHD4K_ST2018_6G_Squares_2SI_Kona5_io4KPlus = 19,
UHD4K_ST2018_12G_Squares_2SI = 20,
UHD4K_ST2018_12G_Squares_2SI_Kona5_io4KPlus = 21,
UHD28K_ST2082_Dual_12G = 22,
UHD28K_ST2082_RGB_Dual_12G = 23,
UHD28K_ST2082_Quad_12G = 24,
Unknown = 25,
UHD2_8K = 3,
Unknown
};
enum class HDMIWireFormat {
@ -84,5 +82,7 @@ enum class HDMIWireFormat {
UHD_4K_RGB_LFR = 7,
UHD_4K_RGB_HFR = 8,
TTAP_PRO = 9,
Unknown = 10
Unknown
};
using VPIDSpec = std::pair<RasterDefinition, VPIDStandard>;

View File

@ -65,7 +65,6 @@ AJAOutput::AJAOutput(CNTV2Card *card, const std::string &cardID,
mOutputID{outputID},
mDeviceIndex{deviceIndex},
mDeviceID{deviceID},
mFrameTimes{},
mAudioPlayCursor{0},
mAudioWriteCursor{0},
mAudioWrapAddress{0},
@ -140,31 +139,17 @@ void AJAOutput::Initialize(const OutputProps &props)
props.pixelFormat);
mCard->SetOutputFrame(props.Channel(), mWriteCardFrame);
mCard->WaitForOutputVerticalInterrupt(props.Channel());
const auto &cardFrameRate =
GetNTV2FrameRateFromVideoFormat(props.videoFormat);
ULWord fpsNum = 0;
ULWord fpsDen = 0;
GetFramesPerSecond(cardFrameRate, fpsNum, fpsDen);
mFrameRateNum = fpsNum;
mFrameRateDen = fpsDen;
mFrameTimes.cardFrameTime =
(1000000000ULL / (uint64_t)(fpsNum / fpsDen));
mFrameTimes.cardFps = (double)(fpsNum / fpsDen);
mFrameTimes.obsFps = obs_get_active_fps();
if (mFrameTimes.obsFps < 1.0)
mFrameTimes.obsFps = 30.0;
mFrameTimes.obsFrameTime =
(1000000000ULL / (uint64_t)mFrameTimes.obsFps);
mVideoDelay = ((int64_t)mNumCardFrames - 0) * 1000000 * mFrameRateDen /
mFrameRateNum;
mAudioRate = props.audioSampleRate;
SetOutputProps(props);
}
@ -510,7 +495,7 @@ uint32_t AJAOutput::get_frame_count()
}
// Perform DMA of audio samples to AJA card while taking into account wrapping around the
// ends of the card's audio buffer (size set to 4MB in Routing::ConfigureOutputAudio).
// ends of the card's audio buffer (size set to 4MB in aja::Routing::ConfigureOutputAudio).
void AJAOutput::dma_audio_samples(NTV2AudioSystem audioSys, uint32_t *data,
size_t size)
{
@ -780,28 +765,8 @@ bool aja_output_device_changed(void *data, obs_properties_t *props,
populate_output_device_list(list);
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
size_t itemCount = obs_property_list_item_count(list);
bool itemFound = false;
for (size_t i = 0; i < itemCount; i++) {
const char *itemCardID = obs_property_list_item_string(list, i);
if (strcmp(cardID, itemCardID) == 0) {
itemFound = true;
break;
}
}
if (!itemFound) {
obs_property_list_insert_string(list, 0, cardID, cardID);
obs_property_list_item_disable(list, 0, true);
return true;
}
if (!cardID) {
blog(LOG_ERROR, "aja_output_device_changed: Card ID is null!");
if (!cardID)
return false;
}
const char *outputID =
obs_data_get_string(settings, kUIPropAJAOutputID.id);
@ -828,8 +793,10 @@ bool aja_output_device_changed(void *data, obs_properties_t *props,
obs_properties_get(props, kUIPropVideoFormatSelect.id);
obs_property_t *pix_fmt_list =
obs_properties_get(props, kUIPropPixelFormatSelect.id);
obs_property_t *sdi_trx_list =
obs_properties_get(props, kUIPropSDITransport.id);
obs_property_t *sdi_4k_list =
obs_properties_get(props, kUIPropSDI4KTransport.id);
obs_properties_get(props, kUIPropSDITransport4K.id);
const NTV2DeviceID deviceID = cardEntry->GetDeviceID();
populate_io_selection_output_list(cardID, outputID, deviceID,
@ -850,6 +817,11 @@ bool aja_output_device_changed(void *data, obs_properties_t *props,
obs_property_list_clear(pix_fmt_list);
populate_pixel_format_list(deviceID, pix_fmt_list);
IOSelection io_select = static_cast<IOSelection>(
obs_data_get_int(settings, kUIPropOutput.id));
obs_property_list_clear(sdi_trx_list);
populate_sdi_transport_list(sdi_trx_list, io_select);
obs_property_list_clear(sdi_4k_list);
populate_sdi_4k_transport_list(sdi_4k_list);
@ -863,11 +835,9 @@ bool aja_output_dest_changed(obs_properties_t *props, obs_property_t *list,
blog(LOG_DEBUG, "AJA Output Dest Changed");
int dest = obs_data_get_int(settings, kUIPropOutput.id);
size_t itemCount = obs_property_list_item_count(list);
bool itemFound = false;
int dest = obs_data_get_int(settings, kUIPropOutput.id);
size_t itemCount = obs_property_list_item_count(list);
for (size_t i = 0; i < itemCount; i++) {
int itemDest = obs_property_list_item_int(list, i);
if (dest == itemDest) {
@ -875,29 +845,12 @@ bool aja_output_dest_changed(obs_properties_t *props, obs_property_t *list,
break;
}
}
if (!itemFound) {
obs_property_list_insert_int(list, 0, "", dest);
obs_property_list_item_disable(list, 0, true);
return true;
}
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
if (!cardID) {
blog(LOG_ERROR, "aja_output_dest_changed: Card ID is null!");
return false;
}
auto &cardManager = aja::CardManager::Instance();
cardManager.EnumerateCards();
auto cardEntry = cardManager.GetCardEntry(cardID);
if (!cardEntry) {
blog(LOG_ERROR,
"aja_output_dest_changed: Card entry not found for %s",
cardID);
return false;
}
// Revert to "Select..." if desired IOSelection is already in use
auto io_select = static_cast<IOSelection>(
obs_data_get_int(settings, kUIPropOutput.id));
@ -916,6 +869,13 @@ bool aja_output_dest_changed(obs_properties_t *props, obs_property_t *list,
}
}
obs_property_t *sdi_trx_list =
obs_properties_get(props, kUIPropSDITransport.id);
obs_property_list_clear(sdi_trx_list);
populate_sdi_transport_list(sdi_trx_list, io_select);
obs_property_set_visible(sdi_trx_list,
aja::IsIOSelectionSDI(io_select));
return true;
}
@ -971,7 +931,6 @@ static void *aja_output_create(obs_data_t *settings, obs_output_t *output)
}
NTV2DeviceID deviceID = card->GetDeviceID();
OutputProps outputProps(deviceID);
outputProps.ioSelect = static_cast<IOSelection>(
obs_data_get_int(settings, kUIPropOutput.id));
@ -980,20 +939,19 @@ static void *aja_output_create(obs_data_t *settings, obs_output_t *output)
"aja_output_create: Select a valid AJA Output IOSelection!");
return nullptr;
}
outputProps.videoFormat = static_cast<NTV2VideoFormat>(
obs_data_get_int(settings, kUIPropVideoFormatSelect.id));
outputProps.pixelFormat = static_cast<NTV2PixelFormat>(
obs_data_get_int(settings, kUIPropPixelFormatSelect.id));
outputProps.sdi4kTransport = static_cast<SDI4KTransport>(
obs_data_get_int(settings, kUIPropSDI4KTransport.id));
outputProps.sdiTransport = static_cast<SDITransport>(
obs_data_get_int(settings, kUIPropSDITransport.id));
outputProps.sdi4kTransport = static_cast<SDITransport4K>(
obs_data_get_int(settings, kUIPropSDITransport4K.id));
outputProps.audioNumChannels = kDefaultAudioChannels;
outputProps.audioSampleSize = kDefaultAudioSampleSize;
outputProps.audioSampleRate = kDefaultAudioSampleRate;
if (NTV2_IS_4K_VIDEO_FORMAT(outputProps.videoFormat) &&
outputProps.sdi4kTransport == SDI4KTransport::Squares) {
outputProps.sdi4kTransport == SDITransport4K::Squares) {
if (outputProps.ioSelect == IOSelection::SDI1_2) {
outputProps.ioSelect = IOSelection::SDI1_2_Squares;
} else if (outputProps.ioSelect == IOSelection::SDI3_4) {
@ -1025,7 +983,6 @@ static void *aja_output_create(obs_data_t *settings, obs_output_t *output)
auto ajaOutput = new AJAOutput(card, cardID, outputID,
(UWord)cardEntry->GetCardIndex(),
deviceID);
ajaOutput->Initialize(outputProps);
ajaOutput->ClearVideoQueue();
ajaOutput->ClearAudioQueue();
@ -1066,9 +1023,7 @@ static bool aja_output_start(void *data)
const std::string &cardID = ajaOutput->mCardID;
auto &cardManager = aja::CardManager::Instance();
cardManager.EnumerateCards();
auto cardEntry = cardManager.GetCardEntry(cardID);
if (!cardEntry) {
blog(LOG_DEBUG,
@ -1115,14 +1070,14 @@ static bool aja_output_start(void *data)
}
// Configures crosspoint routing on AJA card
if (!Routing::ConfigureOutputRoute(outputProps, NTV2_MODE_DISPLAY,
card)) {
if (!aja::Routing::ConfigureOutputRoute(outputProps, NTV2_MODE_DISPLAY,
card)) {
blog(LOG_ERROR,
"aja_output_start: Error configuring output route!");
return false;
}
Routing::ConfigureOutputAudio(outputProps, card);
aja::Routing::ConfigureOutputAudio(outputProps, card);
const auto &formatDesc = outputProps.FormatDesc();
struct video_scale_info scaler = {};
@ -1166,26 +1121,22 @@ static void aja_output_stop(void *data, uint64_t ts)
blog(LOG_ERROR, "aja_output_stop: Plugin instance is null!");
return;
}
auto outputProps = ajaOutput->GetOutputProps();
const std::string &cardID = ajaOutput->mCardID;
auto &cardManager = aja::CardManager::Instance();
cardManager.EnumerateCards();
auto cardEntry = cardManager.GetCardEntry(cardID);
if (!cardEntry) {
blog(LOG_ERROR, "aja_output_stop: Card Entry not found for %s",
cardID.c_str());
return;
}
CNTV2Card *card = ajaOutput->GetCard();
if (!card) {
blog(LOG_ERROR, "aja_output_stop: Card instance is null!");
return;
}
auto outputProps = ajaOutput->GetOutputProps();
if (!cardEntry->ReleaseOutputSelection(outputProps.ioSelect,
card->GetDeviceID(),
ajaOutput->mOutputID)) {
@ -1194,15 +1145,13 @@ static void aja_output_stop(void *data, uint64_t ts)
aja::IOSelectionToString(outputProps.ioSelect).c_str(),
cardID.c_str());
}
auto audioSystem = outputProps.AudioSystem();
ajaOutput->GenerateTestPattern(outputProps.videoFormat,
outputProps.pixelFormat,
NTV2_TestPatt_Black);
obs_output_end_data_capture(ajaOutput->GetOBSOutput());
auto audioSystem = outputProps.AudioSystem();
card->StopAudioOutput(audioSystem);
blog(LOG_INFO, "AJA Output stopped.");
@ -1234,28 +1183,28 @@ static void aja_output_raw_audio(void *data, struct audio_data *frames)
static obs_properties_t *aja_output_get_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
obs_property_t *device_list = obs_properties_add_list(
props, kUIPropDevice.id, obs_module_text(kUIPropDevice.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
obs_property_t *output_list = obs_properties_add_list(
props, kUIPropOutput.id, obs_module_text(kUIPropOutput.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_t *vid_fmt_list = obs_properties_add_list(
props, kUIPropVideoFormatSelect.id,
obs_module_text(kUIPropVideoFormatSelect.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_list(props, kUIPropPixelFormatSelect.id,
obs_module_text(kUIPropPixelFormatSelect.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_list(props, kUIPropSDI4KTransport.id,
obs_module_text(kUIPropSDI4KTransport.text),
obs_properties_add_list(props, kUIPropSDITransport.id,
obs_module_text(kUIPropSDITransport.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_list(props, kUIPropSDITransport.id,
obs_module_text(kUIPropSDITransport.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_list(props, kUIPropSDITransport4K.id,
obs_module_text(kUIPropSDITransport4K.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_bool(props, kUIPropAutoStartOutput.id,
obs_module_text(kUIPropAutoStartOutput.text));
@ -1265,7 +1214,6 @@ static obs_properties_t *aja_output_get_properties(void *data)
aja_output_dest_changed);
obs_property_set_modified_callback2(device_list,
aja_output_device_changed, data);
return props;
}
@ -1274,13 +1222,6 @@ static const char *aja_output_get_name(void *)
return obs_module_text(kUIPropOutputModule.text);
}
// NOTE(paulh): Drop-down defaults are set on a clean launch in aja-output-ui code.
// Otherwise we load the settings stored in the ajaOutputProps/ajaPreviewOutputProps.json configs.
void aja_output_get_defaults(obs_data_t *settings)
{
obs_data_set_default_bool(settings, kUIPropAutoStartOutput.id, false);
}
struct obs_output_info create_aja_output_info()
{
struct obs_output_info aja_output_info = {};
@ -1295,8 +1236,6 @@ struct obs_output_info create_aja_output_info()
aja_output_info.raw_video = aja_output_raw_video;
aja_output_info.raw_audio = aja_output_raw_audio;
aja_output_info.update = aja_output_update;
aja_output_info.get_defaults = aja_output_get_defaults;
aja_output_info.get_properties = aja_output_get_properties;
return aja_output_info;
}

View File

@ -28,14 +28,6 @@ struct AudioFrames {
size_t size;
};
//TODO(paulh): Refactor me into OutputProps
struct FrameTimes {
double obsFps;
uint64_t obsFrameTime;
double cardFps;
uint64_t cardFrameTime;
};
using VideoQueue = std::deque<VideoFrame>;
using AudioQueue = std::deque<AudioFrames>;
@ -90,8 +82,6 @@ public:
UWord mDeviceIndex;
NTV2DeviceID mDeviceID;
FrameTimes mFrameTimes;
uint32_t mAudioPlayCursor;
uint32_t mAudioWriteCursor;
uint32_t mAudioWrapAddress;

1544
plugins/aja/aja-presets.cpp Normal file

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,48 @@
#pragma once
#include "aja-enums.hpp"
#include <ajantv2/includes/ntv2enums.h>
#include <map>
#include <string>
#include <vector>
namespace aja {
struct RoutingPreset {
std::string name;
ConnectionKind kind;
NTV2Mode mode;
uint32_t num_channels;
uint32_t num_framestores;
uint32_t flags;
bool is_rgb;
std::string route_string;
std::vector<NTV2DeviceID> device_ids;
RasterDefinition raster_def;
HDMIWireFormat hdmi_wire_format;
VPIDStandard vpid_standard;
};
using RoutingPresets = std::vector<RoutingPreset>;
using RoutingPresetPair = std::pair<std::string, RoutingPreset>;
using RoutingPresetMap = std::map<std::string, RoutingPreset>;
class RoutingConfigurator {
public:
RoutingConfigurator();
void AddPreset(const std::string &name, const RoutingPreset &preset);
bool PresetByName(const std::string &name, RoutingPreset &preset) const;
RoutingPresetMap GetPresetTable() const;
bool FindFirstPreset(ConnectionKind kind, NTV2DeviceID id,
NTV2Mode mode, NTV2VideoFormat vf,
NTV2PixelFormat pf, VPIDStandard standard,
RoutingPreset &preset);
private:
void build_preset_table();
RoutingPresetMap m_presets;
};
} // aja

View File

@ -1,129 +1,18 @@
#include "aja-props.hpp"
#include "aja-common.hpp"
#include <ajantv2/includes/ntv2devicefeatures.h>
#include <ajantv2/includes/ntv2utils.h>
#include <ajantv2/includes/ntv2vpid.h>
VPIDData::VPIDData()
: mVpidA{0},
mVpidB{0},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
}
VPIDData::VPIDData(ULWord vpidA, ULWord vpidB)
: mVpidA{vpidA},
mVpidB{vpidB},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
Parse();
}
VPIDData::VPIDData(const VPIDData &other)
: mVpidA{other.mVpidA},
mVpidB{other.mVpidB},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
Parse();
}
VPIDData::VPIDData(VPIDData &&other)
: mVpidA{other.mVpidA},
mVpidB{other.mVpidB},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
Parse();
}
VPIDData &VPIDData::operator=(const VPIDData &other)
{
mVpidA = other.mVpidA;
mVpidB = other.mVpidB;
return *this;
}
VPIDData &VPIDData::operator=(VPIDData &&other)
{
mVpidA = other.mVpidA;
mVpidB = other.mVpidB;
return *this;
}
bool VPIDData::operator==(const VPIDData &rhs) const
{
return (mVpidA == rhs.mVpidA && mVpidB == rhs.mVpidB);
}
bool VPIDData::operator!=(const VPIDData &rhs) const
{
return !operator==(rhs);
}
void VPIDData::SetA(ULWord vpidA)
{
mVpidA = vpidA;
}
void VPIDData::SetB(ULWord vpidB)
{
mVpidB = vpidB;
}
void VPIDData::Parse()
{
CNTV2VPID parserA;
parserA.SetVPID(mVpidA);
mStandardA = parserA.GetStandard();
mSamplingA = parserA.GetSampling();
CNTV2VPID parserB;
parserB.SetVPID(mVpidB);
mStandardB = parserB.GetStandard();
mSamplingB = parserB.GetSampling();
}
bool VPIDData::IsRGB() const
{
switch (mSamplingA) {
default:
break;
case VPIDSampling_GBR_444:
case VPIDSampling_GBRA_4444:
case VPIDSampling_GBRD_4444:
return true;
}
return false;
}
VPIDStandard VPIDData::Standard() const
{
return mStandardA;
}
VPIDSampling VPIDData::Sampling() const
{
return mSamplingA;
}
// AJASource Properties
SourceProps::SourceProps()
: deviceID{DEVICE_ID_NOTFOUND},
ioSelect{IOSelection::Invalid},
inputSource{NTV2_INPUTSOURCE_INVALID},
// inputSource{NTV2_INPUTSOURCE_INVALID},
videoFormat{NTV2_FORMAT_UNKNOWN},
pixelFormat{NTV2_FBF_INVALID},
sdi4kTransport{SDI4KTransport::TwoSampleInterleave},
sdiTransport{SDITransport::SingleLink},
sdi4kTransport{SDITransport4K::TwoSampleInterleave},
audioNumChannels{8},
audioSampleSize{4},
audioSampleRate{48000},
@ -136,10 +25,11 @@ SourceProps::SourceProps()
SourceProps::SourceProps(NTV2DeviceID devID)
: deviceID{devID},
ioSelect{IOSelection::Invalid},
inputSource{NTV2_INPUTSOURCE_INVALID},
// inputSource{NTV2_INPUTSOURCE_INVALID},
videoFormat{NTV2_FORMAT_UNKNOWN},
pixelFormat{NTV2_FBF_INVALID},
sdi4kTransport{SDI4KTransport::TwoSampleInterleave},
sdiTransport{SDITransport::SingleLink},
sdi4kTransport{SDITransport4K::TwoSampleInterleave},
audioNumChannels{8},
audioSampleSize{4},
audioSampleRate{48000},
@ -153,9 +43,10 @@ SourceProps::SourceProps(const SourceProps &props)
{
deviceID = props.deviceID;
ioSelect = props.ioSelect;
inputSource = props.inputSource;
// inputSource = props.inputSource;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -169,9 +60,10 @@ SourceProps::SourceProps(SourceProps &&props)
{
deviceID = props.deviceID;
ioSelect = props.ioSelect;
inputSource = props.inputSource;
// inputSource = props.inputSource;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -185,9 +77,10 @@ void SourceProps::operator=(const SourceProps &props)
{
deviceID = props.deviceID;
ioSelect = props.ioSelect;
inputSource = props.inputSource;
// inputSource = props.inputSource;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -201,9 +94,10 @@ void SourceProps::operator=(SourceProps &&props)
{
deviceID = props.deviceID;
ioSelect = props.ioSelect;
inputSource = props.inputSource;
// inputSource = props.inputSource;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -221,6 +115,7 @@ bool SourceProps::operator==(const SourceProps &props)
pixelFormat == props.pixelFormat &&
// vpid == props.vpid &&
autoDetect == props.autoDetect &&
sdiTransport == props.sdiTransport &&
sdi4kTransport == props.sdi4kTransport &&
audioNumChannels == props.audioNumChannels &&
audioSampleSize == props.audioSampleSize &&
@ -233,9 +128,25 @@ bool SourceProps::operator!=(const SourceProps &props)
return !operator==(props);
}
NTV2InputSource SourceProps::InitialInputSource() const
{
auto inputSources = InputSources();
if (!inputSources.empty()) {
return *inputSources.begin();
}
return NTV2_INPUTSOURCE_INVALID;
}
NTV2InputSourceSet SourceProps::InputSources() const
{
NTV2InputSourceSet inputSources;
aja::IOSelectionToInputSources(ioSelect, inputSources);
return inputSources;
}
NTV2Channel SourceProps::Channel() const
{
return NTV2InputSourceToChannel(inputSource);
return NTV2InputSourceToChannel(InitialInputSource());
}
NTV2AudioSystem SourceProps::AudioSystem() const
@ -291,7 +202,7 @@ OutputProps::OutputProps(NTV2DeviceID devID)
outputDest{NTV2_OUTPUTDESTINATION_ANALOG},
videoFormat{NTV2_FORMAT_UNKNOWN},
pixelFormat{NTV2_FBF_INVALID},
sdi4kTransport{SDI4KTransport::TwoSampleInterleave},
sdi4kTransport{SDITransport4K::TwoSampleInterleave},
audioNumChannels{8},
audioSampleSize{4},
audioSampleRate{48000}
@ -305,6 +216,7 @@ OutputProps::OutputProps(OutputProps &&props)
outputDest = props.outputDest;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -318,6 +230,7 @@ OutputProps::OutputProps(const OutputProps &props)
outputDest = props.outputDest;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -331,6 +244,7 @@ void OutputProps::operator=(const OutputProps &props)
outputDest = props.outputDest;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -344,6 +258,7 @@ void OutputProps::operator=(OutputProps &&props)
outputDest = props.outputDest;
videoFormat = props.videoFormat;
pixelFormat = props.pixelFormat;
sdiTransport = props.sdiTransport;
sdi4kTransport = props.sdi4kTransport;
audioNumChannels = props.audioNumChannels;
audioSampleSize = props.audioSampleSize;
@ -356,6 +271,8 @@ bool OutputProps::operator==(const OutputProps &props)
// outputDest == props.outputDest &&
videoFormat == props.videoFormat &&
pixelFormat == props.pixelFormat &&
sdiTransport == props.sdiTransport &&
sdi4kTransport == props.sdi4kTransport &&
audioNumChannels == props.audioNumChannels &&
audioSampleSize == props.audioSampleSize &&
audioSampleRate == props.audioSampleRate);

View File

@ -1,6 +1,7 @@
#pragma once
#include "aja-enums.hpp"
#include "aja-vpid-data.hpp"
#include <media-io/audio-io.h>
@ -11,38 +12,6 @@
#include <string>
#include <vector>
class VPIDData {
public:
VPIDData();
VPIDData(ULWord vpidA, ULWord vpidB);
VPIDData(const VPIDData &other);
VPIDData(VPIDData &&other);
~VPIDData() = default;
VPIDData &operator=(const VPIDData &other);
VPIDData &operator=(VPIDData &&other);
bool operator==(const VPIDData &rhs) const;
bool operator!=(const VPIDData &rhs) const;
void SetA(ULWord vpidA);
void SetB(ULWord vpidB);
void Parse();
bool IsRGB() const;
VPIDStandard Standard() const;
VPIDSampling Sampling() const;
private:
ULWord mVpidA;
ULWord mVpidB;
VPIDStandard mStandardA;
VPIDSampling mSamplingA;
VPIDStandard mStandardB;
VPIDSampling mSamplingB;
};
using VPIDDataList = std::vector<VPIDData>;
//TODO(paulh): Consolidate the two Props classes
class SourceProps {
public:
@ -56,6 +25,8 @@ public:
bool operator==(const SourceProps &props);
bool operator!=(const SourceProps &props);
NTV2InputSource InitialInputSource() const;
NTV2InputSourceSet InputSources() const;
NTV2Channel Channel() const;
NTV2AudioSystem AudioSystem() const;
NTV2AudioRate AudioRate() const;
@ -65,10 +36,10 @@ public:
NTV2DeviceID deviceID;
IOSelection ioSelect;
NTV2InputSource inputSource;
NTV2VideoFormat videoFormat;
NTV2PixelFormat pixelFormat;
SDI4KTransport sdi4kTransport;
SDITransport sdiTransport;
SDITransport4K sdi4kTransport;
VPIDDataList vpids;
uint32_t audioNumChannels;
uint32_t audioSampleSize;
@ -101,7 +72,8 @@ public:
NTV2OutputDestination outputDest;
NTV2VideoFormat videoFormat;
NTV2PixelFormat pixelFormat;
SDI4KTransport sdi4kTransport;
SDITransport sdiTransport;
SDITransport4K sdi4kTransport;
uint32_t audioNumChannels;
uint32_t audioSampleSize;
uint32_t audioSampleRate;

View File

@ -3,67 +3,13 @@
#include "aja-routing.hpp"
#include "aja-widget-io.hpp"
// Signal routing crosspoint and register setting tables for SDI/HDMI/etc.
#include "routing/hdmi_rgb_capture.h"
#include "routing/hdmi_rgb_display.h"
#include "routing/hdmi_ycbcr_capture.h"
#include "routing/hdmi_ycbcr_display.h"
#include "routing/sdi_ycbcr_capture.h"
#include "routing/sdi_ycbcr_display.h"
#include "routing/sdi_rgb_capture.h"
#include "routing/sdi_rgb_display.h"
#include <ajabase/common/common.h>
#include <ajantv2/includes/ntv2card.h>
#include <ajantv2/includes/ntv2devicefeatures.h>
#include <obs-module.h>
RasterDefinition GetRasterDefinition(IOSelection io, NTV2VideoFormat vf,
NTV2DeviceID deviceID)
{
RasterDefinition def = RasterDefinition::Unknown;
if (NTV2_IS_SD_VIDEO_FORMAT(vf)) {
def = RasterDefinition::SD;
} else if (NTV2_IS_HD_VIDEO_FORMAT(vf)) {
def = RasterDefinition::HD;
} else if (NTV2_IS_QUAD_FRAME_FORMAT(vf)) {
def = RasterDefinition::UHD_4K;
/* NOTE(paulh): Special enum for Kona5 Retail & IO4K+ firmwares which route UHD/4K formats
* over 1x 6G/12G SDI using an undocumented crosspoint config.
*/
if (aja::IsSDIOneWireIOSelection(io) &&
aja::IsRetailSDI12G(deviceID))
def = RasterDefinition::UHD_4K_Retail_12G;
} else if (NTV2_IS_QUAD_QUAD_FORMAT(vf)) {
def = RasterDefinition::UHD2_8K;
} else {
def = RasterDefinition::Unknown;
}
return def;
}
#define NTV2UTILS_ENUM_CASE_RETURN_STR(enum_name) \
case (enum_name): \
return #enum_name
std::string RasterDefinitionToString(RasterDefinition rd)
{
std::string str = "";
switch (rd) {
NTV2UTILS_ENUM_CASE_RETURN_STR(RasterDefinition::SD);
NTV2UTILS_ENUM_CASE_RETURN_STR(RasterDefinition::HD);
NTV2UTILS_ENUM_CASE_RETURN_STR(RasterDefinition::UHD_4K);
NTV2UTILS_ENUM_CASE_RETURN_STR(RasterDefinition::UHD2_8K);
NTV2UTILS_ENUM_CASE_RETURN_STR(RasterDefinition::Unknown);
}
return str;
}
namespace aja {
/*
* Parse the widget routing shorthand string into a map of input and output NTV2CrosspointIDs.
* For example "sdi[0][0]->fb[0][0]" is shorthand for connecting the output crosspoint for
@ -191,137 +137,12 @@ bool Routing::ParseRouteString(const std::string &route,
return parse_ok > 0;
}
// Determine the appropriate SDIWireFormat based on the specified device ID and VPID specification.
bool Routing::DetermineSDIWireFormat(NTV2DeviceID deviceID, VPIDSpec spec,
SDIWireFormat &swf)
{
if (deviceID == DEVICE_ID_KONA5 || deviceID == DEVICE_ID_IO4KPLUS) {
static const std::vector<VPIDStandard> kRetail6GVpidStandards = {
VPIDStandard_2160_Single_6Gb,
VPIDStandard_1080_Single_6Gb,
VPIDStandard_1080_AFR_Single_6Gb,
};
static const std::vector<VPIDStandard> kRetail12GVpidStandards =
{VPIDStandard_2160_Single_12Gb,
VPIDStandard_1080_10_12_AFR_Single_12Gb};
if (spec.first == RasterDefinition::UHD_4K &&
aja::vec_contains<VPIDStandard>(kRetail6GVpidStandards,
spec.second)) {
swf = SDIWireFormat::
UHD4K_ST2018_6G_Squares_2SI_Kona5_io4KPlus;
return true;
} else if (spec.first == RasterDefinition::UHD_4K &&
aja::vec_contains<VPIDStandard>(
kRetail12GVpidStandards, spec.second)) {
swf = SDIWireFormat::
UHD4K_ST2018_12G_Squares_2SI_Kona5_io4KPlus;
return true;
} else {
if (kSDIWireFormats.find(spec) !=
kSDIWireFormats.end()) {
swf = kSDIWireFormats.at(spec);
return true;
}
}
} else {
if (kSDIWireFormats.find(spec) != kSDIWireFormats.end()) {
swf = kSDIWireFormats.at(spec);
return true;
}
}
return false;
}
// Lookup configuration for HDMI input/output in the routing table.
bool Routing::FindRoutingConfigHDMI(HDMIWireFormat hwf, NTV2Mode mode,
bool isRGB, NTV2DeviceID deviceID,
RoutingConfig &routing)
{
if (isRGB) {
if (mode == NTV2_MODE_CAPTURE) {
if (kHDMIRGBCaptureConfigs.find(hwf) !=
kHDMIRGBCaptureConfigs.end()) {
routing = kHDMIRGBCaptureConfigs.at(hwf);
return true;
}
} else {
if (deviceID == DEVICE_ID_TTAP_PRO) {
routing = kHDMIRGBDisplayConfigs.at(
HDMIWireFormat::TTAP_PRO);
return true;
}
if (kHDMIRGBDisplayConfigs.find(hwf) !=
kHDMIRGBDisplayConfigs.end()) {
routing = kHDMIRGBDisplayConfigs.at(hwf);
return true;
}
}
} else {
if (mode == NTV2_MODE_CAPTURE) {
if (kHDMIYCbCrCaptureConfigs.find(hwf) !=
kHDMIYCbCrCaptureConfigs.end()) {
routing = kHDMIYCbCrCaptureConfigs.at(hwf);
return true;
}
} else {
if (kHDMIYCbCrDisplayConfigs.find(hwf) !=
kHDMIYCbCrDisplayConfigs.end()) {
routing = kHDMIYCbCrDisplayConfigs.at(hwf);
return true;
}
}
}
return false;
}
// Lookup configuration for SDI input/output in the routing table.
bool Routing::FindRoutingConfigSDI(SDIWireFormat swf, NTV2Mode mode, bool isRGB,
NTV2DeviceID deviceID,
RoutingConfig &routing)
{
UNUSED_PARAMETER(deviceID);
if (isRGB) {
if (mode == NTV2_MODE_CAPTURE) {
if (kSDIRGBCaptureConfigs.find(swf) !=
kSDIRGBCaptureConfigs.end()) {
routing = kSDIRGBCaptureConfigs.at(swf);
return true;
}
} else if (mode == NTV2_MODE_DISPLAY) {
if (kSDIRGBDisplayConfigs.find(swf) !=
kSDIRGBDisplayConfigs.end()) {
routing = kSDIRGBDisplayConfigs.at(swf);
return true;
}
}
} else {
if (mode == NTV2_MODE_CAPTURE) {
if (kSDIYCbCrCaptureConfigs.find(swf) !=
kSDIYCbCrCaptureConfigs.end()) {
routing = kSDIYCbCrCaptureConfigs.at(swf);
return true;
}
} else if (mode == NTV2_MODE_DISPLAY) {
if (kSDIYCbCrDisplayConfigs.find(swf) !=
kSDIYCbCrDisplayConfigs.end()) {
routing = kSDIYCbCrDisplayConfigs.at(swf);
return true;
}
}
}
return false;
}
void Routing::StartSourceAudio(const SourceProps &props, CNTV2Card *card)
{
if (!card)
return;
auto inputSrc = props.inputSource;
auto inputSrc = props.InitialInputSource();
auto channel = props.Channel();
auto audioSys = props.AudioSystem();
@ -383,118 +204,42 @@ void Routing::StopSourceAudio(const SourceProps &props, CNTV2Card *card)
}
}
// Guess an SDIWireFormat based on specified Video Format, IOSelection, 4K Transport and device ID.
SDIWireFormat GuessSDIWireFormat(NTV2VideoFormat vf, IOSelection io,
SDI4KTransport t4k,
NTV2DeviceID device_id = DEVICE_ID_NOTFOUND)
{
auto rd = GetRasterDefinition(io, vf, device_id);
auto fg = GetNTV2FrameGeometryFromVideoFormat(vf);
SDIWireFormat swf = SDIWireFormat::Unknown;
if (rd == RasterDefinition::SD) {
swf = SDIWireFormat::SD_ST352;
} else if (rd == RasterDefinition::HD) {
if (fg == NTV2_FG_1280x720) {
swf = SDIWireFormat::HD_720p_ST292;
} else if (fg == NTV2_FG_1920x1080 || fg == NTV2_FG_2048x1080) {
swf = SDIWireFormat::HD_1080_ST292;
}
} else if (rd == RasterDefinition::UHD_4K) {
if (t4k == SDI4KTransport::Squares) {
if (aja::IsSDIFourWireIOSelection(io)) {
swf = SDIWireFormat::UHD4K_ST292_Quad_1_5_Squares;
} else if (aja::IsSDITwoWireIOSelection(io)) {
swf = SDIWireFormat::UHD4K_ST292_Dual_1_5_Squares;
}
} else if (t4k == SDI4KTransport::TwoSampleInterleave) {
if (aja::IsSDIOneWireIOSelection(io)) {
if (NTV2_IS_4K_HFR_VIDEO_FORMAT(vf)) {
if (aja::IsRetailSDI12G(device_id)) {
swf = SDIWireFormat::
UHD4K_ST2018_12G_Squares_2SI_Kona5_io4KPlus;
} else {
swf = SDIWireFormat::
UHD4K_ST2018_12G_Squares_2SI;
}
} else {
if (aja::IsRetailSDI12G(device_id)) {
swf = SDIWireFormat::
UHD4K_ST2018_6G_Squares_2SI_Kona5_io4KPlus;
} else {
swf = SDIWireFormat::
UHD4K_ST2018_6G_Squares_2SI;
}
}
} else if (aja::IsSDITwoWireIOSelection(io)) {
swf = SDIWireFormat::UHD4K_ST425_Dual_3Gb_2SI;
} else if (aja::IsSDIFourWireIOSelection(io)) {
swf = SDIWireFormat::UHD4K_ST425_Quad_3Gb_2SI;
}
}
}
return swf;
}
bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
CNTV2Card *card)
{
if (!card)
return false;
bool found_preset = false;
auto deviceID = props.deviceID;
NTV2VideoFormat vf = props.videoFormat;
if (NTV2_VIDEO_FORMAT_IS_B(props.videoFormat)) {
vf = aja::GetLevelAFormatForLevelBFormat(props.videoFormat);
}
NTV2InputSourceSet inputSources;
aja::IOSelectionToInputSources(props.ioSelect, inputSources);
if (inputSources.empty()) {
blog(LOG_DEBUG,
"No Input Sources specified to configure routing!");
return false;
}
auto init_src = *inputSources.begin();
auto init_channel = NTV2InputSourceToChannel(init_src);
RoutingConfig rc;
auto init_src = props.InitialInputSource();
auto init_channel = props.Channel();
RoutingConfigurator rc;
RoutingPreset rp;
if (NTV2_INPUT_SOURCE_IS_SDI(init_src)) {
SDIWireFormat swf = SDIWireFormat::Unknown;
auto standard = VPIDStandard_Unknown;
auto vpidList = props.vpids;
if (vpidList.size() > 0)
standard = vpidList.at(0).Standard();
if (standard != VPIDStandard_Unknown) {
// Determine SDI format based on raster "definition" and VPID byte 1 value (AKA SMPTE standard)
auto rasterDef = GetRasterDefinition(props.ioSelect, vf,
props.deviceID);
VPIDSpec vpidSpec = std::make_pair(rasterDef, standard);
DetermineSDIWireFormat(deviceID, vpidSpec, swf);
} else {
// Best guess SDI format from incoming video format if no VPIDs detected
swf = GuessSDIWireFormat(vf, props.ioSelect,
props.sdi4kTransport,
props.deviceID);
auto vpidStandard = VPIDStandard_Unknown;
if (props.autoDetect) {
auto vpidList = props.vpids;
if (vpidList.size() > 0)
vpidStandard = vpidList.at(0).Standard();
}
if (swf == SDIWireFormat::Unknown) {
blog(LOG_DEBUG, "Could not determine SDI Wire Format!");
return false;
if (vpidStandard == VPIDStandard_Unknown) {
vpidStandard = DetermineVPIDStandard(
deviceID, props.ioSelect, props.videoFormat,
props.pixelFormat, props.sdiTransport,
props.sdi4kTransport);
}
if (!FindRoutingConfigSDI(swf, mode,
NTV2_IS_FBF_RGB(props.pixelFormat),
props.deviceID, rc)) {
blog(LOG_DEBUG,
"Could not find RoutingConfig for SDI Wire Format!");
if (!rc.FindFirstPreset(ConnectionKind::SDI, props.deviceID,
NTV2_MODE_CAPTURE, vf,
props.pixelFormat, vpidStandard, rp)) {
blog(LOG_WARNING,
"No SDI capture routing preset found!");
return false;
}
} else if (NTV2_INPUT_SOURCE_IS_HDMI(init_src)) {
HDMIWireFormat hwf = HDMIWireFormat::Unknown;
if (NTV2_IS_FBF_RGB(props.pixelFormat)) {
if (NTV2_IS_HD_VIDEO_FORMAT(vf))
hwf = HDMIWireFormat::HD_RGB_LFR;
@ -504,18 +249,20 @@ bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
else if (NTV2_IS_4K_VIDEO_FORMAT(vf))
hwf = HDMIWireFormat::UHD_4K_YCBCR_LFR;
}
if (!FindRoutingConfigHDMI(hwf, mode,
NTV2_IS_FBF_RGB(props.pixelFormat),
props.deviceID, rc)) {
blog(LOG_DEBUG,
"Could not find RoutingConfig for HDMI Wire Format!");
if (!rc.FindFirstPreset(ConnectionKind::HDMI, props.deviceID,
NTV2_MODE_CAPTURE, vf,
props.pixelFormat, VPIDStandard_Unknown,
rp)) {
blog(LOG_WARNING,
"No HDMI capture routing preset found!");
return false;
}
}
LogRoutingPreset(rp);
// Substitute channel placeholders for actual indices
std::string route_string = rc.route_string;
std::string route_string = rp.route_string;
ULWord start_channel_index = GetIndexForNTV2Channel(init_channel);
for (ULWord c = 0; c < 8; c++) {
std::string channel_placeholder =
@ -526,43 +273,45 @@ bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
}
NTV2XptConnections cnx;
ParseRouteString(route_string, cnx);
if (!ParseRouteString(route_string, cnx))
return false;
card->ApplySignalRoute(cnx, false);
// Apply SDI widget settings
start_channel_index = GetIndexForNTV2Channel(init_channel);
for (uint32_t i = (uint32_t)start_channel_index;
i < (start_channel_index + rc.num_wires); i++) {
i < (start_channel_index + rp.num_channels); i++) {
NTV2Channel channel = GetNTV2ChannelForIndex(i);
if (::NTV2DeviceHasBiDirectionalSDI(deviceID)) {
card->SetSDITransmitEnable(channel,
mode == NTV2_MODE_DISPLAY);
}
card->SetSDIOut3GEnable(channel, rc.enable_3g_out);
card->SetSDIOut3GbEnable(channel, rc.enable_3gb_out);
card->SetSDIOut6GEnable(channel, rc.enable_6g_out);
card->SetSDIOut12GEnable(channel, rc.enable_12g_out);
card->SetSDIOut3GEnable(channel, rp.flags & kEnable3GOut);
card->SetSDIOut3GbEnable(channel, rp.flags & kEnable3GbOut);
card->SetSDIOut6GEnable(channel, rp.flags & kEnable6GOut);
card->SetSDIOut12GEnable(channel, rp.flags & kEnable12GOut);
card->SetSDIInLevelBtoLevelAConversion((UWord)i,
rc.convert_3g_in);
card->SetSDIOutLevelAtoLevelBConversion((UWord)i,
rc.convert_3g_out);
card->SetSDIOutRGBLevelAConversion((UWord)i,
rc.enable_rgb_3ga_convert);
rp.flags & kConvert3GIn);
card->SetSDIOutLevelAtoLevelBConversion(
(UWord)i, rp.flags & kConvert3GOut);
card->SetSDIOutRGBLevelAConversion(
(UWord)i, rp.flags & kConvert3GaRGBOut);
}
// Apply Framestore settings
for (uint32_t i = (uint32_t)start_channel_index;
i < (start_channel_index + rc.num_framestores); i++) {
i < (start_channel_index + rp.num_framestores); i++) {
NTV2Channel channel = GetNTV2ChannelForIndex(i);
card->EnableChannel(channel);
card->SetMode(channel, mode);
card->SetVANCMode(NTV2_VANCMODE_OFF, channel);
card->SetVideoFormat(vf, false, false, channel);
card->SetFrameBufferFormat(channel, props.pixelFormat);
card->SetTsiFrameEnable(rc.enable_tsi, channel);
card->Set4kSquaresEnable(rc.enable_4k_squares, channel);
card->SetQuadQuadSquaresEnable(rc.enable_8k_squares, channel);
card->SetTsiFrameEnable(rp.flags & kEnable4KTSI, channel);
card->Set4kSquaresEnable(rp.flags & kEnable4KSquares, channel);
card->SetQuadQuadSquaresEnable(rp.flags & kEnable8KSquares,
channel);
}
return true;
@ -574,8 +323,8 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
if (!card)
return false;
bool found_preset = false;
auto deviceID = props.deviceID;
NTV2OutputDestinations outputDests;
aja::IOSelectionToOutputDests(props.ioSelect, outputDests);
if (outputDests.empty()) {
@ -586,29 +335,22 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
auto init_dest = *outputDests.begin();
auto init_channel = NTV2OutputDestinationToChannel(init_dest);
RoutingConfig rc;
RoutingConfigurator rc;
RoutingPreset rp;
if (NTV2_OUTPUT_DEST_IS_SDI(init_dest)) {
SDIWireFormat swf = GuessSDIWireFormat(props.videoFormat,
props.ioSelect,
props.sdi4kTransport,
props.deviceID);
if (swf == SDIWireFormat::Unknown) {
blog(LOG_DEBUG, "Could not determine SDI Wire Format!");
return false;
}
if (!FindRoutingConfigSDI(swf, mode,
NTV2_IS_FBF_RGB(props.pixelFormat),
props.deviceID, rc)) {
blog(LOG_DEBUG,
"Could not find RoutingConfig for SDI Wire Format!");
VPIDStandard vpidStandard = DetermineVPIDStandard(
deviceID, props.ioSelect, props.videoFormat,
props.pixelFormat, props.sdiTransport,
props.sdi4kTransport);
if (!rc.FindFirstPreset(ConnectionKind::SDI, props.deviceID,
NTV2_MODE_DISPLAY, props.videoFormat,
props.pixelFormat, vpidStandard, rp)) {
blog(LOG_WARNING,
"No SDI output routing preset found!");
return false;
}
} else if (NTV2_OUTPUT_DEST_IS_HDMI(init_dest)) {
HDMIWireFormat hwf = HDMIWireFormat::Unknown;
// special case devices...
if (props.deviceID == DEVICE_ID_TTAP_PRO) {
hwf = HDMIWireFormat::TTAP_PRO;
@ -627,20 +369,22 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
}
}
}
if (!FindRoutingConfigHDMI(hwf, mode,
NTV2_IS_FBF_RGB(props.pixelFormat),
props.deviceID, rc)) {
blog(LOG_DEBUG,
"Could not find RoutingConfig for HDMI Wire Format!");
if (!rc.FindFirstPreset(ConnectionKind::HDMI, props.deviceID,
NTV2_MODE_DISPLAY, props.videoFormat,
props.pixelFormat, VPIDStandard_Unknown,
rp)) {
blog(LOG_WARNING,
"No HDMI output routing preset found!");
return false;
}
}
std::string route_string = rc.route_string;
LogRoutingPreset(rp);
std::string route_string = rp.route_string;
// Replace framestore channel placeholders
ULWord start_framestore_index = initial_framestore_output_index(
ULWord start_framestore_index = InitialFramestoreOutputIndex(
deviceID, props.ioSelect, init_channel);
for (ULWord c = 0; c < NTV2_MAX_NUM_CHANNELS; c++) {
std::string fs_channel_placeholder =
@ -661,75 +405,58 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
}
NTV2XptConnections cnx;
ParseRouteString(route_string, cnx);
if (!ParseRouteString(route_string, cnx))
return false;
card->ApplySignalRoute(cnx, false);
// Apply SDI widget settings
if (props.ioSelect != IOSelection::HDMIMonitorOut) {
start_channel_index = GetIndexForNTV2Channel(init_channel);
for (uint32_t i = (uint32_t)start_channel_index;
i < (start_channel_index + rc.num_wires); i++) {
i < (start_channel_index + rp.num_channels); i++) {
NTV2Channel channel = GetNTV2ChannelForIndex(i);
if (::NTV2DeviceHasBiDirectionalSDI(deviceID)) {
card->SetSDITransmitEnable(
channel, mode == NTV2_MODE_DISPLAY);
}
card->SetSDIOut3GEnable(channel, rc.enable_3g_out);
card->SetSDIOut3GbEnable(channel, rc.enable_3gb_out);
card->SetSDIOut6GEnable(channel, rc.enable_6g_out);
card->SetSDIOut12GEnable(channel, rc.enable_12g_out);
card->SetSDIOut3GEnable(channel,
rp.flags & kEnable3GOut);
card->SetSDIOut3GbEnable(channel,
rp.flags & kEnable3GbOut);
card->SetSDIOut6GEnable(channel,
rp.flags & kEnable6GOut);
card->SetSDIOut12GEnable(channel,
rp.flags & kEnable12GOut);
card->SetSDIInLevelBtoLevelAConversion(
(UWord)i, rc.convert_3g_in);
(UWord)i, rp.flags & kConvert3GIn);
card->SetSDIOutLevelAtoLevelBConversion(
(UWord)i, rc.convert_3g_out);
(UWord)i, rp.flags & kConvert3GOut);
card->SetSDIOutRGBLevelAConversion(
(UWord)i, rc.enable_rgb_3ga_convert);
(UWord)i, rp.flags & kConvert3GaRGBOut);
}
}
// Apply Framestore settings
start_framestore_index = initial_framestore_output_index(
start_framestore_index = InitialFramestoreOutputIndex(
deviceID, props.ioSelect, init_channel);
for (uint32_t i = (uint32_t)start_framestore_index;
i < (start_framestore_index + rc.num_framestores); i++) {
i < (start_framestore_index + rp.num_framestores); i++) {
NTV2Channel channel = GetNTV2ChannelForIndex(i);
card->EnableChannel(channel);
card->SetMode(channel, mode);
card->SetVANCMode(NTV2_VANCMODE_OFF, channel);
card->SetVideoFormat(props.videoFormat, false, false, channel);
card->SetFrameBufferFormat(channel, props.pixelFormat);
card->SetTsiFrameEnable(rc.enable_tsi, channel);
card->Set4kSquaresEnable(rc.enable_4k_squares, channel);
card->SetQuadQuadSquaresEnable(rc.enable_8k_squares, channel);
card->SetTsiFrameEnable(rp.flags & kEnable4KTSI, channel);
card->Set4kSquaresEnable(rp.flags & kEnable4KSquares, channel);
card->SetQuadQuadSquaresEnable(rp.flags & kEnable8KSquares,
channel);
}
return true;
}
ULWord Routing::initial_framestore_output_index(NTV2DeviceID deviceID,
IOSelection io,
NTV2Channel init_channel)
{
if (deviceID == DEVICE_ID_TTAP_PRO) {
return 0;
} else if (deviceID == DEVICE_ID_KONA1) {
return 1;
} else if (deviceID == DEVICE_ID_IO4K ||
deviceID == DEVICE_ID_IO4KPLUS) {
// SDI Monitor output uses framestore 4
if (io == IOSelection::SDI5)
return 3;
}
// HDMI Monitor output uses framestore 4
if (io == IOSelection::HDMIMonitorOut) {
return 3;
}
return GetIndexForNTV2Channel(init_channel);
}
// Output Routing
void Routing::ConfigureOutputAudio(const OutputProps &props, CNTV2Card *card)
{
if (!card)
@ -813,3 +540,60 @@ void Routing::ConfigureOutputAudio(const OutputProps &props, CNTV2Card *card)
card->StopAudioOutput(audioSys);
}
ULWord Routing::InitialFramestoreOutputIndex(NTV2DeviceID deviceID,
IOSelection io,
NTV2Channel init_channel)
{
if (deviceID == DEVICE_ID_TTAP_PRO) {
return 0;
} else if (deviceID == DEVICE_ID_KONA1) {
return 1;
} else if (deviceID == DEVICE_ID_IO4K ||
deviceID == DEVICE_ID_IO4KPLUS) {
// SDI Monitor output uses framestore 4
if (io == IOSelection::SDI5)
return 3;
}
// HDMI Monitor output uses framestore 4
if (io == IOSelection::HDMIMonitorOut) {
return 3;
}
return GetIndexForNTV2Channel(init_channel);
}
void Routing::LogRoutingPreset(const RoutingPreset &rp)
{
auto hexStr = [&](uint8_t val) -> std::string {
std::stringstream ss;
ss << std::setfill('0') << std::setw(sizeof(uint8_t) * 2)
<< std::hex << (val | 0);
return ss.str();
};
std::stringstream ss;
ss << "[ AJA Crosspoint Routing Preset ]"
<< "\nPreset: " << rp.name;
if (rp.kind == ConnectionKind::SDI) {
ss << "\nVPID Standard: 0x"
<< hexStr(static_cast<uint8_t>(rp.vpid_standard));
}
ss << "\nMode: " << NTV2ModeToString(rp.mode)
<< "\nChannels: " << rp.num_channels
<< "\nFramestores: " << rp.num_framestores;
blog(LOG_INFO, ss.str().c_str());
if (rp.device_ids.size() > 0) {
ss.clear();
for (auto id : rp.device_ids) {
ss << " - " << NTV2DeviceIDToString(id) << "\n";
}
blog(LOG_INFO, "\nCompatible Device IDs: \n%s",
ss.str().c_str());
}
}
} // aja

View File

@ -1,15 +1,16 @@
#pragma once
#include "aja-props.hpp"
#include "aja-presets.hpp"
#include <ajantv2/includes/ntv2enums.h>
#include <ajantv2/includes/ntv2signalrouter.h>
#include <iostream>
#include <string>
#include <map>
#include <vector>
class CNTV2Card;
namespace aja {
/* The AJA hardware and NTV2 SDK uses a concept called "Signal Routing" to connect high-level firmware
* blocks known as "Widgets" to one another via "crosspoint" connections. This facilitates streaming
* data from one Widget to another to achieve specific functionality.
@ -41,99 +42,26 @@ struct RoutingConfig {
route_string; // signal routing shorthand string to parse into crosspoint connections
};
/* This table is used to correlate a particular "raster definition" (i.e. SD/HD/4K/etc.)
* and SMPTE VPID transport byte (VPIDStandard) to an SDIWireFormat enum.
* This allows mapping SDI video signals to the correct format, particularly in the case
* where multiple SDI formats share the same VPID transport value.
* For example: VPIDStandard_1080 (0x85) is used on the wire for both single-link (1x SDI wire)
* 1080-line HD SDI video AND quad-link (4x SDI wires) UHD/4K "square-division" video.
*/
using VPIDSpec = std::pair<RasterDefinition, VPIDStandard>;
static inline const std::map<VPIDSpec, SDIWireFormat> kSDIWireFormats = {
{{RasterDefinition::SD, VPIDStandard_483_576}, SDIWireFormat::SD_ST352},
{{RasterDefinition::HD, VPIDStandard_720},
SDIWireFormat::HD_720p_ST292},
{{RasterDefinition::HD, VPIDStandard_1080},
SDIWireFormat::HD_1080_ST292},
{{RasterDefinition::HD, VPIDStandard_1080_DualLink},
SDIWireFormat::HD_1080_ST372_Dual},
{{RasterDefinition::HD, VPIDStandard_720_3Ga},
SDIWireFormat::HD_720p_ST425_3Ga},
{{RasterDefinition::HD, VPIDStandard_1080_3Ga},
SDIWireFormat::HD_1080p_ST425_3Ga},
{{RasterDefinition::HD, VPIDStandard_1080_DualLink_3Gb},
SDIWireFormat::HD_1080p_ST425_3Gb_DL},
{{RasterDefinition::HD, VPIDStandard_720_3Gb},
SDIWireFormat::HD_720p_ST425_3Gb},
{{RasterDefinition::HD, VPIDStandard_1080_3Gb},
SDIWireFormat::HD_1080p_ST425_3Gb},
{{RasterDefinition::HD, VPIDStandard_1080_Dual_3Ga},
SDIWireFormat::HD_1080p_ST425_Dual_3Ga},
{{RasterDefinition::HD, VPIDStandard_1080_Dual_3Gb},
SDIWireFormat::HD_1080p_ST425_Dual_3Gb},
{{RasterDefinition::UHD_4K, VPIDStandard_1080_3Gb},
SDIWireFormat::UHD4K_ST292_Dual_1_5_Squares},
{{RasterDefinition::UHD_4K, VPIDStandard_1080},
SDIWireFormat::UHD4K_ST292_Quad_1_5_Squares},
{{RasterDefinition::UHD_4K, VPIDStandard_1080_3Ga},
SDIWireFormat::UHD4K_ST425_Quad_3Ga_Squares},
{{RasterDefinition::UHD_4K, VPIDStandard_1080_DualLink_3Gb},
SDIWireFormat::UHD4K_ST425_Quad_3Gb_Squares},
{{RasterDefinition::UHD_4K, VPIDStandard_2160_DualLink},
SDIWireFormat::UHD4K_ST425_Dual_3Gb_2SI},
{{RasterDefinition::UHD_4K, VPIDStandard_2160_QuadLink_3Ga},
SDIWireFormat::UHD4K_ST425_Quad_3Ga_2SI},
{{RasterDefinition::UHD_4K, VPIDStandard_2160_QuadDualLink_3Gb},
SDIWireFormat::UHD4K_ST425_Quad_3Gb_2SI},
{{RasterDefinition::UHD_4K, VPIDStandard_2160_Single_6Gb},
SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI},
{{RasterDefinition::UHD_4K_Retail_12G, VPIDStandard_2160_Single_6Gb},
SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI_Kona5_io4KPlus},
{{RasterDefinition::UHD_4K, VPIDStandard_2160_Single_12Gb},
SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI},
{{RasterDefinition::UHD_4K_Retail_12G, VPIDStandard_2160_Single_12Gb},
SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI_Kona5_io4KPlus},
{{RasterDefinition::UHD2_8K, VPIDStandard_4320_DualLink_12Gb},
SDIWireFormat::UHD28K_ST2082_Dual_12G},
{{RasterDefinition::UHD2_8K, VPIDStandard_2160_DualLink_12Gb},
SDIWireFormat::UHD28K_ST2082_RGB_Dual_12G},
{{RasterDefinition::UHD2_8K, VPIDStandard_4320_QuadLink_12Gb},
SDIWireFormat::UHD28K_ST2082_Quad_12G},
};
extern RasterDefinition
GetRasterDefinition(IOSelection io, NTV2VideoFormat vf,
NTV2DeviceID deviceID = DEVICE_ID_NOTFOUND);
extern std::string RasterDefinitionToString(RasterDefinition rd);
// Applies RoutingConfig settings to the card to configure a specific SDI/HDMI capture/output mode.
class Routing {
public:
static bool ParseRouteString(const std::string &route,
NTV2XptConnections &cnx);
static bool DetermineSDIWireFormat(NTV2DeviceID deviceID, VPIDSpec spec,
SDIWireFormat &swf);
static bool FindRoutingConfigHDMI(HDMIWireFormat hwf, NTV2Mode mode,
bool isRGB, NTV2DeviceID deviceID,
RoutingConfig &routing);
static bool FindRoutingConfigSDI(SDIWireFormat swf, NTV2Mode mode,
bool isRGB, NTV2DeviceID deviceID,
RoutingConfig &routing);
static void StartSourceAudio(const SourceProps &props, CNTV2Card *card);
static void StopSourceAudio(const SourceProps &props, CNTV2Card *card);
static bool ConfigureSourceRoute(const SourceProps &props,
NTV2Mode mode, CNTV2Card *card);
static bool ConfigureOutputRoute(const OutputProps &props,
NTV2Mode mode, CNTV2Card *card);
static ULWord initial_framestore_output_index(NTV2DeviceID deviceID,
IOSelection io,
NTV2Channel init_channel);
static void ConfigureOutputAudio(const OutputProps &props,
CNTV2Card *card);
static ULWord InitialFramestoreOutputIndex(NTV2DeviceID deviceID,
IOSelection io,
NTV2Channel init_channel);
static void LogRoutingPreset(const RoutingPreset &rp);
};
} // aja

View File

@ -10,6 +10,7 @@
#include <obs-module.h>
#include <ajantv2/includes/ntv2card.h>
#include <ajantv2/includes/ntv2utils.h>
#define NTV2_AUDIOSIZE_MAX (401 * 1024)
@ -73,10 +74,8 @@ std::string AJASource::GetName() const
void populate_source_device_list(obs_property_t *list)
{
obs_property_list_clear(list);
auto &cardManager = aja::CardManager::Instance();
cardManager.EnumerateCards();
for (const auto &iter : cardManager.GetCardEntries()) {
if (iter.second) {
CNTV2Card *card = iter.second->GetCard();
@ -117,11 +116,9 @@ static void ResetAudioBufferOffsets(CNTV2Card *card,
offsets.readOffset = 0;
offsets.wrapAddress = 0;
offsets.bytesRead = 0;
card->GetAudioReadOffset(offsets.readOffset, audioSystem);
card->GetAudioWrapAddress(offsets.wrapAddress, audioSystem);
offsets.wrapAddress += offsets.readOffset;
offsets.lastAddress = offsets.readOffset;
}
@ -130,7 +127,6 @@ void AJASource::GenerateTestPattern(NTV2VideoFormat vf, NTV2PixelFormat pf,
{
NTV2VideoFormat vid_fmt = vf;
NTV2PixelFormat pix_fmt = pf;
if (vid_fmt == NTV2_FORMAT_UNKNOWN)
vid_fmt = NTV2_FORMAT_720p_5994;
if (pix_fmt == NTV2_FBF_INVALID)
@ -138,17 +134,14 @@ void AJASource::GenerateTestPattern(NTV2VideoFormat vf, NTV2PixelFormat pf,
NTV2FormatDesc fd(vid_fmt, pix_fmt, NTV2_VANCMODE_OFF);
auto bufSize = fd.GetTotalRasterBytes();
if (bufSize != mTestPattern.size()) {
mTestPattern.clear();
mTestPattern.resize(bufSize);
NTV2TestPatternGen gen;
gen.DrawTestPattern(ps, fd.GetRasterWidth(),
fd.GetRasterHeight(), pix_fmt,
mTestPattern);
}
if (mTestPattern.size() == 0) {
blog(LOG_DEBUG,
"AJASource::GenerateTestPattern: Error generating test pattern!");
@ -163,13 +156,12 @@ void AJASource::GenerateTestPattern(NTV2VideoFormat vf, NTV2PixelFormat pf,
obsFrame.format = aja::AJAPixelFormatToOBSVideoFormat(pix_fmt);
obsFrame.data[0] = mTestPattern.data();
obsFrame.linesize[0] = fd.GetBytesPerRow();
video_format_get_parameters(VIDEO_CS_DEFAULT, VIDEO_RANGE_FULL,
obsFrame.color_matrix,
obsFrame.color_range_min,
obsFrame.color_range_max);
obs_source_output_video2(mSource, &obsFrame);
blog(LOG_DEBUG, "AJASource::GenerateTestPattern: Black");
}
void AJASource::CaptureThread(AJAThread *thread, void *data)
@ -195,9 +187,9 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
}
auto sourceProps = ajaSource->GetSourceProps();
auto inputSource = sourceProps.InitialInputSource();
auto channel = sourceProps.Channel();
auto audioSystem = sourceProps.AudioSystem();
// Current "on-air" frame on the card. The capture thread "Ping-pongs" between
// two frames, starting at an index corresponding to the framestore channel.
// For example:
@ -221,26 +213,21 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
while (ajaSource->IsCapturing()) {
if (card->GetModelName() == "(Not Found)") {
os_sleep_ms(250);
obs_source_update(ajaSource->mSource, settings);
break;
}
auto videoFormat = sourceProps.videoFormat;
auto pixelFormat = sourceProps.pixelFormat;
auto ioSelection = sourceProps.ioSelect;
bool audioOverrun = false;
card->WaitForInputFieldID(NTV2_FIELD0, channel);
currentCardFrame ^= 1;
auto videoFormat = sourceProps.videoFormat;
auto pixelFormat = sourceProps.pixelFormat;
// Card format detection -- restarts capture thread via aja_source_update callback
auto newVideoFormat = card->GetInputVideoFormat(
sourceProps.inputSource,
aja::Is3GLevelB(card, channel));
inputSource, aja::Is3GLevelB(card, channel));
if (newVideoFormat == NTV2_FORMAT_UNKNOWN) {
blog(LOG_DEBUG,
"AJASource::CaptureThread: Video format unknown!");
@ -250,6 +237,9 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
continue;
}
newVideoFormat = aja::HandleSpecialCaseFormats(
ioSelection, newVideoFormat, sourceProps.deviceID);
if (sourceProps.autoDetect && (videoFormat != newVideoFormat)) {
blog(LOG_INFO,
"AJASource::CaptureThread: New Video Format detected! Triggering 'aja_source_update' callback and returning...");
@ -258,33 +248,26 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
NTV2VideoFormatToString(videoFormat, true).c_str(),
NTV2VideoFormatToString(newVideoFormat, true)
.c_str());
os_sleep_ms(250);
obs_source_update(ajaSource->mSource, settings);
break;
}
card->ReadAudioLastIn(offsets.currentAddress, audioSystem);
offsets.currentAddress &= ~0x3; // Force DWORD alignment
offsets.currentAddress += offsets.readOffset;
if (offsets.currentAddress < offsets.lastAddress) {
offsets.bytesRead =
offsets.wrapAddress - offsets.lastAddress;
if (offsets.bytesRead >
ajaSource->mAudioBuffer.GetByteCount()) {
blog(LOG_DEBUG,
"AJASource::CaptureThread: Audio overrun (1)! Buffer Size: %d, Bytes Captured: %d",
ajaSource->mAudioBuffer.GetByteCount(),
offsets.bytesRead);
ResetAudioBufferOffsets(card, audioSystem,
offsets);
audioOverrun = true;
}
@ -293,7 +276,6 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
ajaSource->mAudioBuffer,
offsets.lastAddress,
offsets.bytesRead);
card->DMAReadAudio(
audioSystem,
reinterpret_cast<ULWord *>(
@ -303,42 +285,33 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
offsets.readOffset,
offsets.currentAddress -
offsets.readOffset);
offsets.bytesRead += offsets.currentAddress -
offsets.readOffset;
}
if (offsets.bytesRead >
ajaSource->mAudioBuffer.GetByteCount()) {
blog(LOG_DEBUG,
"AJASource::CaptureThread: Audio overrun (2)! Buffer Size: %d, Bytes Captured: %d",
ajaSource->mAudioBuffer.GetByteCount(),
offsets.bytesRead);
ResetAudioBufferOffsets(card, audioSystem,
offsets);
audioOverrun = true;
}
} else {
offsets.bytesRead =
offsets.currentAddress - offsets.lastAddress;
if (offsets.bytesRead >
ajaSource->mAudioBuffer.GetByteCount()) {
blog(LOG_DEBUG,
"AJASource::CaptureThread: Audio overrun (3)! Buffer Size: %d, Bytes Captured: %d",
ajaSource->mAudioBuffer.GetByteCount(),
offsets.bytesRead);
ResetAudioBufferOffsets(card, audioSystem,
offsets);
audioOverrun = true;
}
if (!audioOverrun) {
card->DMAReadAudio(audioSystem,
ajaSource->mAudioBuffer,
@ -349,7 +322,6 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
if (!audioOverrun) {
offsets.lastAddress = offsets.currentAddress;
obs_source_audio audioPacket;
audioPacket.samples_per_sec = 48000;
audioPacket.format = AUDIO_FORMAT_32BIT;
@ -358,7 +330,6 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
audioPacket.timestamp = os_gettime_ns();
audioPacket.data[0] = (uint8_t *)ajaSource->mAudioBuffer
.GetHostPointer();
obs_source_output_audio(ajaSource->mSource,
&audioPacket);
}
@ -378,7 +349,6 @@ void AJASource::CaptureThread(AJAThread *thread, void *data)
videoFormat);
NTV2FormatDesc fd(actualVideoFormat, pixelFormat);
struct obs_source_frame2 obsFrame;
obsFrame.flip = false;
obsFrame.timestamp = os_gettime_ns();
@ -497,18 +467,22 @@ bool AJASource::ReadChannelVPIDs(NTV2Channel channel, VPIDData &vpids)
return read_ok;
}
bool AJASource::ReadWireFormats(NTV2DeviceID device_id,
const NTV2InputSourceSet &srcs,
bool AJASource::ReadWireFormats(NTV2DeviceID device_id, IOSelection io_select,
NTV2VideoFormat &vf, NTV2PixelFormat &pf,
VPIDDataList &vpids)
{
if (srcs.empty())
NTV2InputSourceSet input_srcs;
aja::IOSelectionToInputSources(io_select, input_srcs);
if (input_srcs.empty()) {
blog(LOG_INFO,
"AJASource::ReadWireFormats: No NTV2InputSources found for IOSelection %s",
aja::IOSelectionToString(io_select).c_str());
return false;
}
NTV2InputSource initial_src = *srcs.begin();
for (auto &&src : srcs) {
NTV2InputSource initial_src = *input_srcs.begin();
for (auto &&src : input_srcs) {
auto channel = NTV2InputSourceToChannel(src);
mCard->EnableChannel(channel);
if (NTV2_INPUT_SOURCE_IS_SDI(src)) {
if (NTV2DeviceHasBiDirectionalSDI(device_id)) {
@ -567,6 +541,8 @@ bool AJASource::ReadWireFormats(NTV2DeviceID device_id,
}
}
vf = aja::HandleSpecialCaseFormats(io_select, vf, device_id);
blog(LOG_INFO, "AJASource::ReadWireFormats - Detected video format %s",
NTV2VideoFormatToString(vf).c_str());
@ -625,11 +601,13 @@ bool aja_source_device_changed(void *data, obs_properties_t *props,
return false;
}
auto &cardManager = aja::CardManager::Instance();
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
if (!cardID)
return false;
auto &cardManager = aja::CardManager::Instance();
auto cardEntry = cardManager.GetCardEntry(cardID);
if (!cardID || !cardEntry) {
if (!cardEntry) {
blog(LOG_DEBUG,
"aja_source_device_changed: Card Entry not found for %s",
cardID);
@ -663,17 +641,28 @@ bool aja_source_device_changed(void *data, obs_properties_t *props,
obs_properties_get(props, kUIPropVideoFormatSelect.id);
obs_property_t *pix_fmt_list =
obs_properties_get(props, kUIPropPixelFormatSelect.id);
obs_property_t *sdi_trx_list =
obs_properties_get(props, kUIPropSDITransport.id);
obs_property_t *sdi_4k_list =
obs_properties_get(props, kUIPropSDI4KTransport.id);
obs_properties_get(props, kUIPropSDITransport4K.id);
obs_property_list_clear(vid_fmt_list);
obs_property_list_add_int(vid_fmt_list, "Auto", kVideoFormatAuto);
obs_property_list_add_int(vid_fmt_list, obs_module_text("Auto"),
kAutoDetect);
populate_video_format_list(deviceID, vid_fmt_list, videoFormatChannel1);
obs_property_list_clear(pix_fmt_list);
obs_property_list_add_int(pix_fmt_list, "Auto", kPixelFormatAuto);
obs_property_list_add_int(pix_fmt_list, obs_module_text("Auto"),
kAutoDetect);
populate_pixel_format_list(deviceID, pix_fmt_list);
IOSelection io_select = static_cast<IOSelection>(
obs_data_get_int(settings, kUIPropInput.id));
obs_property_list_clear(sdi_trx_list);
obs_property_list_add_int(sdi_trx_list, obs_module_text("Auto"),
kAutoDetect);
populate_sdi_transport_list(sdi_trx_list, io_select);
obs_property_list_clear(sdi_4k_list);
populate_sdi_4k_transport_list(sdi_4k_list);
@ -706,8 +695,11 @@ bool aja_io_selection_changed(void *data, obs_properties_t *props,
return false;
}
auto &cardManager = aja::CardManager::Instance();
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
if (!cardID)
return false;
auto &cardManager = aja::CardManager::Instance();
auto cardEntry = cardManager.GetCardEntry(cardID);
if (!cardEntry) {
blog(LOG_DEBUG,
@ -770,7 +762,8 @@ void aja_source_destroy(void *data)
CNTV2Card *card = ajaSource->GetCard();
if (card) {
deviceID = card->GetDeviceID();
Routing::StopSourceAudio(ajaSource->GetSourceProps(), card);
aja::Routing::StopSourceAudio(ajaSource->GetSourceProps(),
card);
}
ajaSource->mVideoBuffer.Deallocate();
@ -779,9 +772,7 @@ void aja_source_destroy(void *data)
ajaSource->mAudioBuffer = NULL;
auto &cardManager = aja::CardManager::Instance();
const auto &cardID = ajaSource->CardID();
auto cardEntry = cardManager.GetCardEntry(cardID);
if (!cardEntry) {
blog(LOG_DEBUG,
@ -863,30 +854,29 @@ static void aja_source_update(void *data, obs_data_t *settings)
return;
}
const std::string &wantCardID =
obs_data_get_string(settings, kUIPropDevice.id);
const std::string &currentCardID = ajaSource->CardID();
auto io_select = static_cast<IOSelection>(
obs_data_get_int(settings, kUIPropInput.id));
auto vf_select = static_cast<NTV2VideoFormat>(
obs_data_get_int(settings, kUIPropVideoFormatSelect.id));
auto pf_select = static_cast<NTV2PixelFormat>(
obs_data_get_int(settings, kUIPropPixelFormatSelect.id));
auto t4_select = static_cast<SDI4KTransport>(
obs_data_get_int(settings, kUIPropSDI4KTransport.id));
auto sdi_trx_select = static_cast<SDITransport>(
obs_data_get_int(settings, kUIPropSDITransport.id));
auto sdi_t4k_select = static_cast<SDITransport4K>(
obs_data_get_int(settings, kUIPropSDITransport4K.id));
bool deactivateWhileNotShowing =
obs_data_get_bool(settings, kUIPropDeactivateWhenNotShowing.id);
const std::string &wantCardID =
obs_data_get_string(settings, kUIPropDevice.id);
auto &cardManager = aja::CardManager::Instance();
cardManager.EnumerateCards();
const std::string &currentCardID = ajaSource->CardID();
if (wantCardID != currentCardID) {
initialized = false;
ajaSource->Deactivate();
}
auto &cardManager = aja::CardManager::Instance();
cardManager.EnumerateCards();
auto cardEntry = cardManager.GetCardEntry(wantCardID);
if (!cardEntry) {
blog(LOG_DEBUG,
@ -894,7 +884,6 @@ static void aja_source_update(void *data, obs_data_t *settings)
wantCardID.c_str());
return;
}
CNTV2Card *card = cardEntry->GetCard();
if (!card || !card->IsOpen()) {
blog(LOG_ERROR, "aja_source_update: AJA device %s not open!",
@ -907,7 +896,6 @@ static void aja_source_update(void *data, obs_data_t *settings)
wantCardID.c_str());
return;
}
ajaSource->SetCard(cardEntry->GetCard());
SourceProps curr_props = ajaSource->GetSourceProps();
@ -941,37 +929,31 @@ static void aja_source_update(void *data, obs_data_t *settings)
return;
}
NTV2InputSourceSet input_srcs;
aja::IOSelectionToInputSources(io_select, input_srcs);
if (input_srcs.empty()) {
blog(LOG_INFO,
"aja_source_update: No NTV2InputSources found for IOSelection %s",
aja::IOSelectionToString(io_select).c_str());
return;
}
SourceProps want_props;
want_props.deviceID = card->GetDeviceID();
want_props.ioSelect = io_select;
want_props.inputSource = *input_srcs.begin();
want_props.videoFormat =
((int32_t)vf_select == kVideoFormatAuto)
((int32_t)vf_select == kAutoDetect)
? NTV2_FORMAT_UNKNOWN
: static_cast<NTV2VideoFormat>(vf_select);
want_props.pixelFormat =
((int32_t)pf_select == kPixelFormatAuto)
((int32_t)pf_select == kAutoDetect)
? NTV2_FBF_INVALID
: static_cast<NTV2PixelFormat>(pf_select);
want_props.sdi4kTransport = t4_select;
want_props.sdiTransport =
((int32_t)sdi_trx_select == kAutoDetect)
? SDITransport::Unknown
: static_cast<SDITransport>(sdi_trx_select);
want_props.sdi4kTransport = sdi_t4k_select;
want_props.vpids.clear();
want_props.deactivateWhileNotShowing = deactivateWhileNotShowing;
want_props.autoDetect = ((int32_t)vf_select == kVideoFormatAuto ||
(int32_t)pf_select == kPixelFormatAuto);
want_props.autoDetect = ((int32_t)vf_select == kAutoDetect ||
(int32_t)pf_select == kAutoDetect);
ajaSource->SetCardID(wantCardID);
ajaSource->SetDeviceIndex((UWord)cardEntry->GetCardIndex());
if (NTV2_IS_4K_VIDEO_FORMAT(want_props.videoFormat) &&
want_props.sdi4kTransport == SDI4KTransport::Squares) {
want_props.sdi4kTransport == SDITransport4K::Squares) {
if (want_props.ioSelect == IOSelection::SDI1_2) {
want_props.ioSelect = IOSelection::SDI1_2_Squares;
} else if (want_props.ioSelect == IOSelection::SDI3_4) {
@ -1009,21 +991,20 @@ static void aja_source_update(void *data, obs_data_t *settings)
// Read SDI video payload IDs (VPID) used for helping to determine the wire format
NTV2VideoFormat new_vf = want_props.videoFormat;
NTV2PixelFormat new_pf = want_props.pixelFormat;
if (!ajaSource->ReadWireFormats(want_props.deviceID, input_srcs, new_vf,
new_pf, want_props.vpids)) {
if (!ajaSource->ReadWireFormats(want_props.deviceID,
want_props.ioSelect, new_vf, new_pf,
want_props.vpids)) {
blog(LOG_ERROR, "aja_source_update: ReadWireFormats failed!");
cardEntry->ReleaseInputSelection(want_props.ioSelect,
curr_props.deviceID,
ajaSource->GetName());
return;
}
// Set auto-detected formats
if ((int32_t)vf_select == kVideoFormatAuto)
if ((int32_t)vf_select == kAutoDetect)
want_props.videoFormat = new_vf;
if ((int32_t)pf_select == kPixelFormatAuto)
if ((int32_t)pf_select == kAutoDetect)
want_props.pixelFormat = new_pf;
if (want_props.videoFormat == NTV2_FORMAT_UNKNOWN ||
@ -1033,66 +1014,51 @@ static void aja_source_update(void *data, obs_data_t *settings)
NTV2VideoFormatToString(want_props.videoFormat).c_str(),
NTV2FrameBufferFormatToString(want_props.pixelFormat)
.c_str());
cardEntry->ReleaseInputSelection(want_props.ioSelect,
curr_props.deviceID,
ajaSource->GetName());
return;
}
// Change capture format and restart capture thread
if (!initialized || want_props != ajaSource->GetSourceProps()) {
Routing::ConfigureSourceRoute(want_props, NTV2_MODE_CAPTURE,
card);
aja::Routing::ConfigureSourceRoute(want_props,
NTV2_MODE_CAPTURE, card);
ajaSource->Deactivate();
initialized = true;
}
ajaSource->SetSourceProps(want_props);
ajaSource->ResetVideoBuffer(want_props.videoFormat,
want_props.pixelFormat);
Routing::StartSourceAudio(want_props, card);
aja::Routing::StartSourceAudio(want_props, card);
card->SetReference(NTV2_REFERENCE_FREERUN);
ajaSource->Activate(true);
}
static obs_properties_t *aja_source_get_properties(void *data)
{
obs_properties_t *props = obs_properties_create();
// Uncomment below to only update when the user presses OK or Apply
// obs_properties_set_flags(props, OBS_PROPERTIES_DEFER_UPDATE);
obs_property_t *device_list = obs_properties_add_list(
props, kUIPropDevice.id, obs_module_text(kUIPropDevice.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_STRING);
populate_source_device_list(device_list);
obs_property_t *io_select_list = obs_properties_add_list(
props, kUIPropInput.id, obs_module_text(kUIPropInput.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_property_t *vid_fmt_list = obs_properties_add_list(
props, kUIPropVideoFormatSelect.id,
obs_module_text(kUIPropVideoFormatSelect.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_list(props, kUIPropPixelFormatSelect.id,
obs_module_text(kUIPropPixelFormatSelect.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_list(props, kUIPropSDI4KTransport.id,
obs_module_text(kUIPropSDI4KTransport.text),
obs_properties_add_list(props, kUIPropSDITransport.id,
obs_module_text(kUIPropSDITransport.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_list(props, kUIPropSDITransport4K.id,
obs_module_text(kUIPropSDITransport4K.text),
OBS_COMBO_TYPE_LIST, OBS_COMBO_FORMAT_INT);
obs_properties_add_bool(
props, kUIPropDeactivateWhenNotShowing.id,
obs_module_text(kUIPropDeactivateWhenNotShowing.text));
@ -1111,26 +1077,21 @@ void aja_source_get_defaults(obs_data_t *settings)
{
obs_data_set_default_int(settings, kUIPropInput.id,
static_cast<long long>(IOSelection::Invalid));
obs_data_set_default_int(settings, kUIPropVideoFormatSelect.id,
static_cast<long long>(kVideoFormatAuto));
static_cast<long long>(kAutoDetect));
obs_data_set_default_int(settings, kUIPropPixelFormatSelect.id,
static_cast<long long>(kAutoDetect));
obs_data_set_default_int(settings, kUIPropSDITransport.id,
static_cast<long long>(kAutoDetect));
obs_data_set_default_int(
settings, kUIPropPixelFormatSelect.id,
static_cast<long long>(kDefaultAJAPixelFormat));
obs_data_set_default_int(
settings, kUIPropSDI4KTransport.id,
static_cast<long long>(SDI4KTransport::TwoSampleInterleave));
settings, kUIPropSDITransport4K.id,
static_cast<long long>(SDITransport4K::TwoSampleInterleave));
obs_data_set_default_bool(settings, kUIPropDeactivateWhenNotShowing.id,
false);
}
void aja_source_save(void *data, obs_data_t *settings)
{
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
AJASource *ajaSource = (AJASource *)data;
if (!ajaSource) {
blog(LOG_ERROR,
@ -1138,9 +1099,13 @@ void aja_source_save(void *data, obs_data_t *settings)
return;
}
const char *cardID = obs_data_get_string(settings, kUIPropDevice.id);
if (!cardID)
return;
auto &cardManager = aja::CardManager::Instance();
auto cardEntry = cardManager.GetCardEntry(cardID);
if (!cardID || !cardEntry) {
if (!cardEntry) {
blog(LOG_DEBUG, "aja_source_save: Card Entry not found for %s",
cardID);
return;
@ -1176,6 +1141,5 @@ struct obs_source_info create_aja_source_info()
aja_source_info.get_defaults = aja_source_get_defaults;
aja_source_info.save = aja_source_save;
aja_source_info.icon_type = OBS_ICON_TYPE_CAMERA;
return aja_source_info;
}

View File

@ -50,8 +50,7 @@ public:
bool ReadChannelVPIDs(NTV2Channel channel, VPIDData &vpids);
bool ReadWireFormats(NTV2DeviceID device_id,
const NTV2InputSourceSet &srcs,
bool ReadWireFormats(NTV2DeviceID device_id, IOSelection io_select,
NTV2VideoFormat &vf, NTV2PixelFormat &pf,
VPIDDataList &vpids);

View File

@ -13,13 +13,13 @@ struct UIProperty {
static const UIProperty kUIPropCaptureModule = {
"aja_source",
obs_module_text("AJACapture.Device"),
"AJACapture.Device",
"",
};
static const UIProperty kUIPropOutputModule = {
"aja_output",
obs_module_text("AJAOutput.Device"),
"AJAOutput.Device",
"",
};
@ -35,57 +35,75 @@ static const UIProperty kUIPropAJAOutputID = {
static const UIProperty kUIPropDevice = {
"ui_prop_device",
obs_module_text("Device"),
"Device",
"",
};
static const UIProperty kUIPropOutput = {
"ui_prop_output",
obs_module_text("Output"),
"Output",
"",
};
static const UIProperty kUIPropInput = {
"ui_prop_input",
obs_module_text("Input"),
"Input",
"",
};
static const UIProperty kUIPropIOSelect = {"ui_prop_select_input",
obs_module_text("IOSelect"), ""};
static const UIProperty kUIPropIOSelect = {"ui_prop_select_input", "IOSelect",
""};
static const UIProperty kUIPropSDI4KTransport = {
static const UIProperty kUIPropSDITransport = {
"ui_prop_sdi_transport",
obs_module_text("SDI4KTransport"),
"SDITransport",
"",
};
static const UIProperty kUIPropSDITransport4K = {
"ui_prop_sdi_transport_4k",
"SDITransport4K",
"",
};
static const UIProperty kUIPropVideoFormatSelect = {
"ui_prop_vid_fmt",
obs_module_text("VideoFormat"),
"VideoFormat",
"",
};
static const UIProperty kUIPropPixelFormatSelect = {
"ui_prop_pix_fmt",
obs_module_text("PixelFormat"),
"PixelFormat",
"",
};
static const UIProperty kUIPropAutoStartOutput = {
"ui_prop_auto_start_output",
obs_module_text("AutoStart"),
"AutoStart",
"",
};
static const UIProperty kUIPropDeactivateWhenNotShowing = {
"ui_prop_deactivate_when_not_showing",
obs_module_text("DeactivateWhenNotShowing"),
"DeactivateWhenNotShowing",
"",
};
static const UIProperty kUIPropBuffering = {
"ui_prop_buffering",
obs_module_text("Buffering"),
"Buffering",
"",
};
static const UIProperty kUIPropMultiViewEnable = {
"ui_prop_multi_view_enable",
"Enable Multi View",
"",
};
static const UIProperty kUIPropMultiViewAudioSource = {
"ui_prop_multi_view_audio_source",
"Multi View Audio Source",
"",
};

View File

@ -0,0 +1,113 @@
#include "aja-vpid-data.hpp"
VPIDData::VPIDData()
: mVpidA{0},
mVpidB{0},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
}
VPIDData::VPIDData(ULWord vpidA, ULWord vpidB)
: mVpidA{vpidA},
mVpidB{vpidB},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
Parse();
}
VPIDData::VPIDData(const VPIDData &other)
: mVpidA{other.mVpidA},
mVpidB{other.mVpidB},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
Parse();
}
VPIDData::VPIDData(VPIDData &&other)
: mVpidA{other.mVpidA},
mVpidB{other.mVpidB},
mStandardA{VPIDStandard_Unknown},
mStandardB{VPIDStandard_Unknown},
mSamplingA{VPIDSampling_XYZ_444},
mSamplingB{VPIDSampling_XYZ_444}
{
Parse();
}
VPIDData &VPIDData::operator=(const VPIDData &other)
{
mVpidA = other.mVpidA;
mVpidB = other.mVpidB;
return *this;
}
VPIDData &VPIDData::operator=(VPIDData &&other)
{
mVpidA = other.mVpidA;
mVpidB = other.mVpidB;
return *this;
}
bool VPIDData::operator==(const VPIDData &rhs) const
{
return (mVpidA == rhs.mVpidA && mVpidB == rhs.mVpidB);
}
bool VPIDData::operator!=(const VPIDData &rhs) const
{
return !operator==(rhs);
}
void VPIDData::SetA(ULWord vpidA)
{
mVpidA = vpidA;
}
void VPIDData::SetB(ULWord vpidB)
{
mVpidB = vpidB;
}
void VPIDData::Parse()
{
CNTV2VPID parserA;
parserA.SetVPID(mVpidA);
mStandardA = parserA.GetStandard();
mSamplingA = parserA.GetSampling();
CNTV2VPID parserB;
parserB.SetVPID(mVpidB);
mStandardB = parserB.GetStandard();
mSamplingB = parserB.GetSampling();
}
bool VPIDData::IsRGB() const
{
switch (mSamplingA) {
default:
break;
case VPIDSampling_GBR_444:
case VPIDSampling_GBRA_4444:
case VPIDSampling_GBRD_4444:
return true;
}
return false;
}
VPIDStandard VPIDData::Standard() const
{
return mStandardA;
}
VPIDSampling VPIDData::Sampling() const
{
return mSamplingA;
}

View File

@ -0,0 +1,43 @@
#pragma once
#include <ajantv2/includes/ntv2enums.h>
#include <ajantv2/includes/ntv2vpid.h>
/*
* Wrapper class for handling SMPTE 352M Video Payload ID (VPID) data
* Each SDI data stream contains two 32-bit VPID bitfields, representing
* characteristics about the video streams on the SDI wire. AJA and other SDI
* devices may use VPID to help determine what kind of video data is being
* conveyed by the incoming/outgoing streams.
*/
class VPIDData {
public:
VPIDData();
VPIDData(ULWord vpidA, ULWord vpidB);
VPIDData(const VPIDData &other);
VPIDData(VPIDData &&other);
~VPIDData() = default;
VPIDData &operator=(const VPIDData &other);
VPIDData &operator=(VPIDData &&other);
bool operator==(const VPIDData &rhs) const;
bool operator!=(const VPIDData &rhs) const;
void SetA(ULWord vpidA);
void SetB(ULWord vpidB);
void Parse();
bool IsRGB() const;
VPIDStandard Standard() const;
VPIDSampling Sampling() const;
private:
ULWord mVpidA;
ULWord mVpidB;
VPIDStandard mStandardA;
VPIDSampling mSamplingA;
VPIDStandard mStandardB;
VPIDSampling mSamplingB;
};
using VPIDDataList = std::vector<VPIDData>;

View File

@ -1,6 +1,7 @@
#include "aja-widget-io.hpp"
#include <ajantv2/includes/ntv2utils.h>
#include <ajantv2/includes/ntv2signalrouter.h>
#include <iostream>
@ -31,312 +32,312 @@ static const char *kOENickname = "oe";
// Table of firmware widget's input crosspoint/id/channel/name/datastream index
// clang-format off
static const WidgetInputSocket kWidgetInputSockets[] = {
//NTV2InputCrosspointID | NTV2WidgetID | NTV2Channel | Name | DatastreamIndex
{ NTV2_INPUT_CROSSPOINT_INVALID, NTV2_WIDGET_INVALID, NTV2_CHANNEL_INVALID, "", -1},
{ NTV2_XptFrameBuffer1Input, NTV2_WgtFrameBuffer1, NTV2_CHANNEL1, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer1BInput, NTV2_WgtFrameBuffer1, NTV2_CHANNEL1, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer2Input, NTV2_WgtFrameBuffer2, NTV2_CHANNEL2, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer2BInput, NTV2_WgtFrameBuffer2, NTV2_CHANNEL2, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer3Input, NTV2_WgtFrameBuffer3, NTV2_CHANNEL3, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer3BInput, NTV2_WgtFrameBuffer3, NTV2_CHANNEL3, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer4Input, NTV2_WgtFrameBuffer4, NTV2_CHANNEL4, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer4BInput, NTV2_WgtFrameBuffer4, NTV2_CHANNEL4, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer5Input, NTV2_WgtFrameBuffer5, NTV2_CHANNEL5, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer5BInput, NTV2_WgtFrameBuffer5, NTV2_CHANNEL5, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer6Input, NTV2_WgtFrameBuffer6, NTV2_CHANNEL6, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer6BInput, NTV2_WgtFrameBuffer6, NTV2_CHANNEL6, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer7Input, NTV2_WgtFrameBuffer7, NTV2_CHANNEL7, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer7BInput, NTV2_WgtFrameBuffer7, NTV2_CHANNEL7, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer8Input, NTV2_WgtFrameBuffer8, NTV2_CHANNEL8, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer8BInput, NTV2_WgtFrameBuffer8, NTV2_CHANNEL8, kFramebufferNickname, 1},
{ NTV2_XptCSC1VidInput, NTV2_WgtCSC1, NTV2_CHANNEL1, kCSCNickname, 0},
{ NTV2_XptCSC1KeyInput, NTV2_WgtCSC1, NTV2_CHANNEL1, kCSCNickname, 1},
{ NTV2_XptCSC2VidInput, NTV2_WgtCSC2, NTV2_CHANNEL2, kCSCNickname, 0},
{ NTV2_XptCSC2KeyInput, NTV2_WgtCSC2, NTV2_CHANNEL2, kCSCNickname, 1},
{ NTV2_XptCSC3VidInput, NTV2_WgtCSC3, NTV2_CHANNEL3, kCSCNickname, 0},
{ NTV2_XptCSC3KeyInput, NTV2_WgtCSC3, NTV2_CHANNEL3, kCSCNickname, 1},
{ NTV2_XptCSC4VidInput, NTV2_WgtCSC4, NTV2_CHANNEL4, kCSCNickname, 0},
{ NTV2_XptCSC4KeyInput, NTV2_WgtCSC4, NTV2_CHANNEL4, kCSCNickname, 1},
{ NTV2_XptCSC5VidInput, NTV2_WgtCSC5, NTV2_CHANNEL5, kCSCNickname, 0},
{ NTV2_XptCSC5KeyInput, NTV2_WgtCSC5, NTV2_CHANNEL5, kCSCNickname, 1},
{ NTV2_XptCSC6VidInput, NTV2_WgtCSC6, NTV2_CHANNEL6, kCSCNickname, 0},
{ NTV2_XptCSC6KeyInput, NTV2_WgtCSC6, NTV2_CHANNEL6, kCSCNickname, 1},
{ NTV2_XptCSC7VidInput, NTV2_WgtCSC7, NTV2_CHANNEL7, kCSCNickname, 0},
{ NTV2_XptCSC7KeyInput, NTV2_WgtCSC7, NTV2_CHANNEL7, kCSCNickname, 1},
{ NTV2_XptCSC8VidInput, NTV2_WgtCSC8, NTV2_CHANNEL8, kCSCNickname, 0},
{ NTV2_XptCSC8KeyInput, NTV2_WgtCSC8, NTV2_CHANNEL8, kCSCNickname, 1},
{ NTV2_XptLUT1Input, NTV2_WgtLUT1, NTV2_CHANNEL1, kLUTNickname, 0},
{ NTV2_XptLUT2Input, NTV2_WgtLUT2, NTV2_CHANNEL2, kLUTNickname, 0},
{ NTV2_XptLUT3Input, NTV2_WgtLUT3, NTV2_CHANNEL3, kLUTNickname, 0},
{ NTV2_XptLUT4Input, NTV2_WgtLUT4, NTV2_CHANNEL4, kLUTNickname, 0},
{ NTV2_XptLUT5Input, NTV2_WgtLUT5, NTV2_CHANNEL5, kLUTNickname, 0},
{ NTV2_XptLUT6Input, NTV2_WgtLUT6, NTV2_CHANNEL6, kLUTNickname, 0},
{ NTV2_XptLUT7Input, NTV2_WgtLUT7, NTV2_CHANNEL7, kLUTNickname, 0},
{ NTV2_XptLUT8Input, NTV2_WgtLUT8, NTV2_CHANNEL8, kLUTNickname, 0},
{ NTV2_XptMultiLinkOut1Input, NTV2_WgtMultiLinkOut1, NTV2_CHANNEL1, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut1InputDS2, NTV2_WgtMultiLinkOut1, NTV2_CHANNEL1, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut2Input, NTV2_WgtMultiLinkOut2, NTV2_CHANNEL1, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut2InputDS2, NTV2_WgtMultiLinkOut2, NTV2_CHANNEL1, kMultiLinkNickname, 0},
{ NTV2_XptSDIOut1Input, NTV2_WgtSDIOut1, NTV2_CHANNEL1, kSDINickname, 0},
{ NTV2_XptSDIOut1InputDS2, NTV2_Wgt3GSDIOut1, NTV2_CHANNEL1, kSDINickname, 1},
{ NTV2_XptSDIOut2Input, NTV2_WgtSDIOut2, NTV2_CHANNEL2, kSDINickname, 0},
{ NTV2_XptSDIOut2InputDS2, NTV2_Wgt3GSDIOut2, NTV2_CHANNEL2, kSDINickname, 1},
{ NTV2_XptSDIOut3Input, NTV2_WgtSDIOut3, NTV2_CHANNEL3, kSDINickname, 0},
{ NTV2_XptSDIOut3InputDS2, NTV2_Wgt3GSDIOut3, NTV2_CHANNEL3, kSDINickname, 1},
{ NTV2_XptSDIOut4Input, NTV2_WgtSDIOut4, NTV2_CHANNEL4, kSDINickname, 0},
{ NTV2_XptSDIOut4InputDS2, NTV2_Wgt3GSDIOut4, NTV2_CHANNEL4, kSDINickname, 1},
{ NTV2_XptSDIOut5Input, NTV2_WgtSDIMonOut1, NTV2_CHANNEL5, kSDINickname, 0},
{ NTV2_XptSDIOut5InputDS2, NTV2_WgtSDIMonOut1, NTV2_CHANNEL5, kSDINickname, 1},
{ NTV2_XptSDIOut6Input, NTV2_Wgt3GSDIOut6, NTV2_CHANNEL6, kSDINickname, 0},
{ NTV2_XptSDIOut6InputDS2, NTV2_Wgt3GSDIOut6, NTV2_CHANNEL6, kSDINickname, 1},
{ NTV2_XptSDIOut7Input, NTV2_Wgt3GSDIOut7, NTV2_CHANNEL7, kSDINickname, 0},
{ NTV2_XptSDIOut7InputDS2, NTV2_Wgt3GSDIOut7, NTV2_CHANNEL7, kSDINickname, 1},
{ NTV2_XptSDIOut8Input, NTV2_Wgt3GSDIOut8, NTV2_CHANNEL8, kSDINickname, 0},
{ NTV2_XptSDIOut8InputDS2, NTV2_Wgt3GSDIOut8, NTV2_CHANNEL8, kSDINickname, 1},
{ NTV2_XptDualLinkIn1Input, NTV2_WgtDualLinkV2In1, NTV2_CHANNEL1, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn1DSInput, NTV2_WgtDualLinkV2In1, NTV2_CHANNEL1, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn2Input, NTV2_WgtDualLinkV2In2, NTV2_CHANNEL2, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn2DSInput, NTV2_WgtDualLinkV2In2, NTV2_CHANNEL2, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn3Input, NTV2_WgtDualLinkV2In3, NTV2_CHANNEL3, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn3DSInput, NTV2_WgtDualLinkV2In3, NTV2_CHANNEL3, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn4Input, NTV2_WgtDualLinkV2In4, NTV2_CHANNEL4, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn4DSInput, NTV2_WgtDualLinkV2In4, NTV2_CHANNEL4, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn5Input, NTV2_WgtDualLinkV2In5, NTV2_CHANNEL5, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn5DSInput, NTV2_WgtDualLinkV2In5, NTV2_CHANNEL5, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn6Input, NTV2_WgtDualLinkV2In6, NTV2_CHANNEL6, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn6DSInput, NTV2_WgtDualLinkV2In6, NTV2_CHANNEL6, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn7Input, NTV2_WgtDualLinkV2In7, NTV2_CHANNEL7, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn7DSInput, NTV2_WgtDualLinkV2In7, NTV2_CHANNEL7, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn8Input, NTV2_WgtDualLinkV2In8, NTV2_CHANNEL8, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn8DSInput, NTV2_WgtDualLinkV2In8, NTV2_CHANNEL8, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkOut1Input, NTV2_WgtDualLinkV2Out1, NTV2_CHANNEL1, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut2Input, NTV2_WgtDualLinkV2Out2, NTV2_CHANNEL2, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut3Input, NTV2_WgtDualLinkV2Out3, NTV2_CHANNEL3, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut4Input, NTV2_WgtDualLinkV2Out4, NTV2_CHANNEL4, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut5Input, NTV2_WgtDualLinkV2Out5, NTV2_CHANNEL5, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut6Input, NTV2_WgtDualLinkV2Out6, NTV2_CHANNEL6, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut7Input, NTV2_WgtDualLinkV2Out7, NTV2_CHANNEL7, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut8Input, NTV2_WgtDualLinkV2Out8, NTV2_CHANNEL8, kDualLinkOutNickname, 0},
{ NTV2_XptMixer1BGKeyInput, NTV2_WgtMixer1, NTV2_CHANNEL1, kMixerNickname, 3},
{ NTV2_XptMixer1BGVidInput, NTV2_WgtMixer1, NTV2_CHANNEL1, kMixerNickname, 2},
{ NTV2_XptMixer1FGKeyInput, NTV2_WgtMixer1, NTV2_CHANNEL1, kMixerNickname, 1},
{ NTV2_XptMixer1FGVidInput, NTV2_WgtMixer1, NTV2_CHANNEL1, kMixerNickname, 0},
{ NTV2_XptMixer2BGKeyInput, NTV2_WgtMixer2, NTV2_CHANNEL2, kMixerNickname, 3},
{ NTV2_XptMixer2BGVidInput, NTV2_WgtMixer2, NTV2_CHANNEL2, kMixerNickname, 2},
{ NTV2_XptMixer2FGKeyInput, NTV2_WgtMixer2, NTV2_CHANNEL2, kMixerNickname, 1},
{ NTV2_XptMixer2FGVidInput, NTV2_WgtMixer2, NTV2_CHANNEL2, kMixerNickname, 0},
{ NTV2_XptMixer3BGKeyInput, NTV2_WgtMixer3, NTV2_CHANNEL3, kMixerNickname, 3},
{ NTV2_XptMixer3BGVidInput, NTV2_WgtMixer3, NTV2_CHANNEL3, kMixerNickname, 2},
{ NTV2_XptMixer3FGKeyInput, NTV2_WgtMixer3, NTV2_CHANNEL3, kMixerNickname, 1},
{ NTV2_XptMixer3FGVidInput, NTV2_WgtMixer3, NTV2_CHANNEL3, kMixerNickname, 0},
{ NTV2_XptMixer4BGKeyInput, NTV2_WgtMixer4, NTV2_CHANNEL4, kMixerNickname, 3},
{ NTV2_XptMixer4BGVidInput, NTV2_WgtMixer4, NTV2_CHANNEL4, kMixerNickname, 2},
{ NTV2_XptMixer4FGKeyInput, NTV2_WgtMixer4, NTV2_CHANNEL4, kMixerNickname, 1},
{ NTV2_XptMixer4FGVidInput, NTV2_WgtMixer4, NTV2_CHANNEL4, kMixerNickname, 0},
{ NTV2_XptHDMIOutInput, NTV2_WgtHDMIOut1, NTV2_CHANNEL1, kHDMINickname, 0},
{ NTV2_XptHDMIOutQ2Input, NTV2_WgtHDMIOut1v2, NTV2_CHANNEL1, kHDMINickname, 1},
{ NTV2_XptHDMIOutQ3Input, NTV2_WgtHDMIOut1v2, NTV2_CHANNEL1, kHDMINickname, 2},
{ NTV2_XptHDMIOutQ4Input, NTV2_WgtHDMIOut1v2, NTV2_CHANNEL1, kHDMINickname, 3},
{ NTV2_Xpt4KDCQ1Input, NTV2_Wgt4KDownConverter, NTV2_CHANNEL1, k4KDownConvertNickname, 0},
{ NTV2_Xpt4KDCQ2Input, NTV2_Wgt4KDownConverter, NTV2_CHANNEL2, k4KDownConvertNickname, 0},
{ NTV2_Xpt4KDCQ3Input, NTV2_Wgt4KDownConverter, NTV2_CHANNEL3, k4KDownConvertNickname, 0},
{ NTV2_Xpt4KDCQ4Input, NTV2_Wgt4KDownConverter, NTV2_CHANNEL4, k4KDownConvertNickname, 0},
{ NTV2_Xpt425Mux1AInput, NTV2_Wgt425Mux1, NTV2_CHANNEL1, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux1BInput, NTV2_Wgt425Mux1, NTV2_CHANNEL1, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux2AInput, NTV2_Wgt425Mux2, NTV2_CHANNEL2, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux2BInput, NTV2_Wgt425Mux2, NTV2_CHANNEL2, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux3AInput, NTV2_Wgt425Mux3, NTV2_CHANNEL3, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux3BInput, NTV2_Wgt425Mux3, NTV2_CHANNEL3, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux4AInput, NTV2_Wgt425Mux4, NTV2_CHANNEL4, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux4BInput, NTV2_Wgt425Mux4, NTV2_CHANNEL4, kTSIMuxNickname, 1},
{ NTV2_XptAnalogOutInput, NTV2_WgtAnalogOut1, NTV2_CHANNEL1, kAnalogNickname, 0},
{ NTV2_Xpt3DLUT1Input, NTV2_Wgt3DLUT1, NTV2_CHANNEL1, kLUT3DNickname, 0},
{ NTV2_XptAnalogOutCompositeOut, NTV2_WgtAnalogCompositeOut1, NTV2_CHANNEL1, kCompositeNickname, 0},
{ NTV2_XptStereoLeftInput, NTV2_WgtStereoCompressor, NTV2_CHANNEL1, kStereoCompNickname, 0},
{ NTV2_XptStereoRightInput, NTV2_WgtStereoCompressor, NTV2_CHANNEL1, kStereoCompNickname, 0},
{ NTV2_XptWaterMarker1Input, NTV2_WgtWaterMarker1, NTV2_CHANNEL1, kWatermarkNickname, 0},
{ NTV2_XptWaterMarker2Input, NTV2_WgtWaterMarker2, NTV2_CHANNEL2, kWatermarkNickname, 0},
{ NTV2_XptConversionMod2Input, NTV2_WgtUpDownConverter2, NTV2_CHANNEL2, kUpDownConvertNickname, 0},
{ NTV2_XptCompressionModInput, NTV2_WgtCompression1, NTV2_CHANNEL1, kCompressionNickname, 0},
{ NTV2_XptConversionModInput, NTV2_WgtUpDownConverter1, NTV2_CHANNEL1, kUpDownConvertNickname, 0},
{ NTV2_XptFrameSync2Input, NTV2_WgtFrameSync2, NTV2_CHANNEL2, kFrameSyncNickname, 0},
//NTV2InputCrosspointID | NTV2WidgetID | Name | DatastreamIndex
{ NTV2_INPUT_CROSSPOINT_INVALID, NTV2_WIDGET_INVALID, "", -1},
{ NTV2_XptFrameBuffer1Input, NTV2_WgtFrameBuffer1, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer1BInput, NTV2_WgtFrameBuffer1, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer2Input, NTV2_WgtFrameBuffer2, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer2BInput, NTV2_WgtFrameBuffer2, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer3Input, NTV2_WgtFrameBuffer3, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer3BInput, NTV2_WgtFrameBuffer3, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer4Input, NTV2_WgtFrameBuffer4, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer4BInput, NTV2_WgtFrameBuffer4, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer5Input, NTV2_WgtFrameBuffer5, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer5BInput, NTV2_WgtFrameBuffer5, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer6Input, NTV2_WgtFrameBuffer6, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer6BInput, NTV2_WgtFrameBuffer6, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer7Input, NTV2_WgtFrameBuffer7, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer7BInput, NTV2_WgtFrameBuffer7, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer8Input, NTV2_WgtFrameBuffer8, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer8BInput, NTV2_WgtFrameBuffer8, kFramebufferNickname, 1},
{ NTV2_XptCSC1VidInput, NTV2_WgtCSC1, kCSCNickname, 0},
{ NTV2_XptCSC1KeyInput, NTV2_WgtCSC1, kCSCNickname, 1},
{ NTV2_XptCSC2VidInput, NTV2_WgtCSC2, kCSCNickname, 0},
{ NTV2_XptCSC2KeyInput, NTV2_WgtCSC2, kCSCNickname, 1},
{ NTV2_XptCSC3VidInput, NTV2_WgtCSC3, kCSCNickname, 0},
{ NTV2_XptCSC3KeyInput, NTV2_WgtCSC3, kCSCNickname, 1},
{ NTV2_XptCSC4VidInput, NTV2_WgtCSC4, kCSCNickname, 0},
{ NTV2_XptCSC4KeyInput, NTV2_WgtCSC4, kCSCNickname, 1},
{ NTV2_XptCSC5VidInput, NTV2_WgtCSC5, kCSCNickname, 0},
{ NTV2_XptCSC5KeyInput, NTV2_WgtCSC5, kCSCNickname, 1},
{ NTV2_XptCSC6VidInput, NTV2_WgtCSC6, kCSCNickname, 0},
{ NTV2_XptCSC6KeyInput, NTV2_WgtCSC6, kCSCNickname, 1},
{ NTV2_XptCSC7VidInput, NTV2_WgtCSC7, kCSCNickname, 0},
{ NTV2_XptCSC7KeyInput, NTV2_WgtCSC7, kCSCNickname, 1},
{ NTV2_XptCSC8VidInput, NTV2_WgtCSC8, kCSCNickname, 0},
{ NTV2_XptCSC8KeyInput, NTV2_WgtCSC8, kCSCNickname, 1},
{ NTV2_XptLUT1Input, NTV2_WgtLUT1, kLUTNickname, 0},
{ NTV2_XptLUT2Input, NTV2_WgtLUT2, kLUTNickname, 0},
{ NTV2_XptLUT3Input, NTV2_WgtLUT3, kLUTNickname, 0},
{ NTV2_XptLUT4Input, NTV2_WgtLUT4, kLUTNickname, 0},
{ NTV2_XptLUT5Input, NTV2_WgtLUT5, kLUTNickname, 0},
{ NTV2_XptLUT6Input, NTV2_WgtLUT6, kLUTNickname, 0},
{ NTV2_XptLUT7Input, NTV2_WgtLUT7, kLUTNickname, 0},
{ NTV2_XptLUT8Input, NTV2_WgtLUT8, kLUTNickname, 0},
{ NTV2_XptMultiLinkOut1Input, NTV2_WgtMultiLinkOut1, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut1InputDS2, NTV2_WgtMultiLinkOut1, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut2Input, NTV2_WgtMultiLinkOut2, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut2InputDS2, NTV2_WgtMultiLinkOut2, kMultiLinkNickname, 0},
{ NTV2_XptSDIOut1Input, NTV2_WgtSDIOut1, kSDINickname, 0},
{ NTV2_XptSDIOut1InputDS2, NTV2_Wgt3GSDIOut1, kSDINickname, 1},
{ NTV2_XptSDIOut2Input, NTV2_WgtSDIOut2, kSDINickname, 0},
{ NTV2_XptSDIOut2InputDS2, NTV2_Wgt3GSDIOut2, kSDINickname, 1},
{ NTV2_XptSDIOut3Input, NTV2_WgtSDIOut3, kSDINickname, 0},
{ NTV2_XptSDIOut3InputDS2, NTV2_Wgt3GSDIOut3, kSDINickname, 1},
{ NTV2_XptSDIOut4Input, NTV2_WgtSDIOut4, kSDINickname, 0},
{ NTV2_XptSDIOut4InputDS2, NTV2_Wgt3GSDIOut4, kSDINickname, 1},
{ NTV2_XptSDIOut5Input, NTV2_WgtSDIMonOut1, kSDINickname, 0},
{ NTV2_XptSDIOut5InputDS2, NTV2_WgtSDIMonOut1, kSDINickname, 1},
{ NTV2_XptSDIOut6Input, NTV2_Wgt3GSDIOut6, kSDINickname, 0},
{ NTV2_XptSDIOut6InputDS2, NTV2_Wgt3GSDIOut6, kSDINickname, 1},
{ NTV2_XptSDIOut7Input, NTV2_Wgt3GSDIOut7, kSDINickname, 0},
{ NTV2_XptSDIOut7InputDS2, NTV2_Wgt3GSDIOut7, kSDINickname, 1},
{ NTV2_XptSDIOut8Input, NTV2_Wgt3GSDIOut8, kSDINickname, 0},
{ NTV2_XptSDIOut8InputDS2, NTV2_Wgt3GSDIOut8, kSDINickname, 1},
{ NTV2_XptDualLinkIn1Input, NTV2_WgtDualLinkV2In1, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn1DSInput, NTV2_WgtDualLinkV2In1, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn2Input, NTV2_WgtDualLinkV2In2, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn2DSInput, NTV2_WgtDualLinkV2In2, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn3Input, NTV2_WgtDualLinkV2In3, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn3DSInput, NTV2_WgtDualLinkV2In3, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn4Input, NTV2_WgtDualLinkV2In4, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn4DSInput, NTV2_WgtDualLinkV2In4, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn5Input, NTV2_WgtDualLinkV2In5, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn5DSInput, NTV2_WgtDualLinkV2In5, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn6Input, NTV2_WgtDualLinkV2In6, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn6DSInput, NTV2_WgtDualLinkV2In6, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn7Input, NTV2_WgtDualLinkV2In7, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn7DSInput, NTV2_WgtDualLinkV2In7, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkIn8Input, NTV2_WgtDualLinkV2In8, kDualLinkInNickname, 0},
{ NTV2_XptDualLinkIn8DSInput, NTV2_WgtDualLinkV2In8, kDualLinkInNickname, 1},
{ NTV2_XptDualLinkOut1Input, NTV2_WgtDualLinkV2Out1, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut2Input, NTV2_WgtDualLinkV2Out2, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut3Input, NTV2_WgtDualLinkV2Out3, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut4Input, NTV2_WgtDualLinkV2Out4, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut5Input, NTV2_WgtDualLinkV2Out5, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut6Input, NTV2_WgtDualLinkV2Out6, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut7Input, NTV2_WgtDualLinkV2Out7, kDualLinkOutNickname, 0},
{ NTV2_XptDualLinkOut8Input, NTV2_WgtDualLinkV2Out8, kDualLinkOutNickname, 0},
{ NTV2_XptMixer1BGKeyInput, NTV2_WgtMixer1, kMixerNickname, 3},
{ NTV2_XptMixer1BGVidInput, NTV2_WgtMixer1, kMixerNickname, 2},
{ NTV2_XptMixer1FGKeyInput, NTV2_WgtMixer1, kMixerNickname, 1},
{ NTV2_XptMixer1FGVidInput, NTV2_WgtMixer1, kMixerNickname, 0},
{ NTV2_XptMixer2BGKeyInput, NTV2_WgtMixer2, kMixerNickname, 3},
{ NTV2_XptMixer2BGVidInput, NTV2_WgtMixer2, kMixerNickname, 2},
{ NTV2_XptMixer2FGKeyInput, NTV2_WgtMixer2, kMixerNickname, 1},
{ NTV2_XptMixer2FGVidInput, NTV2_WgtMixer2, kMixerNickname, 0},
{ NTV2_XptMixer3BGKeyInput, NTV2_WgtMixer3, kMixerNickname, 3},
{ NTV2_XptMixer3BGVidInput, NTV2_WgtMixer3, kMixerNickname, 2},
{ NTV2_XptMixer3FGKeyInput, NTV2_WgtMixer3, kMixerNickname, 1},
{ NTV2_XptMixer3FGVidInput, NTV2_WgtMixer3, kMixerNickname, 0},
{ NTV2_XptMixer4BGKeyInput, NTV2_WgtMixer4, kMixerNickname, 3},
{ NTV2_XptMixer4BGVidInput, NTV2_WgtMixer4, kMixerNickname, 2},
{ NTV2_XptMixer4FGKeyInput, NTV2_WgtMixer4, kMixerNickname, 1},
{ NTV2_XptMixer4FGVidInput, NTV2_WgtMixer4, kMixerNickname, 0},
{ NTV2_XptHDMIOutInput, NTV2_WgtHDMIOut1, kHDMINickname, 0},
{ NTV2_XptHDMIOutQ2Input, NTV2_WgtHDMIOut1v2, kHDMINickname, 1},
{ NTV2_XptHDMIOutQ3Input, NTV2_WgtHDMIOut1v2, kHDMINickname, 2},
{ NTV2_XptHDMIOutQ4Input, NTV2_WgtHDMIOut1v2, kHDMINickname, 3},
{ NTV2_Xpt4KDCQ1Input, NTV2_Wgt4KDownConverter, k4KDownConvertNickname, 0},
{ NTV2_Xpt4KDCQ2Input, NTV2_Wgt4KDownConverter, k4KDownConvertNickname, 0},
{ NTV2_Xpt4KDCQ3Input, NTV2_Wgt4KDownConverter, k4KDownConvertNickname, 0},
{ NTV2_Xpt4KDCQ4Input, NTV2_Wgt4KDownConverter, k4KDownConvertNickname, 0},
{ NTV2_Xpt425Mux1AInput, NTV2_Wgt425Mux1, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux1BInput, NTV2_Wgt425Mux1, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux2AInput, NTV2_Wgt425Mux2, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux2BInput, NTV2_Wgt425Mux2, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux3AInput, NTV2_Wgt425Mux3, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux3BInput, NTV2_Wgt425Mux3, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux4AInput, NTV2_Wgt425Mux4, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux4BInput, NTV2_Wgt425Mux4, kTSIMuxNickname, 1},
{ NTV2_XptAnalogOutInput, NTV2_WgtAnalogOut1, kAnalogNickname, 0},
{ NTV2_Xpt3DLUT1Input, NTV2_Wgt3DLUT1, kLUT3DNickname, 0},
{ NTV2_XptAnalogOutCompositeOut, NTV2_WgtAnalogCompositeOut1, kCompositeNickname, 0},
{ NTV2_XptStereoLeftInput, NTV2_WgtStereoCompressor, kStereoCompNickname, 0},
{ NTV2_XptStereoRightInput, NTV2_WgtStereoCompressor, kStereoCompNickname, 0},
{ NTV2_XptWaterMarker1Input, NTV2_WgtWaterMarker1, kWatermarkNickname, 0},
{ NTV2_XptWaterMarker2Input, NTV2_WgtWaterMarker2, kWatermarkNickname, 0},
{ NTV2_XptConversionMod2Input, NTV2_WgtUpDownConverter2, kUpDownConvertNickname, 0},
{ NTV2_XptCompressionModInput, NTV2_WgtCompression1, kCompressionNickname, 0},
{ NTV2_XptConversionModInput, NTV2_WgtUpDownConverter1, kUpDownConvertNickname, 0},
{ NTV2_XptFrameSync2Input, NTV2_WgtFrameSync2, kFrameSyncNickname, 0},
};
// Table of firmware widget's output crosspoint/id/channel/name/datastream index
static WidgetOutputSocket kWidgetOutputSockets[] = {
{ NTV2_OUTPUT_CROSSPOINT_INVALID, NTV2_WIDGET_INVALID, NTV2_CHANNEL_INVALID, "", -1},
{ NTV2_XptBlack, NTV2_WgtUndefined, NTV2_CHANNEL1, kBlackNickname, 0},
{ NTV2_XptSDIIn1, NTV2_WgtSDIIn1, NTV2_CHANNEL1, kSDINickname, 0},
{ NTV2_XptSDIIn2, NTV2_WgtSDIIn2, NTV2_CHANNEL2, kSDINickname, 0},
{ NTV2_XptLUT1YUV, NTV2_WgtLUT1, NTV2_CHANNEL1, kSDINickname, 0},
{ NTV2_XptCSC1VidYUV, NTV2_WgtCSC1, NTV2_CHANNEL1, kCSCNickname, 0},
{ NTV2_XptConversionModule, NTV2_WgtUpDownConverter1, NTV2_CHANNEL1, kUpDownConvertNickname, 0},
{ NTV2_XptCompressionModule, NTV2_WgtCompression1, NTV2_CHANNEL1, kCompressionNickname, 0},
{ NTV2_XptFrameBuffer1YUV, NTV2_WgtFrameBuffer1, NTV2_CHANNEL1, kFramebufferNickname, 0},
{ NTV2_XptFrameSync1YUV, NTV2_WgtFrameSync1, NTV2_CHANNEL1, kFrameSyncNickname, 0},
{ NTV2_XptFrameSync2YUV, NTV2_WgtFrameSync2, NTV2_CHANNEL2, kFrameSyncNickname, 0},
{ NTV2_XptDuallinkOut1, NTV2_WgtDualLinkV2Out1, NTV2_CHANNEL1, kDualLinkOutNickname, 0},
{ NTV2_XptCSC1KeyYUV, NTV2_WgtCSC1, NTV2_CHANNEL1, kCSCNickname, 2},
{ NTV2_XptFrameBuffer2YUV, NTV2_WgtFrameBuffer2, NTV2_CHANNEL2, kFramebufferNickname, 0},
{ NTV2_XptCSC2VidYUV, NTV2_WgtCSC2, NTV2_CHANNEL2, kCSCNickname, 0},
{ NTV2_XptCSC2KeyYUV, NTV2_WgtCSC2, NTV2_CHANNEL2, kCSCNickname, 2},
{ NTV2_XptMixer1VidYUV, NTV2_WgtMixer1, NTV2_CHANNEL1, kMixerNickname, 0},
{ NTV2_XptMixer1KeyYUV, NTV2_WgtMixer1, NTV2_CHANNEL1, kMixerNickname, 1},
{ NTV2_XptMultiLinkOut1DS1, NTV2_WgtMultiLinkOut1, NTV2_CHANNEL1, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut1DS2, NTV2_WgtMultiLinkOut1, NTV2_CHANNEL1, kMultiLinkNickname, 1},
{ NTV2_XptAnalogIn, NTV2_WgtAnalogIn1, NTV2_CHANNEL1, kAnalogNickname, 0},
{ NTV2_XptHDMIIn1, NTV2_WgtHDMIIn1, NTV2_CHANNEL1, kHDMINickname, 0},
{ NTV2_XptMultiLinkOut1DS3, NTV2_WgtMultiLinkOut1, NTV2_CHANNEL1, kMultiLinkNickname, 2},
{ NTV2_XptMultiLinkOut1DS4, NTV2_WgtMultiLinkOut1, NTV2_CHANNEL1, kMultiLinkNickname, 3},
{ NTV2_XptMultiLinkOut2DS1, NTV2_WgtMultiLinkOut2, NTV2_CHANNEL2, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut2DS2, NTV2_WgtMultiLinkOut2, NTV2_CHANNEL2, kMultiLinkNickname, 1},
{ NTV2_XptDuallinkOut2, NTV2_WgtDualLinkV2Out2, NTV2_CHANNEL2, kDualLinkOutNickname, 0},
{ NTV2_XptTestPatternYUV, NTV2_WgtTestPattern1, NTV2_CHANNEL1, kTestPatternNickname, 0},
{ NTV2_XptSDIIn1DS2, NTV2_Wgt3GSDIIn1, NTV2_CHANNEL1, kSDINickname, 1},
{ NTV2_XptSDIIn2DS2, NTV2_Wgt3GSDIIn2, NTV2_CHANNEL2, kSDINickname, 1},
{ NTV2_XptMixer2VidYUV, NTV2_WgtMixer2, NTV2_CHANNEL2, kMixerNickname, 0},
{ NTV2_XptMixer2KeyYUV, NTV2_WgtMixer2, NTV2_CHANNEL2, kMixerNickname, 1},
{ NTV2_XptStereoCompressorOut, NTV2_WgtStereoCompressor, NTV2_CHANNEL1, kStereoCompNickname, 0},
{ NTV2_XptFrameBuffer3YUV, NTV2_WgtFrameBuffer3, NTV2_CHANNEL3, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer4YUV, NTV2_WgtFrameBuffer4, NTV2_CHANNEL4, kFramebufferNickname, 0},
{ NTV2_XptDuallinkOut1DS2, NTV2_WgtDualLinkV2Out1, NTV2_CHANNEL1, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut2DS2, NTV2_WgtDualLinkV2Out2, NTV2_CHANNEL2, kDualLinkOutNickname, 1},
{ NTV2_XptCSC5VidYUV, NTV2_WgtCSC5, NTV2_CHANNEL5, kCSCNickname, 0},
{ NTV2_XptCSC5KeyYUV, NTV2_WgtCSC5, NTV2_CHANNEL5, kCSCNickname, 1},
{ NTV2_XptMultiLinkOut2DS3, NTV2_WgtMultiLinkOut2, NTV2_CHANNEL2, kMultiLinkNickname, 2},
{ NTV2_XptMultiLinkOut2DS4, NTV2_WgtMultiLinkOut2, NTV2_CHANNEL2, kMultiLinkNickname, 3},
{ NTV2_XptSDIIn3, NTV2_Wgt3GSDIIn3, NTV2_CHANNEL3, kSDINickname, 0},
{ NTV2_XptSDIIn4, NTV2_Wgt3GSDIIn4, NTV2_CHANNEL4, kSDINickname, 0},
{ NTV2_XptSDIIn3DS2, NTV2_Wgt3GSDIIn3, NTV2_CHANNEL3, kSDINickname, 1},
{ NTV2_XptSDIIn4DS2, NTV2_Wgt3GSDIIn4, NTV2_CHANNEL4, kSDINickname, 1},
{ NTV2_XptDuallinkOut3, NTV2_WgtDualLinkV2Out3, NTV2_CHANNEL3, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut3DS2, NTV2_WgtDualLinkV2Out3, NTV2_CHANNEL3, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut4, NTV2_WgtDualLinkV2Out4, NTV2_CHANNEL4, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut4DS2, NTV2_WgtDualLinkV2Out4, NTV2_CHANNEL4, kDualLinkOutNickname, 1},
{ NTV2_XptCSC3VidYUV, NTV2_WgtCSC3, NTV2_CHANNEL3, kCSCNickname, 0},
{ NTV2_XptCSC3KeyYUV, NTV2_WgtCSC3, NTV2_CHANNEL3, kCSCNickname, 2},
{ NTV2_XptCSC4VidYUV, NTV2_WgtCSC4, NTV2_CHANNEL4, kCSCNickname, 0},
{ NTV2_XptCSC4KeyYUV, NTV2_WgtCSC4, NTV2_CHANNEL4, kCSCNickname, 2},
{ NTV2_XptDuallinkOut5, NTV2_WgtDualLinkV2Out5, NTV2_CHANNEL5, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut5DS2, NTV2_WgtDualLinkV2Out5, NTV2_CHANNEL5, kDualLinkOutNickname, 1},
{ NTV2_Xpt3DLUT1YUV, NTV2_Wgt3DLUT1, NTV2_CHANNEL1, kLUT3DNickname, 0},
{ NTV2_XptHDMIIn1Q2, NTV2_WgtHDMIIn1v3, NTV2_CHANNEL1, kHDMINickname, 1},
{ NTV2_XptHDMIIn1Q3, NTV2_WgtHDMIIn1v3, NTV2_CHANNEL1, kHDMINickname, 2},
{ NTV2_XptHDMIIn1Q4, NTV2_WgtHDMIIn1v3, NTV2_CHANNEL1, kHDMINickname, 3},
{ NTV2_Xpt4KDownConverterOut, NTV2_Wgt4KDownConverter, NTV2_CHANNEL1, k4KDownConvertNickname, 0},
{ NTV2_XptSDIIn5, NTV2_Wgt3GSDIIn5, NTV2_CHANNEL5, kSDINickname, 0},
{ NTV2_XptSDIIn6, NTV2_Wgt3GSDIIn6, NTV2_CHANNEL6, kSDINickname, 0},
{ NTV2_XptSDIIn5DS2, NTV2_Wgt3GSDIIn5, NTV2_CHANNEL5, kSDINickname, 1},
{ NTV2_XptSDIIn6DS2, NTV2_Wgt3GSDIIn6, NTV2_CHANNEL6, kSDINickname, 1},
{ NTV2_XptSDIIn7, NTV2_Wgt3GSDIIn7, NTV2_CHANNEL7, kSDINickname, 0},
{ NTV2_XptSDIIn8, NTV2_Wgt3GSDIIn8, NTV2_CHANNEL8, kSDINickname, 0},
{ NTV2_XptSDIIn7DS2, NTV2_Wgt3GSDIIn7, NTV2_CHANNEL7, kSDINickname, 1},
{ NTV2_XptSDIIn8DS2, NTV2_Wgt3GSDIIn8, NTV2_CHANNEL8, kSDINickname, 1},
{ NTV2_XptFrameBuffer5YUV, NTV2_WgtFrameBuffer5, NTV2_CHANNEL5, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer6YUV, NTV2_WgtFrameBuffer6, NTV2_CHANNEL6, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer7YUV, NTV2_WgtFrameBuffer7, NTV2_CHANNEL7, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer8YUV, NTV2_WgtFrameBuffer8, NTV2_CHANNEL8, kFramebufferNickname, 0},
{ NTV2_XptMixer3VidYUV, NTV2_WgtMixer3, NTV2_CHANNEL3, kMixerNickname, 0},
{ NTV2_XptMixer3KeyYUV, NTV2_WgtMixer3, NTV2_CHANNEL3, kMixerNickname, 1},
{ NTV2_XptMixer4VidYUV, NTV2_WgtMixer4, NTV2_CHANNEL4, kMixerNickname, 0},
{ NTV2_XptMixer4KeyYUV, NTV2_WgtMixer4, NTV2_CHANNEL4, kMixerNickname, 1},
{ NTV2_XptCSC6VidYUV, NTV2_WgtCSC6, NTV2_CHANNEL6, kCSCNickname, 0},
{ NTV2_XptCSC6KeyYUV, NTV2_WgtCSC6, NTV2_CHANNEL6, kCSCNickname, 1},
{ NTV2_XptCSC7VidYUV, NTV2_WgtCSC7, NTV2_CHANNEL7, kCSCNickname, 0},
{ NTV2_XptCSC7KeyYUV, NTV2_WgtCSC7, NTV2_CHANNEL7, kCSCNickname, 1},
{ NTV2_XptCSC8VidYUV, NTV2_WgtCSC8, NTV2_CHANNEL8, kCSCNickname, 0},
{ NTV2_XptCSC8KeyYUV, NTV2_WgtCSC8, NTV2_CHANNEL8, kCSCNickname, 1},
{ NTV2_XptDuallinkOut6, NTV2_WgtDualLinkV2Out6, NTV2_CHANNEL6, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut6DS2, NTV2_WgtDualLinkV2Out6, NTV2_CHANNEL6, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut7, NTV2_WgtDualLinkV2Out7, NTV2_CHANNEL7, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut7DS2, NTV2_WgtDualLinkV2Out7, NTV2_CHANNEL7, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut8, NTV2_WgtDualLinkV2Out8, NTV2_CHANNEL8, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut8DS2, NTV2_WgtDualLinkV2Out8, NTV2_CHANNEL8, kDualLinkOutNickname, 1},
{ NTV2_Xpt425Mux1AYUV, NTV2_Wgt425Mux1, NTV2_CHANNEL1, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux1BYUV, NTV2_Wgt425Mux1, NTV2_CHANNEL1, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux2AYUV, NTV2_Wgt425Mux2, NTV2_CHANNEL2, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux2BYUV, NTV2_Wgt425Mux2, NTV2_CHANNEL2, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux3AYUV, NTV2_Wgt425Mux3, NTV2_CHANNEL3, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux3BYUV, NTV2_Wgt425Mux3, NTV2_CHANNEL3, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux4AYUV, NTV2_Wgt425Mux4, NTV2_CHANNEL4, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux4BYUV, NTV2_Wgt425Mux4, NTV2_CHANNEL4, kTSIMuxNickname, 1},
{ NTV2_XptFrameBuffer1_DS2YUV, NTV2_WgtFrameBuffer1, NTV2_CHANNEL1, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer2_DS2YUV, NTV2_WgtFrameBuffer2, NTV2_CHANNEL2, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer3_DS2YUV, NTV2_WgtFrameBuffer3, NTV2_CHANNEL3, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer4_DS2YUV, NTV2_WgtFrameBuffer4, NTV2_CHANNEL4, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer5_DS2YUV, NTV2_WgtFrameBuffer5, NTV2_CHANNEL5, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer6_DS2YUV, NTV2_WgtFrameBuffer6, NTV2_CHANNEL6, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer7_DS2YUV, NTV2_WgtFrameBuffer7, NTV2_CHANNEL7, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer8_DS2YUV, NTV2_WgtFrameBuffer8, NTV2_CHANNEL8, kFramebufferNickname, 1},
{ NTV2_XptHDMIIn2, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 0},
{ NTV2_XptHDMIIn2Q2, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 1},
{ NTV2_XptHDMIIn2Q3, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 2},
{ NTV2_XptHDMIIn2Q4, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 3},
{ NTV2_XptHDMIIn3, NTV2_WgtHDMIIn3v4, NTV2_CHANNEL3, kHDMINickname, 0},
{ NTV2_XptHDMIIn4, NTV2_WgtHDMIIn4v4, NTV2_CHANNEL4, kHDMINickname, 0},
{ NTV2_XptDuallinkIn1, NTV2_WgtDualLinkV2In1, NTV2_CHANNEL1, kDualLinkInNickname, 0},
{ NTV2_XptLUT1Out, NTV2_WgtLUT1, NTV2_CHANNEL1, kLUTNickname, 0},
{ NTV2_XptCSC1VidRGB, NTV2_WgtCSC1, NTV2_CHANNEL1, kCSCNickname, 1},
{ NTV2_XptFrameBuffer1RGB, NTV2_WgtFrameBuffer1, NTV2_CHANNEL1, kFramebufferNickname, 2},
{ NTV2_XptFrameSync1RGB, NTV2_WgtFrameSync1, NTV2_CHANNEL1, kFrameSyncNickname, 1},
{ NTV2_XptFrameSync2RGB, NTV2_WgtFrameSync2, NTV2_CHANNEL2, kFrameSyncNickname, 1},
{ NTV2_XptLUT2Out, NTV2_WgtLUT2, NTV2_CHANNEL2, kLUTNickname, 0},
{ NTV2_XptFrameBuffer2RGB, NTV2_WgtFrameBuffer2, NTV2_CHANNEL2, kFramebufferNickname, 2},
{ NTV2_XptCSC2VidRGB, NTV2_WgtCSC2, NTV2_CHANNEL2, kCSCNickname, 1},
{ NTV2_XptMixer1VidRGB, NTV2_WgtMixer1, NTV2_CHANNEL1, kMixerNickname, 1},
{ NTV2_XptHDMIIn1RGB, NTV2_WgtHDMIIn1v3, NTV2_CHANNEL1, kHDMINickname, 2},
{ NTV2_XptFrameBuffer3RGB, NTV2_WgtFrameBuffer3, NTV2_CHANNEL3, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer4RGB, NTV2_WgtFrameBuffer4, NTV2_CHANNEL4, kFramebufferNickname, 2},
{ NTV2_XptDuallinkIn2, NTV2_WgtDualLinkV2In2, NTV2_CHANNEL2, kDualLinkInNickname, 0},
{ NTV2_XptLUT3Out, NTV2_WgtLUT3, NTV2_CHANNEL3, kLUTNickname, 0},
{ NTV2_XptLUT4Out, NTV2_WgtLUT4, NTV2_CHANNEL4, kLUTNickname, 0},
{ NTV2_XptLUT5Out, NTV2_WgtLUT5, NTV2_CHANNEL5, kLUTNickname, 0},
{ NTV2_XptCSC5VidRGB, NTV2_WgtCSC5, NTV2_CHANNEL5, kCSCNickname, 2},
{ NTV2_XptDuallinkIn3, NTV2_WgtDualLinkV2In3, NTV2_CHANNEL3, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn4, NTV2_WgtDualLinkV2In4, NTV2_CHANNEL4, kDualLinkInNickname, 0},
{ NTV2_XptCSC3VidRGB, NTV2_WgtCSC3, NTV2_CHANNEL3, kCSCNickname, 2},
{ NTV2_XptCSC4VidRGB, NTV2_WgtCSC4, NTV2_CHANNEL4, kCSCNickname, 2},
{ NTV2_Xpt3DLUT1RGB, NTV2_Wgt3DLUT1, NTV2_CHANNEL1, kLUT3DNickname, 1},
{ NTV2_XptHDMIIn1Q2RGB, NTV2_WgtHDMIIn1v3, NTV2_CHANNEL1, kHDMINickname, 1},
{ NTV2_XptHDMIIn1Q3RGB, NTV2_WgtHDMIIn1v3, NTV2_CHANNEL1, kHDMINickname, 2},
{ NTV2_XptHDMIIn1Q4RGB, NTV2_WgtHDMIIn1v3, NTV2_CHANNEL1, kHDMINickname, 3},
{ NTV2_Xpt4KDownConverterOutRGB, NTV2_Wgt4KDownConverter, NTV2_CHANNEL1, k4KDownConvertNickname, 1},
{ NTV2_XptDuallinkIn5, NTV2_WgtDualLinkV2In5, NTV2_CHANNEL5, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn6, NTV2_WgtDualLinkV2In6, NTV2_CHANNEL6, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn7, NTV2_WgtDualLinkV2In7, NTV2_CHANNEL7, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn8, NTV2_WgtDualLinkV2In8, NTV2_CHANNEL8, kDualLinkInNickname, 0},
{ NTV2_XptFrameBuffer5RGB, NTV2_WgtFrameBuffer5, NTV2_CHANNEL5, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer6RGB, NTV2_WgtFrameBuffer6, NTV2_CHANNEL6, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer7RGB, NTV2_WgtFrameBuffer7, NTV2_CHANNEL7, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer8RGB, NTV2_WgtFrameBuffer8, NTV2_CHANNEL8, kFramebufferNickname, 2},
{ NTV2_XptCSC6VidRGB, NTV2_WgtCSC6, NTV2_CHANNEL6, kCSCNickname, 1},
{ NTV2_XptCSC7VidRGB, NTV2_WgtCSC7, NTV2_CHANNEL7, kCSCNickname, 1},
{ NTV2_XptCSC8VidRGB, NTV2_WgtCSC8, NTV2_CHANNEL8, kCSCNickname, 1},
{ NTV2_XptLUT6Out, NTV2_WgtLUT6, NTV2_CHANNEL6, kLUTNickname, 0},
{ NTV2_XptLUT7Out, NTV2_WgtLUT7, NTV2_CHANNEL7, kLUTNickname, 0},
{ NTV2_XptLUT8Out, NTV2_WgtLUT8, NTV2_CHANNEL8, kLUTNickname, 0},
{ NTV2_Xpt425Mux1ARGB, NTV2_Wgt425Mux1, NTV2_CHANNEL1, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux1BRGB, NTV2_Wgt425Mux1, NTV2_CHANNEL1, kTSIMuxNickname, 3},
{ NTV2_Xpt425Mux2ARGB, NTV2_Wgt425Mux2, NTV2_CHANNEL2, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux2BRGB, NTV2_Wgt425Mux2, NTV2_CHANNEL2, kTSIMuxNickname, 3},
{ NTV2_Xpt425Mux3ARGB, NTV2_Wgt425Mux3, NTV2_CHANNEL3, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux3BRGB, NTV2_Wgt425Mux3, NTV2_CHANNEL3, kTSIMuxNickname, 3},
{ NTV2_Xpt425Mux4ARGB, NTV2_Wgt425Mux4, NTV2_CHANNEL4, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux4BRGB, NTV2_Wgt425Mux4, NTV2_CHANNEL4, kTSIMuxNickname, 3},
{ NTV2_XptFrameBuffer1_DS2RGB, NTV2_WgtFrameBuffer1, NTV2_CHANNEL1, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer2_DS2RGB, NTV2_WgtFrameBuffer2, NTV2_CHANNEL2, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer3_DS2RGB, NTV2_WgtFrameBuffer3, NTV2_CHANNEL3, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer4_DS2RGB, NTV2_WgtFrameBuffer4, NTV2_CHANNEL4, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer5_DS2RGB, NTV2_WgtFrameBuffer5, NTV2_CHANNEL5, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer6_DS2RGB, NTV2_WgtFrameBuffer6, NTV2_CHANNEL6, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer7_DS2RGB, NTV2_WgtFrameBuffer7, NTV2_CHANNEL7, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer8_DS2RGB, NTV2_WgtFrameBuffer8, NTV2_CHANNEL8, kFramebufferNickname, 3},
{ NTV2_XptHDMIIn2RGB, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 0},
{ NTV2_XptHDMIIn2Q2RGB, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 1},
{ NTV2_XptHDMIIn2Q3RGB, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 2},
{ NTV2_XptHDMIIn2Q4RGB, NTV2_WgtHDMIIn2v4, NTV2_CHANNEL2, kHDMINickname, 3},
{ NTV2_XptHDMIIn3RGB, NTV2_WgtHDMIIn3v4, NTV2_CHANNEL3, kHDMINickname, 0},
{ NTV2_XptHDMIIn4RGB, NTV2_WgtHDMIIn4v4, NTV2_CHANNEL4, kHDMINickname, 0},
{ NTV2_OUTPUT_CROSSPOINT_INVALID, NTV2_WIDGET_INVALID, "", -1},
{ NTV2_XptBlack, NTV2_WgtUndefined, kBlackNickname, 0},
{ NTV2_XptSDIIn1, NTV2_WgtSDIIn1, kSDINickname, 0},
{ NTV2_XptSDIIn2, NTV2_WgtSDIIn2, kSDINickname, 0},
{ NTV2_XptLUT1YUV, NTV2_WgtLUT1, kSDINickname, 0},
{ NTV2_XptCSC1VidYUV, NTV2_WgtCSC1, kCSCNickname, 0},
{ NTV2_XptConversionModule, NTV2_WgtUpDownConverter1, kUpDownConvertNickname, 0},
{ NTV2_XptCompressionModule, NTV2_WgtCompression1, kCompressionNickname, 0},
{ NTV2_XptFrameBuffer1YUV, NTV2_WgtFrameBuffer1, kFramebufferNickname, 0},
{ NTV2_XptFrameSync1YUV, NTV2_WgtFrameSync1, kFrameSyncNickname, 0},
{ NTV2_XptFrameSync2YUV, NTV2_WgtFrameSync2, kFrameSyncNickname, 0},
{ NTV2_XptDuallinkOut1, NTV2_WgtDualLinkV2Out1, kDualLinkOutNickname, 0},
{ NTV2_XptCSC1KeyYUV, NTV2_WgtCSC1, kCSCNickname, 2},
{ NTV2_XptFrameBuffer2YUV, NTV2_WgtFrameBuffer2, kFramebufferNickname, 0},
{ NTV2_XptCSC2VidYUV, NTV2_WgtCSC2, kCSCNickname, 0},
{ NTV2_XptCSC2KeyYUV, NTV2_WgtCSC2, kCSCNickname, 2},
{ NTV2_XptMixer1VidYUV, NTV2_WgtMixer1, kMixerNickname, 0},
{ NTV2_XptMixer1KeyYUV, NTV2_WgtMixer1, kMixerNickname, 1},
{ NTV2_XptMultiLinkOut1DS1, NTV2_WgtMultiLinkOut1, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut1DS2, NTV2_WgtMultiLinkOut1, kMultiLinkNickname, 1},
{ NTV2_XptAnalogIn, NTV2_WgtAnalogIn1, kAnalogNickname, 0},
{ NTV2_XptHDMIIn1, NTV2_WgtHDMIIn1, kHDMINickname, 0},
{ NTV2_XptMultiLinkOut1DS3, NTV2_WgtMultiLinkOut1, kMultiLinkNickname, 2},
{ NTV2_XptMultiLinkOut1DS4, NTV2_WgtMultiLinkOut1, kMultiLinkNickname, 3},
{ NTV2_XptMultiLinkOut2DS1, NTV2_WgtMultiLinkOut2, kMultiLinkNickname, 0},
{ NTV2_XptMultiLinkOut2DS2, NTV2_WgtMultiLinkOut2, kMultiLinkNickname, 1},
{ NTV2_XptDuallinkOut2, NTV2_WgtDualLinkV2Out2, kDualLinkOutNickname, 0},
{ NTV2_XptTestPatternYUV, NTV2_WgtTestPattern1, kTestPatternNickname, 0},
{ NTV2_XptSDIIn1DS2, NTV2_Wgt3GSDIIn1, kSDINickname, 1},
{ NTV2_XptSDIIn2DS2, NTV2_Wgt3GSDIIn2, kSDINickname, 1},
{ NTV2_XptMixer2VidYUV, NTV2_WgtMixer2, kMixerNickname, 0},
{ NTV2_XptMixer2KeyYUV, NTV2_WgtMixer2, kMixerNickname, 1},
{ NTV2_XptStereoCompressorOut, NTV2_WgtStereoCompressor, kStereoCompNickname, 0},
{ NTV2_XptFrameBuffer3YUV, NTV2_WgtFrameBuffer3, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer4YUV, NTV2_WgtFrameBuffer4, kFramebufferNickname, 0},
{ NTV2_XptDuallinkOut1DS2, NTV2_WgtDualLinkV2Out1, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut2DS2, NTV2_WgtDualLinkV2Out2, kDualLinkOutNickname, 1},
{ NTV2_XptCSC5VidYUV, NTV2_WgtCSC5, kCSCNickname, 0},
{ NTV2_XptCSC5KeyYUV, NTV2_WgtCSC5, kCSCNickname, 1},
{ NTV2_XptMultiLinkOut2DS3, NTV2_WgtMultiLinkOut2, kMultiLinkNickname, 2},
{ NTV2_XptMultiLinkOut2DS4, NTV2_WgtMultiLinkOut2, kMultiLinkNickname, 3},
{ NTV2_XptSDIIn3, NTV2_Wgt3GSDIIn3, kSDINickname, 0},
{ NTV2_XptSDIIn4, NTV2_Wgt3GSDIIn4, kSDINickname, 0},
{ NTV2_XptSDIIn3DS2, NTV2_Wgt3GSDIIn3, kSDINickname, 1},
{ NTV2_XptSDIIn4DS2, NTV2_Wgt3GSDIIn4, kSDINickname, 1},
{ NTV2_XptDuallinkOut3, NTV2_WgtDualLinkV2Out3, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut3DS2, NTV2_WgtDualLinkV2Out3, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut4, NTV2_WgtDualLinkV2Out4, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut4DS2, NTV2_WgtDualLinkV2Out4, kDualLinkOutNickname, 1},
{ NTV2_XptCSC3VidYUV, NTV2_WgtCSC3, kCSCNickname, 0},
{ NTV2_XptCSC3KeyYUV, NTV2_WgtCSC3, kCSCNickname, 2},
{ NTV2_XptCSC4VidYUV, NTV2_WgtCSC4, kCSCNickname, 0},
{ NTV2_XptCSC4KeyYUV, NTV2_WgtCSC4, kCSCNickname, 2},
{ NTV2_XptDuallinkOut5, NTV2_WgtDualLinkV2Out5, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut5DS2, NTV2_WgtDualLinkV2Out5, kDualLinkOutNickname, 1},
{ NTV2_Xpt3DLUT1YUV, NTV2_Wgt3DLUT1, kLUT3DNickname, 0},
{ NTV2_XptHDMIIn1Q2, NTV2_WgtHDMIIn1v3, kHDMINickname, 1},
{ NTV2_XptHDMIIn1Q3, NTV2_WgtHDMIIn1v3, kHDMINickname, 2},
{ NTV2_XptHDMIIn1Q4, NTV2_WgtHDMIIn1v3, kHDMINickname, 3},
{ NTV2_Xpt4KDownConverterOut, NTV2_Wgt4KDownConverter, k4KDownConvertNickname, 0},
{ NTV2_XptSDIIn5, NTV2_Wgt3GSDIIn5, kSDINickname, 0},
{ NTV2_XptSDIIn6, NTV2_Wgt3GSDIIn6, kSDINickname, 0},
{ NTV2_XptSDIIn5DS2, NTV2_Wgt3GSDIIn5, kSDINickname, 1},
{ NTV2_XptSDIIn6DS2, NTV2_Wgt3GSDIIn6, kSDINickname, 1},
{ NTV2_XptSDIIn7, NTV2_Wgt3GSDIIn7, kSDINickname, 0},
{ NTV2_XptSDIIn8, NTV2_Wgt3GSDIIn8, kSDINickname, 0},
{ NTV2_XptSDIIn7DS2, NTV2_Wgt3GSDIIn7, kSDINickname, 1},
{ NTV2_XptSDIIn8DS2, NTV2_Wgt3GSDIIn8, kSDINickname, 1},
{ NTV2_XptFrameBuffer5YUV, NTV2_WgtFrameBuffer5, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer6YUV, NTV2_WgtFrameBuffer6, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer7YUV, NTV2_WgtFrameBuffer7, kFramebufferNickname, 0},
{ NTV2_XptFrameBuffer8YUV, NTV2_WgtFrameBuffer8, kFramebufferNickname, 0},
{ NTV2_XptMixer3VidYUV, NTV2_WgtMixer3, kMixerNickname, 0},
{ NTV2_XptMixer3KeyYUV, NTV2_WgtMixer3, kMixerNickname, 1},
{ NTV2_XptMixer4VidYUV, NTV2_WgtMixer4, kMixerNickname, 0},
{ NTV2_XptMixer4KeyYUV, NTV2_WgtMixer4, kMixerNickname, 1},
{ NTV2_XptCSC6VidYUV, NTV2_WgtCSC6, kCSCNickname, 0},
{ NTV2_XptCSC6KeyYUV, NTV2_WgtCSC6, kCSCNickname, 1},
{ NTV2_XptCSC7VidYUV, NTV2_WgtCSC7, kCSCNickname, 0},
{ NTV2_XptCSC7KeyYUV, NTV2_WgtCSC7, kCSCNickname, 1},
{ NTV2_XptCSC8VidYUV, NTV2_WgtCSC8, kCSCNickname, 0},
{ NTV2_XptCSC8KeyYUV, NTV2_WgtCSC8, kCSCNickname, 1},
{ NTV2_XptDuallinkOut6, NTV2_WgtDualLinkV2Out6, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut6DS2, NTV2_WgtDualLinkV2Out6, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut7, NTV2_WgtDualLinkV2Out7, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut7DS2, NTV2_WgtDualLinkV2Out7, kDualLinkOutNickname, 1},
{ NTV2_XptDuallinkOut8, NTV2_WgtDualLinkV2Out8, kDualLinkOutNickname, 0},
{ NTV2_XptDuallinkOut8DS2, NTV2_WgtDualLinkV2Out8, kDualLinkOutNickname, 1},
{ NTV2_Xpt425Mux1AYUV, NTV2_Wgt425Mux1, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux1BYUV, NTV2_Wgt425Mux1, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux2AYUV, NTV2_Wgt425Mux2, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux2BYUV, NTV2_Wgt425Mux2, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux3AYUV, NTV2_Wgt425Mux3, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux3BYUV, NTV2_Wgt425Mux3, kTSIMuxNickname, 1},
{ NTV2_Xpt425Mux4AYUV, NTV2_Wgt425Mux4, kTSIMuxNickname, 0},
{ NTV2_Xpt425Mux4BYUV, NTV2_Wgt425Mux4, kTSIMuxNickname, 1},
{ NTV2_XptFrameBuffer1_DS2YUV, NTV2_WgtFrameBuffer1, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer2_DS2YUV, NTV2_WgtFrameBuffer2, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer3_DS2YUV, NTV2_WgtFrameBuffer3, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer4_DS2YUV, NTV2_WgtFrameBuffer4, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer5_DS2YUV, NTV2_WgtFrameBuffer5, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer6_DS2YUV, NTV2_WgtFrameBuffer6, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer7_DS2YUV, NTV2_WgtFrameBuffer7, kFramebufferNickname, 1},
{ NTV2_XptFrameBuffer8_DS2YUV, NTV2_WgtFrameBuffer8, kFramebufferNickname, 1},
{ NTV2_XptHDMIIn2, NTV2_WgtHDMIIn2v4, kHDMINickname, 0},
{ NTV2_XptHDMIIn2Q2, NTV2_WgtHDMIIn2v4, kHDMINickname, 1},
{ NTV2_XptHDMIIn2Q3, NTV2_WgtHDMIIn2v4, kHDMINickname, 2},
{ NTV2_XptHDMIIn2Q4, NTV2_WgtHDMIIn2v4, kHDMINickname, 3},
{ NTV2_XptHDMIIn3, NTV2_WgtHDMIIn3v4, kHDMINickname, 0},
{ NTV2_XptHDMIIn4, NTV2_WgtHDMIIn4v4, kHDMINickname, 0},
{ NTV2_XptDuallinkIn1, NTV2_WgtDualLinkV2In1, kDualLinkInNickname, 0},
{ NTV2_XptLUT1Out, NTV2_WgtLUT1, kLUTNickname, 0},
{ NTV2_XptCSC1VidRGB, NTV2_WgtCSC1, kCSCNickname, 1},
{ NTV2_XptFrameBuffer1RGB, NTV2_WgtFrameBuffer1, kFramebufferNickname, 2},
{ NTV2_XptFrameSync1RGB, NTV2_WgtFrameSync1, kFrameSyncNickname, 1},
{ NTV2_XptFrameSync2RGB, NTV2_WgtFrameSync2, kFrameSyncNickname, 1},
{ NTV2_XptLUT2Out, NTV2_WgtLUT2, kLUTNickname, 0},
{ NTV2_XptFrameBuffer2RGB, NTV2_WgtFrameBuffer2, kFramebufferNickname, 2},
{ NTV2_XptCSC2VidRGB, NTV2_WgtCSC2, kCSCNickname, 1},
{ NTV2_XptMixer1VidRGB, NTV2_WgtMixer1, kMixerNickname, 1},
{ NTV2_XptHDMIIn1RGB, NTV2_WgtHDMIIn1v3, kHDMINickname, 2},
{ NTV2_XptFrameBuffer3RGB, NTV2_WgtFrameBuffer3, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer4RGB, NTV2_WgtFrameBuffer4, kFramebufferNickname, 2},
{ NTV2_XptDuallinkIn2, NTV2_WgtDualLinkV2In2, kDualLinkInNickname, 0},
{ NTV2_XptLUT3Out, NTV2_WgtLUT3, kLUTNickname, 0},
{ NTV2_XptLUT4Out, NTV2_WgtLUT4, kLUTNickname, 0},
{ NTV2_XptLUT5Out, NTV2_WgtLUT5, kLUTNickname, 0},
{ NTV2_XptCSC5VidRGB, NTV2_WgtCSC5, kCSCNickname, 2},
{ NTV2_XptDuallinkIn3, NTV2_WgtDualLinkV2In3, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn4, NTV2_WgtDualLinkV2In4, kDualLinkInNickname, 0},
{ NTV2_XptCSC3VidRGB, NTV2_WgtCSC3, kCSCNickname, 2},
{ NTV2_XptCSC4VidRGB, NTV2_WgtCSC4, kCSCNickname, 2},
{ NTV2_Xpt3DLUT1RGB, NTV2_Wgt3DLUT1, kLUT3DNickname, 1},
{ NTV2_XptHDMIIn1Q2RGB, NTV2_WgtHDMIIn1v3, kHDMINickname, 1},
{ NTV2_XptHDMIIn1Q3RGB, NTV2_WgtHDMIIn1v3, kHDMINickname, 2},
{ NTV2_XptHDMIIn1Q4RGB, NTV2_WgtHDMIIn1v3, kHDMINickname, 3},
{ NTV2_Xpt4KDownConverterOutRGB, NTV2_Wgt4KDownConverter, k4KDownConvertNickname, 1},
{ NTV2_XptDuallinkIn5, NTV2_WgtDualLinkV2In5, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn6, NTV2_WgtDualLinkV2In6, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn7, NTV2_WgtDualLinkV2In7, kDualLinkInNickname, 0},
{ NTV2_XptDuallinkIn8, NTV2_WgtDualLinkV2In8, kDualLinkInNickname, 0},
{ NTV2_XptFrameBuffer5RGB, NTV2_WgtFrameBuffer5, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer6RGB, NTV2_WgtFrameBuffer6, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer7RGB, NTV2_WgtFrameBuffer7, kFramebufferNickname, 2},
{ NTV2_XptFrameBuffer8RGB, NTV2_WgtFrameBuffer8, kFramebufferNickname, 2},
{ NTV2_XptCSC6VidRGB, NTV2_WgtCSC6, kCSCNickname, 1},
{ NTV2_XptCSC7VidRGB, NTV2_WgtCSC7, kCSCNickname, 1},
{ NTV2_XptCSC8VidRGB, NTV2_WgtCSC8, kCSCNickname, 1},
{ NTV2_XptLUT6Out, NTV2_WgtLUT6, kLUTNickname, 0},
{ NTV2_XptLUT7Out, NTV2_WgtLUT7, kLUTNickname, 0},
{ NTV2_XptLUT8Out, NTV2_WgtLUT8, kLUTNickname, 0},
{ NTV2_Xpt425Mux1ARGB, NTV2_Wgt425Mux1, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux1BRGB, NTV2_Wgt425Mux1, kTSIMuxNickname, 3},
{ NTV2_Xpt425Mux2ARGB, NTV2_Wgt425Mux2, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux2BRGB, NTV2_Wgt425Mux2, kTSIMuxNickname, 3},
{ NTV2_Xpt425Mux3ARGB, NTV2_Wgt425Mux3, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux3BRGB, NTV2_Wgt425Mux3, kTSIMuxNickname, 3},
{ NTV2_Xpt425Mux4ARGB, NTV2_Wgt425Mux4, kTSIMuxNickname, 2},
{ NTV2_Xpt425Mux4BRGB, NTV2_Wgt425Mux4, kTSIMuxNickname, 3},
{ NTV2_XptFrameBuffer1_DS2RGB, NTV2_WgtFrameBuffer1, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer2_DS2RGB, NTV2_WgtFrameBuffer2, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer3_DS2RGB, NTV2_WgtFrameBuffer3, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer4_DS2RGB, NTV2_WgtFrameBuffer4, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer5_DS2RGB, NTV2_WgtFrameBuffer5, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer6_DS2RGB, NTV2_WgtFrameBuffer6, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer7_DS2RGB, NTV2_WgtFrameBuffer7, kFramebufferNickname, 3},
{ NTV2_XptFrameBuffer8_DS2RGB, NTV2_WgtFrameBuffer8, kFramebufferNickname, 3},
{ NTV2_XptHDMIIn2RGB, NTV2_WgtHDMIIn2v4, kHDMINickname, 0},
{ NTV2_XptHDMIIn2Q2RGB, NTV2_WgtHDMIIn2v4, kHDMINickname, 1},
{ NTV2_XptHDMIIn2Q3RGB, NTV2_WgtHDMIIn2v4, kHDMINickname, 2},
{ NTV2_XptHDMIIn2Q4RGB, NTV2_WgtHDMIIn2v4, kHDMINickname, 3},
{ NTV2_XptHDMIIn3RGB, NTV2_WgtHDMIIn3v4, kHDMINickname, 0},
{ NTV2_XptHDMIIn4RGB, NTV2_WgtHDMIIn4v4, kHDMINickname, 0},
};
// clang-format on
@ -349,7 +350,9 @@ bool WidgetInputSocket::Find(const std::string &name, NTV2Channel channel,
int32_t datastream, WidgetInputSocket &inp)
{
for (const auto &in : kWidgetInputSockets) {
if (name == in.name && channel == in.channel &&
if (name == in.name &&
channel == CNTV2SignalRouter::WidgetIDToChannel(
in.widget_id) &&
datastream == in.datastream_index) {
inp = in;
return true;
@ -389,7 +392,8 @@ NTV2Channel WidgetInputSocket::InputXptChannel(InputXpt xpt)
NTV2Channel channel = NTV2_CHANNEL_INVALID;
for (auto &x : kWidgetInputSockets) {
if (x.id == xpt) {
channel = x.channel;
channel = CNTV2SignalRouter::WidgetIDToChannel(
x.widget_id);
break;
}
}
@ -415,7 +419,9 @@ bool WidgetOutputSocket::Find(const std::string &name, NTV2Channel channel,
// << ", chan = " << NTV2ChannelToString(channel)
// << ", datastream = " << datastream << std::endl;
for (const auto &wo : kWidgetOutputSockets) {
if (name == wo.name && channel == wo.channel &&
if (name == wo.name &&
channel == CNTV2SignalRouter::WidgetIDToChannel(
wo.widget_id) &&
datastream == wo.datastream_index) {
out = wo;
return true;
@ -455,7 +461,8 @@ NTV2Channel WidgetOutputSocket::OutputXptChannel(OutputXpt xpt)
NTV2Channel channel = NTV2_CHANNEL_INVALID;
for (auto &x : kWidgetOutputSockets) {
if (x.id == xpt) {
channel = x.channel;
channel = CNTV2SignalRouter::WidgetIDToChannel(
x.widget_id);
break;
}
}

View File

@ -11,7 +11,6 @@ using InputXpt = NTV2InputCrosspointID; // dest
struct WidgetInputSocket {
InputXpt id;
NTV2WidgetID widget_id;
NTV2Channel channel;
const char *name;
int32_t datastream_index;
@ -28,7 +27,6 @@ struct WidgetInputSocket {
struct WidgetOutputSocket {
OutputXpt id;
NTV2WidgetID widget_id;
NTV2Channel channel;
const char *name;
int32_t datastream_index;

View File

@ -12,4 +12,6 @@ AutoStart="Auto start on launch"
Buffering="Use Buffering"
DeactivateWhenNotShowing="Deactivate when not showing"
IOSelect="Select..."
SDI4KTransport="SDI 4K Transport"
SDITransport="SDI Transport"
SDITransport4K="SDI 4K Transport"
Auto="Auto"

View File

@ -20,8 +20,9 @@ bool obs_module_load(void)
{
CNTV2DeviceScanner scanner;
auto numDevices = scanner.GetNumDevices();
if (numDevices == 0) {
blog(LOG_WARNING,
"No AJA devices found, skipping loading AJA plugin");
return false;
}
@ -36,6 +37,20 @@ bool obs_module_load(void)
return true;
}
void obs_module_post_load(void)
{
struct calldata params = {0};
auto cardManager = &aja::CardManager::Instance();
auto num = cardManager->NumCardEntries();
blog(LOG_WARNING, "aja main card manager: %lu", cardManager);
blog(LOG_WARNING, "NUM CARDS: %lu", num);
calldata_set_ptr(&params, "card_manager", (void *)cardManager);
auto signal_handler = obs_get_signal_handler();
signal_handler_signal(signal_handler, "aja_loaded", &params);
calldata_free(&params);
}
void obs_module_unload(void)
{
aja::CardManager::Instance().ClearCardEntries();

View File

@ -1,22 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<HDMIWireFormat, RoutingConfig>
kHDMIRGBCaptureConfigs = {{HDMIWireFormat::HD_RGB_LFR,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"hdmi[{ch1}][0]->fb[{ch1}][0];",
}}};

View File

@ -1,29 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<HDMIWireFormat, RoutingConfig>
kHDMIRGBDisplayConfigs = {{HDMIWireFormat::HD_RGB_LFR,
{NTV2_MODE_DISPLAY, 1, 1, true, false, false,
false, false, false, false, false, false,
false, "fb[{ch1}][0]->hdmi[0][0];"}},
{HDMIWireFormat::TTAP_PRO,
{
NTV2_MODE_DISPLAY,
1,
1,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];"
"fb[{ch1}][2]->hdmi[{ch1}][0];",
}}};

View File

@ -1,48 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<HDMIWireFormat, RoutingConfig>
kHDMIYCbCrCaptureConfigs = {
{HDMIWireFormat::HD_YCBCR_LFR,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"hdmi[{ch1}][0]->fb[{ch1}][0];",
}},
{HDMIWireFormat::UHD_4K_YCBCR_LFR,
{
NTV2_MODE_CAPTURE,
1,
2,
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
"hdmi[0][0]->tsi[{ch1}][0];"
"hdmi[0][1]->tsi[{ch1}][1];"
"hdmi[0][2]->tsi[{ch2}][0];"
"hdmi[0][3]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->fb[{ch1}][0];"
"tsi[{ch1}][1]->fb[{ch1}][1];"
"tsi[{ch2}][0]->fb[{ch2}][0];"
"tsi[{ch2}][1]->fb[{ch2}][1];",
}},
};

View File

@ -1,64 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<HDMIWireFormat, RoutingConfig>
kHDMIYCbCrDisplayConfigs = {{HDMIWireFormat::HD_YCBCR_LFR,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->hdmi[0][0];",
}},
{HDMIWireFormat::UHD_4K_YCBCR_LFR,
{
NTV2_MODE_DISPLAY,
1,
2,
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
"fb[{ch1}][0]->tsi[{ch1}][0];"
"fb[{ch1}][1]->tsi[{ch1}][1];"
"fb[{ch2}][0]->tsi[{ch2}][0];"
"fb[{ch2}][1]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->hdmi[0][0];"
"tsi[{ch1}][1]->hdmi[0][1];"
"tsi[{ch2}][0]->hdmi[0][2];"
"tsi[{ch2}][1]->hdmi[0][3];",
}},
{HDMIWireFormat::TTAP_PRO,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch1}][0]->hdmi[{ch1}][0];",
}}};

View File

@ -1,467 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<SDIWireFormat, RoutingConfig>
kSDIRGBCaptureConfigs = {
{
SDIWireFormat::SD_ST352,
{
NTV2_MODE_CAPTURE, // i/o mode
1, // num wires
1, // num framestores
false, // enable 3G output?
false, // enable 6G output?
false, // enable 12G output?
false, // convert 3Gb -> 3Ga input?
false, // convert 3Ga -> 3Gb output?
false, // convert RGB 3Ga output?
false, // enable 3Gb output?
false, // enable 4K Square Division?
false, // enable 8K Square Division?
false, // enable two-sample-interleave?
"",
},
},
{SDIWireFormat::HD_720p_ST292,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_1080_ST292,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Capture
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_1080_ST372_Dual,
{
NTV2_MODE_CAPTURE,
2,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Capture
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch2}][0]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_720p_ST425_3Ga,
{
NTV2_MODE_CAPTURE,
1,
1,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
// Capture
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_1080p_ST425_3Ga,
{
NTV2_MODE_CAPTURE,
1,
1,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
// Capture
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb_DL,
{
NTV2_MODE_CAPTURE,
1,
1,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Capture
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_720p_ST425_3Gb,
{
NTV2_MODE_CAPTURE,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Capture
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb,
{
NTV2_MODE_CAPTURE,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Capture
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Ga,
{
NTV2_MODE_CAPTURE,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Gb,
{
NTV2_MODE_CAPTURE,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"",
}},
{SDIWireFormat::UHD4K_ST292_Quad_1_5_Squares,
{
NTV2_MODE_CAPTURE,
4,
4,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Capture
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch2}][0]->fb[{ch2}][0];"
"sdi[{ch3}][0]->fb[{ch3}][0];"
"sdi[{ch4}][0]->fb[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_Squares,
{
NTV2_MODE_CAPTURE,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Capture
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch2}][0]->fb[{ch2}][0];"
"sdi[{ch3}][0]->fb[{ch3}][0];"
"sdi[{ch4}][0]->fb[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_Squares,
{
NTV2_MODE_CAPTURE,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"sdi[{ch2}][0]->dli[{ch2}][0];"
"sdi[{ch2}][1]->dli[{ch2}][1];"
"sdi[{ch3}][0]->dli[{ch3}][0];"
"sdi[{ch3}][1]->dli[{ch3}][1];"
"sdi[{ch4}][0]->dli[{ch4}][0];"
"sdi[{ch4}][1]->dli[{ch4}][1];"
"dli[{ch1}][0]->fb[{ch1}][2];"
"dli[{ch2}][0]->fb[{ch2}][2];"
"dli[{ch3}][0]->fb[{ch3}][2];"
"dli[{ch4}][0]->fb[{ch4}][2];",
}},
{SDIWireFormat::UHD4K_ST425_Dual_3Gb_2SI,
{
NTV2_MODE_CAPTURE,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_2SI,
{
NTV2_MODE_CAPTURE,
4,
4,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
// SDI 1-4 -> Dual-Link 1-4
// -> TSI Mux 1-2 -> Framestore 1-2
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"sdi[{ch2}][0]->dli[{ch2}][0];"
"sdi[{ch2}][1]->dli[{ch2}][1];"
"sdi[{ch3}][0]->dli[{ch3}][0];"
"sdi[{ch3}][1]->dli[{ch3}][1];"
"sdi[{ch4}][0]->dli[{ch4}][0];"
"sdi[{ch4}][1]->dli[{ch4}][1];"
"dli[{ch1}][0]->tsi[{ch1}][0];"
"dli[{ch2}][0]->tsi[{ch1}][1];"
"dli[{ch3}][0]->tsi[{ch2}][0];"
"dli[{ch4}][0]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->fb[{ch1}][0];"
"tsi[{ch1}][1]->fb[{ch1}][1];"
"tsi[{ch2}][0]->fb[{ch2}][0];"
"tsi[{ch2}][1]->fb[{ch2}][1];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_2SI,
{
NTV2_MODE_CAPTURE,
4,
4,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
// SDI 1-4 -> Dual-Link 1-4
// -> TSI Mux 1-2 -> Framestore 1-2
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"sdi[{ch2}][0]->dli[{ch2}][0];"
"sdi[{ch2}][1]->dli[{ch2}][1];"
"sdi[{ch3}][0]->dli[{ch3}][0];"
"sdi[{ch3}][1]->dli[{ch3}][1];"
"sdi[{ch4}][0]->dli[{ch4}][0];"
"sdi[{ch4}][1]->dli[{ch4}][1];"
"dli[{ch1}][0]->tsi[{ch1}][0];"
"dli[{ch2}][0]->tsi[{ch1}][1];"
"dli[{ch3}][0]->tsi[{ch2}][0];"
"dli[{ch4}][0]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->fb[{ch1}][0];"
"tsi[{ch1}][1]->fb[{ch1}][1];"
"tsi[{ch2}][0]->fb[{ch2}][0];"
"tsi[{ch2}][1]->fb[{ch2}][1];",
}},
{SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
true,
false,
false,
true,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_Dual_12G,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_RGB_Dual_12G,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_Quad_12G,
{
NTV2_MODE_CAPTURE,
4,
4,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
};

View File

@ -1,469 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<SDIWireFormat, RoutingConfig>
kSDIRGBDisplayConfigs = {
{
SDIWireFormat::SD_ST352,
{
NTV2_MODE_DISPLAY,
1, // num wires
1, // num framestores
false, // enable 3G output?
false, // enable 6G output?
false, // enable 12G output?
false, // convert 3Gb -> 3Ga input?
false, // convert 3Ga -> 3Gb output?
false, // convert RGB 3Ga output?
false, // enable 3Gb output?
false, // enable 4K Square Division?
false, // enable 8K Square Division?
false, // enable two-sample-interleave?
"", // RGB Output Route
},
},
{SDIWireFormat::HD_720p_ST292,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}[0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080_ST292,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}[0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080_ST372_Dual,
{
NTV2_MODE_DISPLAY,
2,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Playout
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}[0];"
"dlo[{ch1}][1]->sdi[{ch2}][0];",
}},
{SDIWireFormat::HD_720p_ST425_3Ga,
{
NTV2_MODE_DISPLAY,
1,
1,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
// Output
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080p_ST425_3Ga,
{
NTV2_MODE_DISPLAY,
1,
1,
true,
false,
false,
false,
false,
true,
false,
false,
false,
false,
// Output
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb_DL,
{
NTV2_MODE_DISPLAY,
1,
1,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Output
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_720p_ST425_3Gb,
{
NTV2_MODE_DISPLAY,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Output
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb,
{
NTV2_MODE_DISPLAY,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
// Output
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Ga,
{
NTV2_MODE_DISPLAY,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Gb,
{
NTV2_MODE_DISPLAY,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"",
}},
{SDIWireFormat::UHD4K_ST292_Quad_1_5_Squares,
{
NTV2_MODE_DISPLAY,
4,
4,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Playout
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch2}][0]->sdi[{ch2}][0];"
"fb[{ch3}][0]->sdi[{ch3}][0];"
"fb[{ch4}][0]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_Squares,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Playout
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch2}][0]->sdi[{ch2}][0];"
"fb[{ch3}][0]->sdi[{ch3}][0];"
"fb[{ch4}][0]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_Squares,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Framestores 1-4 -> Dual-Link 1-4 -> SDI 1-4
"fb[{ch1}][2]->dlo[{ch1}][0];"
"fb[{ch2}][2]->dlo[{ch2}][0];"
"fb[{ch3}][2]->dlo[{ch3}][0];"
"fb[{ch4}][2]->dlo[{ch4}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];"
"dlo[{ch2}][0]->sdi[{ch2}][0];"
"dlo[{ch2}][1]->sdi[{ch2}][1];"
"dlo[{ch3}][0]->sdi[{ch3}][0];"
"dlo[{ch3}][1]->sdi[{ch3}][1];"
"dlo[{ch4}][0]->sdi[{ch4}][0];"
"dlo[{ch4}][1]->sdi[{ch4}][1];",
}},
{SDIWireFormat::UHD4K_ST425_Dual_3Gb_2SI,
{
NTV2_MODE_DISPLAY,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_2SI,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
// Framestores 1-2 -> TSI Mux 1-2
// -> Dual-Link 1-4 -> SDI 1-4
"fb[{ch1}][2]->tsi[{ch1}][0];"
"fb[{ch1}][3]->tsi[{ch1}][1];"
"fb[{ch2}][2]->tsi[{ch2}][0];"
"fb[{ch2}][3]->tsi[{ch2}][1];"
"tsi[{ch1}][2]->dlo[{ch1}][0];"
"tsi[{ch1}][3]->dlo[{ch2}][0];"
"tsi[{ch2}][2]->dlo[{ch3}][0];"
"tsi[{ch2}][3]->dlo[{ch4}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];"
"dlo[{ch2}][0]->sdi[{ch2}][0];"
"dlo[{ch2}][1]->sdi[{ch2}][1];"
"dlo[{ch3}][0]->sdi[{ch3}][0];"
"dlo[{ch3}][1]->sdi[{ch3}][1];"
"dlo[{ch4}][0]->sdi[{ch4}][0];"
"dlo[{ch4}][1]->sdi[{ch4}][1];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_2SI,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
// Framestores 1-2 -> TSI Mux 1-2
// -> Dual-Link 1-4 -> SDI 1-4
"fb[{ch1}][2]->tsi[{ch1}][0];"
"fb[{ch1}][3]->tsi[{ch1}][1];"
"fb[{ch2}][2]->tsi[{ch2}][0];"
"fb[{ch2}][3]->tsi[{ch2}][1];"
"tsi[{ch1}][2]->dlo[{ch1}][0];"
"tsi[{ch1}][3]->dlo[{ch2}][0];"
"tsi[{ch2}][2]->dlo[{ch3}][0];"
"tsi[{ch2}][3]->dlo[{ch4}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];"
"dlo[{ch2}][0]->sdi[{ch2}][0];"
"dlo[{ch2}][1]->sdi[{ch2}][1];"
"dlo[{ch3}][0]->sdi[{ch3}][0];"
"dlo[{ch3}][1]->sdi[{ch3}][1];"
"dlo[{ch4}][0]->sdi[{ch4}][0];"
"dlo[{ch4}][1]->sdi[{ch4}][1];",
}},
{SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI,
{
NTV2_MODE_DISPLAY,
2,
2,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
true,
false,
false,
true,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_Dual_12G,
{
NTV2_MODE_DISPLAY,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_RGB_Dual_12G,
{
NTV2_MODE_DISPLAY,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_Quad_12G,
{
NTV2_MODE_DISPLAY,
4,
4,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
};

View File

@ -1,466 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<SDIWireFormat, RoutingConfig> kSDIYCbCrCaptureConfigs = {
{
SDIWireFormat::SD_ST352,
{
NTV2_MODE_CAPTURE,
1, // num wires
1, // num framestores
false, // enable 3G output?
false, // enable 6G output?
false, // enable 12G output?
false, // convert 3Gb -> 3Ga input?
false, // convert 3Ga -> 3Gb output?
false, // convert RGB 3Ga output?
false, // enable 3Gb output?
false, // enable 4K Square Division?
false, // enable 8K Square Division?
false, // enable two-sample-interleave?
"sdi[{ch1}][0]->fb[{ch1}][0]", // YCbCr Capture Route
},
},
{SDIWireFormat::HD_720p_ST292,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]",
}},
{SDIWireFormat::HD_1080_ST292,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]",
}},
{SDIWireFormat::HD_1080_ST372_Dual,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]; sdi[{ch2}][0]->fb[{ch2}][0]",
}},
{SDIWireFormat::HD_720p_ST425_3Ga,
{
NTV2_MODE_CAPTURE,
1,
1,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]",
}},
{SDIWireFormat::HD_1080p_ST425_3Ga,
{
NTV2_MODE_CAPTURE,
1,
1,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb_DL,
{
NTV2_MODE_CAPTURE,
1,
1,
true,
false,
false,
true,
true,
false,
true,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]",
}},
{SDIWireFormat::HD_720p_ST425_3Gb,
{
NTV2_MODE_CAPTURE,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]; sdi[{ch1}][1]->fb[{ch2}][0];",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb,
{
NTV2_MODE_CAPTURE,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0]; sdi[{ch1}][1]->fb[{ch2}][0];",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Ga,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch2}][0]->fb[{ch2}][0];",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Gb,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
false,
false,
true,
false,
false,
false,
false,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch2}][0]->fb[{ch2}][0];",
}},
{SDIWireFormat::UHD4K_ST292_Dual_1_5_Squares,
{
NTV2_MODE_CAPTURE,
2,
4,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch1}][1]->fb[{ch2}][0];"
"sdi[{ch2}][0]->fb[{ch3}][0];"
"sdi[{ch2}][1]->fb[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST292_Quad_1_5_Squares,
{
NTV2_MODE_CAPTURE,
4,
4,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Capture
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch2}][0]->fb[{ch2}][0];"
"sdi[{ch3}][0]->fb[{ch3}][0];"
"sdi[{ch4}][0]->fb[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_Squares,
{
NTV2_MODE_CAPTURE,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Capture
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch2}][0]->fb[{ch2}][0];"
"sdi[{ch3}][0]->fb[{ch3}][0];"
"sdi[{ch4}][0]->fb[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_Squares,
{
NTV2_MODE_CAPTURE,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Capture
"sdi[{ch1}][0]->fb[{ch1}][0];"
"sdi[{ch2}][0]->fb[{ch2}][0];"
"sdi[{ch3}][0]->fb[{ch3}][0];"
"sdi[{ch4}][0]->fb[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Dual_3Gb_2SI,
{NTV2_MODE_CAPTURE, 2, 2, true, false, false, false, false, false,
false, false, false, true,
"sdi[{ch1}][0]->tsi[{ch1}][0];"
"sdi[{ch1}][1]->tsi[{ch1}][1];"
"sdi[{ch2}][0]->tsi[{ch2}][0];"
"sdi[{ch2}][1]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->fb[{ch1}][0];"
"tsi[{ch1}][1]->fb[{ch1}][1];"
"tsi[{ch2}][0]->fb[{ch2}][0];"
"tsi[{ch2}][1]->fb[{ch2}][1];"}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_2SI,
{
NTV2_MODE_CAPTURE,
4,
4,
false,
false,
false,
false,
false,
false,
false,
false,
false,
true,
"sdi[{ch1}][0]->tsi[{ch1}][0];"
"sdi[{ch2}][0]->tsi[{ch1}][1];"
"sdi[{ch3}][0]->tsi[{ch2}][0];"
"sdi[{ch4}][0]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->fb[{ch1}][0];"
"tsi[{ch1}][1]->fb[{ch1}][1];"
"tsi[{ch2}][0]->fb[{ch2}][0];"
"tsi[{ch2}][1]->fb[{ch2}][1];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_2SI,
{
NTV2_MODE_CAPTURE,
4,
4,
false,
false,
false,
true,
false,
false,
false,
false,
false,
true,
"sdi[{ch1}][0]->tsi[{ch1}][0];"
"sdi[{ch2}][0]->tsi[{ch1}][1];"
"sdi[{ch3}][0]->tsi[{ch2}][0];"
"sdi[{ch4}][0]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->fb[{ch1}][0];"
"tsi[{ch1}][1]->fb[{ch1}][1];"
"tsi[{ch2}][0]->fb[{ch2}][0];"
"tsi[{ch2}][1]->fb[{ch2}][1];",
}},
{SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
"sdi[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI_Kona5_io4KPlus,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
// Capture
"sdi[{ch1}][0]->tsi[{ch1}][0];"
"sdi[{ch2}][0]->tsi[{ch1}][1];"
"sdi[{ch3}][0]->tsi[{ch2}][0];"
"sdi[{ch4}][0]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->fb[{ch1}][0];"
"tsi[{ch1}][1]->fb[{ch1}][1];"
"tsi[{ch2}][0]->fb[{ch2}][0];"
"tsi[{ch2}][1]->fb[{ch2}][1];",
}},
{SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
true,
false,
false,
true,
false,
false,
false,
true,
"sdi[{ch1}][0]->fb[{ch1}][0];",
}},
{SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI_Kona5_io4KPlus,
{
NTV2_MODE_CAPTURE,
1,
1,
false,
false,
true,
false,
false,
true,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_Dual_12G,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_RGB_Dual_12G,
{
NTV2_MODE_CAPTURE,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_Quad_12G,
{
NTV2_MODE_CAPTURE,
4,
4,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
};

View File

@ -1,486 +0,0 @@
#pragma once
#include "../aja-routing.hpp"
static inline const std::map<SDIWireFormat, RoutingConfig> kSDIYCbCrDisplayConfigs = {
{
SDIWireFormat::SD_ST352,
{
NTV2_MODE_DISPLAY,
1, // num wires
1, // num framestores
false, // enable 3G output?
false, // enable 6G output?
false, // enable 12G output?
false, // convert 3Gb -> 3Ga input?
false, // convert 3Ga -> 3Gb output?
false, // convert RGB 3Ga output?
false, // enable 3Gb output?
false, // enable 4K Square Division?
false, // enable 8K Square Division?
false, // enable two-sample-interleave?
"fb[{ch1}][0]->sdi[{ch1}][0]", // YCbCr Output Route
},
},
{SDIWireFormat::HD_720p_ST292,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0]",
}},
{SDIWireFormat::HD_1080_ST292,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0]",
}},
{SDIWireFormat::HD_1080_ST372_Dual,
{
NTV2_MODE_DISPLAY,
2,
2,
false,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch2}][0]->sdi[{ch2}][0]",
}},
{SDIWireFormat::HD_720p_ST425_3Ga,
{
NTV2_MODE_DISPLAY,
1,
1,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0]",
}},
{SDIWireFormat::HD_1080p_ST425_3Ga,
{
NTV2_MODE_DISPLAY,
1,
1,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0]",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb_DL,
{
NTV2_MODE_DISPLAY,
1,
1,
true,
false,
false,
true,
true,
false,
true,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0]",
}},
{SDIWireFormat::HD_720p_ST425_3Gb,
{
NTV2_MODE_DISPLAY,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0]; fb[{ch2}][0]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080p_ST425_3Gb,
{
NTV2_MODE_DISPLAY,
1,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0]; fb[{ch2}][0]->sdi[{ch1}][1];",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Ga,
{
NTV2_MODE_DISPLAY,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"",
}},
{SDIWireFormat::HD_1080p_ST425_Dual_3Gb,
{
NTV2_MODE_DISPLAY,
2,
2,
true,
false,
false,
false,
false,
false,
false,
false,
false,
false,
"",
}},
{SDIWireFormat::UHD4K_ST292_Dual_1_5_Squares,
{
NTV2_MODE_DISPLAY,
2,
4,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch2}][0]->sdi[{ch1}][1];"
"fb[{ch3}][0]->sdi[{ch2}][0];"
"fb[{ch4}][0]->sdi[{ch2}][1];",
}},
{SDIWireFormat::UHD4K_ST292_Quad_1_5_Squares,
{
NTV2_MODE_DISPLAY,
4,
4,
false,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Playout
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch2}][0]->sdi[{ch2}][0];"
"fb[{ch3}][0]->sdi[{ch3}][0];"
"fb[{ch4}][0]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_Squares,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Playout
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch2}][0]->sdi[{ch2}][0];"
"fb[{ch3}][0]->sdi[{ch3}][0];"
"fb[{ch4}][0]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_Squares,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
false,
true,
false,
false,
// Playout
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch2}][0]->sdi[{ch2}][0];"
"fb[{ch3}][0]->sdi[{ch3}][0];"
"fb[{ch4}][0]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Dual_3Gb_2SI,
{
NTV2_MODE_DISPLAY,
2,
2,
true,
false,
false,
false,
false,
false,
true,
false,
false,
true,
"fb[{ch1}][0]->tsi[{ch1}][0];"
"fb[{ch1}][1]->tsi[{ch1}][1];"
"fb[{ch2}][0]->tsi[{ch2}][0];"
"fb[{ch2}][1]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->sdi[{ch1}][0];"
"tsi[{ch1}][1]->sdi[{ch1}][1];"
"tsi[{ch2}][0]->sdi[{ch2}][0];"
"tsi[{ch2}][1]->sdi[{ch2}][1];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Ga_2SI,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
false,
false,
false,
true,
"fb[{ch1}][0]->tsi[{ch1}][0];"
"fb[{ch1}][1]->tsi[{ch1}][1];"
"fb[{ch2}][0]->tsi[{ch2}][0];"
"fb[{ch2}][1]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->sdi[{ch1}][0];"
"tsi[{ch1}][1]->sdi[{ch2}][0];"
"tsi[{ch2}][0]->sdi[{ch3}][0];"
"tsi[{ch2}][1]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST425_Quad_3Gb_2SI,
{
NTV2_MODE_DISPLAY,
4,
4,
true,
false,
false,
false,
false,
false,
true,
false,
false,
true,
"fb[{ch1}][0]->tsi[{ch1}][0];"
"fb[{ch1}][1]->tsi[{ch1}][1];"
"fb[{ch2}][0]->tsi[{ch2}][0];"
"fb[{ch2}][1]->tsi[{ch2}][1];"
"tsi[{ch1}][0]->sdi[{ch1}][0];"
"tsi[{ch1}][1]->sdi[{ch2}][0];"
"tsi[{ch2}][0]->sdi[{ch3}][0];"
"tsi[{ch2}][1]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
"fb[{ch1}][0]->sdi[{ch1}][0];",
}},
{SDIWireFormat::UHD4K_ST2018_6G_Squares_2SI_Kona5_io4KPlus,
{
NTV2_MODE_DISPLAY,
2,
2,
false,
true,
false,
false,
false,
false,
false,
false,
false,
true,
// Playout
"fb[{ch3}][0]->tsi[{ch3}][0];"
"fb[{ch3}][1]->tsi[{ch3}][1];"
"fb[{ch4}][0]->tsi[{ch4}][0];"
"fb[{ch4}][1]->tsi[{ch4}][1];"
"tsi[{ch3}][0]->sdi[{ch1}][0];"
"tsi[{ch3}][1]->sdi[{ch2}][0];"
"tsi[{ch4}][0]->sdi[{ch3}][0];"
"tsi[{ch4}][1]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
true,
false,
false,
true,
false,
false,
false,
true,
"fb[{ch1}][0]->sdi[{ch1}][0];",
}},
{SDIWireFormat::UHD4K_ST2018_12G_Squares_2SI_Kona5_io4KPlus,
{
NTV2_MODE_DISPLAY,
1,
1,
false,
false,
true,
false,
false,
true,
false,
false,
false,
true,
// Playout
"fb[{ch3}][0]->tsi[{ch3}][0];"
"fb[{ch3}][1]->tsi[{ch3}][1];"
"fb[{ch4}][0]->tsi[{ch4}][0];"
"fb[{ch4}][1]->tsi[{ch4}][1];"
"tsi[{ch3}][0]->sdi[{ch1}][0];"
"tsi[{ch3}][1]->sdi[{ch2}][0];"
"tsi[{ch4}][0]->sdi[{ch3}][0];"
"tsi[{ch4}][1]->sdi[{ch4}][0];",
}},
{SDIWireFormat::UHD28K_ST2082_Dual_12G,
{
NTV2_MODE_DISPLAY,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_RGB_Dual_12G,
{
NTV2_MODE_DISPLAY,
2,
2,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
{SDIWireFormat::UHD28K_ST2082_Quad_12G,
{
NTV2_MODE_DISPLAY,
4,
4,
false,
false,
true,
false,
false,
false,
false,
false,
false,
true,
"",
}},
};