From 805487369e57e5eb57911805ba6de78b653d79ad Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Wed, 6 Nov 2019 01:09:13 +0100 Subject: [PATCH] Various timing hacks and development. --- src/wx/film_viewer.cc | 27 ++++++++++++++++----------- src/wx/film_viewer.h | 5 ++--- src/wx/gl_video_view.cc | 23 ++++++++++++++++++----- src/wx/gl_video_view.h | 3 +++ src/wx/simple_video_view.cc | 14 ++++++-------- src/wx/simple_video_view.h | 4 +--- src/wx/video_view.h | 10 ++++++---- 7 files changed, 52 insertions(+), 34 deletions(-) diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 5c73f292c..f40ed229f 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -122,7 +122,7 @@ FilmViewer::~FilmViewer () /** Ask for ::get() to be called next time we are idle */ void -FilmViewer::request_idle_get () +FilmViewer::request_idle_display_next_frame () { if (_idle_get) { return; @@ -140,7 +140,7 @@ FilmViewer::idle_handler () return; } - if (_video_view->get(true)) { + if (_video_view->display_next_frame(true)) { _idle_get = false; } else { /* get() could not complete quickly so we'll try again later */ @@ -156,7 +156,6 @@ FilmViewer::set_film (shared_ptr film) } _film = film; - _video_position = DCPTime (); _video_view->clear (); _video_view->set_image (shared_ptr()); @@ -302,7 +301,7 @@ FilmViewer::resume () --_suspended; if (_playing && !_suspended) { if (_audio.isStreamOpen()) { - _audio.setStreamTime (_video_position.seconds()); + _audio.setStreamTime (_video_view->position().seconds()); _audio.startStream (); } _video_view->start (); @@ -323,7 +322,7 @@ FilmViewer::start () } if (_audio.isStreamOpen()) { - _audio.setStreamTime (_video_position.seconds()); + _audio.setStreamTime (_video_view->position().seconds()); _audio.startStream (); } @@ -393,7 +392,7 @@ FilmViewer::film_change (ChangeType type, Film::Property p) void FilmViewer::slow_refresh () { - seek (_video_position, true); + seek (_video_view->position(), true); } /** Try to re-get the current frame quickly by resetting the metadata @@ -458,7 +457,9 @@ FilmViewer::seek (DCPTime t, bool accurate) _butler->seek (t, accurate); if (!_playing) { - request_idle_get (); + request_idle_display_next_frame (); + } else { + while (!_video_view->display_next_frame(false)) {} } resume (); @@ -536,7 +537,7 @@ FilmViewer::uncorrected_time () const return DCPTime::from_seconds (const_cast(&_audio)->getStreamTime()); } - return _video_position; + return _video_view->position(); } DCPTime @@ -547,7 +548,7 @@ FilmViewer::time () const DCPTime::from_frames (average_latency(), _film->audio_frame_rate()); } - return _video_position; + return _video_view->position(); } int @@ -620,7 +621,7 @@ FilmViewer::show_closed_captions () void FilmViewer::seek_by (DCPTime by, bool accurate) { - seek (_video_position + by, accurate); + seek (_video_view->position() + by, accurate); } void @@ -634,5 +635,9 @@ int FilmViewer::time_until_next_frame () const { DCPTime const next = position() + one_video_frame(); - return max ((next.seconds() - time().seconds()) * 1000, 1.0); + std::cout << to_string(next) << " " << to_string(time()) << " " << ((next.seconds() - time().seconds()) * 1000) << "\n"; + if (next < time()) { + return 0; + } + return (next.seconds() - time().seconds()) * 1000; } diff --git a/src/wx/film_viewer.h b/src/wx/film_viewer.h index 6b6aa78f5..beb1a5d74 100644 --- a/src/wx/film_viewer.h +++ b/src/wx/film_viewer.h @@ -69,7 +69,7 @@ public: void seek_by (dcpomatic::DCPTime by, bool accurate); /** @return our `playhead' position; this may not lie exactly on a frame boundary */ dcpomatic::DCPTime position () const { - return _video_position; + return _video_view->position(); } dcpomatic::DCPTime one_video_frame () const; @@ -159,7 +159,7 @@ private: void calculate_sizes (); void player_change (ChangeType type, int, bool); void idle_handler (); - void request_idle_get (); + void request_idle_display_next_frame (); void film_change (ChangeType, Film::Property); void recreate_butler (); void config_changed (Config::Property); @@ -178,7 +178,6 @@ private: bool _coalesce_player_changes; std::list _pending_player_changes; - dcpomatic::DCPTime _video_position; Position _inter_position; dcp::Size _inter_size; diff --git a/src/wx/gl_video_view.cc b/src/wx/gl_video_view.cc index c69ab210a..ebf8b8fe2 100644 --- a/src/wx/gl_video_view.cc +++ b/src/wx/gl_video_view.cc @@ -55,6 +55,7 @@ GLVideoView::GLVideoView (FilmViewer* viewer, wxWindow *parent) : VideoView (viewer) , _vsync_enabled (false) , _thread (0) + , _one_shot (false) { _canvas = new wxGLCanvas (parent, wxID_ANY, 0, wxDefaultPosition, wxDefaultSize, wxFULL_REPAINT_ON_RESIZE); _canvas->Bind (wxEVT_PAINT, boost::bind(&GLVideoView::paint, this)); @@ -105,7 +106,7 @@ GLVideoView::~GLVideoView () } static void - check_gl_error (char const * last) +check_gl_error (char const * last) { GLenum const e = glGetError (); if (e != GL_NO_ERROR) { @@ -278,25 +279,29 @@ try } while (true) { - if (!_viewer->film() || !_viewer->playing()) { + if ((!_viewer->film() || !_viewer->playing()) && !_one_shot) { dcpomatic_sleep_milliseconds (40); continue; } + _one_shot = false; + dcpomatic::DCPTime const next = _viewer->position() + _viewer->one_video_frame(); if (next >= _viewer->film()->length()) { _viewer->stop (); _viewer->Finished (); - return; + continue; } get_next_frame (false); set_image (_player_video.first->image(bind(&PlayerVideo::force, _1, AV_PIX_FMT_RGB24), false, true)); draw (); - _viewer->_video_position = _player_video.second; - std::cout << "sleep " << _viewer->time_until_next_frame() << "\n"; + while (_viewer->time_until_next_frame() < 5) { + get_next_frame (true); + } + dcpomatic_sleep_milliseconds (_viewer->time_until_next_frame()); } @@ -318,3 +323,11 @@ GLVideoView::context () const boost::mutex::scoped_lock lm (_context_mutex); return _context; } + +bool +GLVideoView::display_next_frame (bool non_blocking) +{ + bool const g = get_next_frame (non_blocking); + _one_shot = true; + return g; +} diff --git a/src/wx/gl_video_view.h b/src/wx/gl_video_view.h index e32a1ede9..4ad4b1283 100644 --- a/src/wx/gl_video_view.h +++ b/src/wx/gl_video_view.h @@ -40,6 +40,8 @@ public: void update (); void start (); + bool display_next_frame (bool); + bool vsync_enabled () const { return _vsync_enabled; } @@ -59,4 +61,5 @@ private: boost::optional _size; bool _vsync_enabled; boost::thread* _thread; + bool _one_shot; }; diff --git a/src/wx/simple_video_view.cc b/src/wx/simple_video_view.cc index 619a35cce..e66ed815e 100644 --- a/src/wx/simple_video_view.cc +++ b/src/wx/simple_video_view.cc @@ -149,7 +149,7 @@ SimpleVideoView::timer () return; } - get (false); + display_next_frame (false); DCPTime const next = _viewer->position() + _viewer->one_video_frame(); if (next >= _viewer->film()->length()) { @@ -173,21 +173,21 @@ SimpleVideoView::start () } /** Try to get a frame from the butler and display it. - * @param lazy true to return false quickly if no video is available quickly (i.e. we are waiting for the butler). + * @param non_blocking true to return false quickly if no video is available quickly (i.e. we are waiting for the butler). * false to ask the butler to block until it has video (unless it is suspended). * @return true on success, false if we did nothing because it would have taken too long. */ bool -SimpleVideoView::get (bool lazy) +SimpleVideoView::display_next_frame (bool non_blocking) { - bool r = get_next_frame (lazy); + bool r = get_next_frame (non_blocking); if (!r) { - if (lazy) { + if (non_blocking) { /* No video available; return saying we failed */ return false; } else { /* Player was suspended; come back later */ - signal_manager->when_idle (boost::bind(&SimpleVideoView::get, this, false)); + signal_manager->when_idle (boost::bind(&SimpleVideoView::display_next_frame, this, false)); return false; } } @@ -210,7 +210,6 @@ SimpleVideoView::display_player_video () /* 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). */ - _viewer->_video_position = _player_video.second; ++_viewer->_dropped; return; } @@ -243,7 +242,6 @@ SimpleVideoView::display_player_video () _viewer->ImageChanged (_player_video.first); _viewer->_state_timer.unset (); - _viewer->_video_position = _player_video.second; _viewer->_inter_position = _player_video.first->inter_position (); _viewer->_inter_size = _player_video.first->inter_size (); diff --git a/src/wx/simple_video_view.h b/src/wx/simple_video_view.h index 1d5242a1a..e8bb932e4 100644 --- a/src/wx/simple_video_view.h +++ b/src/wx/simple_video_view.h @@ -37,14 +37,12 @@ public: } void update (); - void start (); + bool display_next_frame (bool non_blocking); private: void paint (); void timer (); - /* XXX_b: rename this (there's already a get() in the parent) */ - bool get (bool lazy); void display_player_video (); wxPanel* _panel; diff --git a/src/wx/video_view.h b/src/wx/video_view.h index 827d1bf73..d6e76ada7 100644 --- a/src/wx/video_view.h +++ b/src/wx/video_view.h @@ -53,13 +53,15 @@ public: boost::signals2::signal Sized; - /* XXX_b: to remove */ - virtual bool get (bool) { - return true; - } + virtual bool display_next_frame (bool) = 0; + /* XXX_b: to remove */ virtual void display_player_video () {} + dcpomatic::DCPTime position () const { + return _player_video.second; + } + protected: /* XXX_b: to remove */ friend class FilmViewer; -- 2.30.2