From: Steinar H. Gunderson Date: Fri, 4 Mar 2016 22:52:37 +0000 (+0100) Subject: Add an option to scan through all possible modes for the PCI cards, as a substitute... X-Git-Tag: 1.2.0~41 X-Git-Url: https://git.sesse.net/?a=commitdiff_plain;h=1202ad9167357a461366dab9cbbaa6c578423253;p=nageru Add an option to scan through all possible modes for the PCI cards, as a substitute for autodetection. --- diff --git a/glwidget.cpp b/glwidget.cpp index 9215fca..5a13258 100644 --- a/glwidget.cpp +++ b/glwidget.cpp @@ -144,6 +144,7 @@ void GLWidget::show_context_menu(unsigned signal_num, const QPoint &pos) 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); + bool has_auto_mode = false; for (const auto &mode : video_modes) { QString description(QString::fromStdString(mode.second.name)); QAction *action = new QAction(description, &mode_group); @@ -153,6 +154,19 @@ void GLWidget::show_context_menu(unsigned signal_num, const QPoint &pos) } action->setData(QList{"video_mode", mode.first}); mode_submenu.addAction(action); + + // TODO: Relying on the 0 value here (from bmusb.h) is ugly, it should be a named constant. + if (mode.first == 0) { + has_auto_mode = true; + } + } + + // Add a “scan” menu if there's no “auto” mode. + if (!has_auto_mode) { + QAction *action = new QAction("Scan", &mode_group); + action->setData(QList{"video_mode", 0}); + mode_submenu.addSeparator(); + mode_submenu.addAction(action); } mode_submenu.setTitle("Input mode"); @@ -175,7 +189,11 @@ void GLWidget::show_context_menu(unsigned signal_num, const QPoint &pos) 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); + if (mode == 0 && !has_auto_mode) { + global_mixer->start_mode_scanning(current_card); + } else { + 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); diff --git a/mixer.cpp b/mixer.cpp index d725ad3..a1c038d 100644 --- a/mixer.cpp +++ b/mixer.cpp @@ -329,6 +329,26 @@ void Mixer::bm_frame(unsigned card_index, uint16_t timecode, { CaptureCard *card = &cards[card_index]; + if (is_mode_scanning[card_index]) { + if (video_format.has_signal) { + // Found a stable signal, so stop scanning. + is_mode_scanning[card_index] = false; + } else { + static constexpr double switch_time_s = 0.5; // Should be enough time for the signal to stabilize. + timespec now; + clock_gettime(CLOCK_MONOTONIC, &now); + double sec_since_last_switch = (now.tv_sec - last_mode_scan_change[card_index].tv_sec) + + 1e-9 * (now.tv_nsec - last_mode_scan_change[card_index].tv_nsec); + if (sec_since_last_switch > switch_time_s) { + // It isn't this mode; try the next one. + mode_scanlist_index[card_index]++; + mode_scanlist_index[card_index] %= mode_scanlist[card_index].size(); + cards[card_index].capture->set_video_mode(mode_scanlist[card_index][mode_scanlist_index[card_index]]); + last_mode_scan_change[card_index] = now; + } + } + } + int64_t frame_length = int64_t(TIMEBASE * video_format.frame_rate_den) / video_format.frame_rate_nom; size_t num_samples = (audio_frame.len >= audio_offset) ? (audio_frame.len - audio_offset) / audio_format.num_channels / (audio_format.bits_per_sample / 8) : 0; @@ -1037,6 +1057,23 @@ void Mixer::reset_meters() correlation.reset(); } +void Mixer::start_mode_scanning(unsigned card_index) +{ + assert(card_index < num_cards); + if (is_mode_scanning[card_index]) { + return; + } + is_mode_scanning[card_index] = true; + mode_scanlist[card_index].clear(); + for (const auto &mode : cards[card_index].capture->get_available_video_modes()) { + mode_scanlist[card_index].push_back(mode.first); + } + assert(!mode_scanlist[card_index].empty()); + mode_scanlist_index[card_index] = 0; + cards[card_index].capture->set_video_mode(mode_scanlist[card_index][0]); + clock_gettime(CLOCK_MONOTONIC, &last_mode_scan_change[card_index]); +} + Mixer::OutputChannel::~OutputChannel() { if (has_current_frame) { diff --git a/mixer.h b/mixer.h index 27ba586..061b382 100644 --- a/mixer.h +++ b/mixer.h @@ -256,6 +256,8 @@ public: cards[card_index].capture->set_video_mode(mode); } + void start_mode_scanning(unsigned card_index); + private: void configure_card(unsigned card_index, const QSurfaceFormat &format, CaptureInterface *capture); void bm_frame(unsigned card_index, uint16_t timecode, @@ -382,6 +384,12 @@ private: std::mutex audio_mutex; std::condition_variable audio_task_queue_changed; std::queue audio_task_queue; // Under audio_mutex. + + // For mode scanning. + bool is_mode_scanning[MAX_CARDS]{ false }; + std::vector mode_scanlist[MAX_CARDS]; + unsigned mode_scanlist_index[MAX_CARDS]{ 0 }; + timespec last_mode_scan_change[MAX_CARDS]; }; extern Mixer *global_mixer;