Apply rotation at source level if WebRTC sink ask so
authoryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Mar 2020 16:41:12 +0000 (16:41 +0000)
committeryouenn@apple.com <youenn@apple.com@268f45cc-cd09-0410-ab3c-d52691b4dbfc>
Mon, 16 Mar 2020 16:41:12 +0000 (16:41 +0000)
https://bugs.webkit.org/show_bug.cgi?id=205645

Reviewed by Eric Carlson.

Source/WebCore:

Add a virtual method to RealtimeMediaSource to pass the information that the sink prefers the frames to be rotated before sending them.

Source/WebKit:

Implement RealtimeMediaSource setShouldApplyRotation by sending IPC to capture process.
In capture process, if rotation should be applied, use an ImageRotationSessionVT session to apply it before sending the video frame.
This allows WebProcess to no longer need an ImageRotationSessionVT for WebRTC.

* UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::setShouldApplyRotation):
(WebKit::UserMediaCaptureManagerProxy::SourceProxy::rotatePixelBuffer):
(WebKit::UserMediaCaptureManagerProxy::setShouldApplyRotation):
* UIProcess/Cocoa/UserMediaCaptureManagerProxy.h:
* UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in:
* WebProcess/cocoa/UserMediaCaptureManager.cpp:
(WebKit::UserMediaCaptureManager::Source::setShouldApplyRotation):

LayoutTests:

* webrtc/video-rotation-no-cvo-expected.txt: Added.
* webrtc/video-rotation-no-cvo.html: Added.

git-svn-id: https://svn.webkit.org/repository/webkit/trunk@258504 268f45cc-cd09-0410-ab3c-d52691b4dbfc

16 files changed:
LayoutTests/ChangeLog
LayoutTests/webrtc/video-rotation-no-cvo-expected.txt [new file with mode: 0644]
LayoutTests/webrtc/video-rotation-no-cvo.html [new file with mode: 0644]
Source/WebCore/ChangeLog
Source/WebCore/Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp
Source/WebCore/WebCore.xcodeproj/project.pbxproj
Source/WebCore/platform/graphics/cv/ImageRotationSessionVT.h
Source/WebCore/platform/graphics/cv/ImageRotationSessionVT.mm
Source/WebCore/platform/mediastream/RealtimeMediaSource.h
Source/WebCore/platform/mediastream/RealtimeOutgoingVideoSource.cpp
Source/WebCore/platform/mediastream/RealtimeOutgoingVideoSource.h
Source/WebKit/ChangeLog
Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp
Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.h
Source/WebKit/UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in
Source/WebKit/WebProcess/cocoa/UserMediaCaptureManager.cpp

index 4af5285..1541a9e 100644 (file)
@@ -1,3 +1,13 @@
+2020-03-16  Youenn Fablet  <youenn@apple.com>
+
+        Apply rotation at source level if WebRTC sink ask so
+        https://bugs.webkit.org/show_bug.cgi?id=205645
+
+        Reviewed by Eric Carlson.
+
+        * webrtc/video-rotation-no-cvo-expected.txt: Added.
+        * webrtc/video-rotation-no-cvo.html: Added.
+
 2020-03-16  youenn fablet  <youenn@apple.com>
 
         Audio is not played from an audio element when the srcObject object has unstarted video tracks
diff --git a/LayoutTests/webrtc/video-rotation-no-cvo-expected.txt b/LayoutTests/webrtc/video-rotation-no-cvo-expected.txt
new file mode 100644 (file)
index 0000000..d29e8ba
--- /dev/null
@@ -0,0 +1,4 @@
+  
+
+PASS Testing video exchange with rotation applied before transmission 
+
diff --git a/LayoutTests/webrtc/video-rotation-no-cvo.html b/LayoutTests/webrtc/video-rotation-no-cvo.html
new file mode 100644 (file)
index 0000000..d4d97f1
--- /dev/null
@@ -0,0 +1,42 @@
+<!-- webkit-test-runner [ enableCaptureVideoInUIProcess=true ] -->
+<!doctype html>
+<html>
+    <head>
+        <meta charset="utf-8">
+        <title>Testing video rotation without CVO</title>
+        <script src="../resources/testharness.js"></script>
+        <script src="../resources/testharnessreport.js"></script>
+    </head>
+    <body>
+        <video id="localVideo" autoplay playsInline width="320" height="240"></video>
+        <video id="remoteVideo" autoplay playsInline width="320" height="240"></video>
+        <script src ="routines.js"></script>
+        <script>
+promise_test(async (test) => {
+    const localStream = await navigator.mediaDevices.getUserMedia({ video: { width: 320, height: 240 } });
+    if (window.testRunner)
+        window.testRunner.setMockCameraOrientation(90);
+
+    localVideo.srcObject = localStream;
+    const remoteStream = await new Promise((resolve, reject) => {
+        track = localStream.getVideoTracks()[0];
+
+        createConnections((firstConnection) => {
+            firstConnection.addTrack(track, localStream);
+            if (window.internals)
+                internals.applyRotationForOutgoingVideoSources(firstConnection);
+        }, (secondConnection) => {
+            secondConnection.ontrack = (trackEvent) => {
+                resolve(trackEvent.streams[0]);
+            };
+        });
+        setTimeout(() => reject("Test timed out"), 5000);
+    });
+
+    remoteVideo.srcObject = remoteStream;
+    await remoteVideo.play();
+    await waitForVideoSize(remoteVideo, 240, 320);
+}, "Testing video exchange with rotation applied before transmission");
+        </script>
+    </body>
+</html>
index fe4271f..13d57f8 100644 (file)
@@ -1,3 +1,35 @@
+2020-03-16  Youenn Fablet  <youenn@apple.com>
+
+        Apply rotation at source level if WebRTC sink ask so
+        https://bugs.webkit.org/show_bug.cgi?id=205645
+
+        Reviewed by Eric Carlson.
+
+        Add a virtual method to RealtimeMediaSource to pass the information that the sink prefers the frames to be rotated before sending them.
+r       By default, the method does nothing and RealtimeOutgoingVideoSource will continue to do the rotation itself.
+        Update ImageRotationSessionVT to be more easily usable by users having MediaSample instead of CVPixelBuffer.
+        Update RealtimeOutgoingVideoSource to use that routine: whenever applying rotation is needed,
+        it will ask its track source to apply rotation. If the track source cannot do it, it will do it on its own.
+
+        Test: webrtc/video-rotation-no-cvo.html
+
+        * Modules/mediastream/libwebrtc/LibWebRTCPeerConnectionBackend.cpp:
+        (WebCore::LibWebRTCPeerConnectionBackend::applyRotationForOutgoingVideoSources):
+        * WebCore.xcodeproj/project.pbxproj:
+        * platform/graphics/cv/ImageRotationSessionVT.h:
+        (WebCore::operator==):
+        (WebCore::operator!=):
+        * platform/graphics/cv/ImageRotationSessionVT.mm:
+        (WebCore::ImageRotationSessionVT::ImageRotationSessionVT):
+        (WebCore::ImageRotationSessionVT::initialize):
+        (WebCore::ImageRotationSessionVT::rotate):
+        * platform/mediastream/RealtimeMediaSource.h:
+        * platform/mediastream/RealtimeOutgoingVideoSource.cpp:
+        (WebCore::RealtimeOutgoingVideoSource::setSource):
+        (WebCore::RealtimeOutgoingVideoSource::applyRotation):
+        (WebCore::RealtimeOutgoingVideoSource::AddOrUpdateSink):
+        * platform/mediastream/RealtimeOutgoingVideoSource.h:
+
 2020-03-16  youenn fablet  <youenn@apple.com>
 
         Audio is not played from an audio element when the srcObject object has unstarted video tracks
index 6d91086..ab4d2ca 100644 (file)
@@ -445,7 +445,7 @@ void LibWebRTCPeerConnectionBackend::applyRotationForOutgoingVideoSources()
     for (auto& transceiver : m_peerConnection.currentTransceivers()) {
         if (!transceiver->sender().isStopped()) {
             if (auto* videoSource = backendFromRTPSender(transceiver->sender()).videoSource())
-                videoSource->setApplyRotation(true);
+                videoSource->applyRotation();
         }
     }
 }
index 86ae858..6fbc8b0 100644 (file)
                CD1E7347167BC78E009A885D /* TextTrackRepresentation.cpp in Sources */ = {isa = PBXBuildFile; fileRef = CD1E7346167BC78E009A885D /* TextTrackRepresentation.cpp */; };
                CD225C0B1C46FBF400140761 /* WebCoreNSURLSession.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD225C091C46FBF400140761 /* WebCoreNSURLSession.mm */; };
                CD225C0C1C46FBF400140761 /* WebCoreNSURLSession.h in Headers */ = {isa = PBXBuildFile; fileRef = CD225C0A1C46FBF400140761 /* WebCoreNSURLSession.h */; settings = {ATTRIBUTES = (Private, ); }; };
-               CD27AE5022A9868700947FF9 /* ImageRotationSessionVT.h in Headers */ = {isa = PBXBuildFile; fileRef = CD27AE4E22A9868700947FF9 /* ImageRotationSessionVT.h */; };
+               CD27AE5022A9868700947FF9 /* ImageRotationSessionVT.h in Headers */ = {isa = PBXBuildFile; fileRef = CD27AE4E22A9868700947FF9 /* ImageRotationSessionVT.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CD27AE5122A9868700947FF9 /* ImageRotationSessionVT.mm in Sources */ = {isa = PBXBuildFile; fileRef = CD27AE4F22A9868700947FF9 /* ImageRotationSessionVT.mm */; };
                CD2F4A2418D89F700063746D /* AudioHardwareListener.h in Headers */ = {isa = PBXBuildFile; fileRef = CD2F4A2218D89F700063746D /* AudioHardwareListener.h */; settings = {ATTRIBUTES = (Private, ); }; };
                CD2F4A2818D8A3490063746D /* AudioHardwareListenerMac.h in Headers */ = {isa = PBXBuildFile; fileRef = CD2F4A2618D8A3490063746D /* AudioHardwareListenerMac.h */; };
index 6001bb7..2ddf496 100644 (file)
@@ -36,6 +36,8 @@ typedef struct __CVPixelBufferPool* CVPixelBufferPoolRef;
 
 namespace WebCore {
 
+class MediaSample;
+
 class ImageRotationSessionVT final {
     WTF_MAKE_FAST_ALLOCATED;
 public:
@@ -52,8 +54,9 @@ public:
         Yes,
     };
 
-    ImageRotationSessionVT(AffineTransform&&, FloatSize, OSType pixelFormat, IsCGImageCompatible);
-    ImageRotationSessionVT(RotationProperties&&, FloatSize, OSType pixelFormat, IsCGImageCompatible);
+    ImageRotationSessionVT(AffineTransform&&, FloatSize, OSType, IsCGImageCompatible);
+    ImageRotationSessionVT(const RotationProperties&, FloatSize, OSType, IsCGImageCompatible);
+    ImageRotationSessionVT() = default;
 
     const Optional<AffineTransform>& transform() const { return m_transform; }
     const RotationProperties& rotationProperties() const { return m_rotationProperties; }
@@ -61,8 +64,13 @@ public:
     const FloatSize& rotatedSize() { return m_rotatedSize; }
 
     RetainPtr<CVPixelBufferRef> rotate(CVPixelBufferRef);
+    WEBCORE_EXPORT RetainPtr<CVPixelBufferRef> rotate(MediaSample&, const RotationProperties&, IsCGImageCompatible);
+
+    bool isMatching(MediaSample&, const RotationProperties&);
 
 private:
+    void initialize(const RotationProperties&, FloatSize, OSType pixelFormat, IsCGImageCompatible);
+
     Optional<AffineTransform> m_transform;
     RotationProperties m_rotationProperties;
     FloatSize m_size;
@@ -71,6 +79,16 @@ private:
     RetainPtr<CVPixelBufferPoolRef> m_rotationPool;
 };
 
+inline bool operator==(const ImageRotationSessionVT::RotationProperties& rotation1, const ImageRotationSessionVT::RotationProperties& rotation2)
+{
+    return rotation1.flipX == rotation2.flipX && rotation1.flipY == rotation2.flipY && rotation1.angle == rotation2.angle;
+}
+
+inline bool operator!=(const ImageRotationSessionVT::RotationProperties& rotation1, const ImageRotationSessionVT::RotationProperties& rotation2)
+{
+    return !(rotation1 == rotation2);
+}
+
 }
 
 #endif
index 88a5db5..59057aa 100644 (file)
 #include "ImageRotationSessionVT.h"
 
 #include "AffineTransform.h"
+#include "MediaSample.h"
 
 #include "CoreVideoSoftLink.h"
 #include "VideoToolboxSoftLink.h"
+#import <pal/cf/CoreMediaSoftLink.h>
 
 #if USE(VIDEOTOOLBOX)
 
@@ -64,11 +66,16 @@ ImageRotationSessionVT::ImageRotationSessionVT(AffineTransform&& transform, Floa
     m_transform = WTFMove(transform);
 }
 
+ImageRotationSessionVT::ImageRotationSessionVT(const RotationProperties& rotation, FloatSize size, OSType pixelFormat, IsCGImageCompatible cvImageCompatibility)
+{
+    initialize(rotation, size, pixelFormat, cvImageCompatibility);
+}
 
-ImageRotationSessionVT::ImageRotationSessionVT(RotationProperties&& rotation, FloatSize size, OSType pixelFormat, IsCGImageCompatible cvImageCompatibility)
-    : m_rotationProperties(WTFMove(rotation))
-    , m_size(size)
+void ImageRotationSessionVT::initialize(const RotationProperties& rotation, FloatSize size, OSType pixelFormat, IsCGImageCompatible cvImageCompatibility)
 {
+    m_rotationProperties = rotation;
+    m_size = size;
+
     if (m_rotationProperties.angle == 90 || m_rotationProperties.angle == 270)
         size = size.transposedSize();
 
@@ -89,6 +96,7 @@ ImageRotationSessionVT::ImageRotationSessionVT(RotationProperties&& rotation, Fl
         (__bridge NSString *)kCVPixelBufferHeightKey: @(m_rotatedSize.height()),
         (__bridge NSString *)kCVPixelBufferPixelFormatTypeKey: @(pixelFormat),
         (__bridge NSString *)kCVPixelBufferCGImageCompatibilityKey: (cvImageCompatibility == IsCGImageCompatible::Yes ? @YES : @NO),
+        (__bridge NSString *)kCVPixelBufferIOSurfacePropertiesKey : @{ }
     };
     CVPixelBufferPoolRef rawPool = nullptr;
     if (auto err = CVPixelBufferPoolCreate(kCFAllocatorDefault, nullptr, (__bridge CFDictionaryRef)pixelAttributes, &rawPool); err != noErr)
@@ -106,6 +114,20 @@ RetainPtr<CVPixelBufferRef> ImageRotationSessionVT::rotate(CVPixelBufferRef pixe
     return nullptr;
 }
 
+RetainPtr<CVPixelBufferRef> ImageRotationSessionVT::rotate(MediaSample& sample, const RotationProperties& rotation, IsCGImageCompatible cvImageCompatibility)
+{
+    auto pixelBuffer = static_cast<CVPixelBufferRef>(PAL::CMSampleBufferGetImageBuffer(sample.platformSample().sample.cmSampleBuffer));
+    ASSERT(pixelBuffer);
+    if (!pixelBuffer)
+        return nullptr;
+
+    IntSize size { (int)CVPixelBufferGetWidth(pixelBuffer), (int)CVPixelBufferGetHeight(pixelBuffer) };
+    if (rotation != m_rotationProperties || m_size != size)
+        initialize(rotation, size, CVPixelBufferGetPixelFormatType(pixelBuffer), cvImageCompatibility);
+
+    return rotate(pixelBuffer);
+}
+
 }
 
 #endif
index 39b9976..1b9d6a2 100644 (file)
@@ -200,6 +200,8 @@ public:
     virtual void delaySamples(Seconds) { };
     void setInterruptedForTesting(bool);
 
+    virtual bool setShouldApplyRotation(bool) { return false; }
+
 protected:
     RealtimeMediaSource(Type, String&& name, String&& deviceID = { }, String&& hashSalt = { });
 
index d9a77a8..5b933f1 100644 (file)
@@ -80,6 +80,21 @@ void RealtimeOutgoingVideoSource::setSource(Ref<MediaStreamTrackPrivate>&& newSo
 {
     ASSERT(!m_videoSource->hasObserver(*this));
     m_videoSource = WTFMove(newSource);
+
+    if (!m_areSinksAskingToApplyRotation)
+        return;
+    if (!m_videoSource->source().setShouldApplyRotation(true))
+        m_shouldApplyRotation = true;
+}
+
+void RealtimeOutgoingVideoSource::applyRotation()
+{
+    if (m_areSinksAskingToApplyRotation)
+        return;
+
+    m_areSinksAskingToApplyRotation = true;
+    if (!m_videoSource->source().setShouldApplyRotation(true))
+        m_shouldApplyRotation = true;
 }
 
 void RealtimeOutgoingVideoSource::stop()
@@ -135,7 +150,7 @@ void RealtimeOutgoingVideoSource::AddOrUpdateSink(rtc::VideoSinkInterface<webrtc
     ASSERT(!sinkWants.black_frames);
 
     if (sinkWants.rotation_applied)
-        m_shouldApplyRotation = true;
+        applyRotation();
 
     auto locker = holdLock(m_sinksLock);
     m_sinks.add(sink);
@@ -161,7 +176,7 @@ void RealtimeOutgoingVideoSource::sendBlackFramesIfNeeded()
     if (!m_blackFrame) {
         auto width = m_width;
         auto height = m_height;
-        if (m_shouldApplyRotation && (m_currentRotation == webrtc::kVideoRotation_0 || m_currentRotation == webrtc::kVideoRotation_90))
+        if (m_shouldApplyRotation && (m_currentRotation == webrtc::kVideoRotation_270 || m_currentRotation == webrtc::kVideoRotation_90))
             std::swap(width, height);
         m_blackFrame = createBlackFrame(width, height);
         ASSERT(m_blackFrame);
index e2a48d0..a6656ce 100644 (file)
@@ -71,7 +71,7 @@ public:
         return rtc::RefCountReleaseStatus::kOtherRefsRemained;
     }
 
-    void setApplyRotation(bool shouldApplyRotation) { m_shouldApplyRotation = shouldApplyRotation; }
+    void applyRotation();
 
 protected:
     explicit RealtimeOutgoingVideoSource(Ref<MediaStreamTrackPrivate>&&);
@@ -134,6 +134,7 @@ private:
 
     mutable RecursiveLock m_sinksLock;
     HashSet<rtc::VideoSinkInterface<webrtc::VideoFrame>*> m_sinks;
+    bool m_areSinksAskingToApplyRotation { false };
 
     bool m_enabled { true };
     bool m_muted { false };
index 36b80db..ff0fcb6 100644 (file)
@@ -1,3 +1,23 @@
+2020-03-16  Youenn Fablet  <youenn@apple.com>
+
+        Apply rotation at source level if WebRTC sink ask so
+        https://bugs.webkit.org/show_bug.cgi?id=205645
+
+        Reviewed by Eric Carlson.
+
+        Implement RealtimeMediaSource setShouldApplyRotation by sending IPC to capture process.
+        In capture process, if rotation should be applied, use an ImageRotationSessionVT session to apply it before sending the video frame.
+        This allows WebProcess to no longer need an ImageRotationSessionVT for WebRTC.
+
+        * UIProcess/Cocoa/UserMediaCaptureManagerProxy.cpp:
+        (WebKit::UserMediaCaptureManagerProxy::SourceProxy::setShouldApplyRotation):
+        (WebKit::UserMediaCaptureManagerProxy::SourceProxy::rotatePixelBuffer):
+        (WebKit::UserMediaCaptureManagerProxy::setShouldApplyRotation):
+        * UIProcess/Cocoa/UserMediaCaptureManagerProxy.h:
+        * UIProcess/Cocoa/UserMediaCaptureManagerProxy.messages.in:
+        * WebProcess/cocoa/UserMediaCaptureManager.cpp:
+        (WebKit::UserMediaCaptureManager::Source::setShouldApplyRotation):
+
 2020-03-13  Sergio Villar Senin  <svillar@igalia.com>
 
         [WebXR] IDLs, stubs and build configuration for WPE
index 3d9f283..9d6fbaf 100644 (file)
@@ -35,6 +35,7 @@
 #include "WebProcessProxy.h"
 #include <WebCore/AudioSession.h>
 #include <WebCore/CARingBuffer.h>
+#include <WebCore/ImageRotationSessionVT.h>
 #include <WebCore/MediaConstraints.h>
 #include <WebCore/RealtimeMediaSourceCenter.h>
 #include <WebCore/RemoteVideoSample.h>
@@ -96,6 +97,8 @@ public:
         m_source->requestToEnd(*this);
     }
 
+    void setShouldApplyRotation(bool shouldApplyRotation) { m_shouldApplyRotation = true; }
+
 private:
     void sourceStopped() final {
         if (m_source->captureDidFail()) {
@@ -135,7 +138,12 @@ private:
     void videoSampleAvailable(MediaSample& sample) final
     {
 #if HAVE(IOSURFACE)
-        auto remoteSample = RemoteVideoSample::create(sample);
+        std::unique_ptr<RemoteVideoSample> remoteSample;
+        if (m_shouldApplyRotation && sample.videoRotation() != MediaSample::VideoRotation::None) {
+            auto pixelBuffer = rotatePixelBuffer(sample);
+            remoteSample = RemoteVideoSample::create(pixelBuffer.get(), sample.presentationTime());
+        } else
+            remoteSample = RemoteVideoSample::create(sample);
         if (remoteSample)
             m_connection->send(Messages::UserMediaCaptureManager::RemoteVideoSampleAvailable(m_id, WTFMove(*remoteSample)), 0);
 #else
@@ -143,6 +151,30 @@ private:
 #endif
     }
 
+    RetainPtr<CVPixelBufferRef> rotatePixelBuffer(MediaSample& sample)
+    {
+        if (!m_rotationSession)
+            m_rotationSession = makeUnique<ImageRotationSessionVT>();
+
+        ImageRotationSessionVT::RotationProperties rotation;
+        switch (sample.videoRotation()) {
+        case MediaSample::VideoRotation::None:
+            ASSERT_NOT_REACHED();
+            rotation.angle = 0;
+            break;
+        case MediaSample::VideoRotation::UpsideDown:
+            rotation.angle = 180;
+            break;
+        case MediaSample::VideoRotation::Right:
+            rotation.angle = 90;
+            break;
+        case MediaSample::VideoRotation::Left:
+            rotation.angle = 270;
+            break;
+        }
+        return m_rotationSession->rotate(sample, rotation, ImageRotationSessionVT::IsCGImageCompatible::No);
+    }
+
     void storageChanged(SharedMemory* storage) final {
         SharedMemory::Handle handle;
         if (storage)
@@ -164,6 +196,8 @@ private:
     CAAudioStreamDescription m_description { };
     int64_t m_numberOfFrames { 0 };
     bool m_isEnded { false };
+    std::unique_ptr<ImageRotationSessionVT> m_rotationSession;
+    bool m_shouldApplyRotation { false };
 };
 
 UserMediaCaptureManagerProxy::UserMediaCaptureManagerProxy(UniqueRef<ConnectionProxy>&& connectionProxy)
@@ -272,6 +306,12 @@ void UserMediaCaptureManagerProxy::requestToEnd(RealtimeMediaSourceIdentifier so
         proxy->requestToEnd();
 }
 
+void UserMediaCaptureManagerProxy::setShouldApplyRotation(RealtimeMediaSourceIdentifier sourceID, bool shouldApplyRotation)
+{
+    if (auto* proxy = m_proxies.get(sourceID))
+        proxy->setShouldApplyRotation(shouldApplyRotation);
+}
+
 void UserMediaCaptureManagerProxy::clear()
 {
     m_proxies.clear();
index 452c818..a3d6ef2 100644 (file)
@@ -78,6 +78,7 @@ private:
     void applyConstraints(WebCore::RealtimeMediaSourceIdentifier, const WebCore::MediaConstraints&);
     void clone(WebCore::RealtimeMediaSourceIdentifier clonedID, WebCore::RealtimeMediaSourceIdentifier cloneID);
     void requestToEnd(WebCore::RealtimeMediaSourceIdentifier);
+    void setShouldApplyRotation(WebCore::RealtimeMediaSourceIdentifier, bool shouldApplyRotation);
 
     class SourceProxy;
     friend class SourceProxy;
index baabacc..28e9299 100644 (file)
@@ -31,6 +31,7 @@ messages -> UserMediaCaptureManagerProxy NotRefCounted {
     ApplyConstraints(WebCore::RealtimeMediaSourceIdentifier id, struct WebCore::MediaConstraints constraints)
     Clone(WebCore::RealtimeMediaSourceIdentifier clonedID, WebCore::RealtimeMediaSourceIdentifier cloneID)
     RequestToEnd(WebCore::RealtimeMediaSourceIdentifier sourceID)
+    SetShouldApplyRotation(WebCore::RealtimeMediaSourceIdentifier sourceID, bool shouldApplyRotation)
 }
 
 #endif
index bd43df5..052b955 100644 (file)
@@ -249,6 +249,8 @@ private:
     // RealtimeMediaSource
     void beginConfiguration() final { }
     void commitConfiguration() final { }
+    bool setShouldApplyRotation(bool /* shouldApplyRotation */) final;
+
 
     void applyConstraints(const WebCore::MediaConstraints&, ApplyConstraintsHandler&&) final;
 
@@ -429,6 +431,12 @@ void UserMediaCaptureManager::Source::stopProducingData()
     connection()->send(Messages::UserMediaCaptureManagerProxy::StopProducingData(m_id), 0);
 }
 
+bool UserMediaCaptureManager::Source::setShouldApplyRotation(bool shouldApplyRotation)
+{
+    connection()->send(Messages::UserMediaCaptureManagerProxy::SetShouldApplyRotation(m_id, shouldApplyRotation), 0);
+    return true;
+}
+
 const WebCore::RealtimeMediaSourceCapabilities& UserMediaCaptureManager::Source::capabilities()
 {
     return m_capabilities;