From: Carl Hetherington Date: Sat, 24 Feb 2018 01:05:14 +0000 (+0000) Subject: Speed some operations by re-using the last PlayerVideo but with X-Git-Tag: v2.13.0~49 X-Git-Url: https://git.carlh.net/gitweb/?p=dcpomatic.git;a=commitdiff_plain;h=14cccb179fff7bbbf422e13f9d2e3264239c93c7 Speed some operations by re-using the last PlayerVideo but with updated metadata (where possible). Helps with #1194. --- diff --git a/src/lib/player.cc b/src/lib/player.cc index 0d4d9f0a2..bd194c373 100644 --- a/src/lib/player.cc +++ b/src/lib/player.cc @@ -78,6 +78,12 @@ using boost::dynamic_pointer_cast; using boost::optional; using boost::scoped_ptr; +int const PlayerProperty::VIDEO_CONTAINER_SIZE = 700; +int const PlayerProperty::PLAYLIST = 701; +int const PlayerProperty::FILM_CONTAINER = 702; +int const PlayerProperty::FILM_VIDEO_FRAME_RATE = 703; +int const PlayerProperty::DCP_DECODE_REDUCTION = 704; + Player::Player (shared_ptr film, shared_ptr playlist) : _film (film) , _playlist (playlist) @@ -211,7 +217,7 @@ Player::playlist_content_changed (weak_ptr w, int property, bool freque ) { _have_valid_pieces = false; - Changed (frequent); + Changed (property, frequent); } else if ( property == SubtitleContentProperty::LINE_SPACING || @@ -231,7 +237,7 @@ Player::playlist_content_changed (weak_ptr w, int property, bool freque property == VideoContentProperty::FADE_OUT ) { - Changed (frequent); + Changed (property, frequent); } } @@ -247,14 +253,14 @@ Player::set_video_container_size (dcp::Size s) _black_image.reset (new Image (AV_PIX_FMT_RGB24, _video_container_size, true)); _black_image->make_black (); - Changed (false); + Changed (PlayerProperty::VIDEO_CONTAINER_SIZE, false); } void Player::playlist_changed () { _have_valid_pieces = false; - Changed (false); + Changed (PlayerProperty::PLAYLIST, false); } void @@ -266,13 +272,13 @@ Player::film_changed (Film::Property p) */ if (p == Film::CONTAINER) { - Changed (false); + Changed (PlayerProperty::FILM_CONTAINER, false); } else if (p == Film::VIDEO_FRAME_RATE) { /* Pieces contain a FrameRateChange which contains the DCP frame rate, so we need new pieces here. */ _have_valid_pieces = false; - Changed (false); + Changed (PlayerProperty::FILM_VIDEO_FRAME_RATE, false); } else if (p == Film::AUDIO_PROCESSOR) { if (_film->audio_processor ()) { _audio_processor = _film->audio_processor()->clone (_film->audio_frame_rate ()); @@ -337,7 +343,9 @@ Player::black_player_video_frame (Eyes eyes) const _video_container_size, eyes, PART_WHOLE, - PresetColourConversion::all().front().conversion + PresetColourConversion::all().front().conversion, + boost::weak_ptr(), + boost::optional() ) ); } @@ -758,7 +766,9 @@ Player::video (weak_ptr wp, ContentVideo video) _video_container_size, video.eyes, video.part, - piece->content->video->colour_conversion () + piece->content->video->colour_conversion(), + piece->content, + video.frame ) ); @@ -1078,5 +1088,5 @@ Player::set_dcp_decode_reduction (optional reduction) _dcp_decode_reduction = reduction; _have_valid_pieces = false; - Changed (false); + Changed (PlayerProperty::DCP_DECODE_REDUCTION, false); } diff --git a/src/lib/player.h b/src/lib/player.h index 8142f8e7f..fc7117ba2 100644 --- a/src/lib/player.h +++ b/src/lib/player.h @@ -48,6 +48,16 @@ class AudioBuffers; class ReferencedReelAsset; class Shuffler; +class PlayerProperty +{ +public: + static int const VIDEO_CONTAINER_SIZE; + static int const PLAYLIST; + static int const FILM_CONTAINER; + static int const FILM_VIDEO_FRAME_RATE; + static int const DCP_DECODE_REDUCTION; +}; + /** @class Player * @brief A class which can `play' a Playlist. */ @@ -62,6 +72,9 @@ public: std::list > get_subtitle_fonts (); std::list get_reel_assets (); + dcp::Size video_container_size () const { + return _video_container_size; + } void set_video_container_size (dcp::Size); void set_ignore_video (); @@ -75,9 +88,10 @@ public: * the last frame again it would look different. This is not emitted after * a seek. * - * The parameter is true if these signals are currently likely to be frequent. + * The first parameter is what changed. + * The second parameter is true if these signals are currently likely to be frequent. */ - boost::signals2::signal Changed; + boost::signals2::signal Changed; /** Emitted when a video frame is ready. These emissions happen in the correct order. */ boost::signals2::signal, DCPTime)> Video; diff --git a/src/lib/player_video.cc b/src/lib/player_video.cc index 4784b1637..c24f9ccaa 100644 --- a/src/lib/player_video.cc +++ b/src/lib/player_video.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2013-2015 Carl Hetherington + Copyright (C) 2013-2018 Carl Hetherington This file is part of DCP-o-matic. @@ -19,6 +19,8 @@ */ #include "player_video.h" +#include "content.h" +#include "video_content.h" #include "image.h" #include "image_proxy.h" #include "j2k_image_proxy.h" @@ -33,6 +35,7 @@ extern "C" { using std::string; using std::cout; using boost::shared_ptr; +using boost::weak_ptr; using boost::dynamic_pointer_cast; using boost::optional; using boost::function; @@ -47,7 +50,9 @@ PlayerVideo::PlayerVideo ( dcp::Size out_size, Eyes eyes, Part part, - optional colour_conversion + optional colour_conversion, + weak_ptr content, + optional video_frame ) : _in (in) , _crop (crop) @@ -57,6 +62,8 @@ PlayerVideo::PlayerVideo ( , _eyes (eyes) , _part (part) , _colour_conversion (colour_conversion) + , _content (content) + , _video_frame (video_frame) { } @@ -272,7 +279,24 @@ PlayerVideo::shallow_copy () const _out_size, _eyes, _part, - _colour_conversion + _colour_conversion, + _content, + _video_frame ) ); } + +/** Re-read crop, fade, inter/out size and colour conversion from our content */ +void +PlayerVideo::reset_metadata (dcp::Size video_container_size, dcp::Size film_frame_size) +{ + shared_ptr content = _content.lock(); + DCPOMATIC_ASSERT (content); + DCPOMATIC_ASSERT (_video_frame); + + _crop = content->video->crop(); + _fade = content->video->fade(_video_frame.get()); + _inter_size = content->video->scale().size(content->video, video_container_size, film_frame_size); + _out_size = video_container_size; + _colour_conversion = content->video->colour_conversion(); +} diff --git a/src/lib/player_video.h b/src/lib/player_video.h index a6e39d66e..7cc00f46b 100644 --- a/src/lib/player_video.h +++ b/src/lib/player_video.h @@ -30,6 +30,7 @@ extern "C" { #include } #include +#include class Image; class ImageProxy; @@ -50,7 +51,9 @@ public: dcp::Size, Eyes, Part, - boost::optional + boost::optional, + boost::weak_ptr, + boost::optional ); PlayerVideo (boost::shared_ptr, boost::shared_ptr); @@ -68,6 +71,8 @@ public: void add_metadata (xmlpp::Node* node) const; void send_binary (boost::shared_ptr socket) const; + void reset_metadata (dcp::Size video_container_size, dcp::Size film_frame_size); + bool has_j2k () const; dcp::Data j2k () const; @@ -105,6 +110,10 @@ private: Part _part; boost::optional _colour_conversion; boost::optional _subtitle; + /** Content that we came from. This is so that reset_metadata() can work */ + boost::weak_ptr _content; + /** Video frame that we came from. Again, this is for reset_metadata() */ + boost::optional _video_frame; }; #endif diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index d521e5385..11505e510 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -87,7 +87,6 @@ FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected , _timecode (new wxStaticText (this, wxID_ANY, wxT(""))) , _play_button (new wxToggleButton (this, wxID_ANY, _("Play"))) , _coalesce_player_changes (false) - , _pending_player_change (false) , _slider_being_moved (false) , _was_running_before_slider (false) , _audio (DCPOMATIC_RTAUDIO_API) @@ -146,8 +145,8 @@ FilmViewer::FilmViewer (wxWindow* p, bool outline_content, bool jump_to_selected if (_outline_content) { _outline_content->Bind (wxEVT_CHECKBOX, boost::bind (&FilmViewer::refresh_panel, this)); } - _left_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::refresh, this)); - _right_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::refresh, this)); + _left_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::slow_refresh, this)); + _right_eye->Bind (wxEVT_RADIOBUTTON, boost::bind (&FilmViewer::slow_refresh, this)); _slider->Bind (wxEVT_SCROLL_THUMBTRACK, boost::bind (&FilmViewer::slider_moved, this, false)); _slider->Bind (wxEVT_SCROLL_PAGEUP, boost::bind (&FilmViewer::slider_moved, this, true)); _slider->Bind (wxEVT_SCROLL_PAGEDOWN, boost::bind (&FilmViewer::slider_moved, this, true)); @@ -222,7 +221,7 @@ FilmViewer::set_film (shared_ptr film) _player->set_play_referenced (); _film->Changed.connect (boost::bind (&FilmViewer::film_changed, this, _1)); - _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1)); + _player->Changed.connect (boost::bind (&FilmViewer::player_changed, this, _1, _2)); /* Keep about 1 second's worth of history samples */ _latency_history_count = _film->audio_frame_rate() / _audio_block_size; @@ -230,7 +229,7 @@ FilmViewer::set_film (shared_ptr film) recreate_butler (); calculate_sizes (); - refresh (); + slow_refresh (); setup_sensitivity (); } @@ -283,27 +282,32 @@ FilmViewer::get () { DCPOMATIC_ASSERT (_butler); - pair, DCPTime> video; do { - video = _butler->get_video (); + _player_video = _butler->get_video (); } while ( _film->three_d() && - ((_left_eye->GetValue() && video.first->eyes() == EYES_RIGHT) || (_right_eye->GetValue() && video.first->eyes() == EYES_LEFT)) + ((_left_eye->GetValue() && _player_video.first->eyes() == EYES_RIGHT) || (_right_eye->GetValue() && _player_video.first->eyes() == EYES_LEFT)) ); _butler->rethrow (); - if (!video.first) { + display_player_video (); +} + +void +FilmViewer::display_player_video () +{ + if (!_player_video.first) { _frame.reset (); refresh_panel (); return; } - if (_playing && (time() - video.second) > one_video_frame()) { + if (_playing && (time() - _player_video.second) > one_video_frame()) { /* Too late; just drop this frame before we try to get its image (which will be the time-consuming part if this frame is J2K). */ - _video_position = video.second; + _video_position = _player_video.second; ++_dropped; return; } @@ -326,17 +330,17 @@ FilmViewer::get () * image and convert it (from whatever the user has said it is) to RGB. */ - _frame = video.first->image ( + _frame = _player_video.first->image ( bind (&Log::dcp_log, _film->log().get(), _1, _2), bind (&PlayerVideo::always_rgb, _1), false, true ); - ImageChanged (video.first); + ImageChanged (_player_video.first); - _video_position = video.second; - _inter_position = video.first->inter_position (); - _inter_size = video.first->inter_size (); + _video_position = _player_video.second; + _inter_position = _player_video.first->inter_position (); + _inter_size = _player_video.first->inter_size (); refresh_panel (); } @@ -442,7 +446,7 @@ FilmViewer::panel_sized (wxSizeEvent& ev) _panel_size.height = ev.GetSize().GetHeight(); calculate_sizes (); - refresh (); + quick_refresh (); update_position_label (); update_position_slider (); } @@ -623,19 +627,31 @@ FilmViewer::forward_clicked (wxMouseEvent& ev) } void -FilmViewer::player_changed (bool frequent) +FilmViewer::player_changed (int property, bool frequent) { if (frequent) { return; } if (_coalesce_player_changes) { - _pending_player_change = true; + _pending_player_changes.push_back (property); return; } calculate_sizes (); - refresh (); + if ( + property == VideoContentProperty::CROP || + property == VideoContentProperty::SCALE || + property == VideoContentProperty::FADE_IN || + property == VideoContentProperty::FADE_OUT || + property == VideoContentProperty::COLOUR_CONVERSION || + property == PlayerProperty::VIDEO_CONTAINER_SIZE || + property == PlayerProperty::FILM_CONTAINER + ) { + quick_refresh (); + } else { + slow_refresh (); + } update_position_label (); update_position_slider (); } @@ -673,13 +689,25 @@ FilmViewer::film_changed (Film::Property p) } } -/** Re-get the current frame */ +/** Re-get the current frame slowly by seeking */ void -FilmViewer::refresh () +FilmViewer::slow_refresh () { seek (_video_position, true); } +/** Re-get the current frame quickly by resetting the metadata in the PlayerVideo that we used last time */ +void +FilmViewer::quick_refresh () +{ + if (!_player_video.first) { + return; + } + + _player_video.first->reset_metadata (_player->video_container_size(), _film->frame_size()); + display_player_video (); +} + void FilmViewer::set_position (DCPTime p) { @@ -694,12 +722,11 @@ FilmViewer::set_coalesce_player_changes (bool c) { _coalesce_player_changes = c; - if (c) { - _pending_player_change = false; - } else { - if (_pending_player_change) { - player_changed (false); + if (!c) { + BOOST_FOREACH (int i, _pending_player_changes) { + player_changed (i, false); } + _pending_player_changes.clear (); } } diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 1c4f3c693..f769fd6b9 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -59,7 +59,8 @@ public: void set_dcp_decode_reduction (boost::optional reduction); boost::optional dcp_decode_reduction () const; - void refresh (); + void slow_refresh (); + void quick_refresh (); int dropped () const { return _dropped; @@ -82,10 +83,11 @@ private: void rewind_clicked (wxMouseEvent &); void back_clicked (wxMouseEvent &); void forward_clicked (wxMouseEvent &); - void player_changed (bool); + void player_changed (int, bool); void update_position_label (); void update_position_slider (); void get (); + void display_player_video (); void seek (DCPTime t, bool accurate); void refresh_panel (); void setup_sensitivity (); @@ -122,10 +124,11 @@ private: wxToggleButton* _play_button; wxTimer _timer; bool _coalesce_player_changes; - bool _pending_player_change; + std::list _pending_player_changes; bool _slider_being_moved; bool _was_running_before_slider; + std::pair, DCPTime> _player_video; boost::shared_ptr _frame; DCPTime _video_position; Position _inter_position; diff --git a/src/wx/video_waveform_dialog.cc b/src/wx/video_waveform_dialog.cc index 83253d335..c38dbf65d 100644 --- a/src/wx/video_waveform_dialog.cc +++ b/src/wx/video_waveform_dialog.cc @@ -106,7 +106,7 @@ VideoWaveformDialog::shown (wxShowEvent& ev) { _plot->set_enabled (ev.IsShown ()); if (ev.IsShown ()) { - _viewer->refresh (); + _viewer->slow_refresh (); } } diff --git a/test/client_server_test.cc b/test/client_server_test.cc index 074ca0c9e..b3d57e813 100644 --- a/test/client_server_test.cc +++ b/test/client_server_test.cc @@ -43,6 +43,7 @@ using std::list; using boost::shared_ptr; using boost::thread; using boost::optional; +using boost::weak_ptr; using dcp::Data; void @@ -94,7 +95,9 @@ BOOST_AUTO_TEST_CASE (client_server_test_rgb) dcp::Size (1998, 1080), EYES_BOTH, PART_WHOLE, - ColourConversion () + ColourConversion(), + weak_ptr(), + optional() ) ); @@ -177,7 +180,9 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv) dcp::Size (1998, 1080), EYES_BOTH, PART_WHOLE, - ColourConversion () + ColourConversion(), + weak_ptr(), + optional() ) ); @@ -247,7 +252,9 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k) dcp::Size (1998, 1080), EYES_BOTH, PART_WHOLE, - ColourConversion () + ColourConversion(), + weak_ptr(), + optional() ) ); @@ -273,7 +280,9 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k) dcp::Size (1998, 1080), EYES_BOTH, PART_WHOLE, - PresetColourConversion::all().front().conversion + PresetColourConversion::all().front().conversion, + weak_ptr(), + optional() ) );