Various bits and pieces.
authorCarl Hetherington <cth@carlh.net>
Thu, 23 May 2013 16:18:49 +0000 (17:18 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 23 May 2013 16:18:49 +0000 (17:18 +0100)
39 files changed:
src/lib/audio_content.cc
src/lib/audio_content.h
src/lib/audio_decoder.cc
src/lib/audio_decoder.h
src/lib/black_decoder.cc
src/lib/black_decoder.h
src/lib/content.cc
src/lib/content.h
src/lib/examine_content_job.cc
src/lib/ffmpeg_content.cc
src/lib/ffmpeg_content.h
src/lib/ffmpeg_decoder.cc
src/lib/film.cc
src/lib/film.h
src/lib/imagemagick_content.cc
src/lib/imagemagick_content.h
src/lib/null_content.cc
src/lib/null_content.h
src/lib/player.cc
src/lib/player.h
src/lib/playlist.cc
src/lib/playlist.h
src/lib/silence_decoder.cc [new file with mode: 0644]
src/lib/silence_decoder.h
src/lib/sndfile_content.cc
src/lib/sndfile_content.h
src/lib/types.h
src/lib/video_content.cc
src/lib/video_content.h
src/lib/video_decoder.h
src/lib/wscript
src/tools/dcpomatic.cc
src/tools/dcpomatic_batch.cc
src/tools/dcpomatic_cli.cc
src/tools/servomatictest.cc
src/wx/film_editor.cc
src/wx/film_viewer.cc
src/wx/timeline.cc
test/test.cc

index a3942f64bf3d6455922c2742ca0834cc311b28b0..607e71c50ba6f1013f429c36d190af4e0d48380e 100644 (file)
@@ -32,24 +32,24 @@ int const AudioContentProperty::AUDIO_FRAME_RATE = 202;
 int const AudioContentProperty::AUDIO_GAIN = 203;
 int const AudioContentProperty::AUDIO_DELAY = 204;
 
-AudioContent::AudioContent (Time s)
-       : Content (s)
+AudioContent::AudioContent (shared_ptr<const Film> f, Time s)
+       : Content (f, s)
        , _audio_gain (0)
        , _audio_delay (0)
 {
 
 }
 
-AudioContent::AudioContent (boost::filesystem::path f)
-       : Content (f)
+AudioContent::AudioContent (shared_ptr<const Film> f, boost::filesystem::path p)
+       : Content (f, p)
        , _audio_gain (0)
        , _audio_delay (0)
 {
 
 }
 
-AudioContent::AudioContent (shared_ptr<const cxml::Node> node)
-       : Content (node)
+AudioContent::AudioContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+       : Content (f, node)
 {
        _audio_gain = node->number_child<float> ("AudioGain");
        _audio_delay = node->number_child<int> ("AudioDelay");
index e767fd326c2395378083ddf867eb4cc77fc85c69..0c5287eaf776708f61d246b16d302357edb8b8ed 100644 (file)
@@ -42,9 +42,9 @@ public:
 class AudioContent : public virtual Content
 {
 public:
-       AudioContent (Time);
-       AudioContent (boost::filesystem::path);
-       AudioContent (boost::shared_ptr<const cxml::Node>);
+       AudioContent (boost::shared_ptr<const Film>, Time);
+       AudioContent (boost::shared_ptr<const Film>, boost::filesystem::path);
+       AudioContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
        AudioContent (AudioContent const &);
 
        void as_xml (xmlpp::Node *) const;
@@ -52,7 +52,7 @@ public:
         virtual int audio_channels () const = 0;
         virtual ContentAudioFrame audio_length () const = 0;
         virtual int content_audio_frame_rate () const = 0;
-       virtual int output_audio_frame_rate (boost::shared_ptr<const Film>) const = 0;
+       virtual int output_audio_frame_rate () const = 0;
        virtual AudioMapping audio_mapping () const = 0;
 
        void set_audio_gain (float);
index ddda816a571d374897ee499f8bfdee155b1b8ee2..6712e06241dc37a9e1c99fcaeb88c92c50f4d01d 100644 (file)
@@ -32,15 +32,18 @@ AudioDecoder::AudioDecoder (shared_ptr<const Film> f, shared_ptr<const AudioCont
        : Decoder (f)
        , _next_audio (0)
        , _audio_content (c)
-       , _output_audio_frame_rate (_audio_content->output_audio_frame_rate (f))
 {
-       if (_audio_content->content_audio_frame_rate() != _output_audio_frame_rate) {
+       if (_audio_content->content_audio_frame_rate() != _audio_content->output_audio_frame_rate()) {
 
                shared_ptr<const Film> film = _film.lock ();
                assert (film);
 
                stringstream s;
-               s << String::compose ("Will resample audio from %1 to %2", _audio_content->content_audio_frame_rate(), _output_audio_frame_rate);
+               s << String::compose (
+                       "Will resample audio from %1 to %2",
+                       _audio_content->content_audio_frame_rate(), _audio_content->output_audio_frame_rate()
+                       );
+               
                film->log()->log (s.str ());
 
                /* We will be using planar float data when we call the
@@ -55,7 +58,7 @@ AudioDecoder::AudioDecoder (shared_ptr<const Film> f, shared_ptr<const AudioCont
                        0,
                        av_get_default_channel_layout (MAX_AUDIO_CHANNELS),
                        AV_SAMPLE_FMT_FLTP,
-                       _output_audio_frame_rate,
+                       _audio_content->output_audio_frame_rate(),
                        av_get_default_channel_layout (MAX_AUDIO_CHANNELS),
                        AV_SAMPLE_FMT_FLTP,
                        _audio_content->content_audio_frame_rate(),
@@ -115,7 +118,9 @@ AudioDecoder::audio (shared_ptr<const AudioBuffers> data, Time time)
        if (_swr_context) {
 
                /* Compute the resampled frames count and add 32 for luck */
-               int const max_resampled_frames = ceil ((int64_t) data->frames() * _output_audio_frame_rate / _audio_content->content_audio_frame_rate()) + 32;
+               int const max_resampled_frames = ceil (
+                       (int64_t) data->frames() * _audio_content->output_audio_frame_rate() / _audio_content->content_audio_frame_rate()
+                       ) + 32;
 
                shared_ptr<AudioBuffers> resampled (new AudioBuffers (MAX_AUDIO_CHANNELS, max_resampled_frames));
 
index 0f7cb6dbdbca441721a9374c48090a7e88cd7b7e..fb9f23f034be4bd410b5b50bb5ec05c7611e16a7 100644 (file)
@@ -46,11 +46,10 @@ protected:
        void audio (boost::shared_ptr<const AudioBuffers>, Time);
 
        Time _next_audio;
-
-private:
        boost::shared_ptr<const AudioContent> _audio_content;
+
+private:       
        SwrContext* _swr_context;
-       int _output_audio_frame_rate;
 };
 
 #endif
index 482cd2ce1ebe2333f714127b3a1724f2d9652edd..e8e1a3df2e2ce967bb5ae79d0fcfef16a82e85da 100644 (file)
 */
 
 #include "black_decoder.h"
+#include "image.h"
+#include "null_content.h"
 
-BlackDecoder::BlackDecoder (shared_ptr<Film> f, shared_ptr<NullContent> c)
-       : VideoDecoder (f, c)
+using boost::shared_ptr;
+
+BlackDecoder::BlackDecoder (shared_ptr<const Film> f, shared_ptr<NullContent> c)
+       : Decoder (f)
+       , VideoDecoder (f, c)
 {
 
 }
@@ -29,7 +34,7 @@ void
 BlackDecoder::pass ()
 {
        if (!_image) {
-               _image.reset (new SimpleImage (AV_PIX_FMT_RGB24, video_size ()));
+               _image.reset (new SimpleImage (AV_PIX_FMT_RGB24, video_size(), true));
                _image->make_black ();
                video (_image, false, _next_video);
        } else {
@@ -59,3 +64,9 @@ BlackDecoder::next () const
 {
        return _next_video;
 }
+
+void
+BlackDecoder::seek (Time t)
+{
+       _next_video = t;
+}
index bb3e7711d3431c5a32231a2c1836d88bc7e656f1..b4beb0fdd4da2f61a3a0a3289bb06f1ff5d30cd4 100644 (file)
@@ -19,6 +19,8 @@
 
 #include "video_decoder.h"
 
+class NullContent;
+
 class BlackDecoder : public VideoDecoder
 {
 public:
index 43d0ef958c08bd7ca93ff772133242de018240da..395359fa7d498dbb28a4cd56297ac762b14807dc 100644 (file)
@@ -29,20 +29,23 @@ using std::string;
 using boost::shared_ptr;
 using boost::lexical_cast;
 
-Content::Content (Time s)
-       : _start (s)
+Content::Content (shared_ptr<const Film> f, Time s)
+       : _film (f)
+       , _start (s)
 {
 
 }
 
-Content::Content (boost::filesystem::path f)
-       : _file (f)
+Content::Content (shared_ptr<const Film> f, boost::filesystem::path p)
+       : _film (f)
+       , _file (p)
        , _start (0)
 {
 
 }
 
-Content::Content (shared_ptr<const cxml::Node> node)
+Content::Content (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+       : _film (f)
 {
        _file = node->string_child ("File");
        _digest = node->string_child ("Digest");
@@ -51,6 +54,7 @@ Content::Content (shared_ptr<const cxml::Node> node)
 
 Content::Content (Content const & o)
        : boost::enable_shared_from_this<Content> (o)
+       , _film (o._film)
        , _file (o._file)
        , _digest (o._digest)
        , _start (o._start)
@@ -68,7 +72,7 @@ Content::as_xml (xmlpp::Node* node) const
 }
 
 void
-Content::examine (shared_ptr<Film>, shared_ptr<Job>)
+Content::examine (shared_ptr<Job>)
 {
        string const d = md5_digest (_file);
        boost::mutex::scoped_lock lm (_mutex);
index db1e56bc4d609151db6114a1707eee56a989c70e..bcfbef7e3bc7a83d6bfb4b75bcb0a031106624cd 100644 (file)
@@ -39,17 +39,17 @@ class Film;
 class Content : public boost::enable_shared_from_this<Content>
 {
 public:
-       Content (Time);
-       Content (boost::filesystem::path);
-       Content (boost::shared_ptr<const cxml::Node>);
+       Content (boost::shared_ptr<const Film>, Time);
+       Content (boost::shared_ptr<const Film>, boost::filesystem::path);
+       Content (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
        Content (Content const &);
        
-       virtual void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>);
+       virtual void examine (boost::shared_ptr<Job>);
        virtual std::string summary () const = 0;
        virtual std::string information () const = 0;
        virtual void as_xml (xmlpp::Node *) const;
        virtual boost::shared_ptr<Content> clone () const = 0;
-       virtual Time length (boost::shared_ptr<const Film>) const = 0;
+       virtual Time length () const = 0;
 
        boost::filesystem::path file () const {
                boost::mutex::scoped_lock lm (_mutex);
@@ -66,15 +66,16 @@ public:
                return _start;
        }
 
-       Time end (boost::shared_ptr<const Film> f) const {
-               return start() + length(f);
+       Time end () const {
+               return start() + length();
        }
 
        boost::signals2::signal<void (boost::weak_ptr<Content>, int)> Changed;
 
 protected:
        void signal_changed (int);
-       
+
+       boost::weak_ptr<const Film> _film;
        mutable boost::mutex _mutex;
 
 private:
index 21ab4a71d6a29bebd42dcb5a3f60a76808dd5586..6d5f4faf9e690b754e621883452a1253234c775b 100644 (file)
@@ -47,7 +47,7 @@ ExamineContentJob::name () const
 void
 ExamineContentJob::run ()
 {
-       _content->examine (_film, shared_from_this ());
+       _content->examine (shared_from_this ());
        set_progress (1);
        set_state (FINISHED_OK);
 }
index 2a42833535db640736b85ee155f58c1ab3733fd0..ad7af07d864479123513384ecf93241e49176af7 100644 (file)
@@ -42,18 +42,18 @@ int const FFmpegContentProperty::SUBTITLE_STREAM = 101;
 int const FFmpegContentProperty::AUDIO_STREAMS = 102;
 int const FFmpegContentProperty::AUDIO_STREAM = 103;
 
-FFmpegContent::FFmpegContent (boost::filesystem::path f)
-       : Content (f)
-       , VideoContent (f)
-       , AudioContent (f)
+FFmpegContent::FFmpegContent (shared_ptr<const Film> f, boost::filesystem::path p)
+       : Content (f, p)
+       , VideoContent (f, p)
+       , AudioContent (f, p)
 {
 
 }
 
-FFmpegContent::FFmpegContent (shared_ptr<const cxml::Node> node)
-       : Content (node)
-       , VideoContent (node)
-       , AudioContent (node)
+FFmpegContent::FFmpegContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+       : Content (f, node)
+       , VideoContent (f, node)
+       , AudioContent (f, node)
 {
        list<shared_ptr<cxml::Node> > c = node->node_children ("SubtitleStream");
        for (list<shared_ptr<cxml::Node> >::const_iterator i = c.begin(); i != c.end(); ++i) {
@@ -112,11 +112,14 @@ FFmpegContent::as_xml (xmlpp::Node* node) const
 }
 
 void
-FFmpegContent::examine (shared_ptr<Film> film, shared_ptr<Job> job)
+FFmpegContent::examine (shared_ptr<Job> job)
 {
        job->set_progress_unknown ();
 
-       Content::examine (film, job);
+       Content::examine (job);
+
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
 
        shared_ptr<FFmpegDecoder> decoder (new FFmpegDecoder (film, shared_from_this (), true, false, false));
 
@@ -233,8 +236,11 @@ FFmpegContent::content_audio_frame_rate () const
 }
 
 int
-FFmpegContent::output_audio_frame_rate (shared_ptr<const Film> film) const
+FFmpegContent::output_audio_frame_rate () const
 {
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
        /* Resample to a DCI-approved sample rate */
        double t = dcp_audio_frame_rate (content_audio_frame_rate ());
 
@@ -308,8 +314,11 @@ FFmpegContent::clone () const
 }
 
 Time
-FFmpegContent::length (shared_ptr<const Film> film) const
+FFmpegContent::length () const
 {
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
        FrameRateConversion frc (video_frame_rate (), film->dcp_video_frame_rate ());
        return video_length() * frc.factor() * TIME_HZ / film->dcp_video_frame_rate ();
 }
index 9d842515ef2ef5949093f5a7ce5f1bd440d6566a..d5b9869967074de0347244ebaec3c6ebbab17f3e 100644 (file)
@@ -80,26 +80,26 @@ public:
 class FFmpegContent : public VideoContent, public AudioContent
 {
 public:
-       FFmpegContent (boost::filesystem::path);
-       FFmpegContent (boost::shared_ptr<const cxml::Node>);
+       FFmpegContent (boost::shared_ptr<const Film>, boost::filesystem::path);
+       FFmpegContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
        FFmpegContent (FFmpegContent const &);
 
        boost::shared_ptr<FFmpegContent> shared_from_this () {
                return boost::dynamic_pointer_cast<FFmpegContent> (Content::shared_from_this ());
        }
        
-       void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>);
+       void examine (boost::shared_ptr<Job>);
        std::string summary () const;
        std::string information () const;
        void as_xml (xmlpp::Node *) const;
        boost::shared_ptr<Content> clone () const;
-       Time length (boost::shared_ptr<const Film>) const;
+       Time length () const;
 
         /* AudioContent */
         int audio_channels () const;
         ContentAudioFrame audio_length () const;
         int content_audio_frame_rate () const;
-        int output_audio_frame_rate (boost::shared_ptr<const Film>) const;
+        int output_audio_frame_rate () const;
        AudioMapping audio_mapping () const;
        
         std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
index f7bb979441870c707454df55e23ed15c94dfc926..b45ba8585f329b259fe1f2eb4d99bc3db28d2f63 100644 (file)
@@ -473,6 +473,7 @@ void
 FFmpegDecoder::do_seek (Time t, bool backwards, bool accurate)
 {
        int64_t const vt = t / (av_q2d (_format_context->streams[_video_stream]->time_base) * TIME_HZ);
+       cout << "seek-> " << t << "\n";
        av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0);
 
        avcodec_flush_buffers (_video_codec_context);
index b561c2d15b2d2703242b20d54e373054906cefe1..9103024ab14d1fbc560743106bf2bc47abcff7e2 100644 (file)
@@ -83,15 +83,12 @@ using libdcp::Size;
 
 int const Film::state_version = 4;
 
-/** Construct a Film object in a given directory, reading any metadata
- *  file that exists in that directory.  An exception will be thrown if
- *  must_exist is true and the specified directory does not exist.
+/** Construct a Film object in a given directory.
  *
  *  @param d Film directory.
- *  @param must_exist true to throw an exception if does not exist.
  */
 
-Film::Film (string d, bool must_exist)
+Film::Film (string d)
        : _playlist (new Playlist)
        , _use_dci_name (true)
        , _dcp_content_type (Config::instance()->default_dcp_content_type ())
@@ -131,21 +128,6 @@ Film::Film (string d, bool must_exist)
        }
 
        set_directory (result.string ());
-       
-       if (!boost::filesystem::exists (directory())) {
-               if (must_exist) {
-                       throw OpenFileError (directory());
-               } else {
-                       boost::filesystem::create_directory (directory());
-               }
-       }
-
-       if (must_exist) {
-               read_metadata ();
-       } else {
-               write_metadata ();
-       }
-
        _log.reset (new FileLog (file ("log")));
 }
 
@@ -388,6 +370,10 @@ Film::encoded_frames () const
 void
 Film::write_metadata () const
 {
+       if (!boost::filesystem::exists (directory())) {
+               boost::filesystem::create_directory (directory());
+       }
+       
        boost::mutex::scoped_lock lm (_state_mutex);
        LocaleGuard lg;
 
@@ -477,7 +463,7 @@ Film::read_metadata ()
        _dcp_video_frame_rate = f.number_child<int> ("DCPVideoFrameRate");
        _dci_date = boost::gregorian::from_undelimited_string (f.string_child ("DCIDate"));
 
-       _playlist->set_from_xml (f.node_child ("Playlist"));
+       _playlist->set_from_xml (shared_from_this(), f.node_child ("Playlist"));
 
        _dirty = false;
 }
@@ -865,7 +851,7 @@ Film::remove_content (shared_ptr<Content> c)
 Time
 Film::length () const
 {
-       return _playlist->length (shared_from_this ());
+       return _playlist->length ();
 }
 
 bool
index 71a3b1c34b68cd226525d02611d665b363a4b14b..b8d4ee40e1b1cefbcc6e9aeffa5f14da4d915d3c 100644 (file)
@@ -56,7 +56,7 @@ class Player;
 class Film : public boost::enable_shared_from_this<Film>
 {
 public:
-       Film (std::string d, bool must_exist = true);
+       Film (std::string d);
        Film (Film const &);
 
        std::string info_dir () const;
@@ -86,6 +86,7 @@ public:
        std::string file (std::string f) const;
        std::string dir (std::string d) const;
 
+       void read_metadata ();
        void write_metadata () const;
 
        std::string dci_name (bool if_created_now) const;
@@ -259,7 +260,6 @@ private:
        void signal_changed (Property);
        void analyse_audio_finished ();
        std::string video_state_identifier () const;
-       void read_metadata ();
        void playlist_changed ();
        void playlist_content_changed (boost::weak_ptr<Content>, int);
        std::string filename_safe_name () const;
index f9daf204e7787b41c0560e87f2e1bf01973a3db8..ac04fb15b7588c44b20419bb932f38bba997025e 100644 (file)
@@ -29,16 +29,16 @@ using std::string;
 using std::stringstream;
 using boost::shared_ptr;
 
-ImageMagickContent::ImageMagickContent (boost::filesystem::path f)
-       : Content (f)
-       , VideoContent (f)
+ImageMagickContent::ImageMagickContent (shared_ptr<const Film> f, boost::filesystem::path p)
+       : Content (f, p)
+       , VideoContent (f, p)
 {
 
 }
 
-ImageMagickContent::ImageMagickContent (shared_ptr<const cxml::Node> node)
-       : Content (node)
-       , VideoContent (node)
+ImageMagickContent::ImageMagickContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+       : Content (f, node)
+       , VideoContent (f, node)
 {
        
 }
@@ -66,9 +66,13 @@ ImageMagickContent::as_xml (xmlpp::Node* node) const
 }
 
 void
-ImageMagickContent::examine (shared_ptr<Film> film, shared_ptr<Job> job)
+ImageMagickContent::examine (shared_ptr<Job> job)
 {
-       Content::examine (film, job);
+       Content::examine (job);
+
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
        shared_ptr<ImageMagickDecoder> decoder (new ImageMagickDecoder (film, shared_from_this()));
 
        {
@@ -100,8 +104,11 @@ ImageMagickContent::set_video_length (ContentVideoFrame len)
 }
 
 Time
-ImageMagickContent::length (shared_ptr<const Film> film) const
+ImageMagickContent::length () const
 {
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
        FrameRateConversion frc (24, film->dcp_video_frame_rate ());
        return video_length() * frc.factor() * TIME_HZ / film->dcp_video_frame_rate ();
 }
index b7f2cd2c327e5bfd773513fdf9871cee91e56901..e3e82789238a3a4ee6a2e6ad3638155371e18969 100644 (file)
@@ -27,18 +27,18 @@ namespace cxml {
 class ImageMagickContent : public VideoContent
 {
 public:
-       ImageMagickContent (boost::filesystem::path);
-       ImageMagickContent (boost::shared_ptr<const cxml::Node>);
+       ImageMagickContent (boost::shared_ptr<const Film>, boost::filesystem::path);
+       ImageMagickContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
 
        boost::shared_ptr<ImageMagickContent> shared_from_this () {
                return boost::dynamic_pointer_cast<ImageMagickContent> (Content::shared_from_this ());
        };
 
-       void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>);
+       void examine (boost::shared_ptr<Job>);
        std::string summary () const;
        void as_xml (xmlpp::Node *) const;
        boost::shared_ptr<Content> clone () const;
-       Time length (boost::shared_ptr<const Film>) const;
+       Time length () const;
 
        void set_video_length (ContentVideoFrame);
 
index 0e275a3932e48bd3230d2031c48fac2c68edbc03..0084972c2ae5e5045000c8ae8cd297655e1a893b 100644 (file)
 
 */
 
-NullContent::NullContent (Time s, Time len, shared_ptr<const Film> f)
-       : Content (s)
-       , VideoContent (s, f->time_to_video_frames (len))
-       , AudioContent (s)
+#include "null_content.h"
+#include "film.h"
+
+using boost::shared_ptr;
+
+NullContent::NullContent (shared_ptr<const Film> f, Time s, Time len)
+       : Content (f, s)
+       , VideoContent (f, s, f->time_to_video_frames (len))
+       , AudioContent (f, s)
        , _audio_length (f->time_to_audio_frames (len))
-       , _content_audio_frame_rate (f->dcp_audio_frame_rate ())
+       , _length (len)
+{
+
+}
+
+int
+NullContent::content_audio_frame_rate () const
 {
+       return output_audio_frame_rate ();
+}
+       
 
+int
+NullContent::output_audio_frame_rate () const
+{
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       return film->dcp_audio_frame_rate ();
 }
index e680087826d571f523c8a317012228ea8428d53f..d4a3b7371ed8514b75372cc08626784939686b71 100644 (file)
 
 #include <string>
 #include <boost/shared_ptr.hpp>
-#include "content.h"
+#include "video_content.h"
+#include "audio_content.h"
 
 class NullContent : public VideoContent, public AudioContent
 {
 public:
-       NullContent (Time, Time, boost::shared_ptr<const Film>);
+       NullContent (boost::shared_ptr<const Film>, Time, Time);
 
        std::string summary () const {
                return "";
@@ -48,23 +49,19 @@ public:
                return _audio_length;
        }
        
-        int content_audio_frame_rate () const {
-               return _content_audio_frame_rate;
-       }
+        int content_audio_frame_rate () const;
        
-       int output_audio_frame_rate (boost::shared_ptr<const Film> f) const {
-               return f->dcp_audio_frame_rate ();
-       }
+       int output_audio_frame_rate () const;
        
        AudioMapping audio_mapping () const {
                return AudioMapping ();
        }
        
-       Time length (boost::shared_ptr<const Film>) const {
+       Time length () const {
                return _length;
        }
 
 private:
        ContentAudioFrame _audio_length;
-       ContentAudioFrame _content_audio_frame_rate;
+       Time _length;
 };
index b0a408c1016a1cfd9bf5307a44975f2fa65e3b72..c87e27ba3311f8887b953711f4746412df6ec63d 100644 (file)
@@ -62,8 +62,6 @@ Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
        , _have_valid_pieces (false)
        , _position (0)
        , _audio_buffers (MAX_AUDIO_CHANNELS, 0)
-       , _last_video (0)
-       , _last_was_black (false)
        , _next_audio (0)
 {
        _playlist->Changed.connect (bind (&Player::playlist_changed, this));
@@ -104,7 +102,7 @@ Player::pass ()
         shared_ptr<Piece> earliest;
 
        for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
-               if ((*i)->content->end(_film) < _position) {
+               if ((*i)->content->end() < _position) {
                        continue;
                }
                
@@ -124,7 +122,7 @@ Player::pass ()
        /* Move position to earliest active next emission */
 
        for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
-               if ((*i)->content->end(_film) < _position) {
+               if ((*i)->content->end() < _position) {
                        continue;
                }
 
@@ -200,6 +198,16 @@ Player::seek (Time t)
                return;
        }
 
+       for (list<shared_ptr<Piece> >::iterator i = _pieces.begin(); i != _pieces.end(); ++i) {
+               if ((*i)->content->end() < t) {
+                       continue;
+               }
+
+               (*i)->decoder->seek (t);
+       }
+
+       _position = t;
+       
        /* XXX: don't seek audio because we don't need to... */
 }
 
@@ -290,18 +298,18 @@ Player::setup_pieces ()
                if (dynamic_pointer_cast<VideoContent> ((*i)->content)) {
                        Time const diff = video_pos - (*i)->content->start();
                        if (diff > 0) {
-                               shared_ptr<NullContent> nc (new NullContent (video_pos, diff));
+                               shared_ptr<NullContent> nc (new NullContent (_film, video_pos, diff));
                                _pieces.push_back (shared_ptr<Piece> (new Piece (nc, shared_ptr<Decoder> (new BlackDecoder (_film, nc)))));
                        }
                                                
-                       video_pos = (*i)->content->start() + (*i)->content->length(_film);
+                       video_pos = (*i)->content->end();
                } else {
                        Time const diff = audio_pos - (*i)->content->start();
                        if (diff > 0) {
-                               shared_ptr<NullContent> nc (new NullContent (audio_pos, diff));
+                               shared_ptr<NullContent> nc (new NullContent (_film, audio_pos, diff));
                                _pieces.push_back (shared_ptr<Piece> (new Piece (nc, shared_ptr<Decoder> (new SilenceDecoder (_film, nc)))));
                        }
-                       audio_pos = (*i)->content->start() + (*i)->content->length(_film);
+                       audio_pos = (*i)->content->end();
                }
        }
 
index c8f6eecb87f9eba46d9d8bc6a3bb029803a39940..a5fe844f0af88ca76321c5163c8afa5fa18134dc 100644 (file)
@@ -56,8 +56,8 @@ public:
        void seek_back ();
        void seek_forward ();
 
-       Time last_video () const {
-               return _last_video;
+       Time position () const {
+               return _position;
        }
 
 private:
@@ -81,13 +81,7 @@ private:
 
        /** Time of the earliest thing not yet to have been emitted */
        Time _position;
-       Time _last_black;
-       Time _last_silence;
-
-       /* XXX: position and last_video? Need both? */
        AudioBuffers _audio_buffers;
-       Time _last_video;
-       bool _last_was_black;
        Time _next_audio;
 };
 
index 36d6c6b52d789c2f33020b950e49e37efb486c77..7ab320558b01324e78cfe2d821f0d6379bbc1eb1 100644 (file)
@@ -122,7 +122,7 @@ Playlist::video_digest () const
 
 /** @param node <Playlist> node */
 void
-Playlist::set_from_xml (shared_ptr<const cxml::Node> node)
+Playlist::set_from_xml (shared_ptr<const Film> film, shared_ptr<const cxml::Node> node)
 {
        list<shared_ptr<cxml::Node> > c = node->node_children ("Content");
        for (list<shared_ptr<cxml::Node> >::iterator i = c.begin(); i != c.end(); ++i) {
@@ -131,11 +131,11 @@ Playlist::set_from_xml (shared_ptr<const cxml::Node> node)
                boost::shared_ptr<Content> content;
 
                if (type == "FFmpeg") {
-                       content.reset (new FFmpegContent (*i));
+                       content.reset (new FFmpegContent (film, *i));
                } else if (type == "ImageMagick") {
-                       content.reset (new ImageMagickContent (*i));
+                       content.reset (new ImageMagickContent (film, *i));
                } else if (type == "Sndfile") {
-                       content.reset (new SndfileContent (*i));
+                       content.reset (new SndfileContent (film, *i));
                }
 
                _content.push_back (content);
@@ -261,11 +261,11 @@ Playlist::best_dcp_frame_rate () const
 }
 
 Time
-Playlist::length (shared_ptr<const Film> film) const
+Playlist::length () const
 {
        Time len = 0;
        for (ContentList::const_iterator i = _content.begin(); i != _content.end(); ++i) {
-               len = max (len, (*i)->end (film));
+               len = max (len, (*i)->end ());
        }
 
        return len;
index e8cac0247d46877ea5e73bfa5771eafa2699d574..aff6017fad640101241bf0e3ed8ba9e9fbfe1f7d 100644 (file)
@@ -61,7 +61,7 @@ public:
        ~Playlist ();
 
        void as_xml (xmlpp::Node *);
-       void set_from_xml (boost::shared_ptr<const cxml::Node>);
+       void set_from_xml (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
 
        void add (boost::shared_ptr<Content>);
        void remove (boost::shared_ptr<Content>);
@@ -83,7 +83,7 @@ public:
        
        void set_loop (int l);
 
-       Time length (boost::shared_ptr<const Film>) const;
+       Time length () const;
        int best_dcp_frame_rate () const;
 
        mutable boost::signals2::signal<void ()> Changed;
diff --git a/src/lib/silence_decoder.cc b/src/lib/silence_decoder.cc
new file mode 100644 (file)
index 0000000..9eee5bb
--- /dev/null
@@ -0,0 +1,56 @@
+/*
+    Copyright (C) 2013 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
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+
+*/
+
+#include "silence_decoder.h"
+#include "null_content.h"
+#include "audio_buffers.h"
+
+using std::min;
+using boost::shared_ptr;
+
+SilenceDecoder::SilenceDecoder (shared_ptr<const Film> f, shared_ptr<NullContent> c)
+       : Decoder (f)
+       , AudioDecoder (f, c)
+{
+       
+}
+
+void
+SilenceDecoder::pass ()
+{
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
+       Time const this_time = min (_audio_content->length() - _next_audio, TIME_HZ / 2);
+       shared_ptr<AudioBuffers> data (new AudioBuffers (MAX_AUDIO_CHANNELS, film->time_to_audio_frames (this_time)));
+       data->make_silent ();
+       audio (data, _next_audio);
+}
+
+void
+SilenceDecoder::seek (Time t)
+{
+       _next_audio = t;
+}
+
+Time
+SilenceDecoder::next () const
+{
+       return _next_audio;
+}
index eec3c8ed97bca2ebeb57cb9f106dacca0a1e3dbd..e2a004d618543da126246adcdf29b51741db9843 100644 (file)
 
 */
 
+#include <boost/shared_ptr.hpp>
+#include "audio_decoder.h"
+
+class Film;
+class NullContent;
+
 class SilenceDecoder : public AudioDecoder
 {
 public:
index 758ae942d4463c5dbcb67c2fddcb03e99d99ed92..0f895c95e109b28ddd57b7007e3d6264fd33cd32 100644 (file)
@@ -33,9 +33,9 @@ using std::cout;
 using boost::shared_ptr;
 using boost::lexical_cast;
 
-SndfileContent::SndfileContent (boost::filesystem::path f)
-       : Content (f)
-       , AudioContent (f)
+SndfileContent::SndfileContent (shared_ptr<const Film> f, boost::filesystem::path p)
+       : Content (f, p)
+       , AudioContent (f, p)
        , _audio_channels (0)
        , _audio_length (0)
        , _audio_frame_rate (0)
@@ -43,9 +43,9 @@ SndfileContent::SndfileContent (boost::filesystem::path f)
 
 }
 
-SndfileContent::SndfileContent (shared_ptr<const cxml::Node> node)
-       : Content (node)
-       , AudioContent (node)
+SndfileContent::SndfileContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+       : Content (f, node)
+       , AudioContent (f, node)
 {
        _audio_channels = node->number_child<int> ("AudioChannels");
        _audio_length = node->number_child<ContentAudioFrame> ("AudioLength");
@@ -93,10 +93,13 @@ SndfileContent::clone () const
 }
 
 void
-SndfileContent::examine (shared_ptr<Film> film, shared_ptr<Job> job)
+SndfileContent::examine (shared_ptr<Job> job)
 {
        job->set_progress_unknown ();
-       Content::examine (film, job);
+       Content::examine (job);
+
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
 
        SndfileDecoder dec (film, shared_from_this());
 
@@ -122,15 +125,20 @@ SndfileContent::as_xml (xmlpp::Node* node) const
        node->add_child("AudioFrameRate")->add_child_text (lexical_cast<string> (_audio_frame_rate));
 }
 
-int
-SndfileContent::output_audio_frame_rate (shared_ptr<const Film>) const
+Time
+SndfileContent::length () const
 {
-       /* Resample to a DCI-approved sample rate */
-       return dcp_audio_frame_rate (content_audio_frame_rate ());
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
+       return film->audio_frames_to_time (audio_length ());
 }
 
-Time
-SndfileContent::length (shared_ptr<const Film> film) const
+int
+SndfileContent::output_audio_frame_rate () const
 {
-       return film->audio_frames_to_time (audio_length ());
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       
+       return film->dcp_audio_frame_rate ();
 }
index bb7fa5f50198ae39f00b9aae417f1005ac973dfc..17423b8edd76acd053f34568190a2629a220218d 100644 (file)
@@ -31,19 +31,19 @@ namespace cxml {
 class SndfileContent : public AudioContent
 {
 public:
-       SndfileContent (boost::filesystem::path);
-       SndfileContent (boost::shared_ptr<const cxml::Node>);
+       SndfileContent (boost::shared_ptr<const Film>, boost::filesystem::path);
+       SndfileContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
 
        boost::shared_ptr<SndfileContent> shared_from_this () {
                return boost::dynamic_pointer_cast<SndfileContent> (Content::shared_from_this ());
        }
        
-       void examine (boost::shared_ptr<Film>, boost::shared_ptr<Job>);
+       void examine (boost::shared_ptr<Job>);
        std::string summary () const;
        std::string information () const;
        void as_xml (xmlpp::Node *) const;
        boost::shared_ptr<Content> clone () const;
-       Time length (boost::shared_ptr<const Film>) const;
+       Time length () const;
 
         /* AudioContent */
         int audio_channels () const {
@@ -61,7 +61,7 @@ public:
                return _audio_frame_rate;
        }
 
-        int output_audio_frame_rate (boost::shared_ptr<const Film>) const;
+       int output_audio_frame_rate () const;
 
        AudioMapping audio_mapping () const {
                boost::mutex::scoped_lock lm (_mutex);
index 4b8b8072d909caa311db52b815da8c888f6448cf..8f2fe2c7165c6a3be02df80441b94877f99a6f84 100644 (file)
@@ -31,7 +31,7 @@ typedef int64_t ContentAudioFrame;
 typedef int     ContentVideoFrame;
 typedef int64_t Time;
 #define TIME_MAX INT64_MAX
-#define TIME_HZ  96000
+#define TIME_HZ  ((Time) 96000)
 typedef int64_t OutputAudioFrame;
 typedef int     OutputVideoFrame;
 
index e077730483988725fd0fb116c1119210bc38357f..2e413678f5d0aa219a91157b8162b8a0594fd3f5 100644 (file)
@@ -34,22 +34,22 @@ using std::setprecision;
 using boost::shared_ptr;
 using boost::lexical_cast;
 
-VideoContent::VideoContent (Time s, ContentVideoFrame len)
-       : Content (s)
+VideoContent::VideoContent (shared_ptr<const Film> f, Time s, ContentVideoFrame len)
+       : Content (f, s)
        , _video_length (len)
 {
 
 }
 
-VideoContent::VideoContent (boost::filesystem::path f)
-       : Content (f)
+VideoContent::VideoContent (shared_ptr<const Film> f, boost::filesystem::path p)
+       : Content (f, p)
        , _video_length (0)
 {
 
 }
 
-VideoContent::VideoContent (shared_ptr<const cxml::Node> node)
-       : Content (node)
+VideoContent::VideoContent (shared_ptr<const Film> f, shared_ptr<const cxml::Node> node)
+       : Content (f, node)
 {
        _video_length = node->number_child<ContentVideoFrame> ("VideoLength");
        _video_size.width = node->number_child<int> ("VideoWidth");
index 8b0461e3fb3ab1349ca03d7ba789cef7b6853a0a..7dde927af0bd14d8103fb96c4c3430c4f7a08c54 100644 (file)
@@ -37,9 +37,9 @@ public:
 class VideoContent : public virtual Content
 {
 public:
-       VideoContent (Time);
-       VideoContent (boost::filesystem::path);
-       VideoContent (boost::shared_ptr<const cxml::Node>);
+       VideoContent (boost::shared_ptr<const Film>, Time, ContentVideoFrame);
+       VideoContent (boost::shared_ptr<const Film>, boost::filesystem::path);
+       VideoContent (boost::shared_ptr<const Film>, boost::shared_ptr<const cxml::Node>);
        VideoContent (VideoContent const &);
 
        void as_xml (xmlpp::Node *) const;
index 0f1432907fec5203f59ab54de62f5993786fbb6d..b31766b5080ba8b6abf378cdf594bc391e33a967 100644 (file)
@@ -46,9 +46,9 @@ protected:
        void subtitle (boost::shared_ptr<TimedSubtitle>);
 
        Time _next_video;
+       boost::shared_ptr<const VideoContent> _video_content;
 
 private:
-       boost::shared_ptr<const VideoContent> _video_content;
        boost::shared_ptr<TimedSubtitle> _timed_subtitle;
        FrameRateConversion _frame_rate_conversion;
        bool _odd;
index 1da2454841bc8c047ba0df18ee29b25c1312cca6..e7349a9c4d71149588ab867b4b303955ca2214f5 100644 (file)
@@ -11,6 +11,7 @@ sources = """
           audio_decoder.cc
           audio_mapping.cc
           audio_source.cc
+          black_decoder.cc
           config.cc
           combiner.cc
           container.cc
@@ -38,11 +39,13 @@ sources = """
           job_manager.cc
           log.cc
           lut.cc
+          null_content.cc
           player.cc
           playlist.cc
           scp_dcp_job.cc
           scaler.cc
           server.cc
+          silence_decoder.cc
           sndfile_content.cc
           sndfile_decoder.cc
           sound_processor.cc
index 71c29072f43c4009ee15e6d6bf3cff4d15e5fcfc..50dd08245c73ddfe468d407e243da66415711b4a 100644 (file)
@@ -312,7 +312,8 @@ private:
                        }
                        
                        maybe_save_then_delete_film ();
-                       film.reset (new Film (d->get_path (), false));
+                       film.reset (new Film (d->get_path ()));
+                       film->write_metadata ();
                        film->log()->set_level (log_level);
                        film->set_name (boost::filesystem::path (d->get_path()).filename().generic_string());
                        set_film ();
@@ -497,6 +498,7 @@ class App : public wxApp
                if (!film_to_load.empty() && boost::filesystem::is_directory (film_to_load)) {
                        try {
                                film.reset (new Film (film_to_load));
+                               film->read_metadata ();
                                film->log()->set_level (log_level);
                        } catch (exception& e) {
                                error_dialog (0, std_to_wx (String::compose (wx_to_std (_("Could not load film %1 (%2)")), film_to_load, e.what())));
@@ -504,7 +506,8 @@ class App : public wxApp
                }
 
                if (!film_to_create.empty ()) {
-                       film.reset (new Film (film_to_create, false));
+                       film.reset (new Film (film_to_create));
+                       film->write_metadata ();
                        film->log()->set_level (log_level);
                        film->set_name (boost::filesystem::path (film_to_create).filename().generic_string ());
                }
index 2b0826bc156455dd19ed5e6acd8119a5828f635b..403c1c21b7273556a805c6eb4950249fd0fec1f9 100644 (file)
@@ -177,6 +177,7 @@ private:
                if (r == wxID_OK) {
                        try {
                                shared_ptr<Film> film (new Film (wx_to_std (c->GetPath ())));
+                               film->read_metadata ();
                                film->make_dcp ();
                        } catch (std::exception& e) {
                                wxString p = c->GetPath ();
index d4a4210dee560549db7868319b9fb28e8c6d8442..bc95f622da36f6cbfd7fb286ec03ff6d4e5efb4e 100644 (file)
@@ -125,7 +125,8 @@ main (int argc, char* argv[])
 
        shared_ptr<Film> film;
        try {
-               film.reset (new Film (film_dir, true));
+               film.reset (new Film (film_dir));
+               film->read_metadata ();
        } catch (std::exception& e) {
                cerr << argv[0] << ": error reading film `" << film_dir << "' (" << e.what() << ")\n";
                exit (EXIT_FAILURE);
index af176ac18e6b02ea011cc526bd3a4a581b49e128..88974eed731e6be7334a6dd0ab57d473dbb15583 100644 (file)
@@ -148,7 +148,8 @@ main (int argc, char* argv[])
        dcpomatic_setup ();
 
        server = new ServerDescription (server_host, 1);
-       shared_ptr<Film> film (new Film (film_dir, true));
+       shared_ptr<Film> film (new Film (film_dir));
+       film->read_metadata ();
 
        shared_ptr<Player> player = film->player ();
        player->disable_audio ();
index 80d069ae5b799f8dc506d3f356351440b21926eb..0857b780a4d3f67525d1726f6054a2c19fb5eb0d 100644 (file)
@@ -1077,11 +1077,11 @@ FilmEditor::content_add_clicked (wxCommandEvent &)
                boost::filesystem::path p (wx_to_std (paths[i]));
 
                if (ImageMagickContent::valid_file (p)) {
-                       _film->add_content (shared_ptr<ImageMagickContent> (new ImageMagickContent (p)));
+                       _film->add_content (shared_ptr<ImageMagickContent> (new ImageMagickContent (_film, p)));
                } else if (SndfileContent::valid_file (p)) {
-                       _film->add_content (shared_ptr<SndfileContent> (new SndfileContent (p)));
+                       _film->add_content (shared_ptr<SndfileContent> (new SndfileContent (_film, p)));
                } else {
-                       _film->add_content (shared_ptr<FFmpegContent> (new FFmpegContent (p)));
+                       _film->add_content (shared_ptr<FFmpegContent> (new FFmpegContent (_film, p)));
                }
        }
 }
index f64e8d92bacd3c01947298edb6959826f7e07aaf..13776110c49503c683f8a25c4c778d3a06b743c5 100644 (file)
@@ -186,7 +186,7 @@ FilmViewer::update_from_decoder ()
                return;
        }
 
-       _player->seek (_player->last_video ());
+       _player->seek (_player->position ());
        get_frame ();
        _panel->Refresh ();
        _panel->Update ();
@@ -205,7 +205,7 @@ FilmViewer::timer (wxTimerEvent &)
        get_frame ();
 
        if (_film->length()) {
-               int const new_slider_position = 4096 * _player->last_video() / _film->length();
+               int const new_slider_position = 4096 * _player->position() / _film->length();
                if (new_slider_position != _slider->GetValue()) {
                        _slider->SetValue (new_slider_position);
                }
index e5457020fd561ee4f5802ef001fed3f920cbeff7..eff686a354564a2f0e126f86e5172bf7d2723c24 100644 (file)
@@ -75,7 +75,7 @@ public:
                }
 
                Time const start = content->start ();
-               Time const len = content->length (film);
+               Time const len = content->length ();
 
                gc->SetPen (*wxBLACK_PEN);
                
@@ -127,7 +127,7 @@ public:
                return Rect (
                        time_x (content->start ()),
                        y_pos (_track),
-                       content->length (film) * _timeline.pixels_per_time_unit(),
+                       content->length () * _timeline.pixels_per_time_unit(),
                        _timeline.track_height()
                        );
        }
index 68d8611c11a8670a683449d9fca6917606d17129..b6ac4751768d4a3f303084024cd8c12803919016 100644 (file)
@@ -80,7 +80,8 @@ new_test_film (string name)
                boost::filesystem::remove_all (p);
        }
        
-       return shared_ptr<Film> (new Film (p.string(), false));
+       shared_ptr<Film> f = shared_ptr<Film> (new Film (p.string()));
+       f->write_metadata ();
 }
 
 
@@ -134,9 +135,8 @@ BOOST_AUTO_TEST_CASE (film_metadata_test)
                boost::filesystem::remove_all (test_film);
        }
 
-       BOOST_CHECK_THROW (new Film (test_film, true), OpenFileError);
-       
-       shared_ptr<Film> f (new Film (test_film, false));
+       shared_ptr<Film> f (new Film (test_film));
+       f->write_metadata ();
        f->_dci_date = boost::gregorian::from_undelimited_string ("20130211");
        BOOST_CHECK (f->container() == 0);
        BOOST_CHECK (f->dcp_content_type() == 0);
@@ -157,7 +157,8 @@ BOOST_AUTO_TEST_CASE (film_metadata_test)
        s << "diff -u test/metadata.ref " << test_film << "/metadata";
        BOOST_CHECK_EQUAL (::system (s.str().c_str ()), 0);
 
-       shared_ptr<Film> g (new Film (test_film, true));
+       shared_ptr<Film> g (new Film (test_film));
+       g->read_metadata ();
 
        BOOST_CHECK_EQUAL (g->name(), "fred");
        BOOST_CHECK_EQUAL (g->dcp_content_type(), DCPContentType::from_pretty_name ("Short"));