X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fbutler.cc;h=f7e7222725455c71cb8c78590c8c4fb428dcba72;hb=d8ea1796f34ff894b148a0af78c0a547e0496ee1;hp=96546a673fa70c474b18e8f15fb1066a206540fe;hpb=f06c1a6f6748938b732bf3991e87fe71e6d8a9d9;p=dcpomatic.git diff --git a/src/lib/butler.cc b/src/lib/butler.cc index 96546a673..f7e722272 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -41,9 +41,11 @@ Butler::Butler (weak_ptr film, shared_ptr player, AudioMappi , _player (player) , _pending_seek_accurate (false) , _finished (false) + , _died (false) + , _stop_thread (false) , _audio_mapping (audio_mapping) , _audio_channels (audio_channels) - , _stop_thread (false) + , _disable_audio (false) { _player_video_connection = _player->Video.connect (bind (&Butler::video, this, _1, _2)); _player_audio_connection = _player->Audio.connect (bind (&Butler::audio, this, _1, _2)); @@ -53,7 +55,11 @@ Butler::Butler (weak_ptr film, shared_ptr player, AudioMappi Butler::~Butler () { - _stop_thread = true; + { + boost::mutex::scoped_lock lm (_mutex); + _stop_thread = true; + } + _thread->interrupt (); try { _thread->join (); @@ -63,6 +69,13 @@ Butler::~Butler () delete _thread; } +/** Caller must hold a lock on _mutex */ +bool +Butler::should_run () const +{ + return (_video.size() < VIDEO_READAHEAD || (!_disable_audio && _audio.size() < AUDIO_READAHEAD)) && !_stop_thread && !_finished && !_died; +} + void Butler::thread () try @@ -71,12 +84,13 @@ try boost::mutex::scoped_lock lm (_mutex); /* Wait until we have something to do */ - while ((_video.size() >= VIDEO_READAHEAD && _audio.size() >= AUDIO_READAHEAD && !_pending_seek_position) || _stop_thread) { + while (!should_run() && !_pending_seek_position) { _summon.wait (lm); } /* Do any seek that has been requested */ if (_pending_seek_position) { + _finished = false; _player->seek (*_pending_seek_position, _pending_seek_accurate); _pending_seek_position = optional (); } @@ -85,19 +99,28 @@ try while lm is unlocked, as in that state nothing will be added to _video/_audio. */ - while ((_video.size() < VIDEO_READAHEAD || _audio.size() < AUDIO_READAHEAD) && !_pending_seek_position && !_stop_thread) { + while (should_run() && !_pending_seek_position) { lm.unlock (); - if (_player->pass ()) { + bool const r = _player->pass (); + lm.lock (); + if (r) { _finished = true; _arrived.notify_all (); break; } - lm.lock (); _arrived.notify_all (); } } } catch (boost::thread_interrupted) { /* The butler thread is being terminated */ + boost::mutex::scoped_lock lm (_mutex); + _finished = true; + _arrived.notify_all (); +} catch (...) { + store_current (); + boost::mutex::scoped_lock lm (_mutex); + _died = true; + _arrived.notify_all (); } pair, DCPTime> @@ -106,11 +129,11 @@ Butler::get_video () boost::mutex::scoped_lock lm (_mutex); /* Wait for data if we have none */ - while (_video.empty() && !_finished) { + while (_video.empty() && !_finished && !_died) { _arrived.wait (lm); } - if (_finished) { + if (_video.empty()) { return make_pair (shared_ptr(), DCPTime()); } @@ -123,7 +146,12 @@ void Butler::seek (DCPTime position, bool accurate) { boost::mutex::scoped_lock lm (_mutex); + if (_died) { + return; + } + _video.clear (); + _audio.clear (); _finished = false; _pending_seek_position = position; _pending_seek_accurate = accurate; @@ -149,8 +177,8 @@ Butler::audio (shared_ptr audio, DCPTime time) { { boost::mutex::scoped_lock lm (_mutex); - if (_pending_seek_position) { - /* Don't store any audio while a seek is pending */ + if (_pending_seek_position || _disable_audio) { + /* Don't store any audio while a seek is pending, or if audio is disabled */ return; } } @@ -170,12 +198,22 @@ Butler::player_changed () if (t) { seek (*t, true); + } else { + _video.clear (); + _audio.clear (); } } void Butler::get_audio (float* out, Frame frames) { - _audio.get (reinterpret_cast (out), _audio_channels, frames); + _audio.get (out, _audio_channels, frames); _summon.notify_all (); } + +void +Butler::disable_audio () +{ + boost::mutex::scoped_lock lm (_mutex); + _disable_audio = true; +}