Hopefully fix seek back/forward.
authorCarl Hetherington <cth@carlh.net>
Tue, 9 Jul 2013 21:56:47 +0000 (22:56 +0100)
committerCarl Hetherington <cth@carlh.net>
Tue, 9 Jul 2013 21:56:47 +0000 (22:56 +0100)
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/imagemagick_decoder.cc
src/lib/imagemagick_decoder.h
src/lib/player.cc
src/lib/player.h
src/lib/video_decoder.h
src/wx/film_viewer.cc

index 3b7d727b88eec115b508da254d806da5f90b9f27..bcd1e738a46bbff94976afbc2fe178b8f3ff2cd3 100644 (file)
@@ -281,26 +281,11 @@ FFmpegDecoder::bytes_per_audio_sample () const
 }
 
 void
-FFmpegDecoder::seek (VideoContent::Frame frame)
+FFmpegDecoder::seek (VideoContent::Frame frame, bool accurate)
 {
-       do_seek (frame, false, false);
-}
-
-void
-FFmpegDecoder::seek_back ()
-{
-       if (_video_position == 0) {
-               return;
-       }
-       
-       do_seek (_video_position - 1, true, true);
-}
-
-void
-FFmpegDecoder::do_seek (VideoContent::Frame frame, bool backwards, bool accurate)
-{
-       int64_t const vt = frame / (_ffmpeg_content->video_frame_rate() * av_q2d (_format_context->streams[_video_stream]->time_base));
-       av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0);
+       double const time_base = av_q2d (_format_context->streams[_video_stream]->time_base);
+       int64_t const vt = frame / (_ffmpeg_content->video_frame_rate() * time_base);
+       av_seek_frame (_format_context, _video_stream, vt, AVSEEK_FLAG_BACKWARD);
 
        avcodec_flush_buffers (video_codec_context());
        if (_subtitle_codec_context) {
@@ -323,9 +308,11 @@ FFmpegDecoder::do_seek (VideoContent::Frame frame, bool backwards, bool accurate
                                int const r = avcodec_decode_video2 (video_codec_context(), _frame, &finished, &_packet);
                                if (r >= 0 && finished) {
                                        int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
-                                       if (bet > vt) {
-                                               _video_position = (bet * av_q2d (_format_context->streams[_video_stream]->time_base) + _pts_offset)
-                                                       * _ffmpeg_content->video_frame_rate();
+                                       if (bet >= vt) {
+                                               _video_position = rint (
+                                                       (bet * time_base + _pts_offset) * _ffmpeg_content->video_frame_rate()
+                                                       );
+                                               av_free_packet (&_packet);
                                                break;
                                        }
                                }
@@ -427,10 +414,10 @@ FFmpegDecoder::decode_video_packet ()
                                /* We just did a seek, so disable any attempts to correct for where we
                                   are / should be.
                                */
-                               _video_position = pts * _ffmpeg_content->video_frame_rate ();
+                               _video_position = rint (pts * _ffmpeg_content->video_frame_rate ());
                                _just_sought = false;
                        }
-                       
+
                        double const next = _video_position / _ffmpeg_content->video_frame_rate();
                        double const one_frame = 1 / _ffmpeg_content->video_frame_rate ();
                        double delta = pts - next;
index 2e64d8801104471a84fde174f8add41e5cd0c6e6..eebf75445c24ec402b8d89a678a64df28b009827 100644 (file)
@@ -50,8 +50,7 @@ public:
        ~FFmpegDecoder ();
 
        void pass ();
-       void seek (VideoContent::Frame);
-       void seek_back ();
+       void seek (VideoContent::Frame, bool);
        bool done () const;
 
 private:
@@ -67,7 +66,6 @@ private:
 
        AVSampleFormat audio_sample_format () const;
        int bytes_per_audio_sample () const;
-       void do_seek (VideoContent::Frame, bool, bool);
 
        bool decode_video_packet ();
        void decode_audio_packet ();
index 04d3d9df7c47d166c52e7692b3977d550993b547..6178443cfae57ef18a4613848efcf3a0dc8a2571 100644 (file)
@@ -75,19 +75,11 @@ ImageMagickDecoder::pass ()
 }
 
 void
-ImageMagickDecoder::seek (VideoContent::Frame frame)
+ImageMagickDecoder::seek (VideoContent::Frame frame, bool)
 {
        _video_position = frame;
 }
 
-void
-ImageMagickDecoder::seek_back ()
-{
-       if (_video_position > 0) {
-               _video_position--;
-       }
-}
-
 bool
 ImageMagickDecoder::done () const
 {
index 286f473378396f9bbd44f39f28f08c7eeefaf0dd..3e551c3b7c0d86aba36b020c4201a149f0360c38 100644 (file)
@@ -34,8 +34,7 @@ public:
        /* Decoder */
 
        void pass ();
-       void seek (VideoContent::Frame);
-       void seek_back ();
+       void seek (VideoContent::Frame, bool);
        bool done () const;
 
 private:
index 7488364bddcc0a0d82bc4f193d69eedf4a6f7334..4de691c0bd2d70b4517b720acb319215675c9c48 100644 (file)
@@ -337,7 +337,7 @@ Player::flush ()
 
 /** @return true on error */
 void
-Player::seek (Time t)
+Player::seek (Time t, bool accurate)
 {
        if (!_have_valid_pieces) {
                setup_pieces ();
@@ -360,19 +360,12 @@ Player::seek (Time t)
 
                FrameRateConversion frc (vc->video_frame_rate(), _film->dcp_video_frame_rate());
                VideoContent::Frame f = s * _film->dcp_video_frame_rate() / (frc.factor() * TIME_HZ);
-               dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f);
+               dynamic_pointer_cast<VideoDecoder>((*i)->decoder)->seek (f, accurate);
        }
 
        /* XXX: don't seek audio because we don't need to... */
 }
 
-
-void
-Player::seek_back ()
-{
-
-}
-
 void
 Player::setup_pieces ()
 {
index 3f8d59d29b4ab60fa0b4e2181d396bb1ba7d6982..15fa4dbd6ce5c1d118683e26bc5278e96cf31eef 100644 (file)
@@ -49,8 +49,7 @@ public:
        void disable_audio ();
 
        bool pass ();
-       void seek (Time);
-       void seek_back ();
+       void seek (Time, bool);
 
        Time video_position () const {
                return _video_position;
index d24219d956cba2df1b92b8a58e2d3f5bc8d24d78..0b33504721efe4c1867474405b231d51eebfc4b5 100644 (file)
@@ -30,8 +30,7 @@ class VideoDecoder : public virtual Decoder
 public:
        VideoDecoder (boost::shared_ptr<const Film>);
 
-       virtual void seek (VideoContent::Frame) = 0;
-       virtual void seek_back () = 0;
+       virtual void seek (VideoContent::Frame, bool) = 0;
 
        /** Emitted when a video frame is ready.
         *  First parameter is the video image.
index 6469d0962bce8c4560d2858276178eb21a20652a..6d7181b5fae3a74f3a6165f5c937747629489620 100644 (file)
@@ -141,8 +141,7 @@ FilmViewer::fetch_current_frame_again ()
                return;
        }
 
-       /* This will cause a Player::Changed to be emitted */
-       _player->seek (_player->video_position() - _film->video_frames_to_time (1));
+       _player->seek (_player->video_position() - _film->video_frames_to_time (1), false);
        fetch_next_frame ();
 }
 
@@ -202,7 +201,7 @@ void
 FilmViewer::slider_moved (wxScrollEvent &)
 {
        if (_film && _player) {
-               _player->seek (_slider->GetValue() * _film->length() / 4096);
+               _player->seek (_slider->GetValue() * _film->length() / 4096, false);
                fetch_next_frame ();
        }
 }
@@ -336,8 +335,10 @@ FilmViewer::back_clicked (wxCommandEvent &)
        if (!_player) {
                return;
        }
+
+       Time const t = _film->video_frames_to_time (1);
        
-       _player->seek_back ();
+       _player->seek (_player->video_position() - t * 2.5, true);
        fetch_next_frame ();
 }