Bug 1323631 - update original frame timestamp or duration rather than creating shallow copy. r?jwwang draft
authorJohn Lin <jolin@mozilla.com>
Thu, 15 Dec 2016 17:57:21 +0800
changeset 449864 d63fc94aa17ec38811fccd1c19958b2ea24319fd
parent 449801 7652a58efa46f1c57c94bba26efc5d53b6184e83
child 449865 75a301b01f1ff7670d66c42679c75f77819dd978
push id38707
push userbmo:jolin@mozilla.com
push dateThu, 15 Dec 2016 10:35:22 +0000
reviewersjwwang
bugs1323631
milestone53.0a1
Bug 1323631 - update original frame timestamp or duration rather than creating shallow copy. r?jwwang MozReview-Commit-ID: 4oSheJwFNOE
dom/media/MediaData.cpp
dom/media/MediaData.h
dom/media/MediaDecoderStateMachine.cpp
dom/media/android/AndroidMediaReader.cpp
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -172,65 +172,34 @@ VideoData::SizeOfIncludingThis(MallocSiz
     const mozilla::layers::PlanarYCbCrImage* img =
         static_cast<const mozilla::layers::PlanarYCbCrImage*>(mImage.get());
     size += img->SizeOfIncludingThis(aMallocSizeOf);
   }
 
   return size;
 }
 
-/* static */
-already_AddRefed<VideoData>
-VideoData::ShallowCopyUpdateDuration(const VideoData* aOther,
-                                     int64_t aDuration)
+void
+VideoData::UpdateDuration(int64_t aDuration)
 {
-  RefPtr<VideoData> v = new VideoData(aOther->mOffset,
-                                        aOther->mTime,
-                                        aDuration,
-                                        aOther->mKeyframe,
-                                        aOther->mTimecode,
-                                        aOther->mDisplay,
-                                        aOther->mFrameID);
-  v->mImage = aOther->mImage;
-  return v.forget();
+  MOZ_ASSERT(aDuration >= 0);
+
+  mDuration = aDuration;
 }
 
-/* static */
-already_AddRefed<VideoData>
-VideoData::ShallowCopyUpdateTimestamp(const VideoData* aOther,
-                                      int64_t aTimestamp)
+void
+VideoData::UpdateTimestamp(int64_t aTimestamp)
 {
-  NS_ENSURE_TRUE(aOther, nullptr);
-  RefPtr<VideoData> v = new VideoData(aOther->mOffset,
-                                        aTimestamp,
-                                        aOther->GetEndTime() - aTimestamp,
-                                        aOther->mKeyframe,
-                                        aOther->mTimecode,
-                                        aOther->mDisplay,
-                                        aOther->mFrameID);
-  v->mImage = aOther->mImage;
-  return v.forget();
-}
+  MOZ_ASSERT(aTimestamp >= 0);
 
-/* static */
-already_AddRefed<VideoData>
-VideoData::ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther,
-                                                 int64_t aTimestamp,
-                                                 int64_t aDuration)
-{
-  NS_ENSURE_TRUE(aOther, nullptr);
-  RefPtr<VideoData> v = new VideoData(aOther->mOffset,
-                                        aTimestamp,
-                                        aDuration,
-                                        aOther->mKeyframe,
-                                        aOther->mTimecode,
-                                        aOther->mDisplay,
-                                        aOther->mFrameID);
-  v->mImage = aOther->mImage;
-  return v.forget();
+  int64_t updatedDuration = GetEndTime() - aTimestamp;
+  MOZ_ASSERT(updatedDuration >= 0);
+
+  mTime = aTimestamp;
+  mDuration = updatedDuration;
 }
 
 /* static */
 bool VideoData::SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
                                     const VideoInfo& aInfo,
                                     const YCbCrBuffer &aBuffer,
                                     const IntRect& aPicture,
                                     bool aCopyData)
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -488,39 +488,16 @@ public:
                                                      int64_t aOffset,
                                                      int64_t aTime,
                                                      int64_t aDuration,
                                                      const RefPtr<Image>& aImage,
                                                      bool aKeyframe,
                                                      int64_t aTimecode,
                                                      const IntRect& aPicture);
 
-  // Creates a new VideoData identical to aOther, but with a different
-  // specified duration. All data from aOther is copied into the new
-  // VideoData. The new VideoData's mImage field holds a reference to
-  // aOther's mImage, i.e. the Image is not copied. This function is useful
-  // in reader backends that can't determine the duration of a VideoData
-  // until the next frame is decoded, i.e. it's a way to change the const
-  // duration field on a VideoData.
-  static already_AddRefed<VideoData> ShallowCopyUpdateDuration(const VideoData* aOther,
-                                                               int64_t aDuration);
-
-  // Creates a new VideoData identical to aOther, but with a different
-  // specified timestamp. All data from aOther is copied into the new
-  // VideoData, as ShallowCopyUpdateDuration() does.
-  static already_AddRefed<VideoData> ShallowCopyUpdateTimestamp(const VideoData* aOther,
-                                                                int64_t aTimestamp);
-
-  // Creates a new VideoData identical to aOther, but with a different
-  // specified timestamp and duration. All data from aOther is copied
-  // into the new VideoData, as ShallowCopyUpdateDuration() does.
-  static already_AddRefed<VideoData>
-  ShallowCopyUpdateTimestampAndDuration(const VideoData* aOther, int64_t aTimestamp,
-                                        int64_t aDuration);
-
   // Initialize PlanarYCbCrImage. Only When aCopyData is true,
   // video data is copied to PlanarYCbCrImage.
   static bool SetVideoDataToImage(PlanarYCbCrImage* aVideoImage,
                                   const VideoInfo& aInfo,
                                   const YCbCrBuffer &aBuffer,
                                   const IntRect& aPicture,
                                   bool aCopyData);
 
@@ -543,16 +520,19 @@ public:
             int64_t aTimecode,
             IntSize aDisplay,
             uint32_t aFrameID);
 
   void SetListener(UniquePtr<Listener> aListener);
   void MarkSentToCompositor();
   bool IsSentToCompositor() { return mSentToCompositor; }
 
+  void UpdateDuration(int64_t aDuration);
+  void UpdateTimestamp(int64_t aTimestamp);
+
 protected:
   ~VideoData();
 
   bool mSentToCompositor;
   UniquePtr<Listener> mListener;
 };
 
 class CryptoTrack
--- a/dom/media/MediaDecoderStateMachine.cpp
+++ b/dom/media/MediaDecoderStateMachine.cpp
@@ -1237,20 +1237,18 @@ private:
     // to display this frame after the seek, so discard it.
     if (target >= video->GetEndTime()) {
       SLOG("DropVideoUpToSeekTarget() pop video frame [%lld, %lld] target=%lld",
            video->mTime, video->GetEndTime(), target);
       mFirstVideoFrameAfterSeek = video;
     } else {
       if (target >= video->mTime && video->GetEndTime() >= target) {
         // The seek target lies inside this frame's time slice. Adjust the frame's
-        // start time to match the seek target. We do this by replacing the
-        // first frame with a shallow copy which has the new timestamp.
-        RefPtr<VideoData> temp = VideoData::ShallowCopyUpdateTimestamp(video.get(), target);
-        video = temp;
+        // start time to match the seek target.
+        video->UpdateTimestamp(target);
       }
       mFirstVideoFrameAfterSeek = nullptr;
 
       SLOG("DropVideoUpToSeekTarget() found video frame [%lld, %lld] containing target=%lld",
                   video->mTime, video->GetEndTime(), target);
 
       MOZ_ASSERT(!mSeekedVideoData, "Should be the 1st sample after seeking");
       mSeekedVideoData = video;
--- a/dom/media/android/AndroidMediaReader.cpp
+++ b/dom/media/android/AndroidMediaReader.cpp
@@ -136,19 +136,18 @@ bool AndroidMediaReader::DecodeVideoFram
     if (!mPlugin->ReadVideo(mPlugin, &frame, mVideoSeekTimeUs, &bufferCallback)) {
       // We reached the end of the video stream. If we have a buffered
       // video frame, push it the video queue using the total duration
       // of the video as the end time.
       if (mLastVideoFrame) {
         int64_t durationUs;
         mPlugin->GetDuration(mPlugin, &durationUs);
         durationUs = std::max<int64_t>(durationUs - mLastVideoFrame->mTime, 0);
-        RefPtr<VideoData> data = VideoData::ShallowCopyUpdateDuration(mLastVideoFrame,
-                                                                        durationUs);
-        mVideoQueue.Push(data);
+        mLastVideoFrame->UpdateDuration(durationUs);
+        mVideoQueue.Push(mLastVideoFrame);
         mLastVideoFrame = nullptr;
       }
       return false;
     }
     mVideoSeekTimeUs = -1;
 
     if (aKeyframeSkip) {
       // Disable keyframe skipping for now as
@@ -256,17 +255,17 @@ bool AndroidMediaReader::DecodeVideoFram
       mLastVideoFrame = v;
       continue;
     }
 
     // Calculate the duration as the timestamp of the current frame minus the
     // timestamp of the previous frame. We can then return the previously
     // decoded frame, and it will have a valid timestamp.
     int64_t duration = v->mTime - mLastVideoFrame->mTime;
-    mLastVideoFrame = VideoData::ShallowCopyUpdateDuration(mLastVideoFrame, duration);
+    mLastVideoFrame->UpdateDuration(duration);
 
     // We have the start time of the next frame, so we can push the previous
     // frame into the queue, except if the end time is below the threshold,
     // in which case it wouldn't be displayed anyway.
     if (mLastVideoFrame->GetEndTime() < aTimeThreshold) {
       mLastVideoFrame = nullptr;
       continue;
     }