content/media/webrtc/MediaEngineTabVideoSource.cpp

Fri, 16 Jan 2015 04:50:19 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Fri, 16 Jan 2015 04:50:19 +0100
branch
TOR_BUG_9701
changeset 13
44a2da4a2ab2
permissions
-rw-r--r--

Replace accessor implementation with direct member state manipulation, by
request https://trac.torproject.org/projects/tor/ticket/9701#comment:32

     1 /* This Source Code Form is subject to the terms of the Mozilla Public
     2  * License, v. 2.0. If a copy of the MPL was not distributed with this file,
     3  * You can obtain one at http://mozilla.org/MPL/2.0/. */
     5 #include "MediaEngineTabVideoSource.h"
     7 #include "mozilla/gfx/2D.h"
     8 #include "mozilla/RefPtr.h"
     9 #include "nsGlobalWindow.h"
    10 #include "nsDOMWindowUtils.h"
    11 #include "nsIDOMClientRect.h"
    12 #include "nsIDocShell.h"
    13 #include "nsIPresShell.h"
    14 #include "nsPresContext.h"
    15 #include "gfxContext.h"
    16 #include "gfx2DGlue.h"
    17 #include "ImageContainer.h"
    18 #include "Layers.h"
    19 #include "nsIInterfaceRequestorUtils.h"
    20 #include "nsIDOMDocument.h"
    21 #include "nsITabSource.h"
    22 #include "VideoUtils.h"
    23 #include "nsServiceManagerUtils.h"
    24 #include "nsIPrefService.h"
    26 namespace mozilla {
    28 using namespace mozilla::gfx;
    30 NS_IMPL_ISUPPORTS(MediaEngineTabVideoSource, nsIDOMEventListener, nsITimerCallback)
    32 MediaEngineTabVideoSource::MediaEngineTabVideoSource()
    33 : mMonitor("MediaEngineTabVideoSource")
    34 {
    35 }
    37 nsresult
    38 MediaEngineTabVideoSource::StartRunnable::Run()
    39 {
    40   mVideoSource->Draw();
    41   nsCOMPtr<nsPIDOMWindow> privateDOMWindow = do_QueryInterface(mVideoSource->mWindow);
    42   if (privateDOMWindow) {
    43     privateDOMWindow->GetChromeEventHandler()->AddEventListener(NS_LITERAL_STRING("MozAfterPaint"), mVideoSource, false);
    44   } else {
    45     mVideoSource->mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
    46     mVideoSource->mTimer->InitWithCallback(mVideoSource, mVideoSource->mTimePerFrame, nsITimer:: TYPE_REPEATING_SLACK);
    47   }
    48   mVideoSource->mTabSource->NotifyStreamStart(mVideoSource->mWindow);
    49   return NS_OK;
    50 }
    52 nsresult
    53 MediaEngineTabVideoSource::StopRunnable::Run()
    54 {
    55   nsCOMPtr<nsPIDOMWindow> privateDOMWindow = do_QueryInterface(mVideoSource->mWindow);
    56   if (privateDOMWindow && mVideoSource && privateDOMWindow->GetChromeEventHandler()) {
    57     privateDOMWindow->GetChromeEventHandler()->RemoveEventListener(NS_LITERAL_STRING("MozAfterPaint"), mVideoSource, false);
    58   }
    60   if (mVideoSource->mTimer) {
    61     mVideoSource->mTimer->Cancel();
    62     mVideoSource->mTimer = nullptr;
    63   }
    64   mVideoSource->mTabSource->NotifyStreamStop(mVideoSource->mWindow);
    65   return NS_OK;
    66 }
    68 NS_IMETHODIMP
    69 MediaEngineTabVideoSource::HandleEvent(nsIDOMEvent *event) {
    70   Draw();
    71   return NS_OK;
    72 }
    74 NS_IMETHODIMP
    75 MediaEngineTabVideoSource::Notify(nsITimer*) {
    76   Draw();
    77   return NS_OK;
    78 }
    80 nsresult
    81 MediaEngineTabVideoSource::InitRunnable::Run()
    82 {
    83   nsresult rv;
    84   nsCOMPtr<nsIPrefService> prefs = do_GetService("@mozilla.org/preferences-service;1", &rv);
    85   NS_ENSURE_SUCCESS(rv, rv);
    86   nsCOMPtr<nsIPrefBranch> branch = do_QueryInterface(prefs);
    87   if (!branch)
    88     return NS_OK;
    89   branch->GetIntPref("media.tabstreaming.width", &mVideoSource->mBufW);
    90   branch->GetIntPref("media.tabstreaming.height", &mVideoSource->mBufH);
    91   branch->GetIntPref("media.tabstreaming.time_per_frame", &mVideoSource->mTimePerFrame);
    92   mVideoSource->mData = (unsigned char*)malloc(mVideoSource->mBufW * mVideoSource->mBufH * 4);
    94   mVideoSource->mTabSource = do_GetService(NS_TABSOURCESERVICE_CONTRACTID, &rv);
    95   NS_ENSURE_SUCCESS(rv, rv);
    97   nsCOMPtr<nsIDOMWindow> win;
    98   rv = mVideoSource->mTabSource->GetTabToStream(getter_AddRefs(win));
    99   NS_ENSURE_SUCCESS(rv, rv);
   100   if (!win)
   101     return NS_OK;
   103   mVideoSource->mWindow = win;
   104   nsCOMPtr<nsIRunnable> start(new StartRunnable(mVideoSource));
   105   start->Run();
   106   return NS_OK;
   107 }
   109 void
   110 MediaEngineTabVideoSource::GetName(nsAString_internal& aName)
   111 {
   112   aName.Assign(NS_LITERAL_STRING("&getUserMedia.videoDevice.tabShare;"));
   113 }
   115 void
   116 MediaEngineTabVideoSource::GetUUID(nsAString_internal& aUuid)
   117 {
   118   aUuid.Assign(NS_LITERAL_STRING("uuid"));
   119 }
   121 nsresult
   122 MediaEngineTabVideoSource::Allocate(const VideoTrackConstraintsN&,
   123                                     const MediaEnginePrefs&)
   124 {
   125   return NS_OK;
   126 }
   128 nsresult
   129 MediaEngineTabVideoSource::Deallocate()
   130 {
   131   return NS_OK;
   132 }
   134 nsresult
   135 MediaEngineTabVideoSource::Start(mozilla::SourceMediaStream* aStream, mozilla::TrackID aID)
   136 {
   137   nsCOMPtr<nsIRunnable> runnable;
   138   if (!mWindow)
   139     runnable = new InitRunnable(this);
   140   else
   141     runnable = new StartRunnable(this);
   142   NS_DispatchToMainThread(runnable);
   143   aStream->AddTrack(aID, USECS_PER_S, 0, new VideoSegment());
   144   aStream->AdvanceKnownTracksTime(STREAM_TIME_MAX);
   146   return NS_OK;
   147 }
   149 nsresult
   150 MediaEngineTabVideoSource::Snapshot(uint32_t, nsIDOMFile**)
   151 {
   152   return NS_OK;
   153 }
   155 void
   156 MediaEngineTabVideoSource::
   157 NotifyPull(MediaStreamGraph*, SourceMediaStream* aSource, mozilla::TrackID aID, mozilla::StreamTime aDesiredTime, mozilla::TrackTicks& aLastEndTime)
   158 {
   159   VideoSegment segment;
   160   MonitorAutoLock mon(mMonitor);
   162   // Note: we're not giving up mImage here
   163   nsRefPtr<layers::CairoImage> image = mImage;
   164   TrackTicks target = TimeToTicksRoundUp(USECS_PER_S, aDesiredTime);
   165   TrackTicks delta = target - aLastEndTime;
   166   if (delta > 0) {
   167     // nullptr images are allowed
   168     gfx::IntSize size = image ? image->GetSize() : IntSize(0, 0);
   169     segment.AppendFrame(image.forget().downcast<layers::Image>(), delta, size);
   170     // This can fail if either a) we haven't added the track yet, or b)
   171     // we've removed or finished the track.
   172     if (aSource->AppendToTrack(aID, &(segment))) {
   173       aLastEndTime = target;
   174     }
   175   }
   176 }
   178 void
   179 MediaEngineTabVideoSource::Draw() {
   181   IntSize size(mBufW, mBufH);
   183   nsresult rv;
   184   float scale = 1.0;
   186   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mWindow);
   188   if (!win) {
   189     return;
   190   }
   192   // take a screenshot, as wide as possible, proportional to the destination size
   193   nsCOMPtr<nsIDOMWindowUtils> utils = do_GetInterface(win);
   194   if (!utils) {
   195     return;
   196   }
   198   nsCOMPtr<nsIDOMClientRect> rect;
   199   rv = utils->GetRootBounds(getter_AddRefs(rect));
   200   NS_ENSURE_SUCCESS_VOID(rv);
   201   if (!rect) {
   202     return;
   203   }
   205   float left, top, width, height;
   206   rect->GetLeft(&left);
   207   rect->GetTop(&top);
   208   rect->GetWidth(&width);
   209   rect->GetHeight(&height);
   211   if (width == 0 || height == 0) {
   212     return;
   213   }
   215   int32_t srcX = left;
   216   int32_t srcY = top;
   217   int32_t srcW;
   218   int32_t srcH;
   220   float aspectRatio = ((float) size.width) / size.height;
   221   if (width / aspectRatio < height) {
   222     srcW = width;
   223     srcH = width / aspectRatio;
   224   } else {
   225     srcW = height * aspectRatio;
   226     srcH = height;
   227   }
   229   nsRefPtr<nsPresContext> presContext;
   230   nsIDocShell* docshell = win->GetDocShell();
   231   if (docshell) {
   232     docshell->GetPresContext(getter_AddRefs(presContext));
   233   }
   234   if (!presContext) {
   235     return;
   236   }
   237   nscolor bgColor = NS_RGB(255, 255, 255);
   238   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
   239   uint32_t renderDocFlags = (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
   240                              nsIPresShell::RENDER_DOCUMENT_RELATIVE);
   241   nsRect r(nsPresContext::CSSPixelsToAppUnits(srcX / scale),
   242            nsPresContext::CSSPixelsToAppUnits(srcY / scale),
   243            nsPresContext::CSSPixelsToAppUnits(srcW / scale),
   244            nsPresContext::CSSPixelsToAppUnits(srcH / scale));
   246   gfxImageFormat format = gfxImageFormat::RGB24;
   247   uint32_t stride = gfxASurface::FormatStrideForWidth(format, size.width);
   249   nsRefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
   250   RefPtr<DrawTarget> dt =
   251     Factory::CreateDrawTargetForData(BackendType::CAIRO,
   252                                      mData.rwget(),
   253                                      size,
   254                                      stride,
   255                                      SurfaceFormat::B8G8R8X8);
   256   if (!dt) {
   257     return;
   258   }
   259   nsRefPtr<gfxContext> context = new gfxContext(dt);
   260   gfxPoint pt(0, 0);
   261   context->Translate(pt);
   262   context->Scale(scale * size.width / srcW, scale * size.height / srcH);
   263   rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
   265   NS_ENSURE_SUCCESS_VOID(rv);
   267   RefPtr<SourceSurface> surface = dt->Snapshot();
   268   if (!surface) {
   269     return;
   270   }
   272   layers::CairoImage::Data cairoData;
   273   cairoData.mSize = size;
   274   cairoData.mSourceSurface = surface;
   276   nsRefPtr<layers::CairoImage> image = new layers::CairoImage();
   278   image->SetData(cairoData);
   280   MonitorAutoLock mon(mMonitor);
   281   mImage = image;
   282 }
   284 nsresult
   285 MediaEngineTabVideoSource::Stop(mozilla::SourceMediaStream*, mozilla::TrackID)
   286 {
   287   NS_DispatchToMainThread(new StopRunnable(this));
   288   return NS_OK;
   289 }
   291 nsresult
   292 MediaEngineTabVideoSource::Config(bool, uint32_t, bool, uint32_t, bool, uint32_t, int32_t)
   293 {
   294   return NS_OK;
   295 }
   297 bool
   298 MediaEngineTabVideoSource::IsFake()
   299 {
   300   return false;
   301 }
   303 }

mercurial