Bug 938022. Part 2: Block captured MediaStream when the MediaDecoderStateMachine is not playing. r=cpearce

--HG--
extra : rebase_source : 01d887b3b5917b7c51a286d61feb10e7b2426d9a
This commit is contained in:
Robert O'Callahan 2013-11-23 22:48:24 +13:00
parent b32400571f
commit 397a575007
4 changed files with 41 additions and 5 deletions

View File

@ -199,7 +199,8 @@ MediaDecoder::DecodedStreamData::DecodedStreamData(MediaDecoder* aDecoder,
mHaveSentFinishAudio(false),
mHaveSentFinishVideo(false),
mStream(aStream),
mHaveBlockedForPlayState(false)
mHaveBlockedForPlayState(false),
mHaveBlockedForStateMachineNotPlaying(false)
{
mStream->AddMainThreadListener(this);
}
@ -244,6 +245,29 @@ void MediaDecoder::DestroyDecodedStream()
mDecodedStream = nullptr;
}
void MediaDecoder::UpdateStreamBlockingForStateMachinePlaying()
{
GetReentrantMonitor().AssertCurrentThreadIn();
if (!mDecodedStream) {
return;
}
bool blockForStateMachineNotPlaying =
mDecoderStateMachine && !mDecoderStateMachine->IsPlaying() &&
mDecoderStateMachine->GetState() != MediaDecoderStateMachine::DECODER_STATE_COMPLETED;
if (blockForStateMachineNotPlaying != mDecodedStream->mHaveBlockedForStateMachineNotPlaying) {
mDecodedStream->mHaveBlockedForStateMachineNotPlaying = blockForStateMachineNotPlaying;
int32_t delta = blockForStateMachineNotPlaying ? 1 : -1;
if (NS_IsMainThread()) {
mDecodedStream->mStream->ChangeExplicitBlockerCount(delta);
} else {
nsCOMPtr<nsIRunnable> runnable =
NS_NewRunnableMethodWithArg<int32_t>(mDecodedStream->mStream.get(),
&MediaStream::ChangeExplicitBlockerCount, delta);
NS_DispatchToMainThread(runnable);
}
}
}
void MediaDecoder::RecreateDecodedStream(int64_t aStartTimeUSecs)
{
MOZ_ASSERT(NS_IsMainThread());
@ -269,6 +293,7 @@ void MediaDecoder::RecreateDecodedStream(int64_t aStartTimeUSecs)
}
ConnectDecodedStreamToOutputStream(&os);
}
UpdateStreamBlockingForStateMachinePlaying();
mDecodedStream->mHaveBlockedForPlayState = mPlayState != PLAY_STATE_PLAYING;
if (mDecodedStream->mHaveBlockedForPlayState) {

View File

@ -384,6 +384,9 @@ public:
// True when we've explicitly blocked this stream because we're
// not in PLAY_STATE_PLAYING. Used on the main thread only.
bool mHaveBlockedForPlayState;
// We also have an explicit blocker on the stream when
// mDecoderStateMachine is non-null and MediaDecoderStateMachine is false.
bool mHaveBlockedForStateMachineNotPlaying;
virtual void NotifyMainThreadStateChanged() MOZ_OVERRIDE;
};
@ -411,8 +414,14 @@ public:
* Recreates mDecodedStream. Call this to create mDecodedStream at first,
* and when seeking, to ensure a new stream is set up with fresh buffers.
* aStartTimeUSecs is relative to the state machine's mStartTime.
* Decoder monitor must be held.
*/
void RecreateDecodedStream(int64_t aStartTimeUSecs);
/**
* Call this when mDecoderStateMachine or mDecoderStateMachine->IsPlaying() changes.
* Decoder monitor must be held.
*/
void UpdateStreamBlockingForStateMachinePlaying();
/**
* Called when the state of mDecodedStream as visible on the main thread
* has changed. In particular we want to know when the stream has finished

View File

@ -1316,6 +1316,7 @@ void MediaDecoderStateMachine::StopPlayback()
// so it can pause audio playback.
mDecoder->GetReentrantMonitor().NotifyAll();
NS_ASSERTION(!IsPlaying(), "Should report not playing at end of StopPlayback()");
mDecoder->UpdateStreamBlockingForStateMachinePlaying();
}
void MediaDecoderStateMachine::StartPlayback()
@ -1333,6 +1334,7 @@ void MediaDecoderStateMachine::StartPlayback()
NS_WARNING("Failed to create audio thread");
}
mDecoder->GetReentrantMonitor().NotifyAll();
mDecoder->UpdateStreamBlockingForStateMachinePlaying();
}
void MediaDecoderStateMachine::UpdatePlaybackPositionInternal(int64_t aTime)

View File

@ -345,6 +345,10 @@ public:
void QueueMetadata(int64_t aPublishTime, int aChannels, int aRate, bool aHasAudio, bool aHasVideo, MetadataTags* aTags);
// Returns true if we're currently playing. The decoder monitor must
// be held.
bool IsPlaying();
protected:
virtual uint32_t GetAmpleVideoFrames() { return mAmpleVideoFrames; }
@ -519,10 +523,6 @@ private:
void StartDecodeMetadata();
// Returns true if we're currently playing. The decoder monitor must
// be held.
bool IsPlaying();
// Returns the "media time". This is the absolute time which the media
// playback has reached. i.e. this returns values in the range
// [mStartTime, mEndTime], and mStartTime will not be 0 if the media does