X-Git-Url: https://git.carlh.net/gitweb/?a=blobdiff_plain;f=src%2Flib%2Fbutler.cc;h=386e7f9db78a90b723bb6b5463f5bed802ab20b9;hb=1fe6bd7f8ba059322b8357b2210f0fd590567ce2;hp=112778e25184794f7f72e20dd1f790192854c7be;hpb=3f8e7d70bb81890246f9cea54cbc494b027dcc53;p=dcpomatic.git diff --git a/src/lib/butler.cc b/src/lib/butler.cc index 112778e25..386e7f9db 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -62,7 +62,10 @@ Butler::Butler (shared_ptr player, shared_ptr log, AudioMapping aud , _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)); + _player_audio_connection = _player->Audio.connect (bind (&Butler::audio, this, _1, _2)); + _player_text_connection = _player->Text.connect (bind (&Butler::text, this, _1, _2, _3)); + _player_changed_connection = _player->Changed.connect (bind (&Butler::return_seek, this, _2)); + _player_not_changed_connection = _player->NotChanged.connect (bind (&Butler::return_seek, this, false)); _thread = new boost::thread (bind (&Butler::thread, this)); #ifdef DCPOMATIC_LINUX pthread_setname_np (_thread->native_handle(), "butler"); @@ -202,19 +205,38 @@ Butler::get_video () return r; } +optional > +Butler::get_closed_caption () +{ + boost::mutex::scoped_lock lm (_mutex); + return _closed_caption.get (); +} + void Butler::seek (DCPTime position, bool accurate) { boost::mutex::scoped_lock lm (_mutex); + seek_unlocked (position, accurate); +} + +void +Butler::seek_unlocked (DCPTime position, bool accurate) +{ if (_died) { return; } - _video.clear (); - _audio.clear (); _finished = false; _pending_seek_position = position; _pending_seek_accurate = accurate; + + { + boost::mutex::scoped_lock lm (_buffers_mutex); + _video.clear (); + _audio.clear (); + _closed_caption.clear (); + } + _summon.notify_all (); } @@ -234,17 +256,20 @@ void Butler::video (shared_ptr video, DCPTime time) { boost::mutex::scoped_lock lm (_mutex); + if (_pending_seek_position) { /* Don't store any video while a seek is pending */ return; } _prepare_service.post (bind (&Butler::prepare, this, weak_ptr(video))); + + boost::mutex::scoped_lock lm2 (_buffers_mutex); _video.put (video, time); } void -Butler::audio (shared_ptr audio) +Butler::audio (shared_ptr audio, DCPTime time) { { boost::mutex::scoped_lock lm (_mutex); @@ -254,19 +279,20 @@ Butler::audio (shared_ptr audio) } } - _audio.put (remap (audio, _audio_channels, _audio_mapping)); + boost::mutex::scoped_lock lm2 (_buffers_mutex); + _audio.put (remap (audio, _audio_channels, _audio_mapping), time); } /** Try to get `frames' frames of audio and copy it into `out'. Silence * will be filled if no audio is available. - * @return true if there was a buffer underrun, otherwise false. + * @return time of this audio, or unset if there was a buffer underrun. */ -bool +optional Butler::get_audio (float* out, Frame frames) { - bool const underrun = _audio.get (out, _audio_channels, frames); + optional t = _audio.get (out, _audio_channels, frames); _summon.notify_all (); - return underrun; + return t; } void @@ -282,3 +308,37 @@ Butler::memory_used () const /* XXX: should also look at _audio.memory_used() */ return _video.memory_used(); } + +void +Butler::return_seek (bool frequent) +{ + boost::mutex::scoped_lock lm (_mutex); + if (_died || _pending_seek_position || frequent) { + return; + } + + DCPTime seek_to; + DCPTime next = _video.get().second; + if (_awaiting && _awaiting > next) { + /* We have recently done a player_changed seek and our buffers haven't been refilled yet, + so assume that we're seeking to the same place as last time. + */ + seek_to = *_awaiting; + } else { + seek_to = next; + } + + seek_unlocked (seek_to, true); + _awaiting = seek_to; +} + +void +Butler::text (PlayerText pt, TextType type, DCPTimePeriod period) +{ + if (type != TEXT_CLOSED_CAPTION) { + return; + } + + boost::mutex::scoped_lock lm2 (_buffers_mutex); + _closed_caption.put (make_pair(pt, period)); +}