diff options
| author | Carl Hetherington <cth@carlh.net> | 2012-11-14 20:04:15 +0000 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2012-11-14 20:04:15 +0000 |
| commit | 05c37b9bb09f7bfa4c2ec8ea6b3fa4a83d0fec20 (patch) | |
| tree | fa7a3e408c2eb66b070864694b6af7e0787e508f /src | |
| parent | 5161626c3c28ba528511a8b211286a5e81a0f02a (diff) | |
Tests pass again.
Diffstat (limited to 'src')
| -rw-r--r-- | src/lib/decoder.cc | 50 | ||||
| -rw-r--r-- | src/lib/decoder.h | 7 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.cc | 41 | ||||
| -rw-r--r-- | src/lib/ffmpeg_decoder.h | 12 | ||||
| -rw-r--r-- | src/lib/filter_graph.cc | 22 | ||||
| -rw-r--r-- | src/lib/filter_graph.h | 6 | ||||
| -rw-r--r-- | src/lib/gain.cc | 26 | ||||
| -rw-r--r-- | src/lib/gain.h | 12 | ||||
| -rw-r--r-- | src/lib/image.cc | 41 | ||||
| -rw-r--r-- | src/lib/image.h | 12 | ||||
| -rw-r--r-- | src/lib/imagemagick_decoder.cc | 10 | ||||
| -rw-r--r-- | src/lib/processor.h | 8 | ||||
| -rw-r--r-- | src/lib/tiff_decoder.cc | 23 | ||||
| -rw-r--r-- | src/lib/transcoder.cc | 31 | ||||
| -rw-r--r-- | src/lib/transcoder.h | 3 | ||||
| -rw-r--r-- | src/lib/util.cc | 10 | ||||
| -rw-r--r-- | src/lib/util.h | 3 | ||||
| -rw-r--r-- | src/lib/wscript | 1 |
18 files changed, 186 insertions, 132 deletions
diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index e91b5e19e..8e1e4e3c5 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -73,57 +73,19 @@ Decoder::go () } } -/** Called to tell the world that some audio data is ready - * @param audio Audio data. - */ -void -Decoder::process_audio (shared_ptr<AudioBuffers> audio) -{ - /* Maybe apply gain */ - if (_film->audio_gain() != 0) { - float const linear_gain = pow (10, _film->audio_gain() / 20); - for (int i = 0; i < audio->channels(); ++i) { - for (int j = 0; j < audio->frames(); ++j) { - audio->data(i)[j] *= linear_gain; - } - } - } - - Audio (audio); -} - /** Called by subclasses to tell the world that some video data is ready. * We do some post-processing / filtering then emit it for listeners. * @param frame to decode; caller manages memory. */ void -Decoder::process_video (AVFrame const * frame) +Decoder::emit_video (shared_ptr<Image> image) { - shared_ptr<FilterGraph> graph; - - list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin(); - while (i != _filter_graphs.end() && !(*i)->can_process (Size (frame->width, frame->height), (AVPixelFormat) frame->format)) { - ++i; - } - - if (i == _filter_graphs.end ()) { - graph.reset (new FilterGraph (_film, this, _opt->apply_crop, Size (frame->width, frame->height), (AVPixelFormat) frame->format)); - _filter_graphs.push_back (graph); - _film->log()->log (String::compose ("New graph for %1x%2, pixel format %3", frame->width, frame->height, frame->format)); - } else { - graph = *i; + shared_ptr<Subtitle> sub; + if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frame()) / _film->frames_per_second())) { + sub = _timed_subtitle->subtitle (); } - list<shared_ptr<Image> > images = graph->process (frame); - - for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) { - shared_ptr<Subtitle> sub; - if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frame()) / _film->frames_per_second())) { - sub = _timed_subtitle->subtitle (); - } - - emit_video (*i, sub); - } + Video (image, sub); } void @@ -149,7 +111,7 @@ Decoder::emit_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub) } void -Decoder::process_subtitle (shared_ptr<TimedSubtitle> s) +Decoder::emit_subtitle (shared_ptr<TimedSubtitle> s) { _timed_subtitle = s; diff --git a/src/lib/decoder.h b/src/lib/decoder.h index a458c348b..5bb5b574d 100644 --- a/src/lib/decoder.h +++ b/src/lib/decoder.h @@ -99,9 +99,8 @@ protected: virtual PixelFormat pixel_format () const = 0; - void process_video (AVFrame const *); - void process_audio (boost::shared_ptr<AudioBuffers>); - void process_subtitle (boost::shared_ptr<TimedSubtitle>); + void emit_video (boost::shared_ptr<Image>); + void emit_subtitle (boost::shared_ptr<TimedSubtitle>); void repeat_last_video (); /** our Film */ @@ -122,8 +121,6 @@ private: SourceFrame _video_frame; - std::list<boost::shared_ptr<FilterGraph> > _filter_graphs; - boost::shared_ptr<TimedSubtitle> _timed_subtitle; boost::shared_ptr<Image> _last_image; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 78d0c48c4..3767d7c5f 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -47,12 +47,14 @@ extern "C" { #include "util.h" #include "log.h" #include "ffmpeg_decoder.h" +#include "filter_graph.h" #include "subtitle.h" using std::cout; using std::string; using std::vector; using std::stringstream; +using std::list; using boost::shared_ptr; using boost::optional; @@ -223,7 +225,7 @@ FFmpegDecoder::pass () int frame_finished; while (avcodec_decode_video2 (_video_codec_context, _frame, &frame_finished, &_packet) >= 0 && frame_finished) { - process_video (_frame); + filter_and_emit_video (_frame); } if (_audio_stream && _opt->decode_audio && _film->use_content_audio()) { @@ -233,7 +235,7 @@ FFmpegDecoder::pass () ); assert (_audio_codec_context->channels == _film->audio_channels()); - process_audio (deinterleave_audio (_frame->data[0], data_size)); + Audio (deinterleave_audio (_frame->data[0], data_size)); } } @@ -283,7 +285,7 @@ FFmpegDecoder::pass () if (delta > -one_frame) { /* Process this frame */ - process_video (_frame); + filter_and_emit_video (_frame); } else { /* Otherwise we are omitting a frame to keep things right */ _film->log()->log (String::compose ("Frame removed at %1s", out_pts_seconds)); @@ -326,7 +328,7 @@ FFmpegDecoder::pass () if (s) { shared_ptr<AudioBuffers> audio (new AudioBuffers (_audio_stream.get().channels(), s)); audio->make_silent (); - process_audio (audio); + Audio (audio); } } @@ -335,7 +337,7 @@ FFmpegDecoder::pass () ); assert (_audio_codec_context->channels == _film->audio_channels()); - process_audio (deinterleave_audio (_frame->data[0], data_size)); + Audio (deinterleave_audio (_frame->data[0], data_size)); } } @@ -348,9 +350,9 @@ FFmpegDecoder::pass () indicate that the previous subtitle should stop. */ if (sub.num_rects > 0) { - process_subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub, _first_video.get()))); + emit_subtitle (shared_ptr<TimedSubtitle> (new TimedSubtitle (sub, _first_video.get()))); } else { - process_subtitle (shared_ptr<TimedSubtitle> ()); + emit_subtitle (shared_ptr<TimedSubtitle> ()); } avsubtitle_free (&sub); } @@ -527,3 +529,28 @@ FFmpegDecoder::set_subtitle_stream (optional<SubtitleStream> s) Decoder::set_subtitle_stream (s); setup_subtitle (); } + +void +FFmpegDecoder::filter_and_emit_video (AVFrame* frame) +{ + shared_ptr<FilterGraph> graph; + + list<shared_ptr<FilterGraph> >::iterator i = _filter_graphs.begin(); + while (i != _filter_graphs.end() && !(*i)->can_process (Size (frame->width, frame->height), (AVPixelFormat) frame->format)) { + ++i; + } + + if (i == _filter_graphs.end ()) { + graph.reset (new FilterGraph (_film, this, _opt->apply_crop, Size (frame->width, frame->height), (AVPixelFormat) frame->format)); + _filter_graphs.push_back (graph); + _film->log()->log (String::compose ("New graph for %1x%2, pixel format %3", frame->width, frame->height, frame->format)); + } else { + graph = *i; + } + + list<shared_ptr<Image> > images = graph->process (frame); + + for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) { + emit_video (*i); + } +} diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 856ac0801..5c6f8ab26 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -58,6 +58,10 @@ public: /* Methods to query our input video */ float frames_per_second () const; Size native_size () const; + int time_base_numerator () const; + int time_base_denominator () const; + int sample_aspect_ratio_numerator () const; + int sample_aspect_ratio_denominator () const; void set_audio_stream (boost::optional<AudioStream>); void set_subtitle_stream (boost::optional<SubtitleStream>); @@ -66,13 +70,11 @@ private: bool pass (); PixelFormat pixel_format () const; - int time_base_numerator () const; - int time_base_denominator () const; - int sample_aspect_ratio_numerator () const; - int sample_aspect_ratio_denominator () const; AVSampleFormat audio_sample_format () const; int bytes_per_audio_sample () const; + void filter_and_emit_video (AVFrame *); + void setup_general (); void setup_video (); void setup_audio (); @@ -99,4 +101,6 @@ private: boost::optional<double> _first_video; boost::optional<double> _first_audio; + + std::list<boost::shared_ptr<FilterGraph> > _filter_graphs; }; diff --git a/src/lib/filter_graph.cc b/src/lib/filter_graph.cc index 72bb8deb7..aaa9e07ba 100644 --- a/src/lib/filter_graph.cc +++ b/src/lib/filter_graph.cc @@ -28,42 +28,36 @@ extern "C" { #endif #include <libavformat/avio.h> } -#include "film.h" #include "decoder.h" #include "filter_graph.h" #include "ffmpeg_compatibility.h" #include "filter.h" #include "exceptions.h" #include "image.h" +#include "film.h" +#include "ffmpeg_decoder.h" using std::stringstream; using std::string; using std::list; using boost::shared_ptr; -FilterGraph::FilterGraph (shared_ptr<Film> film, Decoder* decoder, bool crop, Size s, AVPixelFormat p) +FilterGraph::FilterGraph (shared_ptr<Film> film, FFmpegDecoder* decoder, bool crop, Size s, AVPixelFormat p) : _buffer_src_context (0) , _buffer_sink_context (0) , _size (s) , _pixel_format (p) { - stringstream fs; - Size size_after_crop; - - if (crop) { - size_after_crop = film->cropped_size (decoder->native_size ()); - fs << crop_string (Position (film->crop().left, film->crop().top), size_after_crop); - } else { - size_after_crop = decoder->native_size (); - fs << crop_string (Position (0, 0), size_after_crop); - } - string filters = Filter::ffmpeg_strings (film->filters()).first; if (!filters.empty ()) { filters += ","; } - filters += fs.str (); + if (crop) { + filters += crop_string (Position (film->crop().left, film->crop().top), film->cropped_size (decoder->native_size())); + } else { + filters += crop_string (Position (0, 0), decoder->native_size()); + } avfilter_register_all (); diff --git a/src/lib/filter_graph.h b/src/lib/filter_graph.h index 4ff10dece..5c0c83d16 100644 --- a/src/lib/filter_graph.h +++ b/src/lib/filter_graph.h @@ -22,14 +22,14 @@ #include "util.h" -class Decoder; class Image; -class Film; +class VideoFilter; +class FFmpegDecoder; class FilterGraph { public: - FilterGraph (boost::shared_ptr<Film> film, Decoder* decoder, bool crop, Size s, AVPixelFormat p); + FilterGraph (boost::shared_ptr<Film> film, FFmpegDecoder* decoder, bool crop, Size s, AVPixelFormat p); bool can_process (Size s, AVPixelFormat p) const; std::list<boost::shared_ptr<Image> > process (AVFrame const * frame); diff --git a/src/lib/gain.cc b/src/lib/gain.cc new file mode 100644 index 000000000..80d3b7c72 --- /dev/null +++ b/src/lib/gain.cc @@ -0,0 +1,26 @@ +#include "gain.h" + +using boost::shared_ptr; + +/** @param gain gain in dB */ +Gain::Gain (Log* log, float gain) + : AudioProcessor (log) + , _gain (gain) +{ + +} + +void +Gain::process_audio (shared_ptr<AudioBuffers> b) +{ + if (_gain != 0) { + float const linear_gain = pow (10, _gain / 20); + for (int i = 0; i < b->channels(); ++i) { + for (int j = 0; j < b->frames(); ++j) { + b->data(i)[j] *= linear_gain; + } + } + } + + Audio (b); +} diff --git a/src/lib/gain.h b/src/lib/gain.h new file mode 100644 index 000000000..c1221ed48 --- /dev/null +++ b/src/lib/gain.h @@ -0,0 +1,12 @@ +#include "processor.h" + +class Gain : public AudioProcessor +{ +public: + Gain (Log* log, float gain); + + void process_audio (boost::shared_ptr<AudioBuffers>); + +private: + float _gain; +}; diff --git a/src/lib/image.cc b/src/lib/image.cc index 05270954d..4f818b739 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -293,7 +293,7 @@ Image::write_to_socket (shared_ptr<Socket> socket) const * @param p Pixel format. * @param s Size in pixels. */ -SimpleImage::SimpleImage (AVPixelFormat p, Size s, function<int (int)> rounder) +SimpleImage::SimpleImage (AVPixelFormat p, Size s, function<int (int, int const *)> stride_computer) : Image (p) , _size (s) { @@ -329,7 +329,7 @@ SimpleImage::SimpleImage (AVPixelFormat p, Size s, function<int (int)> rounder) } for (int i = 0; i < components(); ++i) { - _stride[i] = rounder (_line_size[i]); + _stride[i] = stride_computer (i, _line_size); _data[i] = (uint8_t *) av_malloc (_stride[i] * lines (i)); } } @@ -371,19 +371,13 @@ SimpleImage::size () const } AlignedImage::AlignedImage (AVPixelFormat f, Size s) - : SimpleImage (f, s, boost::bind (round_up, _1, 32)) + : SimpleImage (f, s, boost::bind (stride_round_up, _1, _2, 32)) { } -CompactImage::CompactImage (AVPixelFormat f, Size s) - : SimpleImage (f, s, boost::bind (round_up, _1, 1)) -{ - setup_picture (); -} - -CompactImage::CompactImage (shared_ptr<Image> im) - : SimpleImage (im->pixel_format(), im->size(), boost::bind (round_up, _1, 1)) +AlignedImage::AlignedImage (shared_ptr<Image> im) + : SimpleImage (im->pixel_format(), im->size(), boost::bind (stride_round_up, _1, _2, 1)) { assert (components() == im->components()); @@ -400,16 +394,31 @@ CompactImage::CompactImage (shared_ptr<Image> im) o += im->stride()[c]; } } +} + +CompactImage::CompactImage (AVPixelFormat f, Size s) + : SimpleImage (f, s, boost::bind (stride_round_up, _1, _2, 1)) +{ - setup_picture (); } -void -CompactImage::setup_picture () +CompactImage::CompactImage (shared_ptr<Image> im) + : SimpleImage (im->pixel_format(), im->size(), boost::bind (stride_round_up, _1, _2, 1)) { + assert (components() == im->components()); + for (int c = 0; c < components(); ++c) { - _picture.data[c] = data()[c]; - _picture.linesize[c] = line_size()[c]; + + assert (line_size()[c] == im->line_size()[c]); + + uint8_t* t = data()[c]; + uint8_t* o = im->data()[c]; + + for (int y = 0; y < lines(c); ++y) { + memcpy (t, o, line_size()[c]); + t += stride()[c]; + o += im->stride()[c]; + } } } diff --git a/src/lib/image.h b/src/lib/image.h index bb4a32319..69f3a8837 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -111,7 +111,7 @@ private: class SimpleImage : public Image { public: - SimpleImage (AVPixelFormat, Size, boost::function<int (int)> rounder); + SimpleImage (AVPixelFormat, Size, boost::function<int (int, int const *)> rounder); ~SimpleImage (); uint8_t ** data () const; @@ -131,6 +131,7 @@ class AlignedImage : public SimpleImage { public: AlignedImage (AVPixelFormat, Size); + AlignedImage (boost::shared_ptr<Image>); }; class CompactImage : public SimpleImage @@ -138,15 +139,6 @@ class CompactImage : public SimpleImage public: CompactImage (AVPixelFormat, Size); CompactImage (boost::shared_ptr<Image>); - - AVPicture const * picture () const { - return &_picture; - } - -private: - void setup_picture (); - - AVPicture _picture; }; #endif diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index fd4e5b18d..53e1db879 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -23,8 +23,8 @@ #include "image.h" #include "film.h" -using namespace std; -using namespace boost; +using std::cout; +using boost::shared_ptr; ImageMagickDecoder::ImageMagickDecoder ( boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j) @@ -50,9 +50,9 @@ ImageMagickDecoder::pass () } Size size = native_size (); - CompactImage image (PIX_FMT_RGB24, size); + shared_ptr<CompactImage> image (new CompactImage (PIX_FMT_RGB24, size)); - uint8_t* p = image.data()[0]; + uint8_t* p = image->data()[0]; for (int y = 0; y < size.height; ++y) { for (int x = 0; x < size.width; ++x) { Magick::Color c = _magick_image->pixelColor (x, y); @@ -63,7 +63,7 @@ ImageMagickDecoder::pass () } - process_video ((AVFrame const *) image.picture()); + emit_video (image); _done = true; return false; diff --git a/src/lib/processor.h b/src/lib/processor.h index e99ff2d4d..f7785c346 100644 --- a/src/lib/processor.h +++ b/src/lib/processor.h @@ -38,4 +38,12 @@ public: {} }; +class VideoProcessor : public Processor, public VideoSource, public VideoSink +{ +public: + VideoProcessor (Log* log) + : Processor (log) + {} +}; + #endif diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc index 7e9bda139..a58ea9974 100644 --- a/src/lib/tiff_decoder.cc +++ b/src/lib/tiff_decoder.cc @@ -38,8 +38,10 @@ extern "C" { #include "options.h" #include "film.h" -using namespace std; -using namespace boost; +using std::cout; +using std::string; +using std::stringstream; +using boost::shared_ptr; /** @param f Our Film. * @param o Options. @@ -50,17 +52,17 @@ TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Opt { string const dir = _film->content_path (); - if (!filesystem::is_directory (dir)) { + if (!boost::filesystem::is_directory (dir)) { throw DecodeError ("TIFF content must be in a directory"); } - for (filesystem::directory_iterator i = filesystem::directory_iterator (dir); i != filesystem::directory_iterator(); ++i) { + for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (dir); i != boost::filesystem::directory_iterator(); ++i) { /* Aah, the sweet smell of progress */ #if BOOST_FILESYSTEM_VERSION == 3 - string const ext = filesystem::path(*i).extension().string(); - string const l = filesystem::path(*i).leaf().generic_string(); + string const ext = boost::filesystem::path(*i).extension().string(); + string const l = boost::filesystem::path(*i).leaf().generic_string(); #else - string const ext = filesystem::path(*i).extension(); + string const ext = boost::filesystem::path(*i).extension(); string const l = i->leaf (); #endif if (ext == ".tif" || ext == ".tiff") { @@ -71,7 +73,6 @@ TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Opt _files.sort (); _iter = _files.begin (); - } float @@ -147,9 +148,9 @@ TIFFDecoder::pass () throw DecodeError ("could not read TIFF data"); } - CompactImage image (PIX_FMT_RGB24, Size (width, height)); + shared_ptr<CompactImage> image (new CompactImage (PIX_FMT_RGB24, Size (width, height))); - uint8_t* p = image.data()[0]; + uint8_t* p = image->data()[0]; for (uint32_t y = 0; y < height; ++y) { for (uint32_t x = 0; x < width; ++x) { uint32_t const i = (height - y - 1) * width + x; @@ -162,7 +163,7 @@ TIFFDecoder::pass () _TIFFfree (raster); TIFFClose (t); - process_video ((AVFrame const *) image.picture ()); + emit_video (image); ++_iter; return false; diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc index f53fc4001..01f54be3f 100644 --- a/src/lib/transcoder.cc +++ b/src/lib/transcoder.cc @@ -32,6 +32,8 @@ #include "film.h" #include "matcher.h" #include "delay_line.h" +#include "options.h" +#include "gain.h" using std::string; using boost::shared_ptr; @@ -49,21 +51,30 @@ Transcoder::Transcoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, { assert (_encoder); - AudioStream st = f->audio_stream().get(); - - _matcher.reset (new Matcher (f->log(), st.sample_rate(), f->frames_per_second())); - _delay_line.reset (new DelayLine (f->log(), st.channels(), f->audio_delay() * st.sample_rate() / 1000)); + if (f->audio_stream()) { + AudioStream st = f->audio_stream().get(); + _matcher.reset (new Matcher (f->log(), st.sample_rate(), f->frames_per_second())); + _delay_line.reset (new DelayLine (f->log(), st.channels(), f->audio_delay() * st.sample_rate() / 1000)); + _gain.reset (new Gain (f->log(), f->audio_gain())); + } /* Set up the decoder to use the film's set streams */ _decoder->set_audio_stream (f->audio_stream ()); _decoder->set_subtitle_stream (f->subtitle_stream ()); - _decoder->connect_video (_matcher); - _matcher->connect_video (_encoder); - - _decoder->connect_audio (_delay_line); - _delay_line->connect_audio (_matcher); - _matcher->connect_audio (_delay_line); + if (_matcher) { + _decoder->connect_video (_matcher); + _matcher->connect_video (_encoder); + } else { + _decoder->connect_video (_encoder); + } + + if (_matcher && _delay_line) { + _decoder->connect_audio (_delay_line); + _delay_line->connect_audio (_matcher); + _matcher->connect_audio (_gain); + _gain->connect_audio (_encoder); + } } /** Run the decoder, passing its output to the encoder, until the decoder diff --git a/src/lib/transcoder.h b/src/lib/transcoder.h index d5597ad0e..324a72037 100644 --- a/src/lib/transcoder.h +++ b/src/lib/transcoder.h @@ -31,6 +31,8 @@ class Job; class Encoder; class FilmState; class Matcher; +class VideoFilter; +class Gain; /** @class Transcoder * @brief A class which takes a FilmState and some Options, then uses those to transcode a Film. @@ -59,4 +61,5 @@ protected: boost::shared_ptr<Decoder> _decoder; boost::shared_ptr<Matcher> _matcher; boost::shared_ptr<DelayLine> _delay_line; + boost::shared_ptr<Gain> _gain; }; diff --git a/src/lib/util.cc b/src/lib/util.cc index 219441865..5e82650a5 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -620,12 +620,18 @@ Rect::intersection (Rect const & other) const */ int -round_up (int a, int t) +stride_round_up (int c, int const * stride, int t) { - a += (t - 1); + int const a = stride[c] + (t - 1); return a - (a % t); } +int +stride_lookup (int c, int const * stride) +{ + return stride[c]; +} + /** Read a sequence of key / value pairs from a text stream; * the keys are the first words on the line, and the values are * the remainder of the line following the key. Lines beginning diff --git a/src/lib/util.h b/src/lib/util.h index 577b9ba1b..bb68b6273 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -170,7 +170,8 @@ extern std::string crop_string (Position, Size); extern int dcp_audio_sample_rate (int); extern DCPFrameRate dcp_frame_rate (float); extern std::string colour_lut_index_to_name (int index); -extern int round_up (int, int); +extern int stride_round_up (int, int const *, int); +extern int stride_lookup (int c, int const * stride); extern std::multimap<std::string, std::string> read_key_value (std::istream& s); extern int get_required_int (std::multimap<std::string, std::string> const & kv, std::string k); extern float get_required_float (std::multimap<std::string, std::string> const & kv, std::string k); diff --git a/src/lib/wscript b/src/lib/wscript index 4fc839097..ef4011c5f 100644 --- a/src/lib/wscript +++ b/src/lib/wscript @@ -29,6 +29,7 @@ def build(bld): film.cc filter.cc format.cc + gain.cc image.cc imagemagick_decoder.cc imagemagick_encoder.cc |
