Bug 1299068 - part 3: notify when VideoData are sent to compositor. r=jwwang
authorJohn Lin <jolin@mozilla.com>
Wed, 23 Nov 2016 15:08:17 +0800
changeset 325369 cd931b83e49951ad24f105762152d636941c075c
parent 325368 956f17ac252244a485d2d1ba2b8acfd82d9d3ec8
child 325370 f417fea060f73f7337f7d18c67630479524543e9
push id24
push usermaklebus@msu.edu
push dateTue, 20 Dec 2016 03:11:33 +0000
reviewersjwwang
bugs1299068
milestone53.0a1
Bug 1299068 - part 3: notify when VideoData are sent to compositor. r=jwwang MozReview-Commit-ID: Jn4AqpMaXMg
dom/media/MediaData.cpp
dom/media/MediaData.h
dom/media/mediasink/VideoSink.cpp
--- a/dom/media/MediaData.cpp
+++ b/dom/media/MediaData.cpp
@@ -134,16 +134,38 @@ VideoData::VideoData(int64_t aOffset,
   mKeyframe = aKeyframe;
   mTimecode = aTimecode;
 }
 
 VideoData::~VideoData()
 {
 }
 
+void
+VideoData::SetListener(UniquePtr<Listener> aListener)
+{
+  MOZ_ASSERT(!mSentToCompositor, "Listener should be registered before sending data");
+
+  mListener = Move(aListener);
+}
+
+void
+VideoData::MarkSentToCompositor()
+{
+  if (mSentToCompositor) {
+    return;
+  }
+
+  mSentToCompositor = true;
+  if (mListener != nullptr) {
+    mListener->OnSentToCompositor();
+    mListener = nullptr;
+  }
+}
+
 size_t
 VideoData::SizeOfIncludingThis(MallocSizeOf aMallocSizeOf) const
 {
   size_t size = aMallocSizeOf(this);
 
   // Currently only PLANAR_YCBCR has a well defined function for determining
   // it's size, so reporting is limited to that type.
   if (mImage && mImage->GetFormat() == ImageFormat::PLANAR_YCBCR) {
--- a/dom/media/MediaData.h
+++ b/dom/media/MediaData.h
@@ -442,16 +442,22 @@ public:
       uint32_t mOffset;
       uint32_t mSkip;
     };
 
     Plane mPlanes[3];
     YUVColorSpace mYUVColorSpace = YUVColorSpace::BT601;
   };
 
+  class Listener {
+  public:
+    virtual void OnSentToCompositor() = 0;
+    virtual ~Listener() {}
+  };
+
   // Constructs a VideoData object. If aImage is nullptr, creates a new Image
   // holding a copy of the YCbCr data passed in aBuffer. If aImage is not
   // nullptr, it's stored as the underlying video image and aBuffer is assumed
   // to point to memory within aImage so no copy is made. aTimecode is a codec
   // specific number representing the timestamp of the frame of video data.
   // Returns nsnull if an error occurs. This may indicate that memory couldn't
   // be allocated to create the VideoData object, or it may indicate some
   // problem with the input data (e.g. negative stride).
@@ -525,28 +531,33 @@ public:
   // dimensions scaled with respect to its aspect ratio.
   const IntSize mDisplay;
 
   // This frame's image.
   RefPtr<Image> mImage;
 
   int32_t mFrameID;
 
-  bool mSentToCompositor;
-
   VideoData(int64_t aOffset,
             int64_t aTime,
             int64_t aDuration,
             bool aKeyframe,
             int64_t aTimecode,
             IntSize aDisplay,
             uint32_t aFrameID);
 
+  void SetListener(UniquePtr<Listener> aListener);
+  void MarkSentToCompositor();
+  bool IsSentToCompositor() { return mSentToCompositor; }
+
 protected:
   ~VideoData();
+
+  bool mSentToCompositor;
+  UniquePtr<Listener> mListener;
 };
 
 class CryptoTrack
 {
 public:
   CryptoTrack() : mValid(false), mMode(0), mIVSize(0) {}
   bool mValid;
   int32_t mMode;
--- a/dom/media/mediasink/VideoSink.cpp
+++ b/dom/media/mediasink/VideoSink.cpp
@@ -254,17 +254,17 @@ VideoSink::Shutdown()
 
 void
 VideoSink::OnVideoQueuePushed(RefPtr<MediaData>&& aSample)
 {
   AssertOwnerThread();
   // Listen to push event, VideoSink should try rendering ASAP if first frame
   // arrives but update scheduler is not triggered yet.
   VideoData* v = aSample->As<VideoData>();
-  if (!v->mSentToCompositor) {
+  if (!v->IsSentToCompositor()) {
     // Since we push rendered frames back to the queue, we will receive
     // push events for them. We only need to trigger render loop
     // when this frame is not rendered yet.
     TryUpdateRenderedVideoFrames();
   }
 }
 
 void
@@ -354,17 +354,17 @@ VideoSink::RenderVideoFrames(int32_t aMa
   }
 
   AutoTArray<ImageContainer::NonOwningImage,16> images;
   TimeStamp lastFrameTime;
   MediaSink::PlaybackParams params = mAudioSink->GetPlaybackParams();
   for (uint32_t i = 0; i < frames.Length(); ++i) {
     VideoData* frame = frames[i]->As<VideoData>();
 
-    frame->mSentToCompositor = true;
+    frame->MarkSentToCompositor();
 
     if (!frame->mImage || !frame->mImage->IsValid() ||
         !frame->mImage->GetSize().width || !frame->mImage->GetSize().height) {
       continue;
     }
 
     int64_t frameTime = frame->mTime;
     if (frameTime < 0) {
@@ -412,17 +412,17 @@ VideoSink::UpdateRenderedVideoFrames()
   NS_ASSERTION(clockTime >= 0, "Should have positive clock time.");
 
   // Skip frames up to the playback position.
   int64_t lastFrameEndTime = 0;
   while (VideoQueue().GetSize() > mMinVideoQueueSize &&
          clockTime >= VideoQueue().PeekFront()->GetEndTime()) {
     RefPtr<MediaData> frame = VideoQueue().PopFront();
     lastFrameEndTime = frame->GetEndTime();
-    if (frame->As<VideoData>()->mSentToCompositor) {
+    if (frame->As<VideoData>()->IsSentToCompositor()) {
       mFrameStats.NotifyPresentedFrame();
     } else {
       mFrameStats.NotifyDecodedFrames({ 0, 0, 1 });
       VSINK_LOG_V("discarding video frame mTime=%lld clock_time=%lld",
                   frame->mTime, clockTime);
     }
   }