Diff
Modified: trunk/LayoutTests/ChangeLog (264606 => 264607)
--- trunk/LayoutTests/ChangeLog 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/LayoutTests/ChangeLog 2020-07-20 18:30:48 UTC (rev 264607)
@@ -1,3 +1,18 @@
+2020-07-20 Philippe Normand <[email protected]>
+
+ [GStreamer] Add support for canvas captureStream, tests failing since they were added in r213598
+ https://bugs.webkit.org/show_bug.cgi?id=169811
+
+ Reviewed by Darin Adler.
+
+ Unflag passing tests and rebaseline one platform-specific WPT test expectation which differs
+ from the default by only one line.
+
+ * platform/glib/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt: Added.
+ * platform/gtk/TestExpectations:
+ * platform/gtk/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt: Removed.
+ * platform/wpe/TestExpectations:
+
2020-07-20 Youenn Fablet <[email protected]>
Fix buggy assert in h265_vps_sps_pps_tracker.cc
Added: trunk/LayoutTests/platform/glib/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt (0 => 264607)
--- trunk/LayoutTests/platform/glib/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt (rev 0)
+++ trunk/LayoutTests/platform/glib/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt 2020-07-20 18:30:48 UTC (rev 264607)
@@ -0,0 +1,28 @@
+When prompted, accept to share your video stream.
+
+Description
+
+This test checks that the MediaStream object returned by the success callback in getUserMedia can be properly assigned to a video element via the srcObject attribute.
+
+
+
+Harness Error (TIMEOUT), message = null
+
+PASS Tests that a MediaStream can be assigned to a video element with srcObject
+PASS Tests that a MediaStream assigned to a video element is not seekable
+PASS Tests that a MediaStream assigned to a video element is in readyState HAVE_NOTHING initially
+TIMEOUT Tests that a MediaStream assigned to a video element has expected duration Test timed out
+NOTRUN Tests that a video element with a MediaStream assigned is not preloaded
+NOTRUN Tests that a video element with a MediaStream assigned ignores playbackRate attributes (defaultPlaybackRate is identical)
+NOTRUN Tests that a video element with a MediaStream assigned ignores playbackRate attributes (defaultPlaybackRate is different)
+NOTRUN Tests that a media element with an assigned MediaStream reports the played attribute as expected
+NOTRUN Tests that a media element with an assigned MediaStream reports the currentTime attribute as expected
+NOTRUN Tests that a media element with an assigned MediaStream starts its timeline at 0 regardless of when the MediaStream was created
+NOTRUN Tests that a media element with an assigned MediaStream does not advance currentTime while paused
+NOTRUN Tests that a media element with an assigned MediaStream does not start advancing currentTime until potentially playing
+NOTRUN Tests that the loop attribute has no effect on a media element with an assigned MediaStream
+NOTRUN Tests that a media element with an assigned MediaStream ends when the MediaStream becomes inactive through tracks ending
+NOTRUN Tests that an audio element with an assigned MediaStream ends when the MediaStream becomes inaudible through audio tracks ending
+NOTRUN Tests that a media element with an assigned MediaStream ends when the MediaStream becomes inactive through track removal
+NOTRUN Tests that an audio element with an assigned MediaStream ends when the MediaStream becomes inaudible through track removal
+
Modified: trunk/LayoutTests/platform/gtk/TestExpectations (264606 => 264607)
--- trunk/LayoutTests/platform/gtk/TestExpectations 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/LayoutTests/platform/gtk/TestExpectations 2020-07-20 18:30:48 UTC (rev 264607)
@@ -570,12 +570,6 @@
fast/mediastream/MediaDevices-addEventListener.html [ DumpJSConsoleLogInStdErr ]
-# Canvas captureStream support is not implemented
-webkit.org/b/169811 fast/mediacapturefromelement [ Skip ]
-webkit.org/b/169811 fast/mediastream/captureStream/ [ Failure ]
-webkit.org/b/169811 fast/mediastream/captureStream/canvas2d.html [ Crash Timeout ]
-webkit.org/b/169811 fast/mediastream/captureStream/canvas3d.html [ Crash Timeout ]
-
# No support for GPUProcess yet
fast/mediastream/captureInGPUProcess.html [ Skip ]
@@ -3303,8 +3297,6 @@
webkit.org/b/186601 fullscreen/full-screen-layer-dump.html [ Failure ]
-webkit.org/b/186845 fast/mediastream/captureStream/canvas2d-heavy-drawing.html [ Failure Timeout ]
-
webkit.org/b/186144 transitions/move-after-transition.html [ Failure Timeout ]
webkit.org/b/187268 compositing/backing/backing-store-attachment-outside-viewport.html [ Failure ]
Deleted: trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt (264606 => 264607)
--- trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/LayoutTests/platform/gtk/imported/w3c/web-platform-tests/mediacapture-streams/MediaStream-MediaElement-srcObject.https-expected.txt 2020-07-20 18:30:48 UTC (rev 264607)
@@ -1,26 +0,0 @@
-When prompted, accept to share your video stream.
-
-Description
-
-This test checks that the MediaStream object returned by the success callback in getUserMedia can be properly assigned to a video element via the srcObject attribute.
-
-
-
-FAIL Tests that a MediaStream can be assigned to a video element with srcObject promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a MediaStream assigned to a video element is not seekable promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a MediaStream assigned to a video element is in readyState HAVE_NOTHING initially promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a MediaStream assigned to a video element has expected duration promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a video element with a MediaStream assigned is not preloaded promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a video element with a MediaStream assigned ignores playbackRate attributes (defaultPlaybackRate is identical) promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a video element with a MediaStream assigned ignores playbackRate attributes (defaultPlaybackRate is different) promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a media element with an assigned MediaStream reports the played attribute as expected promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a media element with an assigned MediaStream reports the currentTime attribute as expected promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a media element with an assigned MediaStream starts its timeline at 0 regardless of when the MediaStream was created promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a media element with an assigned MediaStream does not advance currentTime while paused promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a media element with an assigned MediaStream does not start advancing currentTime until potentially playing promise_test: Unhandled rejection with value: object "TypeError: canvas.captureStream is not a function. (In 'canvas.captureStream()', 'canvas.captureStream' is undefined)"
-FAIL Tests that the loop attribute has no effect on a media element with an assigned MediaStream promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a media element with an assigned MediaStream ends when the MediaStream becomes inactive through tracks ending promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that an audio element with an assigned MediaStream ends when the MediaStream becomes inaudible through audio tracks ending promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that a media element with an assigned MediaStream ends when the MediaStream becomes inactive through track removal promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-FAIL Tests that an audio element with an assigned MediaStream ends when the MediaStream becomes inaudible through track removal promise_test: Unhandled rejection with value: object "TypeError: undefined is not an object (evaluating 'navigator.mediaDevices.getUserMedia')"
-
Modified: trunk/LayoutTests/platform/wpe/TestExpectations (264606 => 264607)
--- trunk/LayoutTests/platform/wpe/TestExpectations 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/LayoutTests/platform/wpe/TestExpectations 2020-07-20 18:30:48 UTC (rev 264607)
@@ -131,12 +131,6 @@
# Crash is bug #176801
webkit.org/b/160996 fast/mediastream/MediaStream-video-element-video-tracks-disabled.html [ Timeout ImageOnlyFailure ]
-# Canvas captureStream support is not implemented
-webkit.org/b/169811 fast/mediacapturefromelement [ Skip ]
-webkit.org/b/169811 fast/mediastream/captureStream/ [ Failure ]
-webkit.org/b/169811 fast/mediastream/captureStream/canvas2d.html [ Timeout ]
-webkit.org/b/169811 fast/mediastream/captureStream/canvas3d.html [ Timeout ]
-
# MediaRecorder is not currently implemented
http/wpt/mediarecorder [ Skip ]
imported/w3c/web-platform-tests/mediacapture-record [ Skip ]
Modified: trunk/Source/WebCore/ChangeLog (264606 => 264607)
--- trunk/Source/WebCore/ChangeLog 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/Source/WebCore/ChangeLog 2020-07-20 18:30:48 UTC (rev 264607)
@@ -1,3 +1,29 @@
+2020-07-20 Philippe Normand <[email protected]>
+
+ [GStreamer] Add support for canvas captureStream, tests failing since they were added in r213598
+ https://bugs.webkit.org/show_bug.cgi?id=169811
+
+ Reviewed by Darin Adler.
+
+ Hook captureStream support in GStreamer ports. The only missing bits were:
+
+ 1. create a MediaSample from a BGRA buffer
+ 2. convert a MediaSample to a RGBA buffer (used only for layout tests)
+ 3. set video width and height tags not only on video capture tracks (tracks created from
+ captureStream are not GStreamer capture device tracks)
+
+ * html/HTMLCanvasElement.cpp:
+ (WebCore::HTMLCanvasElement::toMediaSample):
+ * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h: Refactor createImageSample to
+ use unsigned for dimensions.
+ * platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm:
+ * platform/graphics/gstreamer/MediaSampleGStreamer.cpp:
+ (WebCore::MediaSampleGStreamer::createImageSample):
+ (WebCore::MediaSampleGStreamer::getRGBAImageData const):
+ * platform/graphics/gstreamer/MediaSampleGStreamer.h:
+ * platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp:
+ (mediaStreamTrackPrivateGetTags):
+
2020-07-20 Youenn Fablet <[email protected]>
GenerateCertificateAsync should be called on signaling thread
Modified: trunk/Source/WebCore/html/HTMLCanvasElement.cpp (264606 => 264607)
--- trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/Source/WebCore/html/HTMLCanvasElement.cpp 2020-07-20 18:30:48 UTC (rev 264607)
@@ -87,15 +87,19 @@
#include "WebXRSystem.h"
#endif
+#if USE(CG)
+#include "ImageBufferUtilitiesCG.h"
+#endif
+
+#if USE(GSTREAMER)
+#include "MediaSampleGStreamer.h"
+#endif
+
#if PLATFORM(COCOA)
#include "MediaSampleAVFObjC.h"
#include <pal/cf/CoreMediaSoftLink.h>
#endif
-#if USE(CG)
-#include "ImageBufferUtilitiesCG.h"
-#endif
-
namespace WebCore {
WTF_MAKE_ISO_ALLOCATED_IMPL(HTMLCanvasElement);
@@ -789,6 +793,9 @@
#if PLATFORM(COCOA)
makeRenderingResultsAvailable();
return MediaSampleAVFObjC::createImageSample(imageBuffer->toBGRAData(), width(), height());
+#elif USE(GSTREAMER)
+ makeRenderingResultsAvailable();
+ return MediaSampleGStreamer::createImageSample(imageBuffer->toBGRAData(), width(), height());
#else
return nullptr;
#endif
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h (264606 => 264607)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.h 2020-07-20 18:30:48 UTC (rev 264607)
@@ -37,7 +37,7 @@
static Ref<MediaSampleAVFObjC> create(CMSampleBufferRef sample, int trackID) { return adoptRef(*new MediaSampleAVFObjC(sample, trackID)); }
static Ref<MediaSampleAVFObjC> create(CMSampleBufferRef sample, AtomString trackID) { return adoptRef(*new MediaSampleAVFObjC(sample, trackID)); }
static Ref<MediaSampleAVFObjC> create(CMSampleBufferRef sample, VideoRotation rotation = VideoRotation::None, bool mirrored = false) { return adoptRef(*new MediaSampleAVFObjC(sample, rotation, mirrored)); }
- static RefPtr<MediaSampleAVFObjC> createImageSample(Vector<uint8_t>&&, unsigned long width, unsigned long height);
+ static RefPtr<MediaSampleAVFObjC> createImageSample(Vector<uint8_t>&&, unsigned width, unsigned height);
WEBCORE_EXPORT static void setAsDisplayImmediately(MediaSample&);
static RetainPtr<CMSampleBufferRef> cloneSampleBufferAndSetAsDisplayImmediately(CMSampleBufferRef);
Modified: trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm (264606 => 264607)
--- trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/Source/WebCore/platform/graphics/avfoundation/objc/MediaSampleAVFObjC.mm 2020-07-20 18:30:48 UTC (rev 264607)
@@ -46,7 +46,7 @@
WTF::VectorMalloc::free(array);
}
-RefPtr<MediaSampleAVFObjC> MediaSampleAVFObjC::createImageSample(Vector<uint8_t>&& array, unsigned long width, unsigned long height)
+RefPtr<MediaSampleAVFObjC> MediaSampleAVFObjC::createImageSample(Vector<uint8_t>&& array, unsigned width, unsigned height)
{
CVPixelBufferRef pixelBuffer = nullptr;
auto status = CVPixelBufferCreateWithBytes(kCFAllocatorDefault, width, height, kCVPixelFormatType_32BGRA, array.data(), width * 4, releaseUint8Vector, array.releaseBuffer().leakPtr(), NULL, &pixelBuffer);
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.cpp (264606 => 264607)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.cpp 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.cpp 2020-07-20 18:30:48 UTC (rev 264607)
@@ -23,6 +23,8 @@
#include "GStreamerCommon.h"
+#include <_javascript_Core/JSCInlines.h>
+#include <_javascript_Core/TypedArrayInlines.h>
#include <algorithm>
#if ENABLE(VIDEO) && USE(GSTREAMER)
@@ -95,6 +97,53 @@
return adoptRef(*gstreamerMediaSample);
}
+Ref<MediaSampleGStreamer> MediaSampleGStreamer::createImageSample(Vector<uint8_t>&& bgraData, unsigned width, unsigned height)
+{
+ size_t size = bgraData.sizeInBytes();
+ auto* data = ""
+ auto buffer = adoptGRef(gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_READONLY, data, size, 0, size, data, [](gpointer data) {
+ WTF::VectorMalloc::free(data);
+ }));
+ gst_buffer_add_video_meta(buffer.get(), GST_VIDEO_FRAME_FLAG_NONE, GST_VIDEO_FORMAT_BGRA, width, height);
+ auto caps = adoptGRef(gst_caps_new_simple("video/x-raw", "format", G_TYPE_STRING, "BGRA", "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, "framerate", GST_TYPE_FRACTION, 1, 1, nullptr));
+ auto sample = adoptGRef(gst_sample_new(buffer.get(), caps.get(), nullptr, nullptr));
+ return create(WTFMove(sample), FloatSize(width, height), { });
+}
+
+RefPtr<JSC::Uint8ClampedArray> MediaSampleGStreamer::getRGBAImageData() const
+{
+ auto* caps = gst_sample_get_caps(m_sample.get());
+ GstVideoInfo inputInfo;
+ if (!gst_video_info_from_caps(&inputInfo, caps))
+ return nullptr;
+
+ // We could check the input format is RGBA before attempting a conversion, but it is very
+ // unlikely to pay off. The input format is likely to be BGRA (when the samples are created as a
+ // result of mediastream captureStream) or some YUV format if the sample is from a video capture
+ // device. This method is called only by internals during layout tests, it is thus not critical
+ // to optimize this code path.
+
+ auto outputCaps = adoptGRef(gst_caps_copy(caps));
+ gst_caps_set_simple(outputCaps.get(), "format", G_TYPE_STRING, "RGBA", nullptr);
+
+ GstVideoInfo outputInfo;
+ if (!gst_video_info_from_caps(&outputInfo, outputCaps.get()))
+ return nullptr;
+
+ int width = GST_VIDEO_INFO_WIDTH(&inputInfo);
+ int height = GST_VIDEO_INFO_HEIGHT(&inputInfo);
+ unsigned byteLength = GST_VIDEO_INFO_SIZE(&inputInfo);
+ auto bufferStorage = JSC::ArrayBuffer::create(width * height, 4);
+ auto outputBuffer = adoptGRef(gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_NO_SHARE, bufferStorage->data(), byteLength, 0, byteLength, nullptr, [](gpointer) { }));
+ gst_buffer_add_video_meta(outputBuffer.get(), GST_VIDEO_FRAME_FLAG_NONE, GST_VIDEO_FORMAT_RGBA, width, height);
+ GstMappedFrame outputFrame(outputBuffer.get(), outputInfo, GST_MAP_WRITE);
+
+ GUniquePtr<GstVideoConverter> converter(gst_video_converter_new(&inputInfo, &outputInfo, nullptr));
+ GstMappedFrame inputFrame(gst_sample_get_buffer(m_sample.get()), inputInfo, GST_MAP_READ);
+ gst_video_converter_frame(converter.get(), inputFrame.get(), outputFrame.get());
+ return JSC::Uint8ClampedArray::tryCreate(WTFMove(bufferStorage), 0, byteLength);
+}
+
void MediaSampleGStreamer::extendToTheBeginning()
{
// Only to be used with the first sample, as a hack for lack of support for edit lists.
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h (264606 => 264607)
--- trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/MediaSampleGStreamer.h 2020-07-20 18:30:48 UTC (rev 264607)
@@ -37,6 +37,7 @@
}
static Ref<MediaSampleGStreamer> createFakeSample(GstCaps*, MediaTime pts, MediaTime dts, MediaTime duration, const FloatSize& presentationSize, const AtomString& trackId);
+ static Ref<MediaSampleGStreamer> createImageSample(Vector<uint8_t>&&, unsigned width, unsigned height);
void extendToTheBeginning();
MediaTime presentationTime() const override { return m_pts; }
@@ -54,6 +55,7 @@
SampleFlags flags() const override { return m_flags; }
PlatformSample platformSample() override;
void dump(PrintStream&) const override;
+ RefPtr<JSC::Uint8ClampedArray> getRGBAImageData() const final;
protected:
MediaSampleGStreamer(GRefPtr<GstSample>&&, const FloatSize& presentationSize, const AtomString& trackId);
Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp (264606 => 264607)
--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp 2020-07-20 18:28:34 UTC (rev 264606)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerMediaStreamSource.cpp 2020-07-20 18:30:48 UTC (rev 264607)
@@ -29,7 +29,6 @@
#include "AudioTrackPrivate.h"
#include "GStreamerAudioData.h"
#include "GStreamerCommon.h"
-#include "GStreamerVideoCaptureSource.h"
#include "MediaSampleGStreamer.h"
#include "MediaStreamPrivate.h"
#include "MediaStreamTrackPrivate.h"
@@ -63,11 +62,9 @@
else if (track->type() == RealtimeMediaSource::Type::Video) {
gst_tag_list_add(tagList.get(), GST_TAG_MERGE_APPEND, WEBKIT_MEDIA_TRACK_TAG_KIND, static_cast<int>(VideoTrackPrivate::Kind::Main), nullptr);
- if (track->isCaptureTrack()) {
- GStreamerVideoCaptureSource& source = static_cast<GStreamerVideoCaptureSource&>(track->source());
- gst_tag_list_add(tagList.get(), GST_TAG_MERGE_APPEND, WEBKIT_MEDIA_TRACK_TAG_WIDTH, source.size().width(),
- WEBKIT_MEDIA_TRACK_TAG_HEIGHT, source.size().height(), nullptr);
- }
+ auto& settings = track->settings();
+ gst_tag_list_add(tagList.get(), GST_TAG_MERGE_APPEND, WEBKIT_MEDIA_TRACK_TAG_WIDTH, settings.width(),
+ WEBKIT_MEDIA_TRACK_TAG_HEIGHT, settings.height(), nullptr);
}
GST_DEBUG("Track tags: %" GST_PTR_FORMAT, tagList.get());