bug 1116856 - dynamically resize tab mirror video stream based on window size r=rjesup
authorBrad Lassey <blassey@mozilla.com>
Tue, 20 Jan 2015 14:54:19 -0500
changeset 253572 c74a032abad8a43152e0148ff480e9558e05b353
parent 253571 6334e1780232adeea85cc73d366a3b5f111f465c
child 253573 6be66b7371169083e116f6abb63fd091b8917ba4
push id721
push userjlund@mozilla.com
push dateTue, 21 Apr 2015 23:03:33 +0000
treeherdermozilla-release@d27c9211ebb3 [default view] [failures only]
perfherder[talos] [build metrics] [platform microbench] (compared to previous push)
reviewersrjesup
bugs1116856
milestone38.0a1
first release with
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
last release without
nightly linux32
nightly linux64
nightly mac
nightly win32
nightly win64
bug 1116856 - dynamically resize tab mirror video stream based on window size r=rjesup
dom/media/webrtc/MediaEngineTabVideoSource.cpp
dom/media/webrtc/MediaEngineTabVideoSource.h
--- a/dom/media/webrtc/MediaEngineTabVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.cpp
@@ -27,17 +27,17 @@
 namespace mozilla {
 
 using namespace mozilla::gfx;
 using dom::ConstrainLongRange;
 
 NS_IMPL_ISUPPORTS(MediaEngineTabVideoSource, nsIDOMEventListener, nsITimerCallback)
 
 MediaEngineTabVideoSource::MediaEngineTabVideoSource()
-: mMonitor("MediaEngineTabVideoSource"), mTabSource(nullptr)
+: mMonitor("MediaEngineTabVideoSource"), mTabSource(nullptr), mDataSize(0), mData(NULL)
 {
 }
 
 nsresult
 MediaEngineTabVideoSource::StartRunnable::Run()
 {
   mVideoSource->Draw();
   mVideoSource->mTimer = do_CreateInstance(NS_TIMER_CONTRACTID);
@@ -74,17 +74,16 @@ MediaEngineTabVideoSource::Notify(nsITim
   Draw();
   return NS_OK;
 }
 #define LOGTAG "TabVideo"
 
 nsresult
 MediaEngineTabVideoSource::InitRunnable::Run()
 {
-  mVideoSource->mData = (unsigned char*)malloc(mVideoSource->mBufW * mVideoSource->mBufH * 4);
   if (mVideoSource->mWindowId != -1) {
     nsCOMPtr<nsPIDOMWindow> window  = nsGlobalWindow::GetOuterWindowWithId(mVideoSource->mWindowId);
     if (window) {
       mVideoSource->mWindow = window;
     }
   }
   if (!mVideoSource->mWindow) {
     nsresult rv;
@@ -145,30 +144,20 @@ MediaEngineTabVideoSource::Allocate(cons
 
       if (!haveScrollWithPage && advanced[i].mScrollWithPage.WasPassed()) {
         mScrollWithPage = advanced[i].mScrollWithPage.Value();
         haveScrollWithPage = true;
       }
     }
   }
 
-  mBufW = aPrefs.GetWidth(false);
-  mBufH = aPrefs.GetHeight(false);
+  ConstrainLongRange defaultRange;
 
-  if (cWidth.mMin > mBufW) {
-    mBufW = cWidth.mMin;
-  } else if (cWidth.mMax < mBufW) {
-    mBufW = cWidth.mMax;
-  }
-
-  if (cHeight.mMin > mBufH) {
-    mBufH = cHeight.mMin;
-  } else if (cHeight.mMax < mBufH) {
-    mBufH = cHeight.mMax;
-  }
+  mBufWidthMax  = defaultRange.mMax > cWidth.mMax ? cWidth.mMax : aPrefs.GetWidth(false);
+  mBufHeightMax  = defaultRange.mMax > cHeight.mMax ? cHeight.mMax : aPrefs.GetHeight(false);
 
   mTimePerFrame = aPrefs.mFPS ? 1000 / aPrefs.mFPS : aPrefs.mFPS;
   return NS_OK;
 }
 
 nsresult
 MediaEngineTabVideoSource::Deallocate()
 {
@@ -208,45 +197,48 @@ MediaEngineTabVideoSource::NotifyPull(Me
     // This can fail if either a) we haven't added the track yet, or b)
     // we've removed or finished the track.
     aSource->AppendToTrack(aID, &(segment));
   }
 }
 
 void
 MediaEngineTabVideoSource::Draw() {
-
-  IntSize size(mBufW, mBufH);
-
-  nsresult rv;
-
   nsCOMPtr<nsPIDOMWindow> win = do_QueryInterface(mWindow);
 
   if (!win) {
     return;
   }
 
-  int32_t width, height;
-  win->GetInnerWidth(&width);
-  win->GetInnerHeight(&height);
+  int32_t innerWidth, innerHeight;
+  win->GetInnerWidth(&innerWidth);
+  win->GetInnerHeight(&innerHeight);
 
-  if (width == 0 || height == 0) {
+  if (innerWidth == 0 || innerHeight == 0) {
     return;
   }
 
-  int32_t srcW;
-  int32_t srcH;
+  IntSize size;
+  // maintain source aspect ratio
+  if (mBufWidthMax/innerWidth < mBufHeightMax/innerHeight) {
+    size = IntSize(mBufWidthMax, (mBufWidthMax * ((float) innerHeight/innerWidth)));
+  } else {
+    size = IntSize((mBufHeightMax * ((float) innerWidth/innerHeight)), mBufHeightMax);
+  }
 
-  float aspectRatio = ((float) size.width) / size.height;
-  if (width / aspectRatio < height) {
-    srcW = width;
-    srcH = width / aspectRatio;
-  } else {
-    srcW = height * aspectRatio;
-    srcH = height;
+  gfxImageFormat format = gfxImageFormat::RGB24;
+  uint32_t stride = gfxASurface::FormatStrideForWidth(format, size.width);
+
+  if (mDataSize < static_cast<size_t>(stride * size.height)) {
+    mDataSize = stride * size.height;
+    mData = static_cast<unsigned char*>(malloc(mDataSize));
+  }
+
+  if (!mData) {
+    return;
   }
 
   nsRefPtr<nsPresContext> presContext;
   nsIDocShell* docshell = win->GetDocShell();
   if (docshell) {
     docshell->GetPresContext(getter_AddRefs(presContext));
   }
   if (!presContext) {
@@ -254,39 +246,34 @@ MediaEngineTabVideoSource::Draw() {
   }
 
   nscolor bgColor = NS_RGB(255, 255, 255);
   nsCOMPtr<nsIPresShell> presShell = presContext->PresShell();
   uint32_t renderDocFlags = 0;
   if (!mScrollWithPage) {
     renderDocFlags |= nsIPresShell::RENDER_IGNORE_VIEWPORT_SCROLLING;
   }
-  nsRect r(0, 0, nsPresContext::CSSPixelsToAppUnits((float)srcW),
-           nsPresContext::CSSPixelsToAppUnits((float)srcH));
-
-  gfxImageFormat format = gfxImageFormat::RGB24;
-  uint32_t stride = gfxASurface::FormatStrideForWidth(format, size.width);
+  nsRect r(0, 0, nsPresContext::CSSPixelsToAppUnits((float)innerWidth),
+           nsPresContext::CSSPixelsToAppUnits((float)innerHeight));
 
   nsRefPtr<layers::ImageContainer> container = layers::LayerManager::CreateImageContainer();
   RefPtr<DrawTarget> dt =
     Factory::CreateDrawTargetForData(BackendType::CAIRO,
                                      mData.rwget(),
                                      size,
                                      stride,
                                      SurfaceFormat::B8G8R8X8);
   if (!dt) {
     return;
   }
   nsRefPtr<gfxContext> context = new gfxContext(dt);
-  context->SetMatrix(context->CurrentMatrix().Scale((float)size.width/srcW,
-                                                    (float)size.height/srcH));
+  context->SetMatrix(context->CurrentMatrix().Scale((((float) size.width)/innerWidth),
+                                                    (((float) size.height)/innerHeight)));
 
-  rv = presShell->RenderDocument(r, renderDocFlags, bgColor, context);
-
-  NS_ENSURE_SUCCESS_VOID(rv);
+  NS_ENSURE_SUCCESS_VOID(presShell->RenderDocument(r, renderDocFlags, bgColor, context));
 
   RefPtr<SourceSurface> surface = dt->Snapshot();
   if (!surface) {
     return;
   }
 
   layers::CairoImage::Data cairoData;
   cairoData.mSize = size;
--- a/dom/media/webrtc/MediaEngineTabVideoSource.h
+++ b/dom/media/webrtc/MediaEngineTabVideoSource.h
@@ -65,21 +65,22 @@ class MediaEngineTabVideoSource : public
       NS_IMETHOD Run();
       nsRefPtr<MediaEngineTabVideoSource> mVideoSource;
     };
 
 protected:
     ~MediaEngineTabVideoSource() {}
 
 private:
-    int mBufW;
-    int mBufH;
+    int mBufWidthMax;
+    int mBufHeightMax;
     int64_t mWindowId;
     bool mScrollWithPage;
     int mTimePerFrame;
     ScopedFreePtr<unsigned char> mData;
+    size_t mDataSize;
     nsCOMPtr<nsIDOMWindow> mWindow;
     nsRefPtr<layers::CairoImage> mImage;
     nsCOMPtr<nsITimer> mTimer;
     Monitor mMonitor;
     nsCOMPtr<nsITabSource> mTabSource;
   };
 }