Bug 1397307 - P5. Avoid creating two decoders on first sample. r?gerald draft
authorJean-Yves Avenard <jyavenard@mozilla.com>
Tue, 12 Sep 2017 21:02:24 +0200
changeset 665095 992e96056ca923da12df20b765e44717cf894a1f
parent 665094 36a9070518e94a9aca2c9c58e5a7c045fb4a1742
child 665096 9759e2aa9ca20240eeb0a8448a067a1f1b4c1215
push id79919
push userbmo:jyavenard@mozilla.com
push dateThu, 14 Sep 2017 22:16:27 +0000
reviewersgerald
bugs1397307
milestone57.0a1
Bug 1397307 - P5. Avoid creating two decoders on first sample. r?gerald Don't unnecessarily, create a decoder, flush, shutdown and create a new one on the first sample. MozReview-Commit-ID: 8utEX5JEmq8
dom/media/MediaFormatReader.cpp
--- a/dom/media/MediaFormatReader.cpp
+++ b/dom/media/MediaFormatReader.cpp
@@ -2043,75 +2043,76 @@ MediaFormatReader::HandleDemuxedSamples(
     LOGV("Decoder operation in progress, let it complete.");
     return;
   }
 
   if (decoder.mQueuedSamples.IsEmpty()) {
     return;
   }
 
-  if (!decoder.mDecoder) {
-    mDecoderFactory->CreateDecoder(aTrack);
-    return;
-  }
-
-  LOGV("Giving %s input to decoder", TrackTypeToStr(aTrack));
-
   // Decode all our demuxed frames.
   while (decoder.mQueuedSamples.Length()) {
     RefPtr<MediaRawData> sample = decoder.mQueuedSamples[0];
-    RefPtr<TrackInfoSharedPtr> info = sample->mTrackInfo;
+    const RefPtr<TrackInfoSharedPtr> info = sample->mTrackInfo;
 
     if (info && decoder.mLastStreamSourceID != info->GetID()) {
-      bool recyclable = MediaPrefs::MediaDecoderCheckRecycling() &&
-                        decoder.mDecoder->SupportDecoderRecycling();
-      if (!recyclable && decoder.mTimeThreshold.isNothing() &&
-          (decoder.mNextStreamSourceID.isNothing() ||
-           decoder.mNextStreamSourceID.ref() != info->GetID())) {
-        LOG("%s stream id has changed from:%d to:%d, draining decoder.",
-            TrackTypeToStr(aTrack),
-            decoder.mLastStreamSourceID,
-            info->GetID());
-        decoder.RequestDrain();
-        decoder.mNextStreamSourceID = Some(info->GetID());
-        ScheduleUpdate(aTrack);
-        return;
+      nsTArray<RefPtr<MediaRawData>> samples;
+      if (decoder.mDecoder) {
+        bool recyclable = MediaPrefs::MediaDecoderCheckRecycling() &&
+                          decoder.mDecoder->SupportDecoderRecycling();
+        if (!recyclable && decoder.mTimeThreshold.isNothing() &&
+            (decoder.mNextStreamSourceID.isNothing() ||
+             decoder.mNextStreamSourceID.ref() != info->GetID())) {
+          LOG("%s stream id has changed from:%d to:%d, draining decoder.",
+              TrackTypeToStr(aTrack),
+              decoder.mLastStreamSourceID,
+              info->GetID());
+          decoder.RequestDrain();
+          decoder.mNextStreamSourceID = Some(info->GetID());
+          ScheduleUpdate(aTrack);
+          return;
+        }
+
+        // If flushing is required, it will clear our array of queued samples.
+        // So we may need to make a copy.
+        samples = decoder.mQueuedSamples;
+        if (!recyclable) {
+          LOG("Decoder does not support recycling, recreate decoder.");
+          ShutdownDecoder(aTrack);
+        } else if (decoder.HasWaitingPromise()) {
+          decoder.Flush();
+        }
       }
 
       LOG("%s stream id has changed from:%d to:%d.",
-          TrackTypeToStr(aTrack), decoder.mLastStreamSourceID,
+          TrackTypeToStr(aTrack),
+          decoder.mLastStreamSourceID,
           info->GetID());
-      decoder.mLastStreamSourceID = info->GetID();
+
       decoder.mNextStreamSourceID.reset();
-
-      if (!recyclable) {
-        LOG("Decoder does not support recycling, recreate decoder.");
-        // If flushing is required, it will clear our array of queued samples.
-        // So make a copy now.
-        nsTArray<RefPtr<MediaRawData>> samples{ Move(decoder.mQueuedSamples) };
-        ShutdownDecoder(aTrack);
-        if (sample->mKeyframe) {
-          decoder.mQueuedSamples.AppendElements(Move(samples));
-        }
-      } else if (decoder.HasWaitingPromise()) {
-        decoder.Flush();
-      }
-
+      decoder.mLastStreamSourceID = info->GetID();
       decoder.mInfo = info;
 
       if (sample->mKeyframe) {
-        ScheduleUpdate(aTrack);
+        if (samples.Length()) {
+          decoder.mQueuedSamples = Move(samples);
+        }
       } else {
         auto time = TimeInterval(sample->mTime, sample->GetEndTime());
         InternalSeekTarget seekTarget =
           decoder.mTimeThreshold.refOr(InternalSeekTarget(time, false));
         LOG("Stream change occurred on a non-keyframe. Seeking to:%" PRId64,
             sample->mTime.ToMicroseconds());
         InternalSeek(aTrack, seekTarget);
+        return;
       }
+    }
+
+    if (!decoder.mDecoder) {
+      mDecoderFactory->CreateDecoder(aTrack);
       return;
     }
 
     LOGV("Input:%" PRId64 " (dts:%" PRId64 " kf:%d)",
          sample->mTime.ToMicroseconds(), sample->mTimecode.ToMicroseconds(),
          sample->mKeyframe);
     decoder.mNumSamplesInput++;
     decoder.mSizeOfQueue++;