Bug 1059052 - centralize state transitions of MediaDecoderStateMachine. r=cpearce

This commit is contained in:
JW Wang 2014-08-28 02:46:00 +02:00
Родитель 1462ca80fc
Коммит effb885bd5
2 изменённых файлов: 40 добавлений и 14 удалений

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

@ -1049,7 +1049,7 @@ MediaDecoderStateMachine::CheckIfDecodeComplete()
if (!IsVideoDecoding() && !IsAudioDecoding()) { if (!IsVideoDecoding() && !IsAudioDecoding()) {
// We've finished decoding all active streams, // We've finished decoding all active streams,
// so move to COMPLETED state. // so move to COMPLETED state.
mState = DECODER_STATE_COMPLETED; SetState(DECODER_STATE_COMPLETED);
DispatchDecodeTasksIfNeeded(); DispatchDecodeTasksIfNeeded();
ScheduleStateMachine(); ScheduleStateMachine();
} }
@ -1220,6 +1220,30 @@ MediaDecoderOwner::NextFrameStatus MediaDecoderStateMachine::GetNextFrameStatus(
return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE; return MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
} }
static const char* const gMachineStateStr[] = {
"NONE",
"DECODING_METADATA",
"WAIT_FOR_RESOURCES",
"DORMANT",
"DECODING",
"SEEKING",
"BUFFERING",
"COMPLETED",
"SHUTDOWN"
};
void MediaDecoderStateMachine::SetState(State aState)
{
AssertCurrentThreadInMonitor();
if (mState == aState) {
return;
}
DECODER_LOG("Change machine state from %s to %s",
gMachineStateStr[mState], gMachineStateStr[aState]);
mState = aState;
}
void MediaDecoderStateMachine::SetVolume(double volume) void MediaDecoderStateMachine::SetVolume(double volume)
{ {
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread."); NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
@ -1327,13 +1351,13 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
if (aDormant) { if (aDormant) {
ScheduleStateMachine(); ScheduleStateMachine();
mState = DECODER_STATE_DORMANT; SetState(DECODER_STATE_DORMANT);
mDecoder->GetReentrantMonitor().NotifyAll(); mDecoder->GetReentrantMonitor().NotifyAll();
} else if ((aDormant != true) && (mState == DECODER_STATE_DORMANT)) { } else if ((aDormant != true) && (mState == DECODER_STATE_DORMANT)) {
ScheduleStateMachine(); ScheduleStateMachine();
mStartTime = 0; mStartTime = 0;
mCurrentFrameTime = 0; mCurrentFrameTime = 0;
mState = DECODER_STATE_DECODING_NONE; SetState(DECODER_STATE_DECODING_NONE);
mDecoder->GetReentrantMonitor().NotifyAll(); mDecoder->GetReentrantMonitor().NotifyAll();
} }
} }
@ -1348,7 +1372,7 @@ void MediaDecoderStateMachine::Shutdown()
// Change state before issuing shutdown request to threads so those // Change state before issuing shutdown request to threads so those
// threads can start exiting cleanly during the Shutdown call. // threads can start exiting cleanly during the Shutdown call.
DECODER_LOG("Changed state to SHUTDOWN"); DECODER_LOG("Changed state to SHUTDOWN");
mState = DECODER_STATE_SHUTDOWN; SetState(DECODER_STATE_SHUTDOWN);
mScheduler->ScheduleAndShutdown(); mScheduler->ScheduleAndShutdown();
if (mAudioSink) { if (mAudioSink) {
mAudioSink->PrepareToShutdown(); mAudioSink->PrepareToShutdown();
@ -1364,7 +1388,7 @@ void MediaDecoderStateMachine::StartDecoding()
if (mState == DECODER_STATE_DECODING) { if (mState == DECODER_STATE_DECODING) {
return; return;
} }
mState = DECODER_STATE_DECODING; SetState(DECODER_STATE_DECODING);
mDecodeStartTime = TimeStamp::Now(); mDecodeStartTime = TimeStamp::Now();
@ -1388,7 +1412,7 @@ void MediaDecoderStateMachine::StartWaitForResources()
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(), NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
"Should be on state machine or decode thread."); "Should be on state machine or decode thread.");
AssertCurrentThreadInMonitor(); AssertCurrentThreadInMonitor();
mState = DECODER_STATE_WAIT_FOR_RESOURCES; SetState(DECODER_STATE_WAIT_FOR_RESOURCES);
DECODER_LOG("StartWaitForResources"); DECODER_LOG("StartWaitForResources");
} }
@ -1402,7 +1426,7 @@ void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
DECODER_LOG("NotifyWaitingForResourcesStatusChanged"); DECODER_LOG("NotifyWaitingForResourcesStatusChanged");
// The reader is no longer waiting for resources (say a hardware decoder), // The reader is no longer waiting for resources (say a hardware decoder),
// we can now proceed to decode metadata. // we can now proceed to decode metadata.
mState = DECODER_STATE_DECODING_NONE; SetState(DECODER_STATE_DECODING_NONE);
ScheduleStateMachine(); ScheduleStateMachine();
} }
@ -1415,7 +1439,7 @@ void MediaDecoderStateMachine::Play()
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor()); ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mState == DECODER_STATE_BUFFERING) { if (mState == DECODER_STATE_BUFFERING) {
DECODER_LOG("Changed state from BUFFERING to DECODING"); DECODER_LOG("Changed state from BUFFERING to DECODING");
mState = DECODER_STATE_DECODING; SetState(DECODER_STATE_DECODING);
mDecodeStartTime = TimeStamp::Now(); mDecodeStartTime = TimeStamp::Now();
} }
// Once we start playing, we don't want to minimize our prerolling, as we // Once we start playing, we don't want to minimize our prerolling, as we
@ -1500,7 +1524,7 @@ void MediaDecoderStateMachine::Seek(const SeekTarget& aTarget)
mSeekTarget = SeekTarget(seekTime, aTarget.mType); mSeekTarget = SeekTarget(seekTime, aTarget.mType);
DECODER_LOG("Changed state to SEEKING (to %lld)", mSeekTarget.mTime); DECODER_LOG("Changed state to SEEKING (to %lld)", mSeekTarget.mTime);
mState = DECODER_STATE_SEEKING; SetState(DECODER_STATE_SEEKING);
if (mDecoder->GetDecodedStream()) { if (mDecoder->GetDecodedStream()) {
mDecoder->RecreateDecodedStream(seekTime - mStartTime); mDecoder->RecreateDecodedStream(seekTime - mStartTime);
} }
@ -1757,7 +1781,7 @@ MediaDecoderStateMachine::StartAudioThread()
nsresult rv = mAudioSink->Init(); nsresult rv = mAudioSink->Init();
if (NS_FAILED(rv)) { if (NS_FAILED(rv)) {
DECODER_WARN("Changed state to SHUTDOWN because audio sink initialization failed"); DECODER_WARN("Changed state to SHUTDOWN because audio sink initialization failed");
mState = DECODER_STATE_SHUTDOWN; SetState(DECODER_STATE_SHUTDOWN);
mScheduler->ScheduleAndShutdown(); mScheduler->ScheduleAndShutdown();
return rv; return rv;
} }
@ -1836,7 +1860,7 @@ MediaDecoderStateMachine::DecodeError()
// and the HTMLMediaElement, so that our pipeline can start exiting // and the HTMLMediaElement, so that our pipeline can start exiting
// cleanly during the sync dispatch below. // cleanly during the sync dispatch below.
DECODER_WARN("Decode error, changed state to SHUTDOWN due to error"); DECODER_WARN("Decode error, changed state to SHUTDOWN due to error");
mState = DECODER_STATE_SHUTDOWN; SetState(DECODER_STATE_SHUTDOWN);
mScheduler->ScheduleAndShutdown(); mScheduler->ScheduleAndShutdown();
mDecoder->GetReentrantMonitor().NotifyAll(); mDecoder->GetReentrantMonitor().NotifyAll();
@ -2161,7 +2185,7 @@ MediaDecoderStateMachine::SeekCompleted()
stopEvent = NS_NewRunnableMethod(mDecoder, &MediaDecoder::SeekingStoppedAtEnd); stopEvent = NS_NewRunnableMethod(mDecoder, &MediaDecoder::SeekingStoppedAtEnd);
// Explicitly set our state so we don't decode further, and so // Explicitly set our state so we don't decode further, and so
// we report playback ended to the media element. // we report playback ended to the media element.
mState = DECODER_STATE_COMPLETED; SetState(DECODER_STATE_COMPLETED);
DispatchDecodeTasksIfNeeded(); DispatchDecodeTasksIfNeeded();
} else { } else {
DECODER_LOG("Changed state from SEEKING (to %lld) to DECODING", seekTime); DECODER_LOG("Changed state from SEEKING (to %lld) to DECODING", seekTime);
@ -2327,7 +2351,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
} }
case DECODER_STATE_DECODING_NONE: { case DECODER_STATE_DECODING_NONE: {
mState = DECODER_STATE_DECODING_METADATA; SetState(DECODER_STATE_DECODING_METADATA);
// Ensure we have a decode thread to decode metadata. // Ensure we have a decode thread to decode metadata.
return EnqueueDecodeMetadataTask(); return EnqueueDecodeMetadataTask();
} }
@ -2914,7 +2938,7 @@ void MediaDecoderStateMachine::StartBuffering()
// will check the current state and decide whether to tell // will check the current state and decide whether to tell
// the element we're buffering or not. // the element we're buffering or not.
UpdateReadyState(); UpdateReadyState();
mState = DECODER_STATE_BUFFERING; SetState(DECODER_STATE_BUFFERING);
DECODER_LOG("Changed state from DECODING to BUFFERING, decoded for %.3lfs", DECODER_LOG("Changed state from DECODING to BUFFERING, decoded for %.3lfs",
decodeDuration.ToSeconds()); decodeDuration.ToSeconds());
#ifdef PR_LOGGING #ifdef PR_LOGGING

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

@ -355,6 +355,8 @@ protected:
void AssertCurrentThreadInMonitor() const { mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); } void AssertCurrentThreadInMonitor() const { mDecoder->GetReentrantMonitor().AssertCurrentThreadIn(); }
void SetState(State aState);
// Inserts MediaData* samples into their respective MediaQueues. // Inserts MediaData* samples into their respective MediaQueues.
// aSample must not be null. // aSample must not be null.
void Push(AudioData* aSample); void Push(AudioData* aSample);