From a7a8cd74f2f32de8b708c78cc8bc9c0cf17d60f5 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sat, 3 Apr 2021 23:17:56 +0200 Subject: [PATCH] Show an explanatory message if the player is not performing very well (#1932). --- src/lib/config.h | 4 ++++ src/wx/film_viewer.cc | 33 ++++++++++++++++++++++++++++----- src/wx/film_viewer.h | 1 + src/wx/nag_dialog.cc | 2 +- src/wx/video_view.cc | 30 ++++++++++++++++++++++++++++++ src/wx/video_view.h | 13 +++++++------ 6 files changed, 71 insertions(+), 12 deletions(-) diff --git a/src/lib/config.h b/src/lib/config.h index 3371e48bf..0a48a00e1 100644 --- a/src/lib/config.h +++ b/src/lib/config.h @@ -392,6 +392,9 @@ public: return _jump_to_selected; } + /* This could be an enum class but we use the enum a lot to index _nagged + * so it means a lot of casts. + */ enum Nag { NAG_DKDM_CONFIG, NAG_ENCRYPTED_METADATA, @@ -400,6 +403,7 @@ public: NAG_IMPORT_DECRYPTION_CHAIN, NAG_DELETE_DKDM, NAG_32_ON_64, + NAG_TOO_MANY_DROPPED_FRAMES, NAG_COUNT }; diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index b9e9bd533..14737d009 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -1,5 +1,5 @@ /* - Copyright (C) 2012-2019 Carl Hetherington + Copyright (C) 2012-2021 Carl Hetherington This file is part of DCP-o-matic. @@ -18,17 +18,20 @@ */ + /** @file src/film_viewer.cc * @brief A wx widget to view a preview of a Film. */ -#include "film_viewer.h" -#include "playhead_to_timecode_dialog.h" -#include "playhead_to_frame_dialog.h" -#include "wx_util.h" + #include "closed_captions_dialog.h" +#include "film_viewer.h" #include "gl_video_view.h" +#include "nag_dialog.h" +#include "playhead_to_frame_dialog.h" +#include "playhead_to_timecode_dialog.h" #include "simple_video_view.h" +#include "wx_util.h" #include "lib/film.h" #include "lib/ratio.h" #include "lib/util.h" @@ -106,6 +109,7 @@ FilmViewer::FilmViewer (wxWindow* p) } _video_view->Sized.connect (boost::bind(&FilmViewer::video_view_sized, this)); + _video_view->TooManyDropped.connect (boost::bind(&FilmViewer::too_many_frames_dropped, this)); set_film (shared_ptr ()); @@ -730,3 +734,22 @@ FilmViewer::image_changed (shared_ptr pv) emit (boost::bind(boost::ref(ImageChanged), pv)); } + +void +FilmViewer::too_many_frames_dropped () +{ + if (!Config::instance()->nagged(Config::NAG_TOO_MANY_DROPPED_FRAMES)) { + stop (); + } + + bool shown = NagDialog::maybe_nag ( + panel(), + Config::NAG_TOO_MANY_DROPPED_FRAMES, + _("The player is dropping a lot of frames, so playback may not be accurate.\n\n" + "This does not necessarily mean that the DCP you are playing is defective!\n\n" + "You may be able to improve player performance by:\n" + "• choosing 'decode at half resolution' or 'decode at quarter resolution' from the View menu\n" + "• using a more powerful computer.\n" + ) + ); +} diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 8024bb1bf..52b97f0f6 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -161,6 +161,7 @@ private: void config_changed (Config::Property); void film_length_change (); void ui_finished (); + void too_many_frames_dropped (); dcpomatic::DCPTime uncorrected_time () const; Frame average_latency () const; diff --git a/src/wx/nag_dialog.cc b/src/wx/nag_dialog.cc index 466b80b6b..85f2d0110 100644 --- a/src/wx/nag_dialog.cc +++ b/src/wx/nag_dialog.cc @@ -70,7 +70,7 @@ NagDialog::maybe_nag (wxWindow* parent, Config::Nag nag, wxString message, bool return false; } - NagDialog* d = new NagDialog (parent, nag, message, can_cancel); + auto d = new NagDialog (parent, nag, message, can_cancel); int const r = d->ShowModal(); d->Destroy (); diff --git a/src/wx/video_view.cc b/src/wx/video_view.cc index 5f44c37d6..387d4052f 100644 --- a/src/wx/video_view.cc +++ b/src/wx/video_view.cc @@ -25,12 +25,18 @@ #include "lib/butler.h" #include "lib/dcpomatic_log.h" #include +#include + using std::pair; using std::shared_ptr; using boost::optional; +static constexpr int TOO_MANY_DROPPED_FRAMES = 20; +static constexpr int TOO_MANY_DROPPED_PERIOD = 5.0; + + VideoView::VideoView (FilmViewer* viewer) : _viewer (viewer) , _state_timer ("viewer") @@ -124,6 +130,7 @@ VideoView::start () boost::mutex::scoped_lock lm (_mutex); _dropped = 0; _errored = 0; + gettimeofday(&_dropped_check_period_start, nullptr); } @@ -143,3 +150,26 @@ VideoView::reset_metadata (shared_ptr film, dcp::Size player_video_c return true; } + +void +VideoView::add_dropped () +{ + bool too_many = false; + + { + boost::mutex::scoped_lock lm (_mutex); + ++_dropped; + if (_dropped > TOO_MANY_DROPPED_FRAMES) { + struct timeval now; + gettimeofday (&now, nullptr); + double const elapsed = seconds(now) - seconds(_dropped_check_period_start); + too_many = elapsed < TOO_MANY_DROPPED_PERIOD; + _dropped = 0; + _dropped_check_period_start = now; + } + } + + if (too_many) { + emit (boost::bind(boost::ref(TooManyDropped))); + } +} diff --git a/src/wx/video_view.h b/src/wx/video_view.h index d3a15d38c..d7d60c21d 100644 --- a/src/wx/video_view.h +++ b/src/wx/video_view.h @@ -24,9 +24,10 @@ #include "lib/dcpomatic_time.h" +#include "lib/exception_store.h" +#include "lib/signaller.h" #include "lib/timer.h" #include "lib/types.h" -#include "lib/exception_store.h" #include #include @@ -38,7 +39,7 @@ class Player; class PlayerVideo; -class VideoView : public ExceptionStore +class VideoView : public ExceptionStore, public Signaller { public: VideoView (FilmViewer* viewer); @@ -70,6 +71,8 @@ public: /** Emitted from the GUI thread when our display changes in size */ boost::signals2::signal Sized; + /** Emitted from the GUI thread when a lot of frames are being dropped */ + boost::signals2::signal TooManyDropped; /* Accessors for FilmViewer */ @@ -143,10 +146,7 @@ protected: return _player_video; } - void add_dropped () { - boost::mutex::scoped_lock lm (_mutex); - ++_dropped; - } + void add_dropped (); void add_get () { boost::mutex::scoped_lock lm (_mutex); @@ -169,6 +169,7 @@ private: bool _three_d = false; int _dropped = 0; + struct timeval _dropped_check_period_start; int _errored = 0; int _gets = 0; }; -- 2.30.2