LCOV - code coverage report
Current view: top level - dom/media/webrtc - MediaEngineTabVideoSource.cpp (source / functions) Hit Total Coverage
Test: output.info Lines: 0 182 0.0 %
Date: 2017-07-14 16:53:18 Functions: 0 20 0.0 %
Legend: Lines: hit not hit

          Line data    Source code
       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/. */
       5             : 
       6             : #include "MediaEngineTabVideoSource.h"
       7             : 
       8             : #include "mozilla/gfx/2D.h"
       9             : #include "mozilla/gfx/DataSurfaceHelpers.h"
      10             : #include "mozilla/RefPtr.h"
      11             : #include "mozilla/UniquePtrExtensions.h"
      12             : #include "mozilla/dom/BindingDeclarations.h"
      13             : #include "nsGlobalWindow.h"
      14             : #include "nsIDOMClientRect.h"
      15             : #include "nsIDocShell.h"
      16             : #include "nsIPresShell.h"
      17             : #include "nsPresContext.h"
      18             : #include "gfxContext.h"
      19             : #include "gfx2DGlue.h"
      20             : #include "ImageContainer.h"
      21             : #include "Layers.h"
      22             : #include "nsIInterfaceRequestorUtils.h"
      23             : #include "nsIDOMDocument.h"
      24             : #include "nsITabSource.h"
      25             : #include "VideoUtils.h"
      26             : #include "nsServiceManagerUtils.h"
      27             : #include "nsIPrefService.h"
      28             : #include "MediaTrackConstraints.h"
      29             : 
      30             : namespace mozilla {
      31             : 
      32             : using namespace mozilla::gfx;
      33             : 
      34           0 : NS_IMPL_ISUPPORTS(MediaEngineTabVideoSource, nsIDOMEventListener, nsITimerCallback)
      35             : 
      36           0 : MediaEngineTabVideoSource::MediaEngineTabVideoSource()
      37             :   : mBufWidthMax(0)
      38             :   , mBufHeightMax(0)
      39             :   , mWindowId(0)
      40             :   , mScrollWithPage(false)
      41             :   , mViewportOffsetX(0)
      42             :   , mViewportOffsetY(0)
      43             :   , mViewportWidth(0)
      44             :   , mViewportHeight(0)
      45             :   , mTimePerFrame(0)
      46             :   , mDataSize(0)
      47             :   , mBlackedoutWindow(false)
      48           0 :   , mMonitor("MediaEngineTabVideoSource") {}
      49             : 
      50             : nsresult
      51           0 : MediaEngineTabVideoSource::StartRunnable::Run()
      52             : {
      53           0 :   mVideoSource->Draw();
      54           0 :   mVideoSource->mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
      55           0 :   mVideoSource->mTimer->InitWithCallback(mVideoSource, mVideoSource->mTimePerFrame, nsITimer:: TYPE_REPEATING_SLACK);
      56           0 :   if (mVideoSource->mTabSource) {
      57           0 :     mVideoSource->mTabSource->NotifyStreamStart(mVideoSource->mWindow);
      58             :   }
      59           0 :   return NS_OK;
      60             : }
      61             : 
      62             : nsresult
      63           0 : MediaEngineTabVideoSource::StopRunnable::Run()
      64             : {
      65           0 :   if (mVideoSource->mTimer) {
      66           0 :     mVideoSource->mTimer->Cancel();
      67           0 :     mVideoSource->mTimer = nullptr;
      68             :   }
      69           0 :   if (mVideoSource->mTabSource) {
      70           0 :     mVideoSource->mTabSource->NotifyStreamStop(mVideoSource->mWindow);
      71             :   }
      72           0 :   return NS_OK;
      73             : }
      74             : 
      75             : NS_IMETHODIMP
      76           0 : MediaEngineTabVideoSource::HandleEvent(nsIDOMEvent *event) {
      77           0 :   Draw();
      78           0 :   return NS_OK;
      79             : }
      80             : 
      81             : NS_IMETHODIMP
      82           0 : MediaEngineTabVideoSource::Notify(nsITimer*) {
      83           0 :   Draw();
      84           0 :   return NS_OK;
      85             : }
      86             : 
      87             : nsresult
      88           0 : MediaEngineTabVideoSource::InitRunnable::Run()
      89             : {
      90           0 :   if (mVideoSource->mWindowId != -1) {
      91             :     nsGlobalWindow* globalWindow =
      92           0 :       nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId);
      93           0 :     if (!globalWindow) {
      94             :       // We can't access the window, just send a blacked out screen.
      95           0 :       mVideoSource->mWindow = nullptr;
      96           0 :       mVideoSource->mBlackedoutWindow = true;
      97             :     } else {
      98           0 :       nsCOMPtr<nsPIDOMWindowOuter> window = globalWindow->AsOuter();
      99           0 :       if (window) {
     100           0 :         mVideoSource->mWindow = window;
     101           0 :         mVideoSource->mBlackedoutWindow = false;
     102             :       }
     103             :     }
     104             :   }
     105           0 :   if (!mVideoSource->mWindow && !mVideoSource->mBlackedoutWindow) {
     106             :     nsresult rv;
     107           0 :     mVideoSource->mTabSource = do_GetService(NS_TABSOURCESERVICE_CONTRACTID, &rv);
     108           0 :     NS_ENSURE_SUCCESS(rv, rv);
     109             : 
     110           0 :     nsCOMPtr<mozIDOMWindowProxy> win;
     111           0 :     rv = mVideoSource->mTabSource->GetTabToStream(getter_AddRefs(win));
     112           0 :     NS_ENSURE_SUCCESS(rv, rv);
     113           0 :     if (!win)
     114           0 :       return NS_OK;
     115             : 
     116           0 :     mVideoSource->mWindow = nsPIDOMWindowOuter::From(win);
     117           0 :     MOZ_ASSERT(mVideoSource->mWindow);
     118             :   }
     119           0 :   nsCOMPtr<nsIRunnable> start(new StartRunnable(mVideoSource));
     120           0 :   start->Run();
     121           0 :   return NS_OK;
     122             : }
     123             : 
     124             : nsresult
     125           0 : MediaEngineTabVideoSource::DestroyRunnable::Run()
     126             : {
     127           0 :   MOZ_ASSERT(NS_IsMainThread());
     128             : 
     129           0 :   mVideoSource->mWindow = nullptr;
     130           0 :   mVideoSource->mTabSource = nullptr;
     131             : 
     132           0 :   return NS_OK;
     133             : }
     134             : 
     135             : void
     136           0 : MediaEngineTabVideoSource::GetName(nsAString& aName) const
     137             : {
     138           0 :   aName.AssignLiteral(u"&getUserMedia.videoSource.tabShare;");
     139           0 : }
     140             : 
     141             : void
     142           0 : MediaEngineTabVideoSource::GetUUID(nsACString& aUuid) const
     143             : {
     144           0 :   aUuid.AssignLiteral("tab");
     145           0 : }
     146             : 
     147             : #define DEFAULT_TABSHARE_VIDEO_MAX_WIDTH 4096
     148             : #define DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT 4096
     149             : #define DEFAULT_TABSHARE_VIDEO_FRAMERATE 30
     150             : 
     151             : nsresult
     152           0 : MediaEngineTabVideoSource::Allocate(const dom::MediaTrackConstraints& aConstraints,
     153             :                                     const MediaEnginePrefs& aPrefs,
     154             :                                     const nsString& aDeviceId,
     155             :                                     const mozilla::ipc::PrincipalInfo& aPrincipalInfo,
     156             :                                     AllocationHandle** aOutHandle,
     157             :                                     const char** aOutBadConstraint)
     158             : {
     159             :   // windowId is not a proper constraint, so just read it.
     160             :   // It has no well-defined behavior in advanced, so ignore it there.
     161             : 
     162           0 :   mWindowId = aConstraints.mBrowserWindow.WasPassed() ?
     163           0 :               aConstraints.mBrowserWindow.Value() : -1;
     164           0 :   *aOutHandle = nullptr;
     165             : 
     166             :   {
     167           0 :     MonitorAutoLock mon(mMonitor);
     168           0 :     mState = kAllocated;
     169             :   }
     170             : 
     171           0 :   return Restart(nullptr, aConstraints, aPrefs, aDeviceId, aOutBadConstraint);
     172             : }
     173             : 
     174             : nsresult
     175           0 : MediaEngineTabVideoSource::Restart(AllocationHandle* aHandle,
     176             :                                    const dom::MediaTrackConstraints& aConstraints,
     177             :                                    const mozilla::MediaEnginePrefs& aPrefs,
     178             :                                    const nsString& aDeviceId,
     179             :                                    const char** aOutBadConstraint)
     180             : {
     181           0 :   MOZ_ASSERT(!aHandle);
     182             : 
     183             :   // scrollWithPage is not proper a constraint, so just read it.
     184             :   // It has no well-defined behavior in advanced, so ignore it there.
     185             : 
     186           0 :   mScrollWithPage = aConstraints.mScrollWithPage.WasPassed() ?
     187           0 :                     aConstraints.mScrollWithPage.Value() : false;
     188             : 
     189           0 :   FlattenedConstraints c(aConstraints);
     190             : 
     191           0 :   mBufWidthMax = c.mWidth.Get(DEFAULT_TABSHARE_VIDEO_MAX_WIDTH);
     192           0 :   mBufHeightMax = c.mHeight.Get(DEFAULT_TABSHARE_VIDEO_MAX_HEIGHT);
     193           0 :   double frameRate = c.mFrameRate.Get(DEFAULT_TABSHARE_VIDEO_FRAMERATE);
     194           0 :   mTimePerFrame = std::max(10, int(1000.0 / (frameRate > 0? frameRate : 1)));
     195             : 
     196           0 :   if (!mScrollWithPage) {
     197           0 :     mViewportOffsetX = c.mViewportOffsetX.Get(0);
     198           0 :     mViewportOffsetY = c.mViewportOffsetY.Get(0);
     199           0 :     mViewportWidth = c.mViewportWidth.Get(INT32_MAX);
     200           0 :     mViewportHeight = c.mViewportHeight.Get(INT32_MAX);
     201             :   }
     202           0 :   return NS_OK;
     203             : }
     204             : 
     205             : nsresult
     206           0 : MediaEngineTabVideoSource::Deallocate(AllocationHandle* aHandle)
     207             : {
     208           0 :   MOZ_ASSERT(!aHandle);
     209           0 :   NS_DispatchToMainThread(do_AddRef(new DestroyRunnable(this)));
     210             : 
     211             :   {
     212           0 :     MonitorAutoLock mon(mMonitor);
     213           0 :     mState = kReleased;
     214             :   }
     215           0 :   return NS_OK;
     216             : }
     217             : 
     218             : nsresult
     219           0 : MediaEngineTabVideoSource::Start(SourceMediaStream* aStream, TrackID aID,
     220             :                                  const PrincipalHandle& aPrincipalHandle)
     221             : {
     222           0 :   nsCOMPtr<nsIRunnable> runnable;
     223           0 :   if (!mWindow)
     224           0 :     runnable = new InitRunnable(this);
     225             :   else
     226           0 :     runnable = new StartRunnable(this);
     227           0 :   NS_DispatchToMainThread(runnable);
     228           0 :   aStream->AddTrack(aID, 0, new VideoSegment());
     229             : 
     230             :   {
     231           0 :     MonitorAutoLock mon(mMonitor);
     232           0 :     mState = kStarted;
     233             :   }
     234             : 
     235           0 :   return NS_OK;
     236             : }
     237             : 
     238             : void
     239           0 : MediaEngineTabVideoSource::NotifyPull(MediaStreamGraph*,
     240             :                                       SourceMediaStream* aSource,
     241             :                                       TrackID aID, StreamTime aDesiredTime,
     242             :                                       const PrincipalHandle& aPrincipalHandle)
     243             : {
     244           0 :   VideoSegment segment;
     245           0 :   MonitorAutoLock mon(mMonitor);
     246           0 :   if (mState != kStarted) {
     247           0 :     return;
     248             :   }
     249             : 
     250             :   // Note: we're not giving up mImage here
     251           0 :   RefPtr<layers::SourceSurfaceImage> image = mImage;
     252           0 :   StreamTime delta = aDesiredTime - aSource->GetEndOfAppendedData(aID);
     253           0 :   if (delta > 0) {
     254             :     // nullptr images are allowed
     255           0 :     gfx::IntSize size = image ? image->GetSize() : IntSize(0, 0);
     256           0 :     segment.AppendFrame(image.forget().downcast<layers::Image>(), delta, size,
     257           0 :                         aPrincipalHandle);
     258             :     // This can fail if either a) we haven't added the track yet, or b)
     259             :     // we've removed or finished the track.
     260           0 :     aSource->AppendToTrack(aID, &(segment));
     261             :   }
     262             : }
     263             : 
     264             : void
     265           0 : MediaEngineTabVideoSource::Draw() {
     266           0 :   if (!mWindow && !mBlackedoutWindow) {
     267           0 :     return;
     268             :   }
     269             : 
     270           0 :   if (mWindow) {
     271           0 :     if (mScrollWithPage || mViewportWidth == INT32_MAX) {
     272           0 :       mWindow->GetInnerWidth(&mViewportWidth);
     273             :     }
     274           0 :     if (mScrollWithPage || mViewportHeight == INT32_MAX) {
     275           0 :       mWindow->GetInnerHeight(&mViewportHeight);
     276             :     }
     277           0 :     if (!mViewportWidth || !mViewportHeight) {
     278           0 :       return;
     279             :     }
     280             :   } else {
     281           0 :     mViewportWidth = 640;
     282           0 :     mViewportHeight = 480;
     283             :   }
     284             : 
     285           0 :   IntSize size;
     286             :   {
     287             :     float pixelRatio;
     288           0 :     if (mWindow) {
     289           0 :       pixelRatio = mWindow->GetDevicePixelRatio(CallerType::System);
     290             :     } else {
     291           0 :       pixelRatio = 1.0f;
     292             :     }
     293           0 :     const int32_t deviceWidth = (int32_t)(pixelRatio * mViewportWidth);
     294           0 :     const int32_t deviceHeight = (int32_t)(pixelRatio * mViewportHeight);
     295             : 
     296           0 :     if ((deviceWidth <= mBufWidthMax) && (deviceHeight <= mBufHeightMax)) {
     297           0 :       size = IntSize(deviceWidth, deviceHeight);
     298             :     } else {
     299           0 :       const float scaleWidth = (float)mBufWidthMax / (float)deviceWidth;
     300           0 :       const float scaleHeight = (float)mBufHeightMax / (float)deviceHeight;
     301           0 :       const float scale = scaleWidth < scaleHeight ? scaleWidth : scaleHeight;
     302             : 
     303           0 :       size = IntSize((int)(scale * deviceWidth), (int)(scale * deviceHeight));
     304             :     }
     305             :   }
     306             : 
     307           0 :   uint32_t stride = StrideForFormatAndWidth(SurfaceFormat::X8R8G8B8_UINT32,
     308           0 :                                             size.width);
     309             : 
     310           0 :   if (mDataSize < static_cast<size_t>(stride * size.height)) {
     311           0 :     mDataSize = stride * size.height;
     312           0 :     mData = MakeUniqueFallible<unsigned char[]>(mDataSize);
     313             :   }
     314           0 :   if (!mData) {
     315           0 :     return;
     316             :   }
     317             : 
     318           0 :   nsCOMPtr<nsIPresShell> presShell;
     319           0 :   if (mWindow) {
     320           0 :     RefPtr<nsPresContext> presContext;
     321           0 :     nsIDocShell* docshell = mWindow->GetDocShell();
     322           0 :     if (docshell) {
     323           0 :       docshell->GetPresContext(getter_AddRefs(presContext));
     324             :     }
     325           0 :     if (!presContext) {
     326           0 :       return;
     327             :     }
     328           0 :     presShell = presContext->PresShell();
     329             :   }
     330             : 
     331             :   RefPtr<layers::ImageContainer> container =
     332           0 :     layers::LayerManager::CreateImageContainer(layers::ImageContainer::ASYNCHRONOUS);
     333             :   RefPtr<DrawTarget> dt =
     334           0 :     Factory::CreateDrawTargetForData(gfxPlatform::GetPlatform()->GetSoftwareBackend(),
     335             :                                      mData.get(),
     336             :                                      size,
     337             :                                      stride,
     338             :                                      SurfaceFormat::B8G8R8X8,
     339           0 :                                      true);
     340           0 :   if (!dt || !dt->IsValid()) {
     341           0 :     return;
     342             :   }
     343             : 
     344           0 :   if (mWindow) {
     345           0 :     RefPtr<gfxContext> context = gfxContext::CreateOrNull(dt);
     346           0 :     MOZ_ASSERT(context); // already checked the draw target above
     347           0 :     context->SetMatrix(context->CurrentMatrix().PreScale((((float) size.width)/mViewportWidth),
     348           0 :                                                          (((float) size.height)/mViewportHeight)));
     349             : 
     350           0 :     nscolor bgColor = NS_RGB(255, 255, 255);
     351           0 :     uint32_t renderDocFlags = mScrollWithPage? 0 :
     352             :       (nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING |
     353           0 :        nsIPresShell::RENDER_DOCUMENT_RELATIVE);
     354           0 :     nsRect r(nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetX),
     355           0 :              nsPresContext::CSSPixelsToAppUnits((float)mViewportOffsetY),
     356           0 :              nsPresContext::CSSPixelsToAppUnits((float)mViewportWidth),
     357           0 :              nsPresContext::CSSPixelsToAppUnits((float)mViewportHeight));
     358           0 :     NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
     359             :   } else {
     360           0 :     dt->ClearRect(Rect(0, 0, size.width, size.height));
     361             :   }
     362             : 
     363           0 :   RefPtr<SourceSurface> surface = dt->Snapshot();
     364           0 :   if (!surface) {
     365           0 :     return;
     366             :   }
     367             : 
     368           0 :   RefPtr<layers::SourceSurfaceImage> image = new layers::SourceSurfaceImage(size, surface);
     369             : 
     370           0 :   MonitorAutoLock mon(mMonitor);
     371           0 :   mImage = image;
     372             : }
     373             : 
     374             : nsresult
     375           0 : MediaEngineTabVideoSource::Stop(mozilla::SourceMediaStream* aSource,
     376             :                                 mozilla::TrackID aID)
     377             : {
     378             :   // If mBlackedoutWindow is true, we may be running
     379             :   // despite mWindow == nullptr.
     380           0 :   if (!mWindow && !mBlackedoutWindow) {
     381           0 :     return NS_OK;
     382             :   }
     383             : 
     384           0 :   NS_DispatchToMainThread(new StopRunnable(this));
     385             : 
     386             :   {
     387           0 :     MonitorAutoLock mon(mMonitor);
     388           0 :     mState = kStopped;
     389           0 :     aSource->EndTrack(aID);
     390             :   }
     391           0 :   return NS_OK;
     392             : }
     393             : 
     394             : bool
     395           0 : MediaEngineTabVideoSource::IsFake()
     396             : {
     397           0 :   return false;
     398             : }
     399             : 
     400             : }

Generated by: LCOV version 1.13