summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-05-21 13:20:51 +0100
committerCarl Hetherington <cth@carlh.net>2013-05-21 13:20:51 +0100
commit5a57b5631518ce9711e6b44a65a0bb87aa434561 (patch)
tree2db1403b5b3a30ae5b15cfcf23ae34fdef380de4 /src/lib
parent5f0f0de782100a5cb558f30c7768c8af0c19bcb7 (diff)
parentdc6713f19bb9084aac18eabe399b14ca1ac26df9 (diff)
Merge branch 'sync-fixes' into staging
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/delay_line.cc2
-rw-r--r--src/lib/encoder.cc4
-rw-r--r--src/lib/matcher.cc87
-rw-r--r--src/lib/matcher.h17
-rw-r--r--src/lib/transcoder.cc2
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));