diff options
| author | Carl Hetherington <cth@carlh.net> | 2013-05-21 13:20:51 +0100 |
|---|---|---|
| committer | Carl Hetherington <cth@carlh.net> | 2013-05-21 13:20:51 +0100 |
| commit | 5a57b5631518ce9711e6b44a65a0bb87aa434561 (patch) | |
| tree | 2db1403b5b3a30ae5b15cfcf23ae34fdef380de4 /src/lib | |
| parent | 5f0f0de782100a5cb558f30c7768c8af0c19bcb7 (diff) | |
| parent | dc6713f19bb9084aac18eabe399b14ca1ac26df9 (diff) | |
Merge branch 'sync-fixes' into staging
Diffstat (limited to 'src/lib')
| -rw-r--r-- | src/lib/delay_line.cc | 2 | ||||
| -rw-r--r-- | src/lib/encoder.cc | 4 | ||||
| -rw-r--r-- | src/lib/matcher.cc | 87 | ||||
| -rw-r--r-- | src/lib/matcher.h | 17 | ||||
| -rw-r--r-- | src/lib/transcoder.cc | 2 |
5 files changed, 71 insertions, 41 deletions
diff --git a/src/lib/delay_line.cc b/src/lib/delay_line.cc index b0180800a..f6af6f9b1 100644 --- a/src/lib/delay_line.cc +++ b/src/lib/delay_line.cc @@ -50,7 +50,7 @@ void DelayLine::process_video (shared_ptr<const Image> image, bool same, boost::shared_ptr<Subtitle> sub, double t) { if (_seconds < 0) { - t += _seconds; + t -= _seconds; } Video (image, same, sub, t); diff --git a/src/lib/encoder.cc b/src/lib/encoder.cc index cff9899ac..8549962ff 100644 --- a/src/lib/encoder.cc +++ b/src/lib/encoder.cc @@ -296,6 +296,10 @@ Encoder::process_video (shared_ptr<const Image> image, bool same, boost::shared_ void Encoder::process_audio (shared_ptr<const AudioBuffers> data) { + if (!data->frames ()) { + return; + } + #if HAVE_SWRESAMPLE /* Maybe sample-rate convert */ if (_swr_context) { diff --git a/src/lib/matcher.cc b/src/lib/matcher.cc index 9924c003a..4acb82afa 100644 --- a/src/lib/matcher.cc +++ b/src/lib/matcher.cc @@ -48,45 +48,47 @@ Matcher::process_video (boost::shared_ptr<const Image> image, bool same, boost:: _log->log(String::compose("Matcher video @ %1 [audio=%2, video=%3, pending_audio=%4]", t, _audio_frames, _video_frames, _pending_audio.size())); - if (!_first_input) { + if (!_first_input || t < _first_input.get()) { _first_input = t; } bool const this_is_first_video = !_had_first_video; _had_first_video = true; - if (this_is_first_video && _had_first_audio) { + if (!_had_first_audio) { + /* No audio yet; we must postpone these data until we have some */ + _pending_video.push_back (VideoRecord (image, same, sub, t)); + } else if (this_is_first_video && _had_first_audio) { /* First video since we got audio */ - fix_start (t); - } - - /* Video before audio is fine, since we can make up an arbitrary difference - with audio samples (contrasting with video which is quantised to frames) - */ + _pending_video.push_back (VideoRecord (image, same, sub, t)); + fix_start (); + } else { + /* Normal running */ - /* Difference between where this video is and where it should be */ - double const delta = t - _first_input.get() - _video_frames / _frames_per_second; - double const one_frame = 1 / _frames_per_second; - - if (delta > one_frame) { - /* Insert frames to make up the difference */ - int const extra = rint (delta / one_frame); - for (int i = 0; i < extra; ++i) { - repeat_last_video (); - _log->log (String::compose ("Extra video frame inserted at %1s", _video_frames / _frames_per_second)); + /* Difference between where this video is and where it should be */ + double const delta = t - _first_input.get() - _video_frames / _frames_per_second; + double const one_frame = 1 / _frames_per_second; + + if (delta > one_frame) { + /* Insert frames to make up the difference */ + int const extra = rint (delta / one_frame); + for (int i = 0; i < extra; ++i) { + repeat_last_video (); + _log->log (String::compose ("Extra video frame inserted at %1s", _video_frames / _frames_per_second)); + } } - } - if (delta > -one_frame) { - Video (image, same, sub); - ++_video_frames; - } else { - /* We are omitting a frame to keep things right */ - _log->log (String::compose ("Frame removed at %1s", t)); + if (delta > -one_frame) { + Video (image, same, sub); + ++_video_frames; + } else { + /* We are omitting a frame to keep things right */ + _log->log (String::compose ("Frame removed at %1s; delta %2; first input was at %3", t, delta, _first_input.get())); + } + + _last_image = image; + _last_subtitle = sub; } - - _last_image = image; - _last_subtitle = sub; } void @@ -95,27 +97,29 @@ Matcher::process_audio (boost::shared_ptr<const AudioBuffers> b, double t) _channels = b->channels (); _log->log (String::compose ( - "Matcher audio (%1 frames) @ %2 [video=%3, audio=%4, pending_audio=%5]", - b->frames(), t, _video_frames, _audio_frames, _pending_audio.size() + "Matcher audio (%1 frames) @ %2 [video=%3, audio=%4, pending_video=%5, pending_audio=%6]", + b->frames(), t, _video_frames, _audio_frames, _pending_video.size(), _pending_audio.size() ) ); - if (!_first_input) { + if (!_first_input || t < _first_input.get()) { _first_input = t; } - bool const this_is_first_audio = _had_first_audio; + bool const this_is_first_audio = !_had_first_audio; _had_first_audio = true; if (!_had_first_video) { /* No video yet; we must postpone these data until we have some */ _pending_audio.push_back (AudioRecord (b, t)); - } else if (this_is_first_audio && !_had_first_video) { + } else if (this_is_first_audio && _had_first_video) { /* First audio since we got video */ _pending_audio.push_back (AudioRecord (b, t)); - fix_start (_first_input.get ()); + fix_start (); } else { - /* Normal running. We assume audio time stamps are consecutive */ + /* Normal running. We assume audio time stamps are consecutive, so there's no equivalent of + the checking / insertion of repeat frames that there is for video. + */ Audio (b); _audio_frames += b->frames (); } @@ -136,13 +140,20 @@ Matcher::process_end () } void -Matcher::fix_start (double first_video) +Matcher::fix_start () { + assert (!_pending_video.empty ()); assert (!_pending_audio.empty ()); + + _log->log (String::compose ("Fixing start; video at %1, audio at %2", _pending_video.front().time, _pending_audio.front().time)); + + match (_pending_video.front().time - _pending_audio.front().time); - _log->log (String::compose ("Fixing start; video at %1, audio at %2", first_video, _pending_audio.front().time)); + for (list<VideoRecord>::iterator i = _pending_video.begin(); i != _pending_video.end(); ++i) { + process_video (i->image, i->same, i->subtitle, i->time); + } - match (first_video - _pending_audio.front().time); + _pending_video.clear (); for (list<AudioRecord>::iterator i = _pending_audio.begin(); i != _pending_audio.end(); ++i) { process_audio (i->audio, i->time); diff --git a/src/lib/matcher.h b/src/lib/matcher.h index 21e42f53d..61fd81436 100644 --- a/src/lib/matcher.h +++ b/src/lib/matcher.h @@ -29,7 +29,7 @@ public: void process_end (); private: - void fix_start (double); + void fix_start (); void match (double); void repeat_last_video (); @@ -41,6 +41,20 @@ private: boost::optional<libdcp::Size> _size; boost::optional<int> _channels; + struct VideoRecord { + VideoRecord (boost::shared_ptr<const Image> i, bool s, boost::shared_ptr<Subtitle> u, double t) + : image (i) + , same (s) + , subtitle (u) + , time (t) + {} + + boost::shared_ptr<const Image> image; + bool same; + boost::shared_ptr<Subtitle> subtitle; + double time; + }; + struct AudioRecord { AudioRecord (boost::shared_ptr<const AudioBuffers> a, double t) : audio (a) @@ -51,6 +65,7 @@ private: double time; }; + std::list<VideoRecord> _pending_video; std::list<AudioRecord> _pending_audio; boost::optional<double> _first_input; diff --git a/src/lib/transcoder.cc b/src/lib/transcoder.cc index fcfbb1648..48cf402d7 100644 --- a/src/lib/transcoder.cc +++ b/src/lib/transcoder.cc @@ -56,7 +56,7 @@ Transcoder::Transcoder (shared_ptr<Film> f, DecodeOptions o, Job* j, shared_ptr< assert (_encoder); shared_ptr<AudioStream> st = f->audio_stream(); - if (st && st->sample_rate()) { + if (st && st->sample_rate ()) { _matcher.reset (new Matcher (f->log(), st->sample_rate(), f->source_frame_rate())); } _delay_line.reset (new DelayLine (f->log(), f->audio_delay() / 1000.0f)); |
