Fix mis-alignment of copied AlignedImages; add some asserts; some docs.
authorCarl Hetherington <cth@carlh.net>
Sun, 18 Nov 2012 22:46:15 +0000 (22:46 +0000)
committerCarl Hetherington <cth@carlh.net>
Sun, 18 Nov 2012 22:46:15 +0000 (22:46 +0000)
14 files changed:
doc/mainpage.txt
src/lib/audio_decoder.h
src/lib/audio_sink.h
src/lib/audio_source.h
src/lib/combiner.cc
src/lib/combiner.h
src/lib/film.cc
src/lib/film.h
src/lib/image.cc
src/lib/image.h
src/lib/processor.h
src/lib/util.cc
src/lib/util.h
src/lib/video_source.h

index e89ca8d26a4ae3e79e94d501ab0565c0b527604d..b018c5929c14387fe1af99ab513c8da34272d289 100644 (file)
@@ -5,9 +5,8 @@
  *  and distributed under the GPL.
  *
  *  Video files are decoded using FFmpeg (http://ffmpeg.org), so any video
- *  supported by FFmpeg should be usable with DVD-o-matic.  Most testing has, however,
- *  happened with files from DVD.  DVD-o-matic's output has been tested on Christie
- *  digital projectors with Doremi servers.
+ *  supported by FFmpeg should be usable with DVD-o-matic.  DVD-o-matic's output has been
+ *  tested on numerous digital projectors.
  *
  *  DVD-o-matic allows you to crop black borders from movies, scale them to the correct
  *  aspect ratio and apply FFmpeg filters.  The time-consuming encoding of JPEG2000 files
  *
  *  DVD-o-matic can also make DCPs from still images, for advertisements and such-like.
  * 
- *  Portions of DVD-o-matic are based on OpenDCP (http://code.google.com/p/opendcp),
+ *  Parts of DVD-o-matic are based on OpenDCP (http://code.google.com/p/opendcp),
  *  written by Terrence Meiczinger.
  *
  *  DVD-o-matic uses libopenjpeg (http://code.google.com/p/openjpeg/) for JPEG2000 encoding
  *  and libsndfile (http://www.mega-nerd.com/libsndfile/) for WAV file manipulation.  It
- *  also makes heavy use of the boost libraries (http://www.boost.org/).  libtiff
- *  (http://www.libtiff.org/) is used for TIFF encoding and decoding, and the GUI is
+ *  also makes heavy use of the boost libraries (http://www.boost.org/).  ImageMagick
+ *  (http://www.imagemagick.org/) is used for still-image encoding and decoding, and the GUI is
  *  built using wxWidgets (http://wxwidgets.org/).  It also uses libmhash (http://mhash.sourceforge.net/)
  *  for debugging purposes.
  *
index e9fbd6f62f19f1605f1e77ec3685f98601d71a0c..1570fe3b00ea3318587d9f7c70d097c2032455cf 100644 (file)
 
 */
 
+/** @file src/lib/audio_decoder.h
+ *  @brief Parent class for audio decoders.
+ */
+
 #ifndef DVDOMATIC_AUDIO_DECODER_H
 #define DVDOMATIC_AUDIO_DECODER_H
 
@@ -24,6 +28,9 @@
 #include "stream.h"
 #include "decoder.h"
 
+/** @class AudioDecoder.
+ *  @brief Parent class for audio decoders.
+ */
 class AudioDecoder : public AudioSource, public virtual Decoder
 {
 public:
@@ -31,16 +38,20 @@ public:
 
        virtual void set_audio_stream (boost::shared_ptr<AudioStream>);
 
+       /** @return Audio stream that we are using */
        boost::shared_ptr<AudioStream> audio_stream () const {
                return _audio_stream;
        }
 
+       /** @return All available audio streams */
        std::vector<boost::shared_ptr<AudioStream> > audio_streams () const {
                return _audio_streams;
        }
 
 protected:
+       /** Audio stream that we are using */
        boost::shared_ptr<AudioStream> _audio_stream;
+       /** All available audio streams */
        std::vector<boost::shared_ptr<AudioStream> > _audio_streams;
 };
 
index 93109a66dbee8bfac509d76aa859588193cd5305..11d578a6035b449c55c95c8301dda82418dee226 100644 (file)
@@ -1,3 +1,22 @@
+/*
+    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.
+
+*/
+
 #ifndef DVDOMATIC_AUDIO_SINK_H
 #define DVDOMATIC_AUDIO_SINK_H
 
index 1c53da74eca2ac9106140baf9902ccee7e904c05..5a1510d3ce5fd242980d88ead686d249a5efed42 100644 (file)
 
 */
 
+/** @file  src/audio_source.h
+ *  @brief Parent class for classes which emit audio data.
+ */
+
 #ifndef DVDOMATIC_AUDIO_SOURCE_H
 #define DVDOMATIC_AUDIO_SOURCE_H
 
@@ -25,6 +29,7 @@
 class AudioBuffers;
 class AudioSink;
 
+/** A class that emits audio data */
 class AudioSource
 {
 public:
index 888046bc434cfd38e5758c1142e9efedf56e7a2a..b85dbf288fba6a2bdc741744e470060e0c585d3c 100644 (file)
@@ -28,16 +28,25 @@ Combiner::Combiner (Log* log)
 
 }
 
+/** Process video for the left half of the frame.
+ *  @param image Frame image.
+ *  @param sub Subtitle (which will be ignored)
+ */
 void
 Combiner::process_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub)
 {
        _image = image;
 }
 
+/** Process video for the right half of the frame.
+ *  @param image Frame image.
+ *  @param sub Subtitle (which will be put onto the whole frame)
+ */
 void
 Combiner::process_video_b (shared_ptr<Image> image, shared_ptr<Subtitle> sub)
 {
        /* Copy the right half of this image into our _image */
+       /* XXX: this should probably be in the Image class */
        for (int i = 0; i < image->components(); ++i) {
                int const line_size = image->line_size()[i];
                int const half_line_size = line_size / 2;
index 021fac6daca926786ab442c147987342900ff7b3..78c9889b5bfcd4cb30e3229d7561811a171ded09 100644 (file)
 
 */
 
+/** @file src/lib/combiner.h
+ *  @brief Class for combining two video streams.
+ */
+
 #include "processor.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
 {
 public:
@@ -28,5 +37,6 @@ public:
        void process_video_b (boost::shared_ptr<Image> i, boost::shared_ptr<Subtitle> s);
 
 private:
+       /** The image that we are currently working on */
        boost::shared_ptr<Image> _image;
 };
index de3a734655737058aeb0f3569aa0c642836e176b..333fe139b8a311ac30719fbf69c7fc39be16c5e9 100644 (file)
@@ -948,6 +948,7 @@ Film::set_content (string c)
                _content = c;
        }
 
+       /* Reset streams here in case the new content doesn't have one or the other */
        _content_audio_stream = shared_ptr<AudioStream> ();
        _subtitle_stream = shared_ptr<SubtitleStream> ();
 
index 99957a00fdf019aca1e8d43eb76ae3fa68f965ff..5e75eefe84f927931435325bac20b2b52d974c74 100644 (file)
@@ -373,6 +373,7 @@ public:
        /** Emitted when some property has changed */
        mutable boost::signals2::signal<void (Property)> Changed;
 
+       /** Current version number of the state file */
        static int const state_version;
 
 private:
@@ -425,8 +426,13 @@ private:
            has the specified filters and post-processing.
        */
        bool _dcp_ab;
+       /** The audio stream to use from our content */
        boost::shared_ptr<AudioStream> _content_audio_stream;
+       /** List of filenames of external audio files, in channel order
+           (L, R, C, Lfe, Ls, Rs)
+       */
        std::vector<std::string> _external_audio;
+       /** true to use audio from our content file; false to use external audio */
        bool _use_content_audio;
        /** Gain to apply to audio in dB */
        float _audio_gain;
@@ -463,14 +469,16 @@ private:
        boost::optional<SourceFrame> _length;
        /** MD5 digest of our content file */
        std::string _content_digest;
-       /** the audio streams in our content */
+       /** The audio streams in our content */
        std::vector<boost::shared_ptr<AudioStream> > _content_audio_streams;
+       /** A stream to represent possible external audio (will always exist) */
        boost::shared_ptr<AudioStream> _external_audio_stream;
        /** the subtitle streams that we can use */
        std::vector<boost::shared_ptr<SubtitleStream> > _subtitle_streams;
        /** Frames per second of the source */
        float _frames_per_second;
 
+       /** true if our state has changed since we last saved it */
        mutable bool _dirty;
 
        /** Mutex for all state except _directory */
index 4f818b739e14d262c1b97f307f1eb85acd19d8d5..72828ed4644cf5d862e8bd72f132f5188221bb2f 100644 (file)
@@ -377,7 +377,7 @@ AlignedImage::AlignedImage (AVPixelFormat f, Size s)
 }
 
 AlignedImage::AlignedImage (shared_ptr<Image> im)
-       : SimpleImage (im->pixel_format(), im->size(), boost::bind (stride_round_up, _1, _2, 1))
+       : SimpleImage (im->pixel_format(), im->size(), boost::bind (stride_round_up, _1, _2, 32))
 {
        assert (components() == im->components());
 
index 69f3a883722b3f10a4c8e609ee4bf35834b8a01e..7c118f338c84f0c52998dda9d814871354c90677 100644 (file)
@@ -127,6 +127,9 @@ private:
        int* _stride; ///< array of strides for each line (including any alignment padding bytes)
 };
 
+/** @class AlignedImage
+ *  @brief An image whose pixel data is padded so that rows always start on 32-byte boundaries.
+ */
 class AlignedImage : public SimpleImage
 {
 public:
@@ -134,6 +137,9 @@ public:
        AlignedImage (boost::shared_ptr<Image>);
 };
 
+/** @class CompactImage
+ *  @brief An image whose pixel data is not padded, so rows may start at any pixel alignment.
+ */
 class CompactImage : public SimpleImage
 {
 public:
index 53e5dae2b7e0a8e27b908be06ef3257bd97aee57..cddcbf3f10fe47a466342fbb756e7a62b7758e38 100644 (file)
 
 */
 
+/** @file  src/processor.h
+ *  @brief Parent class for classes which accept and then emit video or audio data.
+ */
+
 #ifndef DVDOMATIC_PROCESSOR_H
 #define DVDOMATIC_PROCESSOR_H
 
@@ -27,6 +31,9 @@
 
 class Log;
 
+/** @class Processor
+ *  @brief Base class for processors.
+ */
 class Processor
 {
 public:
@@ -41,6 +48,9 @@ protected:
        Log* _log;
 };
 
+/** @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:
@@ -49,6 +59,9 @@ public:
        {}
 };
 
+/** @class AudioProcessor
+ *  @brief A processor which handles just audio data.
+ */
 class AudioProcessor : public Processor, public AudioSource, public AudioSink
 {
 public:
@@ -57,6 +70,9 @@ public:
        {}
 };
 
+/** @class VideoProcessor
+ *  @brief A processor which handles just video data.
+ */
 class VideoProcessor : public Processor, public VideoSource, public VideoSink
 {
 public:
index aeb529702192a84119f6fc1abf4a86b837b2df87..29ba91f7c5f7e43155534b8a8c2f1afba3979425 100644 (file)
@@ -730,6 +730,10 @@ get_optional_int (multimap<string, string> const & kv, string k)
        return lexical_cast<int> (i->second);
 }
 
+/** Construct an AudioBuffers.  Audio data is undefined after this constructor.
+ *  @param channels Number of channels.
+ *  @param frames Number of frames to reserve space for.
+ */
 AudioBuffers::AudioBuffers (int channels, int frames)
        : _channels (channels)
        , _frames (frames)
@@ -741,6 +745,9 @@ AudioBuffers::AudioBuffers (int channels, int frames)
        }
 }
 
+/** Copy constructor.
+ *  @param other Other AudioBuffers; data is copied.
+ */
 AudioBuffers::AudioBuffers (AudioBuffers const & other)
        : _channels (other._channels)
        , _frames (other._frames)
@@ -762,13 +769,20 @@ AudioBuffers::~AudioBuffers ()
        delete[] _data;
 }
 
+/** @param c Channel index.
+ *  @return Buffer for this channel.
+ */
 float*
 AudioBuffers::data (int c) const
 {
        assert (c >= 0 && c < _channels);
        return _data[c];
 }
-       
+
+/** Set the number of frames that these AudioBuffers will report themselves
+ *  as having.
+ *  @param f Frames; must be less than or equal to the number of allocated frames.
+ */
 void
 AudioBuffers::set_frames (int f)
 {
@@ -776,6 +790,7 @@ AudioBuffers::set_frames (int f)
        _frames = f;
 }
 
+/** Make all samples on all channels silent */
 void
 AudioBuffers::make_silent ()
 {
@@ -784,24 +799,45 @@ AudioBuffers::make_silent ()
        }
 }
 
+/** Make all samples on a given channel silent.
+ *  @param c Channel.
+ */
 void
 AudioBuffers::make_silent (int c)
 {
+       assert (c >= 0 && c < _channels);
+       
        for (int i = 0; i < _frames; ++i) {
                _data[c][i] = 0;
        }
 }
 
+/** Copy data from another AudioBuffers to this one.  All channels are copied.
+ *  @param from AudioBuffers to copy from; must have the same number of channels as this.
+ *  @param frames_to_copy Number of frames to copy.
+ *  @param read_offset Offset to read from in `from'.
+ *  @param write_offset Offset to write to in `to'.
+ */
 void
 AudioBuffers::copy_from (AudioBuffers* from, int frames_to_copy, int read_offset, int write_offset)
 {
        assert (from->channels() == channels());
 
+       assert (from);
+       assert (read_offset >= 0 && (read_offset + frames_to_copy) <= from->_allocated_frames);
+       assert (write_offset >= 0 && (write_offset + frames_to_copy) <= _allocated_frames);
+
        for (int i = 0; i < _channels; ++i) {
                memcpy (_data[i] + write_offset, from->_data[i] + read_offset, frames_to_copy * sizeof(float));
        }
 }
 
+/** Move audio data around.
+ *  @param from Offset to move from.
+ *  @param to Offset to move to.
+ *  @param frames Number of frames to move.
+ */
+    
 void
 AudioBuffers::move (int from, int to, int frames)
 {
@@ -823,18 +859,27 @@ AudioBuffers::move (int from, int to, int frames)
        }
 }
 
+/** Trip an assert if the caller is not in the UI thread */
 void
 ensure_ui_thread ()
 {
        assert (this_thread::get_id() == ui_thread);
 }
 
+/** @param v Source video frame.
+ *  @param audio_sample_rate Source audio sample rate.
+ *  @param frames_per_second Number of video frames per second.
+ *  @return Equivalent number of audio frames for `v'.
+ */
 int64_t
 video_frames_to_audio_frames (SourceFrame v, float audio_sample_rate, float frames_per_second)
 {
        return ((int64_t) v * audio_sample_rate / frames_per_second);
 }
 
+/** @param f Filename.
+ *  @return true if this file is a still image, false if it is something else.
+ */
 bool
 still_image_file (string f)
 {
index 53e78e57c8f1d44142bf5e2551812ce63d1b069f..341458155fcc21b8b59c84d30520f0309936f343 100644 (file)
@@ -219,6 +219,9 @@ private:
        int _buffer_data;
 };
 
+/** @class AudioBuffers
+ *  @brief A class to hold multi-channel audio data in float format.
+ */
 class AudioBuffers
 {
 public:
@@ -249,9 +252,13 @@ public:
        void move (int from, int to, int frames);
 
 private:
+       /** Number of channels */
        int _channels;
+       /** Number of frames (where a frame is one sample across all channels) */
        int _frames;
+       /** Number of frames that _data can hold */
        int _allocated_frames;
+       /** Audio data (so that, e.g. _data[2][6] is channel 2, sample 6) */
        float** _data;
 };
 
index de0635ac72895d809320ff981b4b1805e0d61913..d53589e2e21448da56c83b6a437255a2a2563194 100644 (file)
 
 */
 
+/** @file  src/video_source.h
+ *  @brief Parent class for classes which emit video data.
+ */
+
 #ifndef DVDOMATIC_VIDEO_SOURCE_H
 #define DVDOMATIC_VIDEO_SOURCE_H
 
@@ -28,12 +32,15 @@ class VideoSink;
 class Subtitle;
 class Image;
 
+/** @class VideoSink
+ *  @param A class that emits video data.
+ */
 class VideoSource
 {
 public:
 
        /** Emitted when a video frame is ready.
-        *  First parameter is the frame within the source.
+        *  First parameter is the video image.
         *  Second parameter is either 0 or a subtitle that should be on this frame.
         */
        boost::signals2::signal<void (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>)> Video;