From 6ccc929592ef239dc4d011d22facaf19d098567c Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Fri, 4 Mar 2016 00:22:00 +0100 Subject: [PATCH] Make drivers capable of delivering a list of modes, and setting them. --- bmusb | 2 +- decklink_capture.cpp | 74 ++++++++++++++++++++++++++++++++++---------- decklink_capture.h | 7 +++++ 3 files changed, 66 insertions(+), 17 deletions(-) diff --git a/bmusb b/bmusb index 862d8cc..753cbaf 160000 --- a/bmusb +++ b/bmusb @@ -1 +1 @@ -Subproject commit 862d8ccf3a3d48602427eb2bfb319b2fc7181fe0 +Subproject commit 753cbaf5cec7411bdfe5171404c8586b8015faec diff --git a/decklink_capture.cpp b/decklink_capture.cpp index 62af1c0..701675b 100644 --- a/decklink_capture.cpp +++ b/decklink_capture.cpp @@ -134,6 +134,7 @@ size_t memcpy_interleaved_fastpath(uint8_t *dest1, uint8_t *dest2, const uint8_t } // namespace DeckLinkCapture::DeckLinkCapture(IDeckLink *card, int card_index) + : card_index(card_index) { { const char *model_name; @@ -168,29 +169,44 @@ DeckLinkCapture::DeckLinkCapture(IDeckLink *card, int card_index) exit(1); } - // TODO: Make the user mode selectable. - BMDDisplayModeSupport support; - IDeckLinkDisplayMode *display_mode; - if (input->DoesSupportVideoMode(bmdModeHD720p5994, bmdFormat8BitYUV, /*flags=*/0, &support, &display_mode)) { - fprintf(stderr, "Failed to query display mode for card %d\n", card_index); + IDeckLinkDisplayModeIterator *mode_it; + if (input->GetDisplayModeIterator(&mode_it) != S_OK) { + fprintf(stderr, "Failed to enumerate display modes for card %d\n", card_index); exit(1); } - if (support == bmdDisplayModeNotSupported) { - fprintf(stderr, "Card %d does not support display mode\n", card_index); - exit(1); - } + for (IDeckLinkDisplayMode *mode_ptr; mode_it->Next(&mode_ptr) == S_OK; mode_ptr->Release()) { + VideoMode mode; + mode.id = mode_ptr->GetDisplayMode(); - if (display_mode->GetFrameRate(&frame_duration, &time_scale) != S_OK) { - fprintf(stderr, "Could not get frame rate for card %d\n", card_index); - exit(1); - } + const char *mode_name; + if (mode_ptr->GetName(&mode_name) != S_OK) { + mode.name = "Unknown mode"; + } else { + mode.name = mode_name; + } - if (input->EnableVideoInput(bmdModeHD720p5994, bmdFormat8BitYUV, 0) != S_OK) { - fprintf(stderr, "Failed to set 720p59.94 connection for card %d\n", card_index); - exit(1); + mode.autodetect = false; + + mode.width = mode_ptr->GetWidth(); + mode.height = mode_ptr->GetHeight(); + + BMDTimeScale frame_rate_num; + BMDTimeValue frame_rate_den; + if (mode_ptr->GetFrameRate(&frame_rate_den, &frame_rate_num) != S_OK) { + fprintf(stderr, "Could not get frame rate for mode '%s' on card %d\n", mode.name.c_str(), card_index); + exit(1); + } + mode.frame_rate_num = frame_rate_num; + mode.frame_rate_den = frame_rate_den; + + // TODO: Respect the TFF/BFF flag. + mode.interlaced = (mode_ptr->GetFieldDominance() == bmdLowerFieldFirst || mode_ptr->GetFieldDominance() == bmdUpperFieldFirst); } + // TODO: Make the user mode selectable. + set_video_mode(bmdModeHD720p5994); + if (input->EnableAudioInput(48000, bmdAudioSampleType32bitInteger, 2) != S_OK) { fprintf(stderr, "Failed to enable audio input for card %d\n", card_index); exit(1); @@ -346,3 +362,29 @@ void DeckLinkCapture::stop_dequeue_thread() } } +void DeckLinkCapture::set_video_mode(uint32_t video_mode_id) +{ + BMDDisplayModeSupport support; + IDeckLinkDisplayMode *display_mode; + if (input->DoesSupportVideoMode(video_mode_id, bmdFormat8BitYUV, /*flags=*/0, &support, &display_mode)) { + fprintf(stderr, "Failed to query display mode for card %d\n", card_index); + exit(1); + } + + if (support == bmdDisplayModeNotSupported) { + fprintf(stderr, "Card %d does not support display mode\n", card_index); + exit(1); + } + + if (display_mode->GetFrameRate(&frame_duration, &time_scale) != S_OK) { + fprintf(stderr, "Could not get frame rate for card %d\n", card_index); + exit(1); + } + + if (input->EnableVideoInput(video_mode_id, bmdFormat8BitYUV, 0) != S_OK) { + fprintf(stderr, "Failed to set 720p59.94 connection for card %d\n", card_index); + exit(1); + } + + current_video_mode = video_mode_id; +} diff --git a/decklink_capture.h b/decklink_capture.h index 695f9d3..62723bc 100644 --- a/decklink_capture.h +++ b/decklink_capture.h @@ -75,11 +75,15 @@ public: void start_bm_capture() override; void stop_dequeue_thread() override; + std::vector get_available_video_modes() const override { return video_modes; } + void set_video_mode(uint32_t video_mode_id) override; + private: std::atomic refcount{1}; bool done_init = false; std::string description; uint16_t timecode = 0; + int card_index; bool has_dequeue_callbacks = false; std::function dequeue_init_callback = nullptr; @@ -92,6 +96,9 @@ private: IDeckLinkInput *input = nullptr; BMDTimeValue frame_duration; BMDTimeScale time_scale; + + std::vector video_modes; + BMDDisplayMode current_video_mode; }; #endif // !defined(_DECKLINK_CAPTURE_H) -- 2.39.2