summaryrefslogtreecommitdiff
path: root/src/lib
diff options
context:
space:
mode:
authorCarl Hetherington <cth@carlh.net>2013-05-07 23:03:06 +0100
committerCarl Hetherington <cth@carlh.net>2013-05-07 23:03:06 +0100
commitb66a082df05202f0119b16853f04034cf85ec80b (patch)
tree2d4b5b75ed2aa5e3a1076e15e87264add5858d58 /src/lib
parent1f4a21c0da3a917a5ff7743a577cc0f210fa86d8 (diff)
Another attempt to fix matching and confusions about the delay line.
Diffstat (limited to 'src/lib')
-rw-r--r--src/lib/delay_line.cc2
-rw-r--r--src/lib/matcher.cc83
-rw-r--r--src/lib/matcher.h17
3 files changed, 64 insertions, 38 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/matcher.cc b/src/lib/matcher.cc
index f8d5c5fcd..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,12 +97,12 @@ 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;
}
@@ -113,9 +115,11 @@ Matcher::process_audio (boost::shared_ptr<const AudioBuffers> b, double t)
} 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 41aa373a4..d6778da11 100644
--- a/src/lib/matcher.h
+++ b/src/lib/matcher.h
@@ -30,7 +30,7 @@ public:
void process_end ();
private:
- void fix_start (double);
+ void fix_start ();
void match (double);
void repeat_last_video ();
@@ -42,6 +42,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)
@@ -52,6 +66,7 @@ private:
double time;
};
+ std::list<VideoRecord> _pending_video;
std::list<AudioRecord> _pending_audio;
boost::optional<double> _first_input;