Bug 1005366 - Tighten up handling of SourceBuffer decoder resets. r=cajbir

--HG--
rename : content/media/test/crashtests/926665.html => content/media/mediasource/test/crashtests/926665.html
This commit is contained in:
Matthew Gregan 2014-05-08 14:22:34 +12:00
parent 8e813f3fbd
commit 50baa14b08
6 changed files with 71 additions and 21 deletions

View File

@ -280,10 +280,7 @@ SourceBuffer::Abort(ErrorResult& aRv)
mAppendWindowEnd = PositiveInfinity<double>();
MSE_DEBUG("%p Abort: Discarding decoder.", this);
if (mDecoder) {
mDecoder->GetResource()->Ended();
mDecoder = nullptr;
}
DiscardDecoder();
}
void
@ -309,7 +306,7 @@ void
SourceBuffer::Detach()
{
Ended();
mDecoder = nullptr;
DiscardDecoder();
mMediaSource = nullptr;
}
@ -330,7 +327,7 @@ SourceBuffer::SourceBuffer(MediaSource* aMediaSource, const nsACString& aType)
, mTimestampOffset(0)
, mAppendMode(SourceBufferAppendMode::Segments)
, mUpdating(false)
, mDecoderInit(false)
, mDecoderInitialized(false)
{
MOZ_ASSERT(aMediaSource);
mParser = ContainerParser::CreateForMIMEType(aType);
@ -347,9 +344,7 @@ SourceBuffer::Create(MediaSource* aMediaSource, const nsACString& aType)
SourceBuffer::~SourceBuffer()
{
if (mDecoder) {
mDecoder->GetResource()->Ended();
}
DiscardDecoder();
}
MediaSource*
@ -382,15 +377,27 @@ SourceBuffer::QueueAsyncSimpleEvent(const char* aName)
bool
SourceBuffer::InitNewDecoder()
{
MOZ_ASSERT(!mDecoder);
MediaSourceDecoder* parentDecoder = mMediaSource->GetDecoder();
nsRefPtr<SubBufferDecoder> decoder = parentDecoder->CreateSubDecoder(mType);
if (!decoder) {
return false;
}
mDecoder = decoder;
mDecoderInitialized = false;
return true;
}
void
SourceBuffer::DiscardDecoder()
{
if (mDecoder) {
mDecoder->GetResource()->Ended();
}
mDecoder = nullptr;
mDecoderInitialized = false;
}
void
SourceBuffer::StartUpdating()
{
@ -432,18 +439,28 @@ SourceBuffer::AppendData(const uint8_t* aData, uint32_t aLength, ErrorResult& aR
// TODO: Test buffer full flag.
StartUpdating();
// TODO: Run buffer append algorithm asynchronously (would call StopUpdating()).
if (!mDecoder || mParser->IsInitSegmentPresent(aData, aLength)) {
if (!mDecoder || mDecoderInit) {
MSE_DEBUG("%p AppendBuffer: New initialization segment, creating decoder.", this);
mDecoder->GetResource()->Ended();
if (mParser->IsInitSegmentPresent(aData, aLength)) {
MSE_DEBUG("%p AppendBuffer: New initialization segment.", this);
if (mDecoderInitialized) {
// Existing decoder has been used, time for a new one.
DiscardDecoder();
}
if (!InitNewDecoder()) {
aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
return;
}
// If we've got a decoder here, it's not initialized, so we can use it
// rather than creating a new one.
if (!mDecoder && !InitNewDecoder()) {
aRv.Throw(NS_ERROR_FAILURE); // XXX: Review error handling.
return;
}
MSE_DEBUG("%p AppendBuffer: Decoder marked as initialized.", this);
mDecoderInit = true;
mDecoderInitialized = true;
} else if (!mDecoderInitialized) {
MSE_DEBUG("%p AppendBuffer: Non-initialization segment appended during initialization.");
Optional<MediaSourceEndOfStreamError> decodeError(MediaSourceEndOfStreamError::Decode);
ErrorResult dummy;
mMediaSource->EndOfStream(decodeError, dummy);
aRv.Throw(NS_ERROR_FAILURE);
return;
}
// XXX: For future reference: NDA call must run on the main thread.
mDecoder->NotifyDataArrived(reinterpret_cast<const char*>(aData),

View File

@ -119,9 +119,13 @@ private:
void DispatchSimpleEvent(const char* aName);
void QueueAsyncSimpleEvent(const char* aName);
// Create a new decoder for mType, add it to mDecoders and update mCurrentDecoder.
// Create a new decoder for mType, and store the result in mDecoder.
// Returns true if mDecoder was set.
bool InitNewDecoder();
// Set mDecoder to null and reset mDecoderInitialized.
void DiscardDecoder();
// Update mUpdating and fire the appropriate events.
void StartUpdating();
void StopUpdating();
@ -150,7 +154,7 @@ private:
SourceBufferAppendMode mAppendMode;
bool mUpdating;
bool mDecoderInit;
bool mDecoderInitialized;
};
} // namespace dom

View File

@ -0,0 +1,27 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script>
/*
user_pref("media.mediasource.enabled", true);
*/
function boom()
{
var source = new window.MediaSource();
var videoElement = document.createElementNS('http://www.w3.org/1999/xhtml', 'video');
videoElement.src = URL.createObjectURL(source);
setTimeout(function() {
var buf = source.addSourceBuffer("video/webm");
buf.abort();
buf.appendBuffer(new Float32Array(203));
}, 0);
}
</script>
</head>
<body onload="boom();"></body>
</html>

View File

@ -0,0 +1,2 @@
test-pref(media.mediasource.enabled,true) load 926665.html
test-pref(media.mediasource.enabled,true) load 1005366.html

View File

@ -69,4 +69,4 @@ load offline-buffer-source-ended-1.html
skip-if(B2G) HTTP load media-element-source-seek-1.html # intermittent B2G timeouts, bug 994351
skip-if(B2G) load oscillator-ended-1.html # intermittent B2G timeouts, bug 920338
skip-if(B2G) load oscillator-ended-2.html # intermittent B2G timeouts, bug 920338
test-pref(media.mediasource.enabled,true) load 926665.html
include ../../mediasource/test/crashtests/crashtests.list