Always block waiting for audio when exporting.
authorCarl Hetherington <cth@carlh.net>
Fri, 15 Oct 2021 20:33:46 +0000 (22:33 +0200)
committerCarl Hetherington <cth@carlh.net>
Fri, 15 Oct 2021 20:42:48 +0000 (22:42 +0200)
Otherwise if there is non available we'll insert silence and potentially
push the audio out of sync (late).  May help with #2098.

src/lib/butler.cc
src/lib/butler.h
src/lib/ffmpeg_encoder.cc
src/wx/film_viewer.cc
test/butler_test.cc
test/dcp_playback_test.cc

index f19e1e0808b13ca92ca3e712b34d15dcea212502..686fa9f7272849c70f035ef836f17be50096e91c 100644 (file)
@@ -373,13 +373,21 @@ Butler::audio (shared_ptr<AudioBuffers> 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<DCPTime>
-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;
index 529b7383d0b30a9fb84cef51302a26f6ac60cbca..c7e71658da25889107d033147e62b16897f92f4d 100644 (file)
@@ -78,7 +78,7 @@ public:
        };
 
        std::pair<std::shared_ptr<PlayerVideo>, dcpomatic::DCPTime> get_video (Behaviour behaviour, Error* e = nullptr);
-       boost::optional<dcpomatic::DCPTime> get_audio (float* out, Frame frames);
+       boost::optional<dcpomatic::DCPTime> get_audio (Behaviour behaviour, float* out, Frame frames);
        boost::optional<TextRingBuffers::Data> get_closed_caption ();
 
        void disable_audio ();
index d29e191edf018fc508ade75a55140765f2f46957..6dc3a83d40bfda813b0e1546649bcd831f27048c 100644 (file)
@@ -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) {
index 22de7b5934c28751b8d73b2c14a3b56a24273249..e678c6aa3045cc9057d29c77ecd6cafbe2f69cbe 100644 (file)
@@ -649,7 +649,7 @@ int
 FilmViewer::audio_callback (void* out_p, unsigned int frames)
 {
        while (true) {
-               auto t = _butler->get_audio (reinterpret_cast<float*> (out_p), frames);
+               auto t = _butler->get_audio (Butler::Behaviour::NON_BLOCKING, reinterpret_cast<float*> (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;
index e577793342e30c9835871cc5eb5dc78f1d062273..3d524a3b258382d98f82786224fae38a69793eb2 100644 (file)
@@ -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);
index 892825753378bb852ab6ed154b74482a81d094d8..5117be9edd7566ecaa0a94aa7e959bcee235e7d6 100644 (file)
@@ -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);
        }
 }