From: Carl Hetherington Date: Wed, 24 Jul 2019 19:42:50 +0000 (+0100) Subject: Optimise the feel of some GUI functions by doing the seek after X-Git-Tag: v2.15.15~10 X-Git-Url: https://main.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=335ef709439cd3678f6813a3fb880110e4c9cb26 Optimise the feel of some GUI functions by doing the seek after many content changes in an idle handler, rather than blocking the UI update until the seek and image redisplay have finished. --- diff --git a/src/lib/butler.cc b/src/lib/butler.cc index 8c46d5190..2d6c46c7e 100644 --- a/src/lib/butler.cc +++ b/src/lib/butler.cc @@ -216,12 +216,16 @@ try _arrived.notify_all (); } +/** @param blocking true if we should block until video is available. If blocking is false + * and no video is immediately available the method will return a 0 PlayerVideo and the error AGAIN. + * @param e if non-0 this is filled with an error code (if an error occurs) or is untouched if no error occurs. + */ pair, DCPTime> -Butler::get_video (Error* e) +Butler::get_video (bool blocking, Error* e) { boost::mutex::scoped_lock lm (_mutex); - if (_suspended) { + if (_suspended || (_video.empty() && !blocking)) { if (e) { *e = AGAIN; } diff --git a/src/lib/butler.h b/src/lib/butler.h index 09c182f9c..e5581ccb4 100644 --- a/src/lib/butler.h +++ b/src/lib/butler.h @@ -54,7 +54,7 @@ public: AGAIN }; - std::pair, dcpomatic::DCPTime> get_video (Error* e = 0); + std::pair, dcpomatic::DCPTime> get_video (bool blocking, Error* e = 0); boost::optional get_audio (float* out, Frame frames); boost::optional get_closed_caption (); diff --git a/src/lib/ffmpeg_encoder.cc b/src/lib/ffmpeg_encoder.cc index 7c641f5ab..572e7ae16 100644 --- a/src/lib/ffmpeg_encoder.cc +++ b/src/lib/ffmpeg_encoder.cc @@ -150,7 +150,7 @@ FFmpegEncoder::go () } for (int j = 0; j < gets_per_frame; ++j) { - pair, DCPTime> v = _butler->get_video (); + pair, DCPTime> v = _butler->get_video (true, 0); encoder->get(v.first->eyes())->video(v.first, v.second); } diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index a2b055934..edb451e74 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -231,17 +231,22 @@ FilmViewer::refresh_view () _state_timer.unset (); } +/** @param lazy true if it is *not* important that the display be updated as quickly as possible. + * If lazy is true we will try to return from this method quickly and postpone any time-consuming + * work until the UI is next idle. Otherwise we will block here and try to get the image on + * screen as soon as possible. + */ void -FilmViewer::get () +FilmViewer::get (bool lazy) { DCPOMATIC_ASSERT (_butler); ++_gets; do { Butler::Error e; - _player_video = _butler->get_video (&e); + _player_video = _butler->get_video (!lazy, &e); if (!_player_video.first && e == Butler::AGAIN) { - signal_manager->when_idle (boost::bind(&FilmViewer::get, this)); + signal_manager->when_idle (boost::bind(&FilmViewer::get, this, lazy)); return; } } while ( @@ -257,7 +262,11 @@ FilmViewer::get () error_dialog (_video_view->get(), e.what()); } - display_player_video (); + if (lazy) { + signal_manager->when_idle (boost::bind(&FilmViewer::display_player_video, this)); + } else { + display_player_video (); + } } void @@ -322,7 +331,7 @@ FilmViewer::timer () return; } - get (); + get (false); PositionChanged (); DCPTime const next = _video_position + one_video_frame(); @@ -541,7 +550,7 @@ FilmViewer::seek (DCPTime t, bool accurate) _closed_captions_dialog->clear (); _butler->seek (t, accurate); - get (); + get (true); if (was_running) { start (); diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 5ddb12baf..298e9dd00 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -151,7 +151,7 @@ private: void timer (); void calculate_sizes (); void player_change (ChangeType type, int, bool); - void get (); + void get (bool lazy); void display_player_video (); void film_change (ChangeType, Film::Property); void recreate_butler (); diff --git a/test/butler_test.cc b/test/butler_test.cc index cc2841268..7aeba78f9 100644 --- a/test/butler_test.cc +++ b/test/butler_test.cc @@ -54,9 +54,9 @@ BOOST_AUTO_TEST_CASE (butler_test1) Butler butler (shared_ptr(new Player(film, film->playlist())), map, 6, bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, false); - BOOST_CHECK (butler.get_video().second == DCPTime()); - BOOST_CHECK (butler.get_video().second == DCPTime::from_frames(1, 24)); - BOOST_CHECK (butler.get_video().second == DCPTime::from_frames(2, 24)); + BOOST_CHECK (butler.get_video(true, 0).second == DCPTime()); + BOOST_CHECK (butler.get_video(true, 0).second == DCPTime::from_frames(1, 24)); + BOOST_CHECK (butler.get_video(true, 0).second == DCPTime::from_frames(2, 24)); /* XXX: check the frame contents */ float buffer[256 * 6]; diff --git a/test/dcp_playback_test.cc b/test/dcp_playback_test.cc index 9fef1801b..1dda667a0 100644 --- a/test/dcp_playback_test.cc +++ b/test/dcp_playback_test.cc @@ -49,7 +49,7 @@ BOOST_AUTO_TEST_CASE (dcp_playback_test) ); float* audio_buffer = new float[2000*6]; while (true) { - pair, DCPTime> p = butler->get_video (); + pair, DCPTime> p = butler->get_video (true, 0); if (!p.first) { break; } diff --git a/test/player_test.cc b/test/player_test.cc index 7b65783c6..af40002de 100644 --- a/test/player_test.cc +++ b/test/player_test.cc @@ -220,7 +220,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test) for (int i = 0; i < 10; ++i) { DCPTime t = DCPTime::from_frames (i, 24); butler->seek (t, true); - pair, DCPTime> video = butler->get_video(); + pair, DCPTime> video = butler->get_video(true, 0); BOOST_CHECK_EQUAL(video.second.get(), t.get()); write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true), String::compose("build/test/player_seek_test_%1.png", i), "RGB"); /* This 0.055 is empirically chosen (hopefully) to accept changes in rendering between the reference and a test machine @@ -253,7 +253,7 @@ BOOST_AUTO_TEST_CASE (player_seek_test2) for (int i = 0; i < 10; ++i) { DCPTime t = DCPTime::from_seconds(5) + DCPTime::from_frames (i, 24); butler->seek (t, true); - pair, DCPTime> video = butler->get_video(); + pair, DCPTime> video = butler->get_video(true, 0); BOOST_CHECK_EQUAL(video.second.get(), t.get()); write_image(video.first->image(bind(PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true), String::compose("build/test/player_seek_test2_%1.png", i), "RGB"); check_image(String::compose("test/data/player_seek_test2_%1.png", i), String::compose("build/test/player_seek_test2_%1.png", i), 0.055);