aja: Re-work HDMI routing and add missing presets

This commit is contained in:
Paul Hindt 2022-01-27 00:18:07 -08:00 committed by Colin Edwards
parent 4650cf4574
commit eafe588bd3
9 changed files with 431 additions and 148 deletions

View File

@ -987,6 +987,17 @@ bool IsIOSelectionSDI(IOSelection io)
return false; return false;
} }
bool IsIOSelectionHDMI(IOSelection io)
{
if (io == IOSelection::HDMI1 || io == IOSelection::HDMI2 ||
io == IOSelection::HDMI3 || io == IOSelection::HDMI4 ||
io == IOSelection::HDMIMonitorIn ||
io == IOSelection::HDMIMonitorOut) {
return true;
}
return false;
}
std::string MakeCardID(CNTV2Card &card) std::string MakeCardID(CNTV2Card &card)
{ {
std::string cardID; std::string cardID;

View File

@ -97,6 +97,7 @@ extern bool IsSDITwoWireIOSelection(IOSelection io);
extern bool IsSDIFourWireIOSelection(IOSelection io); extern bool IsSDIFourWireIOSelection(IOSelection io);
extern bool IsMonitorOutputSelection(NTV2DeviceID id, IOSelection io); extern bool IsMonitorOutputSelection(NTV2DeviceID id, IOSelection io);
extern bool IsIOSelectionSDI(IOSelection io); extern bool IsIOSelectionSDI(IOSelection io);
extern bool IsIOSelectionHDMI(IOSelection io);
extern std::string MakeCardID(CNTV2Card &card); extern std::string MakeCardID(CNTV2Card &card);

View File

@ -72,16 +72,10 @@ enum class RasterDefinition {
}; };
enum class HDMIWireFormat { enum class HDMIWireFormat {
SD_HDMI = 0, SD_HD_YCBCR = 0,
HD_YCBCR_LFR = 1, SD_HD_RGB = 1,
HD_YCBCR_HFR = 2, UHD_4K_YCBCR = 2,
HD_RGB_LFR = 3, UHD_4K_RGB = 3,
HD_RGB_HFR = 4,
UHD_4K_YCBCR_LFR = 5,
UHD_4K_YCBCR_HFR = 6,
UHD_4K_RGB_LFR = 7,
UHD_4K_RGB_HFR = 8,
TTAP_PRO = 9,
Unknown Unknown
}; };

View File

@ -1076,8 +1076,9 @@ static bool aja_output_start(void *data)
} }
// Configures crosspoint routing on AJA card // Configures crosspoint routing on AJA card
NTV2XptConnections xpt_cnx;
if (!aja::Routing::ConfigureOutputRoute(outputProps, NTV2_MODE_DISPLAY, if (!aja::Routing::ConfigureOutputRoute(outputProps, NTV2_MODE_DISPLAY,
card)) { card, xpt_cnx)) {
blog(LOG_ERROR, blog(LOG_ERROR,
"aja_output_start: Error configuring output route!"); "aja_output_start: Error configuring output route!");
return false; return false;

View File

@ -40,7 +40,7 @@ void RoutingConfigurator::build_preset_table()
ConnectionKind::HDMI, ConnectionKind::HDMI,
NTV2_MODE_CAPTURE, NTV2_MODE_CAPTURE,
RasterDefinition::HD, RasterDefinition::HD,
HDMIWireFormat::HD_RGB_LFR, HDMIWireFormat::SD_HD_RGB,
VPIDStandard_Unknown, VPIDStandard_Unknown,
1, 1,
1, 1,
@ -49,6 +49,41 @@ void RoutingConfigurator::build_preset_table()
{}, {},
true, true,
false}}, false}},
{"HDMI_HD_RGB_HFR_RGB_Capture",
{"HDMI_HD_RGB_HFR_RGB_Capture",
ConnectionKind::HDMI,
NTV2_MODE_CAPTURE,
RasterDefinition::HD,
HDMIWireFormat::SD_HD_RGB,
VPIDStandard_Unknown,
1,
1,
0,
"hdmi[{ch1}][0]->fb[{ch1}][0];",
{},
true,
false}},
{"HDMI_UHD_4K_RGB_Capture (io4K+)",
{"HDMI_UHD_4K_RGB_Capture (io4K+)",
ConnectionKind::HDMI,
NTV2_MODE_CAPTURE,
RasterDefinition::UHD_4K,
HDMIWireFormat::UHD_4K_RGB,
VPIDStandard_Unknown,
1,
2,
kEnable4KTSI,
"hdmi[{ch1}][4]->tsi[{ch1}][0];"
"hdmi[{ch1}][5]->tsi[{ch1}][1];"
"hdmi[{ch1}][6]->tsi[{ch2}][0];"
"hdmi[{ch1}][7]->tsi[{ch2}][1];"
"tsi[{ch1}][2]->fb[{ch1}][0];"
"tsi[{ch1}][3]->fb[{ch1}][1];"
"tsi[{ch2}][2]->fb[{ch2}][0];"
"tsi[{ch2}][3]->fb[{ch2}][1];",
{DEVICE_ID_IO4KPLUS},
true,
false}},
/* /*
* HDMI RGB Display * HDMI RGB Display
*/ */
@ -57,7 +92,7 @@ void RoutingConfigurator::build_preset_table()
ConnectionKind::HDMI, ConnectionKind::HDMI,
NTV2_MODE_DISPLAY, NTV2_MODE_DISPLAY,
RasterDefinition::HD, RasterDefinition::HD,
HDMIWireFormat::HD_RGB_LFR, HDMIWireFormat::SD_HD_RGB,
VPIDStandard_Unknown, VPIDStandard_Unknown,
1, 1,
1, 1,
@ -66,30 +101,63 @@ void RoutingConfigurator::build_preset_table()
{}, {},
true, true,
false}}, false}},
{"HDMI_HD_RGB_LFR_RGB_Display (TTap Pro)", {"HDMI_HD_RGB_HFR_RGB_Display",
{"HDMI_HD_RGB_LFR_RGB_Display (TTap Pro)", {"HDMI_HD_RGB_HFR_RGB_Display",
ConnectionKind::HDMI, ConnectionKind::HDMI,
NTV2_MODE_DISPLAY, NTV2_MODE_DISPLAY,
RasterDefinition::HD, RasterDefinition::HD,
HDMIWireFormat::HD_RGB_LFR, HDMIWireFormat::SD_HD_RGB,
VPIDStandard_Unknown, VPIDStandard_Unknown,
1, 1,
1, 1,
0, 0,
"fb[{ch1}][0]->sdi[{ch1}][0];" "fb[{ch1}][0]->hdmi[0][0];",
"fb[{ch1}][0]->hdmi[{ch1}][0];", {},
true,
false}},
{"HDMI_RGB_LFR_RGB_Display (TTap Pro)",
{"HDMI_RGB_LFR_RGB_Display (TTap Pro)",
ConnectionKind::HDMI,
NTV2_MODE_DISPLAY,
RasterDefinition::HD,
HDMIWireFormat::SD_HD_RGB,
VPIDStandard_Unknown,
1,
1,
kEnable3GOut,
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];"
"fb[{ch1}][2]->hdmi[{ch1}][0];",
{DEVICE_ID_TTAP_PRO},
true,
false}},
{"HDMI_RGB_HFR_RGB_Display (TTap Pro)",
{"HDMI_RGB_HFR_RGB_Display (TTap Pro)",
ConnectionKind::HDMI,
NTV2_MODE_DISPLAY,
RasterDefinition::HD,
HDMIWireFormat::SD_HD_RGB,
VPIDStandard_Unknown,
1,
1,
kConvert3GaRGBOut,
"fb[{ch1}][2]->dlo[{ch1}][0];"
"dlo[{ch1}][0]->sdi[{ch1}][0];"
"dlo[{ch1}][1]->sdi[{ch1}][1];"
"fb[{ch1}][2]->hdmi[{ch1}][0];",
{DEVICE_ID_TTAP_PRO}, {DEVICE_ID_TTAP_PRO},
true, true,
false}}, false}},
/* /*
* HDMI YCbCr Capture * HDMI YCbCr Capture
*/ */
{"HDMI_HD_YCBCR_LFR_YCbCr_Capture", {"HDMI_HD_LFR_YCbCr_Capture",
{"HDMI_HD_YCBCR_LFR_YCbCr_Capture", {"HDMI_HD_LFR_YCbCr_Capture",
ConnectionKind::HDMI, ConnectionKind::HDMI,
NTV2_MODE_CAPTURE, NTV2_MODE_CAPTURE,
RasterDefinition::HD, RasterDefinition::HD,
HDMIWireFormat::HD_YCBCR_LFR, HDMIWireFormat::SD_HD_YCBCR,
VPIDStandard_Unknown, VPIDStandard_Unknown,
1, 1,
1, 1,
@ -98,15 +166,36 @@ void RoutingConfigurator::build_preset_table()
{}, {},
false, false,
false}}, false}},
{"HDMI_UHD_4K_YCbCr_Capture (io4K+)",
{"HDMI_UHD_4K_YCbCr_Capture (io4K+)",
ConnectionKind::HDMI,
NTV2_MODE_CAPTURE,
RasterDefinition::UHD_4K,
HDMIWireFormat::UHD_4K_YCBCR,
VPIDStandard_Unknown,
1,
2,
kEnable4KTSI,
"hdmi[{ch1}][0]->tsi[{ch1}][0];"
"hdmi[{ch1}][1]->tsi[{ch1}][1];"
"hdmi[{ch1}][2]->tsi[{ch2}][0];"
"hdmi[{ch1}][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];",
{DEVICE_ID_IO4KPLUS},
false,
false}},
/* /*
* HDMI YCbCr Display * HDMI YCbCr Display
*/ */
{"HDMI_HD_YCBCR_LFR_YCbCr_Display", {"HDMI_HD_LFR_YCbCr_Display",
{"HDMI_HD_YCBCR_LFR_YCbCr_Display", {"HDMI_HD_LFR_YCbCr_Display",
ConnectionKind::HDMI, ConnectionKind::HDMI,
NTV2_MODE_DISPLAY, NTV2_MODE_DISPLAY,
RasterDefinition::HD, RasterDefinition::HD,
HDMIWireFormat::HD_YCBCR_LFR, HDMIWireFormat::SD_HD_YCBCR,
VPIDStandard_Unknown, VPIDStandard_Unknown,
1, 1,
1, 1,
@ -115,12 +204,33 @@ void RoutingConfigurator::build_preset_table()
{}, {},
false, false,
false}}, false}},
{"HDMI_HD_YCBCR_LFR_YCbCr_Display (TTap Pro)", {"HDMI_UHD_4K_LFR_YCbCr_Display",
{"HDMI_HD_YCBCR_LFR_YCbCr_Display (TTap Pro)", {"HDMI_UHD_4K_LFR_YCbCr_Display",
ConnectionKind::HDMI,
NTV2_MODE_DISPLAY,
RasterDefinition::UHD_4K,
HDMIWireFormat::UHD_4K_YCBCR,
VPIDStandard_Unknown,
1,
2,
kEnable4KTSI,
"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[{ch1}][0];"
"tsi[{ch1}][1]->hdmi[{ch1}][1];"
"tsi[{ch2}][0]->hdmi[{ch1}][2];"
"tsi[{ch2}][1]->hdmi[{ch1}][3];",
{},
false,
false}},
{"HDMI_HD_LFR_YCbCr_Display (TTap Pro)",
{"HDMI_HD_LFR_YCbCr_Display (TTap Pro)",
ConnectionKind::HDMI, ConnectionKind::HDMI,
NTV2_MODE_DISPLAY, NTV2_MODE_DISPLAY,
RasterDefinition::HD, RasterDefinition::HD,
HDMIWireFormat::HD_YCBCR_LFR, HDMIWireFormat::SD_HD_YCBCR,
VPIDStandard_Unknown, VPIDStandard_Unknown,
1, 1,
1, 1,
@ -130,6 +240,51 @@ void RoutingConfigurator::build_preset_table()
{DEVICE_ID_TTAP_PRO}, {DEVICE_ID_TTAP_PRO},
false, false,
false}}, false}},
{"HDMI_HD_HFR_YCbCr_Display (TTap Pro)",
{"HDMI_HD_HFR_YCbCr_Display (TTap Pro)",
ConnectionKind::HDMI,
NTV2_MODE_DISPLAY,
RasterDefinition::HD,
HDMIWireFormat::SD_HD_YCBCR,
VPIDStandard_Unknown,
1,
1,
kEnable3GOut,
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch1}][0]->hdmi[{ch1}][0];",
{DEVICE_ID_TTAP_PRO},
false,
false}},
{"HDMI_UHD_4K_LFR_YCbCr_Display (TTap Pro)",
{"HDMI_UHD_4K_LFR_YCbCr_Display (TTap Pro)",
ConnectionKind::HDMI,
NTV2_MODE_DISPLAY,
RasterDefinition::UHD_4K,
HDMIWireFormat::UHD_4K_YCBCR,
VPIDStandard_Unknown,
1,
1,
kEnable4KTSI | kEnable6GOut,
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch1}][0]->hdmi[{ch1}][0];",
{DEVICE_ID_TTAP_PRO},
false,
false}},
{"HDMI_UHD_4K_HFR_YCbCr_Display (TTap Pro)",
{"HDMI_UHD_4K_HFR_YCbCr_Display (TTap Pro)",
ConnectionKind::HDMI,
NTV2_MODE_DISPLAY,
RasterDefinition::UHD_4K,
HDMIWireFormat::UHD_4K_YCBCR,
VPIDStandard_Unknown,
1,
1,
kEnable4KTSI | kEnable12GOut,
"fb[{ch1}][0]->sdi[{ch1}][0];"
"fb[{ch1}][0]->hdmi[{ch1}][0];",
{DEVICE_ID_TTAP_PRO},
false,
false}},
/* /*
* SDI RGB Capture * SDI RGB Capture
*/ */
@ -299,6 +454,32 @@ void RoutingConfigurator::build_preset_table()
{}, {},
true, true,
false}}, false}},
{"UHD4K_ST425_Quad_3Ga_Squares_RGB_Capture",
{"UHD4K_ST425_Quad_3Ga_Squares_RGB_Capture",
ConnectionKind::SDI,
NTV2_MODE_CAPTURE,
RasterDefinition::UHD_4K,
HDMIWireFormat::Unknown,
VPIDStandard_1080_3Ga,
4,
4,
kEnable4KSquares,
// SDIs -> Dual-Links
"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];" // Dual-Links -> Framestores
"dli[{ch1}][0]->fb[{ch1}][0];"
"dli[{ch2}][0]->fb[{ch2}][0];"
"dli[{ch3}][0]->fb[{ch3}][0];"
"dli[{ch4}][0]->fb[{ch4}][0];",
{},
true,
false}},
{"UHD4K_ST425_Quad_3Gb_Squares_RGB_Capture", {"UHD4K_ST425_Quad_3Gb_Squares_RGB_Capture",
{"UHD4K_ST425_Quad_3Gb_Squares_RGB_Capture", {"UHD4K_ST425_Quad_3Gb_Squares_RGB_Capture",
ConnectionKind::SDI, ConnectionKind::SDI,
@ -334,7 +515,7 @@ void RoutingConfigurator::build_preset_table()
VPIDStandard_2160_QuadLink_3Ga, VPIDStandard_2160_QuadLink_3Ga,
4, 4,
4, 4,
(kEnable3GOut | kEnable4KTSI), kEnable4KTSI,
// SDIs -> Dual-Links // SDIs -> Dual-Links
"sdi[{ch1}][0]->dli[{ch1}][0];" "sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];" "sdi[{ch1}][1]->dli[{ch1}][1];"
@ -385,18 +566,99 @@ void RoutingConfigurator::build_preset_table()
{}, {},
true, true,
false}}, false}},
// TODO(paulh): Find out the proper settings for this route
// { "UHD4K_ST2018_6G_Squares_2SI_RGB_Capture", { /////////////////////////////////
// "UHD4K_ST2018_6G_Squares_2SI_RGB_Capture", {"UHD4K_ST2018_6G_Squares_2SI_RGB_Capture",
// ConnectionKind::SDI, {"UHD4K_ST2018_6G_Squares_2SI_RGB_Capture",
// NTV2_MODE_CAPTURE, ConnectionKind::SDI,
// 2, 2, NTV2_MODE_CAPTURE,
// kEnable6GOut, RasterDefinition::UHD_4K,
// "", HDMIWireFormat::Unknown,
// {}, VPIDStandard_2160_Single_6Gb,
// RasterDefinition::UHD_4K, 1,
// HDMIWireFormat::Unknown, 1,
// VPIDStandard_2160_Single_6Gb, true, false}}, kEnable4KTSI,
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
{},
true,
false}},
{"UHD4K_ST2018_6G_Squares_2SI_RGB_Capture (Kona5/io4K+)",
{"UHD4K_ST2018_6G_Squares_2SI_RGB_Capture (Kona5/io4K+)",
ConnectionKind::SDI,
NTV2_MODE_CAPTURE,
RasterDefinition::UHD_4K,
HDMIWireFormat::Unknown,
VPIDStandard_2160_Single_6Gb,
4,
4,
kEnable4KTSI,
"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}][2]->fb[{ch1}][0];"
"tsi[{ch1}][3]->fb[{ch1}][1];"
"tsi[{ch2}][2]->fb[{ch2}][0];"
"tsi[{ch2}][3]->fb[{ch2}][1];",
{DEVICE_ID_KONA5, DEVICE_ID_IO4KPLUS},
true,
true}},
{"UHD4K_ST2018_12G_Squares_2SI_RGB_Capture",
{"UHD4K_ST2018_12G_Squares_2SI_RGB_Capture",
ConnectionKind::SDI,
NTV2_MODE_CAPTURE,
RasterDefinition::UHD_4K,
HDMIWireFormat::Unknown,
VPIDStandard_2160_Single_12Gb,
1,
1,
kEnable4KTSI,
"sdi[{ch1}][0]->dli[{ch1}][0];"
"sdi[{ch1}][1]->dli[{ch1}][1];"
"dli[{ch1}][0]->fb[{ch1}][0];",
{},
true,
false}},
{"UHD4K_ST2018_12G_Squares_2SI_RGB_Capture (Kona5/io4K+)",
{"UHD4K_ST2018_12G_Squares_2SI_RGB_Capture (Kona5/io4K+)",
ConnectionKind::SDI,
NTV2_MODE_CAPTURE,
RasterDefinition::UHD_4K,
HDMIWireFormat::Unknown,
VPIDStandard_2160_Single_12Gb,
4,
4,
kEnable4KTSI,
"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}][2]->fb[{ch1}][0];"
"tsi[{ch1}][3]->fb[{ch1}][1];"
"tsi[{ch2}][2]->fb[{ch2}][0];"
"tsi[{ch2}][3]->fb[{ch2}][1];",
{DEVICE_ID_KONA5, DEVICE_ID_IO4KPLUS},
true,
true}},
/////////////////////////////////
/* /*
* SDI RGB Display * SDI RGB Display
*/ */
@ -1496,6 +1758,7 @@ bool RoutingConfigurator::FindFirstPreset(ConnectionKind kind, NTV2DeviceID id,
NTV2Mode mode, NTV2VideoFormat vf, NTV2Mode mode, NTV2VideoFormat vf,
NTV2PixelFormat pf, NTV2PixelFormat pf,
VPIDStandard standard, VPIDStandard standard,
HDMIWireFormat hwf,
RoutingPreset &preset) RoutingPreset &preset)
{ {
if (NTV2DeviceCanDoVideoFormat(id, vf) && if (NTV2DeviceCanDoVideoFormat(id, vf) &&
@ -1507,23 +1770,30 @@ bool RoutingConfigurator::FindFirstPreset(ConnectionKind kind, NTV2DeviceID id,
if (p.second.kind == kind && p.second.mode == mode && if (p.second.kind == kind && p.second.mode == mode &&
p.second.raster_def == rd && p.second.raster_def == rd &&
p.second.is_rgb == is_rgb && p.second.is_rgb == is_rgb &&
p.second.vpid_standard == standard) { p.second.vpid_standard == standard &&
p.second.hdmi_wire_format == hwf) {
query.push_back(p); query.push_back(p);
} }
} }
RoutingPresets device_presets; RoutingPresets device_presets;
for (const auto &q : query) { RoutingPresets non_device_presets;
for (auto &q : query) {
if (q.second.device_ids.size() == 0)
non_device_presets.push_back(q.second);
for (const auto &device_id : q.second.device_ids) { for (const auto &device_id : q.second.device_ids) {
if (device_id == id) if (device_id == id) {
device_presets.push_back(q.second); device_presets.push_back(q.second);
break;
}
} }
} }
if (device_presets.size() > 0) { if (device_presets.size() > 0) {
preset = device_presets.at(0); preset = device_presets.at(0);
return true; return true;
} }
if (query.size() > 0) { if (non_device_presets.size() > 0) {
preset = query.at(0).second; preset = non_device_presets.at(0);
return true; return true;
} }
} }

View File

@ -39,7 +39,7 @@ public:
bool FindFirstPreset(ConnectionKind kind, NTV2DeviceID id, bool FindFirstPreset(ConnectionKind kind, NTV2DeviceID id,
NTV2Mode mode, NTV2VideoFormat vf, NTV2Mode mode, NTV2VideoFormat vf,
NTV2PixelFormat pf, VPIDStandard standard, NTV2PixelFormat pf, VPIDStandard standard,
RoutingPreset &preset); HDMIWireFormat hwf, RoutingPreset &preset);
private: private:
void build_preset_table(); void build_preset_table();

View File

@ -6,6 +6,7 @@
#include <ajabase/common/common.h> #include <ajabase/common/common.h>
#include <ajantv2/includes/ntv2card.h> #include <ajantv2/includes/ntv2card.h>
#include <ajantv2/includes/ntv2devicefeatures.h> #include <ajantv2/includes/ntv2devicefeatures.h>
#include <ajantv2/includes/ntv2utils.h>
#include <obs-module.h> #include <obs-module.h>
@ -205,7 +206,7 @@ void Routing::StopSourceAudio(const SourceProps &props, CNTV2Card *card)
} }
bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode, bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
CNTV2Card *card) CNTV2Card *card, NTV2XptConnections &cnx)
{ {
if (!card) if (!card)
return false; return false;
@ -213,13 +214,18 @@ bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
bool found_preset = false; bool found_preset = false;
auto deviceID = props.deviceID; auto deviceID = props.deviceID;
NTV2VideoFormat vf = props.videoFormat; NTV2VideoFormat vf = props.videoFormat;
bool is_hfr = NTV2_IS_HIGH_NTV2FrameRate(
GetNTV2FrameRateFromVideoFormat(props.videoFormat));
auto init_src = props.InitialInputSource(); auto init_src = props.InitialInputSource();
auto init_channel = props.Channel(); auto init_channel = props.Channel();
RoutingConfigurator rc; RoutingConfigurator rc;
RoutingPreset rp; RoutingPreset rp;
ConnectionKind kind = ConnectionKind::Unknown;
VPIDStandard vpidStandard = VPIDStandard_Unknown;
HDMIWireFormat hwf = HDMIWireFormat::Unknown;
if (NTV2_INPUT_SOURCE_IS_SDI(init_src)) { if (NTV2_INPUT_SOURCE_IS_SDI(init_src)) {
auto vpidStandard = VPIDStandard_Unknown; kind = ConnectionKind::SDI;
if (props.autoDetect) { if (props.autoDetect) {
auto vpidList = props.vpids; auto vpidList = props.vpids;
if (vpidList.size() > 0) if (vpidList.size() > 0)
@ -231,40 +237,58 @@ bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
props.pixelFormat, props.sdiTransport, props.pixelFormat, props.sdiTransport,
props.sdi4kTransport); props.sdi4kTransport);
} }
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)) { } else if (NTV2_INPUT_SOURCE_IS_HDMI(init_src)) {
HDMIWireFormat hwf = HDMIWireFormat::Unknown; kind = ConnectionKind::HDMI;
if (NTV2_IS_FBF_RGB(props.pixelFormat)) { if (NTV2_IS_FBF_RGB(props.pixelFormat)) {
if (NTV2_IS_HD_VIDEO_FORMAT(vf)) if (NTV2_IS_HD_VIDEO_FORMAT(vf)) {
hwf = HDMIWireFormat::HD_RGB_LFR; hwf = HDMIWireFormat::SD_HD_RGB;
} else if (NTV2_IS_4K_VIDEO_FORMAT(vf)) {
hwf = HDMIWireFormat::UHD_4K_RGB;
}
} else { } else {
if (NTV2_IS_HD_VIDEO_FORMAT(vf)) if (NTV2_IS_HD_VIDEO_FORMAT(vf)) {
hwf = HDMIWireFormat::HD_YCBCR_LFR; hwf = HDMIWireFormat::SD_HD_YCBCR;
else if (NTV2_IS_4K_VIDEO_FORMAT(vf)) } else if (NTV2_IS_4K_VIDEO_FORMAT(vf)) {
hwf = HDMIWireFormat::UHD_4K_YCBCR_LFR; hwf = HDMIWireFormat::UHD_4K_YCBCR;
} }
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;
} }
} else {
blog(LOG_WARNING,
"Unsupported connection kind. SDI and HDMI only!");
return false;
}
if (!rc.FindFirstPreset(kind, props.deviceID, NTV2_MODE_CAPTURE, vf,
props.pixelFormat, vpidStandard, hwf, rp)) {
blog(LOG_WARNING, "No SDI capture routing preset found!");
return false;
} }
LogRoutingPreset(rp); LogRoutingPreset(rp);
// Substitute channel placeholders for actual indices // Substitute channel placeholders for actual indices
std::string route_string = rp.route_string; std::string route_string = rp.route_string;
// Channel-substitution for widgets associated with framestore channel(s)
ULWord start_framestore_index =
GetIndexForNTV2Channel(props.Framestore());
const std::vector<std::string> fs_associated = {"fb", "tsi", "dli"};
for (ULWord c = 0; c < NTV2_MAX_NUM_CHANNELS; c++) {
for (const auto &name : fs_associated) {
std::string placeholder = std::string(
name + "[{ch" + aja::to_string(c + 1) + "}]");
route_string = aja::replace(
route_string, placeholder,
name + "[" +
aja::to_string(start_framestore_index) +
"]");
}
start_framestore_index++;
}
// Replace other channel placeholders
ULWord start_channel_index = GetIndexForNTV2Channel(init_channel); ULWord start_channel_index = GetIndexForNTV2Channel(init_channel);
for (ULWord c = 0; c < 8; c++) { for (ULWord c = 0; c < NTV2_MAX_NUM_CHANNELS; c++) {
std::string channel_placeholder = std::string channel_placeholder =
std::string("{ch" + aja::to_string(c + 1) + "}"); std::string("{ch" + aja::to_string(c + 1) + "}");
route_string = route_string =
@ -272,7 +296,6 @@ bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
aja::to_string(start_channel_index++)); aja::to_string(start_channel_index++));
} }
NTV2XptConnections cnx;
if (!ParseRouteString(route_string, cnx)) if (!ParseRouteString(route_string, cnx))
return false; return false;
@ -299,9 +322,18 @@ bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
(UWord)i, rp.flags & kConvert3GaRGBOut); (UWord)i, rp.flags & kConvert3GaRGBOut);
} }
// Apply HDMI settings
if (aja::IsIOSelectionHDMI(props.ioSelect)) {
if (NTV2_IS_4K_VIDEO_FORMAT(props.videoFormat))
card->SetHDMIV2Mode(NTV2_HDMI_V2_4K_CAPTURE);
else
card->SetHDMIV2Mode(NTV2_HDMI_V2_HDSD_BIDIRECTIONAL);
}
// Apply Framestore settings // Apply Framestore settings
for (uint32_t i = (uint32_t)start_channel_index; start_framestore_index = GetIndexForNTV2Channel(props.Framestore());
i < (start_channel_index + rp.num_framestores); i++) { for (uint32_t i = (uint32_t)start_framestore_index;
i < (start_framestore_index + rp.num_framestores); i++) {
NTV2Channel channel = GetNTV2ChannelForIndex(i); NTV2Channel channel = GetNTV2ChannelForIndex(i);
card->EnableChannel(channel); card->EnableChannel(channel);
card->SetMode(channel, mode); card->SetMode(channel, mode);
@ -318,13 +350,15 @@ bool Routing::ConfigureSourceRoute(const SourceProps &props, NTV2Mode mode,
} }
bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode, bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
CNTV2Card *card) CNTV2Card *card, NTV2XptConnections &cnx)
{ {
if (!card) if (!card)
return false; return false;
bool found_preset = false; bool found_preset = false;
auto deviceID = props.deviceID; auto deviceID = props.deviceID;
bool is_hfr = NTV2_IS_HIGH_NTV2FrameRate(
GetNTV2FrameRateFromVideoFormat(props.videoFormat));
NTV2OutputDestinations outputDests; NTV2OutputDestinations outputDests;
aja::IOSelectionToOutputDests(props.ioSelect, outputDests); aja::IOSelectionToOutputDests(props.ioSelect, outputDests);
if (outputDests.empty()) { if (outputDests.empty()) {
@ -336,46 +370,43 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
RoutingConfigurator rc; RoutingConfigurator rc;
RoutingPreset rp; RoutingPreset rp;
ConnectionKind kind = ConnectionKind::Unknown;
VPIDStandard vpidStandard = VPIDStandard_Unknown;
HDMIWireFormat hwf = HDMIWireFormat::Unknown;
if (NTV2_OUTPUT_DEST_IS_SDI(init_dest)) { if (NTV2_OUTPUT_DEST_IS_SDI(init_dest)) {
VPIDStandard vpidStandard = DetermineVPIDStandard( kind = ConnectionKind::SDI;
deviceID, props.ioSelect, props.videoFormat, vpidStandard = DetermineVPIDStandard(deviceID, props.ioSelect,
props.pixelFormat, props.sdiTransport, props.videoFormat,
props.sdi4kTransport); props.pixelFormat,
if (!rc.FindFirstPreset(ConnectionKind::SDI, props.deviceID, props.sdiTransport,
NTV2_MODE_DISPLAY, props.videoFormat, props.sdi4kTransport);
props.pixelFormat, vpidStandard, rp)) {
blog(LOG_WARNING,
"No SDI output routing preset found!");
return false;
}
} else if (NTV2_OUTPUT_DEST_IS_HDMI(init_dest)) { } else if (NTV2_OUTPUT_DEST_IS_HDMI(init_dest)) {
HDMIWireFormat hwf = HDMIWireFormat::Unknown; kind = ConnectionKind::HDMI;
// special case devices... hwf = HDMIWireFormat::Unknown;
if (props.deviceID == DEVICE_ID_TTAP_PRO) { if (NTV2_IS_FBF_RGB(props.pixelFormat)) {
hwf = HDMIWireFormat::TTAP_PRO; if (NTV2_IS_HD_VIDEO_FORMAT(props.videoFormat)) {
hwf = HDMIWireFormat::SD_HD_RGB;
} else if (NTV2_IS_4K_VIDEO_FORMAT(props.videoFormat)) {
hwf = HDMIWireFormat::UHD_4K_RGB;
}
} else { } else {
// ...all other devices. if (NTV2_IS_HD_VIDEO_FORMAT(props.videoFormat)) {
if (NTV2_IS_FBF_RGB(props.pixelFormat)) { hwf = HDMIWireFormat::SD_HD_YCBCR;
if (NTV2_IS_HD_VIDEO_FORMAT(props.videoFormat)) } else if (NTV2_IS_4K_VIDEO_FORMAT(props.videoFormat)) {
hwf = HDMIWireFormat::HD_RGB_LFR; hwf = HDMIWireFormat::UHD_4K_YCBCR;
} else {
if (NTV2_IS_HD_VIDEO_FORMAT(
props.videoFormat)) {
hwf = HDMIWireFormat::HD_YCBCR_LFR;
} else if (NTV2_IS_4K_VIDEO_FORMAT(
props.videoFormat)) {
hwf = HDMIWireFormat::UHD_4K_YCBCR_LFR;
}
} }
} }
if (!rc.FindFirstPreset(ConnectionKind::HDMI, props.deviceID, } else {
NTV2_MODE_DISPLAY, props.videoFormat, blog(LOG_WARNING,
props.pixelFormat, VPIDStandard_Unknown, "Unsupported connection kind. SDI and HDMI only!");
rp)) { return false;
blog(LOG_WARNING, }
"No HDMI output routing preset found!");
return false; if (!rc.FindFirstPreset(kind, props.deviceID, NTV2_MODE_DISPLAY,
} props.videoFormat, props.pixelFormat,
vpidStandard, hwf, rp)) {
blog(LOG_WARNING, "No HDMI output routing preset found!");
return false;
} }
LogRoutingPreset(rp); LogRoutingPreset(rp);
@ -384,8 +415,8 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
// Replace framestore channel placeholders // Replace framestore channel placeholders
auto init_channel = NTV2OutputDestinationToChannel(init_dest); auto init_channel = NTV2OutputDestinationToChannel(init_dest);
ULWord start_framestore_index = InitialFramestoreOutputIndex( ULWord start_framestore_index =
deviceID, props.ioSelect, init_channel); GetIndexForNTV2Channel(props.Framestore());
if (rp.verbatim) { if (rp.verbatim) {
// Presets marked "verbatim" must only be routed on the specified channels // Presets marked "verbatim" must only be routed on the specified channels
start_framestore_index = 0; start_framestore_index = 0;
@ -417,14 +448,14 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
aja::to_string(start_channel_index++)); aja::to_string(start_channel_index++));
} }
NTV2XptConnections cnx;
if (!ParseRouteString(route_string, cnx)) if (!ParseRouteString(route_string, cnx))
return false; return false;
card->ApplySignalRoute(cnx, false); card->ApplySignalRoute(cnx, false);
// Apply SDI widget settings // Apply SDI widget settings
if (props.ioSelect != IOSelection::HDMIMonitorOut) { if (props.ioSelect != IOSelection::HDMIMonitorOut ||
props.deviceID == DEVICE_ID_TTAP_PRO) {
start_channel_index = GetIndexForNTV2Channel(init_channel); start_channel_index = GetIndexForNTV2Channel(init_channel);
for (uint32_t i = (uint32_t)start_channel_index; for (uint32_t i = (uint32_t)start_channel_index;
i < (start_channel_index + rp.num_channels); i++) { i < (start_channel_index + rp.num_channels); i++) {
@ -451,8 +482,7 @@ bool Routing::ConfigureOutputRoute(const OutputProps &props, NTV2Mode mode,
} }
// Apply Framestore settings // Apply Framestore settings
start_framestore_index = InitialFramestoreOutputIndex( start_framestore_index = GetIndexForNTV2Channel(props.Framestore());
deviceID, props.ioSelect, init_channel);
if (rp.verbatim) { if (rp.verbatim) {
start_framestore_index = 0; start_framestore_index = 0;
} }
@ -557,29 +587,6 @@ void Routing::ConfigureOutputAudio(const OutputProps &props, CNTV2Card *card)
card->StopAudioOutput(audioSys); 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) void Routing::LogRoutingPreset(const RoutingPreset &rp)
{ {
auto hexStr = [&](uint8_t val) -> std::string { auto hexStr = [&](uint8_t val) -> std::string {

View File

@ -52,15 +52,13 @@ public:
static void StopSourceAudio(const SourceProps &props, CNTV2Card *card); static void StopSourceAudio(const SourceProps &props, CNTV2Card *card);
static bool ConfigureSourceRoute(const SourceProps &props, static bool ConfigureSourceRoute(const SourceProps &props,
NTV2Mode mode, CNTV2Card *card); NTV2Mode mode, CNTV2Card *card,
NTV2XptConnections &cnx);
static bool ConfigureOutputRoute(const OutputProps &props, static bool ConfigureOutputRoute(const OutputProps &props,
NTV2Mode mode, CNTV2Card *card); NTV2Mode mode, CNTV2Card *card,
NTV2XptConnections &cnx);
static void ConfigureOutputAudio(const OutputProps &props, static void ConfigureOutputAudio(const OutputProps &props,
CNTV2Card *card); CNTV2Card *card);
static ULWord InitialFramestoreOutputIndex(NTV2DeviceID deviceID,
IOSelection io,
NTV2Channel init_channel);
static void LogRoutingPreset(const RoutingPreset &rp); static void LogRoutingPreset(const RoutingPreset &rp);
}; };

View File

@ -1023,8 +1023,9 @@ static void aja_source_update(void *data, obs_data_t *settings)
// Change capture format and restart capture thread // Change capture format and restart capture thread
if (!initialized || want_props != ajaSource->GetSourceProps()) { if (!initialized || want_props != ajaSource->GetSourceProps()) {
aja::Routing::ConfigureSourceRoute(want_props, NTV2XptConnections xpt_cnx;
NTV2_MODE_CAPTURE, card); aja::Routing::ConfigureSourceRoute(
want_props, NTV2_MODE_CAPTURE, card, xpt_cnx);
ajaSource->Deactivate(); ajaSource->Deactivate();
initialized = true; initialized = true;
} }