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
