Modified: releases/WebKitGTK/webkit-2.28/Source/WebCore/ChangeLog (257442 => 257443)
--- releases/WebKitGTK/webkit-2.28/Source/WebCore/ChangeLog 2020-02-26 10:56:56 UTC (rev 257442)
+++ releases/WebKitGTK/webkit-2.28/Source/WebCore/ChangeLog 2020-02-26 10:57:00 UTC (rev 257443)
@@ -1,3 +1,39 @@
+2020-02-20 Alicia Boya GarcĂa <[email protected]>
+
+ [GStreamer] Fix race in TextCombinerGStreamer
+ https://bugs.webkit.org/show_bug.cgi?id=208001
+
+ Reviewed by Xabier Rodriguez-Calvar.
+
+ TextCombinerGStreamer uses the CAPS event to determine whether adding
+ a webvttenc between the text track pad and the funnel element used to
+ be able to display several subtitles at the same time.
+
+ The way this was done previously had a race though: all text track
+ pads were preemptively linked directly to the funnel, only adding the
+ webvttenc element later in the middle when receiving the CAPS event.
+
+ When two or more text tracks were present, it wasn't infrequent that
+ one track had its CAPS event processed (causing the webvttenc element
+ to be added) and propagated (fixating the funnel caps) before another
+ track attempted caps negotiation. Because the pads were connected to
+ the funnel preemptively, and because without the webvttenc element the
+ caps of the text pad don't match the funnel's, this causes a caps
+ mismatch error, stopping playback completely. The CAPS event is
+ therefore never sent.
+
+ To avoid this race, we must avoid linking elements until we get the
+ CAPS events, when we actually know where we should link them to,
+ therefore avoiding early caps negotiation errors.
+
+ * platform/graphics/gstreamer/TextCombinerGStreamer.cpp:
+ (webkitTextCombinerPadDispose):
+ (webkitTextCombinerPadEvent):
+ (webkitTextCombinerRequestNewPad):
+ (webkitTextCombinerReleasePad):
+ (webkit_text_combiner_class_init):
+ (webkitTextCombinerPadFinalize): Deleted.
+
2020-02-19 Jack Lee <[email protected]>
ASSERTION FAILED: roundedIntPoint(LayoutPoint(rendererMappedResult)) == result in WebCore::RenderGeometryMap::mapToContainer
Modified: releases/WebKitGTK/webkit-2.28/Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.cpp (257442 => 257443)
--- releases/WebKitGTK/webkit-2.28/Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.cpp 2020-02-26 10:56:56 UTC (rev 257442)
+++ releases/WebKitGTK/webkit-2.28/Source/WebCore/platform/graphics/gstreamer/TextCombinerGStreamer.cpp 2020-02-26 10:57:00 UTC (rev 257443)
@@ -66,6 +66,7 @@
GstGhostPad parent;
GstTagList* tags;
+ GstPad* funnelPad;
};
struct _WebKitTextCombinerPadClass {
@@ -74,6 +75,8 @@
G_DEFINE_TYPE(WebKitTextCombinerPad, webkit_text_combiner_pad, GST_TYPE_GHOST_PAD);
+static GType webVTTEncType;
+
static gboolean webkitTextCombinerPadEvent(GstPad*, GstObject* parent, GstEvent*);
static void webkit_text_combiner_init(WebKitTextCombiner* combiner)
@@ -97,12 +100,12 @@
gst_pad_set_event_function(GST_PAD(pad), webkitTextCombinerPadEvent);
}
-static void webkitTextCombinerPadFinalize(GObject* object)
+static void webkitTextCombinerPadDispose(GObject* object)
{
- WebKitTextCombinerPad* pad = WEBKIT_TEXT_COMBINER_PAD(object);
- if (pad->tags)
- gst_tag_list_unref(pad->tags);
- G_OBJECT_CLASS(webkit_text_combiner_pad_parent_class)->finalize(object);
+ WebKitTextCombinerPad* combinerPad = WEBKIT_TEXT_COMBINER_PAD(object);
+ gst_clear_tag_list(&combinerPad->tags);
+ gst_clear_object(&combinerPad->funnelPad);
+ G_OBJECT_CLASS(webkit_text_combiner_pad_parent_class)->dispose(object);
}
static void webkitTextCombinerPadGetProperty(GObject* object, guint propertyId, GValue* value, GParamSpec* pspec)
@@ -136,17 +139,13 @@
ASSERT(caps);
GRefPtr<GstPad> target = adoptGRef(gst_ghost_pad_get_target(GST_GHOST_PAD(pad)));
- ASSERT(target);
+ GRefPtr<GstElement> targetParent = target ? adoptGRef(gst_pad_get_parent_element(target.get())) : nullptr;
- GRefPtr<GstElement> targetParent = adoptGRef(gst_pad_get_parent_element(target.get()));
- ASSERT(targetParent);
-
GRefPtr<GstCaps> textCaps = adoptGRef(gst_caps_new_empty_simple("text/x-raw"));
if (gst_caps_can_intersect(textCaps.get(), caps)) {
- /* Caps are plain text, put a WebVTT encoder between the ghostpad and
- * the funnel */
- if (targetParent.get() == combiner->funnel) {
- /* Setup a WebVTT encoder */
+ // Caps are plain text, we want a WebVTT encoder between the ghostpad and the funnel.
+ if (!target || G_TYPE_FROM_INSTANCE(targetParent.get()) != webVTTEncType) {
+ // Setup a WebVTT encoder.
GstElement* encoder = gst_element_factory_make("webvttenc", nullptr);
ASSERT(encoder);
@@ -156,7 +155,7 @@
ret = gst_element_sync_state_with_parent(encoder);
ASSERT(ret);
- /* Switch the ghostpad to target the WebVTT encoder */
+ // Switch the ghostpad to target the WebVTT encoder.
GRefPtr<GstPad> sinkPad = adoptGRef(gst_element_get_static_pad(encoder, "sink"));
ASSERT(sinkPad);
@@ -163,31 +162,30 @@
ret = gst_ghost_pad_set_target(GST_GHOST_PAD(pad), sinkPad.get());
ASSERT(ret);
- /* Connect the WebVTT encoder to the funnel */
+ // Connect the WebVTT encoder to the funnel.
GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_static_pad(encoder, "src"));
ASSERT(srcPad);
- ret = GST_PAD_LINK_SUCCESSFUL(gst_pad_link(srcPad.get(), target.get()));
+ ret = GST_PAD_LINK_SUCCESSFUL(gst_pad_link(srcPad.get(), combinerPad->funnelPad));
ASSERT(ret);
- } /* else: pipeline is already correct */
+ } // Else: pipeline is already correct.
} else {
- /* Caps are not plain text, remove the WebVTT encoder */
- if (targetParent.get() != combiner->funnel) {
- /* Get the funnel sink pad */
- GRefPtr<GstPad> srcPad = adoptGRef(gst_element_get_static_pad(targetParent.get(), "src"));
- ASSERT(srcPad);
+ // Caps are not plain text, we assume it's WebVTT.
- GRefPtr<GstPad> sinkPad = adoptGRef(gst_pad_get_peer(srcPad.get()));
- ASSERT(sinkPad);
-
- /* Switch the ghostpad to target the funnel */
- ret = gst_ghost_pad_set_target(GST_GHOST_PAD(pad), sinkPad.get());
+ // Remove the WebVTT encoder if present.
+ if (target && G_TYPE_FROM_INSTANCE(targetParent.get()) == webVTTEncType) {
+ ret = gst_bin_remove(GST_BIN(combiner), targetParent.get());
ASSERT(ret);
- /* Remove the WebVTT encoder */
- ret = gst_bin_remove(GST_BIN(combiner), targetParent.get());
+ target = nullptr;
+ targetParent = nullptr;
+ }
+
+ // Link the pad to the funnel.
+ if (!target) {
+ ret = gst_ghost_pad_set_target(GST_GHOST_PAD(pad), combinerPad->funnelPad);
ASSERT(ret);
- } /* else: pipeline is already correct */
+ } // Else: pipeline is already correct.
}
break;
}
@@ -222,17 +220,15 @@
WebKitTextCombiner* combiner = WEBKIT_TEXT_COMBINER(element);
ASSERT(combiner);
- GstPad* pad = gst_element_request_pad(combiner->funnel, templ, name, caps);
- ASSERT(pad);
-
- GstPad* ghostPad = GST_PAD(g_object_new(WEBKIT_TYPE_TEXT_COMBINER_PAD, "direction", gst_pad_get_direction(pad), nullptr));
+ GstPad* ghostPad = GST_PAD(g_object_new(WEBKIT_TYPE_TEXT_COMBINER_PAD, "direction", GST_PAD_SINK, nullptr));
ASSERT(ghostPad);
ret = gst_ghost_pad_construct(GST_GHOST_PAD(ghostPad));
ASSERT(ret);
- ret = gst_ghost_pad_set_target(GST_GHOST_PAD(ghostPad), pad);
- ASSERT(ret);
+ WebKitTextCombinerPad* combinerPad = WEBKIT_TEXT_COMBINER_PAD(ghostPad);
+ combinerPad->funnelPad = gst_element_request_pad(combiner->funnel, templ, name, caps);
+ ASSERT(combinerPad->funnelPad);
ret = gst_pad_set_active(ghostPad, true);
ASSERT(ret);
@@ -245,14 +241,16 @@
static void webkitTextCombinerReleasePad(GstElement *element, GstPad *pad)
{
WebKitTextCombiner* combiner = WEBKIT_TEXT_COMBINER(element);
+ WebKitTextCombinerPad* combinerPad = WEBKIT_TEXT_COMBINER_PAD(pad);
+
if (GRefPtr<GstPad> peer = adoptGRef(gst_pad_get_peer(pad))) {
GRefPtr<GstElement> parent = adoptGRef(gst_pad_get_parent_element(peer.get()));
ASSERT(parent);
- gst_element_release_request_pad(parent.get(), peer.get());
- if (parent.get() != combiner->funnel)
+ if (G_TYPE_FROM_INSTANCE(parent.get()) == webVTTEncType)
gst_bin_remove(GST_BIN(combiner), parent.get());
}
+ gst_element_release_request_pad(combiner->funnel, combinerPad->funnelPad);
gst_element_remove_pad(element, pad);
}
@@ -271,6 +269,11 @@
GST_DEBUG_FUNCPTR(webkitTextCombinerRequestNewPad);
elementClass->release_pad =
GST_DEBUG_FUNCPTR(webkitTextCombinerReleasePad);
+
+ GRefPtr<GstElementFactory> webVTTEncFactory = adoptGRef(gst_element_factory_find("webvttenc"));
+ gst_object_unref(gst_plugin_feature_load(GST_PLUGIN_FEATURE(webVTTEncFactory.get())));
+ webVTTEncType = gst_element_factory_get_element_type(webVTTEncFactory.get());
+ ASSERT(webVTTEncType);
}
static void webkit_text_combiner_pad_class_init(WebKitTextCombinerPadClass* klass)
@@ -277,7 +280,7 @@
{
GObjectClass* gobjectClass = G_OBJECT_CLASS(klass);
- gobjectClass->finalize = GST_DEBUG_FUNCPTR(webkitTextCombinerPadFinalize);
+ gobjectClass->dispose = GST_DEBUG_FUNCPTR(webkitTextCombinerPadDispose);
gobjectClass->get_property = GST_DEBUG_FUNCPTR(webkitTextCombinerPadGetProperty);
g_object_class_install_property(gobjectClass, PROP_PAD_TAGS,