From: Carl Hetherington Date: Sun, 4 Nov 2012 13:41:43 +0000 (+0000) Subject: Skip every other frame with 50fps sources. X-Git-Tag: v2.0.48~1572^2~1 X-Git-Url: https://main.carlh.net/gitweb/?a=commitdiff_plain;h=c366d41af080b9ac37117a9b27a249722c77f74e;p=dcpomatic.git Skip every other frame with 50fps sources. --- diff --git a/src/lib/check_hashes_job.cc b/src/lib/check_hashes_job.cc index a9f8ac90b..d1483933d 100644 --- a/src/lib/check_hashes_job.cc +++ b/src/lib/check_hashes_job.cc @@ -58,8 +58,9 @@ CheckHashesJob::run () } int const N = _film->dcp_length().get(); + DCPFrameRate const dfr = dcp_frame_rate (_film->frames_per_second ()); - for (int i = 0; i < N; ++i) { + for (int i = 0; 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 9d6022efa..1dcc81f0d 100644 --- a/src/lib/dcp_video_frame.cc +++ b/src/lib/dcp_video_frame.cc @@ -86,8 +86,7 @@ DCPVideoFrame::DCPVideoFrame ( , _subtitle_scale (subtitle_scale) , _scaler (s) , _frame (f) - /* we round here; not sure if this is right */ - , _frames_per_second (rint (fps)) + , _frames_per_second (dcp_frame_rate(fps).frames_per_second) , _post_process (pp) , _colour_lut_index (clut) , _j2k_bandwidth (bw) diff --git a/src/lib/decoder.cc b/src/lib/decoder.cc index 6f5d63358..3feaf43e9 100644 --- a/src/lib/decoder.cc +++ b/src/lib/decoder.cc @@ -61,9 +61,7 @@ Decoder::Decoder (boost::shared_ptr f, boost::shared_ptr o, , _delay_in_bytes (0) , _audio_frames_processed (0) { - if (_opt->decode_video_frequency != 0 && !_film->length()) { - throw DecodeError ("cannot do a partial decode if length is unknown"); - } + } Decoder::~Decoder () @@ -101,7 +99,7 @@ Decoder::process_end () int64_t const audio_short_by_frames = video_length_in_audio_frames - _audio_frames_processed; _film->log()->log ( - String::compose ("DCP length is %1 (%2 audio frames); %3 frames of audio processed.", + 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) @@ -109,7 +107,7 @@ Decoder::process_end () if (audio_short_by_frames >= 0 && _opt->decode_audio) { - _film->log()->log (String::compose ("DCP length is %1; %2 frames of audio processed.", video_frame_index(), _audio_frames_processed)); + _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)); /* XXX: this is slightly questionable; does memset () give silence with all @@ -272,12 +270,7 @@ Decoder::process_video (AVFrame* frame) /* Use Film::length here as our one may be wrong */ - int gap = 0; - if (_opt->decode_video_frequency != 0) { - gap = _film->length().get() / _opt->decode_video_frequency; - } - - if (_opt->decode_video_frequency != 0 && gap != 0 && (_video_frame_index % gap) != 0) { + if (_opt->decode_video_skip != 0 && (_video_frame_index % _opt->decode_video_skip) != 0) { ++_video_frame_index; return; } diff --git a/src/lib/examine_content_job.cc b/src/lib/examine_content_job.cc index 943e9fbf7..6d1233a8c 100644 --- a/src/lib/examine_content_job.cc +++ b/src/lib/examine_content_job.cc @@ -84,7 +84,11 @@ ExamineContentJob::run () o->out_size = _film->size (); o->apply_crop = false; o->decode_audio = false; - o->decode_video_frequency = 128; + if (_film->length() > 0) { + o->decode_video_skip = _film->length().get() / 128; + } else { + o->decode_video_skip = 0; + } o->decode_subtitles = true; shared_ptr e (new ImageMagickEncoder (_film, o)); Transcoder w (_film, o, this, e); diff --git a/src/lib/film.cc b/src/lib/film.cc index 9c351a64d..d29c04465 100644 --- a/src/lib/film.cc +++ b/src/lib/film.cc @@ -272,6 +272,7 @@ Film::make_dcp (bool transcode) o->padding = format()->dcp_padding (shared_from_this ()); o->ratio = format()->ratio_as_float (shared_from_this ()); o->decode_subtitles = with_subtitles (); + o->decode_video_skip = dcp_frame_rate (frames_per_second()).skip; shared_ptr r; @@ -716,11 +717,13 @@ Film::target_audio_sample_rate () const /* Resample to a DCI-approved sample rate */ double t = dcp_audio_sample_rate (audio_sample_rate()); + DCPFrameRate dfr = dcp_frame_rate (frames_per_second ()); + /* Compensate for the fact that video will be rounded to the nearest integer number of frames per second. */ - if (rint (frames_per_second()) != frames_per_second()) { - t *= _frames_per_second / rint (frames_per_second()); + if (dfr.run_fast) { + t *= _frames_per_second * dfr.skip / dfr.frames_per_second; } return rint (t); diff --git a/src/lib/make_dcp_job.cc b/src/lib/make_dcp_job.cc index bf01119e4..4102f8384 100644 --- a/src/lib/make_dcp_job.cc +++ b/src/lib/make_dcp_job.cc @@ -58,7 +58,7 @@ MakeDCPJob::name () const string MakeDCPJob::j2c_path (int f) const { - return _opt->frame_out_path (f, false); + return _opt->frame_out_path (f * dcp_frame_rate(_film->frames_per_second()).skip, false); } string @@ -79,21 +79,23 @@ MakeDCPJob::run () /* Remove any old DCP */ boost::filesystem::remove_all (dcp_path); + DCPFrameRate const dfr = dcp_frame_rate (_film->frames_per_second ()); + int frames = 0; switch (_film->content_type ()) { case VIDEO: - frames = _film->dcp_length().get(); + frames = _film->dcp_length().get() / dfr.skip; break; case STILL: frames = _film->still_duration() * ImageMagickDecoder::static_frames_per_second (); break; } - + libdcp::DCP dcp (_film->dir (_film->dcp_name())); dcp.Progress.connect (boost::bind (&MakeDCPJob::dcp_progress, this, _1)); shared_ptr cpl ( - new libdcp::CPL (_film->dir (_film->dcp_name()), _film->dcp_name(), _film->dcp_content_type()->libdcp_kind (), frames, rint (_film->frames_per_second())) + new libdcp::CPL (_film->dir (_film->dcp_name()), _film->dcp_name(), _film->dcp_content_type()->libdcp_kind (), frames, dfr.frames_per_second) ); dcp.add_cpl (cpl); @@ -105,7 +107,7 @@ MakeDCPJob::run () _film->dir (_film->dcp_name()), "video.mxf", &dcp.Progress, - rint (_film->frames_per_second()), + dfr.frames_per_second, frames, _opt->out_size.width, _opt->out_size.height @@ -124,7 +126,7 @@ MakeDCPJob::run () _film->dir (_film->dcp_name()), "audio.mxf", &dcp.Progress, - rint (_film->frames_per_second()), + dfr.frames_per_second, frames, _film->audio_channels() ) diff --git a/src/lib/options.h b/src/lib/options.h index 86db35210..f4381ef68 100644 --- a/src/lib/options.h +++ b/src/lib/options.h @@ -40,7 +40,7 @@ public: : padding (0) , apply_crop (true) , black_after (0) - , decode_video_frequency (0) + , decode_video_skip (0) , decode_audio (true) , decode_subtitles (false) , _frame_out_path (f) @@ -98,7 +98,8 @@ public: 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_frequency; ///< skip frames so that this many are decoded in all (or 0) (for generating thumbnails) + 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. 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 9058fcc2a..1500b9b48 100644 --- a/src/lib/tiff_decoder.cc +++ b/src/lib/tiff_decoder.cc @@ -198,7 +198,7 @@ TIFFDecoder::pixel_format () const int TIFFDecoder::time_base_numerator () const { - return rint (_film->frames_per_second()); + return dcp_frame_rate(_film->frames_per_second()).frames_per_second; } diff --git a/src/lib/util.cc b/src/lib/util.cc index b68f7e392..d89ebd0d5 100644 --- a/src/lib/util.cc +++ b/src/lib/util.cc @@ -374,6 +374,24 @@ md5_digest (string file) return s.str (); } +DCPFrameRate +dcp_frame_rate (float fps) +{ + DCPFrameRate dfr; + + dfr.run_fast = (fps != rint (fps)); + dfr.frames_per_second = rint (fps); + dfr.skip = 1; + + /* XXX: somewhat arbitrary */ + if (fps == 50) { + dfr.frames_per_second = 25; + dfr.skip = 2; + } + + return dfr; +} + /** @param An arbitrary sampling rate. * @return The appropriate DCP-approved sampling rate (48kHz or 96kHz). */ diff --git a/src/lib/util.h b/src/lib/util.h index 1af650085..26c6ed9fa 100644 --- a/src/lib/util.h +++ b/src/lib/util.h @@ -54,6 +54,13 @@ extern std::string md5_digest (std::string); extern std::string md5_digest (void const *, int); extern void ensure_ui_thread (); +struct DCPFrameRate +{ + int frames_per_second; + int skip; + bool run_fast; +}; + enum ContentType { STILL, VIDEO @@ -157,6 +164,7 @@ struct Rect 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 std::multimap read_key_value (std::istream& s);