Bug 1301675 - Implement CanvasCaptureTrackSource that allows stopping canvas capture. r?jib draft
authorAndreas Pehrson <pehrsons@gmail.com>
Mon, 12 Sep 2016 18:00:14 +0200
changeset 432217 d2e0383c99254fb4786bd7fd6ed5357d19caae33
parent 432216 bae7c2c903ce183dda9865145f0a8974b7bb2d34
child 432218 fe026841fb528052e412a45d619bc08fcb942d49
push id34235
push userbmo:pehrson@telenordigital.com
push dateTue, 01 Nov 2016 13:40:03 +0000
reviewersjib
bugs1301675
milestone52.0a1
Bug 1301675 - Implement CanvasCaptureTrackSource that allows stopping canvas capture. r?jib MozReview-Commit-ID: 81DD9FDOxsm
dom/html/HTMLCanvasElement.cpp
dom/media/CanvasCaptureMediaStream.cpp
dom/media/CanvasCaptureMediaStream.h
--- a/dom/html/HTMLCanvasElement.cpp
+++ b/dom/html/HTMLCanvasElement.cpp
@@ -647,16 +647,59 @@ PrintCallback*
 HTMLCanvasElement::GetMozPrintCallback() const
 {
   if (mOriginalCanvas) {
     return mOriginalCanvas->GetMozPrintCallback();
   }
   return mPrintCallback;
 }
 
+class CanvasCaptureTrackSource : public MediaStreamTrackSource
+{
+public:
+  NS_DECL_ISUPPORTS_INHERITED
+  NS_DECL_CYCLE_COLLECTION_CLASS_INHERITED(CanvasCaptureTrackSource,
+                                           MediaStreamTrackSource)
+
+  CanvasCaptureTrackSource(nsIPrincipal* aPrincipal,
+                           CanvasCaptureMediaStream* aCaptureStream)
+    : MediaStreamTrackSource(aPrincipal, nsString())
+    , mCaptureStream(aCaptureStream) {}
+
+  MediaSourceEnum GetMediaSource() const override
+  {
+    return MediaSourceEnum::Other;
+  }
+
+  void Stop() override
+  {
+    if (!mCaptureStream) {
+      NS_ERROR("No stream");
+      return;
+    }
+
+    mCaptureStream->StopCapture();
+  }
+
+private:
+  virtual ~CanvasCaptureTrackSource() {}
+
+  RefPtr<CanvasCaptureMediaStream> mCaptureStream;
+};
+
+NS_IMPL_ADDREF_INHERITED(CanvasCaptureTrackSource,
+                         MediaStreamTrackSource)
+NS_IMPL_RELEASE_INHERITED(CanvasCaptureTrackSource,
+                          MediaStreamTrackSource)
+NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION_INHERITED(CanvasCaptureTrackSource)
+NS_INTERFACE_MAP_END_INHERITING(MediaStreamTrackSource)
+NS_IMPL_CYCLE_COLLECTION_INHERITED(CanvasCaptureTrackSource,
+                                   MediaStreamTrackSource,
+                                   mCaptureStream)
+
 already_AddRefed<CanvasCaptureMediaStream>
 HTMLCanvasElement::CaptureStream(const Optional<double>& aFrameRate,
                                  ErrorResult& aRv)
 {
   if (IsWriteOnly()) {
     aRv.Throw(NS_ERROR_DOM_SECURITY_ERR);
     return nullptr;
   }
@@ -685,17 +728,17 @@ HTMLCanvasElement::CaptureStream(const O
     stream->Init(aFrameRate, videoTrackId, principal);
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
   RefPtr<MediaStreamTrack> track =
   stream->CreateDOMTrack(videoTrackId, MediaSegment::VIDEO,
-                         new BasicUnstoppableTrackSource(principal));
+                         new CanvasCaptureTrackSource(principal, stream));
   stream->AddTrackInternal(track);
 
   rv = RegisterFrameCaptureListener(stream->FrameCaptureListener());
   if (NS_FAILED(rv)) {
     aRv.Throw(rv);
     return nullptr;
   }
 
--- a/dom/media/CanvasCaptureMediaStream.cpp
+++ b/dom/media/CanvasCaptureMediaStream.cpp
@@ -233,17 +233,16 @@ JSObject*
 CanvasCaptureMediaStream::WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto)
 {
   return dom::CanvasCaptureMediaStreamBinding::Wrap(aCx, this, aGivenProto);
 }
 
 void
 CanvasCaptureMediaStream::RequestFrame()
 {
-  MOZ_ASSERT(mOutputStreamDriver);
   if (mOutputStreamDriver) {
     mOutputStreamDriver->RequestFrameCapture();
   }
 }
 
 nsresult
 CanvasCaptureMediaStream::Init(const dom::Optional<double>& aFPS,
                                const TrackID& aTrackId,
@@ -278,11 +277,22 @@ CanvasCaptureMediaStream::CreateSourceSt
 }
 
 FrameCaptureListener*
 CanvasCaptureMediaStream::FrameCaptureListener()
 {
   return mOutputStreamDriver;
 }
 
+void
+CanvasCaptureMediaStream::StopCapture()
+{
+  if (!mOutputStreamDriver) {
+    return;
+  }
+
+  mOutputStreamDriver->Forget();
+  mOutputStreamDriver = nullptr;
+}
+
 } // namespace dom
 } // namespace mozilla
 
--- a/dom/media/CanvasCaptureMediaStream.h
+++ b/dom/media/CanvasCaptureMediaStream.h
@@ -107,19 +107,25 @@ public:
   nsresult Init(const dom::Optional<double>& aFPS, const TrackID& aTrackId,
                 nsIPrincipal* aPrincipal);
 
   JSObject* WrapObject(JSContext* aCx, JS::Handle<JSObject*> aGivenProto) override;
 
   // WebIDL
   HTMLCanvasElement* Canvas() const { return mCanvas; }
   void RequestFrame();
+
   dom::FrameCaptureListener* FrameCaptureListener();
 
   /**
+   * Stops capturing for this stream at mCanvas.
+   */
+  void StopCapture();
+
+  /**
    * Create a CanvasCaptureMediaStream whose underlying stream is a SourceMediaStream.
    */
   static already_AddRefed<CanvasCaptureMediaStream>
   CreateSourceStream(nsPIDOMWindowInner* aWindow,
                      HTMLCanvasElement* aCanvas);
 
 protected:
   ~CanvasCaptureMediaStream();