-Subproject commit 5b54cc5acb28f5d2071c99ef7a715044aa30f10c
+Subproject commit a5e46ba4b478f7fae63f3032e574208c0e69cc11
exit(1);
}
- /* Set up the video and audio sources. */
- IDeckLinkConfiguration *config;
- if (card->QueryInterface(IID_IDeckLinkConfiguration, (void**)&config) != S_OK) {
- fprintf(stderr, "Failed to get configuration interface for card %d\n", card_index);
+ IDeckLinkAttributes *attr;
+ if (card->QueryInterface(IID_IDeckLinkAttributes, (void**)&attr) != S_OK) {
+ fprintf(stderr, "Card %d has no attributes\n", card_index);
exit(1);
}
- if (config->SetInt(bmdDeckLinkConfigVideoInputConnection, bmdVideoConnectionHDMI) != S_OK) {
- fprintf(stderr, "Failed to set video input connection for card %d\n", card_index);
+ // Get the list of available video inputs.
+ int64_t video_input_mask;
+ if (attr->GetInt(BMDDeckLinkVideoInputConnections, &video_input_mask) != S_OK) {
+ fprintf(stderr, "Failed to enumerate video inputs for card %d\n", card_index);
exit(1);
}
+ const vector<pair<BMDVideoConnection, string>> video_input_types = {
+ { bmdVideoConnectionSDI, "SDI" },
+ { bmdVideoConnectionHDMI, "HDMI" },
+ { bmdVideoConnectionOpticalSDI, "Optical SDI" },
+ { bmdVideoConnectionComponent, "Component" },
+ { bmdVideoConnectionComposite, "Composite" },
+ { bmdVideoConnectionSVideo, "S-Video" }
+ };
+ for (const auto &video_input : video_input_types) {
+ if (video_input_mask & video_input.first) {
+ video_inputs.emplace(video_input.first, video_input.second);
+ }
+ }
- if (config->SetInt(bmdDeckLinkConfigAudioInputConnection, bmdAudioConnectionEmbedded) != S_OK) {
- fprintf(stderr, "Failed to set video input connection for card %d\n", card_index);
+ // And then the available audio inputs.
+ int64_t audio_input_mask;
+ if (attr->GetInt(BMDDeckLinkAudioInputConnections, &audio_input_mask) != S_OK) {
+ fprintf(stderr, "Failed to enumerate audio inputs for card %d\n", card_index);
+ exit(1);
+ }
+ const vector<pair<BMDAudioConnection, string>> audio_input_types = {
+ { bmdAudioConnectionEmbedded, "Embedded" },
+ { bmdAudioConnectionAESEBU, "AES/EBU" },
+ { bmdAudioConnectionAnalog, "Analog" },
+ { bmdAudioConnectionAnalogXLR, "Analog XLR" },
+ { bmdAudioConnectionAnalogRCA, "Analog RCA" },
+ { bmdAudioConnectionMicrophone, "Microphone" },
+ { bmdAudioConnectionHeadphones, "Headphones" }
+ };
+ for (const auto &audio_input : audio_input_types) {
+ if (audio_input_mask & audio_input.first) {
+ audio_inputs.emplace(audio_input.first, audio_input.second);
+ }
+ }
+
+ attr->Release();
+
+ /* Set up the video and audio sources. */
+ if (card->QueryInterface(IID_IDeckLinkConfiguration, (void**)&config) != S_OK) {
+ fprintf(stderr, "Failed to get configuration interface for card %d\n", card_index);
exit(1);
}
+ set_video_input(bmdVideoConnectionHDMI);
+ set_audio_input(bmdAudioConnectionEmbedded);
+
IDeckLinkDisplayModeIterator *mode_it;
if (input->GetDisplayModeIterator(&mode_it) != S_OK) {
fprintf(stderr, "Failed to enumerate display modes for card %d\n", card_index);
current_video_mode = video_mode_id;
}
+
+void DeckLinkCapture::set_video_input(uint32_t video_input_id)
+{
+ if (config->SetInt(bmdDeckLinkConfigVideoInputConnection, video_input_id) != S_OK) {
+ fprintf(stderr, "Failed to set video input connection for card %d\n", card_index);
+ exit(1);
+ }
+
+ current_video_input = video_input_id;
+}
+
+void DeckLinkCapture::set_audio_input(uint32_t audio_input_id)
+{
+ if (config->SetInt(bmdDeckLinkConfigAudioInputConnection, audio_input_id) != S_OK) {
+ fprintf(stderr, "Failed to set audio input connection for card %d\n", card_index);
+ exit(1);
+ }
+
+ current_audio_input = audio_input_id;
+}
void set_video_mode(uint32_t video_mode_id) override;
uint32_t get_current_video_mode() const override { return current_video_mode; }
+ std::map<uint32_t, std::string> get_available_video_inputs() const override { return video_inputs; }
+ void set_video_input(uint32_t video_input_id) override;
+ uint32_t get_current_video_input() const override { return current_video_input; }
+
+ std::map<uint32_t, std::string> get_available_audio_inputs() const override { return audio_inputs; }
+ void set_audio_input(uint32_t audio_input_id) override;
+ uint32_t get_current_audio_input() const override { return current_audio_input; }
+
private:
void set_video_mode_no_restart(uint32_t video_mode_id);
FrameAllocator *audio_frame_allocator = nullptr;
frame_callback_t frame_callback = nullptr;
+ IDeckLinkConfiguration *config = nullptr;
+
IDeckLinkInput *input = nullptr;
BMDTimeValue frame_duration;
BMDTimeScale time_scale;
std::map<uint32_t, VideoMode> video_modes;
BMDDisplayMode current_video_mode;
+
+ std::map<uint32_t, std::string> video_inputs;
+ BMDVideoConnection current_video_input;
+
+ std::map<uint32_t, std::string> audio_inputs;
+ BMDAudioConnection current_audio_input;
};
#endif // !defined(_DECKLINK_CAPTURE_H)
card_submenu.setTitle("Input source");
menu.addMenu(&card_submenu);
- // Add a submenu for selecting resolution, with an action for each resolution.
- // Note that the choice depends a lot on which card is active.
+ // --- The choices in the next few options depend a lot on which card is active ---
+
+ // Add a submenu for selecting video input, with an action for each input.
+ QMenu video_input_submenu;
+ QActionGroup video_input_group(&video_input_submenu);
+ std::map<uint32_t, string> video_inputs = global_mixer->get_available_video_inputs(current_card);
+ uint32_t current_video_input = global_mixer->get_current_video_input(current_card);
+ for (const auto &mode : video_inputs) {
+ QString description(QString::fromStdString(mode.second));
+ QAction *action = new QAction(description, &video_input_group);
+ action->setCheckable(true);
+ if (mode.first == current_video_input) {
+ action->setChecked(true);
+ }
+ action->setData(QList<QVariant>{"video_input", mode.first});
+ video_input_submenu.addAction(action);
+ }
+
+ video_input_submenu.setTitle("Video input");
+ menu.addMenu(&video_input_submenu);
+
+ // The same for audio input.
+ QMenu audio_input_submenu;
+ QActionGroup audio_input_group(&audio_input_submenu);
+ std::map<uint32_t, string> audio_inputs = global_mixer->get_available_audio_inputs(current_card);
+ uint32_t current_audio_input = global_mixer->get_current_audio_input(current_card);
+ for (const auto &mode : audio_inputs) {
+ QString description(QString::fromStdString(mode.second));
+ QAction *action = new QAction(description, &audio_input_group);
+ action->setCheckable(true);
+ if (mode.first == current_audio_input) {
+ action->setChecked(true);
+ }
+ action->setData(QList<QVariant>{"audio_input", mode.first});
+ audio_input_submenu.addAction(action);
+ }
+
+ audio_input_submenu.setTitle("Audio input");
+ menu.addMenu(&audio_input_submenu);
+
+ // The same for resolution.
QMenu mode_submenu;
QActionGroup mode_group(&mode_submenu);
std::map<uint32_t, VideoMode> video_modes = global_mixer->get_available_video_modes(current_card);
mode_submenu.setTitle("Input mode");
menu.addMenu(&mode_submenu);
+
// Add an audio source selector.
QAction *audio_source_action = new QAction("Use as audio source", &menu);
audio_source_action->setCheckable(true);
} else {
global_mixer->set_video_mode(current_card, mode);
}
+ } else if (selected[0].toString() == "video_input") {
+ uint32_t input = selected[1].toUInt(nullptr);
+ global_mixer->set_video_input(current_card, input);
+ } else if (selected[0].toString() == "audio_input") {
+ uint32_t input = selected[1].toUInt(nullptr);
+ global_mixer->set_audio_input(current_card, input);
} else if (selected[0].toString() == "card") {
unsigned card_index = selected[1].toUInt(nullptr);
global_mixer->set_signal_mapping(signal_num, card_index);
void start_mode_scanning(unsigned card_index);
+ std::map<uint32_t, std::string> get_available_video_inputs(unsigned card_index) const {
+ assert(card_index < num_cards);
+ return cards[card_index].capture->get_available_video_inputs();
+ }
+
+ uint32_t get_current_video_input(unsigned card_index) const {
+ assert(card_index < num_cards);
+ return cards[card_index].capture->get_current_video_input();
+ }
+
+ void set_video_input(unsigned card_index, uint32_t input) {
+ assert(card_index < num_cards);
+ cards[card_index].capture->set_video_input(input);
+ }
+
+ std::map<uint32_t, std::string> get_available_audio_inputs(unsigned card_index) const {
+ assert(card_index < num_cards);
+ return cards[card_index].capture->get_available_audio_inputs();
+ }
+
+ uint32_t get_current_audio_input(unsigned card_index) const {
+ assert(card_index < num_cards);
+ return cards[card_index].capture->get_current_audio_input();
+ }
+
+ void set_audio_input(unsigned card_index, uint32_t input) {
+ assert(card_index < num_cards);
+ cards[card_index].capture->set_audio_input(input);
+ }
+
private:
void configure_card(unsigned card_index, const QSurfaceFormat &format, CaptureInterface *capture);
void bm_frame(unsigned card_index, uint16_t timecode,