Diff
Modified: trunk/Source/WebCore/ChangeLog (237800 => 237801)
--- trunk/Source/WebCore/ChangeLog 2018-11-05 15:05:39 UTC (rev 237800)
+++ trunk/Source/WebCore/ChangeLog 2018-11-05 15:09:54 UTC (rev 237801)
@@ -1,5 +1,47 @@
2018-11-05 Thibault Saunier <[email protected]>
+ [GStreamer][WebRTC] Add webrtcencoder bin to cleanup and refactor the way we set encoders
+ https://bugs.webkit.org/show_bug.cgi?id=190674
+
+ Reviewed by Philippe Normand.
+
+ webrtcencoder is a simple GstBin with a set of well known GStreamer encoders which
+ it can use to implement encoding for different formats exposing a trimmed down unified API.
+
+ It also adds proper handling of H264 profiles.
+
+ The added files follow GStreamer coding style as we aim at upstreaming the element
+ in the future.
+
+ This is a refactoring so current tests already cover it.
+
+ * platform/GStreamer.cmake:
+ * platform/graphics/gstreamer/MediaPlayerPrivateGStreamerBase.cpp:
+ (WebCore::MediaPlayerPrivateGStreamerBase::initializeGStreamerAndRegisterWebKitElements):
+ * platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp: Added.
+ (gst_webrtc_video_encoder_get_property):
+ (gst_webrtc_video_encoder_set_bitrate):
+ (gst_webrtc_video_encoder_set_format):
+ (gst_webrtc_video_encoder_set_property):
+ (register_known_encoder):
+ (setup_x264enc):
+ (setup_vp8enc):
+ (setup_openh264enc):
+ (set_bitrate_kbit_per_sec):
+ (set_bitrate_bit_per_sec):
+ (gst_webrtc_video_encoder_class_init):
+ (gst_webrtc_video_encoder_init):
+ * platform/mediastream/libwebrtc/GStreamerVideoEncoder.h: Added.
+ * platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp:
+ (WebCore::GStreamerVideoEncoder::GStreamerVideoEncoder):
+ (WebCore::GStreamerVideoEncoder::InitEncode):
+ (WebCore::GStreamerVideoEncoder::createEncoder):
+ (WebCore::GStreamerVideoEncoder::AddCodecIfSupported):
+ (WebCore::GStreamerVideoEncoder::ImplementationName const):
+ (WebCore::GStreamerVideoEncoder::SetRestrictionCaps):
+
+2018-11-05 Thibault Saunier <[email protected]>
+
[GStreamer][WebRTC] properly mark H.264 stream type in the "decoder"
https://bugs.webkit.org/show_bug.cgi?id=190676
Modified: trunk/Source/WebCore/platform/GStreamer.cmake (237800 => 237801)
--- trunk/Source/WebCore/platform/GStreamer.cmake 2018-11-05 15:05:39 UTC (rev 237800)
+++ trunk/Source/WebCore/platform/GStreamer.cmake 2018-11-05 15:09:54 UTC (rev 237801)
@@ -34,6 +34,7 @@
platform/graphics/gstreamer/mse/WebKitMediaSourceGStreamer.cpp
platform/mediastream/libwebrtc/GStreamerVideoDecoderFactory.cpp
+ platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp
platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp
platform/mediastream/libwebrtc/LibWebRTCAudioModule.cpp
Added: trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp (0 => 237801)
--- trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp 2018-11-05 15:09:54 UTC (rev 237801)
@@ -0,0 +1,343 @@
+/*
+ * Copyright (C) 2018 Metrological Group B.V.
+ * Copyright (C) 2018 Igalia S.L. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+/* NOTE: This file respects GStreamer coding style as we might want to upstream
+ * that element in the future */
+
+#include "config.h"
+
+#if ENABLE(VIDEO) && ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC) && USE(GSTREAMER)
+#include "GStreamerVideoEncoder.h"
+
+GST_DEBUG_CATEGORY (gst_webrtcenc_debug);
+#define GST_CAT_DEFAULT gst_webrtcenc_debug
+
+#define KBIT_TO_BIT 1024
+
+static GstStaticPadTemplate sinkTemplate = GST_STATIC_PAD_TEMPLATE ("sink",
+ GST_PAD_SINK,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-raw(ANY);"));
+
+static GstStaticPadTemplate srcTemplate = GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS ("video/x-h264;video/x-vp8"));
+
+typedef void (*SetBitrateFunc) (GObject * encoder, const gchar * propname,
+ gint bitrate);
+typedef void (*SetupEncoder) (GObject * encoder);
+typedef struct
+{
+ gboolean avalaible;
+ GstCaps *caps;
+ const gchar *name;
+ const gchar *parser_name;
+ GstCaps *encoded_format;
+ SetBitrateFunc setBitrate;
+ SetupEncoder setupEncoder;
+ const gchar *bitrate_propname;
+} EncoderDefinition;
+
+typedef enum
+{
+ ENCODER_NONE = 0,
+ ENCODER_X264,
+ ENCODER_OPENH264,
+ ENCODER_VP8,
+ ENCODER_LAST,
+} EncoderId;
+
+EncoderDefinition encoders[ENCODER_LAST] = {
+ FALSE,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+ NULL,
+};
+
+typedef struct
+{
+ EncoderId encoderId;
+ GstElement *encoder;
+ GstElement *parser;
+ GstElement *capsfilter;
+ guint bitrate;
+} GstWebrtcVideoEncoderPrivate;
+
+/* *INDENT-OFF* */
+G_DEFINE_TYPE_WITH_PRIVATE (GstWebrtcVideoEncoder, gst_webrtc_video_encoder,
+ GST_TYPE_BIN)
+#define PRIV(self) ((GstWebrtcVideoEncoderPrivate*)gst_webrtc_video_encoder_get_instance_private(self))
+/* *INDENT-ON* */
+
+enum
+{
+ PROP_0,
+ PROP_FORMAT,
+ PROP_ENCODER,
+ PROP_BITRATE,
+ N_PROPS
+};
+
+static void
+gst_webrtc_video_encoder_finalize (GObject * object)
+{
+ G_OBJECT_CLASS (gst_webrtc_video_encoder_parent_class)->finalize (object);
+}
+
+static void
+gst_webrtc_video_encoder_get_property (GObject * object,
+ guint prop_id, GValue * value, GParamSpec * pspec)
+{
+ GstWebrtcVideoEncoder *self = GST_WEBRTC_VIDEO_ENCODER (object);
+ GstWebrtcVideoEncoderPrivate *priv = PRIV (self);
+
+ switch (prop_id) {
+ case PROP_FORMAT:
+ if (priv->encoderId != ENCODER_NONE)
+ g_value_set_boxed (value, encoders[priv->encoderId].caps);
+ else
+ g_value_set_boxed (value, NULL);
+ break;
+ case PROP_ENCODER:
+ g_value_set_object (value, priv->encoder);
+ break;
+ case PROP_BITRATE:
+ g_value_set_uint (value, priv->bitrate);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+gst_webrtc_video_encoder_set_bitrate (GstWebrtcVideoEncoder * self,
+ guint bitrate)
+{
+ GstWebrtcVideoEncoderPrivate *priv = PRIV (self);
+
+ priv->bitrate = bitrate;
+ if (priv->encoder) {
+ encoders[priv->encoderId].setBitrate (G_OBJECT (priv->encoder),
+ encoders[priv->encoderId].bitrate_propname, priv->bitrate);
+ }
+}
+
+static void
+gst_webrtc_video_encoder_set_format (GstWebrtcVideoEncoder * self,
+ const GstCaps * caps)
+{
+ gint i;
+ GstWebrtcVideoEncoderPrivate *priv = PRIV (self);
+ g_return_if_fail (priv->encoderId == ENCODER_NONE);
+ g_return_if_fail (caps);
+
+ for (i = 1; i < ENCODER_LAST; i++) {
+ if (encoders[i].avalaible
+ && gst_caps_can_intersect (encoders[i].caps, caps)) {
+ GstPad *tmppad;
+ priv->encoderId = (EncoderId) i;
+ priv->encoder = gst_element_factory_make (encoders[i].name, NULL);
+ encoders[priv->encoderId].setupEncoder (G_OBJECT (priv->encoder));
+
+ if (encoders[i].parser_name)
+ priv->parser = gst_element_factory_make (encoders[i].parser_name, NULL);
+
+ if (encoders[i].encoded_format) {
+ priv->capsfilter = gst_element_factory_make ("capsfilter", NULL);
+ g_object_set (priv->capsfilter, "caps", encoders[i].encoded_format,
+ NULL);
+ }
+
+ gst_bin_add (GST_BIN (self), priv->encoder);
+
+ tmppad = gst_element_get_static_pad (priv->encoder, "sink");
+ gst_ghost_pad_set_target (GST_GHOST_PAD (GST_ELEMENT (self)->
+ sinkpads->data), tmppad);
+ gst_object_unref (tmppad);
+
+ tmppad = gst_element_get_static_pad (priv->encoder, "src");
+ if (priv->parser) {
+ gst_bin_add (GST_BIN (self), priv->parser);
+ gst_element_link (priv->encoder, priv->parser);
+ gst_object_unref (tmppad);
+ tmppad = gst_element_get_static_pad (priv->parser, "src");
+ }
+
+ if (priv->capsfilter) {
+ GstPad *tmppad2 = gst_element_get_static_pad (priv->capsfilter, "sink");
+
+ gst_bin_add (GST_BIN (self), priv->capsfilter);
+ gst_pad_link (tmppad, tmppad2);
+ gst_object_unref (tmppad);
+ tmppad = gst_element_get_static_pad (priv->capsfilter, "src");
+ gst_object_unref (tmppad2);
+ }
+
+ g_assert (gst_ghost_pad_set_target (GST_GHOST_PAD (GST_ELEMENT
+ (self)->srcpads->data), tmppad));
+ gst_object_unref (tmppad);
+
+ gst_webrtc_video_encoder_set_bitrate (self, priv->bitrate);
+ return;
+ }
+ }
+
+ GST_ERROR ("No encoder found for format %" GST_PTR_FORMAT, caps);
+}
+
+static void
+gst_webrtc_video_encoder_set_property (GObject * object,
+ guint prop_id, const GValue * value, GParamSpec * pspec)
+{
+ GstWebrtcVideoEncoder *self = GST_WEBRTC_VIDEO_ENCODER (object);
+
+ switch (prop_id) {
+ case PROP_FORMAT:
+ gst_webrtc_video_encoder_set_format (self, gst_value_get_caps (value));
+ break;
+ case PROP_BITRATE:
+ gst_webrtc_video_encoder_set_bitrate (self, g_value_get_uint (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ }
+}
+
+static void
+register_known_encoder (EncoderId encId, const gchar * name,
+ const gchar * parser_name, const gchar * caps, const gchar * encoded_format,
+ SetupEncoder setupEncoder, const gchar * bitrate_propname,
+ SetBitrateFunc setBitrate)
+{
+ GstPluginFeature *feature =
+ gst_registry_lookup_feature (gst_registry_get (), name);
+ if (!feature) {
+ GST_WARNING ("Could not find %s", name);
+ encoders[encId].avalaible = FALSE;
+
+ return;
+ }
+ gst_object_unref (feature);
+
+ encoders[encId].avalaible = TRUE;
+ encoders[encId].name = name;
+ encoders[encId].parser_name = parser_name;
+ encoders[encId].caps = gst_caps_from_string (caps);
+ if (encoded_format)
+ encoders[encId].encoded_format = gst_caps_from_string (encoded_format);
+ else
+ encoders[encId].encoded_format = NULL;
+ encoders[encId].setupEncoder = setupEncoder;
+ encoders[encId].bitrate_propname = bitrate_propname;
+ encoders[encId].setBitrate = setBitrate;
+}
+
+static void
+setup_x264enc (GObject * encoder)
+{
+ gst_util_set_object_arg (encoder, "tune", "zerolatency");
+}
+
+static void
+setup_vp8enc (GObject * encoder)
+{
+ gst_preset_load_preset (GST_PRESET (encoder), "Profile Realtime");
+}
+
+static void
+setup_openh264enc (GObject *)
+{
+}
+
+static void
+set_bitrate_kbit_per_sec (GObject * encoder, const gchar * prop_name,
+ gint bitrate)
+{
+ g_object_set (encoder, prop_name, bitrate, NULL);
+}
+
+static void
+set_bitrate_bit_per_sec (GObject * encoder, const gchar * prop_name,
+ gint bitrate)
+{
+ g_object_set (encoder, prop_name, bitrate * KBIT_TO_BIT, NULL);
+}
+
+static void
+gst_webrtc_video_encoder_class_init (GstWebrtcVideoEncoderClass * klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ GST_DEBUG_CATEGORY_INIT (gst_webrtcenc_debug, "webrtcencoder", 0,
+ "Video encoder for WebRTC");
+
+ object_class->finalize = gst_webrtc_video_encoder_finalize;
+ object_class->get_property = gst_webrtc_video_encoder_get_property;
+ object_class->set_property = gst_webrtc_video_encoder_set_property;
+
+ g_object_class_install_property (object_class, PROP_FORMAT,
+ g_param_spec_boxed ("format", "Format as caps",
+ "Set the caps of the format to be used.",
+ GST_TYPE_CAPS,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (object_class, PROP_ENCODER,
+ g_param_spec_object ("encoder", "The actual encoder element",
+ "The encoder element", GST_TYPE_ELEMENT,
+ (GParamFlags) (G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)));
+
+ g_object_class_install_property (object_class, PROP_BITRATE,
+ g_param_spec_uint ("bitrate", "Bitrate",
+ "The bitrate in kbit per second", 0, G_MAXINT, 2048,
+ (GParamFlags) (G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS |
+ G_PARAM_CONSTRUCT)));
+
+ register_known_encoder (ENCODER_X264, "x264enc", "h264parse", "video/x-h264",
+ "video/x-h264,alignment=au,stream-format=byte-stream,profile=""
+ setup_x264enc, "bitrate", set_bitrate_kbit_per_sec);
+ register_known_encoder (ENCODER_OPENH264, "openh264enc", "h264parse",
+ "video/x-h264",
+ "video/x-h264,alignment=au,stream-format=byte-stream,profile=""
+ setup_openh264enc, "bitrate", set_bitrate_kbit_per_sec);
+ register_known_encoder (ENCODER_VP8, "vp8enc", NULL, "video/x-vp8", NULL,
+ setup_vp8enc, "target-bitrate", set_bitrate_bit_per_sec);
+}
+
+static void
+gst_webrtc_video_encoder_init (GstWebrtcVideoEncoder * self)
+{
+ GstWebrtcVideoEncoderPrivate *priv = PRIV (self);
+
+ priv->encoderId = ENCODER_NONE;
+ gst_element_add_pad (GST_ELEMENT (self),
+ gst_ghost_pad_new_no_target_from_template ("sink",
+ gst_static_pad_template_get (&sinkTemplate)));
+
+ gst_element_add_pad (GST_ELEMENT (self),
+ gst_ghost_pad_new_no_target_from_template ("src",
+ gst_static_pad_template_get (&srcTemplate)));
+}
+
+#endif // ENABLE(VIDEO) && ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC) && USE(GSTREAMER)
Added: trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.h (0 => 237801)
--- trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.h (rev 0)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.h 2018-11-05 15:09:54 UTC (rev 237801)
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2018 Metrological Group B.V.
+ * Copyright (C) 2018 Igalia S.L. All rights reserved.
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Library General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Library General Public License for more details.
+ *
+ * You should have received a copy of the GNU Library General Public License
+ * aint with this library; see the file COPYING.LIB. If not, write to
+ * the Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
+ * Boston, MA 02110-1301, USA.
+ */
+
+#pragma once
+
+#include <gst/gst.h>
+
+G_BEGIN_DECLS
+
+#define GST_TYPE_WEBRTC_VIDEO_ENCODER (gst_webrtc_video_encoder_get_type())
+
+G_DECLARE_DERIVABLE_TYPE (GstWebrtcVideoEncoder, gst_webrtc_video_encoder, GST, WEBRTC_VIDEO_ENCODER, GstBin)
+
+struct _GstWebrtcVideoEncoderClass
+{
+ GstBinClass parent_class;
+};
+
+G_END_DECLS
Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp (237800 => 237801)
--- trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp 2018-11-05 15:05:39 UTC (rev 237800)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp 2018-11-05 15:09:54 UTC (rev 237801)
@@ -23,6 +23,7 @@
#if ENABLE(VIDEO) && ENABLE(MEDIA_STREAM) && USE(LIBWEBRTC) && USE(GSTREAMER)
#include "GStreamerVideoEncoderFactory.h"
+#include "GStreamerVideoEncoder.h"
#include "GStreamerVideoFrameLibWebRTC.h"
#include "webrtc/common_video/h264/h264_common.h"
#include "webrtc/common_video/h264/profile_level_id.h"
@@ -63,13 +64,11 @@
GStreamerVideoEncoder(const webrtc::SdpVideoFormat&)
: m_firstFramePts(GST_CLOCK_TIME_NONE)
, m_restrictionCaps(adoptGRef(gst_caps_new_empty_simple("video/x-raw")))
- , m_bitrateSetter(nullptr)
{
}
GStreamerVideoEncoder()
: m_firstFramePts(GST_CLOCK_TIME_NONE)
, m_restrictionCaps(adoptGRef(gst_caps_new_empty_simple("video/x-raw")))
- , m_bitrateSetter(nullptr)
{
}
@@ -83,8 +82,8 @@
SetRestrictionCaps(WTFMove(caps));
- if (m_bitrateSetter && m_encoder)
- m_bitrateSetter(m_encoder, newBitrate);
+ if (m_encoder)
+ g_object_set(m_encoder, "bitrate", newBitrate, nullptr);
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -118,20 +117,26 @@
m_pipeline = makeElement("pipeline");
connectSimpleBusMessageCallback(m_pipeline.get());
- auto encodebin = createEncoder(&m_encoder).leakRef();
- ASSERT(m_encoder);
- m_bitrateSetter = getBitrateSetter(gst_element_get_factory(m_encoder));
+ auto encoder = createEncoder();
+ ASSERT(encoder);
+ m_encoder = encoder.get();
m_src = makeElement("appsrc");
g_object_set(m_src, "is-live", true, "format", GST_FORMAT_TIME, nullptr);
- auto capsfilter = CreateFilter();
+ auto videoconvert = makeElement("videoconvert");
+ auto videorate = makeElement("videorate");
auto sink = makeElement("appsink");
gst_app_sink_set_emit_signals(GST_APP_SINK(sink), TRUE);
g_signal_connect(sink, "new-sample", G_CALLBACK(newSampleCallbackTramp), this);
- gst_bin_add_many(GST_BIN(m_pipeline.get()), m_src, encodebin, capsfilter, sink, nullptr);
- if (!gst_element_link_many(m_src, encodebin, capsfilter, sink, nullptr))
+ auto name = String::format("%s_enc_rawcapsfilter_%p", Name(), this);
+ m_capsFilter = gst_element_factory_make("capsfilter", name.utf8().data());
+ if (m_restrictionCaps)
+ g_object_set(m_capsFilter, "caps", m_restrictionCaps.get(), nullptr);
+
+ gst_bin_add_many(GST_BIN(m_pipeline.get()), m_src, videorate, videoconvert, m_capsFilter, encoder.leakRef(), sink, nullptr);
+ if (!gst_element_link_many(m_src, videorate, videoconvert, m_capsFilter, m_encoder, sink, nullptr))
ASSERT_NOT_REACHED();
gst_element_set_state(m_pipeline.get(), GST_STATE_PLAYING);
@@ -144,11 +149,6 @@
return true;
}
- virtual GstElement* CreateFilter()
- {
- return makeElement("capsfilter");
- }
-
int32_t RegisterEncodeCompleteCallback(webrtc::EncodedImageCallback* callback) final
{
m_imageReadyCb = callback;
@@ -160,12 +160,16 @@
{
m_encodedFrame._buffer = nullptr;
m_encodedImageBuffer.reset();
- GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline.get())));
- gst_bus_set_sync_handler(bus.get(), nullptr, nullptr, nullptr);
+ if (m_pipeline) {
+ GRefPtr<GstBus> bus = adoptGRef(gst_pipeline_get_bus(GST_PIPELINE(m_pipeline.get())));
+ gst_bus_set_sync_handler(bus.get(), nullptr, nullptr, nullptr);
- gst_element_set_state(m_pipeline.get(), GST_STATE_NULL);
- m_src = nullptr;
- m_pipeline = nullptr;
+ gst_element_set_state(m_pipeline.get(), GST_STATE_NULL);
+ m_src = nullptr;
+ m_encoder = nullptr;
+ m_capsFilter = nullptr;
+ m_pipeline = nullptr;
+ }
return WEBRTC_VIDEO_CODEC_OK;
}
@@ -255,75 +259,21 @@
return GST_FLOW_OK;
}
-#define RETURN_BITRATE_SETTER_IF_MATCHES(regex, propertyName, bitrateMultiplier, unit) \
- if (g_regex_match(regex.get(), factoryName, static_cast<GRegexMatchFlags>(0), nullptr)) { \
- GST_INFO_OBJECT(encoderFactory, "Detected as having a " #propertyName " property in " unit); \
- return [](GstElement* encoder, uint32_t bitrate) \
- { \
- g_object_set(encoder, propertyName, bitrate * bitrateMultiplier, nullptr); \
- }; \
- }
-
- // GStreamer doesn't have a unified encoder API and the encoders have their
- // own semantics and naming to set the bitrate, this is a best effort to handle
- // setting bitrate for the well known encoders.
- // See https://bugzilla.gnome.org/show_bug.cgi?id=796716
- BitrateSetter getBitrateSetter(GstElementFactory* encoderFactory)
+ GRefPtr<GstElement> createEncoder(void)
{
- static std::once_flag regexRegisteredFlag;
+ GRefPtr<GstElement> encoder = nullptr;
+ GstElement* webrtcencoder = GST_ELEMENT(g_object_ref_sink(gst_element_factory_make("webrtcvideoencoder", NULL)));
- std::call_once(regexRegisteredFlag, [] {
- targetBitrateBitPerSec = g_regex_new("^vp.enc$|^omx.*enc$", static_cast<GRegexCompileFlags>(0), static_cast<GRegexMatchFlags>(0), nullptr);
- bitrateBitPerSec = g_regex_new("^openh264enc$", static_cast<GRegexCompileFlags>(0), static_cast<GRegexMatchFlags>(0), nullptr);
- bitrateKBitPerSec = g_regex_new("^x264enc$|vaapi.*enc$", static_cast<GRegexCompileFlags>(0), static_cast<GRegexMatchFlags>(0), nullptr);
- ASSERT(targetBitrateBitPerSec.get() && bitrateBitPerSec.get() && bitrateKBitPerSec.get());
- });
+ g_object_set(webrtcencoder, "format", adoptGRef(gst_caps_from_string(Caps())).get(), NULL);
+ g_object_get(webrtcencoder, "encoder", &encoder.outPtr(), NULL);
- auto factoryName = GST_OBJECT_NAME(encoderFactory);
- RETURN_BITRATE_SETTER_IF_MATCHES(targetBitrateBitPerSec, "target-bitrate", KBIT_TO_BIT, "Bits Per Second")
- RETURN_BITRATE_SETTER_IF_MATCHES(bitrateBitPerSec, "bitrate", KBIT_TO_BIT, "Bits Per Second")
- RETURN_BITRATE_SETTER_IF_MATCHES(bitrateKBitPerSec, "bitrate", 1, "KBits Per Second")
+ if (!encoder) {
+ GST_INFO("No encoder found for %s", Caps());
- GST_WARNING_OBJECT(encoderFactory, "unkonwn encoder, can't set bitrates on it");
- return nullptr;
- }
-#undef RETURN_BITRATE_SETTER_IF_MATCHES
-
- GRefPtr<GstElement> createEncoder(GstElement** encoder)
- {
- GstElement* enc = nullptr;
-
- m_profile = GST_ENCODING_PROFILE(gst_encoding_video_profile_new(
- adoptGRef(gst_caps_from_string(Caps())).get(),
- ProfileName(),
- gst_caps_ref(m_restrictionCaps.get()),
- 1));
- GRefPtr<GstElement> encodebin = makeElement("encodebin");
-
- if (!encodebin.get()) {
- GST_ERROR("No encodebin present... can't use GStreamer based encoders");
return nullptr;
}
- g_object_set(encodebin.get(), "profile", m_profile.get(), nullptr);
- for (GList* tmp = GST_BIN_CHILDREN(encodebin.get()); tmp; tmp = tmp->next) {
- GstElement* elem = GST_ELEMENT(tmp->data);
- GstElementFactory* factory = gst_element_get_factory((elem));
-
- if (!factory || !gst_element_factory_list_is_type(factory, GST_ELEMENT_FACTORY_TYPE_VIDEO_ENCODER))
- continue;
-
- enc = elem;
- break;
- }
-
- if (!enc)
- return nullptr;
-
- if (encoder)
- *encoder = enc;
-
- return encodebin;
+ return webrtcencoder;
}
void AddCodecIfSupported(std::vector<webrtc::SdpVideoFormat>* supportedFormats)
@@ -330,7 +280,7 @@
{
GstElement* encoder;
- if (createEncoder(&encoder).get() != nullptr) {
+ if (createEncoder().get() != nullptr) {
webrtc::SdpVideoFormat format = ConfigureSupportedCodec(encoder);
supportedFormats->push_back(format);
@@ -380,9 +330,12 @@
const char* ImplementationName() const
{
+ GRefPtr<GstElement> encoderImplementation;
g_return_val_if_fail(m_encoder, nullptr);
- return GST_OBJECT_NAME(gst_element_get_factory(m_encoder));
+ g_object_get(m_encoder, "encoder", &encoderImplementation.outPtr(), nullptr);
+
+ return GST_OBJECT_NAME(gst_element_get_factory(encoderImplementation.get()));
}
virtual const gchar* Name() = 0;
@@ -389,8 +342,8 @@
void SetRestrictionCaps(GRefPtr<GstCaps> caps)
{
- if (caps && m_profile.get() && gst_caps_is_equal(m_restrictionCaps.get(), caps.get()))
- g_object_set(m_profile.get(), "restriction-caps", caps.get(), nullptr);
+ if (m_restrictionCaps)
+ g_object_set(m_capsFilter, "caps", m_restrictionCaps.get(), nullptr);
m_restrictionCaps = caps;
}
@@ -404,12 +357,11 @@
GRefPtr<GstElement> m_pipeline;
GstElement* m_src;
GstElement* m_encoder;
+ GstElement* m_capsFilter;
webrtc::EncodedImageCallback* m_imageReadyCb;
GstClockTime m_firstFramePts;
GRefPtr<GstCaps> m_restrictionCaps;
- GRefPtr<GstEncodingProfile> m_profile;
- BitrateSetter m_bitrateSetter;
webrtc::EncodedImage m_encodedFrame;
std::unique_ptr<uint8_t[]> m_encodedImageBuffer;
size_t m_encodedImageBufferSize;
@@ -483,18 +435,6 @@
}
}
- GstElement* CreateFilter() final
- {
- GstElement* filter = makeElement("capsfilter");
- auto caps = adoptGRef(gst_caps_new_simple(Caps(),
- "alignment", G_TYPE_STRING, "au",
- "stream-format", G_TYPE_STRING, "byte-stream",
- nullptr));
- g_object_set(filter, "caps", caps.get(), nullptr);
-
- return filter;
- }
-
webrtc::SdpVideoFormat ConfigureSupportedCodec(GstElement*) final
{
// TODO- Create from encoder src pad caps template
@@ -558,6 +498,7 @@
std::call_once(debugRegisteredFlag, [] {
GST_DEBUG_CATEGORY_INIT(webkit_webrtcenc_debug, "webkitlibwebrtcvideoencoder", 0, "WebKit WebRTC video encoder");
+ gst_element_register(nullptr, "webrtcvideoencoder", GST_RANK_PRIMARY, GST_TYPE_WEBRTC_VIDEO_ENCODER);
});
}
Modified: trunk/Tools/ChangeLog (237800 => 237801)
--- trunk/Tools/ChangeLog 2018-11-05 15:05:39 UTC (rev 237800)
+++ trunk/Tools/ChangeLog 2018-11-05 15:09:54 UTC (rev 237801)
@@ -1,3 +1,22 @@
+2018-11-05 Thibault Saunier <[email protected]>
+
+ [GStreamer][WebRTC] Add webrtcencoder bin to cleanup and refactor the way we set encoders
+ https://bugs.webkit.org/show_bug.cgi?id=190674
+
+ Reviewed by Philippe Normand.
+
+ webrtcencoder is a simple GstBin with a set of well known GStreamer encoders which
+ it can use to implement encoding for different formats exposing a trimmed down unified API.
+
+ It also adds proper handling of H264 profiles.
+
+ The added files follow GStreamer coding style as we aim at upstreaming the element
+ in the future.
+
+ Reviewed by Philippe Normand.
+
+ * Scripts/webkitpy/style/checker.py:
+
2018-11-05 Michael Catanzaro <[email protected]>
[WPE][GTK] API test /webkit/WebKitSettings/webkit-settings is failing
Modified: trunk/Tools/Scripts/webkitpy/style/checker.py (237800 => 237801)
--- trunk/Tools/Scripts/webkitpy/style/checker.py 2018-11-05 15:05:39 UTC (rev 237800)
+++ trunk/Tools/Scripts/webkitpy/style/checker.py 2018-11-05 15:09:54 UTC (rev 237801)
@@ -237,6 +237,19 @@
"-whitespace/declaration",
"-whitespace/indent"]),
+ ([ # Files following GStreamer coding style (for a simpler upstreaming process for example)
+ os.path.join('Source', 'WebCore', 'platform', 'mediastream', 'libwebrtc', 'GStreamerVideoEncoder.cpp'),
+ os.path.join('Source', 'WebCore', 'platform', 'mediastream', 'libwebrtc', 'GStreamerVideoEncoder.h'),
+ ],
+ ["-whitespace/indent",
+ "-whitespace/declaration",
+ "-whitespace/parens",
+ "-readability/null",
+ "-whitespace/braces",
+ "-readability/naming/underscores",
+ "-readability/enum_casing",
+ ]),
+
([
# There is no way to avoid the symbols __jit_debug_register_code
# and __jit_debug_descriptor when integrating with gdb.