1 #include "nsGlobalWindow.h"
2 #include "nsDOMWindowUtils.h"
3 #include "nsIDOMClientRect.h"
4 #include "nsIDocShell.h"
5 #include "nsIPresShell.h"
6 #include "nsPresContext.h"
7 #include "gfxImageSurface.h"
8 #include "gfxContext.h"
9 #include "ImageContainer.h"
11 #include "nsIInterfaceRequestorUtils.h"
12 #include "nsIDOMDocument.h"
13 #include "nsITabSource.h"
14 #include "MediaEngineTabVideoSource.h"
15 #include "VideoUtils.h"
16 #include "nsServiceManagerUtils.h"
17 #include "nsIPrefService.h"
20 NS_IMPL_ISUPPORTS1(MediaEngineTabVideoSource
, MediaEngineVideoSource
)
22 MediaEngineTabVideoSource::MediaEngineTabVideoSource()
23 : mName(NS_LITERAL_STRING("share tab")), mUuid(NS_LITERAL_STRING("uuid")),
24 mMonitor("MediaEngineTabVideoSource")
29 MediaEngineTabVideoSource::StartRunnable::Run()
32 nsCOMPtr
<nsPIDOMWindow
> privateDOMWindow
= do_QueryInterface(mVideoSource
->mWindow
);
33 if (privateDOMWindow
) {
34 privateDOMWindow
->GetChromeEventHandler()->AddEventListener(NS_LITERAL_STRING("MozAfterPaint"), mVideoSource
, false);
36 mVideoSource
->mTimer
= do_CreateInstance(NS_TIMER_CONTRACTID
);
37 mVideoSource
->mTimer
->InitWithCallback(mVideoSource
, mVideoSource
->mTimePerFrame
, nsITimer:: TYPE_REPEATING_SLACK
);
43 MediaEngineTabVideoSource::StopRunnable::Run()
45 nsCOMPtr
<nsPIDOMWindow
> privateDOMWindow
= do_QueryInterface(mVideoSource
->mWindow
);
46 if (privateDOMWindow
&& mVideoSource
&& privateDOMWindow
->GetChromeEventHandler()) {
47 privateDOMWindow
->GetChromeEventHandler()->RemoveEventListener(NS_LITERAL_STRING("MozAfterPaint"), mVideoSource
, false);
50 if (mVideoSource
->mTimer
) {
51 mVideoSource
->mTimer
->Cancel();
52 mVideoSource
->mTimer
= nullptr;
58 MediaEngineTabVideoSource::HandleEvent(nsIDOMEvent
*event
) {
64 MediaEngineTabVideoSource::Notify(nsITimer
*) {
70 MediaEngineTabVideoSource::InitRunnable::Run()
73 nsCOMPtr
<nsIPrefService
> prefs
= do_GetService("@mozilla.org/preferences-service;1", &rv
);
74 NS_ENSURE_SUCCESS(rv
, rv
);
75 nsCOMPtr
<nsIPrefBranch
> branch
= do_QueryInterface(prefs
);
78 branch
->GetIntPref("media.tabstreaming.width", &mVideoSource
->mBufW
);
79 branch
->GetIntPref("media.tabstreaming.height", &mVideoSource
->mBufH
);
80 branch
->GetIntPref("media.tabstreaming.time_per_frame", &mVideoSource
->mTimePerFrame
);
81 mVideoSource
->mData
= (unsigned char*)malloc(mVideoSource
->mBufW
* mVideoSource
->mBufH
* 4);
83 nsCOMPtr
<nsITabSource
> tabSource
= do_GetService(NS_TABSOURCESERVICE_CONTRACTID
, &rv
);
84 NS_ENSURE_SUCCESS(rv
, rv
);
85 nsCOMPtr
<nsIDOMWindow
> win
;
86 rv
= tabSource
->GetTabToStream(getter_AddRefs(win
));
87 NS_ENSURE_SUCCESS(rv
, rv
);
91 mVideoSource
->mWindow
= win
;
92 nsCOMPtr
<nsIRunnable
> start(new StartRunnable(mVideoSource
));
98 MediaEngineTabVideoSource::GetName(nsAString_internal
& aName
)
105 MediaEngineTabVideoSource::GetUUID(nsAString_internal
& aUuid
)
111 MediaEngineTabVideoSource::Allocate(const mozilla::MediaEnginePrefs
&)
117 MediaEngineTabVideoSource::Deallocate()
123 MediaEngineTabVideoSource::Start(mozilla::SourceMediaStream
* aStream
, mozilla::TrackID aID
)
125 nsCOMPtr
<nsIRunnable
> runnable
;
127 runnable
= new InitRunnable(this);
129 runnable
= new StartRunnable(this);
130 NS_DispatchToMainThread(runnable
);
131 aStream
->AddTrack(aID
, USECS_PER_S
, 0, new VideoSegment());
132 aStream
->AdvanceKnownTracksTime(STREAM_TIME_MAX
);
138 MediaEngineTabVideoSource::Snapshot(uint32_t, nsIDOMFile
**)
144 MediaEngineTabVideoSource::
145 NotifyPull(MediaStreamGraph
*, SourceMediaStream
* aSource
, mozilla::TrackID aID
, mozilla::StreamTime aDesiredTime
, mozilla::TrackTicks
& aLastEndTime
)
147 VideoSegment segment
;
148 MonitorAutoLock
mon(mMonitor
);
150 // Note: we're not giving up mImage here
151 nsRefPtr
<layers::CairoImage
> image
= mImage
;
152 TrackTicks target
= TimeToTicksRoundUp(USECS_PER_S
, aDesiredTime
);
153 TrackTicks delta
= target
- aLastEndTime
;
155 // nullptr images are allowed
157 gfxIntSize size
= image
->GetSize();
158 segment
.AppendFrame(image
.forget(), delta
, size
);
160 segment
.AppendFrame(nullptr, delta
, gfxIntSize(0,0));
162 // This can fail if either a) we haven't added the track yet, or b)
163 // we've removed or finished the track.
164 if (aSource
->AppendToTrack(aID
, &(segment
))) {
165 aLastEndTime
= target
;
171 MediaEngineTabVideoSource::Draw() {
173 nsIntSize
size(mBufW
, mBufH
);
178 nsCOMPtr
<nsPIDOMWindow
> win
= do_QueryInterface(mWindow
);
184 // take a screenshot, as wide as possible, proportional to the destination size
185 nsCOMPtr
<nsIDOMWindowUtils
> utils
= do_GetInterface(win
);
190 nsCOMPtr
<nsIDOMClientRect
> rect
;
191 rv
= utils
->GetRootBounds(getter_AddRefs(rect
));
192 NS_ENSURE_SUCCESS_VOID(rv
);
197 float left
, top
, width
, height
;
198 rect
->GetLeft(&left
);
200 rect
->GetWidth(&width
);
201 rect
->GetHeight(&height
);
203 if (width
== 0 || height
== 0) {
212 float aspectRatio
= ((float) size
.width
) / size
.height
;
213 if (width
/ aspectRatio
< height
) {
215 srcH
= width
/ aspectRatio
;
217 srcW
= height
* aspectRatio
;
221 nsRefPtr
<nsPresContext
> presContext
;
222 nsIDocShell
* docshell
= win
->GetDocShell();
224 docshell
->GetPresContext(getter_AddRefs(presContext
));
229 nscolor bgColor
= NS_RGB(255, 255, 255);
230 nsCOMPtr
<nsIPresShell
> presShell
= presContext
->PresShell();
231 uint32_t renderDocFlags
= (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING
|
232 nsIPresShell::RENDER_DOCUMENT_RELATIVE
);
233 nsRect
r(nsPresContext::CSSPixelsToAppUnits(srcX
/ scale
),
234 nsPresContext::CSSPixelsToAppUnits(srcY
/ scale
),
235 nsPresContext::CSSPixelsToAppUnits(srcW
/ scale
),
236 nsPresContext::CSSPixelsToAppUnits(srcH
/ scale
));
238 gfxImageFormat format
= gfxImageFormatRGB24
;
239 uint32_t stride
= gfxASurface::FormatStrideForWidth(format
, size
.width
);
241 nsRefPtr
<layers::ImageContainer
> container
= layers::LayerManager::CreateImageContainer();
242 nsRefPtr
<gfxASurface
> surf
;
243 surf
= new gfxImageSurface(static_cast<unsigned char*>(mData
), size
,
245 if (surf
->CairoStatus() != 0) {
248 nsRefPtr
<gfxContext
> context
= new gfxContext(surf
);
250 context
->Translate(pt
);
251 context
->Scale(scale
* size
.width
/ srcW
, scale
* size
.height
/ srcH
);
252 rv
= presShell
->RenderDocument(r
, renderDocFlags
, bgColor
, context
);
254 NS_ENSURE_SUCCESS_VOID(rv
);
256 layers::CairoImage::Data cairoData
;
257 cairoData
.mSurface
= surf
;
258 cairoData
.mSize
= size
;
260 nsRefPtr
<layers::CairoImage
> image
= new layers::CairoImage();
262 image
->SetData(cairoData
);
264 MonitorAutoLock
mon(mMonitor
);
269 MediaEngineTabVideoSource::Stop(mozilla::SourceMediaStream
*, mozilla::TrackID
)
271 NS_DispatchToMainThread(new StopRunnable(this));
276 MediaEngineTabVideoSource::Config(bool, uint32_t, bool, uint32_t, bool, uint32_t)
282 MediaEngineTabVideoSource::IsFake()