summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2021-10-15 22:33:46 +0200
committerCarl Hetherington <cth@carlh.net>2021-10-16 10:13:26 +0200
commitc8fa584045ad65283a85015f18ee8789ddf881d1 (patch)
tree9887fe131c628a27555afcf705c565ba91ad9c16
parent0e896f9f37db001f34c876ed5fc50e874f96ae09 (diff)
Always block waiting for audio when exporting.v2.15.169
Otherwise if there is non available we'll insert silence and potentially push the audio out of sync (late). May help with #2098.
-rw-r--r--src/lib/butler.cc16
-rw-r--r--src/lib/butler.h2
-rw-r--r--src/lib/ffmpeg_encoder.cc2
-rw-r--r--src/wx/film_viewer.cc2
-rw-r--r--test/butler_test.cc2
-rw-r--r--test/dcp_playback_test.cc2
6 files changed, 17 insertions, 9 deletions
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<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;
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<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 ();
diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc
index e1081f518..81ea3a9dd 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, audio_frames);
+ _butler->get_audio (Butler::Behaviour::BLOCKING, interleaved, audio_frames);
/* XXX: inefficient; butler interleaves and we deinterleave again */
float* p = interleaved;
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<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;
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 0e57acae4..66a735798 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, 2000);
+ butler->get_audio (Butler::Behaviour::BLOCKING, audio_buffer, 2000);
p.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), VideoRange::FULL, true);
}
delete[] audio_buffer;