Untested use of Frame for video/audio content lengths.
authorCarl Hetherington <cth@carlh.net>
Wed, 27 May 2015 01:09:22 +0000 (02:09 +0100)
committerCarl Hetherington <cth@carlh.net>
Wed, 27 May 2015 01:09:22 +0000 (02:09 +0100)
35 files changed:
doc/design/resampling.tex
src/lib/audio_content.cc
src/lib/audio_content.h
src/lib/audio_examiner.h
src/lib/config.h
src/lib/dcp_content.cc
src/lib/dcp_examiner.cc
src/lib/dcp_examiner.h
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_content.h
src/lib/ffmpeg_examiner.cc
src/lib/ffmpeg_examiner.h
src/lib/image_content.cc
src/lib/image_content.h
src/lib/image_decoder.cc
src/lib/image_examiner.cc
src/lib/image_examiner.h
src/lib/single_stream_audio_content.cc
src/lib/single_stream_audio_content.h
src/lib/sndfile_content.cc
src/lib/sndfile_decoder.cc
src/lib/sndfile_decoder.h
src/lib/video_content.cc
src/lib/video_content.h
src/lib/video_examiner.h
src/tools/dcpomatic_create.cc
src/wx/content_properties_dialog.cc
src/wx/timing_panel.cc
src/wx/video_panel.cc
src/wx/video_panel.h
test/audio_decoder_test.cc
test/black_fill_test.cc
test/ffmpeg_decoder_sequential_test.cc
test/scaling_test.cc
test/wscript

index cf9cfb1edc220bcdfa6f242b4aeee94427c2a0d5..cb7388eb89937a4589c134f0c8a5cbade1e0d285 100644 (file)
@@ -53,4 +53,11 @@ and $C_A$, resample the audio to $R_A$ where
 R_A &= \frac{C_V F_A}{F_V}
 \end{align*}
 
+Once this is done, consider 1 second's worth of content samples ($C_A$
+samples).  We have turned them into $R_A$ samples which should still
+last 1 second.  These samples are then played back at $F_A$ samples
+per second, so they last $R_A / F_A$ seconds.  Hence there is a
+scaling between some content time and some DCP time of $R_A / F_A$
+i.e. $C_V / F_V$.
+
 \end{document}
index 53160fdb0949b786cb99c2fdf8078cf8dd802839..def123fb11489870cb5090a698350a0c2bf3c241 100644 (file)
@@ -188,9 +188,9 @@ string
 AudioContent::technical_summary () const
 {
        return String::compose (
-               "audio: channels %1, length %2, content rate %3, resampled rate %4",
+               "audio: channels %1, length %2 frames, content rate %3, resampled rate %4",
                audio_channels(),
-               audio_length().seconds(),
+               audio_length(),
                audio_frame_rate(),
                resampled_audio_frame_rate()
                );
index f4a537b300258339773bf5f70d54e05786665233..cb14c70cb4020058f8ec240e4d50a482158255dc 100644 (file)
@@ -68,7 +68,7 @@ public:
        /** @return number of audio channels in the content */
        virtual int audio_channels () const = 0;
        /** @return the length of the audio in the content */
-       virtual ContentTime audio_length () const = 0;
+       virtual Frame audio_length () const = 0;
        /** @return the frame rate of the content */
        virtual int audio_frame_rate () const = 0;
        virtual AudioMapping audio_mapping () const = 0;
index d6d4dbe9778607dd8448c34893d2c811775354b6..a5f05598483a26a49d19c91a1db332e5a5c72bcb 100644 (file)
@@ -30,6 +30,6 @@ public:
        virtual ~AudioExaminer () {}
 
        virtual int audio_channels () const = 0;
-       virtual ContentTime audio_length () const = 0;
+       virtual Frame audio_length () const = 0;
        virtual int audio_frame_rate () const = 0;
 };
index b39e7af3ac028c8b1bdd1b418eceaddfccd8e7a0..20529911b605ba363b4117454c9759a773a5dade 100644 (file)
@@ -449,6 +449,7 @@ private:
        /** Default ISDCF metadata for newly-created Films */
        ISDCFMetadata _default_isdcf_metadata;
        boost::optional<std::string> _language;
+       /** Default length of still image content (seconds) */
        int _default_still_length;
        Ratio const * _default_container;
        DCPContentType const * _default_dcp_content_type;
index 51c7f8549ba504fe75a090509893317da526ca9d..0c89685313337b69e1584df648240bd0c7c3d71f 100644 (file)
@@ -141,7 +141,8 @@ DCPContent::full_length () const
 {
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
-       return DCPTime (video_length (), FrameRateChange (video_frame_rate (), film->video_frame_rate ()));
+       FrameRateChange const frc (video_frame_rate (), film->video_frame_rate ());
+       return DCPTime::from_frames (rint (video_length () * frc.factor ()), film->video_frame_rate ());
 }
 
 string
index 9dbac14d0240bda279a826d25e4ef20bb82c5c64..a0d13a7224bb42d090d0f26922f0ee8f99ef50f7 100644 (file)
@@ -81,7 +81,7 @@ DCPExaminer::DCPExaminer (shared_ptr<const DCPContent> content)
                                throw DCPError (_("Mismatched video sizes in DCP"));
                        }
 
-                       _video_length += ContentTime::from_frames ((*i)->main_picture()->duration(), _video_frame_rate.get ());
+                       _video_length += (*i)->main_picture()->duration();
                }
                        
                if ((*i)->main_sound ()) {
@@ -99,7 +99,7 @@ DCPExaminer::DCPExaminer (shared_ptr<const DCPContent> content)
                                throw DCPError (_("Mismatched audio frame rates in DCP"));
                        }
 
-                       _audio_length += ContentTime::from_frames ((*i)->main_sound()->duration(), _video_frame_rate.get ());
+                       _audio_length += (*i)->main_sound()->duration();
                }
 
                if ((*i)->main_subtitle ()) {
index 26957b3e45b2ba31a1edc2e9ca5a82c2141cc445..bf083e8ec68ce0844cdfe7c06f27aa162ae565e7 100644 (file)
@@ -39,7 +39,7 @@ public:
                return _video_size.get_value_or (dcp::Size (1998, 1080));
        }
        
-       ContentTime video_length () const {
+       Frame video_length () const {
                return _video_length;
        }
 
@@ -59,7 +59,7 @@ public:
                return _audio_channels.get_value_or (0);
        }
        
-       ContentTime audio_length () const {
+       Frame audio_length () const {
                return _audio_length;
        }
        
@@ -74,10 +74,10 @@ public:
 private:
        boost::optional<float> _video_frame_rate;
        boost::optional<dcp::Size> _video_size;
-       ContentTime _video_length;
+       Frame _video_length;
        boost::optional<int> _audio_channels;
        boost::optional<int> _audio_frame_rate;
-       ContentTime _audio_length;
+       Frame _audio_length;
        std::string _name;
        bool _has_subtitles;
        bool _encrypted;
index 187d61953d34f1e5c1472a8d468f29206187d87f..9acc883fd0c306ebb01db70206b3693940e54f6a 100644 (file)
@@ -249,14 +249,18 @@ FFmpegContent::set_audio_stream (shared_ptr<FFmpegAudioStream> s)
        signal_changed (FFmpegContentProperty::AUDIO_STREAM);
 }
 
-ContentTime
+Frame
 FFmpegContent::audio_length () const
 {
        if (!audio_stream ()) {
-               return ContentTime ();
+               return 0;
        }
 
-       return video_length ();
+       /* We're talking about the content's audio length here, at the content's frame
+          rate.  We assume it's the same as the video's length, and we can just convert
+          using the content's rates.
+       */
+       return (video_length () / video_frame_rate ()) * audio_frame_rate ();
 }
 
 int
@@ -300,7 +304,8 @@ FFmpegContent::full_length () const
 {
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
-       return DCPTime (video_length_after_3d_combine(), FrameRateChange (video_frame_rate (), film->video_frame_rate ()));
+       FrameRateChange const frc (video_frame_rate (), film->video_frame_rate ());
+       return DCPTime::from_frames (rint (video_length_after_3d_combine() * frc.factor()), film->video_frame_rate());
 }
 
 AudioMapping
index bc1872ac160b380dc20c1509571da635fb5308a7..cff5eaed83ebe022707b0c8861b9203ae027d4cc 100644 (file)
@@ -69,7 +69,7 @@ public:
        
        /* AudioContent */
        int audio_channels () const;
-       ContentTime audio_length () const;
+       Frame audio_length () const;
        int audio_frame_rate () const;
        AudioMapping audio_mapping () const;
        void set_audio_mapping (AudioMapping);
index 8afd4c164a85a54c1fc8dd11e147bc49cd407334..eea99e1e8afdfcf9998e56acf4c7f15a8d3c8d9a 100644 (file)
@@ -70,7 +70,7 @@ FFmpegExaminer::FFmpegExaminer (shared_ptr<const FFmpegContent> c, shared_ptr<Jo
        /* See if the header has duration information in it */
        _need_video_length = _format_context->duration == AV_NOPTS_VALUE;
        if (!_need_video_length) {
-               _video_length = ContentTime::from_seconds (double (_format_context->duration) / AV_TIME_BASE);
+               _video_length = (double (_format_context->duration) / AV_TIME_BASE) * video_frame_rate().get ();
        } else if (job) {
                job->sub (_("Finding length"));
                job->set_progress_unknown ();
@@ -126,7 +126,9 @@ FFmpegExaminer::video_packet (AVCodecContext* context)
                        _first_video = frame_time (_format_context->streams[_video_stream]);
                }
                if (_need_video_length) {
-                       _video_length = frame_time (_format_context->streams[_video_stream]).get_value_or (ContentTime ());
+                       _video_length = frame_time (
+                               _format_context->streams[_video_stream]
+                               ).get_value_or (ContentTime ()).frames (video_frame_rate().get ());
                }
        }
 }
@@ -195,11 +197,10 @@ FFmpegExaminer::video_size () const
 }
 
 /** @return Length according to our content's header */
-ContentTime
+Frame
 FFmpegExaminer::video_length () const
 {
-       ContentTime const length = ContentTime::from_seconds (double (_format_context->duration) / AV_TIME_BASE);
-       return ContentTime (max (ContentTime (1), _video_length));
+       return max (Frame (1), _video_length);
 }
 
 optional<float>
index 34d4b1e0d341304f4f9ff903f7debcc958421a40..d6149446ae0984e26719b542d1d4fba66890edec 100644 (file)
@@ -31,7 +31,7 @@ public:
        
        boost::optional<float> video_frame_rate () const;
        dcp::Size video_size () const;
-       ContentTime video_length () const;
+       Frame video_length () const;
        boost::optional<float> sample_aspect_ratio () const;
 
        std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
@@ -62,7 +62,7 @@ private:
        /** Video length, either obtained from the header or derived by running
         *  through the whole file.
         */
-       ContentTime _video_length;
+       Frame _video_length;
        bool _need_video_length;
 
        boost::optional<ContentTime> _last_subtitle_start;
index 54ac56eaef17112276554b6ce22a7c1efe35171d..c0004e59c826a0aff22749064c230d180b57184c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2015 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
@@ -126,7 +126,7 @@ ImageContent::examine (shared_ptr<Job> job)
 }
 
 void
-ImageContent::set_video_length (ContentTime len)
+ImageContent::set_video_length (Frame len)
 {
        {
                boost::mutex::scoped_lock lm (_mutex);
@@ -141,7 +141,8 @@ ImageContent::full_length () const
 {
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
-       return DCPTime (video_length_after_3d_combine(), FrameRateChange (video_frame_rate(), film->video_frame_rate()));
+       FrameRateChange const frc (video_frame_rate(), film->video_frame_rate());
+       return DCPTime::from_frames (rint (video_length_after_3d_combine() * frc.factor ()), film->video_frame_rate ());
 }
 
 string
@@ -149,7 +150,7 @@ ImageContent::identifier () const
 {
        SafeStringStream s;
        s << VideoContent::identifier ();
-       s << "_" << video_length().get();
+       s << "_" << video_length();
        return s.str ();
 }
 
index 83a02a166ecd621f7a09bb1560b8f4394cae6fe4..11c932153adba433c64174ba6fc14ec97908f069 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2015 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
@@ -48,7 +48,7 @@ public:
        /* VideoContent */
        void set_default_colour_conversion ();
        
-       void set_video_length (ContentTime);
+       void set_video_length (Frame);
        bool still () const;
        void set_video_frame_rate (float);
 };
index 250c8f845b6c2f10141aac2c3c46dd2e7fe55dbd..10eee2f6d40c049dbb7d0bcf2d03470f019e937d 100644 (file)
@@ -45,7 +45,7 @@ ImageDecoder::ImageDecoder (shared_ptr<const ImageContent> c)
 bool
 ImageDecoder::pass (PassReason)
 {
-       if (_video_position >= _image_content->video_length().frames (_image_content->video_frame_rate ())) {
+       if (_video_position >= _image_content->video_length()) {
                return true;
        }
 
index 1fd9cd554a6880140ef0caa0bcab081a93f56ff4..502e8adbe909da9dbeac4240d395b1dca020bdec 100644 (file)
@@ -68,11 +68,9 @@ ImageExaminer::ImageExaminer (shared_ptr<const Film> film, shared_ptr<const Imag
        }
 
        if (content->still ()) {
-               _video_length = ContentTime::from_seconds (Config::instance()->default_still_length());
+               _video_length = Config::instance()->default_still_length() * video_frame_rate().get_value_or (24);
        } else {
-               _video_length = ContentTime::from_frames (
-                       _image_content->number_of_paths (), video_frame_rate().get_value_or (24)
-                       );
+               _video_length = _image_content->number_of_paths ();
        }
 }
 
index 1917a23f399da90a47763d56b174c0008abf5586..937a565f33bc75eb36049d42ee2695f1e2a684be 100644 (file)
@@ -32,7 +32,7 @@ public:
 
        boost::optional<float> video_frame_rate () const;
        dcp::Size video_size () const;
-       ContentTime video_length () const {
+       Frame video_length () const {
                return _video_length;
        }
 
@@ -40,5 +40,5 @@ private:
        boost::weak_ptr<const Film> _film;
        boost::shared_ptr<const ImageContent> _image_content;
        boost::optional<dcp::Size> _video_size;
-       ContentTime _video_length;
+       Frame _video_length;
 };
index 4547ae6001da608176286475bc401f7b3e84f1c9..b470d1a995427d492e5062e33a191e78cb8694b1 100644 (file)
@@ -52,7 +52,7 @@ SingleStreamAudioContent::SingleStreamAudioContent (shared_ptr<const Film> f, cx
        , _audio_mapping (node->node_child ("AudioMapping"), version)
 {
        _audio_channels = node->number_child<int> ("AudioChannels");
-       _audio_length = ContentTime (node->number_child<ContentTime::Type> ("AudioLength"));
+       _audio_length = node->number_child<Frame> ("AudioLength");
        _audio_frame_rate = node->number_child<int> ("AudioFrameRate");
 }
 
@@ -73,7 +73,7 @@ SingleStreamAudioContent::as_xml (xmlpp::Node* node) const
 {
        AudioContent::as_xml (node);
        node->add_child("AudioChannels")->add_child_text (raw_convert<string> (audio_channels ()));
-       node->add_child("AudioLength")->add_child_text (raw_convert<string> (audio_length().get ()));
+       node->add_child("AudioLength")->add_child_text (raw_convert<string> (audio_length ()));
        node->add_child("AudioFrameRate")->add_child_text (raw_convert<string> (audio_frame_rate ()));
        _audio_mapping.as_xml (node->add_child("AudioMapping"));
 }
index fcfaf14ca1b211edf805d279b88744fd99b97488..d1d512d6765b33665ca2fe22db0f0fd1e1f40663 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2014-2015 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
@@ -45,7 +45,7 @@ public:
                return _audio_channels;
        }
        
-       ContentTime audio_length () const {
+       Frame audio_length () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _audio_length;
        }
@@ -66,7 +66,7 @@ public:
 
 protected:
        int _audio_channels;
-       ContentTime _audio_length;
+       Frame _audio_length;
        int _audio_frame_rate;
        AudioMapping _audio_mapping;
 };
index 9f9ea351e2a94e0f93a35d99c5075bf22c171b01..363c11b094dae6f0b7de869f32984229d21ad383 100644 (file)
@@ -93,6 +93,7 @@ SndfileContent::full_length () const
 {
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
-       return DCPTime (audio_length(), film->active_frame_rate_change (position ()));
+       FrameRateChange const frc = film->active_frame_rate_change (position ());
+       return DCPTime::from_frames (audio_length() / frc.speed_up, film->audio_frame_rate ());
 }
 
index 09059a8b0717adbf2b8df12b11c6ec48a941477b..ecd1a7e16d46d74ba49e84c2a22482e24839b38c 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 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
@@ -116,10 +116,10 @@ SndfileDecoder::audio_channels () const
        return _info.channels;
 }
 
-ContentTime
+Frame
 SndfileDecoder::audio_length () const
 {
-       return ContentTime::from_frames (_info.frames, audio_frame_rate ());
+       return _info.frames;
 }
 
 int
index 68c8633a0d604df5e7e6aa3f19dfc07993422d2e..932394626407df4d18292344da435bb4ba36fc8a 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2013 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 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
@@ -31,7 +31,7 @@ public:
        ~SndfileDecoder ();
 
        int audio_channels () const;
-       ContentTime audio_length () const;
+       Frame audio_length () const;
        int audio_frame_rate () const;
 
 private:
index db9a2a5e8a6cfb6a39985e43e36e2416decb70ea..0397647ef78e853df1a7bc34d9b634c38cfccf58 100644 (file)
@@ -70,7 +70,7 @@ VideoContent::VideoContent (shared_ptr<const Film> f)
        set_default_colour_conversion ();
 }
 
-VideoContent::VideoContent (shared_ptr<const Film> f, DCPTime s, ContentTime len)
+VideoContent::VideoContent (shared_ptr<const Film> f, DCPTime s, Frame len)
        : Content (f, s)
        , _video_length (len)
        , _video_frame_rate (0)
@@ -96,14 +96,7 @@ VideoContent::VideoContent (shared_ptr<const Film> f, cxml::ConstNodePtr node, i
        _video_size.width = node->number_child<int> ("VideoWidth");
        _video_size.height = node->number_child<int> ("VideoHeight");
        _video_frame_rate = node->number_child<float> ("VideoFrameRate");
-
-       if (version < 32) {
-               /* DCP-o-matic 1.0 branch */
-               _video_length = ContentTime::from_frames (node->number_child<int64_t> ("VideoLength"), _video_frame_rate);
-       } else {
-               _video_length = ContentTime (node->number_child<ContentTime::Type> ("VideoLength"));
-       }
-       
+       _video_length = node->number_child<Frame> ("VideoLength");
        _video_frame_type = static_cast<VideoFrameType> (node->number_child<int> ("VideoFrameType"));
        _sample_aspect_ratio = node->optional_number_child<float> ("SampleAspectRatio");
        _crop.left = node->number_child<int> ("LeftCrop");
@@ -125,8 +118,8 @@ VideoContent::VideoContent (shared_ptr<const Film> f, cxml::ConstNodePtr node, i
                _colour_conversion = ColourConversion (node->node_child ("ColourConversion"), version);
        }
        if (version >= 32) {
-               _fade_in = ContentTime (node->number_child<int64_t> ("FadeIn"));
-               _fade_out = ContentTime (node->number_child<int64_t> ("FadeOut"));
+               _fade_in = node->number_child<Frame> ("FadeIn");
+               _fade_out = node->number_child<Frame> ("FadeOut");
        }
 }
 
@@ -185,7 +178,7 @@ void
 VideoContent::as_xml (xmlpp::Node* node) const
 {
        boost::mutex::scoped_lock lm (_mutex);
-       node->add_child("VideoLength")->add_child_text (raw_convert<string> (_video_length.get ()));
+       node->add_child("VideoLength")->add_child_text (raw_convert<string> (_video_length));
        node->add_child("VideoWidth")->add_child_text (raw_convert<string> (_video_size.width));
        node->add_child("VideoHeight")->add_child_text (raw_convert<string> (_video_size.height));
        node->add_child("VideoFrameRate")->add_child_text (raw_convert<string> (_video_frame_rate));
@@ -198,8 +191,8 @@ VideoContent::as_xml (xmlpp::Node* node) const
        if (_colour_conversion) {
                _colour_conversion.get().as_xml (node->add_child("ColourConversion"));
        }
-       node->add_child("FadeIn")->add_child_text (raw_convert<string> (_fade_in.get ()));
-       node->add_child("FadeOut")->add_child_text (raw_convert<string> (_fade_out.get ()));
+       node->add_child("FadeIn")->add_child_text (raw_convert<string> (_fade_in));
+       node->add_child("FadeOut")->add_child_text (raw_convert<string> (_fade_out));
 }
 
 void
@@ -216,7 +209,7 @@ VideoContent::take_from_video_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<float> const vfr = d->video_frame_rate ();
-       ContentTime vl = d->video_length ();
+       Frame vl = d->video_length ();
        optional<float> const ar = d->sample_aspect_ratio ();
 
        {
@@ -235,7 +228,7 @@ VideoContent::take_from_video_examiner (shared_ptr<VideoExaminer> d)
 
        shared_ptr<const Film> film = _film.lock ();
        DCPOMATIC_ASSERT (film);
-       LOG_GENERAL ("Video length obtained from header as %1 frames", _video_length.frames (_video_frame_rate));
+       LOG_GENERAL ("Video length obtained from header as %1 frames", _video_length);
 
        set_default_colour_conversion ();
        
@@ -355,8 +348,8 @@ string
 VideoContent::technical_summary () const
 {
        string s = String::compose (
-               N_("video: length %1, size %2x%3, rate %4"),
-               video_length_after_3d_combine().seconds(),
+               N_("video: length %1 frames, size %2x%3, rate %4"),
+               video_length_after_3d_combine(),
                video_size().width,
                video_size().height,
                video_frame_rate()
@@ -413,7 +406,7 @@ VideoContent::set_colour_conversion (ColourConversion c)
 }
 
 void
-VideoContent::set_fade_in (ContentTime t)
+VideoContent::set_fade_in (Frame t)
 {
        {
                boost::mutex::scoped_lock lm (_mutex);
@@ -424,7 +417,7 @@ VideoContent::set_fade_in (ContentTime t)
 }
 
 void
-VideoContent::set_fade_out (ContentTime t)
+VideoContent::set_fade_out (Frame t)
 {
        {
                boost::mutex::scoped_lock lm (_mutex);
@@ -487,13 +480,13 @@ VideoContent::fade (Frame f) const
 {
        DCPOMATIC_ASSERT (f >= 0);
        
-       if (f < fade_in().frames (video_frame_rate ())) {
-               return float (f) / _fade_in.frames (video_frame_rate ());
+       if (f < fade_in()) {
+               return float (f) / fade_in();
        }
 
-       Frame fade_out_start = ContentTime (video_length() - fade_out()).frames (video_frame_rate ());
+       Frame fade_out_start = video_length() - fade_out();
        if (f >= fade_out_start) {
-               return 1 - float (f - fade_out_start) / fade_out().frames (video_frame_rate ());
+               return 1 - float (f - fade_out_start) / fade_out();
        }
 
        return optional<float> ();
index 72bad21f8dd987b089e185529771e21a313466a6..abc9c5fa3e8db454c803b6de462eba4a809c56ef 100644 (file)
@@ -44,7 +44,7 @@ class VideoContent : public virtual Content
 {
 public:
        VideoContent (boost::shared_ptr<const Film>);
-       VideoContent (boost::shared_ptr<const Film>, DCPTime, ContentTime);
+       VideoContent (boost::shared_ptr<const Film>, DCPTime, Frame);
        VideoContent (boost::shared_ptr<const Film>, boost::filesystem::path);
        VideoContent (boost::shared_ptr<const Film>, cxml::ConstNodePtr, int);
        VideoContent (boost::shared_ptr<const Film>, std::vector<boost::shared_ptr<Content> >);
@@ -55,15 +55,15 @@ public:
 
        virtual void set_default_colour_conversion ();
        
-       ContentTime video_length () const {
+       Frame video_length () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _video_length;
        }
 
-       ContentTime video_length_after_3d_combine () const {
+       Frame video_length_after_3d_combine () const {
                boost::mutex::scoped_lock lm (_mutex);
                if (_video_frame_type == VIDEO_FRAME_TYPE_3D_ALTERNATE) {
-                       return ContentTime (_video_length.get() / 2);
+                       return _video_length / 2;
                }
                
                return _video_length;
@@ -91,8 +91,8 @@ public:
        void unset_colour_conversion (bool signal = true);
        void set_colour_conversion (ColourConversion);
 
-       void set_fade_in (ContentTime);
-       void set_fade_out (ContentTime);
+       void set_fade_in (Frame);
+       void set_fade_out (Frame);
        
        VideoFrameType video_frame_type () const {
                boost::mutex::scoped_lock lm (_mutex);
@@ -140,12 +140,12 @@ public:
                return _sample_aspect_ratio;
        }
 
-       ContentTime fade_in () const {
+       Frame fade_in () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _fade_in;
        }
 
-       ContentTime fade_out () const {
+       Frame fade_out () const {
                boost::mutex::scoped_lock lm (_mutex);
                return _fade_out;
        }
@@ -165,7 +165,7 @@ public:
 protected:
        void take_from_video_examiner (boost::shared_ptr<VideoExaminer>);
 
-       ContentTime _video_length;
+       Frame _video_length;
        float _video_frame_rate;
        boost::optional<ColourConversion> _colour_conversion;
 
@@ -185,8 +185,8 @@ private:
            if there is one.
        */
        boost::optional<float> _sample_aspect_ratio;
-       ContentTime _fade_in;
-       ContentTime _fade_out;
+       Frame _fade_in;
+       Frame _fade_out;
 };
 
 #endif
index 2dcacfc349fbeaa11b46219bf80867a6f682729e..f8d247d1542a41a9c229681bda6d2247457dd008 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2013-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2013-2015 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
@@ -34,7 +34,7 @@ public:
        virtual ~VideoExaminer () {}
        virtual boost::optional<float> video_frame_rate () const = 0;
        virtual dcp::Size video_size () const = 0;
-       virtual ContentTime video_length () const = 0;
+       virtual Frame video_length () const = 0;
        virtual boost::optional<float> sample_aspect_ratio () const {
                return boost::optional<float> ();
        }
index d121eb0ccf4caea4030a13e3ac12aa8b574c0e36..a826a10710f32a489bdd1be19c435dd59b94a08f 100644 (file)
@@ -190,7 +190,7 @@ main (int argc, char* argv[])
                for (ContentList::iterator i = content.begin(); i != content.end(); ++i) {
                        shared_ptr<ImageContent> ic = dynamic_pointer_cast<ImageContent> (*i);
                        if (ic) {
-                               ic->set_video_length (ContentTime::from_seconds (still_length));
+                               ic->set_video_length (still_length * 24);
                        }
                }
 
index 76de75ea618981aad1a61cc9987c776dda1ec228..45593fd5b84921982d4658e948d7c5d19a50762a 100644 (file)
@@ -40,7 +40,7 @@ ContentPropertiesDialog::ContentPropertiesDialog (wxWindow* parent, shared_ptr<C
        if (video) {
                add_property (
                        _("Video length"),
-                       std_to_wx (raw_convert<string> (video->video_length ().frames (video->video_frame_rate ()))) + " " + _("video frames")
+                       std_to_wx (raw_convert<string> (video->video_length ())) + " " + _("video frames")
                        );
                add_property (
                        _("Video size"),
@@ -60,7 +60,7 @@ ContentPropertiesDialog::ContentPropertiesDialog (wxWindow* parent, shared_ptr<C
                        );
                add_property (
                        _("Audio length"),
-                       std_to_wx (raw_convert<string> (audio->audio_length().frames (audio->audio_frame_rate ()))) + " " + _("audio frames")
+                       std_to_wx (raw_convert<string> (audio->audio_length())) + " " + _("audio frames")
                        );
        }
        
index cafb06dfcffa6162e4ff88dc59e2980d1c5c2ea4..74c1756a5205221edc15dbec4fd585a07d833961 100644 (file)
@@ -284,8 +284,8 @@ TimingPanel::full_length_changed ()
        for (ContentList::iterator i = c.begin(); i != c.end(); ++i) {
                shared_ptr<ImageContent> ic = dynamic_pointer_cast<ImageContent> (*i);
                if (ic && ic->still ()) {
-                       /* XXX: No effective FRC here... is this right? */
-                       ic->set_video_length (ContentTime (_full_length->get (_parent->film()->video_frame_rate()), FrameRateChange (1, 1)));
+                       int const vfr = _parent->film()->video_frame_rate ();
+                       ic->set_video_length (_full_length->get (vfr).frames (vfr));
                }
        }
 }
index 0f241506e6a29f8f0083f23703c2106a5e9088b1..9ddfd671407bb314d4dea09d4f3f390aa097d761 100644 (file)
@@ -277,24 +277,24 @@ VideoPanel::film_content_changed (int property)
                        }
                }
        } else if (property == VideoContentProperty::VIDEO_FADE_IN) {
-               set<ContentTime> check;
+               set<Frame> check;
                for (VideoContentList::const_iterator i = vc.begin (); i != vc.end(); ++i) {
                        check.insert ((*i)->fade_in ());
                }
                
                if (check.size() == 1) {
-                       _fade_in->set (vc.front()->fade_in (), vc.front()->video_frame_rate ());
+                       _fade_in->set (ContentTime::from_frames (vc.front()->fade_in (), vc.front()->video_frame_rate ()), vc.front()->video_frame_rate ());
                } else {
                        _fade_in->clear ();
                }
        } else if (property == VideoContentProperty::VIDEO_FADE_OUT) {
-               set<ContentTime> check;
+               set<Frame> check;
                for (VideoContentList::const_iterator i = vc.begin (); i != vc.end(); ++i) {
                        check.insert ((*i)->fade_out ());
                }
                
                if (check.size() == 1) {
-                       _fade_out->set (vc.front()->fade_out (), vc.front()->video_frame_rate ());
+                       _fade_out->set (ContentTime::from_frames (vc.front()->fade_out (), vc.front()->video_frame_rate ()), vc.front()->video_frame_rate ());
                } else {
                        _fade_out->clear ();
                }
@@ -394,7 +394,8 @@ VideoPanel::fade_in_changed ()
 {
        VideoContentList vc = _parent->selected_video ();
        for (VideoContentList::const_iterator i = vc.begin(); i != vc.end(); ++i) {
-               (*i)->set_fade_in (_fade_in->get (_parent->film()->video_frame_rate ()));
+               int const vfr = _parent->film()->video_frame_rate ();
+               (*i)->set_fade_in (_fade_in->get (vfr).frames (vfr));
        }
 }
 
@@ -403,7 +404,8 @@ VideoPanel::fade_out_changed ()
 {
        VideoContentList vc = _parent->selected_video ();
        for (VideoContentList::const_iterator i = vc.begin(); i != vc.end(); ++i) {
-               (*i)->set_fade_out (_fade_out->get (_parent->film()->video_frame_rate ()));
+               int const vfr = _parent->film()->video_frame_rate ();
+               (*i)->set_fade_out (_fade_out->get (vfr).frames (vfr));
        }
 }
 
index 28d6aa4bbf6b6d8118cd88784ce799066bd7157c..9c496c4ee3a4d08b6b9a56bbfb45c39995f8f2d3 100644 (file)
@@ -1,5 +1,5 @@
 /*
-    Copyright (C) 2012-2014 Carl Hetherington <cth@carlh.net>
+    Copyright (C) 2012-2015 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
index e31689d3f33f469daf51b06a9e54266184fd0c82..7b7fa637bbf9766b860067403a07a49b5299519f 100644 (file)
@@ -44,7 +44,7 @@ public:
        {
                Frame const N = min (
                        Frame (2000),
-                       _audio_content->audio_length().frames (_audio_content->resampled_audio_frame_rate ()) - _position
+                       _audio_content->audio_length() - _position
                        );
 
                shared_ptr<AudioBuffers> buffers (new AudioBuffers (_audio_content->audio_channels(), N));
@@ -87,15 +87,15 @@ public:
        }
 
        DCPTime full_length () const {
-               return DCPTime (audio_length().get ());
+               return DCPTime::from_seconds (float (audio_length()) / audio_frame_rate ());
        }
 
        int audio_channels () const {
                return 2;
        }
 
-       ContentTime audio_length () const {
-               return ContentTime::from_seconds (61.2942);
+       Frame audio_length () const {
+               return rint (61.2942 * audio_frame_rate ());
        }
 
        int audio_frame_rate () const {
index 5981552d128e6c3f9f0ead28bacfc772ee2fd718..e6f4b69eea64b857cd0477e4ab95ae88832cf730 100644 (file)
@@ -45,10 +45,10 @@ BOOST_AUTO_TEST_CASE (black_fill_test)
        wait_for_jobs ();
 
        contentA->set_scale (VideoContentScale (Ratio::from_id ("185")));
-       contentA->set_video_length (ContentTime::from_frames (3, 24));
+       contentA->set_video_length (3);
        contentA->set_position (DCPTime::from_frames (2, film->video_frame_rate ()));
        contentB->set_scale (VideoContentScale (Ratio::from_id ("185")));
-       contentB->set_video_length (ContentTime::from_frames (1, 24));
+       contentB->set_video_length (1);
        contentB->set_position (DCPTime::from_frames (7, film->video_frame_rate ()));
 
        film->make_dcp ();
index 5511576521f59ce7fc5557ef55015c2f66d2e051..6b02efcb50d264a1de413f537275a5d97922f557 100644 (file)
@@ -54,7 +54,7 @@ test (boost::filesystem::path file, float fps, int gaps)
 
        BOOST_CHECK_CLOSE (decoder.video_content()->video_frame_rate(), fps, 0.01);
        
-       Frame const N = decoder.video_content()->video_length().frames (decoder.video_content()->video_frame_rate ());
+       Frame const N = decoder.video_content()->video_length();
 #ifdef DCPOMATIC_DEBUG 
        decoder.test_gaps = 0;
 #endif 
index 441af6bf30514ecb2eaaafa58ae7deea3ffdaa16..105683ad1aea88d802fea9c0449085cb43bb2871 100644 (file)
@@ -64,7 +64,7 @@ BOOST_AUTO_TEST_CASE (scaling_test)
 
        wait_for_jobs ();
        
-       imc->set_video_length (ContentTime::from_frames (1, 24));
+       imc->set_video_length (1);
 
        scaling_test_for (film, imc, "133", "185");
        scaling_test_for (film, imc, "185", "185");
index d28b96f417023af5ea2acaf6e0f12f9929ac8371..055dc9def0d619ac6dc5a08628bf0b81233e08d8 100644 (file)
@@ -77,6 +77,7 @@ def build(bld):
                  stream_test.cc
                  test.cc
                  threed_test.cc
+                 time_calculation_test.cc
                  update_checker_test.cc
                  upmixer_a_test.cc
                  util_test.cc