Bug 1199879: [MSE] Use latest demux end time to detect discontinuities. r=gerald a=sledru
authorJean-Yves Avenard <jyavenard@mozilla.com>
Sat, 29 Aug 2015 17:34:08 +1000
changeset 289202 7437f28133fc6679c1de658c50d3a13b86b852b7
parent 289201 07fc25608e50adaba4422e6a2c51cd1ca1220ac5
child 289203 fdeacd3d68ad9a1929ffd41856f26821909f6a37
push id5067
push userraliiev@mozilla.com
push dateMon, 21 Sep 2015 14:04:52 +0000
treeherdermozilla-beta@14221ffe5b2f [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersgerald, sledru
bugs1199879
milestone42.0a2
Bug 1199879: [MSE] Use latest demux end time to detect discontinuities. r=gerald a=sledru The ContainerParser doesn't always return an accurate end time.
dom/media/mediasource/TrackBuffersManager.cpp
dom/media/mediasource/TrackBuffersManager.h
--- a/dom/media/mediasource/TrackBuffersManager.cpp
+++ b/dom/media/mediasource/TrackBuffersManager.cpp
@@ -707,19 +707,16 @@ TrackBuffersManager::SegmentParserLoop()
         if (newData || !mParser->MediaSegmentRange().IsNull()) {
           if (mPendingInputBuffer) {
             // We now have a complete media segment header. We can resume parsing
             // the data.
             AppendDataToCurrentInputBuffer(mPendingInputBuffer);
             mPendingInputBuffer = nullptr;
           }
           mNewMediaSegmentStarted = false;
-          if (newData) {
-            mLastParsedEndTime = Some(TimeUnit::FromMicroseconds(end));
-          }
         } else {
           // We don't have any data to demux yet, stash aside the data.
           // This also handles the case:
           // 2. If the input buffer does not contain a complete media segment header yet, then jump to the need more data step below.
           if (!mPendingInputBuffer) {
             mPendingInputBuffer = mInputBuffer;
           } else {
             mPendingInputBuffer->AppendElements(*mInputBuffer);
@@ -867,18 +864,16 @@ TrackBuffersManager::OnDemuxerResetDone(
   if (mPendingInputBuffer) {
     // We had a partial media segment header stashed aside.
     // Reparse its content so we can continue parsing the current input buffer.
     int64_t start, end;
     mParser->ParseStartAndEndTimestamps(mPendingInputBuffer, start, end);
     mProcessedInput += mPendingInputBuffer->Length();
   }
 
-  mLastParsedEndTime.reset();
-
   SegmentParserLoop();
 }
 
 void
 TrackBuffersManager::AppendDataToCurrentInputBuffer(MediaByteBuffer* aData)
 {
   MOZ_ASSERT(mCurrentInputBuffer);
   int64_t offset = mCurrentInputBuffer->GetLength();
@@ -1313,16 +1308,19 @@ TrackBuffersManager::CompleteCodedFrameP
   }
 
   // 5. If the input buffer does not contain a complete media segment, then jump to the need more data step below.
   if (mParser->MediaSegmentRange().IsNull()) {
     ResolveProcessing(true, __func__);
     return;
   }
 
+  mLastParsedEndTime = Some(std::max(mAudioTracks.mLastParsedEndTime,
+                                     mVideoTracks.mLastParsedEndTime));
+
   // 6. Remove the media segment bytes from the beginning of the input buffer.
   // Clear our demuxer from any already processed data.
   // As we have handled a complete media segment, it is safe to evict all data
   // from the resource.
   mCurrentInputBuffer->EvictAll();
   mInputDemuxer->NotifyDataRemoved();
   RecreateParser(true);
 
@@ -1392,26 +1390,36 @@ TrackBuffersManager::ProcessFrames(Track
   TrackBuffer samples; // array that will contain the frames to be added
                        // to our track buffer.
 
   // We assume that no frames are contiguous within a media segment and as such
   // don't need to check for discontinuity except for the first frame and should
   // a frame be ignored due to the target window.
   bool needDiscontinuityCheck = true;
 
+  if (aSamples.Length()) {
+    aTrackData.mLastParsedEndTime = TimeUnit();
+  }
+
   for (auto& sample : aSamples) {
     SAMPLE_DEBUG("Processing %s frame(pts:%lld end:%lld, dts:%lld, duration:%lld, "
                "kf:%d)",
                aTrackData.mInfo->mMimeType.get(),
                sample->mTime,
                sample->GetEndTime(),
                sample->mTimecode,
                sample->mDuration,
                sample->mKeyframe);
 
+    const TimeUnit sampleEndTime =
+      TimeUnit::FromMicroseconds(sample->GetEndTime());
+    if (sampleEndTime > aTrackData.mLastParsedEndTime) {
+      aTrackData.mLastParsedEndTime = sampleEndTime;
+    }
+
     // We perform step 10 right away as we can't do anything should a keyframe
     // be needed until we have one.
 
     // 10. If the need random access point flag on track buffer equals true, then run the following steps:
     if (trackBuffer.mNeedRandomAccessPoint) {
       // 1. If the coded frame is not a random access point, then drop the coded frame and jump to the top of the loop to start processing the next coded frame.
       if (!sample->mKeyframe) {
         continue;
--- a/dom/media/mediasource/TrackBuffersManager.h
+++ b/dom/media/mediasource/TrackBuffersManager.h
@@ -235,16 +235,19 @@ private:
     // Need random access point flag variable that keeps track of whether the
     // track buffer is waiting for a random access point coded frame.
     // The variable is initially set to true to indicate that random access
     // point coded frame is needed before anything can be added to the track
     // buffer.
     bool mNeedRandomAccessPoint;
     nsRefPtr<MediaTrackDemuxer> mDemuxer;
     MozPromiseRequestHolder<MediaTrackDemuxer::SamplesPromise> mDemuxRequest;
+    // Highest end timestamp of the last media segment demuxed.
+    media::TimeUnit mLastParsedEndTime;
+
     // If set, position where the next contiguous frame will be inserted.
     // If a discontinuity is detected, it will be unset and recalculated upon
     // the next insertion.
     Maybe<size_t> mNextInsertionIndex;
     // Samples just demuxed, but not yet parsed.
     TrackBuffer mQueuedSamples;
     // We only manage a single track of each type at this time.
     nsTArray<TrackBuffer> mBuffers;