UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
device_state Struct Reference
Collaboration diagram for device_state:
Collaboration graph

Public Member Functions

void check_attributes (struct vidcap_decklink_state *s)
 
bool init (struct vidcap_decklink_state *s, struct tile *tile, BMDAudioConnection audioConnection)
 

Public Attributes

bool audio = false
 
IDeckLink * deckLink = nullptr
 
IDeckLinkProfileAttributes * deckLinkAttributes = nullptr
 
IDeckLinkConfiguration * deckLinkConfiguration = nullptr
 
IDeckLinkInput * deckLinkInput = nullptr
 
unique_ptr< VideoDelegate > delegate
 
string device_id = "0"
 
struct tile * tile = nullptr
 

Detailed Description

Definition at line 169 of file decklink.cpp.

Member Function Documentation

◆ check_attributes()

void device_state::check_attributes ( struct vidcap_decklink_state * s)

Definition at line 1127 of file decklink.cpp.

1128{
1129 if (s->stereo) {
1131 }
1132}
bool bmd_check_stereo_profile(IDeckLink *deckLink)
IDeckLink * deckLink
Definition decklink.cpp:170

References bmd_check_stereo_profile(), deckLink, and vidcap_decklink_state::stereo.

Referenced by init().

Here is the call graph for this function:

◆ init()

bool device_state::init ( struct vidcap_decklink_state * s,
struct tile * tile,
BMDAudioConnection audioConnection )

Definition at line 1135 of file decklink.cpp.

1136{
1137 IDeckLinkDisplayModeIterator* displayModeIterator = NULL;
1138 IDeckLinkDisplayMode* displayMode = NULL;
1139
1140 tile = t;
1141
1142 bool com_initialized = false;
1143 for (auto &d : bmd_get_sorted_devices(&com_initialized, true)) {
1144 deckLink = get<0>(d).release(); // we must release manually!
1145 string deviceName = bmd_get_device_name(deckLink);
1146 if (!deviceName.empty() && deviceName == device_id.c_str()) {
1147 break;
1148 }
1149
1150 // topological ID
1151 const unsigned long tid =
1152 strtoul(device_id.c_str(), nullptr, 16);
1153 if (get<unsigned>(d) == tid) {
1154 break;
1155 }
1156 // natural (old) index
1157 if (isdigit(device_id.c_str()[0])) {
1158 if (atoi(device_id.c_str()) == get<int>(d)) {
1159 break;
1160 }
1161 }
1162 // new (character) index
1163 if (device_id.length() == 1 && device_id[0] >= 'a') {
1164 if (device_id[0] == get<char>(d)) {
1165 break;
1166 }
1167 }
1168
1169 // Release the IDeckLink instance when we've finished with it to prevent leaks
1170 deckLink->Release();
1171 deckLink = NULL;
1172 }
1173
1174 if (deckLink == nullptr) {
1175 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Device " << device_id << " was not found.\n";
1176 INIT_ERR();
1177 }
1178
1179 // Print the model name of the DeckLink card
1180 string deviceName = bmd_get_device_name(deckLink);
1181 if (!deviceName.empty()) {
1182 LOG(LOG_LEVEL_INFO) << MOD_NAME "Using device " << deviceName << "\n";
1183 }
1184
1185 if (!s->keep_device_defaults && !s->profile.keep()) {
1187 INIT_ERR();
1188 }
1189 }
1190
1191 // Query the DeckLink for its configuration interface
1192 BMD_CHECK(deckLink->QueryInterface(IID_IDeckLinkInput, (void**)&deckLinkInput), "Could not obtain the IDeckLinkInput interface", INIT_ERR());
1193
1194 // Query the DeckLink for its configuration interface
1195 BMD_CHECK(deckLinkInput->QueryInterface(IID_IDeckLinkConfiguration, (void**)&deckLinkConfiguration), "Could not obtain the IDeckLinkConfiguration interface", INIT_ERR());
1196
1197 IDeckLinkProfileAttributes *deckLinkAttributes;
1198 BMD_CHECK(deckLinkInput->QueryInterface(IID_IDeckLinkProfileAttributes, (void**)&deckLinkAttributes), "Could not query device attributes", INIT_ERR());
1199
1200 for (const auto &o : s->device_options) {
1201 if (s->keep_device_defaults && !o.second.is_user_set()) {
1202 continue;
1203 }
1204 if (!o.second.device_write(deckLinkConfiguration, o.first, MOD_NAME)) {
1205 INIT_ERR();
1206 }
1207 }
1208 const BMDVideoInputConversionMode supported_conversion_mode = s->device_options.find(bmdDeckLinkConfigVideoInputConversionMode) != s->device_options.end() ? (BMDVideoInputConversionMode) s->device_options.at(bmdDeckLinkConfigVideoInputConversionMode).get_int() : (BMDVideoInputConversionMode) bmdNoVideoInputConversion;
1209 if (s->stereo) {
1210 CALL_AND_CHECK(deckLinkConfiguration->SetFlag(bmdDeckLinkConfigSDIInput3DPayloadOverride, true), "Unable to set 3D payload override");
1211 }
1212
1213 // set Callback which returns frames
1214 delegate = make_unique<VideoDelegate>(s, *this);
1215 deckLinkInput->SetCallback(delegate.get());
1216
1217 BMDDisplayMode detectedDisplayMode = bmdModeUnknown;
1218 if (s->detect_format) {
1219 if (!detect_format(s, &detectedDisplayMode, this)) {
1220 LOG(LOG_LEVEL_WARNING) << "Signal could have not been detected!\n";
1221 INIT_ERR();
1222 }
1223 }
1224
1225 // Obtain an IDeckLinkDisplayModeIterator to enumerate the display modes supported on input
1226 BMD_CHECK(deckLinkInput->GetDisplayModeIterator(&displayModeIterator),
1227 "Could not obtain the video input display mode iterator:", INIT_ERR());
1228
1230
1231 int mnum = 0;
1232 enum { MODE_SPEC_AUTODETECT = -1, MODE_SPEC_FOURCC = -2, MODE_SPEC_DETECTED = -3 };
1233 int mode_idx = MODE_SPEC_AUTODETECT;
1234
1235 // mode selected manually - either by index or FourCC
1236 if (s->mode.length() > 0) {
1237 if (s->mode.length() <= 2) {
1238 mode_idx = atoi(s->mode.c_str());
1239 } else {
1240 mode_idx = MODE_SPEC_FOURCC;
1241 }
1242 }
1243 if (s->detect_format) { // format already detected manually
1244 mode_idx = MODE_SPEC_DETECTED;
1245 }
1246
1247 while (displayModeIterator->Next(&displayMode) == S_OK) {
1248 if (mode_idx == MODE_SPEC_DETECTED) { // format already detected manually
1249 if (detectedDisplayMode == displayMode->GetDisplayMode()) {
1250 break;
1251 } else {
1252 displayMode->Release();
1253 }
1254 } else if (mode_idx == MODE_SPEC_AUTODETECT) { // autodetect, pick first eligible mode and let device autodetect
1255 if ((s->stereo && (displayMode->GetFlags() & bmdDisplayModeSupports3D) == 0u) || displayMode->GetFieldDominance() == bmdLowerFieldFirst) {
1256 displayMode->Release();
1257 continue;
1258 }
1259 auto it = std::find_if(uv_to_bmd_codec_map.begin(),
1260 uv_to_bmd_codec_map.end(),
1261 [&s](const std::pair<codec_t, BMDPixelFormat>& el){ return el.first == s->codec; });
1262 if (it == uv_to_bmd_codec_map.end()) {
1263 LOG(LOG_LEVEL_ERROR) << "Unsupported codec: " << get_codec_name(s->codec) << "!\n";
1264 INIT_ERR();
1265 }
1266 BMDPixelFormat pf = it->second;
1267 BMD_BOOL supported = 0;
1268 const BMDVideoConnection connection = s->device_options.find(bmdDeckLinkConfigVideoInputConnection) != s->device_options.end()
1269 ? (BMDVideoConnection) s->device_options.at(bmdDeckLinkConfigVideoInputConnection).get_int() : (BMDVideoConnection) bmdVideoConnectionUnspecified;
1270 BMD_CHECK(deckLinkInput->DoesSupportVideoMode(connection, displayMode->GetDisplayMode(), pf, supported_conversion_mode, s->supported_flags, nullptr, &supported), "DoesSupportVideoMode", INIT_ERR());
1271 if (supported) {
1272 break;
1273 }
1274 } else if (mode_idx != MODE_SPEC_FOURCC) { // manually given idx
1275 if (mode_idx != mnum) {
1276 mnum++;
1277 // Release the IDeckLinkDisplayMode object to prevent a leak
1278 displayMode->Release();
1279 continue;
1280 }
1281
1282 mnum++;
1283 break;
1284 } else { // manually given FourCC
1285 if (displayMode->GetDisplayMode() == bmd_read_fourcc(s->mode.c_str())) {
1286 break;
1287 }
1288 displayMode->Release();
1289 }
1290 }
1291
1292 if (displayMode) {
1293 BMD_STR displayModeString = NULL;
1294 if (HRESULT result = displayMode->GetName(&displayModeString); result == S_OK) {
1296 << "The desired display mode is supported: "
1297 << get_str_from_bmd_api_str(displayModeString)
1298 << "\n";
1299 release_bmd_api_str(displayModeString);
1300 }
1301 } else {
1302 if (mode_idx == MODE_SPEC_FOURCC) {
1303 MSG(ERROR,
1304 "Desired mode \"%s\" is invalid or not "
1305 "supported.\n",
1306 s->mode.c_str());
1307 } else if (mode_idx >= 0) {
1308 MSG(ERROR, "Desired mode index %s is out of bounds.\n", s->mode.c_str());
1309 } else if (mode_idx == MODE_SPEC_AUTODETECT) {
1310 MSG(ERROR, "Cannot set initial format for "
1311 "autodetection - perhaps imposible "
1312 "combinations of parameters were set.\n");
1313 } else {
1314 assert("Invalid mode spec." && 0);
1315 }
1316 INIT_ERR();
1317 }
1318
1319 BMDPixelFormat pf;
1320 BMD_CHECK(set_display_mode_properties(s, tile, displayMode, &pf),
1321 "Could not set display mode properties", INIT_ERR());
1322
1323 deckLinkInput->StopStreams();
1324
1325 if (mode_idx == MODE_SPEC_AUTODETECT) {
1326 MSG(INFO, "Trying to autodetect format.\n");
1327 BMD_BOOL autodetection;
1328 BMD_CHECK(deckLinkAttributes->GetFlag(BMDDeckLinkSupportsInputFormatDetection, &autodetection), "Could not verify if device supports autodetection", INIT_ERR());
1329 if (autodetection == BMD_FALSE) {
1330 MSG(ERROR,
1331 "Device doesn't support format autodetection, you "
1332 "must set it manually or try \"-t "
1333 "decklink:detect-format[:connection=<in>]\"\n");
1334 INIT_ERR();
1335 }
1336 s->enable_flags |= bmdVideoInputEnableFormatDetection;
1337 }
1338
1339 BMD_BOOL supported = 0;
1340 const BMDVideoConnection connection = s->device_options.find(bmdDeckLinkConfigVideoInputConnection) != s->device_options.end()
1341 ? (BMDVideoConnection) s->device_options.at(bmdDeckLinkConfigVideoInputConnection).get_int() : (BMDVideoConnection) bmdVideoConnectionUnspecified;
1342 BMD_CHECK(deckLinkInput->DoesSupportVideoMode(connection, displayMode->GetDisplayMode(), pf, supported_conversion_mode, s->supported_flags, nullptr, &supported), "DoesSupportVideoMode", INIT_ERR());
1343
1344 if (!supported) {
1345 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Requested display mode not supported with the selected pixel format\n";
1346 INIT_ERR();
1347 }
1348
1349 if (HRESULT result = deckLinkInput->EnableVideoInput(displayMode->GetDisplayMode(), pf, s->enable_flags); result != S_OK) {
1350 switch (result) {
1351 case E_INVALIDARG:
1352 log_msg(LOG_LEVEL_ERROR, MOD_NAME "You have required invalid video mode and pixel format combination.\n");
1353 break;
1354 case E_ACCESSDENIED:
1355 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to access the hardware or input "
1356 "stream currently active (another application using it?).\n");
1357 break;
1358 default:
1359 LOG(LOG_LEVEL_ERROR) << MOD_NAME "Could not enable video input: " << bmd_hresult_to_string(result) << "\n";
1360 }
1361 INIT_ERR();
1362 }
1363
1364 if (!audio) { //TODO: figure out output from multiple streams
1365 deckLinkInput->DisableAudioInput();
1366 } else {
1367 if (deckLinkConfiguration->SetInt(bmdDeckLinkConfigAudioInputConnection,
1368 audioConnection) == S_OK) {
1369 const map<BMDAudioConnection, string> mapping = {
1370 { bmdAudioConnectionEmbedded, "embedded" },
1371 { bmdAudioConnectionAESEBU, "AES/EBU" },
1372 { bmdAudioConnectionAnalog, "analog" },
1373 { bmdAudioConnectionAnalogXLR, "analogXLR" },
1374 { bmdAudioConnectionAnalogRCA, "analogRCA" },
1375 { bmdAudioConnectionMicrophone, "microphone" },
1376 { bmdAudioConnectionHeadphones, "headphones" },
1377 };
1378 log_msg(LOG_LEVEL_INFO, MOD_NAME "Audio input set to: %s\n", mapping.find(audioConnection) != mapping.end() ? mapping.at(audioConnection).c_str() : "unknown");
1379 } else {
1380 log_msg(LOG_LEVEL_ERROR, MOD_NAME "Unable to set audio input!!! Please check if it is OK. Continuing anyway.\n");
1381
1382 }
1383 if (s->audio.ch_count == 4 ||
1384 s->audio.ch_count > BMD_MAX_AUD_CH ||
1385 !is_power_of_two(s->audio.ch_count)) {
1387 MOD_NAME
1388 "DeckLink may not be able to grab %d audio "
1389 "channels. "
1390 "1, 2, 8, 16, 32 or 64 may work.\n",
1391 s->audio.ch_count);
1392 }
1393 BMD_CHECK(deckLinkInput->EnableAudioInput(
1394 bmdAudioSampleRate48kHz,
1395 s->audio.bps == 2
1396 ? bmdAudioSampleType16bitInteger
1397 : bmdAudioSampleType32bitInteger,
1398 max(s->audio.ch_count, 2)), // capture at least 2
1399 "EnableAudioInput", INIT_ERR());
1400 }
1401
1402 // Start streaming
1403 BMD_CHECK(deckLinkInput->StartStreams(), "Could not start stream", INIT_ERR());
1404
1405 displayMode->Release();
1406 displayMode = NULL;
1407
1408 displayModeIterator->Release();
1409 displayModeIterator = NULL;
1410 return true;
1411}
const char * get_codec_name(codec_t codec)
static const struct codec_param mapping[AC_COUNT]
Definition libavcodec.c:87
uint32_t bmd_read_fourcc(const char *str)
void release_bmd_api_str(BMD_STR string)
string bmd_hresult_to_string(HRESULT res)
string bmd_get_device_name(IDeckLink *decklink)
bool decklink_set_profile(IDeckLink *deckLink, bmd_option const &req_profile, bool stereo)
std::string get_str_from_bmd_api_str(BMD_STR string)
std::vector< bmd_dev > bmd_get_sorted_devices(bool *com_initialized, bool verbose, bool natural_sort)
@ BMD_MAX_AUD_CH
#define BMD_BOOL
#define BMD_STR
#define BMD_CHECK(cmd, name, action)
static std::vector< std::pair< codec_t, BMDPixelFormat > > uv_to_bmd_codec_map
#define BMD_FALSE
void log_msg(int level, const char *format,...)
Definition debug.cpp:130
#define LOG_LEVEL_INFO
normal reporting
Definition debug.h:62
#define LOG_LEVEL_ERROR
general errors
Definition debug.h:59
#define MSG(l, fmt,...)
Definition debug.h:96
#define LOG(level)
Definition debug.h:313
#define LOG_LEVEL_WARNING
less severe errors
Definition debug.h:60
bool is_power_of_two(unsigned long long x)
Definition math.c:69
bool keep() const
string device_id
Definition decklink.cpp:175
IDeckLinkInput * deckLinkInput
Definition decklink.cpp:171
void check_attributes(struct vidcap_decklink_state *s)
unique_ptr< VideoDelegate > delegate
Definition decklink.cpp:172
IDeckLinkConfiguration * deckLinkConfiguration
Definition decklink.cpp:174
IDeckLinkProfileAttributes * deckLinkAttributes
Definition decklink.cpp:173
Struct tile is an area of video_frame.
Definition types.h:279

References audio, BMD_BOOL, BMD_CHECK, BMD_FALSE, bmd_get_device_name(), bmd_get_sorted_devices(), bmd_hresult_to_string(), BMD_MAX_AUD_CH, bmd_read_fourcc(), BMD_STR, CALL_AND_CHECK, check_attributes(), vidcap_decklink_state::codec, deckLink, decklink_set_profile(), deckLinkAttributes, deckLinkConfiguration, deckLinkInput, delegate, detect_format(), vidcap_decklink_state::detect_format, device_id, vidcap_decklink_state::device_options, vidcap_decklink_state::enable_flags, get_codec_name(), get_str_from_bmd_api_str(), INIT_ERR, is_power_of_two(), bmd_option::keep(), vidcap_decklink_state::keep_device_defaults, LOG, LOG_LEVEL_ERROR, LOG_LEVEL_INFO, LOG_LEVEL_WARNING, log_msg(), mapping, MOD_NAME, vidcap_decklink_state::mode, MSG, vidcap_decklink_state::profile, release_bmd_api_str(), set_display_mode_properties(), vidcap_decklink_state::stereo, vidcap_decklink_state::supported_flags, and uv_to_bmd_codec_map.

Here is the call graph for this function:

Member Data Documentation

◆ audio

bool device_state::audio = false

Definition at line 176 of file decklink.cpp.

Referenced by init().

◆ deckLink

IDeckLink* device_state::deckLink = nullptr

◆ deckLinkAttributes

IDeckLinkProfileAttributes* device_state::deckLinkAttributes = nullptr

Definition at line 173 of file decklink.cpp.

Referenced by init(), vidcap_decklink_print_card_info(), and vidcap_decklink_probe().

◆ deckLinkConfiguration

IDeckLinkConfiguration* device_state::deckLinkConfiguration = nullptr

Definition at line 174 of file decklink.cpp.

Referenced by init().

◆ deckLinkInput

IDeckLinkInput* device_state::deckLinkInput = nullptr

◆ delegate

unique_ptr<VideoDelegate> device_state::delegate

Definition at line 172 of file decklink.cpp.

Referenced by detect_format(), and init().

◆ device_id

string device_state::device_id = "0"

Definition at line 175 of file decklink.cpp.

Referenced by init().

◆ tile

struct tile* device_state::tile = nullptr

Definition at line 177 of file decklink.cpp.

Referenced by VideoDelegate::VideoInputFormatChanged().


The documentation for this struct was generated from the following file: