bool
Butler::should_run () const
{
- if (_video.size() >= MAXIMUM_VIDEO_READAHEAD * 10) {
- /* This is way too big */
- optional<DCPTime> pos = _audio.peek();
- if (pos) {
- throw ProgrammingError
- (__FILE__, __LINE__, String::compose ("Butler video buffers reached %1 frames (audio is %2 at %3)", _video.size(), _audio.size(), pos->get()));
- } else {
- throw ProgrammingError
- (__FILE__, __LINE__, String::compose ("Butler video buffers reached %1 frames (audio is %2)", _video.size(), _audio.size()));
+ auto check_video_much_too_big = [this](VideoType type) {
+ if (_video[type].size() >= MAXIMUM_VIDEO_READAHEAD * 10) {
+ /* This is way too big */
+ auto pos = _audio.peek();
+ if (pos) {
+ throw ProgrammingError
+ (__FILE__, __LINE__, String::compose("Butler video (%1) buffers reached %2 frames (audio is %3 at %4)", video_type_to_string(type), _video[type].size(), _audio.size(), pos->get()));
+ } else {
+ throw ProgrammingError
+ (__FILE__, __LINE__, String::compose("Butler video (%1) buffers reached %2 frames (audio is %3)", video_type_to_string(type), _video[type].size(), _audio.size()));
+ }
}
- }
+ };
+
+ check_video_much_too_big(VideoType::MAIN);
+ check_video_much_too_big(VideoType::SIGN_LANGUAGE);
if (_audio.size() >= MAXIMUM_AUDIO_READAHEAD * 10) {
/* This is way too big */
auto pos = _audio.peek();
if (pos) {
throw ProgrammingError
- (__FILE__, __LINE__, String::compose ("Butler audio buffers reached %1 frames at %2 (video is %3)", _audio.size(), pos->get(), _video.size()));
+ (__FILE__, __LINE__, String::compose ("Butler audio buffers reached %1 frames at %2 (main video is %3)", _audio.size(), pos->get(), _video[VideoType::MAIN].size()));
} else {
throw ProgrammingError
- (__FILE__, __LINE__, String::compose ("Butler audio buffers reached %1 frames (video is %3)", _audio.size(), _video.size()));
+ (__FILE__, __LINE__, String::compose ("Butler audio buffers reached %1 frames (main video is %3)", _audio.size(), _video[VideoType::MAIN].size()));
}
}
- if (_video.size() >= MAXIMUM_VIDEO_READAHEAD * 2) {
- LOG_WARNING ("Butler video buffers reached %1 frames (audio is %2)", _video.size(), _audio.size());
- }
+ auto check_video_too_big = [this](VideoType type) {
+ if (_video[type].size() >= MAXIMUM_VIDEO_READAHEAD * 2) {
+ LOG_WARNING ("Butler video buffers reached %1 frames (audio is %2)", _video[type].size(), _audio.size());
+ }
+ };
+
+ check_video_too_big(VideoType::MAIN);
+ check_video_too_big(VideoType::SIGN_LANGUAGE);
if (_audio.size() >= MAXIMUM_AUDIO_READAHEAD * 2) {
- LOG_WARNING ("Butler audio buffers reached %1 frames (video is %2)", _audio.size(), _video.size());
+ LOG_WARNING ("Butler audio buffers reached %1 frames (main video is %2)", _audio.size(), _video[VideoType::MAIN].size());
}
if (_stop_thread || _finished || _died || _suspended) {
return false;
}
- if (_video.size() < MINIMUM_VIDEO_READAHEAD || (!_disable_audio && _audio.size() < MINIMUM_AUDIO_READAHEAD)) {
+ if (_video[VideoType::MAIN].size() < MINIMUM_VIDEO_READAHEAD
+ || (_player.have_sign_language() && _video[VideoType::SIGN_LANGUAGE].size() < MINIMUM_VIDEO_READAHEAD)
+ || (!_disable_audio && _audio.size() < MINIMUM_AUDIO_READAHEAD)
+ ) {
/* Definitely do run: we need data */
return true;
}
/* Run if we aren't full of video or audio */
- return (_video.size() < MAXIMUM_VIDEO_READAHEAD) && (_audio.size() < MAXIMUM_AUDIO_READAHEAD);
+ return _video[VideoType::MAIN].size() < MAXIMUM_VIDEO_READAHEAD
+ && _video[VideoType::SIGN_LANGUAGE].size() < MAXIMUM_VIDEO_READAHEAD
+ && (_audio.size() < MAXIMUM_AUDIO_READAHEAD);
}
* @param e if non-0 this is filled with an error code (if an error occurs) or is untouched if no error occurs.
*/
pair<shared_ptr<PlayerVideo>, DCPTime>
-Butler::get_video (Behaviour behaviour, Error* e)
+Butler::get_video(VideoType type, Behaviour behaviour, Error* e)
{
boost::mutex::scoped_lock lm (_mutex);
}
};
- if (_video.empty() && (_finished || _died || (_suspended && behaviour == Behaviour::NON_BLOCKING))) {
+ if (_video[type].empty() && (_finished || _died || (_suspended && behaviour == Behaviour::NON_BLOCKING))) {
setup_error (e, Error::Code::AGAIN);
- return make_pair(shared_ptr<PlayerVideo>(), DCPTime());
+ return {};
}
/* Wait for data if we have none */
- while (_video.empty() && !_finished && !_died) {
+ while (_video[type].empty() && !_finished && !_died) {
_arrived.wait (lm);
}
- if (_video.empty()) {
+ if (_video[type].empty()) {
setup_error (e, Error::Code::NONE);
- return make_pair(shared_ptr<PlayerVideo>(), DCPTime());
+ return {};
}
- auto const r = _video.get ();
+ auto const r = _video[type].get();
_summon.notify_all ();
return r;
}
_pending_seek_position = position;
_pending_seek_accurate = accurate;
- _video.clear ();
+ _video[VideoType::MAIN].clear();
+ _video[VideoType::SIGN_LANGUAGE].clear();
_audio.clear ();
_closed_caption.clear ();
_prepare_service.post (bind(&Butler::prepare, this, weak_ptr<PlayerVideo>(video)));
- _video.put (video, time);
+ _video[video->type()].put(video, time);
}
pair<size_t, string>
Butler::memory_used () const
{
- /* XXX: should also look at _audio.memory_used() */
- return _video.memory_used();
+ /* XXX: should also look at _audio and _video[VideoType::SIGN_LANGUAGE] */
+ return _video[VideoType::MAIN].memory_used();
}
if (type == ChangeType::DONE) {
auto film = _film.lock();
if (film) {
- _video.reset_metadata(film, _player.video_container_size(VideoType::MAIN));
+ _video[VideoType::MAIN].reset_metadata(film, _player.video_container_size(VideoType::MAIN));
+ _video[VideoType::SIGN_LANGUAGE].reset_metadata(film, _player.video_container_size(VideoType::SIGN_LANGUAGE));
}
}
return;
}
DCPTime seek_to;
- auto next = _video.get().second;
+ auto next = _video[VideoType::MAIN].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.
Butler::Audio::ENABLED
);
- BOOST_CHECK (butler.get_video(Butler::Behaviour::BLOCKING, 0).second == DCPTime());
- BOOST_CHECK (butler.get_video(Butler::Behaviour::BLOCKING, 0).second == DCPTime::from_frames(1, 24));
- BOOST_CHECK (butler.get_video(Butler::Behaviour::BLOCKING, 0).second == DCPTime::from_frames(2, 24));
+ BOOST_CHECK (butler.get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0).second == DCPTime());
+ BOOST_CHECK (butler.get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0).second == DCPTime::from_frames(1, 24));
+ BOOST_CHECK (butler.get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0).second == DCPTime::from_frames(2, 24));
/* XXX: check the frame contents */
float buffer[256 * 6];
int const audio_frames_per_video_frame = 48000 / 25;
float audio_buffer[audio_frames_per_video_frame * 6];
for (int i = 0; i < 16; ++i) {
- butler.get_video(Butler::Behaviour::BLOCKING, 0);
+ butler.get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0);
butler.get_audio(Butler::Behaviour::BLOCKING, audio_buffer, audio_frames_per_video_frame);
}
butler.seek (DCPTime::from_seconds(60), false);
for (int i = 0; i < 240; ++i) {
- butler.get_video(Butler::Behaviour::BLOCKING, 0);
+ butler.get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0);
butler.get_audio(Butler::Behaviour::BLOCKING, audio_buffer, audio_frames_per_video_frame);
}
for (int i = 0; i < 10; ++i) {
auto t = DCPTime::from_frames (i, 24);
butler->seek (t, true);
- auto video = butler->get_video(Butler::Behaviour::BLOCKING, 0);
+ auto video = butler->get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0);
BOOST_CHECK_EQUAL(video.second.get(), t.get());
write_image(video.first->image(bind(PlayerVideo::force, AV_PIX_FMT_RGB24), VideoRange::FULL, true), String::compose("build/test/player_seek_test_%1.png", i));
/* This 14.08 is empirically chosen (hopefully) to accept changes in rendering between the reference and a test machine
for (int i = 0; i < 10; ++i) {
auto t = DCPTime::from_seconds(5) + DCPTime::from_frames (i, 24);
butler->seek (t, true);
- auto video = butler->get_video(Butler::Behaviour::BLOCKING, 0);
+ auto video = butler->get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0);
BOOST_CHECK_EQUAL(video.second.get(), t.get());
write_image(
video.first->image(bind(PlayerVideo::force, AV_PIX_FMT_RGB24), VideoRange::FULL, true), String::compose("build/test/player_seek_test2_%1.png", i)
float buffer[2000 * 6];
for (int i = 0; i < length; ++i) {
- butler.get_video(Butler::Behaviour::BLOCKING, 0);
+ butler.get_video(VideoType::MAIN, Butler::Behaviour::BLOCKING, 0);
butler.get_audio(Butler::Behaviour::BLOCKING, buffer, 2000);
}