Hopefully fix up still-image generation.
authorCarl Hetherington <cth@carlh.net>
Wed, 6 Mar 2013 22:55:11 +0000 (22:55 +0000)
committerCarl Hetherington <cth@carlh.net>
Wed, 6 Mar 2013 22:55:11 +0000 (22:55 +0000)
src/lib/ffmpeg_decoder.cc
src/lib/imagemagick_decoder.cc
src/lib/imagemagick_decoder.h
src/lib/matcher.cc
src/lib/matcher.h
src/lib/video_decoder.cc
src/lib/video_decoder.h

index e1834d7f644fbc768e28c2b19a48c4dd687d9b6f..2d7092789b849de3110e07ceb7f980d28eb187bf 100644 (file)
@@ -520,7 +520,7 @@ FFmpegDecoder::filter_and_emit_video ()
        for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
                int64_t const bet = av_frame_get_best_effort_timestamp (_frame);
                if (bet != AV_NOPTS_VALUE) {
-                       emit_video (*i, bet * av_q2d (_format_context->streams[_video_stream]->time_base));
+                       emit_video (*i, false, bet * av_q2d (_format_context->streams[_video_stream]->time_base));
                } else {
                        _film->log()->log ("Dropping frame without PTS");
                }
index 119f057928defa198c9776ff4bcb2e439cc553f0..5ce22c29622a403c33425a5ce6e8e9a5f3e26de5 100644 (file)
@@ -31,8 +31,6 @@ using std::cout;
 using boost::shared_ptr;
 using libdcp::Size;
 
-/* XXX: reads a directory and then ignores it */
-
 ImageMagickDecoder::ImageMagickDecoder (
        boost::shared_ptr<Film> f, DecodeOptions o)
        : Decoder (f, o)
@@ -79,8 +77,7 @@ ImageMagickDecoder::pass ()
                        return true;
                }
 
-               /* XXX: timestamp */
-               emit_video (_image, 0);
+               emit_video (_image, true, double (video_frame()) / frames_per_second());
                return false;
        }
        
@@ -105,8 +102,7 @@ ImageMagickDecoder::pass ()
 
        _image = image->crop (_film->crop(), true);
 
-       /* XXX: timestamp */
-       emit_video (_image, 0);
+       emit_video (_image, false, double (video_frame()) / frames_per_second());
 
        ++_iter;
        return false;
@@ -134,7 +130,6 @@ ImageMagickDecoder::seek_to_last ()
 bool
 ImageMagickDecoder::seek (double t)
 {
-       /* XXX: frames_per_second == 0 */
        int const f = t * frames_per_second();
        
        _iter = _files.begin ();
@@ -155,3 +150,9 @@ ImageMagickDecoder::film_changed (Film::Property p)
                OutputChanged ();
        }
 }
+
+float
+ImageMagickDecoder::frames_per_second () const
+{
+       return _film->source_frame_rate ();
+}
index ef550c6515b18cedbb66f4db2113de597cdb0705..ca8e819d39277da33db4059eb03ec1be57a896ee 100644 (file)
@@ -28,10 +28,7 @@ class ImageMagickDecoder : public VideoDecoder
 public:
        ImageMagickDecoder (boost::shared_ptr<Film>, DecodeOptions);
 
-       float frames_per_second () const {
-               /* We don't know */
-               return 0;
-       }
+       float frames_per_second () const;
 
        libdcp::Size native_size () const;
 
@@ -88,5 +85,4 @@ private:
        std::list<std::string>::iterator _iter;
 
        boost::shared_ptr<Image> _image;
-       
 };
index 93531dbc5adc6dd2584fb2d86b3d98bafeefc8d9..fbd3e3e76887a2fea0f869186a4c7285a3cdc6c3 100644 (file)
@@ -49,37 +49,35 @@ Matcher::process_video (boost::shared_ptr<Image> image, bool same, boost::shared
        if (!_first_input) {
                _first_input = t;
        }
+
+       /* Video before audio is fine, since we can make up an arbitrary difference
+          with audio samples (contrasting with video which is quantised to frames)
+       */
+
+       /* Difference between where this video is and where it should be */
+       double const delta = t - _first_input.get() - _video_frames / _frames_per_second;
+       double const one_frame = 1 / _frames_per_second;
+       
+       if (delta > one_frame) {
+               /* Insert frames to make up the difference */
+               int const extra = rint (delta / one_frame);
+               for (int i = 0; i < extra; ++i) {
+                       repeat_last_video ();
+                       _log->log (String::compose ("Extra video frame inserted at %1s", _video_frames / _frames_per_second));
+               }
+       }
+               
+       if (delta > -one_frame) {
+               Video (image, same, sub);
+               ++_video_frames;
+       } else {
+               /* We are omitting a frame to keep things right */
+               _log->log (String::compose ("Frame removed at %1s", t));
+       }
        
-       if (_audio_frames == 0 && _pending_audio.empty ()) {
-               /* No audio yet; we must postpone this frame until we have some */
-               _pending_video.push_back (VideoRecord (image, same, sub, t));
-       } else if (!_pending_audio.empty() && _pending_video.empty ()) {
+       if (!_pending_audio.empty() && _video_frames == 1) {
                /* First video since we got audio */
-               _pending_video.push_back (VideoRecord (image, same, sub, t));
                fix_start ();
-       } else {
-               /* Normal running */
-
-               /* Difference between where this video is and where it should be */
-               double const delta = t - _first_input.get() - _video_frames / _frames_per_second;
-               double const one_frame = 1 / _frames_per_second;
-
-               if (delta > one_frame) {
-                       /* Insert frames to make up the difference */
-                       int const extra = rint (delta / one_frame);
-                       for (int i = 0; i < extra; ++i) {
-                               repeat_last_video ();
-                               _log->log (String::compose ("Extra video frame inserted at %1s", _video_frames / _frames_per_second));
-                       }
-               }
-
-               if (delta > -one_frame) {
-                       Video (image, same, sub);
-                       ++_video_frames;
-               } else {
-                       /* We are omitting a frame to keep things right */
-                       _log->log (String::compose ("Frame removed at %1s", t));
-               }
        }
                
        _last_image = image;
@@ -95,10 +93,10 @@ Matcher::process_audio (boost::shared_ptr<AudioBuffers> b, double t)
                _first_input = t;
        }
        
-       if (_video_frames == 0 && _pending_video.empty ()) {
+       if (_video_frames == 0) {
                /* No video yet; we must postpone these data until we have some */
                _pending_audio.push_back (AudioRecord (b, t));
-       } else if (!_pending_video.empty() && _pending_audio.empty ()) {
+       } else if (_video_frames > 0 && _pending_audio.empty ()) {
                /* First audio since we got video */
                _pending_audio.push_back (AudioRecord (b, t));
                fix_start ();
@@ -126,22 +124,20 @@ Matcher::process_end ()
 void
 Matcher::fix_start ()
 {
-       assert (!_pending_video.empty ());
        assert (!_pending_audio.empty ());
+       assert (_first_input);
 
-       _log->log (String::compose ("Fixing start; video at %1, audio at %2", _pending_video.front().time, _pending_audio.front().time));
-
-       match (_pending_video.front().time - _pending_audio.front().time);
+       _log->log (String::compose ("Fixing start; start at %1, audio at %2", _first_input.get(), _pending_audio.front().time));
 
-       for (list<VideoRecord>::iterator i = _pending_video.begin(); i != _pending_video.end(); ++i) {
-               process_video (i->image, i->same, i->subtitle, i->time);
-       }
+       /* This will not add any video frames, since the input parameter will always be -ve.
+          Indeed, it cannot add any, since we've already started adding "real" video.
+       */
+       match (_first_input.get() - _pending_audio.front().time);
 
        for (list<AudioRecord>::iterator i = _pending_audio.begin(); i != _pending_audio.end(); ++i) {
                process_audio (i->audio, i->time);
        }
        
-       _pending_video.clear ();
        _pending_audio.clear ();
 }
 
index 2f580b589f7060b01ced9230dcdbcd459cea189d..84ae2f73eba86c7684a18bfbba321154aded8a91 100644 (file)
@@ -42,22 +42,6 @@ private:
        boost::optional<libdcp::Size> _size;
        boost::optional<int> _channels;
 
-       struct VideoRecord {
-               VideoRecord (boost::shared_ptr<Image> i, bool s, boost::shared_ptr<Subtitle> sub, double t)
-                       : image (i)
-                       , same (s)
-                       , subtitle (sub)
-                       , time (t)
-               {}
-               
-               boost::shared_ptr<Image> image;
-               bool same;
-               boost::shared_ptr<Subtitle> subtitle;
-               double time;
-       };
-
-       std::list<VideoRecord> _pending_video;
-
        struct AudioRecord {
                AudioRecord (boost::shared_ptr<AudioBuffers> a, double t)
                        : audio (a)
index 9c0d2bbe3a610e44d51e6cf608454bd20f53e25e..16a076698eff8c652061a693dc95960f38e0cf9e 100644 (file)
@@ -45,14 +45,14 @@ VideoDecoder::VideoDecoder (shared_ptr<Film> f, DecodeOptions o)
  *  @param t Time of the frame within the source, in seconds.
  */
 void
-VideoDecoder::emit_video (shared_ptr<Image> image, double t)
+VideoDecoder::emit_video (shared_ptr<Image> image, bool same, double t)
 {
        shared_ptr<Subtitle> sub;
        if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
                sub = _timed_subtitle->subtitle ();
        }
 
-       Video (image, false, sub, t);
+       Video (image, same, sub, t);
        ++_video_frame;
        
        _last_source_time = t;
index 1a02272a5ef245a591c1b1d5723834d4b7b2e25e..6e4fd48c0019710a2632e921d35645efa119c239 100644 (file)
@@ -65,7 +65,7 @@ protected:
        
        virtual PixelFormat pixel_format () const = 0;
 
-       void emit_video (boost::shared_ptr<Image>, double);
+       void emit_video (boost::shared_ptr<Image>, bool, double);
        void emit_subtitle (boost::shared_ptr<TimedSubtitle>);
 
        /** Subtitle stream to use when decoding */