Various timing hacks and development.
authorCarl Hetherington <cth@carlh.net>
Wed, 6 Nov 2019 00:09:13 +0000 (01:09 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 8 Jan 2020 20:56:47 +0000 (21:56 +0100)
src/wx/film_viewer.cc
src/wx/film_viewer.h
src/wx/gl_video_view.cc
src/wx/gl_video_view.h
src/wx/simple_video_view.cc
src/wx/simple_video_view.h
src/wx/video_view.h

index 5c73f29..f40ed22 100644 (file)
@@ -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 = film;
-       _video_position = DCPTime ();
        _video_view->clear ();
 
        _video_view->set_image (shared_ptr<Image>());
@@ -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<RtAudio*>(&_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;
 }
index 6b6aa78..beb1a5d 100644 (file)
@@ -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<int> _pending_player_changes;
 
-       dcpomatic::DCPTime _video_position;
        Position<int> _inter_position;
        dcp::Size _inter_size;
 
index c69ab21..ebf8b8f 100644 (file)
@@ -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;
+}
index e32a1ed..4ad4b12 100644 (file)
@@ -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<dcp::Size> _size;
        bool _vsync_enabled;
        boost::thread* _thread;
+       bool _one_shot;
 };
index 619a35c..e66ed81 100644 (file)
@@ -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 ();
 
index 1d5242a..e8bb932 100644 (file)
@@ -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;
index 827d1bf..d6e76ad 100644 (file)
@@ -53,13 +53,15 @@ public:
 
        boost::signals2::signal<void()> 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;