From b1defe9019642dc4b80697291d40ed88f09de8be Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Sun, 18 Nov 2012 22:46:15 +0000 Subject: [PATCH] Fix mis-alignment of copied AlignedImages; add some asserts; some docs. --- doc/mainpage.txt | 11 +++++----- src/lib/audio_decoder.h | 11 ++++++++++ src/lib/audio_sink.h | 19 +++++++++++++++++ src/lib/audio_source.h | 5 +++++ src/lib/combiner.cc | 9 ++++++++ src/lib/combiner.h | 10 +++++++++ src/lib/film.cc | 1 + src/lib/film.h | 10 ++++++++- src/lib/image.cc | 2 +- src/lib/image.h | 6 ++++++ src/lib/processor.h | 16 ++++++++++++++ src/lib/util.cc | 47 ++++++++++++++++++++++++++++++++++++++++- src/lib/util.h | 7 ++++++ src/lib/video_source.h | 9 +++++++- 14 files changed, 153 insertions(+), 10 deletions(-) diff --git a/doc/mainpage.txt b/doc/mainpage.txt index e89ca8d26..b018c5929 100644 --- a/doc/mainpage.txt +++ b/doc/mainpage.txt @@ -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 @@ -16,13 +15,13 @@ * * 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. * diff --git a/src/lib/audio_decoder.h b/src/lib/audio_decoder.h index e9fbd6f62..1570fe3b0 100644 --- a/src/lib/audio_decoder.h +++ b/src/lib/audio_decoder.h @@ -17,6 +17,10 @@ */ +/** @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); + /** @return Audio stream that we are using */ boost::shared_ptr audio_stream () const { return _audio_stream; } + /** @return All available audio streams */ std::vector > audio_streams () const { return _audio_streams; } protected: + /** Audio stream that we are using */ boost::shared_ptr _audio_stream; + /** All available audio streams */ std::vector > _audio_streams; }; diff --git a/src/lib/audio_sink.h b/src/lib/audio_sink.h index 93109a66d..11d578a60 100644 --- a/src/lib/audio_sink.h +++ b/src/lib/audio_sink.h @@ -1,3 +1,22 @@ +/* + Copyright (C) 2012 Carl Hetherington + + 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 diff --git a/src/lib/audio_source.h b/src/lib/audio_source.h index 1c53da74e..5a1510d3c 100644 --- a/src/lib/audio_source.h +++ b/src/lib/audio_source.h @@ -17,6 +17,10 @@ */ +/** @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: diff --git a/src/lib/combiner.cc b/src/lib/combiner.cc index 888046bc4..b85dbf288 100644 --- a/src/lib/combiner.cc +++ b/src/lib/combiner.cc @@ -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, shared_ptr 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, shared_ptr 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; diff --git a/src/lib/combiner.h b/src/lib/combiner.h index 021fac6da..78c9889b5 100644 --- a/src/lib/combiner.h +++ b/src/lib/combiner.h @@ -17,8 +17,17 @@ */ +/** @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 i, boost::shared_ptr s); private: + /** The image that we are currently working on */ boost::shared_ptr _image; }; diff --git a/src/lib/film.cc b/src/lib/film.cc index de3a73465..333fe139b 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -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 (); _subtitle_stream = shared_ptr (); diff --git a/src/lib/film.h b/src/lib/film.h index 99957a00f..5e75eefe8 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -373,6 +373,7 @@ public: /** Emitted when some property has changed */ mutable boost::signals2::signal 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 _content_audio_stream; + /** List of filenames of external audio files, in channel order + (L, R, C, Lfe, Ls, Rs) + */ std::vector _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 _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 > _content_audio_streams; + /** A stream to represent possible external audio (will always exist) */ boost::shared_ptr _external_audio_stream; /** the subtitle streams that we can use */ std::vector > _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 */ diff --git a/src/lib/image.cc b/src/lib/image.cc index 4f818b739..72828ed46 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -377,7 +377,7 @@ AlignedImage::AlignedImage (AVPixelFormat f, Size s) } AlignedImage::AlignedImage (shared_ptr 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()); diff --git a/src/lib/image.h b/src/lib/image.h index 69f3a8837..7c118f338 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -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); }; +/** @class CompactImage + * @brief An image whose pixel data is not padded, so rows may start at any pixel alignment. + */ class CompactImage : public SimpleImage { public: diff --git a/src/lib/processor.h b/src/lib/processor.h index 53e5dae2b..cddcbf3f1 100644 --- a/src/lib/processor.h +++ b/src/lib/processor.h @@ -17,6 +17,10 @@ */ +/** @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: diff --git a/src/lib/util.cc b/src/lib/util.cc index aeb529702..29ba91f7c 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -730,6 +730,10 @@ get_optional_int (multimap const & kv, string k) return lexical_cast (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) { diff --git a/src/lib/util.h b/src/lib/util.h index 53e78e57c..341458155 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -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; }; diff --git a/src/lib/video_source.h b/src/lib/video_source.h index de0635ac7..d53589e2e 100644 --- a/src/lib/video_source.h +++ b/src/lib/video_source.h @@ -17,6 +17,10 @@ */ +/** @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, boost::shared_ptr)> Video; -- 2.30.2