mirror of
https://gitlab.winehq.org/wine/wine-gecko.git
synced 2024-09-13 09:24:08 -07:00
Bug 1185972
: P2. Refactor handling of first frame decoded. r=jwwang
This commit is contained in:
parent
c6c1ed3337
commit
ae50bb7910
@ -217,7 +217,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
|
||||
mDecodeToSeekTarget(false),
|
||||
mCurrentTimeBeforeSeek(0),
|
||||
mCorruptFrames(30),
|
||||
mDecodingFirstFrame(false),
|
||||
mDecodingFirstFrame(true),
|
||||
mDisabledHardwareAcceleration(false),
|
||||
mDecodingFrozenAtStateDecoding(false),
|
||||
mSentLoadedMetadataEvent(false),
|
||||
@ -571,8 +571,7 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
Push(audio);
|
||||
if (IsDecodingFirstFrame()) {
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
if (MaybeFinishDecodeFirstFrame()) {
|
||||
return;
|
||||
}
|
||||
if (mIsAudioPrerolling && DonePrerollingAudio()) {
|
||||
@ -782,8 +781,7 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
|
||||
switch (mState) {
|
||||
case DECODER_STATE_BUFFERING:
|
||||
case DECODER_STATE_DECODING: {
|
||||
if (IsDecodingFirstFrame()) {
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
if (MaybeFinishDecodeFirstFrame()) {
|
||||
return;
|
||||
}
|
||||
CheckIfDecodeComplete();
|
||||
@ -819,18 +817,26 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
bool
|
||||
MediaDecoderStateMachine::MaybeFinishDecodeFirstFrame()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
if ((IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
|
||||
if (!IsDecodingFirstFrame() ||
|
||||
(IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
|
||||
(IsVideoDecoding() && VideoQueue().GetSize() == 0)) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
if (NS_FAILED(FinishDecodeFirstFrame())) {
|
||||
DecodeError();
|
||||
FinishDecodeFirstFrame();
|
||||
if (!mQueuedSeek.Exists()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// We can now complete the pending seek.
|
||||
mPendingSeek.Steal(mQueuedSeek);
|
||||
SetState(DECODER_STATE_SEEKING);
|
||||
ScheduleStateMachine();
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
@ -860,8 +866,7 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
Push(video);
|
||||
if (IsDecodingFirstFrame()) {
|
||||
MaybeFinishDecodeFirstFrame();
|
||||
if (MaybeFinishDecodeFirstFrame()) {
|
||||
return;
|
||||
}
|
||||
if (mIsVideoPrerolling && DonePrerollingVideo()) {
|
||||
@ -888,7 +893,8 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
|
||||
return;
|
||||
}
|
||||
TimeDuration decodeTime = TimeStamp::Now() - mVideoDecodeStartTime;
|
||||
if (THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
|
||||
if (!IsDecodingFirstFrame() &&
|
||||
THRESHOLD_FACTOR * DurationToUsecs(decodeTime) > mLowAudioThresholdUsecs &&
|
||||
!HasLowUndecodedData())
|
||||
{
|
||||
mLowAudioThresholdUsecs =
|
||||
@ -1161,10 +1167,6 @@ void MediaDecoderStateMachine::SetState(State aState)
|
||||
|
||||
mState = aState;
|
||||
|
||||
if (mState != DECODER_STATE_DECODING) {
|
||||
mDecodingFirstFrame = false;
|
||||
}
|
||||
|
||||
mIsShutdown = mState == DECODER_STATE_ERROR || mState == DECODER_STATE_SHUTDOWN;
|
||||
|
||||
// Clear state-scoped state.
|
||||
@ -1273,6 +1275,7 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
|
||||
mDecodingFrozenAtStateDecoding = true;
|
||||
ScheduleStateMachine();
|
||||
mCurrentPosition = 0;
|
||||
mDecodingFirstFrame = true;
|
||||
SetState(DECODER_STATE_DECODING_NONE);
|
||||
mDecoder->GetReentrantMonitor().NotifyAll();
|
||||
}
|
||||
@ -1323,6 +1326,22 @@ void MediaDecoderStateMachine::StartDecoding()
|
||||
}
|
||||
SetState(DECODER_STATE_DECODING);
|
||||
|
||||
if (mDecodingFirstFrame &&
|
||||
(IsRealTime() || mSentFirstFrameLoadedEvent)) {
|
||||
// if mSentFirstFrameLoadedEvent is set :
|
||||
// We're resuming from dormant state, so we don't need to request
|
||||
// the first samples in order to determine the media start time,
|
||||
// we have the start time from last time we loaded.
|
||||
FinishDecodeFirstFrame();
|
||||
if (mQueuedSeek.Exists()) {
|
||||
// We are returning from dormant, complete any pending seek.
|
||||
mPendingSeek.Steal(mQueuedSeek);
|
||||
SetState(DECODER_STATE_SEEKING);
|
||||
ScheduleStateMachine();
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mDecodeStartTime = TimeStamp::Now();
|
||||
|
||||
CheckIfDecodeComplete();
|
||||
@ -1352,9 +1371,7 @@ void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
|
||||
ScheduleStateMachine();
|
||||
} else if (mState == DECODER_STATE_WAIT_FOR_CDM &&
|
||||
!mReader->IsWaitingOnCDMResource()) {
|
||||
SetState(DECODER_STATE_DECODING);
|
||||
mDecodingFirstFrame = true;
|
||||
EnqueueDecodeFirstFrameTask();
|
||||
StartDecoding();
|
||||
}
|
||||
}
|
||||
|
||||
@ -1484,19 +1501,6 @@ void MediaDecoderStateMachine::StopAudioThread()
|
||||
mAudioSinkPromise.DisconnectIfExists();
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(IsDecodingFirstFrame());
|
||||
|
||||
nsCOMPtr<nsIRunnable> task(
|
||||
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeFirstFrame));
|
||||
OwnerThread()->Dispatch(task.forget());
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
|
||||
{
|
||||
@ -1990,9 +1994,8 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
|
||||
return;
|
||||
}
|
||||
|
||||
SetState(DECODER_STATE_DECODING);
|
||||
mDecodingFirstFrame = true;
|
||||
EnqueueDecodeFirstFrameTask();
|
||||
StartDecoding();
|
||||
|
||||
ScheduleStateMachine();
|
||||
}
|
||||
|
||||
@ -2043,66 +2046,19 @@ MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent()
|
||||
mSentFirstFrameLoadedEvent = true;
|
||||
}
|
||||
|
||||
void
|
||||
MediaDecoderStateMachine::CallDecodeFirstFrame()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
|
||||
if (!IsDecodingFirstFrame()) {
|
||||
return;
|
||||
}
|
||||
if (NS_FAILED(DecodeFirstFrame())) {
|
||||
DECODER_WARN("Decode failed to start, shutting down decoder");
|
||||
DecodeError();
|
||||
}
|
||||
}
|
||||
|
||||
nsresult
|
||||
MediaDecoderStateMachine::DecodeFirstFrame()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
MOZ_ASSERT(IsDecodingFirstFrame());
|
||||
DECODER_LOG("DecodeFirstFrame started");
|
||||
|
||||
if (IsRealTime()) {
|
||||
nsresult res = FinishDecodeFirstFrame();
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
} else if (mSentFirstFrameLoadedEvent) {
|
||||
// We're resuming from dormant state, so we don't need to request
|
||||
// the first samples in order to determine the media start time,
|
||||
// we have the start time from last time we loaded.
|
||||
nsresult res = FinishDecodeFirstFrame();
|
||||
NS_ENSURE_SUCCESS(res, res);
|
||||
} else {
|
||||
if (HasAudio()) {
|
||||
RequestAudioData();
|
||||
}
|
||||
if (HasVideo()) {
|
||||
RequestVideoData();
|
||||
}
|
||||
}
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
bool
|
||||
MediaDecoderStateMachine::IsDecodingFirstFrame()
|
||||
{
|
||||
return mState == DECODER_STATE_DECODING && mDecodingFirstFrame;
|
||||
}
|
||||
|
||||
nsresult
|
||||
void
|
||||
MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
||||
{
|
||||
MOZ_ASSERT(OnTaskQueue());
|
||||
AssertCurrentThreadInMonitor();
|
||||
DECODER_LOG("FinishDecodeFirstFrame");
|
||||
|
||||
if (IsShutdown()) {
|
||||
return NS_ERROR_FAILURE;
|
||||
}
|
||||
|
||||
if (!IsRealTime() && !mSentFirstFrameLoadedEvent) {
|
||||
RenderVideoFrames(1);
|
||||
}
|
||||
@ -2137,18 +2093,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
|
||||
}
|
||||
EnqueueFirstFrameLoadedEvent();
|
||||
|
||||
if (mQueuedSeek.Exists()) {
|
||||
mPendingSeek.Steal(mQueuedSeek);
|
||||
SetState(DECODER_STATE_SEEKING);
|
||||
ScheduleStateMachine();
|
||||
} else if (IsDecodingFirstFrame()) {
|
||||
// StartDecoding() will also check if decode is completed.
|
||||
StartDecoding();
|
||||
}
|
||||
|
||||
mDecodingFirstFrame = false;
|
||||
|
||||
return NS_OK;
|
||||
}
|
||||
|
||||
void
|
||||
@ -2346,7 +2291,8 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
|
||||
|
||||
case DECODER_STATE_DECODING: {
|
||||
if (IsDecodingFirstFrame()) {
|
||||
// DECODER_STATE_DECODING will be started by OnMetadataRead.
|
||||
// We haven't completed decoding our first frames, we can't start
|
||||
// playback yet.
|
||||
return NS_OK;
|
||||
}
|
||||
if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying())
|
||||
|
@ -406,9 +406,6 @@ protected:
|
||||
MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
|
||||
MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }
|
||||
|
||||
bool IsDecodingFirstFrame();
|
||||
nsresult FinishDecodeFirstFrame();
|
||||
|
||||
// True if our buffers of decoded audio are not full, and we should
|
||||
// decode more.
|
||||
bool NeedToDecodeAudio();
|
||||
@ -555,11 +552,6 @@ protected:
|
||||
|
||||
void EnqueueFirstFrameLoadedEvent();
|
||||
|
||||
// Dispatches a task to the state machine thread to begin decoding content.
|
||||
// This is threadsafe and can be called on any thread.
|
||||
// The decoder monitor must be held.
|
||||
nsresult EnqueueDecodeFirstFrameTask();
|
||||
|
||||
// Clears any previous seeking state and initiates a new see on the decoder.
|
||||
// The decoder monitor must be held.
|
||||
void InitiateSeek();
|
||||
@ -617,16 +609,14 @@ protected:
|
||||
void OnMetadataRead(MetadataHolder* aMetadata);
|
||||
void OnMetadataNotRead(ReadMetadataFailureReason aReason);
|
||||
|
||||
// Initiate first content decoding. Called on the state machine thread.
|
||||
// The decoder monitor must be held with exactly one lock count.
|
||||
nsresult DecodeFirstFrame();
|
||||
|
||||
// Wraps the call to DecodeFirstFrame(), signals a DecodeError() on failure.
|
||||
void CallDecodeFirstFrame();
|
||||
|
||||
// Checks whether we're finished decoding first audio and/or video packets,
|
||||
// and switches to DECODING state if so.
|
||||
void MaybeFinishDecodeFirstFrame();
|
||||
// Checks whether we're finished decoding first audio and/or video packets.
|
||||
// If so will trigger firing loadeddata event.
|
||||
// If there are any queued seek, will change state to DECODER_STATE_SEEKING
|
||||
// and return true.
|
||||
bool MaybeFinishDecodeFirstFrame();
|
||||
// Return true if we are currently decoding the first frames.
|
||||
bool IsDecodingFirstFrame();
|
||||
void FinishDecodeFirstFrame();
|
||||
|
||||
// Seeks to mSeekTarget. Called on the decode thread. The decoder monitor
|
||||
// must be held with exactly one lock count.
|
||||
|
Loading…
Reference in New Issue
Block a user