Fix still video playback.
authorCarl Hetherington <cth@carlh.net>
Sun, 7 Apr 2013 00:25:12 +0000 (01:25 +0100)
committerCarl Hetherington <cth@carlh.net>
Sun, 7 Apr 2013 00:25:12 +0000 (01:25 +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/video_content.cc
src/lib/video_decoder.cc
src/lib/video_decoder.h

index fdc5189a6370df5e61ec80c531be8c32a1d98e5a..a0949f635ffeb420a3096dfb2e740d6ef98ddaff 100644 (file)
@@ -400,7 +400,7 @@ FFmpegDecoder::deinterleave_audio (uint8_t** data, int size)
 }
 
 float
-FFmpegDecoder::frames_per_second () const
+FFmpegDecoder::video_frame_rate () const
 {
        AVStream* s = _format_context->streams[_video_stream];
 
@@ -550,7 +550,7 @@ void
 FFmpegDecoder::out_with_sync ()
 {
        /* Where we are in the output, in seconds */
-       double const out_pts_seconds = video_frame() / frames_per_second();
+       double const out_pts_seconds = video_frame() / video_frame_rate();
        
        /* Where we are in the source, in seconds */
        double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
@@ -567,17 +567,17 @@ FFmpegDecoder::out_with_sync ()
        
        /* Difference between where we are and where we should be */
        double const delta = source_pts_seconds - _first_video.get() - out_pts_seconds;
-       double const one_frame = 1 / frames_per_second();
+       double const one_frame = 1 / video_frame_rate();
        
        /* Insert frames if required to get out_pts_seconds up to pts_seconds */
        if (delta > one_frame) {
                int const extra = rint (delta / one_frame);
                for (int i = 0; i < extra; ++i) {
-                       repeat_last_video ();
+                       repeat_last_video (frame_time ());
                        _film->log()->log (
                                String::compose (
                                        N_("Extra video frame inserted at %1s; source frame %2, source PTS %3 (at %4 fps)"),
-                                       out_pts_seconds, video_frame(), source_pts_seconds, frames_per_second()
+                                       out_pts_seconds, video_frame(), source_pts_seconds, video_frame_rate()
                                        )
                                );
                }
@@ -613,7 +613,7 @@ FFmpegDecoder::film_changed (Film::Property p)
 ContentVideoFrame
 FFmpegDecoder::video_length () const
 {
-       return (double(_format_context->duration) / AV_TIME_BASE) * frames_per_second();
+       return (double(_format_context->duration) / AV_TIME_BASE) * video_frame_rate();
 }
 
 double
index 5023ac56ce8e72d98acf5eb45ba13fa7da421d98..cd37d20c6de6cabc53545690a060bedc71720fee 100644 (file)
@@ -60,7 +60,7 @@ public:
        FFmpegDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const FFmpegContent>, bool video, bool audio, bool subtitles, bool video_sync);
        ~FFmpegDecoder ();
 
-       float frames_per_second () const;
+       float video_frame_rate () const;
        libdcp::Size native_size () const;
        ContentVideoFrame video_length () const;
        int time_base_numerator () const;
index dff177548fd6004bfbf538bc8d7973a20d6e5a8d..6a2be1a7ca720560666d955da64eb5651c7eeef2 100644 (file)
@@ -66,7 +66,7 @@ ImageMagickDecoder::pass ()
        }
 
        if (have_last_video ()) {
-               repeat_last_video ();
+               repeat_last_video (double (_position) / 24);
                _position++;
                return false;
        }
@@ -92,7 +92,7 @@ ImageMagickDecoder::pass ()
 
        image = image->crop (_film->crop(), true);
        
-       emit_video (image, 0);
+       emit_video (image, double (_position) / 24);
 
        ++_position;
        return false;
index 424cefe08ff7bacdbdf6b53fb2a945d96a64d100..cb524b44ba2bad08b9fabcde78f7a815d72ccfa3 100644 (file)
@@ -30,7 +30,7 @@ class ImageMagickDecoder : public VideoDecoder
 public:
        ImageMagickDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const ImageMagickContent>);
 
-       float frames_per_second () const {
+       float video_frame_rate () const {
                return 24;
        }
 
index d1f04785115c05a15f6ba87bff5913e6dfb67bf1..ac046fcc0e6eaf9e59c912da2f6ad6a3a812a5e7 100644 (file)
@@ -277,7 +277,14 @@ Player::last_video_time () const
        case Playlist::VIDEO_FFMPEG:
                return _ffmpeg_decoder->last_source_time ();
        case Playlist::VIDEO_IMAGEMAGICK:
-               return (*_imagemagick_decoder)->last_source_time ();
+       {
+               double t = 0;
+               for (list<shared_ptr<ImageMagickDecoder> >::const_iterator i = _imagemagick_decoders.begin(); i != _imagemagick_decoder; ++i) {
+                       t += (*i)->video_length() / (*i)->video_frame_rate ();
+               }
+
+               return t + (*_imagemagick_decoder)->last_source_time ();
+       }
        }
 
        return 0;
index 8176c5c41710c75140f483fa9eed213197c2b921..9fb2b9bce8f3a4c12860ee6bae4ab00e8b2ef59f 100644 (file)
@@ -73,7 +73,7 @@ VideoContent::take_from_video_decoder (shared_ptr<VideoDecoder> d)
 {
        /* These decoder calls could call other content methods which take a lock on the mutex */
        libdcp::Size const vs = d->native_size ();
-       float const vfr = d->frames_per_second ();
+       float const vfr = d->video_frame_rate ();
        
         {
                 boost::mutex::scoped_lock lm (_mutex);
index 47385cc614c8c1387e756b254edbb85f6c78b333..fd2b28d7f13ed8bee4166491aff55620dc800452 100644 (file)
@@ -50,8 +50,7 @@ VideoDecoder::emit_video (shared_ptr<Image> image, double t)
                sub = _timed_subtitle->subtitle ();
        }
 
-       signal_video (image, false, sub);
-       _last_source_time = t;
+       signal_video (image, false, sub, t);
 }
 
 bool
@@ -65,14 +64,14 @@ VideoDecoder::have_last_video () const
  *  we will generate a black frame.
  */
 void
-VideoDecoder::repeat_last_video ()
+VideoDecoder::repeat_last_video (double t)
 {
        if (!_last_image) {
                _last_image.reset (new SimpleImage (pixel_format(), native_size(), true));
                _last_image->make_black ();
        }
 
-       signal_video (_last_image, true, _last_subtitle);
+       signal_video (_last_image, true, _last_subtitle, t);
 }
 
 /** Emit our signal to say that some video data is ready.
@@ -81,7 +80,7 @@ VideoDecoder::repeat_last_video ()
  *  @param sub Subtitle for this frame, or 0.
  */
 void
-VideoDecoder::signal_video (shared_ptr<Image> image, bool same, shared_ptr<Subtitle> sub)
+VideoDecoder::signal_video (shared_ptr<Image> image, bool same, shared_ptr<Subtitle> sub, double t)
 {
        TIMING (N_("Decoder emits %1"), _video_frame);
        Video (image, same, sub);
@@ -89,6 +88,7 @@ VideoDecoder::signal_video (shared_ptr<Image> image, bool same, shared_ptr<Subti
 
        _last_image = image;
        _last_subtitle = sub;
+       _last_source_time = t;
 }
 
 /** Set up the current subtitle.  This will be put onto frames that
index 74343e856a6761c2d029e677f1af0815ed3865ba..c04874342c07846f81d69ad9f02797165b3977b3 100644 (file)
@@ -30,8 +30,8 @@ class VideoDecoder : public VideoSource, public virtual Decoder
 public:
        VideoDecoder (boost::shared_ptr<const Film>);
 
-       /** @return video frames per second, or 0 if unknown */
-       virtual float frames_per_second () const = 0;
+       /** @return video frame rate second, or 0 if unknown */
+       virtual float video_frame_rate () const = 0;
        /** @return native size in pixels */
        virtual libdcp::Size native_size () const = 0;
        /** @return length according to our content's header */
@@ -59,10 +59,10 @@ protected:
        void emit_video (boost::shared_ptr<Image>, double);
        void emit_subtitle (boost::shared_ptr<TimedSubtitle>);
        bool have_last_video () const;
-       void repeat_last_video ();
+       void repeat_last_video (double);
 
 private:
-       void signal_video (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>);
+       void signal_video (boost::shared_ptr<Image>, bool, boost::shared_ptr<Subtitle>, double);
 
        int _video_frame;
        double _last_source_time;