}
-/** 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;
};
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 ();
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) {
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;
/* 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);
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;