Bug 1251460 - MDSM now waits on a promise to enqueue first frame loaded. r=jya

MediaDecoderStateMachine's EnqueueFIrstFrameLoadedEvent would previously call
into MediaDecoderReader to update MDR's buffered ranges and enqueue the frame
loaded event. This commit aims to instead have the buffered update take place,
and only afterwards enqueue the event. This should remove the possibility that
the event will be fired and handled before the update of the buffered ranges has
taken place.

MozReview-Commit-ID: GP8w2nF4xmj

--HG--
extra : transplant_source : %A0m%13%95%E3Gs%ACMd%1F%F4%25%B9qE%28J%21R
This commit is contained in:
Bryce Van Dyk 2016-03-09 15:32:49 +13:00
parent ce47da7e2a
commit 2be9a949c6
5 changed files with 51 additions and 5 deletions

View File

@ -88,6 +88,8 @@ public:
using WaitForDataPromise =
MozPromise<MediaData::Type, WaitForDataRejectValue, IsExclusive>;
using BufferedUpdatePromise = MozPromise<bool, bool, IsExclusive>;
NS_INLINE_DECL_THREADSAFE_REFCOUNTING(MediaDecoderReader)
// The caller must ensure that Shutdown() is called before aDecoder is
@ -232,6 +234,16 @@ public:
UpdateBuffered();
}
// Update the buffered ranges and upon doing so return a promise
// to indicate success. Overrides may need to do extra work to ensure
// buffered is up to date.
virtual RefPtr<BufferedUpdatePromise> UpdateBufferedWithPromise()
{
MOZ_ASSERT(OnTaskQueue());
UpdateBuffered();
return BufferedUpdatePromise::CreateAndResolve(true, __func__);
}
virtual MediaQueue<AudioData>& AudioQueue() { return mAudioQueue; }
virtual MediaQueue<VideoData>& VideoQueue() { return mVideoQueue; }

View File

@ -1325,6 +1325,8 @@ MediaDecoderStateMachine::Shutdown()
ScheduleStateMachine();
SetState(DECODER_STATE_SHUTDOWN);
mBufferedUpdateRequest.DisconnectIfExists();
mQueuedSeek.RejectIfExists(__func__);
mPendingSeek.RejectIfExists(__func__);
mCurrentSeek.RejectIfExists(__func__);
@ -2020,12 +2022,25 @@ void
MediaDecoderStateMachine::EnqueueFirstFrameLoadedEvent()
{
MOZ_ASSERT(OnTaskQueue());
MediaDecoderEventVisibility visibility =
mSentFirstFrameLoadedEvent ? MediaDecoderEventVisibility::Suppressed
: MediaDecoderEventVisibility::Observable;
mFirstFrameLoadedEvent.Notify(nsAutoPtr<MediaInfo>(new MediaInfo(mInfo)),
Move(visibility));
// Track value of mSentFirstFrameLoadedEvent from before updating it
bool firstFrameBeenLoaded = mSentFirstFrameLoadedEvent;
mSentFirstFrameLoadedEvent = true;
RefPtr<MediaDecoderStateMachine> self = this;
mBufferedUpdateRequest.Begin(InvokeAsync(DecodeTaskQueue(), mReader.get(), __func__,
&MediaDecoderReader::UpdateBufferedWithPromise)
->Then(OwnerThread(),
__func__,
// Resolve
[self, firstFrameBeenLoaded]() {
self->mBufferedUpdateRequest.Complete();
MediaDecoderEventVisibility visibility =
firstFrameBeenLoaded ? MediaDecoderEventVisibility::Suppressed
: MediaDecoderEventVisibility::Observable;
self->mFirstFrameLoadedEvent.Notify(nsAutoPtr<MediaInfo>(new MediaInfo(self->mInfo)),
Move(visibility));
},
// Reject
[]() { MOZ_CRASH("Should not reach"); }));
}
bool

View File

@ -1136,6 +1136,9 @@ private:
mozilla::RollingMean<uint32_t, uint32_t> mCorruptFrames;
// Track our request to update the buffered ranges
MozPromiseRequestHolder<MediaDecoderReader::BufferedUpdatePromise> mBufferedUpdateRequest;
// True if we need to call FinishDecodeFirstFrame() upon frame decoding
// successeeding.
bool mDecodingFirstFrame;

View File

@ -1619,6 +1619,20 @@ MediaFormatReader::GetBuffered()
return intervals.Shift(media::TimeUnit::FromMicroseconds(-startTime));
}
// For the MediaFormatReader override we need to force an update to the
// buffered ranges, so we call NotifyDataArrive
RefPtr<MediaDecoderReader::BufferedUpdatePromise>
MediaFormatReader::UpdateBufferedWithPromise() {
MOZ_ASSERT(OnTaskQueue());
// Call NotifyDataArrive to force a recalculation of the buffered
// ranges. UpdateBuffered alone will not force a recalculation, so we
// use NotifyDataArrived which sets flags to force this recalculation.
// See MediaFormatReader::UpdateReceivedNewData for an example of where
// the new data flag is used.
NotifyDataArrived();
return BufferedUpdatePromise::CreateAndResolve(true, __func__);
}
void MediaFormatReader::ReleaseMediaResources()
{
// Before freeing a video codec, all video buffers needed to be released

View File

@ -55,6 +55,8 @@ protected:
public:
media::TimeIntervals GetBuffered() override;
RefPtr<BufferedUpdatePromise> UpdateBufferedWithPromise() override;
bool ForceZeroStartTime() const override;
// For Media Resource Management