Bug 1189506. Simplify blocking calculations based on the observation that once a stream starts blocking in a given processing interval, it must stay blocked. r=karlt

--HG--
extra : commitid : 2gcihxVXqlY
extra : rebase_source : dfb0bf716b8608a47fef25838c3fccdf132e0f82
This commit is contained in:
Robert O'Callahan 2015-09-16 16:17:30 +12:00
Родитель 2e597371be
Коммит d18eba5a82
2 изменённых файлов: 38 добавлений и 80 удалений

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

@ -399,15 +399,15 @@ MediaStreamGraphImpl::UpdateCurrentTimeForStreams(GraphTime aPrevCurrentTime,
}
}
bool
MediaStreamGraphImpl::WillUnderrun(MediaStream* aStream, GraphTime aTime,
GraphTime aEndBlockingDecisions, GraphTime* aEnd)
GraphTime
MediaStreamGraphImpl::WillUnderrun(MediaStream* aStream,
GraphTime aEndBlockingDecisions)
{
// Finished streams can't underrun. ProcessedMediaStreams also can't cause
// underrun currently, since we'll always be able to produce data for them
// unless they block on some other stream.
if (aStream->mFinished || aStream->AsProcessedStream()) {
return false;
return aEndBlockingDecisions;
}
GraphTime bufferEnd =
StreamTimeToGraphTime(aStream, aStream->GetBufferEnd(),
@ -422,27 +422,7 @@ MediaStreamGraphImpl::WillUnderrun(MediaStream* aStream, GraphTime aTime,
NS_ASSERTION(bufferEnd >= mProcessedTime, "Buffer underran");
}
#endif
// We should block after bufferEnd.
if (bufferEnd <= aTime) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p will block due to data underrun at %ld, "
"bufferEnd %ld",
aStream, aTime, bufferEnd));
return true;
}
// We should keep blocking if we're currently blocked and we don't have
// data all the way through to aEndBlockingDecisions. If we don't have
// data all the way through to aEndBlockingDecisions, we'll block soon,
// but we might as well remain unblocked and play the data we've got while
// we can.
if (bufferEnd < aEndBlockingDecisions && aStream->mBlocked.GetBefore(aTime)) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p will block due to speculative data underrun, "
"bufferEnd %f (end at %ld)",
aStream, MediaTimeToSeconds(bufferEnd), bufferEnd));
return true;
}
// Reconsider decisions at bufferEnd
*aEnd = std::min(*aEnd, bufferEnd);
return false;
return std::min(bufferEnd, aEndBlockingDecisions);
}
void
@ -715,12 +695,10 @@ MediaStreamGraphImpl::RecomputeBlocking(GraphTime aEndBlockingDecisions)
STREAM_LOG(LogLevel::Verbose, ("Media graph %p computing blocking for time %f",
this, MediaTimeToSeconds(mStateComputedTime)));
for (MediaStream* stream : AllStreams()) {
GraphTime end;
for (GraphTime t = mStateComputedTime;
t < aEndBlockingDecisions; t = end) {
end = GRAPH_TIME_MAX;
RecomputeBlockingAt(stream, t, aEndBlockingDecisions, &end);
}
GraphTime blockTime =
ComputeStreamBlockTime(stream, mStateComputedTime, aEndBlockingDecisions);
stream->mBlocked.SetAtAndAfter(mStateComputedTime, false);
stream->mBlocked.SetAtAndAfter(blockTime, true);
}
STREAM_LOG(LogLevel::Verbose, ("Media graph %p computed blocking for interval %f to %f",
this, MediaTimeToSeconds(mStateComputedTime),
@ -734,50 +712,32 @@ MediaStreamGraphImpl::RecomputeBlocking(GraphTime aEndBlockingDecisions)
mStateComputedTime = aEndBlockingDecisions;
}
void
MediaStreamGraphImpl::RecomputeBlockingAt(MediaStream* aStream,
GraphTime aTime,
GraphTime aEndBlockingDecisions,
GraphTime* aEnd)
GraphTime
MediaStreamGraphImpl::ComputeStreamBlockTime(MediaStream* aStream,
GraphTime aTime,
GraphTime aEndBlockingDecisions)
{
bool block = false;
do {
if (aStream->mFinished) {
GraphTime endTime = StreamTimeToGraphTime(aStream,
aStream->GetStreamBuffer().GetAllTracksEnd());
if (endTime <= aTime) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is blocked due to being finished", aStream));
// We'll block indefinitely
block = true;
*aEnd = std::min(*aEnd, aEndBlockingDecisions);
continue;
} else {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is finished, but not blocked yet (end at %f, with blocking at %f)",
aStream, MediaTimeToSeconds(aStream->GetBufferEnd()),
MediaTimeToSeconds(endTime)));
*aEnd = std::min(*aEnd, endTime);
}
if (aStream->mFinished) {
GraphTime endTime = StreamTimeToGraphTime(aStream,
aStream->GetStreamBuffer().GetAllTracksEnd());
if (endTime <= aTime) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is blocked due to being finished", aStream));
return aTime;
} else {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is finished, but not blocked yet (end at %f, with blocking at %f)",
aStream, MediaTimeToSeconds(aStream->GetBufferEnd()),
MediaTimeToSeconds(endTime)));
// Data can't be added to a finished stream, so underruns are irrelevant.
return std::min(endTime, aEndBlockingDecisions);
}
}
if (aStream->IsSuspended()) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is blocked due to being suspended", aStream));
block = true;
continue;
}
if (aStream->IsSuspended()) {
STREAM_LOG(LogLevel::Verbose, ("MediaStream %p is blocked due to being suspended", aStream));
return aTime;
}
bool underrun = WillUnderrun(aStream, aTime, aEndBlockingDecisions, aEnd);
if (underrun) {
// We'll block indefinitely
block = true;
*aEnd = std::min(*aEnd, aEndBlockingDecisions);
continue;
}
} while (false);
NS_ASSERTION(*aEnd > aTime, "Failed to advance!");
aStream->mBlocked.SetAtAndAfter(aTime, block);
return WillUnderrun(aStream, aEndBlockingDecisions);
}
void

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

@ -310,9 +310,9 @@ public:
* in the future, *aEnd will be reduced to the first time in the future to
* recompute those decisions.
*/
void RecomputeBlockingAt(MediaStream* aStream,
GraphTime aTime, GraphTime aEndBlockingDecisions,
GraphTime* aEnd);
GraphTime ComputeStreamBlockTime(MediaStream* aStream,
GraphTime aTime,
GraphTime aEndBlockingDecisions);
/**
* Returns smallest value of t such that t is a multiple of
* WEBAUDIO_BLOCK_SIZE and t > aTime.
@ -329,13 +329,11 @@ public:
GraphTime aFrom,
GraphTime aTo);
/**
* Returns true if aStream will underrun at aTime for its own playback.
* aEndBlockingDecisions is when we plan to stop making blocking decisions.
* *aEnd will be reduced to the first time in the future to recompute these
* decisions.
* If aStream will underrun between aTime, and aEndBlockingDecisions, returns
* the time at which the underrun will start. Otherwise return
* aEndBlockingDecisions.
*/
bool WillUnderrun(MediaStream* aStream, GraphTime aTime,
GraphTime aEndBlockingDecisions, GraphTime* aEnd);
GraphTime WillUnderrun(MediaStream* aStream, GraphTime aEndBlockingDecisions);
/**
* Given a graph time aTime, convert it to a stream time taking into