Back out 4 changesets (bug 1229987) for ASan e10s timeout in test_playback.html, Mac timeouts in test_BufferingWait_mp4.html, and Win8 failures in test_WaitingToEndedTransition_mp4.html

Backed out changeset 707a87454058 (bug 1229987)
Backed out changeset 37003d495f20 (bug 1229987)
Backed out changeset c8f4e1eaf884 (bug 1229987)
Backed out changeset 42ca05d8546d (bug 1229987)
This commit is contained in:
Phil Ringnalda 2015-12-10 23:10:20 -08:00
parent 4d21fa83d0
commit 45242f7699
11 changed files with 83 additions and 193 deletions

View File

@ -783,17 +783,6 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
self->WaitRequestRef(aRejection.mType).Complete();
}));
// We are out of data to decode and will enter buffering mode soon.
// We want to play the frames we have already decoded, so we stop pre-rolling
// and ensure that loadeddata is fired as required.
if (isAudio) {
StopPrerollingAudio();
} else {
StopPrerollingVideo();
}
if (mState == DECODER_STATE_BUFFERING || mState == DECODER_STATE_DECODING) {
MaybeFinishDecodeFirstFrame();
}
return;
}

View File

@ -691,7 +691,6 @@ MediaFormatReader::NotifyWaitingForData(TrackType aTrack)
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
decoder.mWaitingForData = true;
decoder.mNeedDraining = true;
ScheduleUpdate(aTrack);
}
@ -884,7 +883,6 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
info->GetID());
decoder.mInfo = info;
decoder.mLastStreamSourceID = info->GetID();
decoder.mNextStreamSourceID.reset();
// Flush will clear our array of queued samples. So make a copy now.
nsTArray<RefPtr<MediaRawData>> samples{decoder.mQueuedSamples};
Flush(aTrack);
@ -894,11 +892,38 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
decoder.mQueuedSamples.AppendElements(Move(samples));
NotifyDecodingRequested(aTrack);
} else {
TimeUnit seekTime =
decoder.mTimeThreshold.refOr(TimeUnit::FromMicroseconds(sample->mTime));
MOZ_ASSERT(decoder.mTimeThreshold.isNothing());
LOG("Stream change occurred on a non-keyframe. Seeking to:%lld",
seekTime.ToMicroseconds());
InternalSeek(aTrack, seekTime);
sample->mTime);
decoder.mTimeThreshold = Some(TimeUnit::FromMicroseconds(sample->mTime));
RefPtr<MediaFormatReader> self = this;
decoder.ResetDemuxer();
decoder.mSeekRequest.Begin(decoder.mTrackDemuxer->Seek(decoder.mTimeThreshold.ref())
->Then(OwnerThread(), __func__,
[self, aTrack] (media::TimeUnit aTime) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
self->NotifyDecodingRequested(aTrack);
},
[self, aTrack] (DemuxerFailureReason aResult) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
switch (aResult) {
case DemuxerFailureReason::WAITING_FOR_DATA:
self->NotifyWaitingForData(aTrack);
break;
case DemuxerFailureReason::END_OF_STREAM:
self->NotifyEndOfStream(aTrack);
break;
case DemuxerFailureReason::CANCELED:
case DemuxerFailureReason::SHUTDOWN:
break;
default:
self->NotifyError(aTrack);
break;
}
decoder.mTimeThreshold.reset();
}));
}
return;
}
@ -932,42 +957,6 @@ MediaFormatReader::HandleDemuxedSamples(TrackType aTrack,
decoder.mInputExhausted = false;
}
void
MediaFormatReader::InternalSeek(TrackType aTrack, const media::TimeUnit& aTime)
{
MOZ_ASSERT(OnTaskQueue());
auto& decoder = GetDecoderData(aTrack);
decoder.mTimeThreshold = Some(aTime);
RefPtr<MediaFormatReader> self = this;
decoder.ResetDemuxer();
decoder.mSeekRequest.Begin(decoder.mTrackDemuxer->Seek(decoder.mTimeThreshold.ref())
->Then(OwnerThread(), __func__,
[self, aTrack] (media::TimeUnit aTime) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
self->NotifyDecodingRequested(aTrack);
},
[self, aTrack] (DemuxerFailureReason aResult) {
auto& decoder = self->GetDecoderData(aTrack);
decoder.mSeekRequest.Complete();
switch (aResult) {
case DemuxerFailureReason::WAITING_FOR_DATA:
self->NotifyWaitingForData(aTrack);
break;
case DemuxerFailureReason::END_OF_STREAM:
self->NotifyEndOfStream(aTrack);
break;
case DemuxerFailureReason::CANCELED:
case DemuxerFailureReason::SHUTDOWN:
break;
default:
self->NotifyError(aTrack);
break;
}
decoder.mTimeThreshold.reset();
}));
}
void
MediaFormatReader::DrainDecoder(TrackType aTrack)
{
@ -1017,8 +1006,7 @@ MediaFormatReader::Update(TrackType aTrack)
return;
}
if (!decoder.HasPromise() && decoder.mWaitingForData &&
!decoder.mDraining && !decoder.mNeedDraining) {
if (!decoder.HasPromise() && decoder.mWaitingForData) {
// Nothing more we can do at present.
LOGV("Still waiting for data.");
return;
@ -1048,47 +1036,32 @@ MediaFormatReader::Update(TrackType aTrack)
RefPtr<MediaData> output = decoder.mOutput[0];
decoder.mOutput.RemoveElementAt(0);
decoder.mSizeOfQueue -= 1;
decoder.mLastSampleTime =
Some(media::TimeUnit::FromMicroseconds(output->GetEndTime()));
if (decoder.mTimeThreshold.isNothing() ||
media::TimeUnit::FromMicroseconds(output->mTime) >= decoder.mTimeThreshold.ref()) {
ReturnOutput(output, aTrack);
decoder.mTimeThreshold.reset();
break;
} else {
LOGV("Internal Seeking: Dropping %s frame time:%f wanted:%f (kf:%d)",
TrackTypeToStr(aTrack),
LOGV("Internal Seeking: Dropping frame time:%f wanted:%f (kf:%d)",
media::TimeUnit::FromMicroseconds(output->mTime).ToSeconds(),
decoder.mTimeThreshold.ref().ToSeconds(),
output->mKeyframe);
}
}
}
}
if (decoder.HasPromise() && decoder.mOutput.IsEmpty()) {
if (decoder.mError) {
decoder.RejectPromise(DECODE_ERROR, __func__);
return;
}
if (decoder.mDrainComplete) {
bool wasDraining = decoder.mDraining;
} else if (decoder.mDrainComplete) {
decoder.mDrainComplete = false;
decoder.mDraining = false;
if (decoder.mDemuxEOS) {
decoder.RejectPromise(END_OF_STREAM, __func__);
// We reached the end of the data stream. Nothing more to do.
if (decoder.mError) {
LOG("Decoding Error");
decoder.RejectPromise(DECODE_ERROR, __func__);
return;
} else if (decoder.mDemuxEOS) {
decoder.RejectPromise(END_OF_STREAM, __func__);
}
if (wasDraining && decoder.mLastSampleTime && !decoder.mNextStreamSourceID) {
// We have completed draining the decoder following WaitingForData.
// Set up the internal seek machinery to be able to resume from the
// last sample decoded.
LOG("Seeking to last sample time: %lld",
decoder.mLastSampleTime.ref().ToMicroseconds());
InternalSeek(aTrack, decoder.mLastSampleTime.ref());
}
}
if (decoder.mWaitingForData && !decoder.mDraining && !decoder.mNeedDraining) {
} else if (decoder.mError) {
decoder.RejectPromise(DECODE_ERROR, __func__);
return;
} else if (decoder.mWaitingForData) {
LOG("Waiting For Data");
decoder.RejectPromise(WAITING_FOR_DATA, __func__);
return;

View File

@ -127,8 +127,6 @@ private:
// Decode any pending already demuxed samples.
bool DecodeDemuxedSamples(TrackType aTrack,
MediaRawData* aSample);
void InternalSeek(TrackType aTrack, const media::TimeUnit& aTime);
// Drain the current decoder.
void DrainDecoder(TrackType aTrack);
void NotifyNewOutput(TrackType aTrack, MediaData* aSample);
@ -263,11 +261,8 @@ private:
bool mDraining;
bool mDrainComplete;
// If set, all decoded samples prior mTimeThreshold will be dropped.
// Used for internal seeking when a change of stream is detected or when
// encountering data discontinuity.
// Used for internal seeking when a change of stream is detected.
Maybe<media::TimeUnit> mTimeThreshold;
// End time of last sample output.
Maybe<media::TimeUnit> mLastSampleTime;
// Decoded samples returned my mDecoder awaiting being returned to
// state machine upon request.
@ -305,7 +300,6 @@ private:
mDraining = false;
mDrainComplete = false;
mTimeThreshold.reset();
mLastSampleTime.reset();
mOutput.Clear();
mNumSamplesInput = 0;
mNumSamplesOutput = 0;

View File

@ -295,7 +295,7 @@ MediaSourceTrackDemuxer::MediaSourceTrackDemuxer(MediaSourceDemuxer* aParent,
, mManager(aManager)
, mType(aType)
, mMonitor("MediaSourceTrackDemuxer")
, mReset(true)
, mLastSeek(Some(TimeUnit()))
{
}
@ -328,8 +328,7 @@ MediaSourceTrackDemuxer::Reset()
RefPtr<MediaSourceTrackDemuxer> self = this;
nsCOMPtr<nsIRunnable> task =
NS_NewRunnableFunction([self] () {
self->mNextSample.reset();
self->mReset = true;
self->mLastSeek = Some(TimeUnit());
self->mManager->Seek(self->mType, TimeUnit(), TimeUnit());
{
MonitorAutoLock mon(self->mMonitor);
@ -381,58 +380,49 @@ MediaSourceTrackDemuxer::DoSeek(media::TimeUnit aTime)
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ);
if (!buffered.Contains(aTime)) {
mLastSeek = Some(aTime);
// We don't have the data to seek to.
return SeekPromise::CreateAndReject(DemuxerFailureReason::WAITING_FOR_DATA,
__func__);
}
TimeUnit seekTime =
mManager->Seek(mType, aTime, MediaSourceDemuxer::EOS_FUZZ);
bool error;
RefPtr<MediaRawData> sample =
mManager->GetSample(mType,
media::TimeUnit(),
error);
MOZ_ASSERT(!error && sample);
mNextSample = Some(sample);
mReset = false;
{
MonitorAutoLock mon(mMonitor);
mNextRandomAccessPoint = mManager->GetNextRandomAccessPoint(mType);
}
mLastSeek = Some(aTime);
return SeekPromise::CreateAndResolve(seekTime, __func__);
}
RefPtr<MediaSourceTrackDemuxer::SamplesPromise>
MediaSourceTrackDemuxer::DoGetSamples(int32_t aNumSamples)
{
if (mReset) {
if (mLastSeek) {
// If a seek (or reset) was recently performed, we ensure that the data
// we are about to retrieve is still available.
TimeIntervals buffered = mManager->Buffered(mType);
buffered.SetFuzz(MediaSourceDemuxer::EOS_FUZZ);
if (!buffered.Contains(TimeUnit::FromMicroseconds(0))) {
if (!buffered.Contains(mLastSeek.ref())) {
return SamplesPromise::CreateAndReject(
mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
DemuxerFailureReason::WAITING_FOR_DATA, __func__);
}
mReset = false;
mLastSeek.reset();
}
bool error = false;
RefPtr<MediaRawData> sample;
if (mNextSample) {
sample = mNextSample.ref();
mNextSample.reset();
} else {
sample = mManager->GetSample(mType, MediaSourceDemuxer::EOS_FUZZ, error);
if (!sample) {
if (error) {
return SamplesPromise::CreateAndReject(DemuxerFailureReason::DEMUXER_ERROR, __func__);
}
return SamplesPromise::CreateAndReject(
mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
DemuxerFailureReason::WAITING_FOR_DATA, __func__);
bool error;
RefPtr<MediaRawData> sample =
mManager->GetSample(mType,
MediaSourceDemuxer::EOS_FUZZ,
error);
if (!sample) {
if (error) {
return SamplesPromise::CreateAndReject(DemuxerFailureReason::DEMUXER_ERROR, __func__);
}
return SamplesPromise::CreateAndReject(
mManager->IsEnded() ? DemuxerFailureReason::END_OF_STREAM :
DemuxerFailureReason::WAITING_FOR_DATA, __func__);
}
RefPtr<SamplesHolder> samples = new SamplesHolder;
samples->mSamples.AppendElement(sample);

View File

@ -129,10 +129,7 @@ private:
// Monitor protecting members below accessed from multiple threads.
Monitor mMonitor;
media::TimeUnit mNextRandomAccessPoint;
Maybe<RefPtr<MediaRawData>> mNextSample;
// Set to true following a reset. Ensure that the next sample demuxed
// is available at position 0.
bool mReset;
Maybe<media::TimeUnit> mLastSeek;
};
} // namespace mozilla

View File

@ -40,9 +40,7 @@ skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac"))
[test_BufferingWait.html]
skip-if = toolkit == 'android' #timeout android bug 1199531
[test_BufferingWait_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_DrainOnMissingData_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138
[test_EndOfStream.html]
skip-if = (true || toolkit == 'android' || buildapp == 'mulet') #timeout android/mulet only bug 1101187 and bug 1182946
[test_EndOfStream_mp4.html]
@ -53,7 +51,7 @@ skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac"))
[test_FrameSelection.html]
[test_HaveMetadataUnbufferedSeek.html]
[test_HaveMetadataUnbufferedSeek_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138
[test_LoadedDataFired_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_LoadedMetadataFired.html]
@ -100,11 +98,11 @@ skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac"))
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
[test_TruncatedDuration.html]
[test_TruncatedDuration_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138
[test_WaitingOnMissingData.html]
skip-if = true # Disabled due to bug 1124493 and friends. WebM MSE is deprioritized.
[test_WaitingOnMissingData_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138
[test_WaitingToEndedTransition_mp4.html]
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac")) # Only supported on osx and vista+
skip-if = ((os == "win" && os_version == "5.1") || (os != "win" && os != "mac") || (os == "win" && os_version == "6.1")) # Only supported on osx and vista+, disabling on win7 bug 1191138

View File

@ -41,14 +41,18 @@ runWithMSE(function(ms, v) {
/* Note - Missing |bipbop4| segment here corresponding to (2.41, 3.20] */
.then(fetchAndLoad.bind(null, sb, 'bipbop/bipbop', ['5'], '.m4s'))
.then(function() {
var promise = waitUntilTime(1.62-1/30);
// Some decoders (Windows in particular) may keep up to 25 frames queued
// before returning a sample. 0.7 is 1.62s - 25 * 0.03333
var promise = waitUntilTime(0.7);
info("Playing video. It should play for a bit, then fire 'waiting'");
v.play();
return promise;
}).then(function() {
window.firstStop = Date.now();
fetchAndLoad(sb, 'bipbop/bipbop', ['3'], '.m4s');
return waitUntilTime(2.41-1/30);
// Some decoders (Windows in particular) may keep up to 25 frames queued
// before returning a sample. 1.5 is 2.41s - 25 * 0.03333
return waitUntilTime(1.5);
}).then(function() {
var waitDuration = (Date.now() - window.firstStop) / 1000;
ok(waitDuration < 15, "Should not spend an inordinate amount of time buffering: " + waitDuration);

View File

@ -1,60 +0,0 @@
<!DOCTYPE html>
<html><head>
<meta http-equiv="content-type" content="text/html; charset=windows-1252">
<title>MSE: |waiting| event when source data is missing</title>
<script type="text/javascript" src="/tests/SimpleTest/SimpleTest.js"></script>
<script type="text/javascript" src="mediasource.js"></script>
<link rel="stylesheet" type="text/css" href="/tests/SimpleTest/test.css" />
</head>
<body>
<pre id="test"><script class="testbody" type="text/javascript">
SimpleTest.waitForExplicitFinish();
runWithMSE(function(ms, el) {
el.controls = true;
once(ms, 'sourceopen').then(function() {
ok(true, "Receive a sourceopen event");
var videosb = ms.addSourceBuffer("video/mp4");
fetchAndLoad(videosb, 'bipbop/bipbop_video', ['init'], '.mp4')
.then(function() {
// Set appendWindowEnd to ensure we only have about 6 frames worth.
// We must feed at least 6 frames to pass the MDSM pre-roll.
videosb.appendWindowEnd = .4;
return fetchAndLoad(videosb, 'bipbop/bipbop_video', ['1'], '.m4s');
})
.then(function() {
info("Invoking play()");
var promises = [];
promises.push(once(el, 'playing'));
el.play();
return Promise.all(promises);
})
.then(function() {
info("got playing");
return once(el, 'waiting');
}).then(function() {
info("got waiting");
info("Loading more data");
// Waiting will be fired on the last frame +- 40ms.
isfuzzy(el.currentTime, videosb.buffered.end(0) - 1/30,
0.04, "Got a waiting event at " + el.currentTime);
videosb.appendWindowEnd = 1;
var p = once(el, 'ended');
var loads = fetchAndLoad(videosb, 'bipbop/bipbop_video', [1], '.m4s');
loads.then(() => ms.endOfStream());
return p;
}).then(function() {
// These fuzz factors are bigger than they should be. We should investigate
// and fix them in bug 1137574.
is(el.duration, 0.801666, "Video has correct duration: " + el.duration);
is(el.currentTime, el.duration, "Video has correct currentTime.");
SimpleTest.finish();
});
});
});
</script>
</pre>
</body>
</html>

View File

@ -37,6 +37,9 @@ runWithMSE(function(ms, el) {
var promises = [];
promises.push(once(el, 'loadeddata'));
promises.push(once(el, 'canplay'));
// Load [0, 1.601666). We must ensure that we load over 25 frames as the
// windows H264 decoder will not produce a sample until then
// (bug 1191138).
promises.push(fetchAndLoad(videosb, 'bipbop/bipbop_video', range(1, 3), '.m4s'));
return Promise.all(promises);
})

View File

@ -40,8 +40,9 @@ runWithMSE(function(ms, el) {
// currentTime is based on the current video frame, so if the audio ends just before
// the next video frame, currentTime can be up to 1 frame's worth earlier than
// min(audioEnd, videoEnd).
isfuzzy(el.currentTime, Math.min(audiosb.buffered.end(0), videosb.buffered.end(0)) - 1/30,
0.04, "Got a waiting event at " + el.currentTime);
// Some decoders (Windows in particular) may keep up to 25 frames queued.
isfuzzy(el.currentTime, Math.min(audiosb.buffered.end(0), videosb.buffered.end(0)) - 1/60,
25 * 1/30, "Got a waiting event at " + el.currentTime);
info("Loading more data");
var p = once(el, 'ended');
var loads = Promise.all([fetchAndLoad(audiosb, 'bipbop/bipbop_audio', [5], '.m4s'),

View File

@ -39,8 +39,9 @@ runWithMSE(function(ms, el) {
// the next video frame, currentTime can be up to 1 frame's worth earlier than
// min(audioEnd, videoEnd).
// Some decoders (Windows in particular) may keep up to 25 frames queued.
isfuzzy(el.currentTime, Math.min(audiosb.buffered.end(0), videosb.buffered.end(0)) - 1/30,
0.04, "Got a waiting event at " + el.currentTime);
isfuzzy(el.currentTime, Math.min(audiosb.buffered.end(0), videosb.buffered.end(0)) - 1/60,
25 * 1/30, "Got a waiting event at " + el.currentTime);
}).then(function() {
var p = once(el, 'ended');
ms.endOfStream();
return p;