Bug 1120017 - Make the DispatchDecodeTasksIfNeeded path handle DECODER_STATE_DECODING_FIRSTFRAME. r=cpearce
Once we make MP4Reader reject with WAITING_FOR_DATA, we end up with the following scenario:
DecodeFirstFrame requests audio data, and then it gets rejected with WAITING_FOR_DATA.
So OnAudioNotDecided does WaitForData, which eventually causes us to be called back in
MediaDecoderStateMachine::WaitForDataResolved. That does DispatchDecodeTasksIfNeeded, which
currently bails out of our state is DECODER_STATE_DECODING_FIRSTFRAME.
The other way to do this would be to add a separate specialized path through all this
asynchronicity for DECODER_STATE_DECODING_FIRSTFRAME. But it's not clear to me what that
buys us.
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -571,16 +571,19 @@ MediaDecoderStateMachine::NeedToDecodeVi
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
(!mMinimizePreroll && !HaveEnoughDecodedVideo()));
}
bool
MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
{
AssertCurrentThreadInMonitor();
+ if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
+ return false;
+ }
MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
mState == DECODER_STATE_BUFFERING ||
mState == DECODER_STATE_SEEKING);
// We are in seeking or buffering states, don't skip frame.
if (!IsVideoDecoding() || mState == DECODER_STATE_BUFFERING ||
mState == DECODER_STATE_SEEKING) {
return false;
@@ -618,16 +621,17 @@ MediaDecoderStateMachine::DecodeVideo()
{
int64_t currentTime = 0;
bool skipToNextKeyFrame = false;
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
if (mState != DECODER_STATE_DECODING &&
+ mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
mVideoRequestStatus = RequestStatus::Idle;
DispatchDecodeTasksIfNeeded();
return;
}
skipToNextKeyFrame = NeedToSkipToNextKeyframe();
@@ -667,16 +671,17 @@ MediaDecoderStateMachine::NeedToDecodeAu
void
MediaDecoderStateMachine::DecodeAudio()
{
{
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
NS_ASSERTION(OnDecodeThread(), "Should be on decode thread.");
if (mState != DECODER_STATE_DECODING &&
+ mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
mAudioRequestStatus = RequestStatus::Idle;
DispatchDecodeTasksIfNeeded();
mon.NotifyAll();
return;
}
}
@@ -1772,16 +1777,17 @@ MediaDecoderStateMachine::SetReaderIdle(
}
void
MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
{
AssertCurrentThreadInMonitor();
if (mState != DECODER_STATE_DECODING &&
+ mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
return;
}
if (mState == DECODER_STATE_DECODING && mDecodingFrozenAtStateDecoding) {
DECODER_LOG("DispatchDecodeTasksIfNeeded return due to "
"mFreezeDecodingAtStateDecoding");
@@ -1887,17 +1893,17 @@ MediaDecoderStateMachine::EnsureAudioDec
SAMPLE_LOG("EnsureAudioDecodeTaskQueued isDecoding=%d status=%d",
IsAudioDecoding(), mAudioRequestStatus);
if (mState >= DECODER_STATE_COMPLETED) {
return NS_OK;
}
- MOZ_ASSERT(mState > DECODER_STATE_DECODING_FIRSTFRAME);
+ MOZ_ASSERT(mState >= DECODER_STATE_DECODING_FIRSTFRAME);
if (IsAudioDecoding() && mAudioRequestStatus == RequestStatus::Idle && !mWaitingForDecoderSeek) {
RefPtr<nsIRunnable> task(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeAudio));
nsresult rv = DecodeTaskQueue()->Dispatch(task);
if (NS_SUCCEEDED(rv)) {
mAudioRequestStatus = RequestStatus::Pending;
} else {
@@ -1932,17 +1938,17 @@ MediaDecoderStateMachine::EnsureVideoDec
NS_ASSERTION(OnStateMachineThread() || OnDecodeThread(),
"Should be on state machine or decode thread.");
if (mState >= DECODER_STATE_COMPLETED) {
return NS_OK;
}
- MOZ_ASSERT(mState > DECODER_STATE_DECODING_FIRSTFRAME);
+ MOZ_ASSERT(mState >= DECODER_STATE_DECODING_FIRSTFRAME);
if (IsVideoDecoding() && mVideoRequestStatus == RequestStatus::Idle && !mWaitingForDecoderSeek) {
RefPtr<nsIRunnable> task(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::DecodeVideo));
nsresult rv = DecodeTaskQueue()->Dispatch(task);
if (NS_SUCCEEDED(rv)) {
mVideoRequestStatus = RequestStatus::Pending;
} else {