Some more tidying up.
authorCarl Hetherington <cth@carlh.net>
Thu, 23 May 2013 07:07:38 +0000 (08:07 +0100)
committerCarl Hetherington <cth@carlh.net>
Thu, 23 May 2013 07:07:38 +0000 (08:07 +0100)
21 files changed:
src/lib/ab_transcoder.cc
src/lib/analyse_audio_job.cc
src/lib/analyse_audio_job.h
src/lib/audio_decoder.cc
src/lib/combiner.cc
src/lib/combiner.h
src/lib/decoder.h
src/lib/ffmpeg_decoder.cc
src/lib/ffmpeg_decoder.h
src/lib/filter_graph.cc
src/lib/filter_graph.h
src/lib/imagemagick_decoder.cc
src/lib/imagemagick_decoder.h
src/lib/player.cc
src/lib/player.h
src/lib/processor.h [deleted file]
src/lib/sndfile_decoder.cc
src/lib/sndfile_decoder.h
src/lib/video_decoder.cc
src/lib/video_decoder.h
src/lib/video_source.h

index 91c4665a783574736aa48e9e78a8b0264f1539f4..1ec29862603a437192d1a60fed093555171e0c51 100644 (file)
@@ -48,7 +48,7 @@ ABTranscoder::ABTranscoder (shared_ptr<Film> film_a, shared_ptr<Film> film_b, sh
        , _player_b (film_b->player ())
        , _job (j)
        , _encoder (new Encoder (film_a, j))
-       , _combiner (new Combiner (film_a->log()))
+       , _combiner (new Combiner)
 {
        _player_a->Video.connect (bind (&Combiner::process_video, _combiner, _1, _2, _3, _4));
        _player_b->Video.connect (bind (&Combiner::process_video_b, _combiner, _1, _2, _3, _4));
index 0ed33827c89b1969ee07610317094b2be1bba373..433b6c98fa800a36d812aa41588b83d849fa06fd 100644 (file)
@@ -35,7 +35,7 @@ int const AnalyseAudioJob::_num_points = 1024;
 
 AnalyseAudioJob::AnalyseAudioJob (shared_ptr<Film> f)
        : Job (f)
-       , _done (0)
+       , _next (0)
        , _samples_per_point (1)
 {
 
@@ -53,15 +53,16 @@ AnalyseAudioJob::run ()
        shared_ptr<Player> player = _film->player ();
        player->disable_video ();
        
-       player->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1));
+       player->Audio.connect (bind (&AnalyseAudioJob::audio, this, _1, _2));
 
        _samples_per_point = max (int64_t (1), _film->time_to_audio_frames (_film->length()) / _num_points);
 
        _current.resize (MAX_AUDIO_CHANNELS);
        _analysis.reset (new AudioAnalysis (MAX_AUDIO_CHANNELS));
-                        
-       while (!player->pass()) {
-               set_progress (float (_done) / _film->time_to_audio_frames (_film->length ()));
+
+       _next = 0;
+       while (_next < _film->length()) {
+               set_progress (double (_next) / _film->length ());
        }
 
        _analysis->write (_film->audio_analysis_path ());
@@ -71,7 +72,7 @@ AnalyseAudioJob::run ()
 }
 
 void
-AnalyseAudioJob::audio (shared_ptr<const AudioBuffers> b)
+AnalyseAudioJob::audio (shared_ptr<const AudioBuffers> b, Time t)
 {
        for (int i = 0; i < b->frames(); ++i) {
                for (int j = 0; j < b->channels(); ++j) {
@@ -91,8 +92,8 @@ AnalyseAudioJob::audio (shared_ptr<const AudioBuffers> b)
                                _current[j] = AudioPoint ();
                        }
                }
-
-               ++_done;
        }
+
+       _next = (t + _film->audio_frames_to_time (b->frames()));
 }
 
index 5435e0a7cfb5401fe5efc2901ac367f7b23c1826..45bf109cc32a1c3589e5285df6713f84416c82b2 100644 (file)
@@ -19,6 +19,7 @@
 
 #include "job.h"
 #include "audio_analysis.h"
+#include "types.h"
 
 class AudioBuffers;
 
@@ -33,7 +34,7 @@ public:
 private:
        void audio (boost::shared_ptr<const AudioBuffers>);
 
-       int64_t _done;
+       Time _next;
        int64_t _samples_per_point;
        std::vector<AudioPoint> _current;
 
index fbc66c335bf21ec149335e28e029c94e09f03de1..c33f68c01c0c0bd3e910c8e46b08774772c8688a 100644 (file)
@@ -36,9 +36,12 @@ AudioDecoder::AudioDecoder (shared_ptr<const Film> f, shared_ptr<const AudioCont
 {
        if (_audio_content->content_audio_frame_rate() != _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);
-               _film->log()->log (s.str ());
+               film->log()->log (s.str ());
 
                /* We will be using planar float data when we call the
                   resampler.  As far as I can see, the audio channel
@@ -79,7 +82,10 @@ AudioDecoder::process_end ()
 {
        if (_swr_context) {
 
-               shared_ptr<AudioBuffers> out (new AudioBuffers (_film->audio_mapping().dcp_channels(), 256));
+               shared_ptr<const Film> film = _film.lock ();
+               assert (film);
+               
+               shared_ptr<AudioBuffers> out (new AudioBuffers (film->audio_mapping().dcp_channels(), 256));
                        
                while (1) {
                        int const frames = swr_convert (_swr_context, (uint8_t **) out->data(), 256, 0, 0);
@@ -130,7 +136,9 @@ AudioDecoder::emit_audio (shared_ptr<const AudioBuffers> data, Time time)
 
        Audio (data, time);
 
-       _next_audio = time + _film->audio_frames_to_time (data->frames());
+       shared_ptr<const Film> film = _film.lock ();
+       assert (film);
+       _next_audio = time + film->audio_frames_to_time (data->frames());
 }
 
                
index 0afb9807ac74a6618b3759a47dcf38ca6dc835ae..db490fd34111ce86e56fe0c05d2ba5fa8d76bdc6 100644 (file)
@@ -22,8 +22,7 @@
 
 using boost::shared_ptr;
 
-Combiner::Combiner (shared_ptr<Log> log)
-       : VideoProcessor (log)
+Combiner::Combiner ()
 {
 
 }
index 062297f0dca31824f2ff262c2d7cf9a9fc318c24..1b7537d42b0eff64d6c85a4c408366fd84385179 100644 (file)
  *  @brief Class for combining two video streams.
  */
 
-#include "processor.h"
+#include "video_source.h"
+#include "video_sink.h"
 
 /** @class Combiner
  *  @brief A class which can combine two video streams into one, with
  *  one image used for the left half of the screen and the other for
  *  the right.
  */
-class Combiner : public VideoProcessor
+class Combiner : public VideoSource, public VideoSink
 {
 public:
-       Combiner (boost::shared_ptr<Log> log);
+       Combiner ();
 
        void process_video (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s, Time);
        void process_video_b (boost::shared_ptr<const Image> i, bool, boost::shared_ptr<Subtitle> s, Time);
index 668e44d380caf3c6cd85a7b76175952568ec2b4b..be9555dc4ffccb21b1c45ebd3d7fda4880d96e13 100644 (file)
@@ -58,7 +58,7 @@ public:
         *  expressed relative to our source's start.
         *  @param t Time.
         */
-       virtual void seek (Time t) {}
+       virtual void seek (Time) {}
 
        /** Seek back one video frame */
        virtual void seek_back () {}
index c0867095fed9c5279b15fb794abeaa0d59faa268..f7bb979441870c707454df55e23ed15c94dfc926 100644 (file)
@@ -222,7 +222,7 @@ FFmpegDecoder::setup_subtitle ()
 }
 
 
-bool
+void
 FFmpegDecoder::pass ()
 {
        int r = av_read_frame (_format_context, &_packet);
@@ -232,7 +232,9 @@ FFmpegDecoder::pass ()
                        /* Maybe we should fail here, but for now we'll just finish off instead */
                        char buf[256];
                        av_strerror (r, buf, sizeof(buf));
-                       _film->log()->log (String::compose (N_("error on av_read_frame (%1) (%2)"), buf, r));
+                       shared_ptr<const Film> film = _film.lock ();
+                       assert (film);
+                       film->log()->log (String::compose (N_("error on av_read_frame (%1) (%2)"), buf, r));
                }
 
                /* Get any remaining frames */
@@ -250,7 +252,7 @@ FFmpegDecoder::pass ()
                        decode_audio_packet ();
                }
                        
-               return true;
+               return;
        }
 
        avcodec_get_frame_defaults (_frame);
@@ -270,19 +272,18 @@ FFmpegDecoder::pass ()
                        if (sub.num_rects > 0) {
                                shared_ptr<TimedSubtitle> ts;
                                try {
-                                       emit_subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub)));
+                                       subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub)));
                                } catch (...) {
                                        /* some problem with the subtitle; we probably didn't understand it */
                                }
                        } else {
-                               emit_subtitle (shared_ptr<TimedSubtitle> ());
+                               subtitle (shared_ptr<TimedSubtitle> ());
                        }
                        avsubtitle_free (&sub);
                }
        }
 
        av_free_packet (&_packet);
-       return false;
 }
 
 /** @param data pointer to array of pointers to buffers.
@@ -404,17 +405,11 @@ FFmpegDecoder::audio_sample_format () const
 }
 
 libdcp::Size
-FFmpegDecoder::native_size () const
+FFmpegDecoder::video_size () const
 {
        return libdcp::Size (_video_codec_context->width, _video_codec_context->height);
 }
 
-PixelFormat
-FFmpegDecoder::pixel_format () const
-{
-       return _video_codec_context->pix_fmt;
-}
-
 string
 FFmpegDecoder::stream_name (AVStream* s) const
 {
@@ -448,38 +443,37 @@ FFmpegDecoder::bytes_per_audio_sample () const
        return av_get_bytes_per_sample (audio_sample_format ());
 }
 
-bool
+void
 FFmpegDecoder::seek (Time t)
 {
-       return do_seek (t, false, false);
+       do_seek (t, false, false);
 }
 
-bool
+void
 FFmpegDecoder::seek_back ()
 {
        if (next() < 2.5) {
-               return true;
+               return;
        }
        
-       return do_seek (next() - 2.5 * TIME_HZ / video_frame_rate(), true, true);
+       do_seek (next() - 2.5 * TIME_HZ / video_frame_rate(), true, true);
 }
 
-bool
+void
 FFmpegDecoder::seek_forward ()
 {
        if (next() >= (video_length() - video_frame_rate())) {
-               return true;
+               return;
        }
        
-       return do_seek (next() - 0.5 * TIME_HZ / video_frame_rate(), true, true);
+       do_seek (next() - 0.5 * TIME_HZ / video_frame_rate(), true, true);
 }
 
-bool
+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);
-
-       int const r = av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0);
+       av_seek_frame (_format_context, _video_stream, vt, backwards ? AVSEEK_FLAG_BACKWARD : 0);
 
        avcodec_flush_buffers (_video_codec_context);
        if (_subtitle_codec_context) {
@@ -490,7 +484,7 @@ FFmpegDecoder::do_seek (Time t, bool backwards, bool accurate)
                while (1) {
                        int r = av_read_frame (_format_context, &_packet);
                        if (r < 0) {
-                               return true;
+                               return;
                        }
                        
                        avcodec_get_frame_defaults (_frame);
@@ -510,7 +504,7 @@ FFmpegDecoder::do_seek (Time t, bool backwards, bool accurate)
                }
        }
 
-       return r < 0;
+       return;
 }
 
 void
@@ -590,7 +584,10 @@ FFmpegDecoder::decode_video_packet ()
        if (i == _filter_graphs.end ()) {
                graph.reset (new FilterGraph (_film, this, libdcp::Size (_frame->width, _frame->height), (AVPixelFormat) _frame->format));
                _filter_graphs.push_back (graph);
-               _film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format));
+
+               shared_ptr<const Film> film = _film.lock ();
+               assert (film);
+               film->log()->log (String::compose (N_("New graph for %1x%2, pixel format %3"), _frame->width, _frame->height, _frame->format));
        } else {
                graph = *i;
        }
@@ -605,9 +602,11 @@ FFmpegDecoder::decode_video_packet ()
                           (as per old Matcher)
                        */
                        Time const t = bet * av_q2d (_format_context->streams[_video_stream]->time_base) * TIME_HZ;
-                       emit_video (*i, false, t);
+                       video (*i, false, t);
                } else {
-                       _film->log()->log ("Dropping frame without PTS");
+                       shared_ptr<const Film> film = _film.lock ();
+                       assert (film);
+                       film->log()->log ("Dropping frame without PTS");
                }
        }
 
index 3b629e3ae56afe281842aebc6bf0d16dd4f41c4c..dbcfe3be01017816205934e2bd8c72a3a1aa2ab4 100644 (file)
@@ -62,16 +62,22 @@ public:
        FFmpegDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const FFmpegContent>, bool video, bool audio, bool subtitles);
        ~FFmpegDecoder ();
 
-       bool pass ();
-       bool seek (Time);
-       bool seek_back ();
-       bool seek_forward ();
+       /* Decoder */
+
+       void pass ();
+       void seek (Time);
+       void seek_back ();
+       void seek_forward ();
        Time next () const;
 
+       /* VideoDecoder */
+
        float video_frame_rate () const;
-       libdcp::Size native_size () const;
+       libdcp::Size video_size () const;
        ContentVideoFrame video_length () const;
 
+       /* FFmpegDecoder */
+
        std::vector<boost::shared_ptr<FFmpegSubtitleStream> > subtitle_streams () const {
                return _subtitle_streams;
        }
@@ -93,7 +99,7 @@ private:
        PixelFormat pixel_format () const;
        AVSampleFormat audio_sample_format () const;
        int bytes_per_audio_sample () const;
-       bool do_seek (Time, bool, bool);
+       void do_seek (Time, bool, bool);
 
        void setup_general ();
        void setup_video ();
index 4a91349cb2345f75d7b8e65bc9382e6cba9b944f..df8f1e9ddef2c14956633dbc6dbb2e010eb77b82 100644 (file)
@@ -49,6 +49,7 @@ using std::stringstream;
 using std::string;
 using std::list;
 using boost::shared_ptr;
+using boost::weak_ptr;
 using libdcp::Size;
 
 /** Construct a FilterGraph for the settings in a film.
@@ -57,19 +58,22 @@ using libdcp::Size;
  *  @param s Size of the images to process.
  *  @param p Pixel format of the images to process.
  */
-FilterGraph::FilterGraph (shared_ptr<const Film> film, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p)
+FilterGraph::FilterGraph (weak_ptr<const Film> weak_film, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p)
        : _buffer_src_context (0)
        , _buffer_sink_context (0)
        , _size (s)
        , _pixel_format (p)
 {
+       shared_ptr<const Film> film = weak_film.lock ();
+       assert (film);
+       
        string filters = Filter::ffmpeg_strings (film->filters()).first;
        if (!filters.empty ()) {
                filters += N_(",");
        }
 
        Crop crop = decoder->ffmpeg_content()->crop ();
-       libdcp::Size cropped_size = decoder->native_size ();
+       libdcp::Size cropped_size = decoder->video_size ();
        cropped_size.width -= crop.left + crop.right;
        cropped_size.height -= crop.top + crop.bottom;
        filters += crop_string (Position (crop.left, crop.top), cropped_size);
index 1ff5527ab827c868a8056ccb4e69226f64079681..c7a01f58e1f66c446c3c1ce21390d200bb182790 100644 (file)
@@ -37,7 +37,7 @@ class FFmpegDecoder;
 class FilterGraph
 {
 public:
-       FilterGraph (boost::shared_ptr<const Film>, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p);
+       FilterGraph (boost::weak_ptr<const Film>, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p);
 
        bool can_process (libdcp::Size s, AVPixelFormat p) const;
        std::list<boost::shared_ptr<Image> > process (AVFrame const * frame);
index ed2db80d8c0dc72a0da62fabc0e213a3a825b4e4..bea4fafa6223ee3e400a110dc7c610c7c2da54ae 100644 (file)
@@ -36,22 +36,21 @@ ImageMagickDecoder::ImageMagickDecoder (shared_ptr<const Film> f, shared_ptr<con
        : Decoder (f)
        , VideoDecoder (f, c)
        , _imagemagick_content (c)
-       , _position (0)
 {
 
 }
 
 libdcp::Size
-ImageMagickDecoder::native_size () const
+ImageMagickDecoder::video_size () const
 {
-       if (!_native_size) {
+       if (!_video_size) {
                using namespace MagickCore;
                Magick::Image* image = new Magick::Image (_imagemagick_content->file().string());
-               _native_size = libdcp::Size (image->columns(), image->rows());
+               _video_size = libdcp::Size (image->columns(), image->rows());
                delete image;
        }
 
-       return _native_size.get ();
+       return _video_size.get ();
 }
 
 int
@@ -60,29 +59,40 @@ ImageMagickDecoder::video_length () const
        return _imagemagick_content->video_length ();
 }
 
-bool
+float
+ImageMagickDecoder::video_frame_rate () const
+{
+       boost::shared_ptr<const Film> f = _film.lock ();
+       if (!f) {
+               return 24;
+       }
+
+       return f->dcp_video_frame_rate ();
+}
+
+void
 ImageMagickDecoder::pass ()
 {
        if (_position < 0 || _position >= _imagemagick_content->video_length ()) {
-               return true;
+               return;
        }
 
        if (_image) {
-               emit_video (_image, true, double (_position) / 24);
+               video (_image, true, double (_position) / video_frame_rate());
                _position++;
-               return false;
+               return;
        }
 
        Magick::Image* magick_image = new Magick::Image (_imagemagick_content->file().string ());
-       _native_size = libdcp::Size (magick_image->columns(), magick_image->rows());
+       _video_size = libdcp::Size (magick_image->columns(), magick_image->rows());
        
-       _image.reset (new SimpleImage (PIX_FMT_RGB24, _native_size.get(), false));
+       _image.reset (new SimpleImage (PIX_FMT_RGB24, _video_size.get(), false));
 
        using namespace MagickCore;
        
        uint8_t* p = _image->data()[0];
-       for (int y = 0; y < _native_size->height; ++y) {
-               for (int x = 0; x < _native_size->width; ++x) {
+       for (int y = 0; y < _video_size->height; ++y) {
+               for (int x = 0; x < _video_size->width; ++x) {
                        Magick::Color c = magick_image->pixelColor (x, y);
                        *p++ = c.redQuantum() * 255 / QuantumRange;
                        *p++ = c.greenQuantum() * 255 / QuantumRange;
@@ -93,7 +103,7 @@ ImageMagickDecoder::pass ()
        delete magick_image;
 
        _image = _image->crop (_imagemagick_content->crop(), true);
-       emit_video (_image, false, double (_position) / 24);
+       video (_image, false, double (_position) / 24);
 
        ++_position;
        return false;
index ba54c0efa28feb41313904bd694d9c88bd5ecf90..74f01d6bba5ac19d60bcdbb77d82ae85bcccc391 100644 (file)
@@ -30,27 +30,26 @@ class ImageMagickDecoder : public VideoDecoder
 public:
        ImageMagickDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const ImageMagickContent>);
 
-       bool pass ();
-       bool seek (double);
+       /* Decoder */
+
+       void pass ();
+       void seek (double);
        Time next () const;
 
-       float video_frame_rate () const {
-               return 24;
-       }
+       /* VideoDecoder */
 
-       libdcp::Size native_size () const;
+       float video_frame_rate () const;
+       libdcp::Size video_size () const;
        ContentVideoFrame video_length () const;
 
+       /* ImageMagickDecoder */
+
        boost::shared_ptr<const ImageMagickContent> content () const {
                return _imagemagick_content;
        }
 
-protected:
-       PixelFormat pixel_format () const;
-
 private:
        boost::shared_ptr<const ImageMagickContent> _imagemagick_content;
        boost::shared_ptr<Image> _image;
-       ContentVideoFrame _position;
-       mutable boost::optional<libdcp::Size> _native_size;
+       mutable boost::optional<libdcp::Size> _video_size;
 };
index eb704f7332fe5ce90b515038ed0c177466d495fa..8ca004689920775b379e5574f142c23ddb48c0ba 100644 (file)
@@ -56,7 +56,7 @@ Player::Player (shared_ptr<const Film> f, shared_ptr<const Playlist> p)
        , _video (true)
        , _audio (true)
        , _subtitles (true)
-       , _have_valid_decoders (false)
+       , _have_valid_pieces (false)
        , _position (0)
        , _audio_buffers (MAX_AUDIO_CHANNELS, 0)
        , _last_video (0)
@@ -138,7 +138,7 @@ Player::pass ()
 void
 Player::process_video (shared_ptr<Piece> piece, shared_ptr<const Image> image, bool same, shared_ptr<Subtitle> sub, Time time)
 {
-       time += piece->start ();
+       time += piece->content->start ();
        
         Video (image, same, sub, time);
 }
@@ -152,7 +152,7 @@ Player::process_audio (shared_ptr<Piece> piece, shared_ptr<const AudioBuffers> a
            be added to any more, so it can be emitted.
         */
 
-       time += piece->start ();
+       time += piece->content->start ();
 
         if (time > _next_audio) {
                 /* We can emit some audio from our buffers */
@@ -175,7 +175,7 @@ Player::process_audio (shared_ptr<Piece> piece, shared_ptr<const AudioBuffers> a
 }
 
 /** @return true on error */
-bool
+void
 Player::seek (Time t)
 {
        if (!_have_valid_pieces) {
@@ -184,12 +184,10 @@ Player::seek (Time t)
        }
 
        if (_pieces.empty ()) {
-               return true;
+               return;
        }
 
        /* XXX: don't seek audio because we don't need to... */
-
-       return false;
 }
 
 
@@ -209,7 +207,7 @@ struct ContentSorter
 {
        bool operator() (shared_ptr<Content> a, shared_ptr<Content> b)
        {
-               return a->time() < b->time();
+               return a->start() < b->start();
        }
 };
 
index 13bdcead479f61677dc4ce428e09d82bca37b7ea..b0179ca7310039e0c3845e7eb240e0f9beca7e62 100644 (file)
@@ -51,8 +51,8 @@ public:
        void disable_audio ();
        void disable_subtitles ();
 
-       bool pass ();
-       bool seek (Time);
+       void pass ();
+       void seek (Time);
        void seek_back ();
        void seek_forward ();
 
diff --git a/src/lib/processor.h b/src/lib/processor.h
deleted file mode 100644 (file)
index 5dbafab..0000000
+++ /dev/null
@@ -1,98 +0,0 @@
-/*
-    Copyright (C) 2012 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.
-
-*/
-
-/** @file  src/processor.h
- *  @brief Parent class for classes which accept and then emit video or audio data.
- */
-
-#ifndef DCPOMATIC_PROCESSOR_H
-#define DCPOMATIC_PROCESSOR_H
-
-#include "video_source.h"
-#include "video_sink.h"
-#include "audio_source.h"
-#include "audio_sink.h"
-
-class Log;
-
-/** @class Processor
- *  @brief Base class for processors.
- */
-class Processor
-{
-public:
-       /** Construct a Processor.
-        *  @param log Log to use.
-        */
-       Processor (boost::shared_ptr<Log> log)
-               : _log (log)
-       {}
-
-       virtual ~Processor() {}
-
-       /** Will be called at the end of a processing run */
-       virtual void process_end () {}
-
-protected:
-       boost::shared_ptr<Log> _log; ///< log to write to
-};
-
-/** @class AudioVideoProcessor
- *  @brief A processor which handles both video and audio data.
- */
-class AudioVideoProcessor : public Processor, public VideoSource, public VideoSink, public AudioSource, public AudioSink
-{
-public:
-       /** Construct an AudioVideoProcessor.
-        *  @param log Log to write to.
-        */
-       AudioVideoProcessor (boost::shared_ptr<Log> log)
-               : Processor (log)
-       {}
-};
-
-/** @class AudioProcessor
- *  @brief A processor which handles just audio data.
- */
-class AudioProcessor : public Processor, public AudioSource, public AudioSink
-{
-public:
-       /** Construct an AudioProcessor.
-        *  @param log Log to write to.
-        */
-       AudioProcessor (boost::shared_ptr<Log> log)
-               : Processor (log)
-       {}
-};
-
-/** @class VideoProcessor
- *  @brief A processor which handles just video data.
- */
-class VideoProcessor : public Processor, public VideoSource, public VideoSink
-{
-public:
-       /** Construct an VideoProcessor.
-        *  @param log Log to write to.
-        */
-       VideoProcessor (boost::shared_ptr<Log> log)
-               : Processor (log)
-       {}
-};
-
-#endif
index 0f2d54d153c971d73344b2ba246b182cea984ed2..b6dac2e765bb89ec0fd17bd3c1ff0c6e91e7e3c1 100644 (file)
@@ -54,7 +54,7 @@ SndfileDecoder::~SndfileDecoder ()
        delete[] _deinterleave_buffer;
 }
 
-bool
+void
 SndfileDecoder::pass ()
 {
        /* Do things in half second blocks as I think there may be limits
@@ -92,8 +92,6 @@ SndfileDecoder::pass ()
        Audio (audio, double(_done) / audio_frame_rate());
        _done += this_time;
        _remaining -= this_time;
-
-       return (_remaining == 0);
 }
 
 int
index 35e50c629483b1f8bdaf8ed1428dd3c2467daca3..a513037d94fed79905a3e1ce489c6ae246eb62c7 100644 (file)
@@ -29,7 +29,7 @@ public:
        SndfileDecoder (boost::shared_ptr<const Film>, boost::shared_ptr<const SndfileContent>);
        ~SndfileDecoder ();
 
-       bool pass ();
+       void pass ();
        Time next ();
 
        int audio_channels () const;
index cb74a7987fead8961b5ae283a4257e550e0ff09c..8bb7f3700ec6a54c51f54ff02e5a13b16ee5606c 100644 (file)
 #include "subtitle.h"
 #include "film.h"
 #include "image.h"
-#include "log.h"
-#include "job.h"
 
 #include "i18n.h"
 
 using std::cout;
 using boost::shared_ptr;
-using boost::optional;
 
 VideoDecoder::VideoDecoder (shared_ptr<const Film> f, shared_ptr<const VideoContent> c)
        : Decoder (f)
        , _next_video (0)
        , _video_content (c)
+       , _frame_rate_conversion (c->video_frame_rate(), f->dcp_frame_rate())
+       , _odd (false)
 {
 
 }
 
-/** Called by subclasses to tell the world that some video data is ready.
- *  We find a subtitle then emit it for listeners.
+/** Called by subclasses when some video is ready.
  *  @param image frame to emit.
+ *  @param same true if this frame is the same as the last one passed to this call.
  *  @param t Time of the frame within the source.
  */
 void
-VideoDecoder::emit_video (shared_ptr<Image> image, bool same, Time t)
+VideoDecoder::video (shared_ptr<Image> image, bool same, Time t)
 {
+       if (_frame_rate_conversion.skip && _odd) {
+               _odd = !_odd;
+               return;
+       }
+
        shared_ptr<Subtitle> sub;
        if (_timed_subtitle && _timed_subtitle->displayed_at (t)) {
                sub = _timed_subtitle->subtitle ();
        }
 
-       TIMING (N_("Decoder emits %1"), _video_frame);
        Video (image, same, sub, t);
-       ++_video_frame;
 
-       /* XXX: who's doing skip / repeat? */
-       _next_video = t + _film->video_frames_to_time (1);
+       if (_frame_rate_conversion.repeat) {
+               Video (image, true, sub, t + _film->video_frames_to_time (1));
+               _next_video = t + _film->video_frames_to_time (2);
+       } else {
+               _next_video = t + _film->video_frames_to_time (1);
+       }
+
+       _odd = !_odd;
 }
 
-/** Set up the current subtitle.  This will be put onto frames that
- *  fit within its time specification.  s may be 0 to say that there
- *  is no current subtitle.
+/** Called by subclasses when a subtitle is ready.
+ *  s may be 0 to say that there is no current subtitle.
  *  @param s New current subtitle, or 0.
  */
 void
-VideoDecoder::emit_subtitle (shared_ptr<TimedSubtitle> s)
+VideoDecoder::subtitle (shared_ptr<TimedSubtitle> s)
 {
        _timed_subtitle = s;
        
index 3a3bc252a8d41ad315b3da277256a881281e278a..0f1432907fec5203f59ab54de62f5993786fbb6d 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "video_source.h"
 #include "decoder.h"
+#include "util.h"
 
 class VideoContent;
 
@@ -41,14 +42,16 @@ public:
 
 protected:
        
-       void emit_video (boost::shared_ptr<Image>, bool, Time);
-       void emit_subtitle (boost::shared_ptr<TimedSubtitle>);
+       void video (boost::shared_ptr<Image>, bool, Time);
+       void subtitle (boost::shared_ptr<TimedSubtitle>);
 
        Time _next_video;
 
 private:
        boost::shared_ptr<const VideoContent> _video_content;
        boost::shared_ptr<TimedSubtitle> _timed_subtitle;
+       FrameRateConversion _frame_rate_conversion;
+       bool _odd;
 };
 
 #endif
index 0b0985c87262f1ad7761741c0139e95d3cf6a41f..c94b5a20a5ccdfe9ef720c276428b5b43880e522 100644 (file)
@@ -33,7 +33,7 @@ class Subtitle;
 class Image;
 
 /** @class VideoSource
- *  @param A class that emits video data without timestamps.
+ *  @param A class that emits video data.
  */
 class VideoSource
 {