}
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";
, _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)
, _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 ()
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)
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
/* 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;
}
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<ImageMagickEncoder> e (new ImageMagickEncoder (_film, o));
Transcoder w (_film, o, this, e);
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<Job> r;
/* 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);
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
/* 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<libdcp::CPL> 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);
_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
_film->dir (_film->dcp_name()),
"audio.mxf",
&dcp.Progress,
- rint (_film->frames_per_second()),
+ dfr.frames_per_second,
frames,
_film->audio_channels()
)
: 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)
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;
int
TIFFDecoder::time_base_numerator () const
{
- return rint (_film->frames_per_second());
+ return dcp_frame_rate(_film->frames_per_second()).frames_per_second;
}
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).
*/
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
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<std::string, std::string> read_key_value (std::istream& s);