Bug 1449832 - P1 - screen share scale when a single dimension constraint is supplied draft
authorNico Grunbaum <na-g@nostrum.com>
Wed, 04 Apr 2018 17:49:09 -0700
changeset 781391 105e361d465933fa863a5396eb90cd495175f32e
parent 781262 516c4fb1e4b862b78a40c472e4d61dea79d51890
child 781392 f3f70536c5c710365c40387ab7243c365ca24098
push id106290
push userbmo:na-g@nostrum.com
push dateThu, 12 Apr 2018 21:57:43 +0000
bugs1449832
milestone61.0a1
Bug 1449832 - P1 - screen share scale when a single dimension constraint is supplied MozReview-Commit-ID: LSce4YaUoDP
dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
--- a/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
+++ b/dom/media/webrtc/MediaEngineRemoteVideoSource.cpp
@@ -476,16 +476,49 @@ MediaEngineRemoteVideoSource::Pull(const
 
   // This is safe from any thread, and is safe if the track is Finished
   // or Destroyed.
   // This can fail if either a) we haven't added the track yet, or b)
   // we've removed or finished the track.
   aStream->AppendToTrack(aTrackID, &segment);
 }
 
+// Translate screen share aspect ratio to constraint aspect ratio if only a
+// single dimension constraint is supplied.
+inline void
+preserveScreenShareAspectRatio(int32_t& aConstraintWidth,
+                               int32_t& aConstraintHeight,
+                               const camera::VideoFrameProperties& aProps)
+{
+  if ((aConstraintHeight && aConstraintWidth) ||
+      (!aConstraintWidth && !aConstraintHeight) ||
+      !aProps.height() || !aProps.width()) {
+    return;
+  }
+  int32_t gcd = EuclidGCD(aProps.width(), aProps.height());
+  int32_t minWidth = aProps.width() / gcd;
+  int32_t minHeight = aProps.height() / gcd;
+  MOZ_ASSERT(minWidth && minHeight);
+  if (aConstraintHeight) {
+    // Clamp height to multiple of the unit height
+    aConstraintHeight -= (aConstraintHeight % minHeight);
+    // Apply aspect ratio in unit widths
+    aConstraintWidth = minWidth * aConstraintHeight / minHeight;
+  } else {
+    // Clamp width to multiple of the unit width
+    aConstraintWidth -= (aConstraintWidth % minWidth);
+    // Apply aspect ratio in unit heights
+    aConstraintHeight = minHeight * aConstraintWidth / minWidth;
+  }
+  if (aConstraintWidth < minWidth || aConstraintHeight < minHeight) {
+    aConstraintHeight = minHeight;
+    aConstraintWidth = minWidth;
+  }
+}
+
 int
 MediaEngineRemoteVideoSource::DeliverFrame(uint8_t* aBuffer,
                                            const camera::VideoFrameProperties& aProps)
 {
   // Cameras IPC thread - take great care with accessing members!
 
   int32_t req_max_width;
   int32_t req_max_height;
@@ -494,17 +527,30 @@ MediaEngineRemoteVideoSource::DeliverFra
   {
     MutexAutoLock lock(mMutex);
     MOZ_ASSERT(mState == kStarted);
     req_max_width = mCapability.width & 0xffff;
     req_max_height = mCapability.height & 0xffff;
     req_ideal_width = (mCapability.width >> 16) & 0xffff;
     req_ideal_height = (mCapability.height >> 16) & 0xffff;
   }
-
+  // See bug Bug 1453269
+  switch (mMediaSource) {
+    case MediaSourceEnum::Screen:
+    case MediaSourceEnum::Window:
+    case MediaSourceEnum::Application: {
+      // Preserve aspect ratio for screen sharing if only a single dimension
+      // is supplied.
+      preserveScreenShareAspectRatio(req_max_width, req_max_height, aProps);
+      preserveScreenShareAspectRatio(req_ideal_width, req_ideal_height, aProps);
+    }
+    default: {
+      break;
+    }
+  }
   if (aProps.rotation() == 90 || aProps.rotation() == 270) {
     // This frame is rotated, so what was negotiated as width is now height,
     // and vice versa.
     std::swap(req_max_width, req_max_height);
     std::swap(req_ideal_width, req_ideal_height);
   }
 
   int32_t dst_max_width = std::min(req_max_width, aProps.width());