/** Video readahead in frames */
#define VIDEO_READAHEAD 10
+/** Audio readahead in frames */
+#define AUDIO_READAHEAD (48000*5)
Butler::Butler (weak_ptr<const Film> film, shared_ptr<Player> player, AudioMapping audio_mapping, int audio_channels)
: _film (film)
, _finished (false)
, _audio_mapping (audio_mapping)
, _audio_channels (audio_channels)
+ , _stop_thread (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));
Butler::~Butler ()
{
+ _stop_thread = true;
_thread->interrupt ();
try {
_thread->join ();
void
Butler::thread ()
+try
{
while (true) {
boost::mutex::scoped_lock lm (_mutex);
/* Wait until we have something to do */
- while (_video.size() >= VIDEO_READAHEAD && !_pending_seek_position) {
+ while ((_video.size() >= VIDEO_READAHEAD && _audio.size() >= AUDIO_READAHEAD && !_pending_seek_position) || _stop_thread) {
_summon.wait (lm);
}
_pending_seek_position = optional<DCPTime> ();
}
- /* Fill _video. Don't try to carry on if a pending seek appears
+ /* Fill _video and _audio. Don't try to carry on if a pending seek appears
while lm is unlocked, as in that state nothing will be added to
- _video.
+ _video/_audio.
*/
- while (_video.size() < VIDEO_READAHEAD && !_pending_seek_position) {
+ while ((_video.size() < VIDEO_READAHEAD || _audio.size() < AUDIO_READAHEAD) && !_pending_seek_position && !_stop_thread) {
lm.unlock ();
if (_player->pass ()) {
_finished = true;
_arrived.notify_all ();
}
}
+} catch (boost::thread_interrupted) {
+ /* The butler thread is being terminated */
}
pair<shared_ptr<PlayerVideo>, DCPTime>
void
Butler::audio (shared_ptr<AudioBuffers> audio, DCPTime time)
{
+ {
+ boost::mutex::scoped_lock lm (_mutex);
+ if (_pending_seek_position) {
+ /* Don't store any audio while a seek is pending */
+ return;
+ }
+ }
+ _audio.put (audio, time);
}
void