import changes from `dev' branch of rmottola/Arctic-Fox:

- Bug 1186367 - Make MDSM more ignorant of AudioData/VideoData via using MediaQueue<MediaData> instead. r=jwwang (344314a04)
- missing of Bug 1123637 - Remove all code relevant to quota prompts; r=bent,ehsan (ac63ae831)
- Bug 1185892. Part 1 - delegate the job of MediaSourceDecoder::IsExpectingMoreData to its MediaResource. r=jya. (64da133b6)
- Bug 1185892. Part 2 - delegate the job of MediaDecoder::IsExpectingMoreData to its MediaResource. r=jya. (4bca8324d)
- Bug 1185892. Part 3 - replace all calls to MediaDecoder::IsExpectingMoreData() with MediaResource::IsExpectingMoreData. r=jya. (3780bf754)
- fix misspatch of Bug 1134434 (976064ea5)
- Bug 1185972: P1. Remove DECODER_STATE_DECODING_FIRSTFRAME state. r=jwwang (dee513d1c)
- Bug 1185972: P2. Refactor handling of first frame decoded. r=jwwang (95482e8b9)
- Bug 1185972: P4. Initiate seek as early as conditions permit. r=jwwang (f938e673b)
- Bug 1148103: P1. Fix mediasource "once" utility. r=karlt (ba3e21d59)
- Bug 1148103: P2. Add MP4 mediasource mochitests. r=karlt (199372ab6)
- Bug 1136399 - Add test_WaitingOnMissingData_mp4.html and disable the webm version for now. r=jya (ab349f245)
- Bug 1185972: P6. Ensure exiting dormant mode has completed seek before notifying decoder. r=jwwang (5a9252b75)
- Bug 1185972: P3. Don't reduce our buffer threshold coming out of dormant mode. r=jwwang (bf76f6b7d)
- bug 1190285 remove unused GetCurrentTime() r=padenot (95c322cb6)
- bug 1190285 unvirtualize MediaStream::AdvanceTimeVaryingValuesToCurrentTime() r=roc (80f536d5a)
- bug 1190285 remove unused DispatchWhenNotEnoughBuffered r=padenot (6fa27d274)
- bug 1190285 remove unused HaveEnoughBuffered r=padenot (0941a1af7)
- bug 1190285 move GetIntervalForIteration() from base class to ThreadedDriver, where it is used r=padenot (0faaf6db8)
- bug 1190285 share ThreadedDriver interval update code r=padenot (3d5d5ce35)
- bug 1190285 only update mStateComputedTime once per iteration r=padenot (b6cea757a)
- bug 1190285 remove unused MediaStreamGraphImpl::GetAudioPosition() r=roc (b14738229)
- bug 1190285 remove unused graph update indices r=roc (475b980fe)
- Bug 1188257 - Use MediaEventSource for MediaQueue to do the job. r=cpearce. (4d16a4595)
- Bug 1189624 - Have AudioSink listen to MediaQueue events to know whether to continue playback. r=kinetik. (753ab8ca2)
- Bug 1191173 - Mirror MediaDecoder::mSameOriginMedia in MDSM. r=jya. (d4690cb87)
- Bug 1191170 - Move DecodedStreamData from the header to its source file. r=roc. (d5726e979)
- Bug 1191171 - Add SetVolume() to DecodedStream. r=roc. (20e87ac20)
- Bug 1182649 - Log a message when disabling DXVA due to too many invalid frames. r=jrmuizel (0d951a60c)
- Bug 1185416 - Don't stop AudioSink prematurely when decoding is completed. r=kinetik. (1ac43f91e)
- Bug 1186752 - Remove ScheduleStateMachine() in MediaDecoder.cpp since we have state mirror. r=jwwang (1e89c535c)
- Bug 1191684 - Remove unnecessary calls to NotifyAll() on the decoder monitor since no one calls Wait(). r=cpearce. (54a95a5a0)
This commit is contained in:
2021-10-01 12:50:08 +08:00
parent 4ded173333
commit 036a7138f8
40 changed files with 1179 additions and 453 deletions
+99 -136
View File
@@ -214,6 +214,7 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
mDecodeToSeekTarget(false),
mCurrentTimeBeforeSeek(0),
mCorruptFrames(30),
mDecodingFirstFrame(true),
mDisabledHardwareAcceleration(false),
mDecodingFrozenAtStateDecoding(false),
mSentLoadedMetadataEvent(false),
@@ -280,13 +281,13 @@ MediaDecoderStateMachine::MediaDecoderStateMachine(MediaDecoder* aDecoder,
nsRefPtr<MediaDecoderStateMachine> self = this;
AudioQueue().AddPopListener(
[self] (const AudioData* aSample) {
self->OnAudioPopped(aSample);
}, mTaskQueue);
[self] (const MediaData* aSample) {
self->OnAudioPopped(aSample->As<AudioData>());
}, mTaskQueue);
VideoQueue().AddPopListener(
[self] (const VideoData* aSample) {
self->OnVideoPopped(aSample);
[self] (const MediaData* aSample) {
self->OnVideoPopped(aSample->As<VideoData>());
}, mTaskQueue);
}
@@ -377,13 +378,14 @@ void MediaDecoderStateMachine::SendStreamData()
const auto clockTime = GetClock();
while (true) {
const AudioData* a = AudioQueue().PeekFront();
const MediaData* a = AudioQueue().PeekFront();
// If we discard audio samples fed to the stream immediately, we will
// keep decoding audio samples till the end and consume a lot of memory.
// Therefore we only discard those behind the stream clock to throttle
// the decoding speed.
if (a && a->mTime <= clockTime) {
nsRefPtr<AudioData> releaseMe = AudioQueue().PopFront();
nsRefPtr<MediaData> releaseMe = AudioQueue().PopFront();
continue;
}
break;
@@ -406,9 +408,8 @@ bool MediaDecoderStateMachine::HaveEnoughDecodedAudio(int64_t aAmpleAudioUSecs)
return false;
}
// We don't have to check SourceMediaStream::HaveEnoughBuffered() in the
// case of stream-capture for MDSM will ensure buffering level is high enough
// for playback speed at 1x at which the DecodedStream is playing.
// MDSM will ensure buffering level is high enough for playback speed at 1x
// at which the DecodedStream is playing.
return true;
}
@@ -435,7 +436,7 @@ MediaDecoderStateMachine::NeedToDecodeVideo()
HaveEnoughDecodedVideo());
return IsVideoDecoding() &&
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
(mState == DECODER_STATE_DECODING_FIRSTFRAME &&
(IsDecodingFirstFrame() &&
IsVideoDecoding() && VideoQueue().GetSize() == 0) ||
(!mMinimizePreroll && !HaveEnoughDecodedVideo()));
}
@@ -445,7 +446,7 @@ MediaDecoderStateMachine::NeedToSkipToNextKeyframe()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
if (IsDecodingFirstFrame()) {
return false;
}
MOZ_ASSERT(mState == DECODER_STATE_DECODING ||
@@ -502,7 +503,7 @@ MediaDecoderStateMachine::NeedToDecodeAudio()
return IsAudioDecoding() &&
((mState == DECODER_STATE_SEEKING && mDecodeToSeekTarget) ||
(mState == DECODER_STATE_DECODING_FIRSTFRAME &&
(IsDecodingFirstFrame() &&
IsAudioDecoding() && AudioQueue().GetSize() == 0) ||
(!mMinimizePreroll &&
!HaveEnoughDecodedAudio(mAmpleAudioThresholdUsecs * mPlaybackRate) &&
@@ -554,12 +555,6 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
(audio ? audio->mDiscontinuity : 0));
switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: {
Push(audio);
MaybeFinishDecodeFirstFrame();
return;
}
case DECODER_STATE_BUFFERING: {
// If we're buffering, this may be the sample we need to stop buffering.
// Save it and schedule the state machine.
@@ -570,6 +565,9 @@ MediaDecoderStateMachine::OnAudioDecoded(AudioData* aAudioSample)
case DECODER_STATE_DECODING: {
Push(audio);
if (MaybeFinishDecodeFirstFrame()) {
return;
}
if (mIsAudioPrerolling && DonePrerollingAudio()) {
StopPrerollingAudio();
}
@@ -773,13 +771,11 @@ MediaDecoderStateMachine::OnNotDecoded(MediaData::Type aType,
StopPrerollingVideo();
}
switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: {
MaybeFinishDecodeFirstFrame();
return;
}
case DECODER_STATE_BUFFERING:
case DECODER_STATE_DECODING: {
if (MaybeFinishDecodeFirstFrame()) {
return;
}
CheckIfDecodeComplete();
mDecoder->GetReentrantMonitor().NotifyAll();
// Tell AudioSink to wake up for audio queue is finished.
@@ -813,18 +809,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
@@ -844,12 +848,6 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
(video ? video->mDiscontinuity : 0));
switch (mState) {
case DECODER_STATE_DECODING_FIRSTFRAME: {
Push(video);
MaybeFinishDecodeFirstFrame();
return;
}
case DECODER_STATE_BUFFERING: {
// If we're buffering, this may be the sample we need to stop buffering.
// Save it and schedule the state machine.
@@ -860,6 +858,9 @@ MediaDecoderStateMachine::OnVideoDecoded(VideoData* aVideoSample)
case DECODER_STATE_DECODING: {
Push(video);
if (MaybeFinishDecodeFirstFrame()) {
return;
}
if (mIsVideoPrerolling && DonePrerollingVideo()) {
StopPrerollingVideo();
}
@@ -884,7 +885,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 =
@@ -1135,8 +1137,7 @@ static const char* const gMachineStateStr[] = {
"NONE",
"DECODING_METADATA",
"WAIT_FOR_RESOURCES",
"WAIT_FOR_RESOURCES",
"DECODING_FIRSTFRAME",
"WAIT_FOR_CDM",
"DORMANT",
"DECODING",
"SEEKING",
@@ -1262,6 +1263,7 @@ void MediaDecoderStateMachine::SetDormant(bool aDormant)
} else if ((aDormant != true) && (mState == DECODER_STATE_DORMANT)) {
mDecodingFrozenAtStateDecoding = true;
ScheduleStateMachine();
mDecodingFirstFrame = true;
SetState(DECODER_STATE_DECODING_NONE);
mDecoder->GetReentrantMonitor().NotifyAll();
}
@@ -1307,11 +1309,32 @@ void MediaDecoderStateMachine::StartDecoding()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mState == DECODER_STATE_DECODING) {
if (mState == DECODER_STATE_DECODING && !mDecodingFirstFrame) {
return;
}
SetState(DECODER_STATE_DECODING);
if (mDecodingFirstFrame &&
(IsRealTime() || mSentFirstFrameLoadedEvent)) {
if (IsRealTime()) {
FinishDecodeFirstFrame();
} else {
// 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 will be launched upon completion of the seek when
// we have data ready to play.
MOZ_ASSERT(mQueuedSeek.Exists() && mSentFirstFrameLoadedEvent,
"Return from dormant must have queued seek");
}
if (mQueuedSeek.Exists()) {
mPendingSeek.Steal(mQueuedSeek);
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
return;
}
}
mDecodeStartTime = TimeStamp::Now();
CheckIfDecodeComplete();
@@ -1339,8 +1362,7 @@ void MediaDecoderStateMachine::NotifyWaitingForResourcesStatusChanged()
ScheduleStateMachine();
} else if (mState == DECODER_STATE_WAIT_FOR_CDM &&
!mReader->IsWaitingOnCDMResource()) {
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
EnqueueDecodeFirstFrameTask();
StartDecoding();
}
}
@@ -1440,7 +1462,8 @@ MediaDecoderStateMachine::Seek(SeekTarget aTarget)
NS_ASSERTION(mState > DECODER_STATE_DECODING_METADATA,
"We should have got duration already");
if (mState < DECODER_STATE_DECODING) {
if (mState < DECODER_STATE_DECODING ||
(IsDecodingFirstFrame() && !mReader->ForceZeroStartTime())) {
DECODER_LOG("Seek() Not Enough Data to continue at this stage, queuing seek");
mQueuedSeek.RejectIfExists(__func__);
mQueuedSeek.mTarget = aTarget;
@@ -1470,19 +1493,6 @@ void MediaDecoderStateMachine::StopAudioThread()
mAudioSinkPromise.DisconnectIfExists();
}
nsresult
MediaDecoderStateMachine::EnqueueDecodeFirstFrameTask()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
nsCOMPtr<nsIRunnable> task(
NS_NewRunnableMethod(this, &MediaDecoderStateMachine::CallDecodeFirstFrame));
OwnerThread()->Dispatch(task.forget());
return NS_OK;
}
void
MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
{
@@ -1490,7 +1500,6 @@ MediaDecoderStateMachine::DispatchDecodeTasksIfNeeded()
AssertCurrentThreadInMonitor();
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
return;
@@ -1639,7 +1648,6 @@ MediaDecoderStateMachine::EnsureAudioDecodeTaskQueued()
IsAudioDecoding(), AudioRequestStatus());
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
return NS_OK;
@@ -1711,7 +1719,6 @@ MediaDecoderStateMachine::EnsureVideoDecodeTaskQueued()
IsVideoDecoding(), VideoRequestStatus());
if (mState != DECODER_STATE_DECODING &&
mState != DECODER_STATE_DECODING_FIRSTFRAME &&
mState != DECODER_STATE_BUFFERING &&
mState != DECODER_STATE_SEEKING) {
return NS_OK;
@@ -1848,7 +1855,7 @@ bool MediaDecoderStateMachine::HasLowUndecodedData(int64_t aUsecs)
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
NS_ASSERTION(mState > DECODER_STATE_DECODING_FIRSTFRAME,
NS_ASSERTION(mState >= DECODER_STATE_DECODING && !IsDecodingFirstFrame(),
"Must have loaded first frame for mBuffered to be valid");
// If we don't have a duration, mBuffered is probably not going to have
@@ -1979,8 +1986,8 @@ MediaDecoderStateMachine::OnMetadataRead(MetadataHolder* aMetadata)
return;
}
SetState(DECODER_STATE_DECODING_FIRSTFRAME);
EnqueueDecodeFirstFrameTask();
StartDecoding();
ScheduleStateMachine();
}
@@ -2031,60 +2038,19 @@ MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent()
mSentFirstFrameLoadedEvent = true;
}
bool
MediaDecoderStateMachine::IsDecodingFirstFrame()
{
return mState == DECODER_STATE_DECODING && mDecodingFirstFrame;
}
void
MediaDecoderStateMachine::CallDecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
ReentrantMonitorAutoEnter mon(mDecoder->GetReentrantMonitor());
if (mState != DECODER_STATE_DECODING_FIRSTFRAME) {
return;
}
if (NS_FAILED(DecodeFirstFrame())) {
DECODER_WARN("Decode failed to start, shutting down decoder");
DecodeError();
}
}
nsresult
MediaDecoderStateMachine::DecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
MOZ_ASSERT(mState == DECODER_STATE_DECODING_FIRSTFRAME);
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;
}
nsresult
MediaDecoderStateMachine::FinishDecodeFirstFrame()
{
MOZ_ASSERT(OnTaskQueue());
AssertCurrentThreadInMonitor();
DECODER_LOG("FinishDecodeFirstFrame");
if (IsShutdown()) {
return NS_ERROR_FAILURE;
}
if (!IsRealTime() && !mSentFirstFrameLoadedEvent) {
RenderVideoFrames(1);
}
@@ -2098,7 +2064,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
"transportSeekable=%d, mediaSeekable=%d",
Duration().ToMicroseconds(), mDecoder->IsTransportSeekable(), mDecoder->IsMediaSeekable());
if (HasAudio() && !HasVideo()) {
if (HasAudio() && !HasVideo() && !mSentFirstFrameLoadedEvent) {
// 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
// order to reduce memory usage.
@@ -2119,16 +2085,7 @@ MediaDecoderStateMachine::FinishDecodeFirstFrame()
}
EnqueueFirstFrameLoadedEvent();
if (mQueuedSeek.Exists()) {
mPendingSeek.Steal(mQueuedSeek);
SetState(DECODER_STATE_SEEKING);
ScheduleStateMachine();
} else if (mState == DECODER_STATE_DECODING_FIRSTFRAME) {
// StartDecoding() will also check if decode is completed.
StartDecoding();
}
return NS_OK;
mDecodingFirstFrame = false;
}
void
@@ -2142,11 +2099,11 @@ MediaDecoderStateMachine::SeekCompleted()
int64_t newCurrentTime = seekTime;
// Setup timestamp state.
nsRefPtr<VideoData> video = VideoQueue().PeekFront();
nsRefPtr<MediaData> video = VideoQueue().PeekFront();
if (seekTime == Duration().ToMicroseconds()) {
newCurrentTime = seekTime;
} else if (HasAudio()) {
AudioData* audio = AudioQueue().PeekFront();
MediaData* audio = AudioQueue().PeekFront();
// Though we adjust the newCurrentTime in audio-based, and supplemented
// by video. For better UX, should NOT bind the slide position to
// the first audio data timestamp directly.
@@ -2161,6 +2118,12 @@ MediaDecoderStateMachine::SeekCompleted()
}
mPlayDuration = newCurrentTime;
if (mDecodingFirstFrame) {
// We were resuming from dormant, or initiated a seek early.
// We can fire loadeddata now.
FinishDecodeFirstFrame();
}
// Change state to DECODING or COMPLETED now. SeekingStopped will
// call MediaDecoderStateMachine::Seek to reset our state to SEEKING
// if we need to seek again.
@@ -2324,12 +2287,12 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
return NS_OK;
}
case DECODER_STATE_DECODING_FIRSTFRAME: {
// DECODER_STATE_DECODING_FIRSTFRAME will be started by OnMetadataRead.
return NS_OK;
}
case DECODER_STATE_DECODING: {
if (IsDecodingFirstFrame()) {
// We haven't completed decoding our first frames, we can't start
// playback yet.
return NS_OK;
}
if (mPlayState != MediaDecoder::PLAY_STATE_PLAYING && IsPlaying())
{
// We're playing, but the element/decoder is in paused state. Stop
@@ -2362,7 +2325,7 @@ nsresult MediaDecoderStateMachine::RunStateMachine()
elapsed < TimeDuration::FromSeconds(mBufferingWait * mPlaybackRate) &&
(mQuickBuffering ? HasLowDecodedData(mQuickBufferingLowDataThresholdUsecs)
: HasLowUndecodedData(mBufferingWait * USECS_PER_S)) &&
mDecoder->IsExpectingMoreData())
mResource->IsExpectingMoreData())
{
DECODER_LOG("Buffering: wait %ds, timeout in %.3lfs %s",
mBufferingWait, mBufferingWait - elapsed.ToSeconds(),
@@ -2538,7 +2501,7 @@ void MediaDecoderStateMachine::RenderVideoFrames(int32_t aMaxFrames,
AssertCurrentThreadInMonitor();
VideoFrameContainer* container = mDecoder->GetVideoFrameContainer();
nsAutoTArray<nsRefPtr<VideoData>,16> frames;
nsAutoTArray<nsRefPtr<MediaData>,16> frames;
VideoQueue().GetFirstElements(aMaxFrames, &frames);
if (frames.IsEmpty() || !container) {
return;
@@ -2547,7 +2510,7 @@ void MediaDecoderStateMachine::RenderVideoFrames(int32_t aMaxFrames,
nsAutoTArray<ImageContainer::NonOwningImage,16> images;
TimeStamp lastFrameTime;
for (uint32_t i = 0; i < frames.Length(); ++i) {
VideoData* frame = frames[i];
VideoData* frame = frames[i]->As<VideoData>();
frame->mSentToCompositor = true;
int64_t frameTime = frame->mTime;
@@ -2585,7 +2548,7 @@ void MediaDecoderStateMachine::RenderVideoFrames(int32_t aMaxFrames,
}
container->SetCurrentFrames(frames[0]->mDisplay, images);
container->SetCurrentFrames(frames[0]->As<VideoData>()->mDisplay, images);
}
void MediaDecoderStateMachine::ResyncAudioClock()
@@ -2689,21 +2652,21 @@ void MediaDecoderStateMachine::UpdateRenderedVideoFrames()
NS_ASSERTION(clockTime >= 0, "Should have positive clock time.");
int64_t remainingTime = AUDIO_DURATION_USECS;
if (VideoQueue().GetSize() > 0) {
nsRefPtr<VideoData> currentFrame = VideoQueue().PopFront();
nsRefPtr<MediaData> currentFrame = VideoQueue().PopFront();
int32_t framesRemoved = 0;
while (VideoQueue().GetSize() > 0) {
VideoData* nextFrame = VideoQueue().PeekFront();
MediaData* nextFrame = VideoQueue().PeekFront();
if (!IsRealTime() && nextFrame->mTime > clockTime) {
remainingTime = nextFrame->mTime - clockTime;
break;
}
++framesRemoved;
if (!currentFrame->mSentToCompositor) {
if (!currentFrame->As<VideoData>()->mSentToCompositor) {
mDecoder->NotifyDecodedFrames(0, 0, 1);
VERBOSE_LOG("discarding video frame mTime=%lld clock_time=%lld",
currentFrame->mTime, clockTime);
}
CheckTurningOffHardwareDecoder(currentFrame);
CheckTurningOffHardwareDecoder(currentFrame->As<VideoData>());
currentFrame = VideoQueue().PopFront();
}
@@ -2721,7 +2684,7 @@ void MediaDecoderStateMachine::UpdateRenderedVideoFrames()
// If we don't, switch to buffering mode.
if (mState == DECODER_STATE_DECODING &&
mPlayState == MediaDecoder::PLAY_STATE_PLAYING &&
mDecoder->IsExpectingMoreData()) {
mResource->IsExpectingMoreData()) {
bool shouldBuffer;
if (mReader->UseBufferingHeuristics()) {
shouldBuffer = HasLowDecodedData(remainingTime + EXHAUSTED_DATA_MARGIN_USECS) &&
@@ -2878,7 +2841,7 @@ void MediaDecoderStateMachine::UpdateNextFrameStatus()
MediaDecoderOwner::NextFrameStatus status;
const char* statusString;
if (mState <= DECODER_STATE_DECODING_FIRSTFRAME) {
if (mState <= DECODER_STATE_WAIT_FOR_CDM || IsDecodingFirstFrame()) {
status = MediaDecoderOwner::NEXT_FRAME_UNAVAILABLE;
statusString = "NEXT_FRAME_UNAVAILABLE";
} else if (IsBuffering()) {