Bug 1201393. Make suspended MediaStreams implicitly always block. r=padenot

To make this work, we have to iterate over suspended MediaStreams in a few
more places. We don't need START_TIME_DELAYED anymore since blocking takes
care of that. I think it's good to allow suspended MediaStreams to notify
the main thread that they're finished; we might need that later when
we have non-AudioNode streams being suspended.

--HG--
extra : commitid : AZKt73Eg3rQ
extra : rebase_source : a662e9c85453212299f30085c1228ec959355440
This commit is contained in:
Robert O'Callahan 2015-09-04 17:01:01 +12:00
Родитель a4974cf43a
Коммит 07c25fad56
2 изменённых файлов: 25 добавлений и 46 удалений

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

@ -82,13 +82,12 @@ MediaStreamGraphImpl::FinishStream(MediaStream* aStream)
SetStreamOrderDirty();
}
static const GraphTime START_TIME_DELAYED = -1;
void
MediaStreamGraphImpl::AddStreamGraphThread(MediaStream* aStream)
{
aStream->mBufferStartTime = mProcessedTime;
// Check if we're adding a stream to a suspended context, in which case, we
// add it to mSuspendedStreams, and delay setting mBufferStartTime
// add it to mSuspendedStreams
bool contextSuspended = false;
if (aStream->AsAudioNodeStream()) {
for (uint32_t i = 0; i < mSuspendedStreams.Length(); i++) {
@ -99,11 +98,9 @@ MediaStreamGraphImpl::AddStreamGraphThread(MediaStream* aStream)
}
if (contextSuspended) {
aStream->mBufferStartTime = START_TIME_DELAYED;
mSuspendedStreams.AppendElement(aStream);
STREAM_LOG(LogLevel::Debug, ("Adding media stream %p to the graph, in the suspended stream array", aStream));
} else {
aStream->mBufferStartTime = mProcessedTime;
mStreams.AppendElement(aStream);
STREAM_LOG(LogLevel::Debug, ("Adding media stream %p to the graph", aStream));
}
@ -395,18 +392,16 @@ MediaStreamGraphImpl::UpdateCurrentTimeForStreams(GraphTime aPrevCurrentTime,
MediaTimeToSeconds(stream->mBufferStartTime),
MediaTimeToSeconds(blockedTime)));
if (mSuspendedStreams.IndexOf(stream) == mSuspendedStreams.NoIndex) {
bool streamHasOutput = blockedTime < aNextCurrentTime - aPrevCurrentTime;
NS_ASSERTION(!streamHasOutput || !stream->mNotifiedFinished,
"Shouldn't have already notified of finish *and* have output!");
bool streamHasOutput = blockedTime < aNextCurrentTime - aPrevCurrentTime;
NS_ASSERTION(!streamHasOutput || !stream->mNotifiedFinished,
"Shouldn't have already notified of finish *and* have output!");
if (streamHasOutput) {
StreamNotifyOutput(stream);
}
if (streamHasOutput) {
StreamNotifyOutput(stream);
}
if (stream->mFinished && !stream->mNotifiedFinished) {
StreamReadyToFinish(stream);
}
if (stream->mFinished && !stream->mNotifiedFinished) {
StreamReadyToFinish(stream);
}
}
}
@ -851,6 +846,12 @@ MediaStreamGraphImpl::RecomputeBlockingAt(const nsTArray<MediaStream*>& aStreams
continue;
}
if (StreamSuspended(stream)) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is blocked due to being suspended", stream));
MarkStreamBlocking(stream);
continue;
}
bool underrun = WillUnderrun(stream, aTime, aEndBlockingDecisions, aEnd);
if (underrun) {
// We'll block indefinitely
@ -1249,9 +1250,9 @@ MediaStreamGraphImpl::PrepareUpdatesToMainThreadState(bool aFinalUpdate)
// We don't want to frequently update the main thread about timing update
// when we are not running in realtime.
if (aFinalUpdate || ShouldUpdateMainThread()) {
mStreamUpdates.SetCapacity(mStreamUpdates.Length() + mStreams.Length());
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
MediaStream* stream = mStreams[i];
mStreamUpdates.SetCapacity(mStreamUpdates.Length() + mStreams.Length() +
mSuspendedStreams.Length());
for (MediaStream* stream : AllStreams()) {
if (!stream->MainThreadNeedsUpdates()) {
continue;
}
@ -1315,9 +1316,8 @@ MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
bool
MediaStreamGraphImpl::AllFinishedStreamsNotified()
{
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
MediaStream* s = mStreams[i];
if (s->mFinished && !s->mNotifiedFinished) {
for (MediaStream* stream : AllStreams()) {
if (stream->mFinished && !stream->mNotifiedFinished) {
return false;
}
}
@ -1462,8 +1462,8 @@ MediaStreamGraphImpl::OneIteration(GraphTime aStateEnd)
if (mNeedsMemoryReport) {
mNeedsMemoryReport = false;
for (uint32_t i = 0; i < mStreams.Length(); ++i) {
AudioNodeStream* stream = mStreams[i]->AsAudioNodeStream();
for (MediaStream* s : AllStreams()) {
AudioNodeStream* stream = s->AsAudioNodeStream();
if (stream) {
AudioNodeSizes usage;
stream->SizeOfAudioNodesIncludingThis(MallocSizeOf, usage);
@ -1582,8 +1582,8 @@ public:
// delete it.
NS_ASSERTION(mGraph->mForceShutDown || !mGraph->mRealtime,
"Not in forced shutdown?");
for (uint32_t i = 0; i < mGraph->mStreams.Length(); ++i) {
DOMMediaStream* s = mGraph->mStreams[i]->GetWrapper();
for (MediaStream* stream : mGraph->AllStreams()) {
DOMMediaStream* s = stream->GetWrapper();
if (s) {
s->NotifyMediaStreamGraphShutdown();
}
@ -3229,13 +3229,6 @@ MediaStreamGraphImpl::MoveStreams(AudioContextOperation aAudioContextOperation,
to.AppendElement(stream);
}
// If streams got added during a period where an AudioContext was suspended,
// set their buffer start time to the appropriate value now:
if (aAudioContextOperation == AudioContextOperation::Resume &&
stream->mBufferStartTime == START_TIME_DELAYED) {
stream->mBufferStartTime = mProcessedTime;
}
stream->remove();
}
STREAM_LOG(LogLevel::Debug, ("Moving streams between suspended and running"

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

@ -857,11 +857,6 @@ AudioContext::Suspend(ErrorResult& aRv)
Destination()->Suspend();
MediaStream* ds = DestinationStream();
if (ds) {
ds->BlockStreamIfNeeded();
}
mPromiseGripArray.AppendElement(promise);
Graph()->ApplyAudioContextOperation(DestinationStream()->AsAudioNodeStream(),
AudioContextOperation::Suspend, promise);
@ -897,11 +892,6 @@ AudioContext::Resume(ErrorResult& aRv)
Destination()->Resume();
MediaStream* ds = DestinationStream();
if (ds) {
ds->UnblockStreamIfNeeded();
}
mPromiseGripArray.AppendElement(promise);
Graph()->ApplyAudioContextOperation(DestinationStream()->AsAudioNodeStream(),
AudioContextOperation::Resume, promise);
@ -943,10 +933,6 @@ AudioContext::Close(ErrorResult& aRv)
if (ds) {
Graph()->ApplyAudioContextOperation(ds->AsAudioNodeStream(),
AudioContextOperation::Close, promise);
if (ds) {
ds->BlockStreamIfNeeded();
}
}
return promise.forget();
}