X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fdecklink_output.cpp;h=00d80432564c569f437a0817e3dafc22a9a3c37d;hb=3941206233723cb45596b1ca54f00ab82e080268;hp=e37002918cb4891f645827dcef74dc7115429031;hpb=3630741c0d8c1d73fb7d888e1eb772e53f117105;p=nageru diff --git a/nageru/decklink_output.cpp b/nageru/decklink_output.cpp index e370029..00d8043 100644 --- a/nageru/decklink_output.cpp +++ b/nageru/decklink_output.cpp @@ -84,6 +84,9 @@ DeckLinkOutput::DeckLinkOutput(ResourcePool *resource_pool, QSurface *surface, u bool DeckLinkOutput::set_device(IDeckLink *decklink) { + if (decklink->QueryInterface(IID_IDeckLinkInput, (void**)&input) != S_OK) { + input = nullptr; + } if (decklink->QueryInterface(IID_IDeckLinkOutput, (void**)&output) != S_OK) { fprintf(stderr, "Warning: Card %u has no outputs\n", card_index); return false; @@ -130,7 +133,7 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) if (video_modes.empty()) { fprintf(stderr, "ERROR: No matching output modes for %dx%d found\n", width, height); - exit(1); + abort(); } should_quit.unquit(); @@ -141,19 +144,19 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) IDeckLinkConfiguration *config = nullptr; if (output->QueryInterface(IID_IDeckLinkConfiguration, (void**)&config) != S_OK) { fprintf(stderr, "Failed to get configuration interface for output card\n"); - exit(1); + abort(); } if (config->SetFlag(bmdDeckLinkConfigLowLatencyVideoOutput, true) != S_OK) { fprintf(stderr, "Failed to set low latency output\n"); - exit(1); + abort(); } if (config->SetInt(bmdDeckLinkConfigVideoOutputConnection, video_connection) != S_OK) { fprintf(stderr, "Failed to set video output connection for card %u\n", card_index); - exit(1); + abort(); } - if (config->SetFlag(bmdDeckLinkConfigUse1080pNotPsF, true) != S_OK) { + if (config->SetFlag(bmdDeckLinkConfigOutput1080pAsPsF, true) != S_OK) { fprintf(stderr, "Failed to set PsF flag for card\n"); - exit(1); + abort(); } if (config->SetFlag(bmdDeckLinkConfigSMPTELevelAOutput, true) != S_OK) { // This affects at least some no-name SDI->HDMI converters. @@ -167,12 +170,12 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) if (output->DoesSupportVideoMode(mode, pixel_format, bmdVideoOutputFlagDefault, &support, &display_mode) != S_OK) { fprintf(stderr, "Couldn't ask for format support\n"); - exit(1); + abort(); } if (support == bmdDisplayModeNotSupported) { fprintf(stderr, "Requested display mode not supported\n"); - exit(1); + abort(); } current_mode_flags = display_mode->GetFlags(); @@ -181,7 +184,7 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) BMDTimeScale time_scale; if (display_mode->GetFrameRate(&time_value, &time_scale) != S_OK) { fprintf(stderr, "Couldn't get frame rate\n"); - exit(1); + abort(); } metric_decklink_output_width_pixels = width; @@ -193,23 +196,32 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) display_mode->Release(); + if (input != nullptr) { + if (input->DisableVideoInput() != S_OK) { + fprintf(stderr, "Warning: Failed to disable video input for card %d\n", card_index); + } + if (input->DisableAudioInput() != S_OK) { + fprintf(stderr, "Warning: Failed to disable audio input for card %d\n", card_index); + } + } + HRESULT result = output->EnableVideoOutput(mode, bmdVideoOutputFlagDefault); if (result != S_OK) { fprintf(stderr, "Couldn't enable output with error 0x%x\n", result); - exit(1); + abort(); } if (output->SetScheduledFrameCompletionCallback(this) != S_OK) { fprintf(stderr, "Couldn't set callback\n"); - exit(1); + abort(); } assert(OUTPUT_FREQUENCY == 48000); if (output->EnableAudioOutput(bmdAudioSampleRate48kHz, bmdAudioSampleType32bitInteger, 2, bmdAudioOutputStreamTimestamped) != S_OK) { fprintf(stderr, "Couldn't enable audio output\n"); - exit(1); + abort(); } if (output->BeginAudioPreroll() != S_OK) { fprintf(stderr, "Couldn't begin audio preroll\n"); - exit(1); + abort(); } present_thread = thread([this]{ @@ -218,7 +230,7 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) if (!make_current(context, this->surface)) { printf("display=%p surface=%p context=%p curr=%p err=%d\n", eglGetCurrentDisplay(), this->surface, context, eglGetCurrentContext(), eglGetError()); - exit(1); + abort(); } present_thread_func(); delete_context(context); @@ -248,6 +260,15 @@ void DeckLinkOutput::end_output() frame_freelist.pop(); } } + + if (input != nullptr) { + input->Release(); + input = nullptr; + } + if (output != nullptr) { + output->Release(); + output = nullptr; + } } void DeckLinkOutput::send_frame(GLuint y_tex, GLuint cbcr_tex, YCbCrLumaCoefficients output_ycbcr_coefficients, const vector &input_frames, int64_t pts, int64_t duration) @@ -366,11 +387,11 @@ void DeckLinkOutput::wait_for_frame(int64_t pts, int *dropped_frames, int64_t *f if (!playback_started) { if (output->EndAudioPreroll() != S_OK) { fprintf(stderr, "Could not end audio preroll\n"); - exit(1); // TODO + abort(); // TODO } if (output->StartScheduledPlayback(base_pts, TIMEBASE, 1.0) != S_OK) { fprintf(stderr, "Could not start playback\n"); - exit(1); // TODO + abort(); // TODO } playback_started = true; } @@ -418,7 +439,7 @@ uint32_t DeckLinkOutput::pick_video_mode(uint32_t mode) const } // Prioritize 59.94 > 60 > 29.97. If none of those are found, then pick the highest one. - for (const pair &desired : vector>{ { 60000, 1001 }, { 60, 0 }, { 30000, 1001 } }) { + for (const pair &desired : vector>{ { 60000, 1001 }, { 60, 1 }, { 30000, 1001 } }) { for (const auto &it : video_modes) { if (it.second.frame_rate_num * desired.second == desired.first * it.second.frame_rate_den) { return it.first; @@ -462,12 +483,12 @@ HRESULT DeckLinkOutput::ScheduledFrameCompleted(/* in */ IDeckLinkVideoFrame *co ++metric_decklink_output_completed_frames_late; break; case bmdOutputFrameDropped: - fprintf(stderr, "Output frame was dropped (pts=%" PRId64 "ld)\n", frame->pts); + fprintf(stderr, "Output frame was dropped (pts=%" PRId64 ")\n", frame->pts); fprintf(stderr, "Consider increasing --output-buffer-frames if this persists.\n"); ++metric_decklink_output_completed_frames_dropped; break; case bmdOutputFrameFlushed: - fprintf(stderr, "Output frame was flushed (pts=%" PRId64 "ld)\n", frame->pts); + fprintf(stderr, "Output frame was flushed (pts=%" PRId64 ")\n", frame->pts); ++metric_decklink_output_completed_frames_flushed; break; default: @@ -543,11 +564,11 @@ void DeckLinkOutput::present_thread_func() for ( ;; ) { unique_ptr frame; { - unique_lock lock(frame_queue_mutex); - frame_queues_changed.wait(lock, [this]{ - return should_quit.should_quit() || !pending_video_frames.empty(); - }); - if (should_quit.should_quit()) { + unique_lock lock(frame_queue_mutex); + frame_queues_changed.wait(lock, [this]{ + return should_quit.should_quit() || !pending_video_frames.empty(); + }); + if (should_quit.should_quit()) { return; } frame = move(pending_video_frames.front());