summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/ab_transcoder.cc2
-rw-r--r--src/lib/ab_transcoder.h5
-rw-r--r--src/lib/check_hashes_job.cc4
-rw-r--r--src/lib/dcp_video_frame.cc4
-rw-r--r--src/lib/dcp_video_frame.h12
-rw-r--r--src/lib/decoder.cc165
-rw-r--r--src/lib/decoder.h35
-rw-r--r--src/lib/decoder_factory.cc11
-rw-r--r--src/lib/decoder_factory.h2
-rw-r--r--src/lib/encoder.cc6
-rw-r--r--src/lib/encoder.h13
-rw-r--r--src/lib/examine_content_job.cc8
-rw-r--r--src/lib/ffmpeg_decoder.cc12
-rw-r--r--src/lib/ffmpeg_decoder.h4
-rw-r--r--src/lib/film.cc105
-rw-r--r--src/lib/film.h46
-rw-r--r--src/lib/imagemagick_decoder.cc6
-rw-r--r--src/lib/imagemagick_decoder.h4
-rw-r--r--src/lib/imagemagick_encoder.cc2
-rw-r--r--src/lib/imagemagick_encoder.h2
-rw-r--r--src/lib/j2k_still_encoder.cc2
-rw-r--r--src/lib/j2k_still_encoder.h2
-rw-r--r--src/lib/j2k_wav_encoder.cc2
-rw-r--r--src/lib/j2k_wav_encoder.h2
-rw-r--r--src/lib/make_dcp_job.cc5
-rw-r--r--src/lib/options.h12
-rw-r--r--src/lib/tiff_decoder.cc7
-rw-r--r--src/lib/tiff_decoder.h4
-rw-r--r--src/lib/transcode_job.cc3
-rw-r--r--src/lib/trim_action.h28
-rw-r--r--src/lib/util.h2
31 files changed, 244 insertions, 273 deletions
diff --git a/src/lib/ab_transcoder.cc b/src/lib/ab_transcoder.cc
index beedd478f..0579aa4ff 100644
--- a/src/lib/ab_transcoder.cc
+++ b/src/lib/ab_transcoder.cc
@@ -66,7 +66,7 @@ ABTranscoder::~ABTranscoder ()
}
void
-ABTranscoder::process_video (shared_ptr<Image> yuv, int frame, shared_ptr<Subtitle> sub, int index)
+ABTranscoder::process_video (shared_ptr<Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub, int index)
{
if (index == 0) {
/* Keep this image around until we get the other half */
diff --git a/src/lib/ab_transcoder.h b/src/lib/ab_transcoder.h
index 7bf5dd4a1..a136fd270 100644
--- a/src/lib/ab_transcoder.h
+++ b/src/lib/ab_transcoder.h
@@ -24,6 +24,7 @@
#include <boost/shared_ptr.hpp>
#include <stdint.h>
+#include "util.h"
class Job;
class Encoder;
@@ -54,7 +55,7 @@ public:
void go ();
private:
- void process_video (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>, int);
+ void process_video (boost::shared_ptr<Image>, SourceFrame, boost::shared_ptr<Subtitle>, int);
boost::shared_ptr<Film> _film_a;
boost::shared_ptr<Film> _film_b;
@@ -63,6 +64,6 @@ private:
boost::shared_ptr<Encoder> _encoder;
boost::shared_ptr<Decoder> _da;
boost::shared_ptr<Decoder> _db;
- int _last_frame;
+ SourceFrame _last_frame;
boost::shared_ptr<Image> _image;
};
diff --git a/src/lib/check_hashes_job.cc b/src/lib/check_hashes_job.cc
index d1483933d..3967d0d70 100644
--- a/src/lib/check_hashes_job.cc
+++ b/src/lib/check_hashes_job.cc
@@ -57,10 +57,10 @@ CheckHashesJob::run ()
throw EncodeError ("cannot check hashes of a DCP with unknown length");
}
- int const N = _film->dcp_length().get();
+ SourceFrame const N = _film->dcp_trim_start() + _film->dcp_length().get();
DCPFrameRate const dfr = dcp_frame_rate (_film->frames_per_second ());
- for (int i = 0; i < N; i += dfr.skip) {
+ for (SourceFrame i = _film->dcp_trim_start(); i < N; i += dfr.skip) {
string const j2k_file = _opt->frame_out_path (i, false);
string const hash_file = j2k_file + ".md5";
diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc
index 1dcc81f0d..c185de0f4 100644
--- a/src/lib/dcp_video_frame.cc
+++ b/src/lib/dcp_video_frame.cc
@@ -76,7 +76,7 @@ using boost::shared_ptr;
DCPVideoFrame::DCPVideoFrame (
shared_ptr<const Image> yuv, shared_ptr<Subtitle> sub,
Size out, int p, int subtitle_offset, float subtitle_scale,
- Scaler const * s, int f, float fps, string pp, int clut, int bw, Log* l
+ Scaler const * s, SourceFrame f, float fps, string pp, int clut, int bw, Log* l
)
: _input (yuv)
, _subtitle (sub)
@@ -376,7 +376,7 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv)
* @param frame Frame index.
*/
void
-EncodedData::write (shared_ptr<const Options> opt, int frame)
+EncodedData::write (shared_ptr<const Options> opt, SourceFrame frame)
{
string const tmp_j2k = opt->frame_out_path (frame, true);
diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h
index 0ff29f7bf..5ae53f1e8 100644
--- a/src/lib/dcp_video_frame.h
+++ b/src/lib/dcp_video_frame.h
@@ -50,7 +50,7 @@ public:
virtual ~EncodedData () {}
void send (boost::shared_ptr<Socket> socket);
- void write (boost::shared_ptr<const Options>, int);
+ void write (boost::shared_ptr<const Options>, SourceFrame);
/** @return data */
uint8_t* data () const {
@@ -106,13 +106,17 @@ public:
class DCPVideoFrame
{
public:
- DCPVideoFrame (boost::shared_ptr<const Image>, boost::shared_ptr<Subtitle>, Size, int, int, float, Scaler const *, int, float, std::string, int, int, Log *);
+ DCPVideoFrame (
+ boost::shared_ptr<const Image>, boost::shared_ptr<Subtitle>, Size,
+ int, int, float, Scaler const *, SourceFrame, float, std::string, int, int, Log *
+ );
+
virtual ~DCPVideoFrame ();
boost::shared_ptr<EncodedData> encode_locally ();
boost::shared_ptr<EncodedData> encode_remotely (ServerDescription const *);
- int frame () const {
+ SourceFrame frame () const {
return _frame;
}
@@ -127,7 +131,7 @@ private:
int _subtitle_offset;
float _subtitle_scale;
Scaler const * _scaler; ///< scaler to use
- int _frame; ///< frame index within the Film
+ SourceFrame _frame; ///< frame index within the Film's source
int _frames_per_second; ///< Frames per second that we will use for the DCP (rounded)
std::string _post_process; ///< FFmpeg post-processing string to use
int _colour_lut_index; ///< Colour look-up table to use (see Config::colour_lut_index ())
diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc
index 110d2aa88..1f93c6c60 100644
--- a/src/lib/decoder.cc
+++ b/src/lib/decoder.cc
@@ -40,6 +40,7 @@
using std::string;
using std::stringstream;
using std::min;
+using std::pair;
using std::list;
using boost::shared_ptr;
@@ -48,18 +49,18 @@ using boost::shared_ptr;
* @param j Job that we are running within, or 0
* @param minimal true to do the bare minimum of work; just run through the content. Useful for acquiring
* accurate frame counts as quickly as possible. This generates no video or audio output.
- * @param ignore_length Ignore the content's claimed length when computing progress.
*/
-Decoder::Decoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal, bool ignore_length)
+Decoder::Decoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal)
: _film (f)
, _opt (o)
, _job (j)
, _minimal (minimal)
- , _ignore_length (ignore_length)
- , _video_frame_index (0)
+ , _video_frames_in (0)
+ , _video_frames_out (0)
+ , _audio_frames_in (0)
+ , _audio_frames_out (0)
, _delay_line (0)
, _delay_in_frames (0)
- , _audio_frames_processed (0)
{
}
@@ -69,15 +70,14 @@ Decoder::~Decoder ()
delete _delay_line;
}
-/** Start off a decode processing run */
+/** Start off a decode processing run. This should only be called once on
+ * a given Decoder object.
+ */
void
Decoder::process_begin ()
{
_delay_in_frames = _film->audio_delay() * audio_sample_rate() / 1000;
- delete _delay_line;
_delay_line = new DelayLine (audio_channels(), _delay_in_frames);
-
- _audio_frames_processed = 0;
}
/** Finish off a decode processing run */
@@ -90,28 +90,44 @@ Decoder::process_end ()
emit_audio (b);
}
- /* If we cut the decode off, the audio may be short; push some silence
- in to get it to the right length.
- */
+ if (_opt->decode_audio && audio_channels()) {
- int64_t const video_length_in_audio_frames = ((int64_t) video_frame_index() * audio_sample_rate() / frames_per_second());
- int64_t const audio_short_by_frames = video_length_in_audio_frames - _audio_frames_processed;
+ /* Ensure that our video and audio emissions are the same length */
- _film->log()->log (
- String::compose ("Source length is %1 (%2 audio frames); %3 frames of audio processed.",
- video_frame_index(),
- video_length_in_audio_frames,
- _audio_frames_processed)
- );
-
- if (audio_short_by_frames > 0 && _opt->decode_audio && audio_channels()) {
+ int64_t audio_short_by_frames = video_frames_to_audio_frames (_video_frames_out) - _audio_frames_out;
- _film->log()->log (String::compose ("Source length is %1; %2 frames of audio processed.", video_frame_index(), _audio_frames_processed));
- _film->log()->log (String::compose ("Adding %1 frames of silence to the end.", audio_short_by_frames));
+ _film->log()->log (
+ String::compose ("Decoder has emitted %1 video frames (which equals %2 audio frames) and %3 audio frames",
+ _video_frames_out,
+ video_frames_to_audio_frames (_video_frames_out),
+ _audio_frames_out)
+ );
- shared_ptr<AudioBuffers> b (new AudioBuffers (audio_channels(), audio_short_by_frames));
- b->make_silent ();
- emit_audio (b);
+ if (audio_short_by_frames < 0) {
+
+ _film->log()->log (String::compose ("Emitted %1 too many audio frames", -audio_short_by_frames));
+
+ /* We have emitted more audio than video. Emit enough black video frames so that we reverse this */
+ int const black_video_frames = ceil (-audio_short_by_frames * frames_per_second() / audio_sample_rate());
+
+ _film->log()->log (String::compose ("Emitting %1 frames of black video", black_video_frames));
+
+ shared_ptr<Image> black (new CompactImage (pixel_format(), native_size()));
+ black->make_black ();
+ for (int i = 0; i < black_video_frames; ++i) {
+ emit_video (black, shared_ptr<Subtitle> ());
+ }
+
+ /* Now recompute our check value */
+ audio_short_by_frames = video_frames_to_audio_frames (_video_frames_out) - _audio_frames_out;
+ }
+
+ if (audio_short_by_frames > 0) {
+ _film->log()->log (String::compose ("Emitted %1 too few audio frames", audio_short_by_frames));
+ shared_ptr<AudioBuffers> b (new AudioBuffers (audio_channels(), audio_short_by_frames));
+ b->make_silent ();
+ emit_audio (b);
+ }
}
}
@@ -127,27 +143,13 @@ Decoder::go ()
while (pass () == false) {
if (_job && _film->dcp_length()) {
- _job->set_progress (float (_video_frame_index) / _film->dcp_length().get());
+ _job->set_progress (float (_video_frames_out) / _film->dcp_length().get());
}
}
process_end ();
}
-/** Run one pass. This may or may not generate any actual video / audio data;
- * some decoders may require several passes to generate a single frame.
- * @return true if we have finished processing all data; otherwise false.
- */
-bool
-Decoder::pass ()
-{
- if (!_ignore_length && _video_frame_index >= _film->dcp_length()) {
- return true;
- }
-
- return do_pass ();
-}
-
/** Called by subclasses to tell the world that some audio data is ready
* @param data Audio data, in Film::audio_sample_format.
* @param size Number of bytes of data.
@@ -229,14 +231,41 @@ Decoder::process_audio (uint8_t* data, int size)
}
_delay_line->feed (audio);
- emit_audio (audio);
+
+ /* Decode range in audio frames */
+ pair<int64_t, int64_t> required_range (
+ video_frames_to_audio_frames (_film->dcp_trim_start()),
+ video_frames_to_audio_frames (_film->dcp_trim_start() + _film->dcp_length().get())
+ );
+
+ /* Range of this block of data */
+ pair<int64_t, int64_t> this_range (
+ _audio_frames_in,
+ _audio_frames_in + audio->frames()
+ );
+
+ /* Trim start */
+ if (required_range.first >= this_range.first && required_range.first < this_range.second) {
+ int64_t const shift = this_range.first - required_range.first;
+ audio->move (shift, 0, audio->frames() - shift);
+ audio->set_frames (audio->frames() - shift);
+ }
+
+ /* Trim end */
+ if (required_range.second >= this_range.first && required_range.second < this_range.second) {
+ audio->set_frames (this_range.first - required_range.second);
+ }
+
+ if (audio->frames()) {
+ emit_audio (audio);
+ }
}
void
Decoder::emit_audio (shared_ptr<AudioBuffers> audio)
{
Audio (audio);
- _audio_frames_processed += audio->frames ();
+ _audio_frames_out += audio->frames ();
}
/** Called by subclasses to tell the world that some video data is ready.
@@ -246,15 +275,22 @@ Decoder::emit_audio (shared_ptr<AudioBuffers> audio)
void
Decoder::process_video (AVFrame* frame)
{
+ assert (_film->length());
+
if (_minimal) {
- ++_video_frame_index;
+ ++_video_frames_in;
return;
}
/* Use Film::length here as our one may be wrong */
- if (_opt->decode_video_skip != 0 && (_video_frame_index % _opt->decode_video_skip) != 0) {
- ++_video_frame_index;
+ if (_opt->decode_video_skip != 0 && (_video_frames_in % _opt->decode_video_skip) != 0) {
+ ++_video_frames_in;
+ return;
+ }
+
+ if (_video_frames_in < _film->dcp_trim_start() || _video_frames_in > (_film->dcp_trim_start() + _film->length().get())) {
+ ++_video_frames_in;
return;
}
@@ -276,20 +312,12 @@ Decoder::process_video (AVFrame* frame)
list<shared_ptr<Image> > images = graph->process (frame);
for (list<shared_ptr<Image> >::iterator i = images.begin(); i != images.end(); ++i) {
- if (_opt->black_after > 0 && _video_frame_index > _opt->black_after) {
- (*i)->make_black ();
- }
-
shared_ptr<Subtitle> sub;
- if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frame_index()) / _film->frames_per_second())) {
+ if (_timed_subtitle && _timed_subtitle->displayed_at (double (video_frames_in()) / _film->frames_per_second())) {
sub = _timed_subtitle->subtitle ();
}
-
- TIMING ("Decoder emits %1", _video_frame_index);
- Video (*i, _video_frame_index, sub);
- ++_video_frame_index;
- _last_image = *i;
- _last_subtitle = sub;
+
+ emit_video (*i, sub);
}
}
@@ -300,9 +328,18 @@ Decoder::repeat_last_video ()
_last_image.reset (new CompactImage (pixel_format(), native_size()));
_last_image->make_black ();
}
-
- Video (_last_image, _video_frame_index, _last_subtitle);
- ++_video_frame_index;
+
+ emit_video (_last_image, _last_subtitle);
+}
+
+void
+Decoder::emit_video (shared_ptr<Image> image, shared_ptr<Subtitle> sub)
+{
+ TIMING ("Decoder emits %1", _video_frames_out);
+ Video (image, _video_frames_out, sub);
+ ++_video_frames_out;
+ _last_image = image;
+ _last_subtitle = sub;
}
void
@@ -322,3 +359,9 @@ Decoder::bytes_per_audio_sample () const
{
return av_get_bytes_per_sample (audio_sample_format ());
}
+
+int64_t
+Decoder::video_frames_to_audio_frames (SourceFrame v) const
+{
+ return ((int64_t) v * audio_sample_rate() / frames_per_second());
+}
diff --git a/src/lib/decoder.h b/src/lib/decoder.h
index 9c7b2de38..2154da8bf 100644
--- a/src/lib/decoder.h
+++ b/src/lib/decoder.h
@@ -52,7 +52,7 @@ class FilterGraph;
class Decoder
{
public:
- Decoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool, bool);
+ Decoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
virtual ~Decoder ();
/* Methods to query our input video */
@@ -76,13 +76,13 @@ public:
virtual int sample_aspect_ratio_denominator () const = 0;
void process_begin ();
- bool pass ();
+ virtual bool pass () = 0;
void process_end ();
void go ();
- /** @return the index of the last video frame to be processed */
- int video_frame_index () const {
- return _video_frame_index;
+ /** @return the number of video frames we got from the source in the last run */
+ SourceFrame video_frames_in () const {
+ return _video_frames_in;
}
virtual std::vector<AudioStream> audio_streams () const {
@@ -94,19 +94,17 @@ public:
}
/** Emitted when a video frame is ready.
- * First parameter is the frame.
+ * First parameter is the frame within the source.
* Second parameter is its index within the content.
* Third parameter is either 0 or a subtitle that should be on this frame.
*/
- boost::signals2::signal<void (boost::shared_ptr<Image>, int, boost::shared_ptr<Subtitle>)> Video;
+ boost::signals2::signal<void (boost::shared_ptr<Image>, SourceFrame, boost::shared_ptr<Subtitle>)> Video;
/** Emitted when some audio data is ready */
boost::signals2::signal<void (boost::shared_ptr<AudioBuffers>)> Audio;
protected:
- /** perform a single pass at our content */
- virtual bool do_pass () = 0;
virtual PixelFormat pixel_format () const = 0;
void process_video (AVFrame *);
@@ -128,25 +126,22 @@ protected:
*/
bool _minimal;
- /** ignore_length Ignore the content's claimed length when computing progress */
- bool _ignore_length;
-
private:
+ void emit_video (boost::shared_ptr<Image>, boost::shared_ptr<Subtitle>);
void emit_audio (boost::shared_ptr<AudioBuffers>);
-
- /** last video frame to be processed */
- int _video_frame_index;
+ int64_t video_frames_to_audio_frames (SourceFrame v) const;
+
+ SourceFrame _video_frames_in;
+ SourceFrame _video_frames_out;
+ int64_t _audio_frames_in;
+ int64_t _audio_frames_out;
+
std::list<boost::shared_ptr<FilterGraph> > _filter_graphs;
DelayLine* _delay_line;
int _delay_in_frames;
- /* Number of audio frames that we have pushed to the encoder
- (at the DCP sample rate).
- */
- int64_t _audio_frames_processed;
-
boost::shared_ptr<TimedSubtitle> _timed_subtitle;
boost::shared_ptr<Image> _last_image;
diff --git a/src/lib/decoder_factory.cc b/src/lib/decoder_factory.cc
index 06377e26c..287bba0da 100644
--- a/src/lib/decoder_factory.cc
+++ b/src/lib/decoder_factory.cc
@@ -32,20 +32,17 @@ using boost::shared_ptr;
shared_ptr<Decoder>
decoder_factory (
- shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, bool minimal = false, bool ignore_length = false
+ shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, bool minimal = false
)
{
if (boost::filesystem::is_directory (f->content_path ())) {
/* Assume a directory contains TIFFs */
- return shared_ptr<Decoder> (new TIFFDecoder (f, o, j, minimal, ignore_length));
+ return shared_ptr<Decoder> (new TIFFDecoder (f, o, j, minimal));
}
if (f->content_type() == STILL) {
- /* Always ignore length of decodes of stills, since the decoder finishes very quickly
- and it's the encoder that takes the time.
- */
- return shared_ptr<Decoder> (new ImageMagickDecoder (f, o, j, minimal, true));
+ return shared_ptr<Decoder> (new ImageMagickDecoder (f, o, j, minimal));
}
- return shared_ptr<Decoder> (new FFmpegDecoder (f, o, j, minimal, ignore_length));
+ return shared_ptr<Decoder> (new FFmpegDecoder (f, o, j, minimal));
}
diff --git a/src/lib/decoder_factory.h b/src/lib/decoder_factory.h
index 81dcec944..b86c60c70 100644
--- a/src/lib/decoder_factory.h
+++ b/src/lib/decoder_factory.h
@@ -28,5 +28,5 @@ class Job;
class Log;
extern boost::shared_ptr<Decoder> decoder_factory (
- boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool minimal = false, bool ignore_length = false
+ boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool minimal = false
);
diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc
index 7352dcfb1..bb23c9e59 100644
--- a/src/lib/encoder.cc
+++ b/src/lib/encoder.cc
@@ -67,7 +67,7 @@ Encoder::skipping () const
}
/** @return Index of last frame to be successfully encoded */
-int
+SourceFrame
Encoder::last_frame () const
{
boost::mutex::scoped_lock (_history_mutex);
@@ -75,10 +75,10 @@ Encoder::last_frame () const
}
/** Should be called when a frame has been encoded successfully.
- * @param n Frame index.
+ * @param n Source frame index.
*/
void
-Encoder::frame_done (int n)
+Encoder::frame_done (SourceFrame n)
{
boost::mutex::scoped_lock lock (_history_mutex);
_just_skipped = false;
diff --git a/src/lib/encoder.h b/src/lib/encoder.h
index 590b8aaa9..704b55e46 100644
--- a/src/lib/encoder.h
+++ b/src/lib/encoder.h
@@ -31,6 +31,7 @@
extern "C" {
#include <libavutil/samplefmt.h>
}
+#include "util.h"
class Options;
class Image;
@@ -58,10 +59,10 @@ public:
/** Called with a frame of video.
* @param i Video frame image.
- * @param f Frame number within the film.
+ * @param f Frame number within the film's source.
* @param s A subtitle that should be on this frame, or 0.
*/
- virtual void process_video (boost::shared_ptr<const Image> i, int f, boost::shared_ptr<Subtitle> s) = 0;
+ virtual void process_video (boost::shared_ptr<const Image> i, SourceFrame f, boost::shared_ptr<Subtitle> s) = 0;
/** Called with some audio data.
* @param d Array of pointers to floating point sample data for each channel.
@@ -74,10 +75,10 @@ public:
float current_frames_per_second () const;
bool skipping () const;
- int last_frame () const;
+ SourceFrame last_frame () const;
protected:
- void frame_done (int n);
+ void frame_done (SourceFrame n);
void frame_skipped ();
/** Film that we are encoding */
@@ -95,8 +96,8 @@ protected:
static int const _history_size;
/** true if the last frame we processed was skipped (because it was already done) */
bool _just_skipped;
- /** Index of the last frame to be processed */
- int _last_frame;
+ /** Source index of the last frame to be processed */
+ SourceFrame _last_frame;
};
#endif
diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc
index 6d1233a8c..d325102a3 100644
--- a/src/lib/examine_content_job.cc
+++ b/src/lib/examine_content_job.cc
@@ -66,12 +66,12 @@ ExamineContentJob::run ()
descend (0.5);
- _decoder = decoder_factory (_film, o, this, true, true);
+ _decoder = decoder_factory (_film, o, this, true);
_decoder->go ();
- _film->set_length (_decoder->video_frame_index());
+ _film->set_length (_decoder->video_frames_in());
- _film->log()->log (String::compose ("Video length is %1 frames", _decoder->video_frame_index()));
+ _film->log()->log (String::compose ("Video length is %1 frames", _film->length()));
ascend ();
@@ -105,7 +105,7 @@ ExamineContentJob::run ()
}
string const tdir = _film->dir ("thumbs");
- vector<int> thumbs;
+ vector<SourceFrame> thumbs;
for (boost::filesystem::directory_iterator i = boost::filesystem::directory_iterator (tdir); i != boost::filesystem::directory_iterator(); ++i) {
diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc
index 09f699543..fa6500b9e 100644
--- a/src/lib/ffmpeg_decoder.cc
+++ b/src/lib/ffmpeg_decoder.cc
@@ -55,8 +55,8 @@ using std::vector;
using std::stringstream;
using boost::shared_ptr;
-FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, bool minimal, bool ignore_length)
- : Decoder (f, o, j, minimal, ignore_length)
+FFmpegDecoder::FFmpegDecoder (shared_ptr<Film> f, shared_ptr<const Options> o, Job* j, bool minimal)
+ : Decoder (f, o, j, minimal)
, _format_context (0)
, _video_stream (-1)
, _audio_stream (-1)
@@ -218,7 +218,7 @@ FFmpegDecoder::setup_subtitle ()
bool
-FFmpegDecoder::do_pass ()
+FFmpegDecoder::pass ()
{
int r = av_read_frame (_format_context, &_packet);
@@ -270,7 +270,7 @@ FFmpegDecoder::do_pass ()
}
/* Where we are in the output, in seconds */
- double const out_pts_seconds = video_frame_index() / frames_per_second();
+ double const out_pts_seconds = video_frames_in() / frames_per_second();
/* Where we are in the source, in seconds */
double const source_pts_seconds = av_q2d (_format_context->streams[_packet.stream_index]->time_base)
@@ -291,8 +291,8 @@ FFmpegDecoder::do_pass ()
repeat_last_video ();
_film->log()->log (
String::compose (
- "Extra frame inserted at %1s; DCP frame %2, source PTS %3",
- out_pts_seconds, video_frame_index(), source_pts_seconds
+ "Extra frame inserted at %1s; source frame %2, source PTS %3",
+ out_pts_seconds, video_frames_in(), source_pts_seconds
)
);
}
diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h
index c04dba5b3..fbd9e5255 100644
--- a/src/lib/ffmpeg_decoder.h
+++ b/src/lib/ffmpeg_decoder.h
@@ -52,7 +52,7 @@ class Log;
class FFmpegDecoder : public Decoder
{
public:
- FFmpegDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool, bool);
+ FFmpegDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
~FFmpegDecoder ();
/* Methods to query our input video */
@@ -69,7 +69,7 @@ public:
private:
- bool do_pass ();
+ bool pass ();
PixelFormat pixel_format () const;
int time_base_numerator () const;
int time_base_denominator () const;
diff --git a/src/lib/film.cc b/src/lib/film.cc
index d29c04465..cacd30764 100644
--- a/src/lib/film.cc
+++ b/src/lib/film.cc
@@ -82,7 +82,8 @@ Film::Film (string d, bool must_exist)
, _dcp_content_type (0)
, _format (0)
, _scaler (Scaler::from_id ("bicubic"))
- , _dcp_trim_action (CUT)
+ , _dcp_trim_start (0)
+ , _dcp_trim_end (0)
, _dcp_ab (false)
, _audio_stream (-1)
, _audio_gain (0)
@@ -142,8 +143,8 @@ Film::Film (Film const & o)
, _crop (o._crop)
, _filters (o._filters)
, _scaler (o._scaler)
- , _dcp_frames (o._dcp_frames)
- , _dcp_trim_action (o._dcp_trim_action)
+ , _dcp_trim_start (o._dcp_trim_start)
+ , _dcp_trim_end (o._dcp_trim_end)
, _dcp_ab (o._dcp_ab)
, _audio_stream (o._audio_stream)
, _audio_gain (o._audio_gain)
@@ -254,21 +255,6 @@ Film::make_dcp (bool transcode)
shared_ptr<Options> o (new Options (j2k_dir(), ".j2c", dir ("wavs")));
o->out_size = format()->dcp_size ();
- if (!dcp_frames()) {
- /* Decode the whole film, no blacking */
- o->black_after = 0;
- } else {
- switch (dcp_trim_action()) {
- case CUT:
- /* Decode only part of the film, no blacking */
- o->black_after = 0;
- break;
- case BLACK_OUT:
- /* Decode the whole film, but black some frames out */
- o->black_after = dcp_frames().get ();
- }
- }
-
o->padding = format()->dcp_padding (shared_from_this ());
o->ratio = format()->ratio_as_float (shared_from_this ());
o->decode_subtitles = with_subtitles ();
@@ -296,7 +282,7 @@ Film::examine_content ()
return;
}
- set_thumbs (vector<int> ());
+ set_thumbs (vector<SourceFrame> ());
boost::filesystem::remove_all (dir ("thumbs"));
/* This call will recreate the directory */
@@ -420,18 +406,8 @@ Film::write_metadata () const
f << "filter " << (*i)->id () << "\n";
}
f << "scaler " << _scaler->id () << "\n";
- f << "dcp_frames " << _dcp_frames.get_value_or(0) << "\n";
-
- f << "dcp_trim_action ";
- switch (_dcp_trim_action) {
- case CUT:
- f << "cut\n";
- break;
- case BLACK_OUT:
- f << "black_out\n";
- break;
- }
-
+ f << "dcp_trim_start " << _dcp_trim_start << "\n";
+ f << "dcp_trim_end " << _dcp_trim_end << "\n";
f << "dcp_ab " << (_dcp_ab ? "1" : "0") << "\n";
f << "selected_audio_stream " << _audio_stream << "\n";
f << "audio_gain " << _audio_gain << "\n";
@@ -452,7 +428,7 @@ Film::write_metadata () const
/* Cached stuff; this is information about our content; we could
look it up each time, but that's slow.
*/
- for (vector<int>::const_iterator i = _thumbs.begin(); i != _thumbs.end(); ++i) {
+ for (vector<SourceFrame>::const_iterator i = _thumbs.begin(); i != _thumbs.end(); ++i) {
f << "thumb " << *i << "\n";
}
f << "width " << _size.width << "\n";
@@ -510,17 +486,10 @@ Film::read_metadata ()
_filters.push_back (Filter::from_id (v));
} else if (k == "scaler") {
_scaler = Scaler::from_id (v);
- } else if (k == "dcp_frames") {
- int const vv = atoi (v.c_str ());
- if (vv) {
- _dcp_frames = vv;
- }
- } else if (k == "dcp_trim_action") {
- if (v == "cut") {
- _dcp_trim_action = CUT;
- } else if (v == "black_out") {
- _dcp_trim_action = BLACK_OUT;
- }
+ } else if (k == "dcp_trim_start") {
+ _dcp_trim_start = atoi (v.c_str ());
+ } else if (k == "dcp_trim_end") {
+ _dcp_trim_end = atoi (v.c_str ());
} else if (k == "dcp_ab") {
_dcp_ab = (v == "1");
} else if (k == "selected_audio_stream") {
@@ -598,17 +567,19 @@ Film::thumb_file (int n) const
return thumb_file_for_frame (thumb_frame (n));
}
-/** @param n A frame index within the Film.
+/** @param n A frame index within the Film's source.
* @return The path to the thumb's image file for this frame;
* we assume that it exists.
*/
string
-Film::thumb_file_for_frame (int n) const
+Film::thumb_file_for_frame (SourceFrame n) const
{
return thumb_base_for_frame(n) + ".png";
}
-/** Must not be called with the _state_mutex locked */
+/** @param n Thumb index.
+ * Must not be called with the _state_mutex locked.
+ */
string
Film::thumb_base (int n) const
{
@@ -616,7 +587,7 @@ Film::thumb_base (int n) const
}
string
-Film::thumb_base_for_frame (int n) const
+Film::thumb_base_for_frame (SourceFrame n) const
{
stringstream s;
s.width (8);
@@ -630,11 +601,11 @@ Film::thumb_base_for_frame (int n) const
}
/** @param n A thumb index.
- * @return The frame within the Film that it is for.
+ * @return The frame within the Film's source that it is for.
*
* Must not be called with the _state_mutex locked.
*/
-int
+SourceFrame
Film::thumb_frame (int n) const
{
boost::mutex::scoped_lock lm (_state_mutex);
@@ -729,18 +700,14 @@ Film::target_audio_sample_rate () const
return rint (t);
}
-boost::optional<int>
+boost::optional<SourceFrame>
Film::dcp_length () const
{
if (!length()) {
- return boost::optional<int> ();
+ return boost::optional<SourceFrame> ();
}
- if (dcp_frames()) {
- return min (dcp_frames().get(), length().get());
- }
-
- return length();
+ return length().get() - dcp_trim_start() - dcp_trim_end();
}
/** @return a DCI-compliant name for a DCP of this film */
@@ -1049,33 +1016,23 @@ Film::set_scaler (Scaler const * s)
}
void
-Film::set_dcp_frames (int f)
-{
- {
- boost::mutex::scoped_lock lm (_state_mutex);
- _dcp_frames = f;
- }
- signal_changed (DCP_FRAMES);
-}
-
-void
-Film::unset_dcp_frames ()
+Film::set_dcp_trim_start (int t)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _dcp_frames = boost::none;
+ _dcp_trim_start = t;
}
- signal_changed (DCP_FRAMES);
+ signal_changed (DCP_TRIM_START);
}
void
-Film::set_dcp_trim_action (TrimAction a)
+Film::set_dcp_trim_end (int t)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
- _dcp_trim_action = a;
+ _dcp_trim_end = t;
}
- signal_changed (DCP_TRIM_ACTION);
+ signal_changed (DCP_TRIM_END);
}
void
@@ -1239,7 +1196,7 @@ Film::set_package_type (string p)
}
void
-Film::set_thumbs (vector<int> t)
+Film::set_thumbs (vector<SourceFrame> t)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
@@ -1259,7 +1216,7 @@ Film::set_size (Size s)
}
void
-Film::set_length (int l)
+Film::set_length (SourceFrame l)
{
{
boost::mutex::scoped_lock lm (_state_mutex);
diff --git a/src/lib/film.h b/src/lib/film.h
index f3ddc652a..06ebba3ce 100644
--- a/src/lib/film.h
+++ b/src/lib/film.h
@@ -38,7 +38,6 @@ extern "C" {
#include "dcp_content_type.h"
#include "util.h"
#include "stream.h"
-#include "trim_action.h"
class Format;
class Job;
@@ -88,7 +87,7 @@ public:
std::string thumb_file (int) const;
std::string thumb_base (int) const;
- int thumb_frame (int) const;
+ SourceFrame thumb_frame (int) const;
int target_audio_sample_rate () const;
@@ -96,7 +95,7 @@ public:
void read_metadata ();
Size cropped_size (Size) const;
- boost::optional<int> dcp_length () const;
+ boost::optional<SourceFrame> dcp_length () const;
std::string dci_name () const;
std::string dcp_name () const;
@@ -118,8 +117,8 @@ public:
CROP,
FILTERS,
SCALER,
- DCP_FRAMES,
- DCP_TRIM_ACTION,
+ DCP_TRIM_START,
+ DCP_TRIM_END,
DCP_AB,
AUDIO_STREAM,
AUDIO_GAIN,
@@ -188,16 +187,16 @@ public:
return _scaler;
}
- boost::optional<int> dcp_frames () const {
+ SourceFrame dcp_trim_start () const {
boost::mutex::scoped_lock lm (_state_mutex);
- return _dcp_frames;
+ return _dcp_trim_start;
}
- TrimAction dcp_trim_action () const {
+ SourceFrame dcp_trim_end () const {
boost::mutex::scoped_lock lm (_state_mutex);
- return _dcp_trim_action;
+ return _dcp_trim_end;
}
-
+
bool dcp_ab () const {
boost::mutex::scoped_lock lm (_state_mutex);
return _dcp_ab;
@@ -290,7 +289,7 @@ public:
return _package_type;
}
- std::vector<int> thumbs () const {
+ std::vector<SourceFrame> thumbs () const {
boost::mutex::scoped_lock lm (_state_mutex);
return _thumbs;
}
@@ -300,7 +299,7 @@ public:
return _size;
}
- boost::optional<int> length () const {
+ boost::optional<SourceFrame> length () const {
boost::mutex::scoped_lock lm (_state_mutex);
return _length;
}
@@ -351,9 +350,8 @@ public:
void set_bottom_crop (int);
void set_filters (std::vector<Filter const *>);
void set_scaler (Scaler const *);
- void set_dcp_frames (int);
- void unset_dcp_frames ();
- void set_dcp_trim_action (TrimAction);
+ void set_dcp_trim_start (int);
+ void set_dcp_trim_end (int);
void set_dcp_ab (bool);
void set_audio_stream (int);
void set_audio_gain (float);
@@ -370,9 +368,9 @@ public:
void set_studio (std::string);
void set_facility (std::string);
void set_package_type (std::string);
- void set_thumbs (std::vector<int>);
+ void set_thumbs (std::vector<SourceFrame>);
void set_size (Size);
- void set_length (int);
+ void set_length (SourceFrame);
void unset_length ();
void set_audio_sample_rate (int);
void set_content_digest (std::string);
@@ -394,8 +392,8 @@ private:
boost::gregorian::date _dci_date;
- std::string thumb_file_for_frame (int) const;
- std::string thumb_base_for_frame (int) const;
+ std::string thumb_file_for_frame (SourceFrame) const;
+ std::string thumb_base_for_frame (SourceFrame) const;
void signal_changed (Property);
void examine_content_finished ();
@@ -424,10 +422,8 @@ private:
std::vector<Filter const *> _filters;
/** Scaler algorithm to use */
Scaler const * _scaler;
- /** Maximum number of frames to put in the DCP, if applicable */
- boost::optional<int> _dcp_frames;
- /** What to do with audio when trimming DCPs */
- TrimAction _dcp_trim_action;
+ SourceFrame _dcp_trim_start;
+ SourceFrame _dcp_trim_end;
/** true to create an A/B comparison DCP, where the left half of the image
is the video without any filters or post-processing, and the right half
has the specified filters and post-processing.
@@ -464,11 +460,11 @@ private:
/* Data which are cached to speed things up */
/** Vector of frame indices for each of our `thumbnails' */
- std::vector<int> _thumbs;
+ std::vector<SourceFrame> _thumbs;
/** Size, in pixels, of the source (ignoring cropping) */
Size _size;
/** Actual length of the source (in video frames) from examining it */
- boost::optional<int> _length;
+ boost::optional<SourceFrame> _length;
/** Sample rate of the source audio, in Hz */
int _audio_sample_rate;
/** MD5 digest of our content file */
diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc
index 76d89b7d8..81349beca 100644
--- a/src/lib/imagemagick_decoder.cc
+++ b/src/lib/imagemagick_decoder.cc
@@ -27,8 +27,8 @@ using namespace std;
using namespace boost;
ImageMagickDecoder::ImageMagickDecoder (
- boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal, bool ignore_length)
- : Decoder (f, o, j, minimal, ignore_length)
+ boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal)
+ : Decoder (f, o, j, minimal)
, _done (false)
{
_magick_image = new Magick::Image (_film->content_path ());
@@ -41,7 +41,7 @@ ImageMagickDecoder::native_size () const
}
bool
-ImageMagickDecoder::do_pass ()
+ImageMagickDecoder::pass ()
{
using namespace MagickCore;
diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h
index 13b53b685..85bcf4c5b 100644
--- a/src/lib/imagemagick_decoder.h
+++ b/src/lib/imagemagick_decoder.h
@@ -26,7 +26,7 @@ namespace Magick {
class ImageMagickDecoder : public Decoder
{
public:
- ImageMagickDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool, bool);
+ ImageMagickDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
float frames_per_second () const {
return static_frames_per_second ();
@@ -59,7 +59,7 @@ public:
}
protected:
- bool do_pass ();
+ bool pass ();
PixelFormat pixel_format () const;
int time_base_numerator () const {
diff --git a/src/lib/imagemagick_encoder.cc b/src/lib/imagemagick_encoder.cc
index e8b060997..e0e2d1cdc 100644
--- a/src/lib/imagemagick_encoder.cc
+++ b/src/lib/imagemagick_encoder.cc
@@ -50,7 +50,7 @@ ImageMagickEncoder::ImageMagickEncoder (shared_ptr<const Film> f, shared_ptr<con
}
void
-ImageMagickEncoder::process_video (shared_ptr<const Image> image, int frame, shared_ptr<Subtitle> sub)
+ImageMagickEncoder::process_video (shared_ptr<const Image> image, SourceFrame frame, shared_ptr<Subtitle> sub)
{
shared_ptr<Image> scaled = image->scale_and_convert_to_rgb (_opt->out_size, _opt->padding, _film->scaler());
shared_ptr<Image> compact (new CompactImage (scaled));
diff --git a/src/lib/imagemagick_encoder.h b/src/lib/imagemagick_encoder.h
index c112300e3..3d8edd25e 100644
--- a/src/lib/imagemagick_encoder.h
+++ b/src/lib/imagemagick_encoder.h
@@ -37,7 +37,7 @@ public:
ImageMagickEncoder (boost::shared_ptr<const Film> f, boost::shared_ptr<const Options> o);
void process_begin (int64_t audio_channel_layout) {}
- void process_video (boost::shared_ptr<const Image>, int, boost::shared_ptr<Subtitle>);
+ void process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
void process_audio (boost::shared_ptr<const AudioBuffers>) {}
void process_end () {}
};
diff --git a/src/lib/j2k_still_encoder.cc b/src/lib/j2k_still_encoder.cc
index edcf0de89..aab686417 100644
--- a/src/lib/j2k_still_encoder.cc
+++ b/src/lib/j2k_still_encoder.cc
@@ -49,7 +49,7 @@ J2KStillEncoder::J2KStillEncoder (shared_ptr<const Film> f, shared_ptr<const Opt
}
void
-J2KStillEncoder::process_video (shared_ptr<const Image> yuv, int frame, shared_ptr<Subtitle> sub)
+J2KStillEncoder::process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
{
pair<string, string> const s = Filter::ffmpeg_strings (_film->filters());
DCPVideoFrame* f = new DCPVideoFrame (
diff --git a/src/lib/j2k_still_encoder.h b/src/lib/j2k_still_encoder.h
index 86bebc0d2..89222ce18 100644
--- a/src/lib/j2k_still_encoder.h
+++ b/src/lib/j2k_still_encoder.h
@@ -37,7 +37,7 @@ public:
J2KStillEncoder (boost::shared_ptr<const Film>, boost::shared_ptr<const Options>);
void process_begin (int64_t audio_channel_layout) {}
- void process_video (boost::shared_ptr<const Image>, int, boost::shared_ptr<Subtitle>);
+ void process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
void process_audio (boost::shared_ptr<const AudioBuffers>) {}
void process_end () {}
};
diff --git a/src/lib/j2k_wav_encoder.cc b/src/lib/j2k_wav_encoder.cc
index bac7d5f35..f93fd9460 100644
--- a/src/lib/j2k_wav_encoder.cc
+++ b/src/lib/j2k_wav_encoder.cc
@@ -106,7 +106,7 @@ J2KWAVEncoder::close_sound_files ()
}
void
-J2KWAVEncoder::process_video (shared_ptr<const Image> yuv, int frame, shared_ptr<Subtitle> sub)
+J2KWAVEncoder::process_video (shared_ptr<const Image> yuv, SourceFrame frame, shared_ptr<Subtitle> sub)
{
boost::mutex::scoped_lock lock (_worker_mutex);
diff --git a/src/lib/j2k_wav_encoder.h b/src/lib/j2k_wav_encoder.h
index 99924829d..2272d7f49 100644
--- a/src/lib/j2k_wav_encoder.h
+++ b/src/lib/j2k_wav_encoder.h
@@ -51,7 +51,7 @@ public:
~J2KWAVEncoder ();
void process_begin (int64_t audio_channel_layout);
- void process_video (boost::shared_ptr<const Image>, int, boost::shared_ptr<Subtitle>);
+ void process_video (boost::shared_ptr<const Image>, SourceFrame, boost::shared_ptr<Subtitle>);
void process_audio (boost::shared_ptr<const AudioBuffers>);
void process_end ();
diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc
index 4102f8384..a1ffd9672 100644
--- a/src/lib/make_dcp_job.cc
+++ b/src/lib/make_dcp_job.cc
@@ -55,10 +55,12 @@ MakeDCPJob::name () const
return String::compose ("Make DCP for %1", _film->name());
}
+/** @param f DCP frame index */
string
MakeDCPJob::j2c_path (int f) const
{
- return _opt->frame_out_path (f * dcp_frame_rate(_film->frames_per_second()).skip, false);
+ SourceFrame const s = (f * dcp_frame_rate(_film->frames_per_second()).skip) + _film->dcp_trim_start();
+ return _opt->frame_out_path (s, false);
}
string
@@ -84,6 +86,7 @@ MakeDCPJob::run ()
int frames = 0;
switch (_film->content_type ()) {
case VIDEO:
+ /* Source frames -> DCP frames */
frames = _film->dcp_length().get() / dfr.skip;
break;
case STILL:
diff --git a/src/lib/options.h b/src/lib/options.h
index f4381ef68..043e3692f 100644
--- a/src/lib/options.h
+++ b/src/lib/options.h
@@ -39,7 +39,6 @@ public:
Options (std::string f, std::string e, std::string m)
: padding (0)
, apply_crop (true)
- , black_after (0)
, decode_video_skip (0)
, decode_audio (true)
, decode_subtitles (false)
@@ -53,11 +52,11 @@ public:
return _frame_out_path;
}
- /** @param f Frame index.
+ /** @param f Source frame index.
* @param t true to return a temporary file path, otherwise a permanent one.
* @return The path to write this video frame to.
*/
- std::string frame_out_path (int f, bool t, std::string e = "") const {
+ std::string frame_out_path (SourceFrame f, bool t, std::string e = "") const {
if (e.empty ()) {
e = _frame_out_extension;
}
@@ -97,9 +96,10 @@ public:
float ratio; ///< ratio of the wanted output image (not considering padding)
int padding; ///< number of pixels of padding (in terms of the output size) each side of the image
bool apply_crop; ///< true to apply cropping
- int black_after; ///< first frame for which to output a black frame, rather than the actual video content, or 0 for none
- int decode_video_skip; ///< skip frames such that we don't decode any frame where (index % decode_video_skip) != 0; e.g.
- ///< 1 for every frame, 2 for every other frame, etc.
+ /** Skip frames such that we don't decode any frame where (index % decode_video_skip) != 0; e.g.
+ * 1 for every frame, 2 for every other frame, etc.
+ */
+ SourceFrame decode_video_skip;
bool decode_audio; ///< true to decode audio, otherwise false
bool decode_subtitles;
diff --git a/src/lib/tiff_decoder.cc b/src/lib/tiff_decoder.cc
index 1500b9b48..2c050def6 100644
--- a/src/lib/tiff_decoder.cc
+++ b/src/lib/tiff_decoder.cc
@@ -46,10 +46,9 @@ using namespace boost;
* @param j Job that we are associated with, or 0.
* @param minimal true to do the bare minimum of work; just run through the content. Useful for acquiring
* accurate frame counts as quickly as possible. This generates no video or audio output.
- * @param ignore_length Ignore the content's claimed length when computing progress.
*/
-TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal, bool ignore_length)
- : Decoder (f, o, j, minimal, ignore_length)
+TIFFDecoder::TIFFDecoder (boost::shared_ptr<Film> f, boost::shared_ptr<const Options> o, Job* j, bool minimal)
+ : Decoder (f, o, j, minimal)
{
string const dir = _film->content_path ();
@@ -131,7 +130,7 @@ TIFFDecoder::audio_channel_layout () const
}
bool
-TIFFDecoder::do_pass ()
+TIFFDecoder::pass ()
{
if (_iter == _files.end ()) {
return true;
diff --git a/src/lib/tiff_decoder.h b/src/lib/tiff_decoder.h
index 1c287ee06..c02a1d03d 100644
--- a/src/lib/tiff_decoder.h
+++ b/src/lib/tiff_decoder.h
@@ -42,7 +42,7 @@ class Image;
class TIFFDecoder : public Decoder
{
public:
- TIFFDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool, bool);
+ TIFFDecoder (boost::shared_ptr<Film>, boost::shared_ptr<const Options>, Job *, bool);
/* Methods to query our input video */
float frames_per_second () const;
@@ -56,7 +56,7 @@ public:
}
private:
- bool do_pass ();
+ bool pass ();
PixelFormat pixel_format () const;
int time_base_numerator () const;
int time_base_denominator () const;
diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc
index 877214316..31808c103 100644
--- a/src/lib/transcode_job.cc
+++ b/src/lib/transcode_job.cc
@@ -110,5 +110,6 @@ TranscodeJob::remaining_time () const
}
/* We assume that dcp_length() is valid */
- return ((_film->dcp_length().get() - _encoder->last_frame()) / fps);
+ SourceFrame const left = _film->dcp_length().get() - _encoder->last_frame() - _film->dcp_trim_start();
+ return left / fps;
}
diff --git a/src/lib/trim_action.h b/src/lib/trim_action.h
deleted file mode 100644
index 405d31bbc..000000000
--- a/src/lib/trim_action.h
+++ /dev/null
@@ -1,28 +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.
-
-*/
-
-#ifndef DVDOMATIC_TRIM_ACTION_H
-#define DVDOMATIC_TRIM_ACTION_H
-
-enum TrimAction {
- CUT, ///< cut everything out after dcp_frames
- BLACK_OUT ///< black out after dcp_frames so that the film stays the same length (and audio continues)
-};
-
-#endif
diff --git a/src/lib/util.h b/src/lib/util.h
index f640122e2..bb0a70a05 100644
--- a/src/lib/util.h
+++ b/src/lib/util.h
@@ -54,6 +54,8 @@ extern std::string md5_digest (std::string);
extern std::string md5_digest (void const *, int);
extern void ensure_ui_thread ();
+typedef int SourceFrame;
+
struct DCPFrameRate
{
int frames_per_second;