Bug 1201363 - MediaStreamVideoSink for ImageCapture case. r?roc draft
authorctai <ctai@mozilla.com>
Mon, 04 Jan 2016 15:41:48 +0800
changeset 324271 d911ce72fa23e45e24509ca508cb0c17967ef1de
parent 324270 3166a49869a153c081b9afa72fe987f8f4999d4f
child 324272 f05599202f920e10160a536d90630c6ee144e650
push id9869
push userbmo:ctai@mozilla.com
push dateFri, 22 Jan 2016 07:09:26 +0000
reviewersroc
bugs1201363
milestone46.0a1
Bug 1201363 - MediaStreamVideoSink for ImageCapture case. r?roc Make CaptureTask to inherite from MediaStreamVideoSink. The main change is to move the logic of |NotifyQueuedTrackChanges| to |SetCurrentFrames|.
dom/media/imagecapture/CaptureTask.cpp
dom/media/imagecapture/CaptureTask.h
--- a/dom/media/imagecapture/CaptureTask.cpp
+++ b/dom/media/imagecapture/CaptureTask.cpp
@@ -53,57 +53,47 @@ CaptureTask::AttachStream()
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<dom::VideoStreamTrack> track = mImageCapture->GetVideoStreamTrack();
 
   RefPtr<DOMMediaStream> domStream = track->GetStream();
   domStream->AddPrincipalChangeObserver(this);
 
   RefPtr<MediaStream> stream = domStream->GetPlaybackStream();
-  stream->AddListener(this);
+  stream->AddVideoOutput(this);
 }
 
 void
 CaptureTask::DetachStream()
 {
   MOZ_ASSERT(NS_IsMainThread());
 
   RefPtr<dom::VideoStreamTrack> track = mImageCapture->GetVideoStreamTrack();
 
   RefPtr<DOMMediaStream> domStream = track->GetStream();
   domStream->RemovePrincipalChangeObserver(this);
 
   RefPtr<MediaStream> stream = domStream->GetPlaybackStream();
-  stream->RemoveListener(this);
+  stream->RemoveVideoOutput(this);
 }
 
 void
 CaptureTask::PrincipalChanged(DOMMediaStream* aMediaStream)
 {
   MOZ_ASSERT(NS_IsMainThread());
   mPrincipalChanged = true;
 }
 
 void
-CaptureTask::NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
-                                      StreamTime aTrackOffset,
-                                      uint32_t aTrackEvents,
-                                      const MediaSegment& aQueuedMedia,
-                                      MediaStream* aInputStream,
-                                      TrackID aInputTrackID)
+CaptureTask::SetCurrentFrames(const VideoSegment& aSegment)
 {
   if (mImageGrabbedOrTrackEnd) {
     return;
   }
 
-  if (aTrackEvents == MediaStreamListener::TRACK_EVENT_ENDED) {
-    PostTrackEndEvent();
-    return;
-  }
-
   // Callback for encoding complete, it calls on main thread.
   class EncodeComplete : public dom::EncodeCompleteCallback
   {
   public:
     explicit EncodeComplete(CaptureTask* aTask) : mTask(aTask) {}
 
     nsresult ReceiveBlob(already_AddRefed<dom::Blob> aBlob) override
     {
@@ -112,61 +102,48 @@ CaptureTask::NotifyQueuedTrackChanges(Me
       mTask = nullptr;
       return NS_OK;
     }
 
   protected:
     RefPtr<CaptureTask> mTask;
   };
 
-  if (aQueuedMedia.GetType() == MediaSegment::VIDEO && mTrackID == aID) {
-    VideoSegment* video =
-      const_cast<VideoSegment*> (static_cast<const VideoSegment*>(&aQueuedMedia));
-    VideoSegment::ChunkIterator iter(*video);
-    while (!iter.IsEnded()) {
-      VideoChunk chunk = *iter;
-      // Extract the first valid video frame.
-      VideoFrame frame;
-      if (!chunk.IsNull()) {
-        RefPtr<layers::Image> image;
-        if (chunk.mFrame.GetForceBlack()) {
-          // Create a black image.
-          image = VideoFrame::CreateBlackImage(chunk.mFrame.GetIntrinsicSize());
-        } else {
-          image = chunk.mFrame.GetImage();
-        }
-        MOZ_ASSERT(image);
-        mImageGrabbedOrTrackEnd = true;
+  VideoSegment::ConstChunkIterator iter(aSegment);
+  while (!iter.IsEnded()) {
+    VideoChunk chunk = *iter;
 
-        // Encode image.
-        nsresult rv;
-        nsAutoString type(NS_LITERAL_STRING("image/jpeg"));
-        nsAutoString options;
-        rv = dom::ImageEncoder::ExtractDataFromLayersImageAsync(
-                                  type,
-                                  options,
-                                  false,
-                                  image,
-                                  new EncodeComplete(this));
-        if (NS_FAILED(rv)) {
-          PostTrackEndEvent();
-        }
-        return;
+    // Extract the first valid video frame.
+    VideoFrame frame;
+    if (!chunk.IsNull()) {
+      RefPtr<layers::Image> image;
+      if (chunk.mFrame.GetForceBlack()) {
+        // Create a black image.
+        image = VideoFrame::CreateBlackImage(chunk.mFrame.GetIntrinsicSize());
+      } else {
+        image = chunk.mFrame.GetImage();
       }
-      iter.Next();
-    }
-  }
-}
+      MOZ_ASSERT(image);
+      mImageGrabbedOrTrackEnd = true;
 
-void
-CaptureTask::NotifyEvent(MediaStreamGraph* aGraph, MediaStreamGraphEvent aEvent)
-{
-  if (((aEvent == EVENT_FINISHED) || (aEvent == EVENT_REMOVED)) &&
-      !mImageGrabbedOrTrackEnd) {
-    PostTrackEndEvent();
+      // Encode image.
+      nsresult rv;
+      nsAutoString type(NS_LITERAL_STRING("image/jpeg"));
+      nsAutoString options;
+      rv = dom::ImageEncoder::ExtractDataFromLayersImageAsync(
+                                type,
+                                options,
+                                false,
+                                image,
+                                new EncodeComplete(this));
+      if (NS_FAILED(rv)) {
+        PostTrackEndEvent();
+      }
+    }
+    iter.Next();
   }
 }
 
 void
 CaptureTask::PostTrackEndEvent()
 {
   mImageGrabbedOrTrackEnd = true;
 
--- a/dom/media/imagecapture/CaptureTask.h
+++ b/dom/media/imagecapture/CaptureTask.h
@@ -4,16 +4,17 @@
  * License, v. 2.0. If a copy of the MPL was not distributed with this
  * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
 
 #ifndef CAPTURETASK_H
 #define CAPTURETASK_H
 
 #include "DOMMediaStream.h"
 #include "MediaStreamGraph.h"
+#include "MediaStreamVideoSink.h"
 
 namespace mozilla {
 
 namespace dom {
 class Blob;
 class ImageCapture;
 } // namespace dom
 
@@ -22,30 +23,23 @@ class ImageCapture;
  * ImageEncoder. The whole procedures start at AttachStream(), it will add this
  * class into MediaStream and retrieves an image in MediaStreamGraph thread.
  * Once the image is retrieved, it will be sent to ImageEncoder and the encoded
  * blob will be sent out via encoder callback in main thread.
  *
  * CaptureTask holds a reference of ImageCapture to ensure ImageCapture won't be
  * released during the period of the capturing process described above.
  */
-class CaptureTask : public MediaStreamListener,
+class CaptureTask : public MediaStreamVideoSink,
                     public DOMMediaStream::PrincipalChangeObserver
 {
 public:
-  // MediaStreamListener methods.
-  void NotifyQueuedTrackChanges(MediaStreamGraph* aGraph, TrackID aID,
-                                StreamTime aTrackOffset,
-                                uint32_t aTrackEvents,
-                                const MediaSegment& aQueuedMedia,
-                                MediaStream* aInputStream,
-                                TrackID aInputTrackID) override;
-
-  void NotifyEvent(MediaStreamGraph* aGraph,
-                   MediaStreamGraphEvent aEvent) override;
+  // MediaStreamVideoSink methods.
+  virtual void SetCurrentFrames(const VideoSegment& aSegment) override;
+  virtual void ClearFrames() override {}
 
   // DOMMediaStream::PrincipalChangeObserver method.
   void PrincipalChanged(DOMMediaStream* aMediaStream) override;
 
   // CaptureTask methods.
 
   // It is called when aBlob is ready to post back to script in company with
   // aRv == NS_OK. If aRv is not NS_OK, it will post an error event to script.