Before this commit, an audio delay of -110ms on a test project
would result in a seek on every video and audio fetch.
This commit does two things to fix that:
1. Don't discard audio data that arrives with a timestamp
before the last seek time. In the case that we are fixing
we had the following sequence:
- video seeks to some frame F
- this causes audio data to arrive a little before F
- this audio data is discarded
- and audio get happens just after F
- the audio code thinks it must seek rather than just pass()ing
since it has no data
If we keep the audio data from before the seek our _decoded
will be much closer to the audio request, so a pass() is more
likely to happen.
2. Extend the length of time that we will happily pass() for
rather than seeking when looking for audio data. Seeking is
really bad so we can tolerate quite long times here. The sensible
length of this value should probably be investigated as the
one in this commit is a finger-in-the-air guess.
Frame const end = frame + length - 1;
Frame const end = frame + length - 1;
- if (frame < _decoded.frame || end > (_decoded.frame + length * 4)) {
- /* Either we have no decoded data, or what we do have is a long way from what we want: seek */
+ /* If we are less than (about) 5 seconds behind the data that we want we'll
+ run through it rather than seeking.
+ */
+ Frame const slack = 5 * 48000;
+
+ if (frame < _decoded.frame || end > (_decoded.frame + _decoded.audio->frames() + slack)) {
+ /* Either we have no decoded data, all our data is after the time that we
+ want, or what we do have is a long way from what we want: seek */
_decoder->seek (ContentTime::from_frames (frame, _content->resampled_frame_rate()), accurate);
}
_decoder->seek (ContentTime::from_frames (frame, _content->resampled_frame_rate()), accurate);
}
padded->copy_from (data.get(), data->frames(), 0, delta_frames);
data = padded;
time -= delta;
padded->copy_from (data.get(), data->frames(), 0, delta_frames);
data = padded;
time -= delta;
- } else if (delta_frames < 0) {
- /* This data comes before the seek time. Throw some data away */
- Frame const to_discard = min (-delta_frames, static_cast<Frame> (data->frames()));
- Frame const to_keep = data->frames() - to_discard;
- if (to_keep == 0) {
- /* We have to throw all this data away, so keep _seek_reference and
- try again next time some data arrives.
- */
- return;
- }
- shared_ptr<AudioBuffers> trimmed (new AudioBuffers (data->channels(), to_keep));
- trimmed->copy_from (data.get(), to_keep, to_discard, 0);
- data = trimmed;
- time += ContentTime::from_frames (to_discard, frame_rate);
}
_seek_reference = optional<ContentTime> ();
}
}
_seek_reference = optional<ContentTime> ();
}