/** Minimum audio readahead in frames; should never be reached unless there are bugs in Player */
#define MAXIMUM_AUDIO_READAHEAD (48000*60)
-#define LOG_WARNING(...) _film.lock()->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_WARNING);
+#define LOG_WARNING(...) _log->log (String::compose(__VA_ARGS__), LogEntry::TYPE_WARNING);
-Butler::Butler (weak_ptr<const Film> film, shared_ptr<Player> player, AudioMapping audio_mapping, int audio_channels)
- : _film (film)
- , _player (player)
+Butler::Butler (shared_ptr<Player> player, shared_ptr<Log> log, AudioMapping audio_mapping, int audio_channels)
+ : _player (player)
+ , _log (log)
+ , _prepare_work (new boost::asio::io_service::work (_prepare_service))
, _pending_seek_accurate (false)
, _finished (false)
, _died (false)
_player_audio_connection = _player->Audio.connect (bind (&Butler::audio, this, _1));
_player_changed_connection = _player->Changed.connect (bind (&Butler::player_changed, this));
_thread = new boost::thread (bind (&Butler::thread, this));
+
+ /* Create some threads to do work on the PlayerVideos we are creating; at present this is used to
+ multi-thread JPEG2000 decoding.
+ */
+ for (size_t i = 0; i < boost::thread::hardware_concurrency(); ++i) {
+ _prepare_pool.create_thread (bind (&boost::asio::io_service::run, &_prepare_service));
+ }
}
Butler::~Butler ()
_stop_thread = true;
}
+ _prepare_work.reset ();
+ _prepare_pool.join_all ();
+ _prepare_service.stop ();
+
_thread->interrupt ();
try {
_thread->join ();
_summon.notify_all ();
}
+void
+Butler::prepare (weak_ptr<PlayerVideo> weak_video) const
+{
+ shared_ptr<PlayerVideo> video = weak_video.lock ();
+ /* If the weak_ptr cannot be locked the video obviously no longer requires any work */
+ if (video) {
+ video->prepare ();
+ }
+}
+
void
Butler::video (shared_ptr<PlayerVideo> video, DCPTime time)
{
}
}
+ _prepare_service.post (bind (&Butler::prepare, this, weak_ptr<PlayerVideo>(video)));
_video.put (video, time);
}
void
Butler::player_changed ()
{
- optional<DCPTime> t;
-
- {
- boost::mutex::scoped_lock lm (_mutex);
- t = _video.earliest ();
- }
-
- if (t) {
- seek (*t, true);
- } else {
- _video.clear ();
- _audio.clear ();
- }
+ _video.clear ();
+ _audio.clear ();
}
-void
+/** 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.
+ */
+bool
Butler::get_audio (float* out, Frame frames)
{
- _audio.get (out, _audio_channels, frames);
+ bool const underrun = _audio.get (out, _audio_channels, frames);
_summon.notify_all ();
+ return underrun;
}
void