From: Carl Hetherington Date: Fri, 15 Oct 2021 20:33:46 +0000 (+0200) Subject: Always block waiting for audio when exporting. X-Git-Tag: checked-for-v2.16.x~248 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=4d0356840c2f400b0376230a3d07f57897275f99 Always block waiting for audio when exporting. Otherwise if there is non available we'll insert silence and potentially push the audio out of sync (late). May help with #2098. --- diff --git a/src/lib/butler.cc b/src/lib/butler.cc index f19e1e080..686fa9f72 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -373,13 +373,21 @@ Butler::audio (shared_ptr audio, DCPTime time, int frame_rate) } -/** Try to get `frames' frames of audio and copy it into `out'. Silence - * will be filled if no audio is available. - * @return time of this audio, or unset if there was a buffer underrun. +/** Try to get `frames' frames of audio and copy it into `out'. + * @param behaviour BLOCKING if we should block until audio is available. If behaviour is NON_BLOCKING + * and no audio is immediately available the buffer will be filled with silence and boost::none + * will be returned. + * @return time of this audio, or unset if blocking was false and no data was available. */ optional -Butler::get_audio (float* out, Frame frames) +Butler::get_audio (Behaviour behaviour, float* out, Frame frames) { + boost::mutex::scoped_lock lm (_mutex); + + while (behaviour == Behaviour::BLOCKING && !_finished && !_died && _audio.size() < frames) { + _arrived.wait (lm); + } + auto t = _audio.get (out, _audio_channels, frames); _summon.notify_all (); return t; diff --git a/src/lib/butler.h b/src/lib/butler.h index 529b7383d..c7e71658d 100644 --- a/src/lib/butler.h +++ b/src/lib/butler.h @@ -78,7 +78,7 @@ public: }; std::pair, dcpomatic::DCPTime> get_video (Behaviour behaviour, Error* e = nullptr); - boost::optional get_audio (float* out, Frame frames); + boost::optional get_audio (Behaviour behaviour, float* out, Frame frames); boost::optional get_closed_caption (); void disable_audio (); diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc index d29e191ed..6dc3a83d4 100644 --- a/src/lib/ffmpeg_encoder.cc +++ b/src/lib/ffmpeg_encoder.cc @@ -204,7 +204,7 @@ FFmpegEncoder::go () waker.nudge (); - _butler->get_audio (interleaved.data(), audio_frames); + _butler->get_audio (Butler::Behaviour::BLOCKING, interleaved.data(), audio_frames); /* XXX: inefficient; butler interleaves and we deinterleave again */ float* p = interleaved.data(); for (int j = 0; j < audio_frames; ++j) { diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 22de7b593..e678c6aa3 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -649,7 +649,7 @@ int FilmViewer::audio_callback (void* out_p, unsigned int frames) { while (true) { - auto t = _butler->get_audio (reinterpret_cast (out_p), frames); + auto t = _butler->get_audio (Butler::Behaviour::NON_BLOCKING, reinterpret_cast (out_p), frames); if (!t || DCPTime(uncorrected_time() - *t) < one_video_frame()) { /* There was an underrun or this audio is on time; carry on */ break; diff --git a/test/butler_test.cc b/test/butler_test.cc index e57779334..3d524a3b2 100644 --- a/test/butler_test.cc +++ b/test/butler_test.cc @@ -67,7 +67,7 @@ BOOST_AUTO_TEST_CASE (butler_test1) /* XXX: check the frame contents */ float buffer[256 * 6]; - BOOST_REQUIRE (butler.get_audio(buffer, 256) == DCPTime()); + BOOST_REQUIRE (butler.get_audio(Butler::Behaviour::BLOCKING, buffer, 256) == DCPTime()); for (int i = 0; i < 256; ++i) { BOOST_REQUIRE_EQUAL (buffer[i * 6 + 0], 0); BOOST_REQUIRE_EQUAL (buffer[i * 6 + 1], 0); diff --git a/test/dcp_playback_test.cc b/test/dcp_playback_test.cc index 892825753..5117be9ed 100644 --- a/test/dcp_playback_test.cc +++ b/test/dcp_playback_test.cc @@ -62,7 +62,7 @@ BOOST_AUTO_TEST_CASE (dcp_playback_test) break; } /* assuming DCP is 24fps/48kHz */ - butler->get_audio (audio_buffer.data(), 2000); + butler->get_audio (Butler::Behaviour::BLOCKING, audio_buffer.data(), 2000); p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true); } }