Bug 1125469: Part1. Don't attempt to seek on time found with fuzz search. r=mattwoodrow

Instead seek to the actual time available.
This commit is contained in:
Jean-Yves Avenard 2015-02-06 23:51:46 +11:00
Родитель 72355abc0d
Коммит 173a0c1120
2 изменённых файлов: 46 добавлений и 18 удалений

Просмотреть файл

@ -125,7 +125,7 @@ MediaSourceReader::RequestAudioData()
} }
MOZ_DIAGNOSTIC_ASSERT(!mAudioSeekRequest.Exists()); MOZ_DIAGNOSTIC_ASSERT(!mAudioSeekRequest.Exists());
SwitchSourceResult ret = SwitchAudioSource(mLastAudioTime); SwitchSourceResult ret = SwitchAudioSource(&mLastAudioTime);
switch (ret) { switch (ret) {
case SOURCE_NEW: case SOURCE_NEW:
mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mLastAudioTime), 0) mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mLastAudioTime), 0)
@ -233,7 +233,7 @@ MediaSourceReader::OnAudioNotDecoded(NotDecodedReason aReason)
} }
// See if we can find a different source that can pick up where we left off. // See if we can find a different source that can pick up where we left off.
if (SwitchAudioSource(mLastAudioTime) == SOURCE_NEW) { if (SwitchAudioSource(&mLastAudioTime) == SOURCE_NEW) {
mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mLastAudioTime), 0) mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mLastAudioTime), 0)
->RefableThen(GetTaskQueue(), __func__, this, ->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::CompleteAudioSeekAndDoRequest, &MediaSourceReader::CompleteAudioSeekAndDoRequest,
@ -267,7 +267,7 @@ MediaSourceReader::RequestVideoData(bool aSkipToNextKeyframe, int64_t aTimeThres
} }
MOZ_DIAGNOSTIC_ASSERT(!mVideoSeekRequest.Exists()); MOZ_DIAGNOSTIC_ASSERT(!mVideoSeekRequest.Exists());
SwitchSourceResult ret = SwitchVideoSource(mLastVideoTime); SwitchSourceResult ret = SwitchVideoSource(&mLastVideoTime);
switch (ret) { switch (ret) {
case SOURCE_NEW: case SOURCE_NEW:
mVideoSeekRequest.Begin(GetVideoReader()->Seek(GetReaderVideoTime(mLastVideoTime), 0) mVideoSeekRequest.Begin(GetVideoReader()->Seek(GetReaderVideoTime(mLastVideoTime), 0)
@ -351,7 +351,7 @@ MediaSourceReader::OnVideoNotDecoded(NotDecodedReason aReason)
} }
// See if we can find a different reader that can pick up where we left off. // See if we can find a different reader that can pick up where we left off.
if (SwitchVideoSource(mLastVideoTime) == SOURCE_NEW) { if (SwitchVideoSource(&mLastVideoTime) == SOURCE_NEW) {
mVideoSeekRequest.Begin(GetVideoReader()->Seek(GetReaderVideoTime(mLastVideoTime), 0) mVideoSeekRequest.Begin(GetVideoReader()->Seek(GetReaderVideoTime(mLastVideoTime), 0)
->RefableThen(GetTaskQueue(), __func__, this, ->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::CompleteVideoSeekAndDoRequest, &MediaSourceReader::CompleteVideoSeekAndDoRequest,
@ -485,7 +485,7 @@ MediaSourceReader::HaveData(int64_t aTarget, MediaData::Type aType)
} }
MediaSourceReader::SwitchSourceResult MediaSourceReader::SwitchSourceResult
MediaSourceReader::SwitchAudioSource(int64_t aTarget) MediaSourceReader::SwitchAudioSource(int64_t* aTarget)
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXX: Can't handle adding an audio track after ReadMetadata. // XXX: Can't handle adding an audio track after ReadMetadata.
@ -496,23 +496,36 @@ MediaSourceReader::SwitchAudioSource(int64_t aTarget)
// We first search without the tolerance and then search with it, so that, in // We first search without the tolerance and then search with it, so that, in
// the case of perfectly-aligned data, we don't prematurely jump to a new // the case of perfectly-aligned data, we don't prematurely jump to a new
// reader and skip the last few samples of the current one. // reader and skip the last few samples of the current one.
bool usedFuzz = false;
nsRefPtr<SourceBufferDecoder> newDecoder = nsRefPtr<SourceBufferDecoder> newDecoder =
SelectDecoder(aTarget, /* aTolerance = */ 0, mAudioTrack->Decoders()); SelectDecoder(*aTarget, /* aTolerance = */ 0, mAudioTrack->Decoders());
if (!newDecoder) { if (!newDecoder) {
newDecoder = SelectDecoder(aTarget, EOS_FUZZ_US, mAudioTrack->Decoders()); newDecoder = SelectDecoder(*aTarget, EOS_FUZZ_US, mAudioTrack->Decoders());
usedFuzz = true;
} }
if (newDecoder && newDecoder != mAudioSourceDecoder) { if (newDecoder && newDecoder != mAudioSourceDecoder) {
GetAudioReader()->SetIdle(); GetAudioReader()->SetIdle();
mAudioSourceDecoder = newDecoder; mAudioSourceDecoder = newDecoder;
MSE_DEBUGV("MediaSourceReader(%p)::SwitchAudioSource switched decoder to %p", if (usedFuzz) {
this, mAudioSourceDecoder.get()); // A decoder buffered range is continuous. We would have failed the exact
// search but succeeded the fuzzy one if our target was shortly before
// start time.
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
newDecoder->GetBuffered(ranges);
int64_t startTime = ranges->GetStartTime() * USECS_PER_S;
if (*aTarget < startTime) {
*aTarget = startTime;
}
}
MSE_DEBUGV("MediaSourceReader(%p)::SwitchAudioSource switched decoder to %p (fuzz:%d)",
this, mAudioSourceDecoder.get(), usedFuzz);
return SOURCE_NEW; return SOURCE_NEW;
} }
return newDecoder ? SOURCE_EXISTING : SOURCE_ERROR; return newDecoder ? SOURCE_EXISTING : SOURCE_ERROR;
} }
MediaSourceReader::SwitchSourceResult MediaSourceReader::SwitchSourceResult
MediaSourceReader::SwitchVideoSource(int64_t aTarget) MediaSourceReader::SwitchVideoSource(int64_t* aTarget)
{ {
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
// XXX: Can't handle adding a video track after ReadMetadata. // XXX: Can't handle adding a video track after ReadMetadata.
@ -523,16 +536,29 @@ MediaSourceReader::SwitchVideoSource(int64_t aTarget)
// We first search without the tolerance and then search with it, so that, in // We first search without the tolerance and then search with it, so that, in
// the case of perfectly-aligned data, we don't prematurely jump to a new // the case of perfectly-aligned data, we don't prematurely jump to a new
// reader and skip the last few samples of the current one. // reader and skip the last few samples of the current one.
bool usedFuzz = false;
nsRefPtr<SourceBufferDecoder> newDecoder = nsRefPtr<SourceBufferDecoder> newDecoder =
SelectDecoder(aTarget, /* aTolerance = */ 0, mVideoTrack->Decoders()); SelectDecoder(*aTarget, /* aTolerance = */ 0, mVideoTrack->Decoders());
if (!newDecoder) { if (!newDecoder) {
newDecoder = SelectDecoder(aTarget, EOS_FUZZ_US, mVideoTrack->Decoders()); newDecoder = SelectDecoder(*aTarget, EOS_FUZZ_US, mVideoTrack->Decoders());
usedFuzz = true;
} }
if (newDecoder && newDecoder != mVideoSourceDecoder) { if (newDecoder && newDecoder != mVideoSourceDecoder) {
GetVideoReader()->SetIdle(); GetVideoReader()->SetIdle();
mVideoSourceDecoder = newDecoder; mVideoSourceDecoder = newDecoder;
MSE_DEBUGV("MediaSourceReader(%p)::SwitchVideoSource switched decoder to %p", if (usedFuzz) {
this, mVideoSourceDecoder.get()); // A decoder buffered range is continuous. We would have failed the exact
// search but succeeded the fuzzy one if our target was shortly before
// start time.
nsRefPtr<dom::TimeRanges> ranges = new dom::TimeRanges();
newDecoder->GetBuffered(ranges);
int64_t startTime = ranges->GetStartTime() * USECS_PER_S;
if (*aTarget < startTime) {
*aTarget = startTime;
}
}
MSE_DEBUGV("MediaSourceReader(%p)::SwitchVideoSource switched decoder to %p (fuzz:%d)",
this, mVideoSourceDecoder.get(), usedFuzz);
return SOURCE_NEW; return SOURCE_NEW;
} }
return newDecoder ? SOURCE_EXISTING : SOURCE_ERROR; return newDecoder ? SOURCE_EXISTING : SOURCE_ERROR;
@ -775,7 +801,7 @@ MediaSourceReader::OnVideoSeekFailed(nsresult aResult)
void void
MediaSourceReader::DoAudioSeek() MediaSourceReader::DoAudioSeek()
{ {
SwitchAudioSource(mPendingSeekTime); SwitchAudioSource(&mPendingSeekTime);
mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mPendingSeekTime), 0) mAudioSeekRequest.Begin(GetAudioReader()->Seek(GetReaderAudioTime(mPendingSeekTime), 0)
->RefableThen(GetTaskQueue(), __func__, this, ->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::OnAudioSeekCompleted, &MediaSourceReader::OnAudioSeekCompleted,
@ -835,7 +861,7 @@ MediaSourceReader::AttemptSeek()
void void
MediaSourceReader::DoVideoSeek() MediaSourceReader::DoVideoSeek()
{ {
SwitchVideoSource(mPendingSeekTime); SwitchVideoSource(&mPendingSeekTime);
mVideoSeekRequest.Begin(GetVideoReader()->Seek(GetReaderVideoTime(mPendingSeekTime), 0) mVideoSeekRequest.Begin(GetVideoReader()->Seek(GetReaderVideoTime(mPendingSeekTime), 0)
->RefableThen(GetTaskQueue(), __func__, this, ->RefableThen(GetTaskQueue(), __func__, this,
&MediaSourceReader::OnVideoSeekCompleted, &MediaSourceReader::OnVideoSeekCompleted,

Просмотреть файл

@ -157,14 +157,16 @@ private:
// Switch the current audio/video source to the source that // Switch the current audio/video source to the source that
// contains aTarget (or up to aTolerance after target). Both // contains aTarget (or up to aTolerance after target). Both
// aTarget and aTolerance are in microseconds. // aTarget and aTolerance are in microseconds.
// Search can be made using a fuzz factor. Should an approximated value be
// found instead, aTarget will be updated to the actual target found.
enum SwitchSourceResult { enum SwitchSourceResult {
SOURCE_ERROR = -1, SOURCE_ERROR = -1,
SOURCE_EXISTING = 0, SOURCE_EXISTING = 0,
SOURCE_NEW = 1, SOURCE_NEW = 1,
}; };
SwitchSourceResult SwitchAudioSource(int64_t aTarget); SwitchSourceResult SwitchAudioSource(int64_t* aTarget);
SwitchSourceResult SwitchVideoSource(int64_t aTarget); SwitchSourceResult SwitchVideoSource(int64_t* aTarget);
void DoAudioRequest(); void DoAudioRequest();
void DoVideoRequest(); void DoVideoRequest();