X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fdecklink_output.cpp;h=20de9229fdc35e42502626c40b571f5741150f4c;hb=ccc2b89c9cf879ccbd948e169a029917cc16f0ee;hp=f1e06e8902cc268f4098bf74c363698725155e1b;hpb=9a0f617093e7cde02a824b90f82f129c47193939;p=nageru diff --git a/nageru/decklink_output.cpp b/nageru/decklink_output.cpp index f1e06e8..20de922 100644 --- a/nageru/decklink_output.cpp +++ b/nageru/decklink_output.cpp @@ -82,11 +82,9 @@ DeckLinkOutput::DeckLinkOutput(ResourcePool *resource_pool, QSurface *surface, u }); } -bool DeckLinkOutput::set_device(IDeckLink *decklink) +bool DeckLinkOutput::set_device(IDeckLink *decklink, IDeckLinkInput *input_arg) { - if (decklink->QueryInterface(IID_IDeckLinkInput, (void**)&input) != S_OK) { - input = nullptr; - } + input_arg = input; if (decklink->QueryInterface(IID_IDeckLinkOutput, (void**)&output) != S_OK) { fprintf(stderr, "Warning: Card %u has no outputs\n", card_index); return false; @@ -154,7 +152,7 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) fprintf(stderr, "Failed to set video output connection for card %u\n", card_index); 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"); abort(); } @@ -255,7 +253,7 @@ void DeckLinkOutput::end_output() // Wait until all frames are accounted for, and free them. { unique_lock lock(frame_queue_mutex); - while (!(frame_freelist.empty() && num_frames_in_flight == 0)) { + while (!(frame_freelist.empty() && scheduled_frames.empty())) { frame_queues_changed.wait(lock, [this]{ return !frame_freelist.empty(); }); frame_freelist.pop(); } @@ -439,7 +437,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; @@ -503,7 +501,8 @@ HRESULT DeckLinkOutput::ScheduledFrameCompleted(/* in */ IDeckLinkVideoFrame *co { lock_guard lock(frame_queue_mutex); frame_freelist.push(unique_ptr(frame)); - --num_frames_in_flight; + assert(scheduled_frames.front() == frame); + scheduled_frames.pop_front(); --metric_decklink_output_inflight_frames; } @@ -564,17 +563,15 @@ 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()); pending_video_frames.pop(); - ++num_frames_in_flight; - ++metric_decklink_output_inflight_frames; } for ( ;; ) { @@ -601,15 +598,14 @@ void DeckLinkOutput::present_thread_func() BMDTimeValue pts = frame->pts; BMDTimeValue duration = frame->duration; HRESULT res = output->ScheduleVideoFrame(frame.get(), pts, duration, TIMEBASE); + lock_guard lock(frame_queue_mutex); if (res == S_OK) { - frame.release(); // Owned by the driver now. + scheduled_frames.push_back(frame.release()); // Owned by the driver now. + ++metric_decklink_output_inflight_frames; } else { fprintf(stderr, "Could not schedule video frame! (error=0x%08x)\n", res); - lock_guard lock(frame_queue_mutex); frame_freelist.push(move(frame)); - --num_frames_in_flight; - --metric_decklink_output_inflight_frames; } } }