Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoCaptureSource.cpp (294228 => 294229)
--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoCaptureSource.cpp 2022-05-16 12:23:09 UTC (rev 294228)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoCaptureSource.cpp 2022-05-16 12:48:52 UTC (rev 294229)
@@ -145,7 +145,7 @@
g_signal_handlers_disconnect_by_func(m_capturer->sink(), reinterpret_cast<gpointer>(newSampleCallback), this);
m_capturer->stop();
- if (m_capturer->feedingFromPipewire()) {
+ if (m_capturer->isCapturingDisplay()) {
auto& manager = GStreamerDisplayCaptureDeviceManager::singleton();
manager.stopSource(persistentID());
}
@@ -162,6 +162,8 @@
if (settings.contains(RealtimeMediaSourceSettings::Flag::FrameRate))
m_capturer->setFrameRate(frameRate());
+
+ m_capturer->reconfigure();
}
void GStreamerVideoCaptureSource::sourceCapsChanged(const GstCaps* caps)
@@ -186,6 +188,7 @@
m_capturer->setSize(size().width(), size().height());
m_capturer->setFrameRate(frameRate());
+ m_capturer->reconfigure();
g_signal_connect(m_capturer->sink(), "new-sample", G_CALLBACK(newSampleCallback), this);
m_capturer->play();
}
Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoCapturer.cpp (294228 => 294229)
--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoCapturer.cpp 2022-05-16 12:23:09 UTC (rev 294228)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoCapturer.cpp 2022-05-16 12:48:52 UTC (rev 294229)
@@ -67,16 +67,43 @@
GstElement* GStreamerVideoCapturer::createConverter()
{
+ auto* bin = gst_bin_new(nullptr);
+ auto* videoscale = gst_element_factory_make("videoscale", "videoscale");
+ auto* videoconvert = gst_element_factory_make("videoconvert", nullptr);
+ auto* videorate = gst_element_factory_make("videorate", "videorate");
+
// https://gitlab.freedesktop.org/gstreamer/gst-plugins-base/issues/97#note_56575
- auto bin = makeGStreamerBin("capsfilter caps=\"video/x-raw\" name=mimetype-filter ! decodebin3 ! videoscale ! videoconvert ! videorate drop-_only_=1 average-period=1 name=videorate", false);
+ g_object_set(videorate, "drop-only", 1, "average-period", 1, nullptr);
- m_videoSrcMIMETypeFilter = adoptGRef(gst_bin_get_by_name(GST_BIN(bin), "mimetype-filter"));
- auto videorate = adoptGRef(gst_bin_get_by_name(GST_BIN(bin), "videorate"));
+ gst_bin_add_many(GST_BIN_CAST(bin), videoscale, videoconvert, videorate, nullptr);
- RELEASE_ASSERT(gst_element_add_pad(bin, gst_ghost_pad_new("sink", GST_PAD(m_videoSrcMIMETypeFilter->sinkpads->data))));
- RELEASE_ASSERT(gst_element_add_pad(bin, gst_ghost_pad_new("src", GST_PAD(videorate->srcpads->data))));
+ GstElement* head = videoscale;
+ if (!isCapturingDisplay()) {
+ m_videoSrcMIMETypeFilter = gst_element_factory_make("capsfilter", "mimetype-filter");
+ head = m_videoSrcMIMETypeFilter.get();
- adjustVideoSrcMIMEType();
+ auto caps = adoptGRef(gst_caps_new_empty_simple("video/x-raw"));
+ g_object_set(m_videoSrcMIMETypeFilter.get(), "caps", caps.get(), nullptr);
+
+ auto* decodebin = gst_element_factory_make("decodebin3", nullptr);
+ gst_bin_add_many(GST_BIN_CAST(bin), m_videoSrcMIMETypeFilter.get(), decodebin, nullptr);
+ gst_element_link(m_videoSrcMIMETypeFilter.get(), decodebin);
+
+ auto sinkPad = adoptGRef(gst_element_get_static_pad(videoscale, "sink"));
+ g_signal_connect_swapped(decodebin, "pad-added", G_CALLBACK(+[](GstPad* sinkPad, GstPad* srcPad) {
+ RELEASE_ASSERT(!gst_pad_is_linked(sinkPad));
+ gst_pad_link(srcPad, sinkPad);
+ }), sinkPad.get());
+ }
+
+ gst_element_link_many(videoscale, videoconvert, videorate, nullptr);
+
+ auto sinkPad = adoptGRef(gst_element_get_static_pad(head, "sink"));
+ gst_element_add_pad(bin, gst_ghost_pad_new("sink", sinkPad.get()));
+
+ auto srcPad = adoptGRef(gst_element_get_static_pad(videorate, "src"));
+ gst_element_add_pad(bin, gst_ghost_pad_new("src", srcPad.get()));
+
return bin;
}
@@ -91,7 +118,7 @@
bool GStreamerVideoCapturer::setSize(int width, int height)
{
- if (feedingFromPipewire()) {
+ if (isCapturingDisplay()) {
// Pipewiresrc doesn't seem to support caps re-negotiation and framerate configuration properly.
GST_FIXME_OBJECT(m_pipeline.get(), "Resizing disabled on display capture source");
return true;
@@ -110,8 +137,6 @@
m_caps = adoptGRef(gst_caps_copy(m_caps.get()));
gst_caps_set_simple(m_caps.get(), "width", G_TYPE_INT, width, "height", G_TYPE_INT, height, nullptr);
- adjustVideoSrcMIMEType();
-
if (!m_capsfilter)
return false;
@@ -121,7 +146,7 @@
bool GStreamerVideoCapturer::setFrameRate(double frameRate)
{
- if (feedingFromPipewire()) {
+ if (isCapturingDisplay()) {
// Pipewiresrc doesn't seem to support caps re-negotiation and framerate configuration properly.
GST_FIXME_OBJECT(m_pipeline.get(), "Framerate override disabled on display capture source");
return true;
@@ -144,8 +169,6 @@
m_caps = adoptGRef(gst_caps_copy(m_caps.get()));
gst_caps_set_simple(m_caps.get(), "framerate", GST_TYPE_FRACTION, numerator, denominator, nullptr);
- adjustVideoSrcMIMEType();
-
if (!m_capsfilter)
return false;
@@ -234,14 +257,20 @@
return (maxFraction > -G_MAXDOUBLE) ? std::make_optional<>(maxFraction) : std::nullopt;
}
-void GStreamerVideoCapturer::adjustVideoSrcMIMEType()
+void GStreamerVideoCapturer::reconfigure()
{
+ if (isCapturingDisplay()) {
+ // Pipewiresrc doesn't seem to support caps re-negotiation and framerate configuration properly.
+ GST_FIXME_OBJECT(m_pipeline.get(), "Caps re-negotiation disabled on display capture source");
+ return;
+ }
+
if (!m_videoSrcMIMETypeFilter)
return;
struct MimeTypeSelector {
const char* mimeType = "video/x-raw";
-
+ const char* format = nullptr;
int maxWidth = 0;
int maxHeight = 0;
double maxFrameRate = 0;
@@ -289,6 +318,7 @@
if (*width >= selector->stopCondition.width && *height >= selector->stopCondition.height
&& *frameRate >= selector->stopCondition.frameRate) {
selector->mimeType = gst_structure_get_name(structure);
+ selector->format = gst_structure_get_string(structure, "format");
return FALSE;
}
@@ -297,15 +327,19 @@
selector->maxHeight = *height;
selector->maxFrameRate = *frameRate;
selector->mimeType = gst_structure_get_name(structure);
+ selector->format = gst_structure_get_string(structure, "format");
}
return TRUE;
- }),
- &selector);
+ }), &selector);
- GST_INFO_OBJECT(m_pipeline.get(), "Setting video capture device mime type to %s", selector.mimeType);
+ auto caps = adoptGRef(gst_caps_new_empty_simple(selector.mimeType));
- auto caps = adoptGRef(gst_caps_new_empty_simple(selector.mimeType));
+ // Workaround for https://gitlab.freedesktop.org/pipewire/pipewire/-/issues/1793.
+ if (selector.format)
+ gst_caps_set_simple(caps.get(), "format", G_TYPE_STRING, selector.format, nullptr);
+
+ GST_INFO_OBJECT(m_pipeline.get(), "Setting video capture device caps to %" GST_PTR_FORMAT, caps.get());
g_object_set(m_videoSrcMIMETypeFilter.get(), "caps", caps.get(), nullptr);
}