Title: [284368] trunk
Revision
284368
Author
[email protected]
Date
2021-10-18 06:07:09 -0700 (Mon, 18 Oct 2021)

Log Message

[GStreamer] fast/mediastream/video-rotation tests are failing due to missing TestController::takeViewPortSnapshot
https://bugs.webkit.org/show_bug.cgi?id=231059

Reviewed by Xabier Rodriguez-Calvar.

Source/WebCore:

Add video orientation and mirroring support to the GStreamer mock video source, all the way
to the media player. The video sink had to be adapted, to catch tag events and trigger
orientation update in the player.

* platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp:
(webKitGLVideoSinkSetMediaPlayerPrivate):
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
(WebCore::getVideoOrientation):
(WebCore::MediaPlayerPrivateGStreamer::updateVideoOrientation):
(WebCore::MediaPlayerPrivateGStreamer::updateVideoSizeAndOrientationFromCaps):
* platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
* platform/graphics/gstreamer/MediaSampleGStreamer.cpp:
(WebCore::MediaSampleGStreamer::MediaSampleGStreamer):
(WebCore::MediaSampleGStreamer::createImageSample):
* platform/graphics/gstreamer/MediaSampleGStreamer.h:
(WebCore::MediaSampleGStreamer::create):
(WebCore::MediaSampleGStreamer::createImageSample):
* platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp:
* platform/mediastream/gstreamer/MockRealtimeVideoSourceGStreamer.cpp:
(WebCore::MockRealtimeVideoSourceGStreamer::updateSampleBuffer):

Source/WebKit:

Implement setOrientationForMediaCapture for GStreamer ports. Because media capture runs in
the WebProcess for those ports, we need a new IPC message, sent from the UIProcess to the
WebProcess.

* UIProcess/API/C/WKPage.cpp:
(WKPageSetMockCameraOrientation):
(WKPageIsMockRealtimeMediaSourceCenterEnabled):
* UIProcess/WebPageProxy.cpp:
(WebKit::WebPageProxy::setOrientationForMediaCapture):
* WebProcess/WebPage/WebPage.cpp:
(WebKit::WebPage::setOrientationForMediaCapture):
* WebProcess/WebPage/WebPage.h:
* WebProcess/WebPage/WebPage.messages.in:

Tools:

Implement takeViewPortSnapshot for WPE and GTK, the WebView snapshot is exported to PNG and
serialized as a data URL.

* WebKitTestRunner/TestController.cpp:
* WebKitTestRunner/gtk/TestControllerGtk.cpp:
(WTR::TestController::takeViewPortSnapshot):
* WebKitTestRunner/wpe/TestControllerWPE.cpp:
(WTR::TestController::takeViewPortSnapshot):

LayoutTests:

The video-rotation.html test was prone to flakyness in GStreamer ports, so a few changes were made:

- don't append canvas to the page, that can "poison" future viewport snapshots
- wait for a timeupdate before checking the first snapshot, that gives us some margin, so
the player might have repainted
- catch validation errors so they're not logged to the console, that would introduce result
diffs in case the first validation was not successful
- try at most 100 validations attempts. Ideally it would be nicer to rely on the
requestVideoFrameCallback API for this.

* fast/mediastream/video-rotation.html:
* platform/glib/TestExpectations:

Modified Paths

Diff

Modified: trunk/LayoutTests/ChangeLog (284367 => 284368)


--- trunk/LayoutTests/ChangeLog	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/LayoutTests/ChangeLog	2021-10-18 13:07:09 UTC (rev 284368)
@@ -1,3 +1,23 @@
+2021-10-18  Philippe Normand  <[email protected]>
+
+        [GStreamer] fast/mediastream/video-rotation tests are failing due to missing TestController::takeViewPortSnapshot
+        https://bugs.webkit.org/show_bug.cgi?id=231059
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        The video-rotation.html test was prone to flakyness in GStreamer ports, so a few changes were made:
+
+        - don't append canvas to the page, that can "poison" future viewport snapshots
+        - wait for a timeupdate before checking the first snapshot, that gives us some margin, so
+        the player might have repainted
+        - catch validation errors so they're not logged to the console, that would introduce result
+        diffs in case the first validation was not successful
+        - try at most 100 validations attempts. Ideally it would be nicer to rely on the
+        requestVideoFrameCallback API for this.
+
+        * fast/mediastream/video-rotation.html:
+        * platform/glib/TestExpectations:
+
 2021-10-18  Tim Nguyen  <[email protected]>
 
         Fix mouse selection on modal <dialog> text nodes

Modified: trunk/LayoutTests/fast/mediastream/video-rotation.html (284367 => 284368)


--- trunk/LayoutTests/fast/mediastream/video-rotation.html	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/LayoutTests/fast/mediastream/video-rotation.html	2021-10-18 13:07:09 UTC (rev 284368)
@@ -47,8 +47,6 @@
     canvas.getContext('2d').drawImage(image, 0, 0);
     const data = "" 0, canvas.width, canvas.height).data;
 
-    document.body.appendChild(canvas);
-
     // We expect to have a green horizontal line until getting some white.
     let j = 100;
     if (!isPixelGreen(100, j, canvas, data))
@@ -67,6 +65,14 @@
     return i === canvas.height;
 }
 
+async function waitFor(element, type) {
+    return new Promise(resolve => {
+        element.addEventListener(type, event => {
+            resolve(event);
+        }, { once: true });
+    });
+}
+
 _onload_ = async () => {
     try {
         video.srcObject = await navigator.mediaDevices.getUserMedia({video: {width: 400, height: 200} });
@@ -80,19 +86,20 @@
         while (video.videoWidth !== 200 && ++counter < 100)
             await new Promise(resolve => setTimeout(resolve, 50));
 
+        await waitFor(video, 'timeupdate');
         counter = 0;
         let isValidSnapshot = false;
         do {
             await new Promise(resolve => setTimeout(resolve, 50));
-            isValidSnapshot = await validateSnapshot();
-        } while (++counter < 50 && !isValidSnapshot)
+            try {
+                isValidSnapshot = await validateSnapshot();
+            } catch (e) { }
+        } while (++counter < 100 && !isValidSnapshot)
 
-        log.innerHTML = counter < 50 ? "PASS" : "FAIL";
+        log.innerHTML = counter < 100 ? "PASS" : "FAIL";
 
-         if (counter < 50) {
+        if (counter < 100)
             document.body.removeChild(image);
-            document.body.removeChild(canvas);
-         }
     } catch (e) {
         console.log(e);
     }

Modified: trunk/LayoutTests/platform/glib/TestExpectations (284367 => 284368)


--- trunk/LayoutTests/platform/glib/TestExpectations	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/LayoutTests/platform/glib/TestExpectations	2021-10-18 13:07:09 UTC (rev 284368)
@@ -676,9 +676,6 @@
 webkit.org/b/79203 fast/mediastream/RTCRtpSender-replaceTrack.html [ Failure ]
 webkit.org/b/187603 fast/mediastream/media-stream-track-source-failure.html [ Timeout Failure Pass ]
 webkit.org/b/231057 fast/mediastream/media-stream-video-track-interrupted.html [ Failure ]
-# Not exactly GStreamer (missing helper method to take viewport screenshot)
-webkit.org/b/231059 fast/mediastream/video-rotation-gpu-process-crash.html [ Failure ]
-webkit.org/b/231059 fast/mediastream/video-rotation.html [ Failure ]
 webkit.org/b/231061 fast/mediastream/captureStream/canvas3d.html [ Timeout ]
 
 webkit.org/b/223508 imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https.html [ Failure Pass ]
@@ -1730,6 +1727,7 @@
 
 # No support for GPUProcess yet
 fast/mediastream/captureInGPUProcess.html [ Skip ]
+fast/mediastream/video-rotation-gpu-process-crash.html [ Skip ]
 
 # Payment Request
 imported/w3c/web-platform-tests/payment-request [ Skip ]

Modified: trunk/Source/WebCore/ChangeLog (284367 => 284368)


--- trunk/Source/WebCore/ChangeLog	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/ChangeLog	2021-10-18 13:07:09 UTC (rev 284368)
@@ -1,3 +1,31 @@
+2021-10-18  Philippe Normand  <[email protected]>
+
+        [GStreamer] fast/mediastream/video-rotation tests are failing due to missing TestController::takeViewPortSnapshot
+        https://bugs.webkit.org/show_bug.cgi?id=231059
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Add video orientation and mirroring support to the GStreamer mock video source, all the way
+        to the media player. The video sink had to be adapted, to catch tag events and trigger
+        orientation update in the player.
+
+        * platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp:
+        (webKitGLVideoSinkSetMediaPlayerPrivate):
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp:
+        (WebCore::getVideoOrientation):
+        (WebCore::MediaPlayerPrivateGStreamer::updateVideoOrientation):
+        (WebCore::MediaPlayerPrivateGStreamer::updateVideoSizeAndOrientationFromCaps):
+        * platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h:
+        * platform/graphics/gstreamer/MediaSampleGStreamer.cpp:
+        (WebCore::MediaSampleGStreamer::MediaSampleGStreamer):
+        (WebCore::MediaSampleGStreamer::createImageSample):
+        * platform/graphics/gstreamer/MediaSampleGStreamer.h:
+        (WebCore::MediaSampleGStreamer::create):
+        (WebCore::MediaSampleGStreamer::createImageSample):
+        * platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp:
+        * platform/mediastream/gstreamer/MockRealtimeVideoSourceGStreamer.cpp:
+        (WebCore::MockRealtimeVideoSourceGStreamer::updateSampleBuffer):
+
 2021-10-18  Carlos Garcia Campos  <[email protected]>
 
         [GTK][a11y] Add implementation of component interface when building with ATSPI

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp (284367 => 284368)


--- trunk/Source/WebCore/platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GLVideoSinkGStreamer.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -255,7 +255,16 @@
     }), player);
 
     GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(priv->appSink.get(), "sink"));
-    gst_pad_add_probe(pad.get(), static_cast<GstPadProbeType>(GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_FLUSH), [] (GstPad*, GstPadProbeInfo* info,  gpointer userData) -> GstPadProbeReturn {
+    gst_pad_add_probe(pad.get(), static_cast<GstPadProbeType>(GST_PAD_PROBE_TYPE_PUSH | GST_PAD_PROBE_TYPE_QUERY_DOWNSTREAM | GST_PAD_PROBE_TYPE_EVENT_FLUSH | GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM), [](GstPad*, GstPadProbeInfo* info, gpointer userData) -> GstPadProbeReturn {
+        auto* player = static_cast<MediaPlayerPrivateGStreamer*>(userData);
+
+        if (info->type & GST_PAD_PROBE_TYPE_EVENT_DOWNSTREAM && GST_EVENT_TYPE(GST_PAD_PROBE_INFO_EVENT(info)) == GST_EVENT_TAG) {
+            GstTagList* tagList;
+            gst_event_parse_tag(GST_PAD_PROBE_INFO_EVENT(info), &tagList);
+            player->updateVideoOrientation(tagList);
+            return GST_PAD_PROBE_OK;
+        }
+
         // In some platforms (e.g. OpenMAX on the Raspberry Pi) when a resolution change occurs the
         // pipeline has to be drained before a frame with the new resolution can be decoded.
         // In this context, it's important that we don't hold references to any previous frame
@@ -272,7 +281,6 @@
             GST_DEBUG("Acting upon flush-start event");
         }
 
-        auto* player = static_cast<MediaPlayerPrivateGStreamer*>(userData);
         player->flushCurrentBuffer();
         return GST_PAD_PROBE_OK;
     }, player, nullptr);

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp (284367 => 284368)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -2945,26 +2945,16 @@
     m_drawCondition.notifyOne();
 }
 
-static ImageOrientation getVideoOrientation(GstElement* sink)
+static ImageOrientation getVideoOrientation(const GstTagList* tagList)
 {
-    GRefPtr<GstPad> pad = adoptGRef(gst_element_get_static_pad(sink, "sink"));
-    ASSERT(pad);
-    GRefPtr<GstEvent> tagsEvent = adoptGRef(gst_pad_get_sticky_event(pad.get(), GST_EVENT_TAG, 0));
-    if (!tagsEvent) {
-        GST_DEBUG_OBJECT(pad.get(), "No sticky tag event, applying no rotation.");
-        return ImageOrientation::None;
-    }
-
-    GstTagList* tagList;
-    gst_event_parse_tag(tagsEvent.get(), &tagList);
     ASSERT(tagList);
     GUniqueOutPtr<gchar> tag;
     if (!gst_tag_list_get_string(tagList, GST_TAG_IMAGE_ORIENTATION, &tag.outPtr())) {
-        GST_DEBUG_OBJECT(pad.get(), "No image_orientation tag, applying no rotation.");
+        GST_DEBUG("No image_orientation tag, applying no rotation.");
         return ImageOrientation::None;
     }
 
-    GST_DEBUG_OBJECT(pad.get(), "Found image_orientation tag: %s", tag.get());
+    GST_DEBUG("Found image_orientation tag: %s", tag.get());
     if (!g_strcmp0(tag.get(), "flip-rotate-0"))
         return ImageOrientation::OriginTopRight;
     if (!g_strcmp0(tag.get(), "rotate-180"))
@@ -2984,6 +2974,20 @@
     return ImageOrientation::None;
 }
 
+void MediaPlayerPrivateGStreamer::updateVideoOrientation(const GstTagList* tagList)
+{
+    GST_DEBUG_OBJECT(pipeline(), "Updating orientation from %" GST_PTR_FORMAT, tagList);
+    setVideoSourceOrientation(getVideoOrientation(tagList));
+
+    // If the video is tagged as rotated 90 or 270 degrees, swap width and height.
+    if (m_videoSourceOrientation.usesWidthAsHeight())
+        m_videoSize = m_videoSize.transposedSize();
+
+    callOnMainThreadAndWait([this] {
+        m_player->sizeChanged();
+    });
+}
+
 void MediaPlayerPrivateGStreamer::updateVideoSizeAndOrientationFromCaps(const GstCaps* caps)
 {
     ASSERT(isMainThread());
@@ -3001,7 +3005,17 @@
         return;
     }
 
-    setVideoSourceOrientation(getVideoOrientation(m_videoSink.get()));
+    auto pad = adoptGRef(gst_element_get_static_pad(m_videoSink.get(), "sink"));
+    ASSERT(pad);
+    auto tagsEvent = adoptGRef(gst_pad_get_sticky_event(pad.get(), GST_EVENT_TAG, 0));
+    auto orientation = ImageOrientation::None;
+    if (tagsEvent) {
+        GstTagList* tagList;
+        gst_event_parse_tag(tagsEvent.get(), &tagList);
+        orientation = getVideoOrientation(tagList);
+    }
+
+    setVideoSourceOrientation(orientation);
     // If the video is tagged as rotated 90 or 270 degrees, swap width and height.
     if (m_videoSourceOrientation.usesWidthAsHeight())
         originalSize = originalSize.transposedSize();

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h (284367 => 284368)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaPlayerPrivateGStreamer.h	2021-10-18 13:07:09 UTC (rev 284368)
@@ -216,6 +216,8 @@
     void updateEnabledAudioTrack();
     void playbin3SendSelectStreamsIfAppropriate();
 
+    void updateVideoOrientation(const GstTagList*);
+
     // Append pipeline interface
     // FIXME: Use the client interface pattern, AppendPipeline does not need the full interface to this class just for this function.
     bool handleNeedContextMessage(GstMessage*);

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.cpp (284367 => 284368)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -32,12 +32,14 @@
 
 namespace WebCore {
 
-MediaSampleGStreamer::MediaSampleGStreamer(GRefPtr<GstSample>&& sample, const FloatSize& presentationSize, const AtomString& trackId)
+MediaSampleGStreamer::MediaSampleGStreamer(GRefPtr<GstSample>&& sample, const FloatSize& presentationSize, const AtomString& trackId, VideoRotation videoRotation, bool videoMirrored)
     : m_pts(MediaTime::zeroTime())
     , m_dts(MediaTime::zeroTime())
     , m_duration(MediaTime::zeroTime())
     , m_trackId(trackId)
     , m_presentationSize(presentationSize)
+    , m_videoRotation(videoRotation)
+    , m_videoMirrored(videoMirrored)
 {
     const GstClockTime minimumDuration = 1000; // 1 us
     ASSERT(sample);
@@ -98,10 +100,10 @@
     return adoptRef(*gstreamerMediaSample);
 }
 
-Ref<MediaSampleGStreamer> MediaSampleGStreamer::createImageSample(PixelBuffer&& pixelBuffer, const IntSize& destinationSize, double frameRate)
+Ref<MediaSampleGStreamer> MediaSampleGStreamer::createImageSample(PixelBuffer&& pixelBuffer, const IntSize& destinationSize, double frameRate, VideoRotation videoRotation, bool videoMirrored)
 {
     ensureGStreamerInitialized();
-    
+
     auto size = pixelBuffer.size();
 
     auto data = ""
@@ -146,7 +148,7 @@
         gst_video_converter_frame(converter.get(), inputFrame.get(), outputFrame.get());
         sample = adoptGRef(gst_sample_new(outputBuffer.get(), outputCaps.get(), nullptr, nullptr));
     }
-    return create(WTFMove(sample), FloatSize(width, height), { });
+    return create(WTFMove(sample), FloatSize(width, height), { }, videoRotation, videoMirrored);
 }
 
 RefPtr<JSC::Uint8ClampedArray> MediaSampleGStreamer::getRGBAImageData() const

Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h (284367 => 284368)


--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h	2021-10-18 13:07:09 UTC (rev 284368)
@@ -34,13 +34,13 @@
 
 class MediaSampleGStreamer : public MediaSample {
 public:
-    static Ref<MediaSampleGStreamer> create(GRefPtr<GstSample>&& sample, const FloatSize& presentationSize, const AtomString& trackId)
+    static Ref<MediaSampleGStreamer> create(GRefPtr<GstSample>&& sample, const FloatSize& presentationSize, const AtomString& trackId, VideoRotation videoRotation = VideoRotation::None, bool videoMirrored = false)
     {
-        return adoptRef(*new MediaSampleGStreamer(WTFMove(sample), presentationSize, trackId));
+        return adoptRef(*new MediaSampleGStreamer(WTFMove(sample), presentationSize, trackId, videoRotation, videoMirrored));
     }
 
     static Ref<MediaSampleGStreamer> createFakeSample(GstCaps*, MediaTime pts, MediaTime dts, MediaTime duration, const FloatSize& presentationSize, const AtomString& trackId);
-    static Ref<MediaSampleGStreamer> createImageSample(PixelBuffer&&, const IntSize& destinationSize = { }, double frameRate = 1);
+    static Ref<MediaSampleGStreamer> createImageSample(PixelBuffer&&, const IntSize& destinationSize = { }, double frameRate = 1, VideoRotation videoRotation = VideoRotation::None, bool videoMirrored = false);
 
     void extendToTheBeginning();
     MediaTime presentationTime() const override { return m_pts; }
@@ -60,9 +60,11 @@
     std::optional<ByteRange> byteRange() const override { return std::nullopt; }
     void dump(PrintStream&) const override;
     RefPtr<JSC::Uint8ClampedArray> getRGBAImageData() const final;
+    VideoRotation videoRotation() const override { return m_videoRotation; }
+    bool videoMirrored() const override { return m_videoMirrored; }
 
 protected:
-    MediaSampleGStreamer(GRefPtr<GstSample>&&, const FloatSize& presentationSize, const AtomString& trackId);
+    MediaSampleGStreamer(GRefPtr<GstSample>&&, const FloatSize& presentationSize, const AtomString& trackId, VideoRotation = VideoRotation::None, bool videoMirrored = false);
     virtual ~MediaSampleGStreamer() = default;
 
 private:
@@ -76,6 +78,8 @@
     GRefPtr<GstSample> m_sample;
     FloatSize m_presentationSize;
     MediaSample::SampleFlags m_flags { MediaSample::IsSync };
+    VideoRotation m_videoRotation { VideoRotation::None };
+    bool m_videoMirrored { false };
 };
 
 } // namespace WebCore.

Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp (284367 => 284368)


--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -280,6 +280,18 @@
             updateBlackFrame(caps);
         }
 
+        auto videoRotation = sample.videoRotation();
+        bool videoMirrored = sample.videoMirrored();
+        if (m_videoRotation != videoRotation || m_videoMirrored != videoMirrored) {
+            m_videoRotation = videoRotation;
+            m_videoMirrored = videoMirrored;
+
+            auto orientation = makeString(videoMirrored ? "flip-" : "", "rotate-", m_videoRotation);
+            GST_DEBUG_OBJECT(m_src.get(), "Pushing orientation tag: %s", orientation.utf8().data());
+            auto pad = adoptGRef(gst_element_get_static_pad(m_src.get(), "src"));
+            gst_pad_push_event(pad.get(), gst_event_new_tag(gst_tag_list_new(GST_TAG_IMAGE_ORIENTATION, orientation.utf8().data(), nullptr)));
+        }
+
         if (m_track.enabled()) {
             GST_TRACE_OBJECT(m_src.get(), "Pushing video frame from enabled track");
             pushSample(gstSample);
@@ -339,6 +351,8 @@
     RefPtr<VideoTrackPrivateMediaStream> m_videoTrack;
     IntSize m_lastKnownSize;
     GRefPtr<GstSample> m_blackFrame;
+    MediaSample::VideoRotation m_videoRotation { MediaSample::VideoRotation::None };
+    bool m_videoMirrored { false };
 };
 
 struct _WebKitMediaStreamSrcPrivate {

Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/MockRealtimeVideoSourceGStreamer.cpp (284367 => 284368)


--- trunk/Source/WebCore/platform/mediastream/gstreamer/MockRealtimeVideoSourceGStreamer.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/MockRealtimeVideoSourceGStreamer.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -152,7 +152,7 @@
     if (!pixelBuffer)
         return;
 
-    auto sample = MediaSampleGStreamer::createImageSample(WTFMove(*pixelBuffer), size(), frameRate());
+    auto sample = MediaSampleGStreamer::createImageSample(WTFMove(*pixelBuffer), size(), frameRate(), sampleRotation());
     sample->offsetTimestampsBy(MediaTime::createWithDouble((elapsedTime() + 100_ms).seconds()));
     dispatchMediaSampleToObservers(sample.get());
 }

Modified: trunk/Source/WebKit/ChangeLog (284367 => 284368)


--- trunk/Source/WebKit/ChangeLog	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebKit/ChangeLog	2021-10-18 13:07:09 UTC (rev 284368)
@@ -1,3 +1,24 @@
+2021-10-18  Philippe Normand  <[email protected]>
+
+        [GStreamer] fast/mediastream/video-rotation tests are failing due to missing TestController::takeViewPortSnapshot
+        https://bugs.webkit.org/show_bug.cgi?id=231059
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Implement setOrientationForMediaCapture for GStreamer ports. Because media capture runs in
+        the WebProcess for those ports, we need a new IPC message, sent from the UIProcess to the
+        WebProcess.
+
+        * UIProcess/API/C/WKPage.cpp:
+        (WKPageSetMockCameraOrientation):
+        (WKPageIsMockRealtimeMediaSourceCenterEnabled):
+        * UIProcess/WebPageProxy.cpp:
+        (WebKit::WebPageProxy::setOrientationForMediaCapture):
+        * WebProcess/WebPage/WebPage.cpp:
+        (WebKit::WebPage::setOrientationForMediaCapture):
+        * WebProcess/WebPage/WebPage.h:
+        * WebProcess/WebPage/WebPage.messages.in:
+
 2021-10-18  Tim Nguyen  <[email protected]>
 
         Fix mouse selection on modal <dialog> text nodes

Modified: trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp (284367 => 284368)


--- trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebKit/UIProcess/API/C/WKPage.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -3147,14 +3147,12 @@
 void WKPageSetMockCameraOrientation(WKPageRef pageRef, uint64_t orientation)
 {
     CRASH_IF_SUSPENDED;
-#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
     toImpl(pageRef)->setOrientationForMediaCapture(orientation);
-#endif
 }
 
 bool WKPageIsMockRealtimeMediaSourceCenterEnabled(WKPageRef)
 {
-#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
+#if (PLATFORM(COCOA) || USE(GSTREAMER)) && ENABLE(MEDIA_STREAM)
     return MockRealtimeMediaSourceCenter::mockRealtimeMediaSourceCenterEnabled();
 #else
     return false;

Modified: trunk/Source/WebKit/UIProcess/WebPageProxy.cpp (284367 => 284368)


--- trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebKit/UIProcess/WebPageProxy.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -10734,7 +10734,8 @@
 
 void WebPageProxy::setOrientationForMediaCapture(uint64_t orientation)
 {
-#if PLATFORM(COCOA) && ENABLE(MEDIA_STREAM)
+#if ENABLE(MEDIA_STREAM)
+#if PLATFORM(COCOA)
     if (auto* proxy = m_process->userMediaCaptureManagerProxy())
         proxy->setOrientation(orientation);
 
@@ -10741,7 +10742,10 @@
     auto* gpuProcess = m_process->processPool().gpuProcess();
     if (gpuProcess && preferences().captureVideoInGPUProcessEnabled())
         gpuProcess->setOrientationForMediaCapture(orientation);
+#elif USE(GSTREAMER)
+    send(Messages::WebPage::SetOrientationForMediaCapture(orientation));
 #endif
+#endif
 }
 
 #if ENABLE(INTELLIGENT_TRACKING_PREVENTION)

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp (284367 => 284368)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -4812,8 +4812,17 @@
     m_userMediaPermissionRequestManager->captureDevicesChanged();
 }
 
-#endif
+#if USE(GSTREAMER)
+void WebPage::setOrientationForMediaCapture(uint64_t rotation)
+{
+    m_page->forEachDocument([&](auto& document) {
+        document.orientationChanged(rotation);
+    });
+}
+#endif // USE(GSTREAMER)
 
+#endif // ENABLE(MEDIA_STREAM)
+
 #if ENABLE(ENCRYPTED_MEDIA)
 void WebPage::mediaKeySystemWasGranted(MediaKeySystemRequestIdentifier mediaKeySystemID, CompletionHandler<void()>&& completionHandler)
 {

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.h (284367 => 284368)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.h	2021-10-18 13:07:09 UTC (rev 284368)
@@ -1223,6 +1223,9 @@
 #if ENABLE(VIDEO) && USE(GSTREAMER)
     void requestInstallMissingMediaPlugins(const String& details, const String& description, WebCore::MediaPlayerRequestInstallMissingPluginsCallback&);
 #endif
+#if ENABLE(MEDIA_STREAM) && USE(GSTREAMER)
+    void setOrientationForMediaCapture(uint64_t rotation);
+#endif
 
     void addUserScript(String&& source, InjectedBundleScriptWorld&, WebCore::UserContentInjectedFrames, WebCore::UserScriptInjectionTime);
     void addUserStyleSheet(const String& source, WebCore::UserContentInjectedFrames);

Modified: trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in (284367 => 284368)


--- trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Source/WebKit/WebProcess/WebPage/WebPage.messages.in	2021-10-18 13:07:09 UTC (rev 284368)
@@ -383,7 +383,10 @@
     UserMediaAccessWasGranted(WebCore::UserMediaRequestIdentifier userMediaID, WebCore::CaptureDevice audioDevice, WebCore::CaptureDevice videoDevice, String mediaDeviceIdentifierHashSalt, WebKit::SandboxExtension::Handle sandboxExtensionHandle) -> () Async
     UserMediaAccessWasDenied(WebCore::UserMediaRequestIdentifier userMediaID, uint64_t reason, String invalidConstraint)
     CaptureDevicesChanged()
+#if USE(GSTREAMER)
+    SetOrientationForMediaCapture(int rotation)
 #endif
+#endif
 
 #if ENABLE(ENCRYPTED_MEDIA)
     MediaKeySystemWasGranted(WebCore::MediaKeySystemRequestIdentifier mediaKeySystemID) -> () Async

Modified: trunk/Tools/ChangeLog (284367 => 284368)


--- trunk/Tools/ChangeLog	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Tools/ChangeLog	2021-10-18 13:07:09 UTC (rev 284368)
@@ -1,3 +1,19 @@
+2021-10-18  Philippe Normand  <[email protected]>
+
+        [GStreamer] fast/mediastream/video-rotation tests are failing due to missing TestController::takeViewPortSnapshot
+        https://bugs.webkit.org/show_bug.cgi?id=231059
+
+        Reviewed by Xabier Rodriguez-Calvar.
+
+        Implement takeViewPortSnapshot for WPE and GTK, the WebView snapshot is exported to PNG and
+        serialized as a data URL.
+
+        * WebKitTestRunner/TestController.cpp:
+        * WebKitTestRunner/gtk/TestControllerGtk.cpp:
+        (WTR::TestController::takeViewPortSnapshot):
+        * WebKitTestRunner/wpe/TestControllerWPE.cpp:
+        (WTR::TestController::takeViewPortSnapshot):
+
 2021-10-18  Carlos Garcia Campos  <[email protected]>
 
         [GTK][a11y] Add implementation of component interface when building with ATSPI

Modified: trunk/Tools/WebKitTestRunner/TestController.cpp (284367 => 284368)


--- trunk/Tools/WebKitTestRunner/TestController.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Tools/WebKitTestRunner/TestController.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -3611,7 +3611,9 @@
 void TestController::setAllowedMenuActions(const Vector<String>&)
 {
 }
+#endif
 
+#if !PLATFORM(COCOA) && !PLATFORM(GTK) && !PLATFORM(WPE)
 WKRetainPtr<WKStringRef> TestController::takeViewPortSnapshot()
 {
     return adoptWK(WKStringCreateWithUTF8CString("not implemented"));

Modified: trunk/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp (284367 => 284368)


--- trunk/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Tools/WebKitTestRunner/gtk/TestControllerGtk.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -34,6 +34,7 @@
 #include <wtf/RunLoop.h>
 #include <wtf/glib/GRefPtr.h>
 #include <wtf/glib/GUniquePtr.h>
+#include <wtf/text/Base64.h>
 #include <wtf/text/WTFString.h>
 
 namespace WTR {
@@ -158,4 +159,15 @@
     return { };
 }
 
+WKRetainPtr<WKStringRef> TestController::takeViewPortSnapshot()
+{
+    Vector<unsigned char> output;
+    cairo_surface_write_to_png_stream(mainWebView()->windowSnapshotImage(), [](void* output, const unsigned char* data, unsigned length) -> cairo_status_t {
+        reinterpret_cast<Vector<unsigned char>*>(output)->append(data, length);
+        return CAIRO_STATUS_SUCCESS;
+    }, &output);
+    auto uri = makeString("data:image/png;base64,", base64Encoded(output.data(), output.size()));
+    return adoptWK(WKStringCreateWithUTF8CString(uri.utf8().data()));
+}
+
 } // namespace WTR

Modified: trunk/Tools/WebKitTestRunner/wpe/TestControllerWPE.cpp (284367 => 284368)


--- trunk/Tools/WebKitTestRunner/wpe/TestControllerWPE.cpp	2021-10-18 12:43:12 UTC (rev 284367)
+++ trunk/Tools/WebKitTestRunner/wpe/TestControllerWPE.cpp	2021-10-18 13:07:09 UTC (rev 284368)
@@ -27,9 +27,11 @@
 #include "TestController.h"
 
 #include "PlatformWebView.h"
+#include <cairo.h>
 #include <glib.h>
 #include <wtf/RunLoop.h>
 #include <wtf/glib/GUniquePtr.h>
+#include <wtf/text/Base64.h>
 
 namespace WTR {
 
@@ -146,4 +148,15 @@
     return features;
 }
 
+WKRetainPtr<WKStringRef> TestController::takeViewPortSnapshot()
+{
+    Vector<unsigned char> output;
+    cairo_surface_write_to_png_stream(mainWebView()->windowSnapshotImage(), [](void* output, const unsigned char* data, unsigned length) -> cairo_status_t {
+        reinterpret_cast<Vector<unsigned char>*>(output)->append(data, length);
+        return CAIRO_STATUS_SUCCESS;
+    }, &output);
+    auto uri = makeString("data:image/png;base64,", base64Encoded(output.data(), output.size()));
+    return adoptWK(WKStringCreateWithUTF8CString(uri.utf8().data()));
+}
+
 } // namespace WTR
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to