Title: [234141] trunk/Source
Revision
234141
Author
[email protected]
Date
2018-07-24 02:08:11 -0700 (Tue, 24 Jul 2018)

Log Message

[GStreamer] Implement bitrate modulation support in GStreamer based libwebrtc Encoders
https://bugs.webkit.org/show_bug.cgi?id=187643

Patch by Thibault Saunier <[email protected]> on 2018-07-24
Reviewed by Philippe Normand.

Source/WebCore:

Problem being that we do not have a proper unified encoder API in GStreamer, some work
started at https://bugzilla.gnome.org/show_bug.cgi?id=796716 but it is quite controversial
and meanwhile we should just move forward working around that limitation.

Source/WebCore:
* platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp:
(WebCore::GStreamerVideoEncoder::GStreamerVideoEncoder):
(WebCore::GStreamerVideoEncoder::InitEncode):
(WebCore::GStreamerVideoEncoder::getBitrateSetter):
(WebCore::GStreamerVideoEncoder::createEncoder):
(WebCore::GStreamerVideoEncoder::AddCodecIfSupported):
(WebCore::GStreamerVideoEncoder::SetRestrictionCaps):
(WebCore::GStreamerVideoEncoder::CreateEncoder): Deleted.

Source/WTF:

Added support for GRegex in GRefPtr.

Source/WTF:
* wtf/glib/GRefPtr.cpp:
(WTF::refGPtr):
(WTF::derefGPtr):
* wtf/glib/GRefPtr.h:

Modified Paths

Diff

Modified: trunk/Source/WTF/ChangeLog (234140 => 234141)


--- trunk/Source/WTF/ChangeLog	2018-07-24 08:55:32 UTC (rev 234140)
+++ trunk/Source/WTF/ChangeLog	2018-07-24 09:08:11 UTC (rev 234141)
@@ -1,3 +1,18 @@
+2018-07-24  Thibault Saunier  <[email protected]>
+
+        [GStreamer] Implement bitrate modulation support in GStreamer based libwebrtc Encoders
+        https://bugs.webkit.org/show_bug.cgi?id=187643
+
+        Reviewed by Philippe Normand.
+
+        Added support for GRegex in GRefPtr.
+
+        Source/WTF:
+        * wtf/glib/GRefPtr.cpp:
+        (WTF::refGPtr):
+        (WTF::derefGPtr):
+        * wtf/glib/GRefPtr.h:
+
 2018-07-23  Ross Kirsling  <[email protected]>
 
         WTF::StringView::split should have an allowEmptyEntries flag

Modified: trunk/Source/WTF/wtf/glib/GRefPtr.cpp (234140 => 234141)


--- trunk/Source/WTF/wtf/glib/GRefPtr.cpp	2018-07-24 08:55:32 UTC (rev 234140)
+++ trunk/Source/WTF/wtf/glib/GRefPtr.cpp	2018-07-24 09:08:11 UTC (rev 234141)
@@ -156,6 +156,19 @@
         g_closure_unref(ptr);
 }
 
+template <> GRegex* refGPtr(GRegex* ptr)
+{
+    if (ptr)
+        g_regex_ref(ptr);
+    return ptr;
+}
+
+template <> void derefGPtr(GRegex* ptr)
+{
+    if (ptr)
+        g_regex_unref(ptr);
+}
+
 } // namespace WTF
 
 #endif // USE(GLIB)

Modified: trunk/Source/WTF/wtf/glib/GRefPtr.h (234140 => 234141)


--- trunk/Source/WTF/wtf/glib/GRefPtr.h	2018-07-24 08:55:32 UTC (rev 234140)
+++ trunk/Source/WTF/wtf/glib/GRefPtr.h	2018-07-24 09:08:11 UTC (rev 234141)
@@ -27,6 +27,7 @@
 
 #include <wtf/HashTraits.h>
 #include <algorithm>
+#include <glib.h>
 
 extern "C" void g_object_unref(gpointer);
 extern "C" gpointer g_object_ref_sink(gpointer);
@@ -236,6 +237,8 @@
 template <> WTF_EXPORT_PRIVATE void derefGPtr(GBytes*);
 template <> WTF_EXPORT_PRIVATE GClosure* refGPtr(GClosure*);
 template <> WTF_EXPORT_PRIVATE void derefGPtr(GClosure*);
+template <> WTF_EXPORT_PRIVATE GRegex* refGPtr(GRegex*);
+template <> WTF_EXPORT_PRIVATE void derefGPtr(GRegex*);
 
 template <typename T> inline T* refGPtr(T* ptr)
 {

Modified: trunk/Source/WebCore/ChangeLog (234140 => 234141)


--- trunk/Source/WebCore/ChangeLog	2018-07-24 08:55:32 UTC (rev 234140)
+++ trunk/Source/WebCore/ChangeLog	2018-07-24 09:08:11 UTC (rev 234141)
@@ -1,3 +1,24 @@
+2018-07-24  Thibault Saunier  <[email protected]>
+
+        [GStreamer] Implement bitrate modulation support in GStreamer based libwebrtc Encoders
+        https://bugs.webkit.org/show_bug.cgi?id=187643
+
+        Reviewed by Philippe Normand.
+
+        Problem being that we do not have a proper unified encoder API in GStreamer, some work
+        started at https://bugzilla.gnome.org/show_bug.cgi?id=796716 but it is quite controversial
+        and meanwhile we should just move forward working around that limitation.
+
+        Source/WebCore:
+        * platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp:
+        (WebCore::GStreamerVideoEncoder::GStreamerVideoEncoder):
+        (WebCore::GStreamerVideoEncoder::InitEncode):
+        (WebCore::GStreamerVideoEncoder::getBitrateSetter):
+        (WebCore::GStreamerVideoEncoder::createEncoder):
+        (WebCore::GStreamerVideoEncoder::AddCodecIfSupported):
+        (WebCore::GStreamerVideoEncoder::SetRestrictionCaps):
+        (WebCore::GStreamerVideoEncoder::CreateEncoder): Deleted.
+
 2018-07-24  Zan Dobersek  <[email protected]>
 
         REGRESSION(r234055): inverted return values in MediaPlayer::wouldTaintOrigin()

Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp (234140 => 234141)


--- trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp	2018-07-24 08:55:32 UTC (rev 234140)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp	2018-07-24 09:08:11 UTC (rev 234141)
@@ -49,8 +49,15 @@
 GST_DEBUG_CATEGORY(webkit_webrtcenc_debug);
 #define GST_CAT_DEFAULT webkit_webrtcenc_debug
 
+#define KBIT_TO_BIT 1024
+
 namespace WebCore {
 
+typedef void (*BitrateSetter)(GstElement* encoder, uint32_t bitrate);
+static GRefPtr<GRegex> targetBitrateBitPerSec;
+static GRefPtr<GRegex> bitrateBitPerSec;
+static GRefPtr<GRegex> bitrateKBitPerSec;
+
 class GStreamerVideoEncoder : public webrtc::VideoEncoder {
 public:
     GStreamerVideoEncoder(const webrtc::SdpVideoFormat&)
@@ -57,6 +64,7 @@
         : m_pictureId(0)
         , m_firstFramePts(GST_CLOCK_TIME_NONE)
         , m_restrictionCaps(adoptGRef(gst_caps_new_empty_simple("video/x-raw")))
+        , m_bitrateSetter(nullptr)
     {
     }
     GStreamerVideoEncoder()
@@ -63,6 +71,7 @@
         : m_pictureId(0)
         , m_firstFramePts(GST_CLOCK_TIME_NONE)
         , m_restrictionCaps(adoptGRef(gst_caps_new_empty_simple("video/x-raw")))
+        , m_bitrateSetter(nullptr)
     {
     }
 
@@ -76,6 +85,9 @@
 
         SetRestrictionCaps(caps);
 
+        if (m_bitrateSetter && m_encoder)
+            m_bitrateSetter(m_encoder, newBitrate);
+
         return WEBRTC_VIDEO_CODEC_OK;
     }
 
@@ -100,8 +112,9 @@
         m_pipeline = makeElement("pipeline");
 
         connectSimpleBusMessageCallback(m_pipeline.get());
-        auto encodebin = CreateEncoder(&m_encoder).leakRef();
+        auto encodebin = createEncoder(&m_encoder).leakRef();
         ASSERT(m_encoder);
+        m_bitrateSetter = getBitrateSetter(gst_element_get_factory(m_encoder));
 
         m_src = makeElement("appsrc");
         g_object_set(m_src, "is-live", true, "format", GST_FORMAT_TIME, nullptr);
@@ -239,8 +252,42 @@
         return GST_FLOW_OK;
     }
 
-    GRefPtr<GstElement> CreateEncoder(GstElement** encoder)
+#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)
     {
+        static std::once_flag regexRegisteredFlag;
+
+        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());
+        });
+
+        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")
+
+        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(
@@ -280,7 +327,7 @@
     {
         GstElement* encoder;
 
-        if (CreateEncoder(&encoder).get() != nullptr) {
+        if (createEncoder(&encoder).get() != nullptr) {
             webrtc::SdpVideoFormat format = ConfigureSupportedCodec(encoder);
 
             supportedFormats->push_back(format);
@@ -338,7 +385,7 @@
 
     void SetRestrictionCaps(GstCaps* caps)
     {
-        if (caps && m_profile.get())
+        if (caps && m_profile.get() && gst_caps_is_equal(m_restrictionCaps.get(), caps))
             g_object_set(m_profile.get(), "restriction-caps", caps, nullptr);
 
         m_restrictionCaps = caps;
@@ -361,6 +408,7 @@
     GstClockTime m_firstFramePts;
     GRefPtr<GstCaps> m_restrictionCaps;
     GRefPtr<GstEncodingProfile> m_profile;
+    BitrateSetter m_bitrateSetter;
 };
 
 class H264Encoder : public GStreamerVideoEncoder {
_______________________________________________
webkit-changes mailing list
[email protected]
https://lists.webkit.org/mailman/listinfo/webkit-changes

Reply via email to