From 96943efedcea66dab5ab6500358951e9f249aef2 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Fri, 4 Mar 2016 23:02:10 +0100 Subject: [PATCH] Add a menu option where the user can change the input resolution. --- decklink_capture.cpp | 20 ++++++++++++++++--- decklink_capture.h | 2 ++ glwidget.cpp | 47 ++++++++++++++++++++++++++++++++++++-------- mixer.h | 15 ++++++++++++++ 4 files changed, 73 insertions(+), 11 deletions(-) diff --git a/decklink_capture.cpp b/decklink_capture.cpp index f2731ac..80aedc1 100644 --- a/decklink_capture.cpp +++ b/decklink_capture.cpp @@ -206,8 +206,7 @@ DeckLinkCapture::DeckLinkCapture(IDeckLink *card, int card_index) video_modes.insert(make_pair(id, mode)); } - // TODO: Make the user mode selectable. - set_video_mode(bmdModeHD720p5994); + set_video_mode_no_restart(bmdModeHD720p5994); if (input->EnableAudioInput(48000, bmdAudioSampleType32bitInteger, 2) != S_OK) { fprintf(stderr, "Failed to enable audio input for card %d\n", card_index); @@ -365,6 +364,21 @@ void DeckLinkCapture::stop_dequeue_thread() } void DeckLinkCapture::set_video_mode(uint32_t video_mode_id) +{ + if (input->StopStreams() != S_OK) { + fprintf(stderr, "StopStreams failed\n"); + exit(1); + } + + set_video_mode_no_restart(video_mode_id); + + if (input->StartStreams() != S_OK) { + fprintf(stderr, "StartStreams failed\n"); + exit(1); + } +} + +void DeckLinkCapture::set_video_mode_no_restart(uint32_t video_mode_id) { BMDDisplayModeSupport support; IDeckLinkDisplayMode *display_mode; @@ -384,7 +398,7 @@ void DeckLinkCapture::set_video_mode(uint32_t video_mode_id) } if (input->EnableVideoInput(video_mode_id, bmdFormat8BitYUV, 0) != S_OK) { - fprintf(stderr, "Failed to set 720p59.94 connection for card %d\n", card_index); + fprintf(stderr, "Failed to set video mode 0x%04x for card %d\n", video_mode_id, card_index); exit(1); } diff --git a/decklink_capture.h b/decklink_capture.h index ad13a93..322adb5 100644 --- a/decklink_capture.h +++ b/decklink_capture.h @@ -80,6 +80,8 @@ public: uint32_t get_current_video_mode() const override { return current_video_mode; } private: + void set_video_mode_no_restart(uint32_t video_mode_id); + std::atomic refcount{1}; bool done_init = false; std::string description; diff --git a/glwidget.cpp b/glwidget.cpp index c57d645..9215fca 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -118,23 +118,45 @@ void GLWidget::show_context_menu(unsigned signal_num, const QPoint &pos) QMenu menu; - // Add an action for each card. - QActionGroup group(&menu); + // Add a submenu for selecting input card, with an action for each card. + QMenu card_submenu; + QActionGroup card_group(&card_submenu); unsigned num_cards = global_mixer->get_num_cards(); unsigned current_card = global_mixer->map_signal(signal_num); for (unsigned card_index = 0; card_index < num_cards; ++card_index) { QString description(QString::fromStdString(global_mixer->get_card_description(card_index))); - QAction *action = new QAction(description, &group); + QAction *action = new QAction(description, &card_group); action->setCheckable(true); if (current_card == card_index) { action->setChecked(true); } - action->setData(card_index); - menu.addAction(action); + action->setData(QList{"card", card_index}); + card_submenu.addAction(action); } - menu.addSeparator(); + 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. + QMenu mode_submenu; + QActionGroup mode_group(&mode_submenu); + std::map video_modes = global_mixer->get_available_video_modes(current_card); + uint32_t current_video_mode = global_mixer->get_current_video_mode(current_card); + for (const auto &mode : video_modes) { + QString description(QString::fromStdString(mode.second.name)); + QAction *action = new QAction(description, &mode_group); + action->setCheckable(true); + if (mode.first == current_video_mode) { + action->setChecked(true); + } + action->setData(QList{"video_mode", mode.first}); + mode_submenu.addAction(action); + } + + 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); @@ -145,11 +167,20 @@ void GLWidget::show_context_menu(unsigned signal_num, const QPoint &pos) } menu.addAction(audio_source_action); + // Show the menu and look at the result. QAction *selected_item = menu.exec(global_pos); if (selected_item == audio_source_action) { global_mixer->set_audio_source(signal_num); } else if (selected_item != nullptr) { - unsigned card_index = selected_item->data().toInt(nullptr); - global_mixer->set_signal_mapping(signal_num, card_index); + QList selected = selected_item->data().toList(); + if (selected[0].toString() == "video_mode") { + uint32_t mode = selected[1].toUInt(nullptr); + global_mixer->set_video_mode(current_card, mode); + } else if (selected[0].toString() == "card") { + unsigned card_index = selected[1].toUInt(nullptr); + global_mixer->set_signal_mapping(signal_num, card_index); + } else { + assert(false); + } } } diff --git a/mixer.h b/mixer.h index 00b10f8..27ba586 100644 --- a/mixer.h +++ b/mixer.h @@ -241,6 +241,21 @@ public: return cards[card_index].capture->get_description(); } + std::map get_available_video_modes(unsigned card_index) const { + assert(card_index < num_cards); + return cards[card_index].capture->get_available_video_modes(); + } + + uint32_t get_current_video_mode(unsigned card_index) const { + assert(card_index < num_cards); + return cards[card_index].capture->get_current_video_mode(); + } + + void set_video_mode(unsigned card_index, uint32_t mode) { + assert(card_index < num_cards); + cards[card_index].capture->set_video_mode(mode); + } + private: void configure_card(unsigned card_index, const QSurfaceFormat &format, CaptureInterface *capture); void bm_frame(unsigned card_index, uint16_t timecode, -- 2.39.2