Start of changing frame numbers to time.
authorCarl Hetherington <cth@carlh.net>
Fri, 13 Dec 2013 10:23:20 +0000 (10:23 +0000)
committerCarl Hetherington <cth@carlh.net>
Fri, 13 Dec 2013 10:23:20 +0000 (10:23 +0000)
src/lib/audio_decoder.cc
src/lib/audio_decoder.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/player.cc
src/lib/player.h
src/lib/video_decoder.cc
src/lib/video_decoder.h

index c0ef02f65d5ab5518dcb7e53aa145b1ff3f9a598..a73ad4d7c4c2e510b129937fa47b7eba9bdf7595 100644 (file)
@@ -35,16 +35,14 @@ using boost::shared_ptr;
 AudioDecoder::AudioDecoder (shared_ptr<const Film> film, shared_ptr<const AudioContent> content)
        : Decoder (film)
        , _audio_content (content)
-       , _audio_position (0)
 {
 
 }
 
 void
-AudioDecoder::audio (shared_ptr<const AudioBuffers> data, AudioContent::Frame frame)
+AudioDecoder::audio (shared_ptr<const AudioBuffers> data, ContentTime time)
 {
-       Audio (data, frame);
-       _audio_position = frame + data->frames ();
+       Audio (data, time);
 }
 
 /** This is a bit odd, but necessary when we have (e.g.) FFmpegDecoders with no audio.
index ab6c4b8a931e12cfe892c8cb74d86ae7162d1a10..10e4298f76a35873c403bc16b42fd8295ec7f801 100644 (file)
@@ -41,13 +41,12 @@ public:
        bool has_audio () const;
 
        /** Emitted when some audio data is ready */
-       boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame)> Audio;
+       boost::signals2::signal<void (boost::shared_ptr<const AudioBuffers>, ContentTime)> Audio;
 
 protected:
 
-       void audio (boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
+       void audio (boost::shared_ptr<const AudioBuffers>, ContentTime);
        boost::shared_ptr<const AudioContent> _audio_content;
-       AudioContent::Frame _audio_position;
 };
 
 #endif
index 2cb18c557e62a59c0bc731458a360649f686ebe8..d72fed0bcc2c8e0ce73d11f772a7e2b167b2a93a 100644 (file)
@@ -70,7 +70,6 @@ FFmpegDecoder::FFmpegDecoder (shared_ptr<const Film> f, shared_ptr<const FFmpegC
        , _decode_audio (audio)
        , _video_pts_offset (0)
        , _audio_pts_offset (0)
-       , _just_sought (false)
 {
        setup_subtitle ();
 
@@ -411,8 +410,6 @@ FFmpegDecoder::seek (DCPTime time, bool accurate)
 
        seek_and_flush (initial_seek);
 
-       _just_sought = true;
-       
        if (time == 0 || !accurate) {
                /* We're already there, or we're as close as we need to be */
                return;
@@ -448,31 +445,14 @@ FFmpegDecoder::decode_audio_packet ()
                }
 
                if (frame_finished) {
-                       
-                       if (_audio_position == 0) {
-                               /* Where we are in the source, in seconds */
-                               double const pts = av_q2d (_format_context->streams[copy_packet.stream_index]->time_base)
-                                       * av_frame_get_best_effort_timestamp(_frame) + _audio_pts_offset;
-
-                               if (pts > 0) {
-                                       /* Emit some silence */
-                                       shared_ptr<AudioBuffers> silence (
-                                               new AudioBuffers (
-                                                       _ffmpeg_content->audio_channels(),
-                                                       pts * _ffmpeg_content->content_audio_frame_rate()
-                                                       )
-                                               );
-                                       
-                                       silence->make_silent ();
-                                       audio (silence, _audio_position);
-                               }
-                       }
+                       Time const t = (av_q2d (_format_context->streams[copy_packet.stream_index]->time_base)
+                                       * av_frame_get_best_effort_timestamp(_frame) + _audio_pts_offset) * TIME_HZ;
                        
                        int const data_size = av_samples_get_buffer_size (
                                0, audio_codec_context()->channels, _frame->nb_samples, audio_sample_format (), 1
                                );
                        
-                       audio (deinterleave_audio (_frame->data, data_size), _audio_position);
+                       audio (deinterleave_audio (_frame->data, data_size), t);
                }
                        
                copy_packet.data += decode_result;
@@ -521,45 +501,8 @@ FFmpegDecoder::decode_video_packet ()
                }
                
                if (i->second != AV_NOPTS_VALUE) {
-
-                       double const pts = i->second * av_q2d (_format_context->streams[_video_stream]->time_base) + _video_pts_offset;
-
-                       if (_just_sought) {
-                               /* We just did a seek, so disable any attempts to correct for where we
-                                  are / should be.
-                               */
-                               _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;
-
-                       while (delta > one_frame) {
-                               /* This PTS is more than one frame forward in time of where we think we should be; emit
-                                  a black frame.
-                               */
-
-                               /* XXX: I think this should be a copy of the last frame... */
-                               boost::shared_ptr<Image> black (
-                                       new Image (
-                                               static_cast<AVPixelFormat> (_frame->format),
-                                               libdcp::Size (video_codec_context()->width, video_codec_context()->height),
-                                               true
-                                               )
-                                       );
-                               
-                               black->make_black ();
-                               video (image, false, _video_position);
-                               delta -= one_frame;
-                       }
-
-                       if (delta > -one_frame) {
-                               /* This PTS is within a frame of being right; emit this (otherwise it will be dropped) */
-                               video (image, false, _video_position);
-                       }
-                               
+                       Time const t = (i->second * av_q2d (_format_context->streams[_video_stream]->time_base) + _video_pts_offset) * TIME_HZ;
+                       video (image, false, t);
                } else {
                        shared_ptr<const Film> film = _film.lock ();
                        assert (film);
index 06e0ef8a551a37804caaeea9b415868ac596d2f6..ed45577029e24312326d2f890cd659f46de0243f 100644 (file)
@@ -90,5 +90,4 @@ private:
 
        double _video_pts_offset;
        double _audio_pts_offset;
-       bool _just_sought;
 };
index be22ae2421f54c6508aac35db80db0d2fd2c329f..7f5e78681c44a53d688b5bf62cf6c13f323a285f 100644 (file)
@@ -86,13 +86,23 @@ public:
 
        void repeat (Player* player)
        {
+               shared_ptr<Piece> p = repeat_video.weak_piece.lock ();
+               if (!p) {
+                       return;
+               }
+
+               shared_ptr<VideoContent> vc = dynamic_pointer_cast<VideoContent> (p->content);
+               if (!vc) {
+                       return;
+               }
+                       
                player->process_video (
                        repeat_video.weak_piece,
                        repeat_video.image,
                        repeat_video.eyes,
                        repeat_done > 0,
-                       repeat_video.frame,
-                       (repeat_done + 1) * (TIME_HZ / player->_film->video_frame_rate ())
+                       repeat_video.time,
+                       (repeat_done + 1) * (TIME_HZ / vc->video_frame_rate ())
                        );
 
                ++repeat_done;
@@ -241,14 +251,14 @@ Player::pass ()
 
 /** @param extra Amount of extra time to add to the content frame's time (for repeat) */
 void
-Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, VideoContent::Frame frame, DCPTime extra)
+Player::process_video (weak_ptr<Piece> weak_piece, shared_ptr<const Image> image, Eyes eyes, bool same, ContentTime time, ContentTime extra)
 {
        /* Keep a note of what came in so that we can repeat it if required */
        _last_incoming_video.weak_piece = weak_piece;
        _last_incoming_video.image = image;
        _last_incoming_video.eyes = eyes;
        _last_incoming_video.same = same;
-       _last_incoming_video.frame = frame;
+       _last_incoming_video.time = time;
        _last_incoming_video.extra = extra;
        
        shared_ptr<Piece> piece = weak_piece.lock ();
@@ -689,7 +699,7 @@ Player::repeat_last_video ()
                _last_incoming_video.image,
                _last_incoming_video.eyes,
                _last_incoming_video.same,
-               _last_incoming_video.frame,
+               _last_incoming_video.time,
                _last_incoming_video.extra
                );
 
index 364d66249ca693cf50fb8325a165d64fdbf68a8b..0d6c8d8ba94adc63ebeb0ae3e9fde5ec62a131c0 100644 (file)
@@ -49,8 +49,8 @@ public:
        boost::shared_ptr<const Image> image;
        Eyes eyes;
        bool same;
-       VideoContent::Frame frame;
-       DCPTime extra;
+       ContentTime time;
+       ContentTime extra;
 };
 
 /** A wrapper for an Image which contains some pending operations; these may
@@ -118,8 +118,8 @@ private:
        friend class PlayerWrapper;
        friend class Piece;
 
-       void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const Image>, Eyes, bool, VideoContent::Frame, DCPTime);
-       void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, AudioContent::Frame);
+       void process_video (boost::weak_ptr<Piece>, boost::shared_ptr<const Image>, Eyes, bool, ContentTime, ContentTime);
+       void process_audio (boost::weak_ptr<Piece>, boost::shared_ptr<const AudioBuffers>, ContentTime);
        void process_subtitle (boost::weak_ptr<Piece>, boost::shared_ptr<Image>, dcpomatic::Rect<double>, DCPTime, DCPTime);
        void setup_pieces ();
        void playlist_changed ();
index eaa4534e44b64ab6c6e503b06bfae280e8dde08e..72caf72e903e9536ed1d342792d5e5ddae47c492 100644 (file)
@@ -28,27 +28,24 @@ using boost::shared_ptr;
 VideoDecoder::VideoDecoder (shared_ptr<const Film> f, shared_ptr<const VideoContent> c)
        : Decoder (f)
        , _video_content (c)
-       , _video_position (0)
 {
 
 }
 
 void
-VideoDecoder::video (shared_ptr<const Image> image, bool same, VideoContent::Frame frame)
+VideoDecoder::video (shared_ptr<const Image> image, bool same, ContentTime time)
 {
        switch (_video_content->video_frame_type ()) {
        case VIDEO_FRAME_TYPE_2D:
-               Video (image, EYES_BOTH, same, frame);
+               Video (image, EYES_BOTH, same, time);
                break;
        case VIDEO_FRAME_TYPE_3D_LEFT_RIGHT:
        {
                int const half = image->size().width / 2;
-               Video (image->crop (Crop (0, half, 0, 0), true), EYES_LEFT, same, frame);
-               Video (image->crop (Crop (half, 0, 0, 0), true), EYES_RIGHT, same, frame);
+               Video (image->crop (Crop (0, half, 0, 0), true), EYES_LEFT, same, time);
+               Video (image->crop (Crop (half, 0, 0, 0), true), EYES_RIGHT, same, time);
                break;
        }
        }
-       
-       _video_position = frame + 1;
 }
 
index 01319e48125a933bada580fd00ed3d559b46ae49..6e9060dbd14abc2d90c07a09d8f2736cae0ffc48 100644 (file)
@@ -38,15 +38,14 @@ public:
         *  First parameter is the video image.
         *  Second parameter is the eye(s) which should see this image.
         *  Third parameter is true if the image is the same as the last one that was emitted for this Eyes value.
-        *  Fourth parameter is the frame within our source.
+        *  Fourth parameter is the time within our source.
         */
-       boost::signals2::signal<void (boost::shared_ptr<const Image>, Eyes, bool, VideoContent::Frame)> Video;
+       boost::signals2::signal<void (boost::shared_ptr<const Image>, Eyes, bool, ContentTime)> Video;
        
 protected:
 
-       void video (boost::shared_ptr<const Image>, bool, VideoContent::Frame);
+       void video (boost::shared_ptr<const Image>, bool, ContentTime);
        boost::shared_ptr<const VideoContent> _video_content;
-       VideoContent::Frame _video_position;
 };
 
 #endif