зеркало из https://github.com/mozilla/gecko-dev.git
Bug 1059052 - centralize state transitions of MediaDecoderStateMachine. r=cpearce
This commit is contained in:
Родитель
1462ca80fc
Коммит
effb885bd5
|
@ -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);
|
||||||
|
|
Загрузка…
Ссылка в новой задаче