* @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)
, _delay_line (0)
, _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
while (pass () == false) {
if (_job && _film->dcp_length()) {
- _job->set_progress (float (_video_frame_index) / _film->dcp_length().get());
+ SourceFrame const p = _video_frame_index - _film->dcp_trim_start();
+ _job->set_progress (float (p) / _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.
void
Decoder::process_video (AVFrame* frame)
{
+ assert (_film->length());
+
if (_minimal) {
++_video_frame_index;
return;
/* 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_skip != 0 && (_video_frame_index % _opt->decode_video_skip) != 0) {
+ ++_video_frame_index;
+ return;
}
- if (_opt->decode_video_frequency != 0 && gap != 0 && (_video_frame_index % gap) != 0) {
+ if (_film->dcp_trim_start() > _video_frame_index || (_film->length().get() - _film->dcp_trim_end()) < _video_frame_index) {
++_video_frame_index;
return;
}
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())) {
sub = _timed_subtitle->subtitle ();
void
Decoder::repeat_last_video ()
{
- assert (_last_image);
+ if (!_last_image) {
+ _last_image.reset (new CompactImage (pixel_format(), native_size()));
+ _last_image->make_black ();
+ }
+
Video (_last_image, _video_frame_index, _last_subtitle);
++_video_frame_index;
}