Bug 1301675 - Implement CanvasCaptureTrackSource that allows stopping canvas capture. r=jib
MozReview-Commit-ID: 81DD9FDOxsm
--- 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();