Bug 1183519: Wait until current drain completes before decoding new data. r=cpearce
authorJean-Yves Avenard <jyavenard@mozilla.com>
Wed, 15 Jul 2015 14:43:35 +1000
changeset 253135 ef1250ce23a38f97b3f75308ef9366319938b4fa
parent 253134 7287e6935c401d2372dc4b6c7bf8fec905cbeb5d
child 253136 e988de526f82dc4209655f1202de3f7dc732768a
push id29061
push userryanvm@gmail.com
push dateThu, 16 Jul 2015 18:53:45 +0000
treeherdermozilla-central@a0f4a688433d [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewerscpearce
bugs1183519
milestone42.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
Bug 1183519: Wait until current drain completes before decoding new data. r=cpearce
dom/media/MediaFormatReader.cpp
dom/media/MediaFormatReader.h
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -521,17 +521,18 @@ MediaFormatReader::ShouldSkip(bool aSkip
 nsRefPtr<MediaDecoderReader::VideoDataPromise>
 MediaFormatReader::RequestVideoData(bool aSkipToNextKeyframe,
                                     int64_t aTimeThreshold,
                                     bool aForceDecodeAhead)
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(mSeekPromise.IsEmpty(), "No sample requests allowed while seeking");
   MOZ_DIAGNOSTIC_ASSERT(!mVideo.HasPromise(), "No duplicate sample requests");
-  MOZ_DIAGNOSTIC_ASSERT(!mVideo.mSeekRequest.Exists());
+  MOZ_DIAGNOSTIC_ASSERT(!mVideo.mSeekRequest.Exists() ||
+                        mVideo.mTimeThreshold.isSome());
   MOZ_DIAGNOSTIC_ASSERT(!mSkipRequest.Exists(), "called mid-skipping");
   MOZ_DIAGNOSTIC_ASSERT(!IsSeeking(), "called mid-seek");
   LOGV("RequestVideoData(%d, %lld)", aSkipToNextKeyframe, aTimeThreshold);
 
   if (!HasVideo()) {
     LOG("called with no video track");
     return VideoDataPromise::CreateAndReject(DECODE_ERROR, __func__);
   }
@@ -618,17 +619,18 @@ MediaFormatReader::OnVideoDemuxCompleted
   ScheduleUpdate(TrackInfo::kVideoTrack);
 }
 
 nsRefPtr<MediaDecoderReader::AudioDataPromise>
 MediaFormatReader::RequestAudioData()
 {
   MOZ_ASSERT(OnTaskQueue());
   MOZ_DIAGNOSTIC_ASSERT(mSeekPromise.IsEmpty(), "No sample requests allowed while seeking");
-  MOZ_DIAGNOSTIC_ASSERT(!mAudio.mSeekRequest.Exists());
+  MOZ_DIAGNOSTIC_ASSERT(!mAudio.mSeekRequest.Exists() ||
+                        mAudio.mTimeThreshold.isSome());
   MOZ_DIAGNOSTIC_ASSERT(!mAudio.HasPromise(), "No duplicate sample requests");
   MOZ_DIAGNOSTIC_ASSERT(!IsSeeking(), "called mid-seek");
   LOGV("");
 
   if (!HasAudio()) {
     LOG("called with no audio track");
     return AudioDataPromise::CreateAndReject(DECODE_ERROR, __func__);
   }
@@ -749,16 +751,17 @@ MediaFormatReader::NeedInput(DecoderData
 {
   MOZ_ASSERT(OnTaskQueue());
   // We try to keep a few more compressed samples input than decoded samples
   // have been output, provided the state machine has requested we send it a
   // decoded sample. To account for H.264 streams which may require a longer
   // run of input than we input, decoders fire an "input exhausted" callback,
   // which overrides our "few more samples" threshold.
   return
+    !aDecoder.mDraining &&
     !aDecoder.mError &&
     (aDecoder.HasPromise() || aDecoder.mForceDecodeAhead) &&
     !aDecoder.mDemuxRequest.Exists() &&
     aDecoder.mOutput.IsEmpty() &&
     (aDecoder.mInputExhausted || !aDecoder.mQueuedSamples.IsEmpty() ||
      aDecoder.mTimeThreshold.isSome() ||
      aDecoder.mForceDecodeAhead ||
      aDecoder.mNumSamplesInput - aDecoder.mNumSamplesOutput < aDecoder.mDecodeAhead);
@@ -959,22 +962,23 @@ MediaFormatReader::DecodeDemuxedSamples(
 }
 
 void
 MediaFormatReader::DrainDecoder(TrackType aTrack)
 {
   MOZ_ASSERT(OnTaskQueue());
 
   auto& decoder = GetDecoderData(aTrack);
-  if (!decoder.mNeedDraining) {
+  if (!decoder.mNeedDraining || decoder.mDraining) {
     return;
   }
   decoder.mOutputRequested = true;
   decoder.mDecoder->Drain();
   decoder.mNeedDraining = false;
+  decoder.mDraining = true;
   LOG("Requesting %s decoder to drain", TrackTypeToStr(aTrack));
 }
 
 void
 MediaFormatReader::Update(TrackType aTrack)
 {
   MOZ_ASSERT(OnTaskQueue());
 
@@ -1019,16 +1023,17 @@ MediaFormatReader::Update(TrackType aTra
       } else {
         LOGV("Internal Seeking: Dropping frame time:%f wanted:%f (kf:%d)",
              media::TimeUnit::FromMicroseconds(output->mTime).ToSeconds(),
              decoder.mTimeThreshold.ref().ToSeconds(),
              output->mKeyframe);
       }
     } else if (decoder.mDrainComplete) {
       decoder.mDrainComplete = false;
+      decoder.mDraining = false;
       if (decoder.mError) {
         LOG("Decoding Error");
         decoder.RejectPromise(DECODE_ERROR, __func__);
         return;
       } else if (decoder.mDemuxEOS) {
         decoder.RejectPromise(END_OF_STREAM, __func__);
       } else if (decoder.mWaitingForData) {
         LOG("Waiting For Data");
--- a/dom/media/MediaFormatReader.h
+++ b/dom/media/MediaFormatReader.h
@@ -192,16 +192,17 @@ private:
       , mDemuxEOS(false)
       , mWaitingForData(false)
       , mReceivedNewData(false)
       , mDiscontinuity(true)
       , mOutputRequested(false)
       , mInputExhausted(false)
       , mError(false)
       , mNeedDraining(false)
+      , mDraining(false)
       , mDrainComplete(false)
       , mNumSamplesInput(0)
       , mNumSamplesOutput(0)
       , mSizeOfQueue(0)
       , mLastStreamSourceID(UINT32_MAX)
     {}
 
     MediaFormatReader* mOwner;
@@ -238,16 +239,17 @@ private:
       return !mWaitingPromise.IsEmpty();
     }
 
     // MediaDataDecoder handler's variables.
     bool mOutputRequested;
     bool mInputExhausted;
     bool mError;
     bool mNeedDraining;
+    bool mDraining;
     bool mDrainComplete;
     // If set, all decoded samples prior mTimeThreshold will be dropped.
     // Used for internal seeking when a change of stream is detected.
     Maybe<media::TimeUnit> mTimeThreshold;
 
     // Decoded samples returned my mDecoder awaiting being returned to
     // state machine upon request.
     nsTArray<nsRefPtr<MediaData>> mOutput;
@@ -274,16 +276,17 @@ private:
       mDemuxEOS = false;
       mWaitingForData = false;
       mReceivedNewData = false;
       mDiscontinuity = true;
       mQueuedSamples.Clear();
       mOutputRequested = false;
       mInputExhausted = false;
       mNeedDraining = false;
+      mDraining = false;
       mDrainComplete = false;
       mTimeThreshold.reset();
       mOutput.Clear();
       mNumSamplesInput = 0;
       mNumSamplesOutput = 0;
       mSizeOfQueue = 0;
       mNextStreamSourceID.reset();
     }