Bug 1089937 Add a fuzz time to end times for MSE reader switching on EOS r=karl,mattwoodrow

mLast{Audio,Video}Time differs from the actual end time because of
Bug 1065207 - the duration of a WebM fragment is an estimate not the
actual duration. In the case of audio time an example of where they
differ would be the actual sample duration being small but the
previous sample being large. The buffered end time uses that last
sample duration as an estimate of the end time duration giving an end
time that is greater than mLastAudioTime, which is the actual sample
end time.

Reader switching is based on the buffered end time though so we can't use
the actual sample end time for switching comparison.

For this reason we use the end time from the buffers to compare if we
should switch readers in this patch. We also add an EOS_FUZZ_US to allow
for the fact that it is an estimate and can differ slightly from actual times.

--HG--
extra : rebase_source : 47149609119c5dcd1ca7374501dd7c1e285469ef
This commit is contained in:
Chris Double ext:(%20with%20tweaks%20by%20Karl%20Tomlinson%20%3Ckarlt%2B%40karlt.net%3E) 2014-11-12 12:12:21 +13:00
parent 5a065a8608
commit ade13ac0f9

View File

@ -33,6 +33,13 @@ extern PRLogModuleInfo* GetMediaSourceAPILog();
#define MSE_API(...) #define MSE_API(...)
#endif #endif
// When a stream hits EOS it needs to decide what other stream to switch to. Due
// to inaccuracies is determining buffer end frames (Bug 1065207) and rounding
// issues we use a fuzz factor to determine the end time of this stream for
// switching to the new stream. This value is based on the end of frame
// default value used in Blink, kDefaultBufferDurationInMs.
#define EOS_FUZZ_US 125000
namespace mozilla { namespace mozilla {
MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder) MediaSourceReader::MediaSourceReader(MediaSourceDecoder* aDecoder)
@ -173,13 +180,43 @@ MediaSourceReader::OnNotDecoded(MediaData::Type aType, RequestSampleCallback::No
GetCallback()->OnNotDecoded(aType, aReason); GetCallback()->OnNotDecoded(aType, aReason);
return; return;
} }
// End of stream. Force switching past this stream to another reader by
// switching to the end of the buffered range.
MOZ_ASSERT(aReason == RequestSampleCallback::END_OF_STREAM);
nsRefPtr<MediaDecoderReader> reader = aType == MediaData::AUDIO_DATA ?
mAudioReader : mVideoReader;
// See if we can find a different reader that can pick up where we left off. // Find the closest approximation to the end time for this stream.
if (aType == MediaData::AUDIO_DATA && SwitchAudioReader(mLastAudioTime)) { // mLast{Audio,Video}Time differs from the actual end time because of
// Bug 1065207 - the duration of a WebM fragment is an estimate not the
// actual duration. In the case of audio time an example of where they
// differ would be the actual sample duration being small but the
// previous sample being large. The buffered end time uses that last
// sample duration as an estimate of the end time duration giving an end
// time that is greater than mLastAudioTime, which is the actual sample
// end time.
// Reader switching is based on the buffered end time though so they can be
// quite different. By using the EOS_FUZZ_US and the buffered end time we
// attempt to account for this difference.
int64_t* time = aType == MediaData::AUDIO_DATA ? &mLastAudioTime : &mLastVideoTime;
if (reader) {
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
reader->GetBuffered(ranges, 0);
if (ranges->Length() > 0) {
// End time is a double so we convert to nearest by adding 0.5.
int64_t end = ranges->GetEndTime() * USECS_PER_S + 0.5;
*time = std::max(*time, end);
}
}
// See if we can find a different reader that can pick up where we left off. We use the
// EOS_FUZZ_US to allow for the fact that our end time can be inaccurate due to bug
// 1065207 - the duration of a WebM frame is an estimate.
if (aType == MediaData::AUDIO_DATA && SwitchAudioReader(*time + EOS_FUZZ_US)) {
RequestAudioData(); RequestAudioData();
return; return;
} }
if (aType == MediaData::VIDEO_DATA && SwitchVideoReader(mLastVideoTime)) { if (aType == MediaData::VIDEO_DATA && SwitchVideoReader(*time + EOS_FUZZ_US)) {
RequestVideoData(false, 0); RequestVideoData(false, 0);
return; return;
} }