Bug 943461. Part 5: Don't allow a stream to finish before it has produced output up to mStateComputedTime. r=padenot

--HG--
extra : rebase_source : 9bf003c246b63b1dd64665024533fda74a8e1fa4
This commit is contained in:
Robert O'Callahan 2013-12-06 09:23:57 +13:00
Родитель 01835a84a4
Коммит 0e1cc53aae
7 изменённых файлов: 36 добавлений и 21 удалений

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

@ -324,7 +324,8 @@ ConvertSegmentToAudioBlock(AudioSegment* aSegment, AudioChunk* aBlock)
}
void
AudioNodeExternalInputStream::ProduceOutput(GraphTime aFrom, GraphTime aTo)
AudioNodeExternalInputStream::ProduceOutput(GraphTime aFrom, GraphTime aTo,
uint32_t aFlags)
{
// According to spec, number of outputs is always 1.
mLastChunks.SetLength(1);

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

@ -25,7 +25,7 @@ public:
AudioNodeExternalInputStream(AudioNodeEngine* aEngine, TrackRate aSampleRate);
~AudioNodeExternalInputStream();
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo) MOZ_OVERRIDE;
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE;
private:
// For storing pointers and data about input tracks, like the last TrackTick which

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

@ -399,16 +399,11 @@ AudioNodeStream::UpMixDownMixChunk(const AudioChunk* aChunk,
// The MediaStreamGraph guarantees that this is actually one block, for
// AudioNodeStreams.
void
AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo)
AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags)
{
if (mMarkAsFinishedAfterThisBlock) {
// This stream was finished the last time that we looked at it, and all
// of the depending streams have finished their output as well, so now
// it's time to mark this stream as finished.
FinishOutput();
}
EnsureTrack(AUDIO_TRACK, mSampleRate);
// No more tracks will be coming
mBuffer.AdvanceKnownTracksTime(STREAM_TIME_MAX);
uint16_t outputCount = std::max(uint16_t(1), mEngine->OutputCount());
mLastChunks.SetLength(outputCount);
@ -446,7 +441,16 @@ AudioNodeStream::ProduceOutput(GraphTime aFrom, GraphTime aTo)
}
}
AdvanceOutputSegment();
if (!IsFinishedOnGraphThread()) {
// Don't output anything after we've finished!
AdvanceOutputSegment();
if (mMarkAsFinishedAfterThisBlock && (aFlags & ALLOW_FINISH)) {
// This stream was finished the last time that we looked at it, and all
// of the depending streams have finished their output as well, so now
// it's time to mark this stream as finished.
FinishOutput();
}
}
}
void

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

@ -84,7 +84,7 @@ public:
mAudioParamStream = true;
}
virtual AudioNodeStream* AsAudioNodeStream() { return this; }
virtual AudioNodeStream* AsAudioNodeStream() MOZ_OVERRIDE { return this; }
// Graph thread only
void SetStreamTimeParameterImpl(uint32_t aIndex, MediaStream* aRelativeToStream,
@ -92,7 +92,7 @@ public:
void SetChannelMixingParametersImpl(uint32_t aNumberOfChannels,
dom::ChannelCountMode aChannelCountMoe,
dom::ChannelInterpretation aChannelInterpretation);
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo);
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE;
TrackTicks GetCurrentPosition();
bool IsAudioParamStream() const
{

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

@ -1092,7 +1092,7 @@ MediaStreamGraphImpl::ProduceDataForStreamsBlockByBlock(uint32_t aStreamIndex,
for (uint32_t i = aStreamIndex; i < mStreams.Length(); ++i) {
ProcessedMediaStream* ps = mStreams[i]->AsProcessedStream();
if (ps) {
ps->ProduceOutput(t, next);
ps->ProduceOutput(t, next, (next == aTo) ? ProcessedMediaStream::ALLOW_FINISH : 0);
}
}
t = next;
@ -1197,7 +1197,8 @@ MediaStreamGraphImpl::RunThread()
ticksProcessed += TimeToTicksRoundDown(n->SampleRate(), mStateComputedTime - prevComputedTime);
doneAllProducing = true;
} else {
ps->ProduceOutput(prevComputedTime, mStateComputedTime);
ps->ProduceOutput(prevComputedTime, mStateComputedTime,
ProcessedMediaStream::ALLOW_FINISH);
NS_ASSERTION(stream->mBuffer.GetEnd() >=
GraphTimeToStreamTime(stream, mStateComputedTime),
"Stream did not produce enough data");

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

@ -958,10 +958,19 @@ public:
* streams (mBlocked is up to date up to mStateComputedTime).
* Also, we've produced output for all streams up to this one. If this stream
* is not in a cycle, then all its source streams have produced data.
* Generate output up to mStateComputedTime.
* Generate output from aFrom to aTo.
* This is called only on streams that have not finished.
* ProduceOutput is allowed to call FinishOnGraphThread only if ALLOW_FINISH
* is in aFlags. (This flag will be set when aTo >= mStateComputedTime, i.e.
* when we've producing the last block of data we need to produce.) Otherwise
* we can get into a situation where we've determined the stream should not
* block before mStateComputedTime, but the stream finishes before
* mStateComputedTime, violating the invariant that finished streams are blocked.
*/
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo) = 0;
enum {
ALLOW_FINISH = 0x01
};
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) = 0;
void SetAutofinishImpl(bool aAutofinish) { mAutofinish = aAutofinish; }
/**

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

@ -29,7 +29,7 @@ public:
mFilterCallback(nullptr),
mMaxTrackID(0) {}
virtual void RemoveInput(MediaInputPort* aPort)
virtual void RemoveInput(MediaInputPort* aPort) MOZ_OVERRIDE
{
for (int32_t i = mTrackMap.Length() - 1; i >= 0; --i) {
if (mTrackMap[i].mInputPort == aPort) {
@ -39,7 +39,7 @@ public:
}
ProcessedMediaStream::RemoveInput(aPort);
}
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo)
virtual void ProduceOutput(GraphTime aFrom, GraphTime aTo, uint32_t aFlags) MOZ_OVERRIDE
{
nsAutoTArray<bool,8> mappedTracksFinished;
nsAutoTArray<bool,8> mappedTracksWithMatchingInputTracks;
@ -95,7 +95,7 @@ public:
mTrackMap.RemoveElementAt(i);
}
}
if (allFinished && mAutofinish) {
if (allFinished && mAutofinish && (aFlags & ALLOW_FINISH)) {
// All streams have finished and won't add any more tracks, and
// all our tracks have actually finished and been removed from our map,
// so we're finished now.
@ -117,7 +117,7 @@ public:
// Forward SetTrackEnabled(output_track_id, enabled) to the Source MediaStream,
// translating the output track ID into the correct ID in the source.
virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) {
virtual void ForwardTrackEnabled(TrackID aOutputID, bool aEnabled) MOZ_OVERRIDE {
for (int32_t i = mTrackMap.Length() - 1; i >= 0; --i) {
if (mTrackMap[i].mOutputTrackID == aOutputID) {
mTrackMap[i].mInputPort->GetSource()->