Move video frame rate ('prepared-for') into Content.
authorCarl Hetherington <cth@carlh.net>
Mon, 9 May 2016 18:58:37 +0000 (19:58 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 18 May 2016 10:50:29 +0000 (11:50 +0100)
36 files changed:
src/lib/audio_content.cc
src/lib/audio_content.h
src/lib/audio_decoder.h
src/lib/content.cc
src/lib/content.h
src/lib/dcp_content.cc
src/lib/dcp_content.h
src/lib/dcp_decoder.cc
src/lib/dcp_subtitle_content.cc
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_content.h
src/lib/ffmpeg_decoder.cc
src/lib/film.cc
src/lib/image_content.cc
src/lib/image_decoder.cc
src/lib/image_examiner.cc
src/lib/player.cc
src/lib/playlist.cc
src/lib/sndfile_content.cc
src/lib/subtitle_content.cc
src/lib/subtitle_content.h
src/lib/text_subtitle_content.cc
src/lib/video_content.cc
src/lib/video_content.h
src/lib/video_decoder.cc
src/lib/video_decoder.h
src/tools/dcpomatic_cli.cc
src/wx/audio_panel.cc
src/wx/content_panel.cc
src/wx/timing_panel.cc
src/wx/video_panel.cc
test/ffmpeg_decoder_sequential_test.cc
test/ffmpeg_pts_offset_test.cc
test/frame_rate_test.cc
test/seek_zero_test.cc
test/time_calculation_test.cc

index a903cfb9a4b7211d58f7f07a15b8be0293c05f5e..a0c9950a680abf7ed930b8db60cfdf721019c58f 100644 (file)
@@ -47,7 +47,6 @@ using boost::optional;
 int const AudioContentProperty::STREAMS = 200;
 int const AudioContentProperty::GAIN = 201;
 int const AudioContentProperty::DELAY = 202;
-int const AudioContentProperty::VIDEO_FRAME_RATE = 203;
 
 AudioContent::AudioContent (Content* parent, shared_ptr<const Film> film)
        : ContentPart (parent, film)
@@ -62,7 +61,12 @@ AudioContent::AudioContent (Content* parent, shared_ptr<const Film> film, cxml::
 {
        _gain = node->number_child<double> ("AudioGain");
        _delay = node->number_child<int> ("AudioDelay");
-       _video_frame_rate = node->optional_number_child<double> ("AudioVideoFrameRate");
+
+       /* Backwards compatibility */
+       optional<double> r = node->optional_number_child<double> ("AudioVideoFrameRate");
+       if (r) {
+               _parent->set_video_frame_rate (r.get ());
+       }
 }
 
 AudioContent::AudioContent (Content* parent, shared_ptr<const Film> film, vector<shared_ptr<Content> > c)
@@ -79,16 +83,10 @@ AudioContent::AudioContent (Content* parent, shared_ptr<const Film> film, vector
                if (c[i]->audio->delay() != ref->delay()) {
                        throw JoinError (_("Content to be joined must have the same audio delay."));
                }
-
-               if (c[i]->audio->video_frame_rate() != ref->video_frame_rate()) {
-                       throw JoinError (_("Content to be joined must have the same video frame rate."));
-               }
        }
 
        _gain = ref->gain ();
        _delay = ref->delay ();
-       /* Preserve the optional<> part of this */
-       _video_frame_rate = ref->_video_frame_rate;
        _streams = ref->streams ();
 }
 
@@ -98,9 +96,6 @@ AudioContent::as_xml (xmlpp::Node* node) const
        boost::mutex::scoped_lock lm (_mutex);
        node->add_child("AudioGain")->add_child_text (raw_convert<string> (_gain));
        node->add_child("AudioDelay")->add_child_text (raw_convert<string> (_delay));
-       if (_video_frame_rate) {
-               node->add_child("AudioVideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate.get()));
-       }
 }
 
 void
@@ -184,7 +179,7 @@ AudioContent::resampled_frame_rate () const
 
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
-       FrameRateChange frc (video_frame_rate(), film->video_frame_rate());
+       FrameRateChange frc (_parent->active_video_frame_rate(), film->video_frame_rate());
 
        /* Compensate if the DCP is being run at a different frame rate
           to the source; that is, if the video is run such that it will
@@ -295,7 +290,7 @@ AudioContent::add_properties (list<UserProperty>& p) const
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
 
-       FrameRateChange const frc (video_frame_rate(), film->video_frame_rate());
+       FrameRateChange const frc (_parent->active_video_frame_rate(), film->video_frame_rate());
        ContentTime const c (_parent->full_length(), frc);
 
        p.push_back (
@@ -326,30 +321,6 @@ AudioContent::add_properties (list<UserProperty>& p) const
        }
 }
 
-void
-AudioContent::set_video_frame_rate (double r)
-{
-       maybe_set (_video_frame_rate, r, AudioContentProperty::VIDEO_FRAME_RATE);
-}
-
-double
-AudioContent::video_frame_rate () const
-{
-       {
-               boost::mutex::scoped_lock lm (_mutex);
-               if (_video_frame_rate) {
-                       return _video_frame_rate.get ();
-               }
-       }
-
-       /* No frame rate specified, so assume this content has been
-          prepared for any concurrent video content.
-       */
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
-       return film->active_frame_rate_change(_parent->position()).source;
-}
-
 void
 AudioContent::set_streams (vector<AudioStreamPtr> streams)
 {
index cfce3fb835c5ae75c52a6b63a011c5d4ecdf7458..7de0742a51067fdfc061f6e66c1d1f9c401a42f3 100644 (file)
@@ -37,7 +37,6 @@ public:
        static int const STREAMS;
        static int const GAIN;
        static int const DELAY;
-       static int const VIDEO_FRAME_RATE;
 };
 
 class AudioContent : public ContentPart
@@ -69,9 +68,6 @@ public:
                return _delay;
        }
 
-       double video_frame_rate () const;
-       void set_video_frame_rate (double r);
-
        std::string processing_description () const;
 
        std::vector<AudioStreamPtr> streams () const {
@@ -92,7 +88,6 @@ private:
        double _gain;
        /** Delay to apply to audio (positive moves audio later) in milliseconds */
        int _delay;
-       boost::optional<double> _video_frame_rate;
        std::vector<AudioStreamPtr> _streams;
 };
 
index 679cdd5c5123f59a98f0b3667e1c2511a777938e..31d0785c6cbc9c9aab196cbb480e85e5fcf6b420 100644 (file)
@@ -42,10 +42,6 @@ class AudioDecoder : public virtual Decoder, public boost::enable_shared_from_th
 public:
        AudioDecoder (boost::shared_ptr<const AudioContent>, bool fast, boost::shared_ptr<Log> log);
 
-       boost::shared_ptr<const AudioContent> audio_content () const {
-               return _audio_content;
-       }
-
        /** Try to fetch some audio from a specific place in this content.
         *  @param frame Frame to start from (after resampling, if applicable)
         *  @param length Frames to get (after resampling, if applicable)
index 3b9c3e3a1e55e13503641b4fd6d8c3586f87122f..ff35eeab73969c49b39386f386660e3a2f464395 100644 (file)
@@ -50,6 +50,7 @@ int const ContentProperty::POSITION = 401;
 int const ContentProperty::LENGTH = 402;
 int const ContentProperty::TRIM_START = 403;
 int const ContentProperty::TRIM_END = 404;
+int const ContentProperty::VIDEO_FRAME_RATE = 405;
 
 Content::Content (shared_ptr<const Film> film)
        : _film (film)
@@ -157,7 +158,6 @@ Content::signal_changed (int p)
 {
        try {
                emit (boost::bind (boost::ref (Changed), shared_from_this (), p, _change_signals_frequent));
-               changed (p);
        } catch (boost::bad_weak_ptr) {
                /* This must be during construction; never mind */
        }
@@ -308,3 +308,33 @@ Content::reel_split_points () const
        t.push_back (position().round_up (film()->video_frame_rate()));
        return t;
 }
+
+void
+Content::set_video_frame_rate (double r)
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               _video_frame_rate = r;
+       }
+
+       signal_changed (ContentProperty::VIDEO_FRAME_RATE);
+}
+
+double
+Content::active_video_frame_rate () const
+{
+       {
+               boost::mutex::scoped_lock lm (_mutex);
+               if (_video_frame_rate) {
+                       return _video_frame_rate.get ();
+               }
+       }
+
+       /* No frame rate specified, so assume this content has been
+          prepared for any concurrent video content or perhaps
+          just the DCP rate.
+       */
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+       return film->active_frame_rate_change(position()).source;
+}
index 60dd89b97ef99cc71a579f4c72c2bd7738951f41..53de14ac17a230b1b576549f2ea9cb4f9db6cebe 100644 (file)
@@ -54,6 +54,7 @@ public:
        static int const LENGTH;
        static int const TRIM_START;
        static int const TRIM_END;
+       static int const VIDEO_FRAME_RATE;
 };
 
 /** @class Content
@@ -93,8 +94,6 @@ public:
         */
        virtual std::list<DCPTime> reel_split_points () const;
 
-       virtual void changed (int) {}
-
        boost::shared_ptr<Content> clone () const;
 
        void set_path (boost::filesystem::path);
@@ -158,6 +157,15 @@ public:
 
        DCPTime length_after_trim () const;
 
+       boost::optional<double> video_frame_rate () const {
+               boost::mutex::scoped_lock lm (_mutex);
+               return _video_frame_rate;
+       }
+
+       void set_video_frame_rate (double r);
+
+       double active_video_frame_rate () const;
+
        void set_change_signals_frequent (bool f) {
                _change_signals_frequent = f;
        }
@@ -189,10 +197,20 @@ protected:
        std::vector<boost::filesystem::path> _paths;
 
 private:
+       friend struct ffmpeg_pts_offset_test;
+       friend struct best_dcp_frame_rate_test_single;
+       friend struct best_dcp_frame_rate_test_double;
+       friend struct audio_sampling_rate_test;
+
        std::string _digest;
        DCPTime _position;
        ContentTime _trim_start;
        ContentTime _trim_end;
+       /** The video frame rate that this content is or was prepared to be used with,
+        *  or empty if the effective rate of this content should be dictated by something
+        *  else (either some video happening at the same time, or the rate of the DCP).
+        */
+       boost::optional<double> _video_frame_rate;
        bool _change_signals_frequent;
 };
 
index 43b404f6004ac4c554b30eab2f9b162def8491f4..6a6f6efc51013e068dfdfc6db896691c45d1a8d3 100644 (file)
@@ -193,7 +193,7 @@ DCPContent::as_xml (xmlpp::Node* node) const
 DCPTime
 DCPContent::full_length () const
 {
-       FrameRateChange const frc (video->frame_rate (), film()->video_frame_rate ());
+       FrameRateChange const frc (active_video_frame_rate (), film()->video_frame_rate ());
        return DCPTime::from_frames (llrint (video->length () * frc.factor ()), film()->video_frame_rate ());
 }
 
@@ -363,11 +363,3 @@ DCPContent::can_reference_subtitle (list<string>& why_not) const
        /* XXX: this needs to be fixed */
        return true;
 }
-
-void
-DCPContent::changed (int property)
-{
-       if (property == VideoContentProperty::FRAME_RATE && subtitle) {
-               subtitle->set_video_frame_rate (video->frame_rate ());
-       }
-}
index 269a0373cfa2f55a038c319d2d0b30b625403e59..5c80587dd130f5a6e9f5be289d99be1b22ccc832 100644 (file)
@@ -65,8 +65,6 @@ public:
        void set_default_colour_conversion ();
        std::list<DCPTime> reel_split_points () const;
 
-       void changed (int property);
-
        boost::filesystem::path directory () const;
 
        bool encrypted () const {
index 1c25587e0aab2771255b0852978ee509896fd5de..8008fe515590fa52df974e4e14ac4f59e3eaff56 100644 (file)
@@ -44,7 +44,7 @@ using boost::shared_ptr;
 using boost::dynamic_pointer_cast;
 
 DCPDecoder::DCPDecoder (shared_ptr<const DCPContent> c, shared_ptr<Log> log, bool fast)
-       : VideoDecoder (c->video, log)
+       : VideoDecoder (c, log)
        , AudioDecoder (c->audio, fast, log)
        , SubtitleDecoder (c->subtitle)
        , _dcp_content (c)
@@ -74,7 +74,7 @@ DCPDecoder::pass (PassReason reason, bool)
                ++i;
        }
 
-       double const vfr = _dcp_content->video->frame_rate ();
+       double const vfr = _dcp_content->active_video_frame_rate ();
 
        /* Frame within the (played part of the) reel that is coming up next */
        int64_t const frame = _next.frames_round (vfr);
@@ -157,8 +157,8 @@ DCPDecoder::seek (ContentTime t, bool accurate)
        SubtitleDecoder::seek (t, accurate);
 
        _reel = _reels.begin ();
-       while (_reel != _reels.end() && t >= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->video->frame_rate ())) {
-               t -= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->video->frame_rate ());
+       while (_reel != _reels.end() && t >= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->active_video_frame_rate ())) {
+               t -= ContentTime::from_frames ((*_reel)->main_picture()->duration(), _dcp_content->active_video_frame_rate ());
                ++_reel;
        }
 
@@ -178,7 +178,7 @@ DCPDecoder::text_subtitles_during (ContentTimePeriod period, bool starting) cons
        /* XXX: inefficient */
 
        list<ContentTimePeriod> ctp;
-       double const vfr = _dcp_content->video->frame_rate ();
+       double const vfr = _dcp_content->active_video_frame_rate ();
 
        BOOST_FOREACH (shared_ptr<dcp::Reel> r, _reels) {
                if (!r->main_subtitle ()) {
index eabcaaafe14680c5054c6bd29769bd37a4534a2d..a6beacb0d728beb21acc3350e4d0555defe2b9d5 100644 (file)
@@ -67,7 +67,7 @@ DCPSubtitleContent::examine (shared_ptr<Job> job)
        shared_ptr<dcp::SMPTESubtitleAsset> smpte = dynamic_pointer_cast<dcp::SMPTESubtitleAsset> (sc);
        if (smpte) {
                subtitle->set_language (smpte->language().get_value_or (""));
-               subtitle->set_video_frame_rate (smpte->edit_rate().numerator);
+               set_video_frame_rate (smpte->edit_rate().numerator);
        }
 
        _length = ContentTime::from_seconds (sc->latest_subtitle_out().as_seconds ());
@@ -80,7 +80,7 @@ DCPSubtitleContent::examine (shared_ptr<Job> job)
 DCPTime
 DCPSubtitleContent::full_length () const
 {
-       FrameRateChange const frc (subtitle->video_frame_rate(), film()->video_frame_rate());
+       FrameRateChange const frc (active_video_frame_rate(), film()->video_frame_rate());
        return DCPTime (_length, frc);
 }
 
index 463722778d1fafb867044b9fc2ac05e2cd4c6737..f249a1c35da1bf47ce53545fccf1311eed0aa79c 100644 (file)
@@ -296,7 +296,7 @@ operator!= (FFmpegStream const & a, FFmpegStream const & b)
 DCPTime
 FFmpegContent::full_length () const
 {
-       FrameRateChange const frc (video->frame_rate (), film()->video_frame_rate ());
+       FrameRateChange const frc (active_video_frame_rate (), film()->video_frame_rate ());
        return DCPTime::from_frames (llrint (video->length_after_3d_combine() * frc.factor()), film()->video_frame_rate());
 }
 
@@ -499,14 +499,6 @@ FFmpegContent::signal_subtitle_stream_changed ()
        signal_changed (FFmpegContentProperty::SUBTITLE_STREAM);
 }
 
-void
-FFmpegContent::changed (int property)
-{
-       if (property == VideoContentProperty::FRAME_RATE && subtitle) {
-               subtitle->set_video_frame_rate (video->frame_rate ());
-       }
-}
-
 vector<shared_ptr<FFmpegAudioStream> >
 FFmpegContent::ffmpeg_audio_streams () const
 {
index b11486bf11ef166da4c29a96989fce2fef5def06..8d6b995f5d5ab2d3728aea06892ab9c7e07a1573 100644 (file)
@@ -65,8 +65,6 @@ public:
 
        void set_filters (std::vector<Filter const *> const &);
 
-       void changed (int property);
-
        std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _subtitle_streams;
index 57327b63d8a070c6259493ad8d34a852b072832f..68dcd518618eccfb10eac0467e8218e6ff65a3cd 100644 (file)
@@ -72,12 +72,12 @@ using boost::split;
 using dcp::Size;
 
 FFmpegDecoder::FFmpegDecoder (shared_ptr<const FFmpegContent> c, shared_ptr<Log> log, bool fast)
-       : VideoDecoder (c->video, log)
+       : VideoDecoder (c, log)
        , AudioDecoder (c->audio, fast, log)
        , SubtitleDecoder (c->subtitle)
        , FFmpeg (c)
        , _log (log)
-       , _pts_offset (pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->video->frame_rate()))
+       , _pts_offset (pts_offset (c->ffmpeg_audio_streams(), c->first_video(), c->active_video_frame_rate()))
 {
 }
 
@@ -413,7 +413,7 @@ FFmpegDecoder::decode_video_packet ()
                        double const pts = i->second * av_q2d (_format_context->streams[_video_stream]->time_base) + _pts_offset.seconds ();
                        video (
                                shared_ptr<ImageProxy> (new RawImageProxy (image)),
-                               llrint (pts * _ffmpeg_content->video->frame_rate ())
+                               llrint (pts * _ffmpeg_content->active_video_frame_rate ())
                                );
                } else {
                        LOG_WARNING_NC ("Dropping frame without PTS");
index 3d5d625e18326f4de7e0e3bde33aeed9985a8730..87a317e5769db7ab40c60e1a2dc3e6f14d9e68f6 100644 (file)
@@ -1096,7 +1096,7 @@ Film::playlist_content_changed (weak_ptr<Content> c, int p, bool frequent)
 {
        _dirty = true;
 
-       if (p == VideoContentProperty::FRAME_RATE) {
+       if (p == ContentProperty::VIDEO_FRAME_RATE) {
                set_video_frame_rate (_playlist->best_dcp_frame_rate ());
        } else if (p == AudioContentProperty::STREAMS) {
                signal_changed (NAME);
index 29af451b7edcaa03ca8a543b34a95c0b83b27098..57212c589155e699d93a5528d7a02dd5d294dbb4 100644 (file)
@@ -124,7 +124,7 @@ ImageContent::full_length () const
 {
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
-       FrameRateChange const frc (video->frame_rate(), film->video_frame_rate());
+       FrameRateChange const frc (active_video_frame_rate(), film->video_frame_rate());
        return DCPTime::from_frames (llrint (video->length_after_3d_combine() * frc.factor ()), film->video_frame_rate ());
 }
 
index c3a11ce971f3895aa3b6ccc8407105dff9757151..6c46b9c08597090f0af2497e456afe68ab0fd667 100644 (file)
@@ -35,7 +35,7 @@ using boost::shared_ptr;
 using dcp::Size;
 
 ImageDecoder::ImageDecoder (shared_ptr<const ImageContent> c, shared_ptr<Log> log)
-       : VideoDecoder (c->video, log)
+       : VideoDecoder (c, log)
        , _image_content (c)
        , _video_position (0)
 {
@@ -71,5 +71,5 @@ void
 ImageDecoder::seek (ContentTime time, bool accurate)
 {
        VideoDecoder::seek (time, accurate);
-       _video_position = time.frames_round (_image_content->video->frame_rate ());
+       _video_position = time.frames_round (_image_content->active_video_frame_rate ());
 }
index 8e15a9d4836b8aee38c2eb0c3893587c8eb1be02..e0be1579420a3ec103edd177dc0e62637f0db1e9 100644 (file)
@@ -85,9 +85,9 @@ ImageExaminer::video_size () const
 optional<double>
 ImageExaminer::video_frame_rate () const
 {
-       if (_image_content->video->has_own_frame_rate()) {
+       if (_image_content->video_frame_rate()) {
                /* The content already knows what frame rate it should be */
-               return _image_content->video->frame_rate();
+               return _image_content->video_frame_rate().get();
        }
 
        /* Don't know */
index 617085a7b88abbdf2b1f12754e5058b954a89939..2abb6a30c2a6d3a53b45eea27104f65b3b180d67 100644 (file)
@@ -80,19 +80,19 @@ using boost::scoped_ptr;
 static bool
 has_video (Content* c)
 {
-       return c->video;
+       return static_cast<bool>(c->video);
 }
 
 static bool
 has_audio (Content* c)
 {
-       return c->audio;
+       return static_cast<bool>(c->audio);
 }
 
 static bool
 has_subtitle (Content* c)
 {
-       return c->subtitle;
+       return static_cast<bool>(c->subtitle);
 }
 
 Player::Player (shared_ptr<const Film> film, shared_ptr<const Playlist> playlist)
@@ -132,13 +132,13 @@ Player::setup_pieces ()
                shared_ptr<const FFmpegContent> fc = dynamic_pointer_cast<const FFmpegContent> (i);
                if (fc) {
                        decoder.reset (new FFmpegDecoder (fc, _film->log(), _fast));
-                       frc = FrameRateChange (fc->video->frame_rate(), _film->video_frame_rate());
+                       frc = FrameRateChange (fc->active_video_frame_rate(), _film->video_frame_rate());
                }
 
                shared_ptr<const DCPContent> dc = dynamic_pointer_cast<const DCPContent> (i);
                if (dc) {
                        decoder.reset (new DCPDecoder (dc, _film->log(), _fast));
-                       frc = FrameRateChange (dc->video->frame_rate(), _film->video_frame_rate());
+                       frc = FrameRateChange (dc->active_video_frame_rate(), _film->video_frame_rate());
                }
 
                /* ImageContent */
@@ -156,7 +156,7 @@ Player::setup_pieces ()
                                decoder.reset (new ImageDecoder (ic, _film->log()));
                        }
 
-                       frc = FrameRateChange (ic->video->frame_rate(), _film->video_frame_rate());
+                       frc = FrameRateChange (ic->active_video_frame_rate(), _film->video_frame_rate());
                }
 
                /* SndfileContent */
@@ -180,7 +180,7 @@ Player::setup_pieces ()
                        }
 
                        if (best_overlap) {
-                               frc = FrameRateChange (best_overlap->video->frame_rate(), _film->video_frame_rate ());
+                               frc = FrameRateChange (best_overlap->active_video_frame_rate(), _film->video_frame_rate ());
                        } else {
                                /* No video overlap; e.g. if the DCP is just audio */
                                frc = FrameRateChange (_film->video_frame_rate(), _film->video_frame_rate ());
@@ -196,14 +196,14 @@ Player::setup_pieces ()
                shared_ptr<const TextSubtitleContent> rc = dynamic_pointer_cast<const TextSubtitleContent> (i);
                if (rc) {
                        decoder.reset (new TextSubtitleDecoder (rc));
-                       frc = FrameRateChange (rc->subtitle->video_frame_rate(), _film->video_frame_rate());
+                       frc = FrameRateChange (rc->active_video_frame_rate(), _film->video_frame_rate());
                }
 
                /* DCPSubtitleContent */
                shared_ptr<const DCPSubtitleContent> dsc = dynamic_pointer_cast<const DCPSubtitleContent> (i);
                if (dsc) {
                        decoder.reset (new DCPSubtitleDecoder (dsc));
-                       frc = FrameRateChange (dsc->subtitle->video_frame_rate(), _film->video_frame_rate());
+                       frc = FrameRateChange (dsc->active_video_frame_rate(), _film->video_frame_rate());
                }
 
                shared_ptr<VideoDecoder> vd = dynamic_pointer_cast<VideoDecoder> (decoder);
@@ -248,6 +248,7 @@ Player::playlist_content_changed (weak_ptr<Content> w, int property, bool freque
                Changed (frequent);
 
        } else if (
+               property == ContentProperty::VIDEO_FRAME_RATE ||
                property == SubtitleContentProperty::USE ||
                property == SubtitleContentProperty::X_OFFSET ||
                property == SubtitleContentProperty::Y_OFFSET ||
@@ -256,7 +257,6 @@ Player::playlist_content_changed (weak_ptr<Content> w, int property, bool freque
                property == SubtitleContentProperty::FONTS ||
                property == VideoContentProperty::CROP ||
                property == VideoContentProperty::SCALE ||
-               property == VideoContentProperty::FRAME_RATE ||
                property == VideoContentProperty::FADE_IN ||
                property == VideoContentProperty::FADE_OUT ||
                property == VideoContentProperty::COLOUR_CONVERSION
index 24a38f2cda97c45d39d63150a2ce69ca43865223..b473bee8a059882a039bc9ab5920f41bc1b6761d 100644 (file)
@@ -266,14 +266,14 @@ Playlist::best_dcp_frame_rate () const
 
                float this_error = 0;
                BOOST_FOREACH (shared_ptr<Content> j, _content) {
-                       if (!j->video || !j->video->has_own_frame_rate()) {
+                       if (!j->video || !j->video_frame_rate()) {
                                continue;
                        }
 
                        /* Best error for this content; we could use the content as-is or double its rate */
                        float best_error = min (
-                               float (fabs (i->source - j->video->frame_rate ())),
-                               float (fabs (i->source - j->video->frame_rate () * 2))
+                               float (fabs (i->source - j->video_frame_rate().get())),
+                               float (fabs (i->source - j->video_frame_rate().get() * 2))
                                );
 
                        /* Use the largest difference between DCP and source as the "error" */
@@ -375,7 +375,13 @@ Playlist::active_frame_rate_change (DCPTime t, int dcp_video_frame_rate) const
                        /* This is the first piece of content (going backwards...) that starts before t,
                           so it's the active one.
                        */
-                       return FrameRateChange ((*i)->video->frame_rate(), dcp_video_frame_rate);
+                       if ((*i)->video_frame_rate ()) {
+                               /* This content specified a rate, so use it */
+                               return FrameRateChange ((*i)->video_frame_rate().get(), dcp_video_frame_rate);
+                       } else {
+                               /* No specified rate so just use the DCP one */
+                               return FrameRateChange (dcp_video_frame_rate, dcp_video_frame_rate);
+                       }
                }
        }
 
index f8e58885ed4876d0559d29ac8375b58f6c7adf66..2b28ba8b4cf0688c86b688a85ee55e7e8a00f611 100644 (file)
@@ -114,6 +114,6 @@ SndfileContent::examine (shared_ptr<Job> job)
 DCPTime
 SndfileContent::full_length () const
 {
-       FrameRateChange const frc (audio->video_frame_rate(), film()->video_frame_rate());
+       FrameRateChange const frc (active_video_frame_rate(), film()->video_frame_rate());
        return DCPTime::from_frames (audio_length() / frc.speed_up, audio->stream()->frame_rate ());
 }
index 2066793fb94e79b966d53aa73bc0c85c6f56558f..228376c343a33dcfd7cde79ba513163a02815f94 100644 (file)
@@ -47,10 +47,9 @@ int const SubtitleContentProperty::USE = 504;
 int const SubtitleContentProperty::BURN = 505;
 int const SubtitleContentProperty::LANGUAGE = 506;
 int const SubtitleContentProperty::FONTS = 507;
-int const SubtitleContentProperty::VIDEO_FRAME_RATE = 508;
-int const SubtitleContentProperty::COLOUR = 509;
-int const SubtitleContentProperty::OUTLINE = 510;
-int const SubtitleContentProperty::OUTLINE_COLOUR = 511;
+int const SubtitleContentProperty::COLOUR = 508;
+int const SubtitleContentProperty::OUTLINE = 509;
+int const SubtitleContentProperty::OUTLINE_COLOUR = 510;
 
 SubtitleContent::SubtitleContent (Content* parent, shared_ptr<const Film> film)
        : ContentPart (parent, film)
@@ -86,7 +85,6 @@ SubtitleContent::SubtitleContent (Content* parent, shared_ptr<const Film> film,
                node->optional_number_child<int>("OutlineGreen").get_value_or(255),
                node->optional_number_child<int>("OutlineBlue").get_value_or(255)
                )
-       , _frame_rate (node->optional_number_child<double>("SubtitleFrameRate"))
 {
        if (version >= 32) {
                _use = node->bool_child ("UseSubtitles");
@@ -316,27 +314,3 @@ SubtitleContent::set_language (string language)
 {
        maybe_set (_language, language, SubtitleContentProperty::LANGUAGE);
 }
-
-void
-SubtitleContent::set_video_frame_rate (double r)
-{
-       maybe_set (_frame_rate, r, SubtitleContentProperty::VIDEO_FRAME_RATE);
-}
-
-double
-SubtitleContent::video_frame_rate () const
-{
-       {
-               boost::mutex::scoped_lock lm (_mutex);
-               if (_frame_rate) {
-                       return _frame_rate.get ();
-               }
-       }
-
-       /* No frame rate specified, so assume this content has been
-          prepared for any concurrent video content.
-       */
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
-       return film->active_frame_rate_change(_parent->position()).source;
-}
index cb61ad9a8e3efb03e688c2586555c9008b6a38e3..09cc92709b2a9a125efec4eff62ae7b83bded7a1 100644 (file)
@@ -38,7 +38,6 @@ public:
        static int const BURN;
        static int const LANGUAGE;
        static int const FONTS;
-       static int const VIDEO_FRAME_RATE;
        static int const COLOUR;
        static int const OUTLINE;
        static int const OUTLINE_COLOUR;
@@ -130,9 +129,6 @@ public:
                return _outline_colour;
        }
 
-       double video_frame_rate () const;
-       void set_video_frame_rate (double r);
-
 protected:
        /** subtitle language (e.g. "German") or empty if it is not known */
        std::string _language;
@@ -161,8 +157,6 @@ private:
        bool _outline;
        dcp::Colour _outline_colour;
        std::list<boost::signals2::connection> _font_connections;
-       /** Video frame rate that this content has been prepared for, if known */
-       boost::optional<double> _frame_rate;
 };
 
 #endif
index 0ad41114eb6f52e13490ba7c7dbc8777cb604385..c7be4c19b8d1bd4a7b29bf1278079548d7802c03 100644 (file)
@@ -86,6 +86,6 @@ TextSubtitleContent::as_xml (xmlpp::Node* node) const
 DCPTime
 TextSubtitleContent::full_length () const
 {
-       FrameRateChange const frc (subtitle->video_frame_rate(), film()->video_frame_rate ());
+       FrameRateChange const frc (active_video_frame_rate(), film()->video_frame_rate ());
        return DCPTime (_length, frc);
 }
index 0533a12e50fcdb922332f43af8ab4aadafd26419..ff5a4cb17a1a976e1a0106e509da3777c4195309 100644 (file)
 #define LOG_GENERAL(...) film->log()->log (String::compose (__VA_ARGS__), LogEntry::TYPE_GENERAL);
 
 int const VideoContentProperty::SIZE     = 0;
-int const VideoContentProperty::FRAME_RATE  = 1;
-int const VideoContentProperty::FRAME_TYPE  = 2;
-int const VideoContentProperty::CROP     = 3;
-int const VideoContentProperty::SCALE    = 4;
-int const VideoContentProperty::COLOUR_CONVERSION = 5;
-int const VideoContentProperty::FADE_IN     = 6;
-int const VideoContentProperty::FADE_OUT    = 7;
+int const VideoContentProperty::FRAME_TYPE  = 1;
+int const VideoContentProperty::CROP     = 2;
+int const VideoContentProperty::SCALE    = 3;
+int const VideoContentProperty::COLOUR_CONVERSION = 4;
+int const VideoContentProperty::FADE_IN     = 5;
+int const VideoContentProperty::FADE_OUT    = 6;
 
 using std::string;
 using std::setprecision;
@@ -81,7 +80,13 @@ VideoContent::VideoContent (Content* parent, shared_ptr<const Film> film, cxml::
 {
        _size.width = node->number_child<int> ("VideoWidth");
        _size.height = node->number_child<int> ("VideoHeight");
-       _frame_rate = node->optional_number_child<double> ("VideoFrameRate");
+
+       /* Backwards compatibility */
+       optional<double> r = node->optional_number_child<double>("VideoFrameRate");
+       if (r) {
+               _parent->set_video_frame_rate (r.get ());
+       }
+
        _length = node->number_child<Frame> ("VideoLength");
        _frame_type = static_cast<VideoFrameType> (node->number_child<int> ("VideoFrameType"));
        _sample_aspect_ratio = node->optional_number_child<double> ("SampleAspectRatio");
@@ -128,10 +133,6 @@ VideoContent::VideoContent (Content* parent, shared_ptr<const Film> film, vector
                        throw JoinError (_("Content to be joined must have the same picture size."));
                }
 
-               if (c[i]->video->frame_rate() != ref->frame_rate()) {
-                       throw JoinError (_("Content to be joined must have the same video frame rate."));
-               }
-
                if (c[i]->video->frame_type() != ref->frame_type()) {
                        throw JoinError (_("Content to be joined must have the same video frame type."));
                }
@@ -160,7 +161,6 @@ VideoContent::VideoContent (Content* parent, shared_ptr<const Film> film, vector
        }
 
        _size = ref->size ();
-       _frame_rate = ref->frame_rate ();
        _frame_type = ref->frame_type ();
        _crop = ref->crop ();
        _scale = ref->scale ();
@@ -176,9 +176,6 @@ VideoContent::as_xml (xmlpp::Node* node) const
        node->add_child("VideoLength")->add_child_text (raw_convert<string> (_length));
        node->add_child("VideoWidth")->add_child_text (raw_convert<string> (_size.width));
        node->add_child("VideoHeight")->add_child_text (raw_convert<string> (_size.height));
-       if (_frame_rate) {
-               node->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_frame_rate.get()));
-       }
        node->add_child("VideoFrameType")->add_child_text (raw_convert<string> (static_cast<int> (_frame_type)));
        if (_sample_aspect_ratio) {
                node->add_child("SampleAspectRatio")->add_child_text (raw_convert<string> (_sample_aspect_ratio.get ()));
@@ -198,7 +195,6 @@ VideoContent::take_from_examiner (shared_ptr<VideoExaminer> d)
 {
        /* These examiner calls could call other content methods which take a lock on the mutex */
        dcp::Size const vs = d->video_size ();
-       optional<double> const vfr = d->video_frame_rate ();
        Frame vl = d->video_length ();
        optional<double> const ar = d->sample_aspect_ratio ();
        bool const yuv = d->yuv ();
@@ -206,7 +202,6 @@ VideoContent::take_from_examiner (shared_ptr<VideoExaminer> d)
        {
                boost::mutex::scoped_lock lm (_mutex);
                _size = vs;
-               _frame_rate = vfr;
                _length = vl;
                _sample_aspect_ratio = ar;
                _yuv = yuv;
@@ -221,8 +216,11 @@ VideoContent::take_from_examiner (shared_ptr<VideoExaminer> d)
        DCPOMATIC_ASSERT (film);
        LOG_GENERAL ("Video length obtained from header as %1 frames", _length);
 
+       if (d->video_frame_rate()) {
+               _parent->set_video_frame_rate (d->video_frame_rate().get());
+       }
+
        _parent->signal_changed (VideoContentProperty::SIZE);
-       _parent->signal_changed (VideoContentProperty::FRAME_RATE);
        _parent->signal_changed (VideoContentProperty::SCALE);
        _parent->signal_changed (ContentProperty::LENGTH);
 }
@@ -251,11 +249,10 @@ string
 VideoContent::technical_summary () const
 {
        string s = String::compose (
-               N_("video: length %1 frames, size %2x%3, rate %4"),
+               N_("video: length %1 frames, size %2x%3"),
                length_after_3d_combine(),
                size().width,
-               size().height,
-               frame_rate()
+               size().height
                );
 
        if (sample_aspect_ratio ()) {
@@ -325,12 +322,17 @@ VideoContent::fade (Frame f) const
 {
        DCPOMATIC_ASSERT (f >= 0);
 
-       Frame const ts = _parent->trim_start().frames_round(frame_rate());
+       shared_ptr<const Film> film = _film.lock ();
+       DCPOMATIC_ASSERT (film);
+
+       double const vfr = _parent->active_video_frame_rate ();
+
+       Frame const ts = _parent->trim_start().frames_round(vfr);
        if ((f - ts) < fade_in()) {
                return double (f - ts) / fade_in();
        }
 
-       Frame fade_out_start = length() - _parent->trim_end().frames_round(frame_rate()) - fade_out();
+       Frame fade_out_start = length() - _parent->trim_end().frames_round(vfr) - fade_out();
        if (f >= fade_out_start) {
                return 1 - double (f - fade_out_start) / fade_out();
        }
@@ -396,12 +398,6 @@ VideoContent::processing_description () const
                d << " (" << fixed << setprecision(2) << container_size.ratio () << ":1)\n";
        }
 
-       d << _("Content frame rate");
-       d << " " << fixed << setprecision(4) << frame_rate() << "\n";
-
-       FrameRateChange frc (frame_rate(), film->video_frame_rate ());
-       d << frc.description () << "\n";
-
        return d.str ();
 }
 
@@ -410,16 +406,6 @@ VideoContent::add_properties (list<UserProperty>& p) const
 {
        p.push_back (UserProperty (_("Video"), _("Length"), raw_convert<string> (length ()), _("video frames")));
        p.push_back (UserProperty (_("Video"), _("Size"), raw_convert<string> (size().width) + "x" + raw_convert<string> (size().height)));
-       p.push_back (UserProperty (_("Video"), _("Frame rate"), raw_convert<string> (frame_rate(), 5), _("frames per second")));
-}
-
-double
-VideoContent::frame_rate () const
-{
-       boost::mutex::scoped_lock lm (_mutex);
-       shared_ptr<const Film> film = _film.lock ();
-       DCPOMATIC_ASSERT (film);
-       return _frame_rate.get_value_or (film->video_frame_rate ());
 }
 
 void
@@ -458,12 +444,6 @@ VideoContent::set_scale (VideoContentScale s)
        maybe_set (_scale, s, VideoContentProperty::SCALE);
 }
 
-void
-VideoContent::set_frame_rate (double r)
-{
-       maybe_set (_frame_rate, r, VideoContentProperty::FRAME_RATE);
-}
-
 void
 VideoContent::set_frame_type (VideoFrameType t)
 {
index 432775651d8d08944089c34679a846873fa486bb..03ffb0fa83098a45d290313291347d20881fe168 100644 (file)
@@ -39,7 +39,6 @@ class VideoContentProperty
 {
 public:
        static int const SIZE;
-       static int const FRAME_RATE;
        static int const FRAME_TYPE;
        static int const CROP;
        static int const SCALE;
@@ -78,18 +77,7 @@ public:
                return _size;
        }
 
-       double frame_rate () const;
-
-       /** @return true if this content has a specific video frame rate, false
-        *  if it should use the DCP's rate.
-        */
-       bool has_own_frame_rate () const {
-               boost::mutex::scoped_lock lm (_mutex);
-               return static_cast<bool>(_frame_rate);
-       }
-
        void set_frame_type (VideoFrameType);
-       void set_frame_rate (double);
 
        void set_left_crop (int);
        void set_right_crop (int);
@@ -189,8 +177,6 @@ private:
        void setup_default_colour_conversion ();
 
        Frame _length;
-       /** Video frame rate, or not set if this content should use the DCP's frame rate */
-       boost::optional<double> _frame_rate;
        boost::optional<ColourConversion> _colour_conversion;
        dcp::Size _size;
        VideoFrameType _frame_type;
index 08f79c3d8ebfebc951880163cd2f076bd914b06d..8862eaa6e5a8abaa68140260db7c65a728485234 100644 (file)
@@ -34,7 +34,7 @@ using std::back_inserter;
 using boost::shared_ptr;
 using boost::optional;
 
-VideoDecoder::VideoDecoder (shared_ptr<const VideoContent> c, shared_ptr<Log> log)
+VideoDecoder::VideoDecoder (shared_ptr<const Content> c, shared_ptr<Log> log)
 #ifdef DCPOMATIC_DEBUG
        : test_gaps (0)
        , _video_content (c)
@@ -45,7 +45,7 @@ VideoDecoder::VideoDecoder (shared_ptr<const VideoContent> c, shared_ptr<Log> lo
        , _last_seek_accurate (true)
        , _ignore_video (false)
 {
-       _black_image.reset (new Image (AV_PIX_FMT_RGB24, _video_content->size(), true));
+       _black_image.reset (new Image (AV_PIX_FMT_RGB24, _video_content->video->size(), true));
        _black_image->make_black ();
 }
 
@@ -83,7 +83,7 @@ VideoDecoder::get_video (Frame frame, bool accurate)
        _log->log (String::compose ("VD has request for %1", frame), LogEntry::TYPE_DEBUG_DECODE);
 
        if (_decoded_video.empty() || frame < _decoded_video.front().frame || frame > (_decoded_video.back().frame + 1)) {
-               seek (ContentTime::from_frames (frame, _video_content->frame_rate()), accurate);
+               seek (ContentTime::from_frames (frame, _video_content->active_video_frame_rate()), accurate);
        }
 
        list<ContentVideo> dec;
@@ -257,7 +257,7 @@ VideoDecoder::video (shared_ptr<const ImageProxy> image, Frame frame)
 
        /* Work out what we are going to push into _decoded_video next */
        list<ContentVideo> to_push;
-       switch (_video_content->frame_type ()) {
+       switch (_video_content->video->frame_type ()) {
        case VIDEO_FRAME_TYPE_2D:
                to_push.push_back (ContentVideo (image, EYES_BOTH, PART_WHOLE, frame));
                break;
@@ -297,7 +297,7 @@ VideoDecoder::video (shared_ptr<const ImageProxy> image, Frame frame)
        optional<Frame> to;
 
        if (_decoded_video.empty() && _last_seek_time && _last_seek_accurate) {
-               from = _last_seek_time->frames_round (_video_content->frame_rate ());
+               from = _last_seek_time->frames_round (_video_content->active_video_frame_rate ());
                to = to_push.front().frame;
        } else if (!_decoded_video.empty ()) {
                from = _decoded_video.back().frame + 1;
@@ -313,7 +313,7 @@ VideoDecoder::video (shared_ptr<const ImageProxy> image, Frame frame)
        }
 
        if (from) {
-               switch (_video_content->frame_type ()) {
+               switch (_video_content->video->frame_type ()) {
                case VIDEO_FRAME_TYPE_2D:
                        fill_one_eye (from.get(), to.get (), EYES_BOTH);
                        break;
index c787faa0413e4181c8206aa35fad5123e6e54e16..669a5ef1edc0a87b793f3ceb9f81264525348dfb 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2015 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2016 Carl Hetherington <cth@carlh.net>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -42,14 +42,10 @@ class Log;
 class VideoDecoder : public virtual Decoder
 {
 public:
-       VideoDecoder (boost::shared_ptr<const VideoContent> c, boost::shared_ptr<Log> log);
+       VideoDecoder (boost::shared_ptr<const Content> c, boost::shared_ptr<Log> log);
 
        std::list<ContentVideo> get_video (Frame frame, bool accurate);
 
-       boost::shared_ptr<const VideoContent> video_content () const {
-               return _video_content;
-       }
-
        void set_ignore_video ();
 
 #ifdef DCPOMATIC_DEBUG
@@ -59,6 +55,8 @@ public:
 protected:
        friend struct video_decoder_fill_test1;
        friend struct video_decoder_fill_test2;
+       friend struct ffmpeg_pts_offset_test;
+       friend void ffmpeg_decoder_sequential_test_one (boost::filesystem::path file, float fps, int gaps, int video_length);
 
        void seek (ContentTime time, bool accurate);
        void video (boost::shared_ptr<const ImageProxy>, Frame frame);
@@ -66,7 +64,7 @@ protected:
        void fill_one_eye (Frame from, Frame to, Eyes);
        void fill_both_eyes (Frame from, Frame to, Eyes);
 
-       boost::shared_ptr<const VideoContent> _video_content;
+       boost::shared_ptr<const Content> _video_content;
        boost::shared_ptr<Log> _log;
        std::list<ContentVideo> _decoded_video;
        boost::shared_ptr<Image> _black_image;
index 8809a712f6e32f2023a4d5d5ad7d377daf5351c9..4bfd5f50f352738568ea8e3913cd9b7b0fa86259 100644 (file)
@@ -86,7 +86,7 @@ print_dump (shared_ptr<Film> film)
 
                if (c->video) {
                        cout << "\t" << c->video->size().width << "x" << c->video->size().height << "\n"
-                            << "\t" << c->video->frame_rate() << "fps\n"
+                            << "\t" << c->active_video_frame_rate() << "fps\n"
                             << "\tcrop left " << c->video->left_crop()
                             << " right " << c->video->right_crop()
                             << " top " << c->video->top_crop()
index 28d81d07b8a3810a797d744cff3d7ba8733b555a..dad1981f44c9d3cc2927af12fa962ce4e0d6a234 100644 (file)
@@ -170,7 +170,7 @@ AudioPanel::film_content_changed (int property)
                }
 
                setup_sensitivity ();
-       } else if (property == AudioContentProperty::VIDEO_FRAME_RATE) {
+       } else if (property == ContentProperty::VIDEO_FRAME_RATE) {
                setup_description ();
        }
 }
index a591c72b352a43e380e0c78958f0cec393bf1023..2008241892879a5d87f9780b0f656e45309f9d93 100644 (file)
@@ -334,7 +334,7 @@ ContentPanel::add_folder_clicked ()
                        return;
                }
 
-               ic->video->set_frame_rate (frame_rate);
+               ic->set_video_frame_rate (frame_rate);
        }
 
        _film->examine_and_add_content (content);
index 8e253c0709742e31ca042adb6644a1d3655f3ca2..2f909aefdf977fe23e44b75670248f879b51138f 100644 (file)
@@ -210,10 +210,8 @@ TimingPanel::film_content_changed (int property)
 
        } else if (
                property == ContentProperty::LENGTH ||
-               property == VideoContentProperty::FRAME_RATE ||
-               property == VideoContentProperty::FRAME_TYPE ||
-               property == AudioContentProperty::VIDEO_FRAME_RATE ||
-               property == SubtitleContentProperty::VIDEO_FRAME_RATE
+               property == ContentProperty::VIDEO_FRAME_RATE ||
+               property == VideoContentProperty::FRAME_TYPE
                ) {
 
                update_full_length ();
@@ -249,48 +247,38 @@ TimingPanel::film_content_changed (int property)
                property == ContentProperty::LENGTH ||
                property == ContentProperty::TRIM_START ||
                property == ContentProperty::TRIM_END ||
-               property == VideoContentProperty::FRAME_RATE ||
-               property == VideoContentProperty::FRAME_TYPE ||
-               property == AudioContentProperty::VIDEO_FRAME_RATE ||
-               property == SubtitleContentProperty::VIDEO_FRAME_RATE
+               property == ContentProperty::VIDEO_FRAME_RATE ||
+               property == VideoContentProperty::FRAME_TYPE
                ) {
 
                update_play_length ();
        }
 
-       if (property == VideoContentProperty::FRAME_RATE || property == SubtitleContentProperty::VIDEO_FRAME_RATE) {
+       if (property == ContentProperty::VIDEO_FRAME_RATE) {
                set<double> check_vc;
-               shared_ptr<const Content> vc;
+               shared_ptr<const Content> content;
                int count_ac = 0;
-               shared_ptr<const Content> ac;
                int count_sc = 0;
-               shared_ptr<const Content> sc;
                BOOST_FOREACH (shared_ptr<const Content> i, _parent->selected ()) {
-                       if (i->video) {
-                               check_vc.insert (i->video->frame_rate ());
-                               vc = i;
+                       if (i->video && i->video_frame_rate()) {
+                               check_vc.insert (i->video_frame_rate().get());
+                               content = i;
                        }
-                       if (i->audio) {
+                       if (i->audio && i->video_frame_rate()) {
                                ++count_ac;
-                               ac = i;
+                               content = i;
                        }
-                       if (i->subtitle) {
+                       if (i->subtitle && i->video_frame_rate()) {
                                ++count_sc;
-                               sc = i;
+                               content = i;
                        }
 
                }
 
-               bool const single_frame_image_content = vc && dynamic_pointer_cast<const ImageContent> (vc) && vc->number_of_paths() == 1;
+               bool const single_frame_image_content = content && dynamic_pointer_cast<const ImageContent> (content) && content->number_of_paths() == 1;
 
                if ((check_vc.size() == 1 || count_ac == 1 || count_sc == 1) && !single_frame_image_content) {
-                       if (vc) {
-                               checked_set (_video_frame_rate, raw_convert<string> (vc->video->frame_rate (), 5));
-                       } else if (ac) {
-                               checked_set (_video_frame_rate, raw_convert<string> (ac->audio->video_frame_rate (), 5));
-                       } else if (sc) {
-                               checked_set (_video_frame_rate, raw_convert<string> (sc->subtitle->video_frame_rate (), 5));
-                       }
+                       checked_set (_video_frame_rate, raw_convert<string> (content->video_frame_rate().get(), 5));
                        _video_frame_rate->Enable (true);
                } else {
                        checked_set (_video_frame_rate, wxT (""));
@@ -401,22 +389,12 @@ TimingPanel::video_frame_rate_changed ()
 void
 TimingPanel::set_video_frame_rate ()
 {
+       double const fr = raw_convert<double> (wx_to_std (_video_frame_rate->GetValue ()));
        BOOST_FOREACH (shared_ptr<Content> i, _parent->selected ()) {
-               shared_ptr<DCPSubtitleContent> dsc = dynamic_pointer_cast<DCPSubtitleContent> (i);
-               shared_ptr<TextSubtitleContent> tsc = dynamic_pointer_cast<TextSubtitleContent> (i);
-               double const fr = raw_convert<double> (wx_to_std (_video_frame_rate->GetValue ()));
-               if (i->video) {
-                       i->video->set_frame_rate (fr);
-               } else if (i->audio) {
-                       /* Audio but not video, i.e. SndfileContent */
-                       i->audio->set_video_frame_rate (fr);
-               } else if (dsc) {
-                       dsc->subtitle->set_video_frame_rate (fr);
-               } else if (tsc) {
-                       tsc->subtitle->set_video_frame_rate (fr);
-               }
-               _set_video_frame_rate->Enable (false);
+               i->set_video_frame_rate (fr);
        }
+
+       _set_video_frame_rate->Enable (false);
 }
 
 void
@@ -428,9 +406,7 @@ TimingPanel::content_selection_changed ()
        film_content_changed (ContentProperty::LENGTH);
        film_content_changed (ContentProperty::TRIM_START);
        film_content_changed (ContentProperty::TRIM_END);
-       film_content_changed (VideoContentProperty::FRAME_RATE);
-       film_content_changed (SubtitleContentProperty::VIDEO_FRAME_RATE);
-       film_content_changed (AudioContentProperty::VIDEO_FRAME_RATE);
+       film_content_changed (ContentProperty::VIDEO_FRAME_RATE);
 }
 
 void
index 28a26ce087612ab95db476cf11e52e4f3e25c067..a8a1d98c8e97f17e5994df4ec6cee21436a5bbec 100644 (file)
@@ -273,13 +273,10 @@ VideoPanel::film_content_changed (int property)
                fcs = dynamic_pointer_cast<FFmpegContent> (vcs);
        }
 
-       if (property == VideoContentProperty::FRAME_TYPE) {
-               setup_description ();
-       } else if (property == VideoContentProperty::CROP) {
-               setup_description ();
-       } else if (property == VideoContentProperty::SCALE) {
-               setup_description ();
-       } else if (property == VideoContentProperty::FRAME_RATE) {
+       if (property == ContentProperty::VIDEO_FRAME_RATE ||
+           property == VideoContentProperty::FRAME_TYPE ||
+           property == VideoContentProperty::CROP ||
+           property == VideoContentProperty::SCALE) {
                setup_description ();
        } else if (property == VideoContentProperty::COLOUR_CONVERSION) {
                if (vcs && vcs->video->colour_conversion ()) {
@@ -316,8 +313,8 @@ VideoPanel::film_content_changed (int property)
 
                if (check.size() == 1) {
                        _fade_in->set (
-                               ContentTime::from_frames (vc.front()->video->fade_in (), vc.front()->video->frame_rate ()),
-                               vc.front()->video->frame_rate ()
+                               ContentTime::from_frames (vc.front()->video->fade_in (), vc.front()->active_video_frame_rate ()),
+                               vc.front()->active_video_frame_rate ()
                                );
                } else {
                        _fade_in->clear ();
@@ -330,8 +327,8 @@ VideoPanel::film_content_changed (int property)
 
                if (check.size() == 1) {
                        _fade_out->set (
-                               ContentTime::from_frames (vc.front()->video->fade_out (), vc.front()->video->frame_rate ()),
-                               vc.front()->video->frame_rate ()
+                               ContentTime::from_frames (vc.front()->video->fade_out (), vc.front()->active_video_frame_rate ()),
+                               vc.front()->active_video_frame_rate ()
                                );
                } else {
                        _fade_out->clear ();
@@ -433,8 +430,8 @@ VideoPanel::content_selection_changed ()
        _bottom_crop->set_content (video_sel);
        _scale->set_content (video_sel);
 
+       film_content_changed (ContentProperty::VIDEO_FRAME_RATE);
        film_content_changed (VideoContentProperty::CROP);
-       film_content_changed (VideoContentProperty::FRAME_RATE);
        film_content_changed (VideoContentProperty::COLOUR_CONVERSION);
        film_content_changed (VideoContentProperty::FADE_IN);
        film_content_changed (VideoContentProperty::FADE_OUT);
index 9cd123890c26936debf8e6cd54d670669275fe74..ac3064aa04b9e9610af8ce3bfddc60dac832d015 100644 (file)
@@ -37,8 +37,8 @@ using std::list;
 using boost::shared_ptr;
 using boost::optional;
 
-static void
-test (boost::filesystem::path file, float fps, int gaps, int video_length)
+void
+ffmpeg_decoder_sequential_test_one (boost::filesystem::path file, float fps, int gaps, int video_length)
 {
        boost::filesystem::path path = private_data / file;
        if (!boost::filesystem::exists (path)) {
@@ -53,7 +53,8 @@ test (boost::filesystem::path file, float fps, int gaps, int video_length)
        shared_ptr<Log> log (new NullLog);
        shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (content, log, false));
 
-       BOOST_CHECK_CLOSE (decoder->video_content()->frame_rate(), fps, 0.01);
+       BOOST_REQUIRE (decoder->_video_content->video_frame_rate());
+       BOOST_CHECK_CLOSE (decoder->_video_content->video_frame_rate().get(), fps, 0.01);
 
 #ifdef DCPOMATIC_DEBUG
        decoder->test_gaps = 0;
@@ -71,10 +72,10 @@ test (boost::filesystem::path file, float fps, int gaps, int video_length)
 
 BOOST_AUTO_TEST_CASE (ffmpeg_decoder_sequential_test)
 {
-       test ("boon_telly.mkv", 29.97, 0, 6910);
-       test ("Sintel_Trailer1.480p.DivX_Plus_HD.mkv", 24, 0, 1248);
+       ffmpeg_decoder_sequential_test_one ("boon_telly.mkv", 29.97, 0, 6910);
+       ffmpeg_decoder_sequential_test_one ("Sintel_Trailer1.480p.DivX_Plus_HD.mkv", 24, 0, 1248);
        /* The first video frame is 12 here, so VideoDecoder should see 12 gaps
           (at the start of the file)
        */
-       test ("prophet_clip.mkv", 23.976, 12, 2875);
+       ffmpeg_decoder_sequential_test_one ("prophet_clip.mkv", 23.976, 12, 2875);
 }
index 5b1821daeb173bfe52dbf167185ec209256818ad..db9e751d5523e51b53bc68c31989fad0fc9a024e 100644 (file)
@@ -36,7 +36,7 @@ BOOST_AUTO_TEST_CASE (ffmpeg_pts_offset_test)
        shared_ptr<Film> film = new_test_film ("ffmpeg_pts_offset_test");
        shared_ptr<FFmpegContent> content (new FFmpegContent (film, "test/data/test.mp4"));
        content->audio->add_stream (shared_ptr<FFmpegAudioStream> (new FFmpegAudioStream));
-       content->video->_frame_rate = 24;
+       content->_video_frame_rate = 24;
 
        {
                /* Sound == video so no offset required */
index 35cd5523a3329e5f3c24b7244835f97815e7cee5..9c2e9ec3fc490ace0ffeacae190f7fe1f06b049c 100644 (file)
@@ -54,7 +54,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        afr.push_back (30);
        Config::instance()->set_allowed_dcp_frame_rates (afr);
 
-       content->video->_frame_rate = 60;
+       content->_video_frame_rate = 60;
        int best = film->best_video_frame_rate ();
        FrameRateChange frc = FrameRateChange (60, best);
        BOOST_CHECK_EQUAL (best, 30);
@@ -63,7 +63,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 50;
+       content->_video_frame_rate = 50;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (50, best);
        BOOST_CHECK_EQUAL (best, 25);
@@ -72,7 +72,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 48;
+       content->_video_frame_rate = 48;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (48, best);
        BOOST_CHECK_EQUAL (best, 24);
@@ -81,7 +81,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 30;
+       content->_video_frame_rate = 30;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (30, best);
        BOOST_CHECK_EQUAL (best, 30);
@@ -90,7 +90,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 29.97;
+       content->_video_frame_rate = 29.97;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (29.97, best);
        BOOST_CHECK_EQUAL (best, 30);
@@ -99,7 +99,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, true);
        BOOST_CHECK_CLOSE (frc.speed_up, 30 / 29.97, 0.1);
 
-       content->video->_frame_rate = 25;
+       content->_video_frame_rate = 25;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (25, best);
        BOOST_CHECK_EQUAL (best, 25);
@@ -108,7 +108,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 24;
+       content->_video_frame_rate = 24;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (24, best);
        BOOST_CHECK_EQUAL (best, 24);
@@ -117,7 +117,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 14.5;
+       content->_video_frame_rate = 14.5;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (14.5, best);
        BOOST_CHECK_EQUAL (best, 30);
@@ -126,7 +126,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, true);
        BOOST_CHECK_CLOSE (frc.speed_up, 15 / 14.5, 0.1);
 
-       content->video->_frame_rate = 12.6;
+       content->_video_frame_rate = 12.6;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (12.6, best);
        BOOST_CHECK_EQUAL (best, 25);
@@ -135,7 +135,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, true);
        BOOST_CHECK_CLOSE (frc.speed_up, 25 / 25.2, 0.1);
 
-       content->video->_frame_rate = 12.4;
+       content->_video_frame_rate = 12.4;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (12.4, best);
        BOOST_CHECK_EQUAL (best, 25);
@@ -144,7 +144,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, true);
        BOOST_CHECK_CLOSE (frc.speed_up, 25 / 24.8, 0.1);
 
-       content->video->_frame_rate = 12;
+       content->_video_frame_rate = 12;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (12, best);
        BOOST_CHECK_EQUAL (best, 24);
@@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        afr.push_back (60);
        Config::instance()->set_allowed_dcp_frame_rates (afr);
 
-       content->video->_frame_rate = 60;
+       content->_video_frame_rate = 60;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (60, best);
        BOOST_CHECK_EQUAL (best, 60);
@@ -171,7 +171,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 50;
+       content->_video_frame_rate = 50;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (50, best);
        BOOST_CHECK_EQUAL (best, 50);
@@ -180,7 +180,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        BOOST_CHECK_EQUAL (frc.change_speed, false);
        BOOST_CHECK_CLOSE (frc.speed_up, 1, 0.1);
 
-       content->video->_frame_rate = 48;
+       content->_video_frame_rate = 48;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (48, best);
        BOOST_CHECK_EQUAL (best, 48);
@@ -203,7 +203,7 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_single)
        afr.push_back (24);
        Config::instance()->set_allowed_dcp_frame_rates (afr);
 
-       content->video->_frame_rate = 25;
+       content->_video_frame_rate = 25;
        best = film->best_video_frame_rate ();
        frc = FrameRateChange (25, best);
        BOOST_CHECK_EQUAL (best, 24);
@@ -234,16 +234,16 @@ BOOST_AUTO_TEST_CASE (best_dcp_frame_rate_test_double)
        afr.push_back (30);
        Config::instance()->set_allowed_dcp_frame_rates (afr);
 
-       A->video->_frame_rate = 30;
-       B->video->_frame_rate = 24;
+       A->_video_frame_rate = 30;
+       B->_video_frame_rate = 24;
        BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 25);
 
-       A->video->_frame_rate = 24;
-       B->video->_frame_rate = 24;
+       A->_video_frame_rate = 24;
+       B->_video_frame_rate = 24;
        BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 24);
 
-       A->video->_frame_rate = 24;
-       B->video->_frame_rate = 48;
+       A->_video_frame_rate = 24;
+       B->_video_frame_rate = 48;
        BOOST_CHECK_EQUAL (film->best_video_frame_rate(), 24);
 }
 
@@ -263,7 +263,7 @@ BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
 
        shared_ptr<FFmpegAudioStream> stream (new FFmpegAudioStream ("foo", 0, 0, 0));
        content->audio->add_stream (stream);
-       content->video->_frame_rate = 24;
+       content->_video_frame_rate = 24;
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(), 48000);
@@ -274,30 +274,30 @@ BOOST_AUTO_TEST_CASE (audio_sampling_rate_test)
        stream->_frame_rate = 80000;
        BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(), 96000);
 
-       content->video->_frame_rate = 23.976;
+       content->_video_frame_rate = 23.976;
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(), 47952);
 
-       content->video->_frame_rate = 29.97;
+       content->_video_frame_rate = 29.97;
        film->set_video_frame_rate (30);
        BOOST_CHECK_EQUAL (film->video_frame_rate (), 30);
        stream->_frame_rate = 48000;
        BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(), 47952);
 
-       content->video->_frame_rate = 25;
+       content->_video_frame_rate = 25;
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(), 50000);
 
-       content->video->_frame_rate = 25;
+       content->_video_frame_rate = 25;
        film->set_video_frame_rate (24);
        stream->_frame_rate = 44100;
        BOOST_CHECK_EQUAL (content->audio->resampled_frame_rate(), 50000);
 
        /* Check some out-there conversions (not the best) */
 
-       content->video->_frame_rate = 14.99;
+       content->_video_frame_rate = 14.99;
        film->set_video_frame_rate (25);
        stream->_frame_rate = 16000;
        /* The FrameRateChange within resampled_frame_rate should choose to double-up
index f05920c26718f74cd490d0132e13890658f4f78d..332c39db9f2093e24766409dd4ed2143c0a06d21 100644 (file)
@@ -58,7 +58,7 @@ BOOST_AUTO_TEST_CASE (seek_zero_test)
                video_delay = ContentTime ();
        }
 
-       Frame const first_frame = video_delay.round_up (content->video->frame_rate ()).frames_round (content->video->frame_rate ());
+       Frame const first_frame = video_delay.round_up (content->active_video_frame_rate ()).frames_round (content->active_video_frame_rate ());
 
        FFmpegDecoder decoder (content, film->log(), false);
        list<ContentVideo> a = decoder.get_video (first_frame, true);
index 7f13e6c0e64320f1dc7214153b90e063a1a7a855..5e5c6211b6f3582477ba9eae4b9c6e26e6d97760 100644 (file)
@@ -162,7 +162,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 0, no trim, content rate = DCP rate */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -174,7 +174,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 3s, no trim, content rate = DCP rate */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -188,7 +188,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 3s, 1.5s trim, content rate = DCP rate */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -205,7 +205,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -217,7 +217,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 3s, no trim, content rate 24, DCP rate 25 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -233,7 +233,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
         */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.6));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -252,7 +252,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -264,7 +264,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 3s, no trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -278,7 +278,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -296,7 +296,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (48);
+       content->set_video_frame_rate (48);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -308,7 +308,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 3s, no trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (48);
+       content->set_video_frame_rate (48);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -322,7 +322,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (48);
+       content->set_video_frame_rate (48);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -336,7 +336,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test1)
        /* Position 0s, no trim, content rate 29.9978733, DCP rate 30 */
        content->set_position (DCPTime::from_seconds (0));
        content->set_trim_start (ContentTime::from_seconds (0));
-       content->video->set_frame_rate (29.9978733);
+       content->set_video_frame_rate (29.9978733);
        film->set_video_frame_rate (30);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -367,7 +367,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 0, no trim, content rate = DCP rate */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -379,7 +379,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, no trim, content rate = DCP rate */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -391,7 +391,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, 1.5s trim, content rate = DCP rate */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -407,7 +407,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -419,7 +419,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, no trim, content rate 24, DCP rate 25 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -431,7 +431,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, 1.6s trim, content rate 24, DCP rate 25, so the 1.6s trim is at 24fps */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.6));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -449,7 +449,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -461,7 +461,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, no trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -473,7 +473,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -490,7 +490,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (48);
+       content->set_video_frame_rate (48);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -502,7 +502,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, no trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (48);
+       content->set_video_frame_rate (48);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -514,7 +514,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test2)
        /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (48);
+       content->set_video_frame_rate (48);
        film->set_video_frame_rate (24);
        player->setup_pieces ();
        BOOST_REQUIRE_EQUAL (player->_pieces.size(), 1);
@@ -544,7 +544,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 0, no trim, video/audio content rate = video/audio DCP rate */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -557,7 +557,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, no trim, video/audio content rate = video/audio DCP rate */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -572,7 +572,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, 1.5s trim, video/audio content rate = video/audio DCP rate */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -587,7 +587,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 0, no trim, content video rate 24, DCP video rate 25, both audio rates still 48k */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -600,7 +600,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, no trim, content video rate 24, DCP rate 25, both audio rates still 48k. */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -617,7 +617,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.6));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (25);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -636,7 +636,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -649,7 +649,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, no trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -664,7 +664,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -682,7 +682,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (48);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -695,7 +695,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, no trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -710,7 +710,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, 1.5s trim, content rate 24, DCP rate 48 */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();
@@ -725,7 +725,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 0, no trim, video content rate = video DCP rate, content audio rate = 44.1k */
        content->set_position (DCPTime ());
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 44100;
        player->setup_pieces ();
@@ -738,7 +738,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, no trim, video content rate = video DCP rate, content audio rate = 44.1k */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime ());
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 44100;
        player->setup_pieces ();
@@ -753,7 +753,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Position 3s, 1.5s trim, video content rate = video DCP rate, content audio rate = 44.1k */
        content->set_position (DCPTime::from_seconds (3));
        content->set_trim_start (ContentTime::from_seconds (1.5));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 44100;
        player->setup_pieces ();
@@ -768,7 +768,7 @@ BOOST_AUTO_TEST_CASE (player_time_calculation_test3)
        /* Check with a large start trim */
        content->set_position (DCPTime::from_seconds (0));
        content->set_trim_start (ContentTime::from_seconds (54143));
-       content->video->set_frame_rate (24);
+       content->set_video_frame_rate (24);
        film->set_video_frame_rate (24);
        stream->_frame_rate = 48000;
        player->setup_pieces ();