Bug 1062134 - Freeze decoding when back from Dormant state. r=jwwang

This commit is contained in:
Benjamin Chen 2014-10-24 17:25:45 +08:00
parent 460ea00cb5
commit ca40a01d83
4 changed files with 34 additions and 17 deletions

View File

@ -213,7 +213,9 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mDropVideoUntilNextDiscontinuity(false),
mDecodeToSeekTarget(false),
mCurrentTimeBeforeSeek(0),
mLastFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED)
mLastFrameStatus(MediaDecoderOwner::NEXT_FRAME_UNINITIALIZED),
mDecodingFrozenAtStateMetadata(false),
mDecodingFrozenAtStateDecoding(false)
{
MOZ_COUNT_CTOR(MediaDecoderStateMachine);
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
@ -1356,8 +1358,9 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
SetState(DECODER_STATE_DORMANT);
mDecoder->GetReentrantMonitor().NotifyAll();
} else if ((aDormant != true) && (mState == DECODER_STATE_DORMANT)) {
mDecodingFrozenAtStateMetadata = true;
mDecodingFrozenAtStateDecoding = true;
ScheduleStateMachine();
mStartTime = 0;
mCurrentFrameTime = 0;
SetState(DECODER_STATE_DECODING_NONE);
mDecoder->GetReentrantMonitor().NotifyAll();
@ -1454,6 +1457,10 @@ void MediaDecoderStateMachine::Play()
SetState(DECODER_STATE_DECODING);
mDecodeStartTime = TimeStamp::Now();
}
if (mDecodingFrozenAtStateDecoding) {
mDecodingFrozenAtStateDecoding = false;
DispatchDecodeTasksIfNeeded();
}
// Once we start playing, we don't want to minimize our prerolling, as we
// assume the user is likely to want to keep playing in future.
mMinimizePreroll = false;
@ -1515,6 +1522,8 @@ void MediaDecoderStateMachine::Seek(const SeekTarget& aTarget)
NS_ASSERTION(NS_IsMainThread(), "Should be on main thread.");
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
mDecodingFrozenAtStateDecoding = false;
if (mState == DECODER_STATE_SHUTDOWN) {
return;
}
@ -1622,6 +1631,11 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
return;
}
if (mState == DECODER_STATE_DECODING && mDecodingFrozenAtStateDecoding) {
DECODER_LOG("DispatchDecodeTasksIfNeeded return due to "
"mFreezeDecodingAtStateDecoding");
return;
}
// NeedToDecodeAudio() can go from false to true while we hold the
// monitor, but it can't go from true to false. This can happen because
// NeedToDecodeAudio() takes into account the amount of decoded audio
@ -1972,6 +1986,10 @@ nsresult MediaDecoderStateMachine::DecodeMetadata()
SetStartTime(0);
res = FinishDecodeMetadata();
NS_ENSURE_SUCCESS(res, res);
} else if (mDecodingFrozenAtStateMetadata) {
SetStartTime(mStartTime);
res = FinishDecodeMetadata();
NS_ENSURE_SUCCESS(res, res);
} else {
if (HasAudio()) {
ReentrantMonitorAutoExit unlock(mDecoder->GetReentrantMonitor());
@ -1997,7 +2015,7 @@ MediaDecoderStateMachine::FinishDecodeMetadata()
return NS_ERROR_FAILURE;
}
if (!mScheduler->IsRealTime()) {
if (!mScheduler->IsRealTime() && !mDecodingFrozenAtStateMetadata) {
const VideoData* v = VideoQueue().PeekFront();
const AudioData* a = AudioQueue().PeekFront();
@ -2029,6 +2047,8 @@ MediaDecoderStateMachine::FinishDecodeMetadata()
mStartTime, mEndTime, GetDuration(),
mDecoder->IsTransportSeekable(), mDecoder->IsMediaSeekable());
mDecodingFrozenAtStateMetadata = false;
if (HasAudio() && !HasVideo()) {
// We're playing audio only. We don't need to worry about slow video
// decodes causing audio underruns, so don't buffer so much audio in

View File

@ -921,6 +921,17 @@ protected:
mozilla::MediaMetadataManager mMetadataManager;
MediaDecoderOwner::NextFrameStatus mLastFrameStatus;
// True if we are back from DECODER_STATE_DORMANT state, and we can skip
// SetStartTime because the mStartTime already set before. Also we don't need
// to decode any audio/video since the MediaDecoder will trigger a seek
// operation soon.
// mDecodingFrozenAtStateMetadata: turn on/off at
// SetDormant/FinishDecodeMetadata.
// mDecodingFrozenAtStateDecoding: turn on/off at
// SetDormant/Seek,Play.
bool mDecodingFrozenAtStateMetadata;
bool mDecodingFrozenAtStateDecoding;
};
} // namespace mozilla;

View File

@ -101,16 +101,4 @@ RtspMediaCodecReader::ReadMetadata(MediaInfo* aInfo,
return rv;
}
// Called on Binder thread.
void
RtspMediaCodecReader::codecReserved(Track& aTrack)
{
// TODO: fix me, we need a SeekTime(0) here because the
// MediaDecoderStateMachine will update the mStartTime after ReadMetadata.
MediaCodecReader::codecReserved(aTrack);
if (aTrack.mCodec != nullptr) {
mRtspResource->SeekTime(0);
}
}
} // namespace mozilla

View File

@ -65,8 +65,6 @@ public:
virtual nsresult ReadMetadata(MediaInfo* aInfo,
MetadataTags** aTags) MOZ_OVERRIDE;
virtual void codecReserved(Track& aTrack) MOZ_OVERRIDE;
private:
// A pointer to RtspMediaResource for calling the Rtsp specific function.
// The lifetime of mRtspResource is controlled by MediaDecoder. MediaDecoder