Speed some operations by re-using the last PlayerVideo but with
authorCarl Hetherington <cth@carlh.net>
Sat, 24 Feb 2018 01:05:14 +0000 (01:05 +0000)
committerCarl Hetherington <cth@carlh.net>
Sat, 24 Feb 2018 23:35:11 +0000 (23:35 +0000)
updated metadata (where possible).  Helps with #1194.

src/lib/player.cc
src/lib/player.h
src/lib/player_video.cc
src/lib/player_video.h
src/wx/film_viewer.cc
src/wx/film_viewer.h
src/wx/video_waveform_dialog.cc
test/client_server_test.cc

index 0d4d9f0a22fe712faa830144165173adb61ac920..bd194c3733dfb05cb267d9af3632d2b542f9245e 100644 (file)
@@ -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<const Film> film, shared_ptr<const Playlist> playlist)
        : _film (film)
        , _playlist (playlist)
@@ -211,7 +217,7 @@ Player::playlist_content_changed (weak_ptr<Content> 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<Content> 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<Content>(),
+                       boost::optional<Frame>()
                )
        );
 }
@@ -758,7 +766,9 @@ Player::video (weak_ptr<Piece> 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<int> reduction)
 
        _dcp_decode_reduction = reduction;
        _have_valid_pieces = false;
-       Changed (false);
+       Changed (PlayerProperty::DCP_DECODE_REDUCTION, false);
 }
index 8142f8e7f7df29cac429cb1042dad67c2cfa1d86..fc7117ba201abc006482819a5c27f8f7e56e140a 100644 (file)
@@ -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<boost::shared_ptr<Font> > get_subtitle_fonts ();
        std::list<ReferencedReelAsset> 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<void (bool)> Changed;
+       boost::signals2::signal<void (int, bool)> Changed;
 
        /** Emitted when a video frame is ready.  These emissions happen in the correct order. */
        boost::signals2::signal<void (boost::shared_ptr<PlayerVideo>, DCPTime)> Video;
index 4784b16378d129fe512a809158e3e367c320df15..c24f9ccaa06b4d70b0b552c62ad4d31876d17c55 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2018 Carl Hetherington <cth@carlh.net>
 
     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<ColourConversion> colour_conversion
+       optional<ColourConversion> colour_conversion,
+       weak_ptr<Content> content,
+       optional<Frame> 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 = _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();
+}
index a6e39d66e8196668ef9998eff4c8beb7acbe63a2..7cc00f46bb25f4d45dcfb02afdc9342584ff5916 100644 (file)
@@ -30,6 +30,7 @@ extern "C" {
 #include <libavutil/pixfmt.h>
 }
 #include <boost/shared_ptr.hpp>
+#include <boost/weak_ptr.hpp>
 
 class Image;
 class ImageProxy;
@@ -50,7 +51,9 @@ public:
                dcp::Size,
                Eyes,
                Part,
-               boost::optional<ColourConversion>
+               boost::optional<ColourConversion>,
+               boost::weak_ptr<Content>,
+               boost::optional<Frame>
                );
 
        PlayerVideo (boost::shared_ptr<cxml::Node>, boost::shared_ptr<Socket>);
@@ -68,6 +71,8 @@ public:
        void add_metadata (xmlpp::Node* node) const;
        void send_binary (boost::shared_ptr<Socket> 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<ColourConversion> _colour_conversion;
        boost::optional<PositionImage> _subtitle;
+       /** Content that we came from.  This is so that reset_metadata() can work */
+       boost::weak_ptr<Content> _content;
+       /** Video frame that we came from.  Again, this is for reset_metadata() */
+       boost::optional<Frame> _video_frame;
 };
 
 #endif
index d521e5385a2559ceef808faff659bb41f15c2e8e..11505e5101e1351699c38d12fcbd291a73dd8fec 100644 (file)
@@ -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> 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> film)
        recreate_butler ();
 
        calculate_sizes ();
-       refresh ();
+       slow_refresh ();
 
        setup_sensitivity ();
 }
@@ -283,27 +282,32 @@ FilmViewer::get ()
 {
        DCPOMATIC_ASSERT (_butler);
 
-       pair<shared_ptr<PlayerVideo>, 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 ();
        }
 }
 
index 1c4f3c693c66adada96839763a08a0eef7f50d44..f769fd6b97de33bb3eac07536e9c3154e7acb7c2 100644 (file)
@@ -59,7 +59,8 @@ public:
        void set_dcp_decode_reduction (boost::optional<int> reduction);
        boost::optional<int> 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<int> _pending_player_changes;
        bool _slider_being_moved;
        bool _was_running_before_slider;
 
+       std::pair<boost::shared_ptr<PlayerVideo>, DCPTime> _player_video;
        boost::shared_ptr<const Image> _frame;
        DCPTime _video_position;
        Position<int> _inter_position;
index 83253d335d61b4304619fd4168b719259396938c..c38dbf65d98a0d9b52ba44a64640a4a6b505aca1 100644 (file)
@@ -106,7 +106,7 @@ VideoWaveformDialog::shown (wxShowEvent& ev)
 {
        _plot->set_enabled (ev.IsShown ());
        if (ev.IsShown ()) {
-               _viewer->refresh ();
+               _viewer->slow_refresh ();
        }
 }
 
index 074ca0c9e8274f888d47159490b7a1d70b10523e..b3d57e8139c0cc0dd244b1e49e602f449332404b 100644 (file)
@@ -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<Content>(),
+                       optional<Frame>()
                        )
                );
 
@@ -177,7 +180,9 @@ BOOST_AUTO_TEST_CASE (client_server_test_yuv)
                        dcp::Size (1998, 1080),
                        EYES_BOTH,
                        PART_WHOLE,
-                       ColourConversion ()
+                       ColourConversion(),
+                       weak_ptr<Content>(),
+                       optional<Frame>()
                        )
                );
 
@@ -247,7 +252,9 @@ BOOST_AUTO_TEST_CASE (client_server_test_j2k)
                        dcp::Size (1998, 1080),
                        EYES_BOTH,
                        PART_WHOLE,
-                       ColourConversion ()
+                       ColourConversion(),
+                       weak_ptr<Content>(),
+                       optional<Frame>()
                        )
                );
 
@@ -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<Content>(),
+                       optional<Frame>()
                        )
                );