X-Git-Url: https://git.sesse.net/?a=blobdiff_plain;f=nageru%2Fdecklink_output.cpp;fp=nageru%2Fdecklink_output.cpp;h=91fbd4095c23c94532823a4158e223845ae43b5c;hb=403942c08c2403321fcfd5e6c5f2e6aa7c099874;hp=56a184e99b326cc6ab3107c985f59bf0345bd384;hpb=c443b4ca0f527ed039d4b1014c1dd654c230eb15;p=nageru diff --git a/nageru/decklink_output.cpp b/nageru/decklink_output.cpp index 56a184e..91fbd40 100644 --- a/nageru/decklink_output.cpp +++ b/nageru/decklink_output.cpp @@ -131,10 +131,11 @@ bool DeckLinkOutput::set_device(IDeckLink *decklink, IDeckLinkInput *input_arg) return true; } -void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) +void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts, bool is_master_card_arg) { assert(output); assert(!playback_initiated); + this->is_master_card = is_master_card_arg; if (video_modes.empty()) { fprintf(stderr, "ERROR: No matching output modes for %dx%d found\n", width, height); @@ -224,9 +225,13 @@ void DeckLinkOutput::start_output(uint32_t mode, int64_t base_pts) fprintf(stderr, "Couldn't enable audio output\n"); abort(); } - if (output->BeginAudioPreroll() != S_OK) { - fprintf(stderr, "Couldn't begin audio preroll\n"); - abort(); + if (is_master_card) { + if (output->BeginAudioPreroll() != S_OK) { + fprintf(stderr, "Couldn't begin audio preroll\n"); + abort(); + } + } else { + playback_started = true; } present_thread = thread([this]{ @@ -253,7 +258,9 @@ void DeckLinkOutput::end_output() present_thread.join(); playback_initiated = false; - output->StopScheduledPlayback(0, nullptr, 0); + if (is_master_card) { + output->StopScheduledPlayback(0, nullptr, 0); + } output->DisableVideoOutput(); output->DisableAudioOutput(); @@ -348,13 +355,20 @@ void DeckLinkOutput::send_audio(int64_t pts, const std::vector &samples) } uint32_t frames_written; - HRESULT result = output->ScheduleAudioSamples(int_samples.get(), samples.size() / 2, - pts, TIMEBASE, &frames_written); + HRESULT result; + if (is_master_card) { + result = output->ScheduleAudioSamples(int_samples.get(), samples.size() / 2, + pts, TIMEBASE, &frames_written); + } else { + result = output->WriteAudioSamplesSync(int_samples.get(), samples.size() / 2, + &frames_written); + } if (result != S_OK) { - fprintf(stderr, "ScheduleAudioSamples(pts=%" PRId64 ") failed (result=0x%08x)\n", pts, result); + fprintf(stderr, "write audio to DeckLink (pts=%" PRId64 ") failed (result=0x%08x)\n", pts, result); } else { - if (frames_written != samples.size() / 2) { - fprintf(stderr, "ScheduleAudioSamples() returned short write (%u/%zu)\n", frames_written, samples.size() / 2); + // Non-master card is not really synchronized on audio at all, so we don't warn on it. + if (frames_written != samples.size() / 2 && is_master_card) { + fprintf(stderr, "write audio to DeckLink returned short write (%u/%zu)\n", frames_written, samples.size() / 2); } } metric_decklink_output_scheduled_samples += samples.size() / 2; @@ -593,16 +607,24 @@ void DeckLinkOutput::present_thread_func() // Release any input frames we needed to render this frame. frame->input_frames.clear(); - 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) { - scheduled_frames.insert(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); + if (is_master_card) { + 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) { + scheduled_frames.insert(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); + frame_freelist.push(move(frame)); + } + } else { + HRESULT res = output->DisplayVideoFrameSync(frame.get()); + if (res != S_OK) { + fprintf(stderr, "Could not schedule video frame! (error=0x%08x)\n", res); + } frame_freelist.push(move(frame)); } }