Bug 1941046 - Part 4: Send a callback request for impression and clicks of MARS Top...
[gecko.git] / dom / media / CanvasCaptureMediaStream.cpp
blob3fdb8c52d671b4eff03c1c3054ad2eb73d8521fc
1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*-*/
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this file,
4 * You can obtain one at http://mozilla.org/MPL/2.0/. */
6 #include "CanvasCaptureMediaStream.h"
8 #include "DOMMediaStream.h"
9 #include "ImageContainer.h"
10 #include "MediaTrackGraph.h"
11 #include "Tracing.h"
12 #include "VideoSegment.h"
13 #include "mozilla/dom/CanvasCaptureMediaStreamBinding.h"
14 #include "mozilla/gfx/2D.h"
15 #include "nsContentUtils.h"
16 #include "nsGlobalWindowInner.h"
18 using namespace mozilla::layers;
19 using namespace mozilla::gfx;
21 namespace mozilla::dom {
23 OutputStreamDriver::OutputStreamDriver(SourceMediaTrack* aSourceStream,
24 const PrincipalHandle& aPrincipalHandle)
25 : mSourceStream(aSourceStream), mPrincipalHandle(aPrincipalHandle) {
26 MOZ_ASSERT(NS_IsMainThread());
27 MOZ_ASSERT(mSourceStream);
30 OutputStreamDriver::~OutputStreamDriver() {
31 MOZ_ASSERT(NS_IsMainThread());
32 EndTrack();
35 void OutputStreamDriver::EndTrack() {
36 MOZ_ASSERT(NS_IsMainThread());
37 if (!mSourceStream->IsDestroyed()) {
38 mSourceStream->Destroy();
42 void OutputStreamDriver::SetImage(RefPtr<layers::Image>&& aImage,
43 const TimeStamp& aTime) {
44 MOZ_ASSERT(NS_IsMainThread());
46 VideoSegment segment;
47 const auto size = aImage->GetSize();
48 segment.AppendFrame(aImage.forget(), size, mPrincipalHandle, false, aTime);
49 mSourceStream->AppendData(&segment);
52 // ----------------------------------------------------------------------
54 class TimerDriver : public OutputStreamDriver {
55 public:
56 explicit TimerDriver(SourceMediaTrack* aSourceStream, const double& aFPS,
57 const PrincipalHandle& aPrincipalHandle)
58 : OutputStreamDriver(aSourceStream, aPrincipalHandle),
59 mFrameInterval(aFPS == 0.0 ? TimeDuration::Forever()
60 : TimeDuration::FromSeconds(1.0 / aFPS)) {}
62 void RequestFrameCapture() override { mExplicitCaptureRequested = true; }
64 bool FrameCaptureRequested(const TimeStamp& aTime) const override {
65 if (mLastFrameTime.IsNull()) {
66 // All CanvasCaptureMediaStreams shall at least get one frame.
67 return true;
70 if (mExplicitCaptureRequested) {
71 return true;
74 if ((aTime - mLastFrameTime) >= mFrameInterval) {
75 return true;
78 return false;
81 void NewFrame(already_AddRefed<Image> aImage,
82 const TimeStamp& aTime) override {
83 nsCString str;
84 if (profiler_thread_is_being_profiled_for_markers()) {
85 TimeDuration sinceLast =
86 aTime - (mLastFrameTime.IsNull() ? aTime : mLastFrameTime);
87 str.AppendPrintf(
88 "TimerDriver %staking frame (%sexplicitly requested; after %.2fms; "
89 "interval cap %.2fms)",
90 sinceLast >= mFrameInterval ? "" : "NOT ",
91 mExplicitCaptureRequested ? "" : "NOT ", sinceLast.ToMilliseconds(),
92 mFrameInterval.ToMilliseconds());
94 AUTO_PROFILER_MARKER_TEXT("Canvas CaptureStream", MEDIA_RT, {}, str);
96 RefPtr<Image> image = aImage;
98 if (!FrameCaptureRequested(aTime)) {
99 return;
102 mLastFrameTime = aTime;
103 mExplicitCaptureRequested = false;
104 SetImage(std::move(image), aTime);
107 protected:
108 virtual ~TimerDriver() = default;
110 private:
111 const TimeDuration mFrameInterval;
112 bool mExplicitCaptureRequested = false;
113 TimeStamp mLastFrameTime;
116 // ----------------------------------------------------------------------
118 class AutoDriver : public OutputStreamDriver {
119 public:
120 explicit AutoDriver(SourceMediaTrack* aSourceStream,
121 const PrincipalHandle& aPrincipalHandle)
122 : OutputStreamDriver(aSourceStream, aPrincipalHandle) {}
124 void RequestFrameCapture() override {}
126 bool FrameCaptureRequested(const TimeStamp& aTime) const override {
127 return true;
130 void NewFrame(already_AddRefed<Image> aImage,
131 const TimeStamp& aTime) override {
132 AUTO_PROFILER_MARKER_TEXT("Canvas CaptureStream", MEDIA_RT, {},
133 "AutoDriver taking frame"_ns);
135 RefPtr<Image> image = aImage;
136 SetImage(std::move(image), aTime);
139 protected:
140 virtual ~AutoDriver() = default;
143 // ----------------------------------------------------------------------
145 NS_IMPL_CYCLE_COLLECTION_INHERITED(CanvasCaptureMediaStream, DOMMediaStream,
146 mCanvas)
148 NS_IMPL_ADDREF_INHERITED(CanvasCaptureMediaStream, DOMMediaStream)
149 NS_IMPL_RELEASE_INHERITED(CanvasCaptureMediaStream, DOMMediaStream)
151 NS_INTERFACE_MAP_BEGIN_CYCLE_COLLECTION(CanvasCaptureMediaStream)
152 NS_INTERFACE_MAP_END_INHERITING(DOMMediaStream)
154 CanvasCaptureMediaStream::CanvasCaptureMediaStream(nsPIDOMWindowInner* aWindow,
155 HTMLCanvasElement* aCanvas)
156 : DOMMediaStream(aWindow), mCanvas(aCanvas) {}
158 CanvasCaptureMediaStream::~CanvasCaptureMediaStream() = default;
160 JSObject* CanvasCaptureMediaStream::WrapObject(
161 JSContext* aCx, JS::Handle<JSObject*> aGivenProto) {
162 return dom::CanvasCaptureMediaStream_Binding::Wrap(aCx, this, aGivenProto);
165 void CanvasCaptureMediaStream::RequestFrame() {
166 if (mOutputStreamDriver) {
167 mOutputStreamDriver->RequestFrameCapture();
171 nsresult CanvasCaptureMediaStream::Init(const dom::Optional<double>& aFPS,
172 nsIPrincipal* aPrincipal) {
173 MediaTrackGraph* graph = MediaTrackGraph::GetInstance(
174 MediaTrackGraph::SYSTEM_THREAD_DRIVER, GetOwnerWindow(),
175 MediaTrackGraph::REQUEST_DEFAULT_SAMPLE_RATE,
176 MediaTrackGraph::DEFAULT_OUTPUT_DEVICE);
177 SourceMediaTrack* source = graph->CreateSourceTrack(MediaSegment::VIDEO);
178 PrincipalHandle principalHandle = MakePrincipalHandle(aPrincipal);
179 if (!aFPS.WasPassed()) {
180 mOutputStreamDriver = new AutoDriver(source, principalHandle);
181 } else if (aFPS.Value() < 0) {
182 return NS_ERROR_ILLEGAL_VALUE;
183 } else {
184 // Cap frame rate to 60 FPS for sanity
185 double fps = std::min(60.0, aFPS.Value());
186 mOutputStreamDriver = new TimerDriver(source, fps, principalHandle);
188 return NS_OK;
191 FrameCaptureListener* CanvasCaptureMediaStream::FrameCaptureListener() {
192 return mOutputStreamDriver;
195 void CanvasCaptureMediaStream::StopCapture() {
196 if (!mOutputStreamDriver) {
197 return;
200 mOutputStreamDriver->EndTrack();
201 mOutputStreamDriver = nullptr;
204 SourceMediaTrack* CanvasCaptureMediaStream::GetSourceStream() const {
205 if (!mOutputStreamDriver) {
206 return nullptr;
208 return mOutputStreamDriver->mSourceStream;
211 } // namespace mozilla::dom