From 39c65e47432c76a4e34aaea5317bd7362409aed0 Mon Sep 17 00:00:00 2001 From: Carl Hetherington Date: Thu, 17 Jan 2013 21:30:16 +0000 Subject: [PATCH 1/1] Try to tidy up frame indexing; use DCP length obtained from the transcode to make the DCP. --- src/lib/check_hashes_job.cc | 12 ++++------ src/lib/dcp_video_frame.cc | 9 ++++---- src/lib/dcp_video_frame.h | 12 +++++----- src/lib/encoder.cc | 39 +++++++++++++++++++-------------- src/lib/encoder.h | 12 ++++++---- src/lib/ffmpeg_decoder.cc | 1 + src/lib/ffmpeg_decoder.h | 2 +- src/lib/film.cc | 40 +++++++++++++++++++++------------- src/lib/film.h | 26 ++++++++++++++-------- src/lib/filter_graph.cc | 1 + src/lib/filter_graph.h | 6 ++--- src/lib/format.cc | 1 + src/lib/format.h | 10 ++++----- src/lib/image.cc | 1 + src/lib/image.h | 14 ++++++------ src/lib/imagemagick_decoder.cc | 3 ++- src/lib/imagemagick_decoder.h | 2 +- src/lib/make_dcp_job.cc | 32 +++++++-------------------- src/lib/matcher.h | 2 +- src/lib/server.cc | 1 + src/lib/subtitle.cc | 1 + src/lib/transcode_job.cc | 15 +++++++++++-- src/lib/util.cc | 11 +--------- src/lib/util.h | 34 ++++------------------------- src/lib/video_decoder.h | 2 +- src/wx/film_editor.cc | 2 ++ src/wx/film_viewer.cc | 1 + src/wx/properties_dialog.cc | 4 ++-- test/metadata.ref | 1 + test/test.cc | 14 ++++++------ 30 files changed, 154 insertions(+), 157 deletions(-) diff --git a/src/lib/check_hashes_job.cc b/src/lib/check_hashes_job.cc index cf4e86b79..55a744552 100644 --- a/src/lib/check_hashes_job.cc +++ b/src/lib/check_hashes_job.cc @@ -53,16 +53,12 @@ CheckHashesJob::run () { _bad = 0; - if (!_film->dcp_length()) { - throw EncodeError ("cannot check hashes of a DCP with unknown length"); + if (!_film->dcp_intrinsic_duration()) { + throw EncodeError ("cannot check hashes of a DCP with unknown intrinsic duration"); } - SourceFrame const N = _film->trim_start() + _film->dcp_length().get(); - DCPFrameRate const dfr (_film->frames_per_second ()); - - int const inc = dfr.skip ? 2 : 1; - - for (SourceFrame i = _film->trim_start(); i < N; i += inc) { + int const N = _film->dcp_intrinsic_duration().get(); + for (int i = 0; i < N; ++i) { string const j2k_file = _film->frame_out_path (i, false); string const hash_file = _film->hash_out_path (i, false); diff --git a/src/lib/dcp_video_frame.cc b/src/lib/dcp_video_frame.cc index c00ed9b88..427d447ef 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -60,13 +60,14 @@ using std::string; using std::stringstream; using std::ofstream; using boost::shared_ptr; +using libdcp::Size; /** Construct a DCP video frame. * @param input Input image. * @param out Required size of output, in pixels (including any padding). * @param s Scaler to use. * @param p Number of pixels of padding either side of the image. - * @param f Index of the frame within the Film's source. + * @param f Index of the frame within the DCP's intrinsic duration. * @param fps Frames per second of the Film's source. * @param pp FFmpeg post-processing string to use. * @param clut Colour look-up table to use (see Config::colour_lut_index ()) @@ -76,7 +77,7 @@ using boost::shared_ptr; DCPVideoFrame::DCPVideoFrame ( shared_ptr yuv, shared_ptr sub, Size out, int p, int subtitle_offset, float subtitle_scale, - Scaler const * s, SourceFrame f, float fps, string pp, int clut, int bw, Log* l + Scaler const * s, int f, float fps, string pp, int clut, int bw, Log* l ) : _input (yuv) , _subtitle (sub) @@ -373,10 +374,10 @@ DCPVideoFrame::encode_remotely (ServerDescription const * serv) /** Write this data to a J2K file. * @param opt Options. - * @param frame Frame index. + * @param frame DCP Frame index. */ void -EncodedData::write (shared_ptr film, SourceFrame frame) +EncodedData::write (shared_ptr film, int frame) { string const tmp_j2k = film->frame_out_path (frame, true); diff --git a/src/lib/dcp_video_frame.h b/src/lib/dcp_video_frame.h index 1b75cb207..4271ebb28 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); - void write (boost::shared_ptr, SourceFrame); + void write (boost::shared_ptr, int); /** @return data */ uint8_t* data () const { @@ -107,8 +107,8 @@ class DCPVideoFrame { public: DCPVideoFrame ( - boost::shared_ptr, boost::shared_ptr, Size, - int, int, float, Scaler const *, SourceFrame, float, std::string, int, int, Log * + boost::shared_ptr, boost::shared_ptr, libdcp::Size, + int, int, float, Scaler const *, int, float, std::string, int, int, Log * ); virtual ~DCPVideoFrame (); @@ -116,7 +116,7 @@ public: boost::shared_ptr encode_locally (); boost::shared_ptr encode_remotely (ServerDescription const *); - SourceFrame frame () const { + int frame () const { return _frame; } @@ -125,12 +125,12 @@ private: boost::shared_ptr _input; ///< the input image boost::shared_ptr _subtitle; ///< any subtitle that should be on the image - Size _out_size; ///< the required size of the output, in pixels + libdcp::Size _out_size; ///< the required size of the output, in pixels int _padding; int _subtitle_offset; float _subtitle_scale; Scaler const * _scaler; ///< scaler to use - SourceFrame _frame; ///< frame index within the Film's source + int _frame; ///< frame index within the DCP's intrinsic duration 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; ///< Colour look-up table to use diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index c32d68834..6df7c85a1 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -54,12 +54,13 @@ int const Encoder::_history_size = 25; Encoder::Encoder (shared_ptr f) : _film (f) , _just_skipped (false) - , _video_frame (0) - , _audio_frame (0) + , _video_frames_in (0) + , _audio_frames_in (0) + , _video_frames_out (0) + , _audio_frames_out (0) #ifdef HAVE_SWRESAMPLE , _swr_context (0) #endif - , _audio_frames_written (0) , _process_end (false) { if (_film->audio_stream()) { @@ -241,12 +242,12 @@ Encoder::skipping () const return _just_skipped; } -/** @return Number of video frames that have been received */ -SourceFrame -Encoder::video_frame () const +/** @return Number of video frames that have been sent out */ +int +Encoder::video_frames_out () const { boost::mutex::scoped_lock (_history_mutex); - return _video_frame; + return _video_frames_out; } /** Should be called when a frame has been encoded successfully. @@ -281,8 +282,8 @@ Encoder::process_video (shared_ptr image, bool same, boost::shared_ptrframes_per_second ()); - if (dfr.skip && (_video_frame % 2)) { - ++_video_frame; + if (dfr.skip && (_video_frames_in % 2)) { + ++_video_frames_in; return; } @@ -300,7 +301,7 @@ Encoder::process_video (shared_ptr image, bool same, boost::shared_ptrframe_out_path (_video_frame, false))) { + if (boost::filesystem::exists (_film->frame_out_path (_video_frames_out, false))) { frame_skipped (); return; } @@ -310,7 +311,7 @@ Encoder::process_video (shared_ptr image, bool same, boost::shared_ptr const s = Filter::ffmpeg_strings (_film->filters()); @@ -319,17 +320,23 @@ Encoder::process_video (shared_ptr image, bool same, boost::shared_ptrformat()->dcp_size(), _film->format()->dcp_padding (_film), _film->subtitle_offset(), _film->subtitle_scale(), - _film->scaler(), _video_frame, _film->frames_per_second(), s.second, + _film->scaler(), _video_frames_out, _film->frames_per_second(), s.second, _film->colour_lut(), _film->j2k_bandwidth(), _film->log() ) )); _worker_condition.notify_all (); - _last_real_frame = _video_frame; + _last_real_frame = _video_frames_out; } - ++_video_frame; + ++_video_frames_in; + ++_video_frames_out; + + if (dfr.repeat) { + _links_required.push_back (make_pair (_video_frames_out, _video_frames_out - 1)); + ++_video_frames_out; + } } void @@ -378,7 +385,7 @@ Encoder::process_audio (shared_ptr data) write_audio (data); - _audio_frame += data->frames (); + _audio_frames_in += data->frames (); } void @@ -388,7 +395,7 @@ Encoder::write_audio (shared_ptr audio) sf_write_float (_sound_files[i], audio->data(i), audio->frames()); } - _audio_frames_written += audio->frames (); + _audio_frames_out += audio->frames (); } void diff --git a/src/lib/encoder.h b/src/lib/encoder.h index d8edf9b26..20255cca9 100644 --- a/src/lib/encoder.h +++ b/src/lib/encoder.h @@ -82,7 +82,7 @@ public: float current_frames_per_second () const; bool skipping () const; - SourceFrame video_frame () const; + int video_frames_out () const; private: @@ -111,9 +111,13 @@ private: bool _just_skipped; /** Number of video frames received so far */ - SourceFrame _video_frame; + SourceFrame _video_frames_in; /** Number of audio frames received so far */ - int64_t _audio_frame; + int64_t _audio_frames_in; + /** Number of video frames written for the DCP so far */ + int _video_frames_out; + /** Number of audio frames written for the DCP so far */ + int64_t _audio_frames_out; #if HAVE_SWRESAMPLE SwrContext* _swr_context; @@ -122,11 +126,11 @@ private: /** List of links that we need to create when all frames have been processed; * such that we need to call link (first, second) for each member of this list. * In other words, `first' is a `real' frame and `second' should be a link to `first'. + * Frames are DCP frames. */ std::list > _links_required; std::vector _sound_files; - int64_t _audio_frames_written; boost::optional _last_real_frame; bool _process_end; diff --git a/src/lib/ffmpeg_decoder.cc b/src/lib/ffmpeg_decoder.cc index 9e5cda889..e7dfc206b 100644 --- a/src/lib/ffmpeg_decoder.cc +++ b/src/lib/ffmpeg_decoder.cc @@ -58,6 +58,7 @@ using std::list; using boost::shared_ptr; using boost::optional; using boost::dynamic_pointer_cast; +using libdcp::Size; FFmpegDecoder::FFmpegDecoder (shared_ptr f, DecodeOptions o, Job* j) : Decoder (f, o, j) diff --git a/src/lib/ffmpeg_decoder.h b/src/lib/ffmpeg_decoder.h index 51b88a24a..9a4e65ebc 100644 --- a/src/lib/ffmpeg_decoder.h +++ b/src/lib/ffmpeg_decoder.h @@ -90,7 +90,7 @@ public: ~FFmpegDecoder (); float frames_per_second () const; - Size native_size () const; + libdcp::Size native_size () const; SourceFrame length () const; int time_base_numerator () const; int time_base_denominator () const; diff --git a/src/lib/film.cc b/src/lib/film.cc index 2af8d3c14..1741d49e6 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -72,6 +72,7 @@ using boost::to_upper_copy; using boost::ends_with; using boost::starts_with; using boost::optional; +using libdcp::Size; int const Film::state_version = 2; @@ -180,6 +181,7 @@ Film::Film (Film const & o) , _package_type (o._package_type) , _size (o._size) , _length (o._length) + , _dcp_intrinsic_duration (o._dcp_intrinsic_duration) , _content_digest (o._content_digest) , _content_audio_streams (o._content_audio_streams) , _external_audio_stream (o._external_audio_stream) @@ -423,6 +425,7 @@ Film::write_metadata () const f << "width " << _size.width << "\n"; f << "height " << _size.height << "\n"; f << "length " << _length.get_value_or(0) << "\n"; + f << "dcp_intrinsic_duration " << _dcp_intrinsic_duration.get_value_or(0) << "\n"; f << "content_digest " << _content_digest << "\n"; for (vector >::const_iterator i = _content_audio_streams.begin(); i != _content_audio_streams.end(); ++i) { @@ -569,6 +572,11 @@ Film::read_metadata () if (vv) { _length = vv; } + } else if (k == "dcp_intrinsic_duration") { + int const vv = atoi (v.c_str ()); + if (vv) { + _dcp_intrinsic_duration = vv; + } } else if (k == "content_digest") { _content_digest = v; } else if (k == "content_audio_stream" || (!version && k == "audio_stream")) { @@ -695,18 +703,10 @@ Film::target_audio_sample_rate () const return rint (t); } -boost::optional -Film::dcp_length () const +int +Film::still_duration_in_frames () const { - if (content_type() == STILL) { - return _still_duration * frames_per_second(); - } - - if (!length()) { - return boost::optional (); - } - - return length().get() - trim_start() - trim_end(); + return still_duration() * frames_per_second(); } /** @return a DCI-compliant name for a DCP of this film */ @@ -1327,7 +1327,17 @@ Film::unset_length () _length = boost::none; } signal_changed (LENGTH); -} +} + +void +Film::set_dcp_intrinsic_duration (int d) +{ + { + boost::mutex::scoped_lock lm (_state_mutex); + _dcp_intrinsic_duration = d; + } + signal_changed (DCP_INTRINSIC_DURATION); +} void Film::set_content_digest (string d) @@ -1409,12 +1419,12 @@ Film::audio_stream () const return _external_audio_stream; } -/** @param f Source frame index. +/** @param f DCP frame index. * @param t true to return a temporary file path, otherwise a permanent one. * @return The path to write this video frame to. */ string -Film::frame_out_path (SourceFrame f, bool t) const +Film::frame_out_path (int f, bool t) const { stringstream s; s << j2k_dir() << "/"; @@ -1429,7 +1439,7 @@ Film::frame_out_path (SourceFrame f, bool t) const } string -Film::hash_out_path (SourceFrame f, bool t) const +Film::hash_out_path (int f, bool t) const { return frame_out_path (f, t) + ".md5"; } diff --git a/src/lib/film.h b/src/lib/film.h index b03d84920..e10abfa4b 100644 --- a/src/lib/film.h +++ b/src/lib/film.h @@ -78,8 +78,8 @@ public: std::string file (std::string f) const; std::string dir (std::string d) const; - std::string frame_out_path (SourceFrame f, bool t) const; - std::string hash_out_path (SourceFrame f, bool t) const; + std::string frame_out_path (int f, bool t) const; + std::string hash_out_path (int f, bool t) const; std::string multichannel_audio_out_path (int c, bool t) const; std::string content_path () const; @@ -90,11 +90,14 @@ public: void write_metadata () const; void read_metadata (); - Size cropped_size (Size) const; - boost::optional dcp_length () const; + libdcp::Size cropped_size (libdcp::Size) const; std::string dci_name () const; std::string dcp_name () const; + boost::optional dcp_intrinsic_duration () const { + return _dcp_intrinsic_duration; + } + /** @return true if our state has changed since we last saved it */ bool dirty () const { return _dirty; @@ -137,6 +140,7 @@ public: DCI_METADATA, SIZE, LENGTH, + DCP_INTRINSIC_DURATION, CONTENT_AUDIO_STREAMS, SUBTITLE_STREAMS, FRAMES_PER_SECOND, @@ -195,12 +199,12 @@ public: return _scaler; } - SourceFrame trim_start () const { + int trim_start () const { boost::mutex::scoped_lock lm (_state_mutex); return _trim_start; } - SourceFrame trim_end () const { + int trim_end () const { boost::mutex::scoped_lock lm (_state_mutex); return _trim_end; } @@ -245,6 +249,8 @@ public: return _still_duration; } + int still_duration_in_frames () const; + boost::shared_ptr subtitle_stream () const { boost::mutex::scoped_lock lm (_state_mutex); return _subtitle_stream; @@ -310,7 +316,7 @@ public: return _package_type; } - Size size () const { + libdcp::Size size () const { boost::mutex::scoped_lock lm (_state_mutex); return _size; } @@ -387,9 +393,10 @@ public: void set_studio (std::string); void set_facility (std::string); void set_package_type (std::string); - void set_size (Size); + void set_size (libdcp::Size); void set_length (SourceFrame); void unset_length (); + void set_dcp_intrinsic_duration (int); void set_content_digest (std::string); void set_content_audio_streams (std::vector >); void set_subtitle_streams (std::vector >); @@ -499,9 +506,10 @@ private: /* Data which are cached to speed things up */ /** Size, in pixels, of the source (ignoring cropping) */ - Size _size; + libdcp::Size _size; /** The length of the source, in video frames (as far as we know) */ boost::optional _length; + boost::optional _dcp_intrinsic_duration; /** MD5 digest of our content file */ std::string _content_digest; /** The audio streams in our content */ diff --git a/src/lib/filter_graph.cc b/src/lib/filter_graph.cc index 376ab404f..86864a762 100644 --- a/src/lib/filter_graph.cc +++ b/src/lib/filter_graph.cc @@ -47,6 +47,7 @@ using std::stringstream; using std::string; using std::list; using boost::shared_ptr; +using libdcp::Size; /** Construct a FilterGraph for the settings in a film. * @param film Film. diff --git a/src/lib/filter_graph.h b/src/lib/filter_graph.h index 9e6ac6252..7e4e8422b 100644 --- a/src/lib/filter_graph.h +++ b/src/lib/filter_graph.h @@ -37,15 +37,15 @@ class FFmpegDecoder; class FilterGraph { public: - FilterGraph (boost::shared_ptr film, FFmpegDecoder* decoder, Size s, AVPixelFormat p); + FilterGraph (boost::shared_ptr film, FFmpegDecoder* decoder, libdcp::Size s, AVPixelFormat p); - bool can_process (Size s, AVPixelFormat p) const; + bool can_process (libdcp::Size s, AVPixelFormat p) const; std::list > process (AVFrame const * frame); private: AVFilterContext* _buffer_src_context; AVFilterContext* _buffer_sink_context; - Size _size; ///< size of the images that this chain can process + libdcp::Size _size; ///< size of the images that this chain can process AVPixelFormat _pixel_format; ///< pixel format of the images that this chain can process }; diff --git a/src/lib/format.cc b/src/lib/format.cc index 975862411..a80fab619 100644 --- a/src/lib/format.cc +++ b/src/lib/format.cc @@ -35,6 +35,7 @@ using std::setprecision; using std::stringstream; using std::vector; using boost::shared_ptr; +using libdcp::Size; vector Format::_formats; diff --git a/src/lib/format.h b/src/lib/format.h index 2118237a4..48a000480 100644 --- a/src/lib/format.h +++ b/src/lib/format.h @@ -31,7 +31,7 @@ class Film; class Format { public: - Format (Size dcp, std::string id, std::string n, std::string d) + Format (libdcp::Size dcp, std::string id, std::string n, std::string d) : _dcp_size (dcp) , _id (id) , _nickname (n) @@ -52,7 +52,7 @@ public: * put in a DCP for this ratio. This size will not correspond * to the ratio when we are doing things like 16:9 in a Flat frame. */ - Size dcp_size () const { + libdcp::Size dcp_size () const { return _dcp_size; } @@ -85,7 +85,7 @@ protected: * put in a DCP for this ratio. This size will not correspond * to the ratio when we are doing things like 16:9 in a Flat frame. */ - Size _dcp_size; + libdcp::Size _dcp_size; /** id for use in metadata */ std::string _id; /** nickname (e.g. Flat, Scope) */ @@ -104,7 +104,7 @@ private: class FixedFormat : public Format { public: - FixedFormat (int, Size, std::string, std::string, std::string); + FixedFormat (int, libdcp::Size, std::string, std::string, std::string); int ratio_as_integer (boost::shared_ptr) const { return _ratio; @@ -125,7 +125,7 @@ private: class VariableFormat : public Format { public: - VariableFormat (Size, std::string, std::string, std::string); + VariableFormat (libdcp::Size, std::string, std::string, std::string); int ratio_as_integer (boost::shared_ptr f) const; float ratio_as_float (boost::shared_ptr f) const; diff --git a/src/lib/image.cc b/src/lib/image.cc index f774f476f..c41558f02 100644 --- a/src/lib/image.cc +++ b/src/lib/image.cc @@ -42,6 +42,7 @@ extern "C" { using namespace std; using namespace boost; +using libdcp::Size; void Image::swap (Image& other) diff --git a/src/lib/image.h b/src/lib/image.h index e19c6f54b..5ca3f337c 100644 --- a/src/lib/image.h +++ b/src/lib/image.h @@ -66,13 +66,13 @@ public: virtual int * stride () const = 0; /** @return Size of the image, in pixels */ - virtual Size size () const = 0; + virtual libdcp::Size size () const = 0; int components () const; int lines (int) const; - boost::shared_ptr scale_and_convert_to_rgb (Size out_size, int padding, Scaler const * scaler, bool aligned) const; - boost::shared_ptr scale (Size, Scaler const *, bool aligned) const; + boost::shared_ptr scale_and_convert_to_rgb (libdcp::Size out_size, int padding, Scaler const * scaler, bool aligned) const; + boost::shared_ptr scale (libdcp::Size, Scaler const *, bool aligned) const; boost::shared_ptr post_process (std::string, bool aligned) const; void alpha_blend (boost::shared_ptr image, Position pos); boost::shared_ptr crop (Crop c, bool aligned) const; @@ -106,7 +106,7 @@ public: uint8_t ** data () const; int * line_size () const; int * stride () const; - Size size () const; + libdcp::Size size () const; private: /* Not allowed */ @@ -122,7 +122,7 @@ private: class SimpleImage : public Image { public: - SimpleImage (AVPixelFormat, Size, bool); + SimpleImage (AVPixelFormat, libdcp::Size, bool); SimpleImage (SimpleImage const &); SimpleImage& operator= (SimpleImage const &); ~SimpleImage (); @@ -130,14 +130,14 @@ public: uint8_t ** data () const; int * line_size () const; int * stride () const; - Size size () const; + libdcp::Size size () const; protected: void allocate (); void swap (SimpleImage &); private: - Size _size; ///< size in pixels + libdcp::Size _size; ///< size in pixels uint8_t** _data; ///< array of pointers to components int* _line_size; ///< array of sizes of the data in each line, in pixels (without any alignment padding bytes) int* _stride; ///< array of strides for each line (including any alignment padding bytes) diff --git a/src/lib/imagemagick_decoder.cc b/src/lib/imagemagick_decoder.cc index 063730540..bab4f2f07 100644 --- a/src/lib/imagemagick_decoder.cc +++ b/src/lib/imagemagick_decoder.cc @@ -27,6 +27,7 @@ using std::cout; using boost::shared_ptr; +using libdcp::Size; ImageMagickDecoder::ImageMagickDecoder ( boost::shared_ptr f, DecodeOptions o, Job* j) @@ -70,7 +71,7 @@ bool ImageMagickDecoder::pass () { if (_iter == _files.end()) { - if (!_film->dcp_length() || video_frame() >= _film->dcp_length().get()) { + if (video_frame() >= _film->still_duration_in_frames()) { return true; } diff --git a/src/lib/imagemagick_decoder.h b/src/lib/imagemagick_decoder.h index 5dfcab6f0..84a6f15f9 100644 --- a/src/lib/imagemagick_decoder.h +++ b/src/lib/imagemagick_decoder.h @@ -33,7 +33,7 @@ public: return 0; } - Size native_size () const; + libdcp::Size native_size () const; SourceFrame length () const { /* We don't know */ diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc index 3603298d9..6877e5e88 100644 --- a/src/lib/make_dcp_job.cc +++ b/src/lib/make_dcp_job.cc @@ -61,10 +61,7 @@ MakeDCPJob::name () const string MakeDCPJob::j2c_path (int f, int offset) const { - DCPFrameRate dfr (_film->frames_per_second()); - int const mult = dfr.skip ? 2 : 1; - SourceFrame const s = ((f + offset) * mult) + _film->trim_start(); - return _film->frame_out_path (s, false); + return _film->frame_out_path (f, false); } string @@ -76,8 +73,8 @@ MakeDCPJob::wav_path (libdcp::Channel c) const void MakeDCPJob::run () { - if (!_film->dcp_length()) { - throw EncodeError ("cannot make a DCP when the source length is not known"); + if (!_film->dcp_intrinsic_duration()) { + throw EncodeError ("cannot make a DCP when its intrinsic duration is not known"); } descend (0.9); @@ -87,22 +84,10 @@ MakeDCPJob::run () /* Remove any old DCP */ boost::filesystem::remove_all (dcp_path); + int const frames = _film->dcp_intrinsic_duration().get(); + int const duration = frames - _film->trim_start() - _film->trim_end(); DCPFrameRate const dfr (_film->frames_per_second ()); - int frames = 0; - switch (_film->content_type ()) { - case VIDEO: - /* Source frames -> DCP frames */ - frames = _film->dcp_length().get(); - if (dfr.skip) { - frames /= 2; - } - break; - case STILL: - frames = _film->still_duration() * 24; - break; - } - libdcp::DCP dcp (_film->dir (_film->dcp_name())); dcp.Progress.connect (boost::bind (&MakeDCPJob::dcp_progress, this, _1)); @@ -138,13 +123,12 @@ MakeDCPJob::run () &dcp.Progress, dfr.frames_per_second, this_time, - _film->format()->dcp_size().width, - _film->format()->dcp_size().height + _film->format()->dcp_size() ) ); pa->set_entry_point (_film->trim_start ()); - pa->set_duration (_film->duration ()); + pa->set_duration (duration); ascend (); @@ -166,7 +150,7 @@ MakeDCPJob::run () ); sa->set_entry_point (_film->trim_start ()); - sa->set_duration (_film->duration ()); + sa->set_duration (duration); ascend (); } diff --git a/src/lib/matcher.h b/src/lib/matcher.h index b94c28446..60bb87432 100644 --- a/src/lib/matcher.h +++ b/src/lib/matcher.h @@ -35,6 +35,6 @@ private: int _video_frames; int64_t _audio_frames; boost::optional _pixel_format; - boost::optional _size; + boost::optional _size; boost::optional _channels; }; diff --git a/src/lib/server.cc b/src/lib/server.cc index bea75cff8..134cb65a0 100644 --- a/src/lib/server.cc +++ b/src/lib/server.cc @@ -45,6 +45,7 @@ using boost::algorithm::is_any_of; using boost::algorithm::split; using boost::thread; using boost::bind; +using libdcp::Size; /** Create a server description from a string of metadata returned from as_metadata(). * @param v Metadata. diff --git a/src/lib/subtitle.cc b/src/lib/subtitle.cc index c52d3ac66..a7aa7cd21 100644 --- a/src/lib/subtitle.cc +++ b/src/lib/subtitle.cc @@ -27,6 +27,7 @@ using namespace std; using namespace boost; +using libdcp::Size; /** Construct a TimedSubtitle. This is a subtitle image, position, * and a range of time over which it should be shown. diff --git a/src/lib/transcode_job.cc b/src/lib/transcode_job.cc index c9792ed2e..6dd74c36c 100644 --- a/src/lib/transcode_job.cc +++ b/src/lib/transcode_job.cc @@ -67,7 +67,10 @@ TranscodeJob::run () set_progress (1); set_state (FINISHED_OK); + _film->set_dcp_intrinsic_duration (_encoder->video_frames_out ()); + _film->log()->log ("Transcode job completed successfully"); + _film->log()->log (String::compose ("DCP intrinsic duration is %1", _encoder->video_frames_out())); } catch (std::exception& e) { @@ -115,11 +118,19 @@ TranscodeJob::remaining_time () const return 0; } - if (!_film->dcp_length()) { + if (!_film->length()) { return 0; } + /* Compute approximate proposed length here, as it's only here that we need it */ + int length = _film->length().get(); + DCPFrameRate const dfr (_film->frames_per_second ()); + if (dfr.skip) { + length /= 2; + } + /* If we are repeating it shouldn't affect transcode time, so don't take it into account */ + /* We assume that dcp_length() is valid, if it is set */ - SourceFrame const left = _film->trim_start() + _film->dcp_length().get() - _encoder->video_frame(); + int const left = length - _encoder->video_frames_out(); return left / fps; } diff --git a/src/lib/util.cc b/src/lib/util.cc index b500ddc2f..0e250bb08 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -63,6 +63,7 @@ extern "C" { using namespace std; using namespace boost; +using libdcp::Size; thread::id ui_thread; @@ -455,16 +456,6 @@ dcp_audio_channels (int f) } -bool operator== (Size const & a, Size const & b) -{ - return (a.width == b.width && a.height == b.height); -} - -bool operator!= (Size const & a, Size const & b) -{ - return !(a == b); -} - bool operator== (Crop const & a, Crop const & b) { return (a.left == b.left && a.right == b.right && a.top == b.top && a.bottom == b.bottom); diff --git a/src/lib/util.h b/src/lib/util.h index 1fd2c0150..c4940a5d7 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -29,6 +29,7 @@ #include #include #include +#include extern "C" { #include #include @@ -99,33 +100,6 @@ enum ContentType { VIDEO ///< content is a video }; -/** @class Size - * @brief Representation of the size of something */ -struct Size -{ - /** Construct a zero Size */ - Size () - : width (0) - , height (0) - {} - - /** @param w Width. - * @param h Height. - */ - Size (int w, int h) - : width (w) - , height (h) - {} - - /** width */ - int width; - /** height */ - int height; -}; - -extern bool operator== (Size const & a, Size const & b); -extern bool operator!= (Size const & a, Size const & b); - /** @struct Crop * @brief A description of the crop of an image or video. */ @@ -195,14 +169,14 @@ struct Rect return Position (x, y); } - Size size () const { - return Size (width, height); + libdcp::Size size () const { + return libdcp::Size (width, height); } Rect intersection (Rect const & other) const; }; -extern std::string crop_string (Position, Size); +extern std::string crop_string (Position, libdcp::Size); extern int dcp_audio_sample_rate (int); extern int dcp_audio_channels (int); extern std::string colour_lut_index_to_name (int index); diff --git a/src/lib/video_decoder.h b/src/lib/video_decoder.h index c0eab2140..ef1ab041a 100644 --- a/src/lib/video_decoder.h +++ b/src/lib/video_decoder.h @@ -32,7 +32,7 @@ public: /** @return video frames per second, or 0 if unknown */ virtual float frames_per_second () const = 0; /** @return native size in pixels */ - virtual Size native_size () const = 0; + virtual libdcp::Size native_size () const = 0; /** @return length (in source video frames), according to our content's header */ virtual SourceFrame length () const = 0; diff --git a/src/wx/film_editor.cc b/src/wx/film_editor.cc index f83518b88..bbaeb17c4 100644 --- a/src/wx/film_editor.cc +++ b/src/wx/film_editor.cc @@ -665,6 +665,8 @@ FilmEditor::film_changed (Film::Property p) _trim_end->SetRange (0, _film->length().get()); } break; + case Film::DCP_INTRINSIC_DURATION: + break; case Film::DCP_CONTENT_TYPE: checked_set (_dcp_content_type, DCPContentType::as_index (_film->dcp_content_type ())); _dcp_name->SetLabel (std_to_wx (_film->dcp_name ())); diff --git a/src/wx/film_viewer.cc b/src/wx/film_viewer.cc index 347531cc2..e5da41d5e 100644 --- a/src/wx/film_viewer.cc +++ b/src/wx/film_viewer.cc @@ -44,6 +44,7 @@ using std::max; using std::cout; using std::list; using boost::shared_ptr; +using libdcp::Size; FilmViewer::FilmViewer (shared_ptr f, wxWindow* p) : wxPanel (p) diff --git a/src/wx/properties_dialog.cc b/src/wx/properties_dialog.cc index c34922ec4..0cf75cf51 100644 --- a/src/wx/properties_dialog.cc +++ b/src/wx/properties_dialog.cc @@ -91,9 +91,9 @@ PropertiesDialog::frames_already_encoded () const return ""; } - if (_film->dcp_length()) { + if (_film->length()) { /* XXX: encoded_frames() should check which frames have been encoded */ - u << " (" << ((_film->encoded_frames() - _film->trim_start()) * 100 / _film->dcp_length().get()) << "%)"; + u << " (" << (_film->encoded_frames() * 100 / _film->length().get()) << "%)"; } return u.str (); } diff --git a/test/metadata.ref b/test/metadata.ref index 90255e916..ff0c25118 100644 --- a/test/metadata.ref +++ b/test/metadata.ref @@ -34,6 +34,7 @@ package_type width 0 height 0 length 0 +dcp_intrinsic_duration 0 content_digest external_audio_stream external 0 0 frames_per_second 0 diff --git a/test/test.cc b/test/test.cc index 9143b87d5..7e1d92e06 100644 --- a/test/test.cc +++ b/test/test.cc @@ -325,7 +325,7 @@ do_remote_encode (shared_ptr frame, ServerDescription* descriptio BOOST_AUTO_TEST_CASE (client_server_test) { - shared_ptr image (new SimpleImage (PIX_FMT_RGB24, Size (1998, 1080), false)); + shared_ptr image (new SimpleImage (PIX_FMT_RGB24, libdcp::Size (1998, 1080), false)); uint8_t* p = image->data()[0]; for (int y = 0; y < 1080; ++y) { @@ -336,7 +336,7 @@ BOOST_AUTO_TEST_CASE (client_server_test) } } - shared_ptr sub_image (new SimpleImage (PIX_FMT_RGBA, Size (100, 200), false)); + shared_ptr sub_image (new SimpleImage (PIX_FMT_RGBA, libdcp::Size (100, 200), false)); p = sub_image->data()[0]; for (int y = 0; y < 200; ++y) { for (int x = 0; x < 100; ++x) { @@ -355,7 +355,7 @@ BOOST_AUTO_TEST_CASE (client_server_test) new DCPVideoFrame ( image, subtitle, - Size (1998, 1080), + libdcp::Size (1998, 1080), 0, 0, 1, @@ -636,7 +636,7 @@ BOOST_AUTO_TEST_CASE (job_manager_test) BOOST_AUTO_TEST_CASE (compact_image_test) { - SimpleImage* s = new SimpleImage (PIX_FMT_RGB24, Size (50, 50), false); + SimpleImage* s = new SimpleImage (PIX_FMT_RGB24, libdcp::Size (50, 50), false); BOOST_CHECK_EQUAL (s->components(), 1); BOOST_CHECK_EQUAL (s->stride()[0], 50 * 3); BOOST_CHECK_EQUAL (s->line_size()[0], 50 * 3); @@ -662,7 +662,7 @@ BOOST_AUTO_TEST_CASE (compact_image_test) BOOST_CHECK (t->stride()[0] == s->stride()[0]); /* assignment operator */ - SimpleImage* u = new SimpleImage (PIX_FMT_YUV422P, Size (150, 150), true); + SimpleImage* u = new SimpleImage (PIX_FMT_YUV422P, libdcp::Size (150, 150), true); *u = *s; BOOST_CHECK_EQUAL (u->components(), 1); BOOST_CHECK_EQUAL (u->stride()[0], 50 * 3); @@ -685,7 +685,7 @@ BOOST_AUTO_TEST_CASE (compact_image_test) BOOST_AUTO_TEST_CASE (aligned_image_test) { - SimpleImage* s = new SimpleImage (PIX_FMT_RGB24, Size (50, 50), true); + SimpleImage* s = new SimpleImage (PIX_FMT_RGB24, libdcp::Size (50, 50), true); BOOST_CHECK_EQUAL (s->components(), 1); /* 160 is 150 aligned to the nearest 32 bytes */ BOOST_CHECK_EQUAL (s->stride()[0], 160); @@ -712,7 +712,7 @@ BOOST_AUTO_TEST_CASE (aligned_image_test) BOOST_CHECK (t->stride()[0] == s->stride()[0]); /* assignment operator */ - SimpleImage* u = new SimpleImage (PIX_FMT_YUV422P, Size (150, 150), false); + SimpleImage* u = new SimpleImage (PIX_FMT_YUV422P, libdcp::Size (150, 150), false); *u = *s; BOOST_CHECK_EQUAL (u->components(), 1); BOOST_CHECK_EQUAL (u->stride()[0], 160); -- 2.30.2