Diff
Modified: trunk/Source/ThirdParty/libwebrtc/CMakeLists.txt (238556 => 238557)
--- trunk/Source/ThirdParty/libwebrtc/CMakeLists.txt 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/ThirdParty/libwebrtc/CMakeLists.txt 2018-11-27 17:34:28 UTC (rev 238557)
@@ -1050,6 +1050,11 @@
Source/webrtc/modules/video_coding/codecs/i420/i420.cc
Source/webrtc/modules/video_coding/codecs/vp8/default_temporal_layers.cc
Source/webrtc/modules/video_coding/codecs/vp8/screenshare_layers.cc
+ Source/webrtc/modules/video_coding/codecs/vp8/vp8_temporal_layers.cc
+ Source/webrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.cc
+ Source/webrtc/modules/video_coding/codecs/vp8/libvpx_interface.cc
+ Source/webrtc/modules/video_coding/codecs/vp8/temporal_layers_checker.cc
+ Source/webrtc/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.cc
Source/webrtc/modules/video_coding/codecs/vp9/svc_config.cc
Source/webrtc/modules/video_coding/codecs/vp9/svc_rate_allocator.cc
Source/webrtc/modules/video_coding/decoder_database.cc
Modified: trunk/Source/ThirdParty/libwebrtc/ChangeLog (238556 => 238557)
--- trunk/Source/ThirdParty/libwebrtc/ChangeLog 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/ThirdParty/libwebrtc/ChangeLog 2018-11-27 17:34:28 UTC (rev 238557)
@@ -1,3 +1,12 @@
+2018-11-27 Thibault Saunier <[email protected]>
+
+ [GStreamer][WebRTC] Use LibWebRTC provided vp8 decoders and encoders
+ https://bugs.webkit.org/show_bug.cgi?id=191861
+
+ Reviewed by Philippe Normand.
+
+ * CMakeLists.txt: Build LibVPX vp8 encoder and decoders.
+
2018-11-14 Youenn Fablet <[email protected]>
Convert libwebrtc error types to DOM exceptions
Modified: trunk/Source/WebCore/ChangeLog (238556 => 238557)
--- trunk/Source/WebCore/ChangeLog 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/WebCore/ChangeLog 2018-11-27 17:34:28 UTC (rev 238557)
@@ -1,3 +1,48 @@
+2018-11-27 Thibault Saunier <[email protected]>
+
+ [GStreamer][WebRTC] Use LibWebRTC provided vp8 decoders and encoders
+ https://bugs.webkit.org/show_bug.cgi?id=191861
+
+ The GStreamer implementations are less feature full and less tested, now that Apple
+ also use the LibWebRTC provided implementations it makes a lot of sense for us to
+ do the same.
+
+ Basically everything related to temporal scalability is not implemented in GStreamer.
+
+ We should make sure to use GStreamer elements on low powered platforms and for
+ accelerated encoders and decoders.
+
+ Reviewed by Philippe Normand.
+
+ This is mostly refactoring, no new test required.
+
+ * platform/graphics/gstreamer/GStreamerCommon.h: Added GstMappedFrame similar to GstMappedBuffer but for video frames.
+ (WebCore::GstMappedFrame::GstMappedFrame):
+ (WebCore::GstMappedFrame::get):
+ (WebCore::GstMappedFrame::ComponentData):
+ (WebCore::GstMappedFrame::ComponentStride):
+ (WebCore::GstMappedFrame::info):
+ (WebCore::GstMappedFrame::width):
+ (WebCore::GstMappedFrame::height):
+ (WebCore::GstMappedFrame::format):
+ (WebCore::GstMappedFrame::~GstMappedFrame):
+ (WebCore::GstMappedFrame::operator bool const):
+ * platform/graphics/gstreamer/GUniquePtrGStreamer.h:
+ * platform/mediastream/gstreamer/GStreamerVideoFrameLibWebRTC.cpp:
+ (WebCore::GStreamerVideoFrameLibWebRTC::ToI420): Implemented support for converting frame formats with the GstVideoConverter API
+ * platform/mediastream/libwebrtc/GStreamerVideoDecoderFactory.cpp:
+ (WebCore::GStreamerVideoDecoder::GstDecoderFactory):
+ (WebCore::GStreamerVideoDecoder::HasGstDecoder):
+ (WebCore::VP8Decoder::Create): Creates a `webrtc::LibvpxVp8Decoder()` if GStreamer decoder would be the LibVPX based one.
+ (WebCore::GStreamerVideoDecoderFactory::CreateVideoDecoder):
+ * platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp:
+ (gst_webrtc_video_encoder_class_init):
+ * platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp: Stop using vp8enc and use LibWebRTC based implementation
+ (WebCore::GStreamerH264Encoder::GStreamerH264Encoder): Renamed H264Encoder to GStreamerH264Encoder to be more coherent with what is done in LibVPX
+ (WebCore::GStreamerVP8Encoder::GStreamerVP8Encoder): Renamed VP8Encoder to GStreamerVP8Encoder to be more coherent with what is done in LibVPX
+ (WebCore::GStreamerVideoEncoderFactory::CreateVideoEncoder):
+ (WebCore::GStreamerVideoEncoderFactory::GetSupportedFormats const):
+
2018-11-27 Javier Fernandez <[email protected]>
[css-grid] align-self center and position sticky don't work together
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h (238556 => 238557)
--- trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GStreamerCommon.h 2018-11-27 17:34:28 UTC (rev 238557)
@@ -135,9 +135,92 @@
return a.size() == gst_buffer_get_size(nonConstB) && !gst_buffer_memcmp(nonConstB, 0, a.data(), a.size());
}
+class GstMappedFrame {
+ WTF_MAKE_NONCOPYABLE(GstMappedFrame);
+public:
+
+ GstMappedFrame(GstBuffer* buffer, GstVideoInfo info, GstMapFlags flags)
+ {
+ m_isValid = gst_video_frame_map(&m_frame, &info, buffer, flags);
+ }
+
+ GstMappedFrame(GRefPtr<GstSample> sample, GstMapFlags flags)
+ {
+ GstVideoInfo info;
+
+ if (!gst_video_info_from_caps(&info, gst_sample_get_caps(sample.get()))) {
+ m_isValid = false;
+ return;
+ }
+
+ m_isValid = gst_video_frame_map(&m_frame, &info, gst_sample_get_buffer(sample.get()), flags);
+ }
+
+ GstVideoFrame* get()
+ {
+ if (!m_isValid) {
+ GST_INFO("Invalid frame, returning NULL");
+
+ return nullptr;
+ }
+
+ return &m_frame;
+ }
+
+ uint8_t* ComponentData(int comp)
+ {
+ return GST_VIDEO_FRAME_COMP_DATA(&m_frame, comp);
+ }
+
+ int ComponentStride(int stride)
+ {
+ return GST_VIDEO_FRAME_COMP_STRIDE(&m_frame, stride);
+ }
+
+ GstVideoInfo* info()
+ {
+ if (!m_isValid) {
+ GST_INFO("Invalid frame, returning NULL");
+
+ return nullptr;
+ }
+
+ return &m_frame.info;
+ }
+
+ int width()
+ {
+ return m_isValid ? GST_VIDEO_FRAME_WIDTH(&m_frame) : -1;
+ }
+
+ int height()
+ {
+ return m_isValid ? GST_VIDEO_FRAME_HEIGHT(&m_frame) : -1;
+ }
+
+ int format()
+ {
+ return m_isValid ? GST_VIDEO_FRAME_FORMAT(&m_frame) : GST_VIDEO_FORMAT_UNKNOWN;
+ }
+
+ ~GstMappedFrame()
+ {
+ if (m_isValid)
+ gst_video_frame_unmap(&m_frame);
+ m_isValid = false;
+ }
+
+ explicit operator bool() const { return m_isValid; }
+
+private:
+ GstVideoFrame m_frame;
+ bool m_isValid { false };
+};
+
+
bool gstRegistryHasElementForMediaType(GList* elementFactories, const char* capsString);
-void connectSimpleBusMessageCallback(GstElement *pipeline);
-void disconnectSimpleBusMessageCallback(GstElement *pipeline);
+void connectSimpleBusMessageCallback(GstElement* pipeline);
+void disconnectSimpleBusMessageCallback(GstElement* pipeline);
}
Modified: trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h (238556 => 238557)
--- trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/WebCore/platform/graphics/gstreamer/GUniquePtrGStreamer.h 2018-11-27 17:34:28 UTC (rev 238557)
@@ -26,6 +26,7 @@
#include <gst/gstsegment.h>
#include <gst/gststructure.h>
#include <gst/pbutils/install-plugins.h>
+#include <gst/video/video.h>
#include <wtf/glib/GUniquePtr.h>
namespace WTF {
@@ -36,6 +37,7 @@
WTF_DEFINE_GPTR_DELETER(GstSegment, gst_segment_free)
WTF_DEFINE_GPTR_DELETER(GstFlowCombiner, gst_flow_combiner_free)
WTF_DEFINE_GPTR_DELETER(GstByteReader, gst_byte_reader_free)
+WTF_DEFINE_GPTR_DELETER(GstVideoConverter, gst_video_converter_free)
}
Modified: trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoFrameLibWebRTC.cpp (238556 => 238557)
--- trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoFrameLibWebRTC.cpp 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/WebCore/platform/mediastream/gstreamer/GStreamerVideoFrameLibWebRTC.cpp 2018-11-27 17:34:28 UTC (rev 238557)
@@ -21,6 +21,8 @@
#if USE(GSTREAMER) && USE(LIBWEBRTC)
#include "GStreamerVideoFrameLibWebRTC.h"
+#include <thread>
+
namespace WebCore {
const GRefPtr<GstSample> GStreamerSampleFromLibWebRTCVideoFrame(const webrtc::VideoFrame& frame)
@@ -90,37 +92,55 @@
rtc::scoped_refptr<webrtc::I420BufferInterface> GStreamerVideoFrameLibWebRTC::ToI420()
{
- GstVideoInfo info;
- GstVideoFrame frame;
+ GstMappedFrame inFrame(m_sample, GST_MAP_READ);
- if (!gst_video_info_from_caps(&info, gst_sample_get_caps(m_sample.get())))
- ASSERT_NOT_REACHED();
+ if (!inFrame) {
+ GST_WARNING("Could not map frame");
- if (GST_VIDEO_INFO_FORMAT(&info) != GST_VIDEO_FORMAT_I420)
return nullptr;
+ }
- gst_video_frame_map(&frame, &info, gst_sample_get_buffer(m_sample.get()), GST_MAP_READ);
-
- auto newBuffer = m_bufferPool.CreateBuffer(GST_VIDEO_FRAME_WIDTH(&frame),
- GST_VIDEO_FRAME_HEIGHT(&frame));
-
+ auto newBuffer = m_bufferPool.CreateBuffer(inFrame.width(), inFrame.height());
ASSERT(newBuffer);
if (!newBuffer) {
- gst_video_frame_unmap(&frame);
GST_WARNING("RealtimeOutgoingVideoSourceGStreamer::videoSampleAvailable unable to allocate buffer for conversion to YUV");
return nullptr;
}
+ if (inFrame.format() != GST_VIDEO_FORMAT_I420) {
+ GstVideoInfo outInfo;
+
+ gst_video_info_set_format(&outInfo, GST_VIDEO_FORMAT_I420, inFrame.width(),
+ inFrame.height());
+ auto info = inFrame.info();
+ outInfo.fps_n = info->fps_n;
+ outInfo.fps_d = info->fps_d;
+
+ GRefPtr<GstBuffer> buffer = adoptGRef(gst_buffer_new_wrapped_full(GST_MEMORY_FLAG_NO_SHARE, newBuffer->MutableDataY(),
+ outInfo.size, 0, outInfo.size, nullptr, nullptr));
+
+ GstMappedFrame outFrame(buffer.get(), outInfo, GST_MAP_WRITE);
+
+ GUniquePtr<GstVideoConverter> videoConverter(gst_video_converter_new(inFrame.info(),
+ &outInfo, gst_structure_new("GstVideoConvertConfig",
+ GST_VIDEO_CONVERTER_OPT_THREADS, G_TYPE_UINT, std::thread::hardware_concurrency() || 1 , nullptr)));
+
+ ASSERT(videoConverter);
+
+ gst_video_converter_frame(videoConverter.get(), inFrame.get(), outFrame.get());
+
+ return newBuffer;
+ }
+
newBuffer->Copy(
- GST_VIDEO_FRAME_WIDTH(&frame),
- GST_VIDEO_FRAME_HEIGHT(&frame),
- GST_VIDEO_FRAME_COMP_DATA(&frame, 0),
- GST_VIDEO_FRAME_COMP_STRIDE(&frame, 0),
- GST_VIDEO_FRAME_COMP_DATA(&frame, 1),
- GST_VIDEO_FRAME_COMP_STRIDE(&frame, 1),
- GST_VIDEO_FRAME_COMP_DATA(&frame, 2),
- GST_VIDEO_FRAME_COMP_STRIDE(&frame, 2));
- gst_video_frame_unmap(&frame);
+ inFrame.width(),
+ inFrame.height(),
+ inFrame.ComponentData(0),
+ inFrame.ComponentStride(0),
+ inFrame.ComponentData(1),
+ inFrame.ComponentStride(1),
+ inFrame.ComponentData(2),
+ inFrame.ComponentStride(2));
return newBuffer;
}
Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoDecoderFactory.cpp (238556 => 238557)
--- trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoDecoderFactory.cpp 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoDecoderFactory.cpp 2018-11-27 17:34:28 UTC (rev 238557)
@@ -29,6 +29,7 @@
#include "webrtc/media/base/codec.h"
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/modules/video_coding/codecs/vp8/libvpx_vp8_decoder.h"
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
#include <gst/app/gstappsink.h>
#include <gst/app/gstappsrc.h>
@@ -214,21 +215,28 @@
return webrtc::SdpVideoFormat(Name());
}
- bool HasGstDecoder()
+ static GRefPtr<GstElementFactory> GstDecoderFactory(const char *capsStr)
{
-
auto all_decoders = gst_element_factory_list_get_elements(GST_ELEMENT_FACTORY_TYPE_DECODER,
GST_RANK_MARGINAL);
- auto caps = adoptGRef(gst_caps_from_string(Caps()));
+ auto caps = adoptGRef(gst_caps_from_string(capsStr));
auto decoders = gst_element_factory_list_filter(all_decoders,
caps.get(), GST_PAD_SINK, FALSE);
gst_plugin_feature_list_free(all_decoders);
+ GRefPtr<GstElementFactory> res;
+ if (decoders)
+ res = GST_ELEMENT_FACTORY(decoders->data);
gst_plugin_feature_list_free(decoders);
- return decoders != nullptr;
+ return res;
}
+ bool HasGstDecoder()
+ {
+ return GstDecoderFactory(Caps());
+ }
+
GstFlowReturn newSampleCallback(GstElement* sink)
{
auto sample = gst_app_sink_pull_sample(GST_APP_SINK(sink));
@@ -343,16 +351,28 @@
const gchar* Caps() final { return "video/x-vp8"; }
const gchar* Name() final { return cricket::kVp8CodecName; }
webrtc::VideoCodecType CodecType() final { return webrtc::kVideoCodecVP8; }
+ static std::unique_ptr<webrtc::VideoDecoder> Create()
+ {
+ auto factory = GstDecoderFactory("video/x-vp8");
+
+ if (factory && !g_strcmp0(GST_OBJECT_NAME(GST_OBJECT(factory.get())), "vp8dec")) {
+ GST_INFO("Our best GStreamer VP8 decoder is vp8dec, better use the one from LibWebRTC");
+
+ return std::unique_ptr<webrtc::VideoDecoder>(new webrtc::LibvpxVp8Decoder());
+ }
+
+ return std::unique_ptr<webrtc::VideoDecoder>(new VP8Decoder());
+ }
};
std::unique_ptr<webrtc::VideoDecoder> GStreamerVideoDecoderFactory::CreateVideoDecoder(const webrtc::SdpVideoFormat& format)
{
- GStreamerVideoDecoder* dec;
+ webrtc::VideoDecoder* dec;
if (format.name == cricket::kH264CodecName)
dec = new H264Decoder();
else if (format.name == cricket::kVp8CodecName)
- dec = new VP8Decoder();
+ return VP8Decoder::Create();
else {
GST_ERROR("Could not create decoder for %s", format.name.c_str());
Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp (238556 => 238557)
--- trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoder.cpp 2018-11-27 17:34:28 UTC (rev 238557)
@@ -278,12 +278,6 @@
}
static void
-setup_vp8enc (GObject * encoder)
-{
- gst_preset_load_preset (GST_PRESET (encoder), "Profile Realtime");
-}
-
-static void
setup_openh264enc (GObject *)
{
}
@@ -296,13 +290,6 @@
}
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);
@@ -344,9 +331,6 @@
"video/x-h264",
"video/x-h264,alignment=au,stream-format=byte-stream,profile=""
setup_openh264enc, "bitrate", set_bitrate_kbit_per_sec, "gop-size");
- register_known_encoder (ENCODER_VP8, "vp8enc", NULL, "video/x-vp8", NULL,
- setup_vp8enc, "target-bitrate", set_bitrate_bit_per_sec,
- "keyframe-max-dist");
}
static void
Modified: trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp (238556 => 238557)
--- trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp 2018-11-27 17:28:23 UTC (rev 238556)
+++ trunk/Source/WebCore/platform/mediastream/libwebrtc/GStreamerVideoEncoderFactory.cpp 2018-11-27 17:34:28 UTC (rev 238557)
@@ -30,6 +30,7 @@
#include "webrtc/media/base/codec.h"
#include "webrtc/modules/video_coding/codecs/h264/include/h264.h"
#include "webrtc/modules/video_coding/codecs/vp8/include/vp8.h"
+#include "webrtc/modules/video_coding/codecs/vp8/libvpx_vp8_encoder.h"
#include "webrtc/modules/video_coding/include/video_codec_interface.h"
#include "webrtc/modules/video_coding/utility/simulcast_utility.h"
@@ -410,11 +411,11 @@
Vector<FrameData> m_framesData;
};
-class H264Encoder : public GStreamerVideoEncoder {
+class GStreamerH264Encoder : public GStreamerVideoEncoder {
public:
- H264Encoder() { }
+ GStreamerH264Encoder() { }
- H264Encoder(const webrtc::SdpVideoFormat& format)
+ GStreamerH264Encoder(const webrtc::SdpVideoFormat& format)
: m_parser(gst_h264_nal_parser_new())
, packetizationMode(webrtc::H264PacketizationMode::NonInterleaved)
{
@@ -508,10 +509,10 @@
webrtc::H264PacketizationMode packetizationMode;
};
-class VP8Encoder : public GStreamerVideoEncoder {
+class GStreamerVP8Encoder : public GStreamerVideoEncoder {
public:
- VP8Encoder() { }
- VP8Encoder(const webrtc::SdpVideoFormat&) { }
+ GStreamerVP8Encoder() { }
+ GStreamerVP8Encoder(const webrtc::SdpVideoFormat&) { }
const gchar* Caps() final { return "video/x-vp8"; }
const gchar* Name() final { return cricket::kVp8CodecName; }
webrtc::VideoCodecType CodecType() final { return webrtc::kVideoCodecVP8; }
@@ -535,11 +536,22 @@
std::unique_ptr<webrtc::VideoEncoder> GStreamerVideoEncoderFactory::CreateVideoEncoder(const webrtc::SdpVideoFormat& format)
{
- if (format.name == cricket::kVp8CodecName)
- return std::make_unique<VP8Encoder>(format);
+ if (format.name == cricket::kVp8CodecName) {
+ GRefPtr<GstElement> webrtcencoder = adoptGRef(GST_ELEMENT(g_object_ref_sink(gst_element_factory_make("webrtcvideoencoder", NULL))));
+ GRefPtr<GstElement> encoder = nullptr;
+ g_object_set(webrtcencoder.get(), "format", adoptGRef(gst_caps_from_string("video/x-vp8")).get(), NULL);
+ g_object_get(webrtcencoder.get(), "encoder", &encoder.outPtr(), NULL);
+
+ if (encoder)
+ return std::make_unique<GStreamerVP8Encoder>(format);
+
+ GST_INFO("Using VP8 Encoder from LibWebRTC.");
+ return std::make_unique<webrtc::LibvpxVp8Encoder>();
+ }
+
if (format.name == cricket::kH264CodecName)
- return std::make_unique<H264Encoder>(format);
+ return std::make_unique<GStreamerH264Encoder>(format);
return nullptr;
}
@@ -558,8 +570,8 @@
{
std::vector<webrtc::SdpVideoFormat> supportedCodecs;
- VP8Encoder().AddCodecIfSupported(&supportedCodecs);
- H264Encoder().AddCodecIfSupported(&supportedCodecs);
+ supportedCodecs.push_back(webrtc::SdpVideoFormat(cricket::kVp8CodecName));
+ GStreamerH264Encoder().AddCodecIfSupported(&supportedCodecs);
return supportedCodecs;
}