Title: [239016] trunk
Revision
239016
Author
eric.carl...@apple.com
Date
2018-12-08 21:36:43 -0800 (Sat, 08 Dec 2018)

Log Message

[MediaStream] Scaled video frames should be resized in letterbox mode
https://bugs.webkit.org/show_bug.cgi?id=192528
<rdar://problem/46576638>

Reviewed by Darin Adler.

Source/WebCore:

Test: fast/mediastream/resize-letterbox.html

* platform/graphics/cv/ImageTransferSessionVT.mm:
(WebCore::ImageTransferSessionVT::ImageTransferSessionVT): Use letterbox resize mode, not trim.

* platform/mock/MockRealtimeVideoSource.cpp:
(WebCore::MockRealtimeVideoSource::captureSize const): "Capture" at the preset size, not
necessarily at the requested size to be more like a physical camera.
(WebCore::MockRealtimeVideoSource::settingsDidChange):
(WebCore::MockRealtimeVideoSource::drawAnimation):
(WebCore::MockRealtimeVideoSource::drawBoxes):
(WebCore::MockRealtimeVideoSource::drawText):
(WebCore::MockRealtimeVideoSource::generateFrame):
(WebCore::MockRealtimeVideoSource::imageBuffer const):
* platform/mock/MockRealtimeVideoSource.h:

LayoutTests:

* fast/mediastream/resize-letterbox-expected.txt: Added.
* fast/mediastream/resize-letterbox.html: Added.

Modified Paths

Added Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (239015 => 239016)


--- trunk/LayoutTests/ChangeLog	2018-12-09 04:11:48 UTC (rev 239015)
+++ trunk/LayoutTests/ChangeLog	2018-12-09 05:36:43 UTC (rev 239016)
@@ -1,3 +1,14 @@
+2018-12-08  Eric Carlson  <eric.carl...@apple.com>
+
+        [MediaStream] Scaled video frames should be resized in letterbox mode
+        https://bugs.webkit.org/show_bug.cgi?id=192528
+        <rdar://problem/46576638>
+
+        Reviewed by Darin Adler.
+
+        * fast/mediastream/resize-letterbox-expected.txt: Added.
+        * fast/mediastream/resize-letterbox.html: Added.
+
 2018-12-08  Simon Fraser  <simon.fra...@apple.com>
 
         Allow control over child order when adding nodes to the scrolling tree

Added: trunk/LayoutTests/fast/mediastream/resize-letterbox-expected.txt (0 => 239016)


--- trunk/LayoutTests/fast/mediastream/resize-letterbox-expected.txt	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/resize-letterbox-expected.txt	2018-12-09 05:36:43 UTC (rev 239016)
@@ -0,0 +1,4 @@
+
+
+PASS Video frames are resized in letterbox-mode when captured at non-native size. 
+

Added: trunk/LayoutTests/fast/mediastream/resize-letterbox.html (0 => 239016)


--- trunk/LayoutTests/fast/mediastream/resize-letterbox.html	                        (rev 0)
+++ trunk/LayoutTests/fast/mediastream/resize-letterbox.html	2018-12-09 05:36:43 UTC (rev 239016)
@@ -0,0 +1,67 @@
+<!DOCTYPE html>
+<html>
+    <head>
+        <video id="video" autoplay width=480px height=480px controls ></video>
+        <canvas id="canvas" width=480px height=480px></canvas>
+        <script src=""
+        <script src=""
+        <script>
+
+const canvas = document.getElementById("canvas");
+const video = document.getElementById("video");
+
+function isPixelBlack(pixel)
+{
+    return pixel[0] === 0 && pixel[1] === 0 && pixel[2] === 0 && pixel[3] === 255;
+}
+
+function isPixelGray(pixel)
+{
+    return pixel[0] === 128 && pixel[1] === 128 && pixel[2] === 128 && pixel[3] === 255;
+}
+
+function logPixel(name, pixel)
+{
+    console.log(`${name}: ${pixel[0]}, ${pixel[1]}, ${pixel[2]}, ${pixel[3]}`);
+}
+
+function checkCanvas(canvas, stream)
+{
+    return new Promise((resolve, reject) => {
+        video.srcObject = stream;
+        video._onplay_ = () => {
+            const ctx = canvas.getContext("2d");
+            ctx.drawImage(video, 0 ,0);
+
+            try {
+                setTimeout(() => {
+                    assert_true(isPixelBlack(ctx.getImageData(5, 5, 1, 1).data), "Pixel at 5x5 is NOT from camera.");
+                    assert_true(isPixelGray(ctx.getImageData(50, 200, 1, 1).data), "Pixel at 50x200 is from camera.");
+                    resolve();
+                }, 500);
+            } catch(err) {
+                reject(err);
+                return;
+            }
+        }
+    });
+}
+
+promise_test(async () => {
+    let stream = await navigator.mediaDevices.getUserMedia({ video: true });
+    stream = null;
+
+    const devices = await navigator.mediaDevices.enumerateDevices();
+    let cameraID = undefined;
+    devices.forEach(device => { if (device.label == "Mock video device 2") cameraID = device.deviceId; });
+    assert_true(cameraID !== undefined, "Found camera2");
+    
+    stream = await navigator.mediaDevices.getUserMedia({ video: { deviceId: { exact: cameraID }, width: 480, height: 480 } });
+    
+    return checkCanvas(canvas, stream);
+
+}, "Video frames are resized in letterbox-mode when captured at non-native size.");
+
+        </script>
+    </head>
+</html>

Modified: trunk/Source/WebCore/ChangeLog (239015 => 239016)


--- trunk/Source/WebCore/ChangeLog	2018-12-09 04:11:48 UTC (rev 239015)
+++ trunk/Source/WebCore/ChangeLog	2018-12-09 05:36:43 UTC (rev 239016)
@@ -1,3 +1,27 @@
+2018-12-08  Eric Carlson  <eric.carl...@apple.com>
+
+        [MediaStream] Scaled video frames should be resized in letterbox mode
+        https://bugs.webkit.org/show_bug.cgi?id=192528
+        <rdar://problem/46576638>
+
+        Reviewed by Darin Adler.
+
+        Test: fast/mediastream/resize-letterbox.html
+
+        * platform/graphics/cv/ImageTransferSessionVT.mm:
+        (WebCore::ImageTransferSessionVT::ImageTransferSessionVT): Use letterbox resize mode, not trim.
+
+        * platform/mock/MockRealtimeVideoSource.cpp:
+        (WebCore::MockRealtimeVideoSource::captureSize const): "Capture" at the preset size, not 
+        necessarily at the requested size to be more like a physical camera.
+        (WebCore::MockRealtimeVideoSource::settingsDidChange):
+        (WebCore::MockRealtimeVideoSource::drawAnimation):
+        (WebCore::MockRealtimeVideoSource::drawBoxes):
+        (WebCore::MockRealtimeVideoSource::drawText):
+        (WebCore::MockRealtimeVideoSource::generateFrame):
+        (WebCore::MockRealtimeVideoSource::imageBuffer const):
+        * platform/mock/MockRealtimeVideoSource.h:
+
 2018-12-08  Alex Christensen  <achristen...@webkit.org>
 
         Don't programmatically capitalize safe browsing warning buttons

Modified: trunk/Source/WebCore/platform/cocoa/VideoToolboxSoftLink.cpp (239015 => 239016)


--- trunk/Source/WebCore/platform/cocoa/VideoToolboxSoftLink.cpp	2018-12-09 04:11:48 UTC (rev 239015)
+++ trunk/Source/WebCore/platform/cocoa/VideoToolboxSoftLink.cpp	2018-12-09 05:36:43 UTC (rev 239016)
@@ -58,7 +58,7 @@
 SOFT_LINK_FUNCTION_FOR_SOURCE(WebCore, VideoToolbox, VTPixelTransferSessionTransferImage, OSStatus, (VTPixelTransferSessionRef session, CVPixelBufferRef sourceBuffer, CVPixelBufferRef destinationBuffer), (session, sourceBuffer, destinationBuffer))
 SOFT_LINK_FUNCTION_FOR_SOURCE(WebCore, VideoToolbox, VTSessionSetProperty, OSStatus, (VTSessionRef session, CFStringRef propertyKey, CFTypeRef propertyValue), (session, propertyKey, propertyValue))
 SOFT_LINK_CONSTANT_FOR_SOURCE(WebCore, VideoToolbox, kVTPixelTransferPropertyKey_ScalingMode, CFStringRef)
-SOFT_LINK_CONSTANT_FOR_SOURCE(WebCore, VideoToolbox, kVTScalingMode_Trim, CFStringRef)
+SOFT_LINK_CONSTANT_FOR_SOURCE(WebCore, VideoToolbox, kVTScalingMode_Letterbox, CFStringRef)
 SOFT_LINK_CONSTANT_FOR_SOURCE(WebCore, VideoToolbox, kVTPixelTransferPropertyKey_EnableHardwareAcceleratedTransfer, CFStringRef)
 SOFT_LINK_CONSTANT_FOR_SOURCE(WebCore, VideoToolbox, kVTPixelTransferPropertyKey_EnableHighSpeedTransfer, CFStringRef)
 SOFT_LINK_CONSTANT_FOR_SOURCE(WebCore, VideoToolbox, kVTPixelTransferPropertyKey_RealTime, CFStringRef)

Modified: trunk/Source/WebCore/platform/cocoa/VideoToolboxSoftLink.h (239015 => 239016)


--- trunk/Source/WebCore/platform/cocoa/VideoToolboxSoftLink.h	2018-12-09 04:11:48 UTC (rev 239015)
+++ trunk/Source/WebCore/platform/cocoa/VideoToolboxSoftLink.h	2018-12-09 05:36:43 UTC (rev 239016)
@@ -83,8 +83,8 @@
 
 SOFT_LINK_CONSTANT_FOR_HEADER(WebCore, VideoToolbox, kVTPixelTransferPropertyKey_ScalingMode, CFStringRef)
 #define kVTPixelTransferPropertyKey_ScalingMode get_VideoToolbox_kVTPixelTransferPropertyKey_ScalingMode()
-SOFT_LINK_CONSTANT_FOR_HEADER(WebCore, VideoToolbox, kVTScalingMode_Trim, CFStringRef)
-#define kVTScalingMode_Trim get_VideoToolbox_kVTScalingMode_Trim()
+SOFT_LINK_CONSTANT_FOR_HEADER(WebCore, VideoToolbox, kVTScalingMode_Letterbox, CFStringRef)
+#define kVTScalingMode_Letterbox get_VideoToolbox_kVTScalingMode_Letterbox()
 SOFT_LINK_CONSTANT_FOR_HEADER(WebCore, VideoToolbox, kVTPixelTransferPropertyKey_EnableHardwareAcceleratedTransfer, CFStringRef)
 #define kVTPixelTransferPropertyKey_EnableHardwareAcceleratedTransfer get_VideoToolbox_kVTPixelTransferPropertyKey_EnableHardwareAcceleratedTransfer()
 SOFT_LINK_CONSTANT_FOR_HEADER(WebCore, VideoToolbox, kVTPixelTransferPropertyKey_EnableHighSpeedTransfer, CFStringRef)

Modified: trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.mm (239015 => 239016)


--- trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.mm	2018-12-09 04:11:48 UTC (rev 239015)
+++ trunk/Source/WebCore/platform/graphics/cv/ImageTransferSessionVT.mm	2018-12-09 05:36:43 UTC (rev 239016)
@@ -59,7 +59,7 @@
     ASSERT(transferSession);
     m_transferSession = adoptCF(transferSession);
 
-    auto status = VTSessionSetProperty(transferSession, kVTPixelTransferPropertyKey_ScalingMode, kVTScalingMode_Trim);
+    auto status = VTSessionSetProperty(transferSession, kVTPixelTransferPropertyKey_ScalingMode, kVTScalingMode_Letterbox);
     if (status != kCVReturnSuccess)
         RELEASE_LOG(Media, "ImageTransferSessionVT::ImageTransferSessionVT: VTSessionSetProperty(kVTPixelTransferPropertyKey_ScalingMode) failed with error %d", static_cast<int>(status));
 

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp (239015 => 239016)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2018-12-09 04:11:48 UTC (rev 239015)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.cpp	2018-12-09 05:36:43 UTC (rev 239016)
@@ -178,11 +178,16 @@
     return m_currentSettings.value();
 }
 
+IntSize MockRealtimeVideoSource::captureSize() const
+{
+    return m_preset ? m_preset->size : this->size();
+}
+
 void MockRealtimeVideoSource::settingsDidChange(OptionSet<RealtimeMediaSourceSettings::Flag> settings)
 {
     m_currentSettings = std::nullopt;
     if (settings.containsAny({ RealtimeMediaSourceSettings::Flag::Width, RealtimeMediaSourceSettings::Flag::Height })) {
-        m_baseFontSize = size().height() * .08;
+        m_baseFontSize = captureSize().height() * .08;
         m_bipBopFontSize = m_baseFontSize * 2.5;
         m_statsFontSize = m_baseFontSize * .5;
         m_imageBuffer = nullptr;
@@ -218,8 +223,9 @@
 
 void MockRealtimeVideoSource::drawAnimation(GraphicsContext& context)
 {
-    float radius = size().width() * .09;
-    FloatPoint location(size().width() * .8, size().height() * .3);
+    auto size = captureSize();
+    float radius = size.width() * .09;
+    FloatPoint location(size.width() * .8, size.height() * .3);
 
     m_path.clear();
     m_path.moveTo(location);
@@ -248,7 +254,7 @@
     static const RGBA32 green = 0xff008000;
     static const RGBA32 cyan = 0xFF00FFFF;
 
-    IntSize size = this->size();
+    IntSize size = captureSize();
     float boxSize = size.width() * .035;
     float boxTop = size.height() * .6;
 
@@ -330,8 +336,8 @@
     FontCascade statsFont { WTFMove(fontDescription), 0, 0 };
     statsFont.update(nullptr);
 
-    IntSize size = this->size();
-    FloatPoint timeLocation(size.width() * .05, size.height() * .15);
+    IntSize captureSize = this->captureSize();
+    FloatPoint timeLocation(captureSize.width() * .05, captureSize.height() * .15);
     context.setFillColor(Color::white);
     context.setTextDrawingMode(TextModeFill);
     String string = String::format("%02u:%02u:%02u.%03u", hours, minutes, seconds, milliseconds % 1000);
@@ -341,7 +347,7 @@
     timeLocation.move(0, m_baseFontSize);
     context.drawText(timeFont, TextRun((StringView(string))), timeLocation);
 
-    FloatPoint statsLocation(size.width() * .45, size.height() * .75);
+    FloatPoint statsLocation(captureSize.width() * .45, captureSize.height() * .75);
     string = String::format("Requested frame rate: %.1f fps", frameRate());
     context.drawText(statsFont, TextRun((StringView(string))), statsLocation);
 
@@ -349,10 +355,15 @@
     string = String::format("Observed frame rate: %.1f fps", observedFrameRate());
     context.drawText(statsFont, TextRun((StringView(string))), statsLocation);
 
+    auto size = this->size();
     statsLocation.move(0, m_statsFontSize);
     string = String::format("Size: %u x %u", size.width(), size.height());
     context.drawText(statsFont, TextRun((StringView(string))), statsLocation);
 
+    statsLocation.move(0, m_statsFontSize);
+    string = String::format("Preset size: %u x %u", captureSize.width(), captureSize.height());
+    context.drawText(statsFont, TextRun((StringView(string))), statsLocation);
+
     if (mockCamera()) {
         const char* camera;
         switch (facingMode()) {
@@ -380,7 +391,7 @@
         context.drawText(statsFont, TextRun { name() }, statsLocation);
     }
 
-    FloatPoint bipBopLocation(size.width() * .6, size.height() * .6);
+    FloatPoint bipBopLocation(captureSize.width() * .6, captureSize.height() * .6);
     unsigned frameMod = m_frameNumber % 60;
     if (frameMod <= 15) {
         context.setFillColor(Color::cyan);
@@ -413,7 +424,7 @@
     GraphicsContext& context = buffer->context();
     GraphicsContextStateSaver stateSaver(context);
 
-    auto& size = this->size();
+    auto size = captureSize();
     FloatRect frameRect(FloatPoint(), size);
 
     context.fillRect(FloatRect(FloatPoint(), size), m_fillColor);
@@ -432,7 +443,7 @@
     if (m_imageBuffer)
         return m_imageBuffer.get();
 
-    m_imageBuffer = ImageBuffer::create(size(), Unaccelerated);
+    m_imageBuffer = ImageBuffer::create(captureSize(), Unaccelerated);
     if (!m_imageBuffer)
         return nullptr;
 

Modified: trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h (239015 => 239016)


--- trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2018-12-09 04:11:48 UTC (rev 239015)
+++ trunk/Source/WebCore/platform/mock/MockRealtimeVideoSource.h	2018-12-09 05:36:43 UTC (rev 239016)
@@ -70,6 +70,8 @@
     bool isCaptureSource() const final { return true; }
     bool supportsSizeAndFrameRate(std::optional<int> width, std::optional<int> height, std::optional<double>) final;
     void setSizeAndFrameRate(std::optional<int> width, std::optional<int> height, std::optional<double>) final;
+    void setSizeAndFrameRateWithPreset(IntSize, double, RefPtr<VideoPreset> preset) final { m_preset = preset; }
+    IntSize captureSize() const;
 
     void generatePresets() final;
 
@@ -108,6 +110,7 @@
     RealtimeMediaSourceSupportedConstraints m_supportedConstraints;
     Color m_fillColor { Color::black };
     MockMediaDevice m_device;
+    RefPtr<VideoPreset> m_preset;
 };
 
 } // namespace WebCore
_______________________________________________
webkit-changes mailing list
webkit-changes@lists.webkit.org
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to