| /* |
| * Copyright (C) 2013 Cable Television Laboratories, Inc. |
| * Copyright (C) 2021 Igalia S.L. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions and the following disclaimer. |
| * 2. Redistributions in binary form must reproduce the above copyright |
| * notice, this list of conditions and the following disclaimer in the |
| * documentation and/or other materials provided with the distribution. |
| * |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS ``AS IS'' AND ANY |
| * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED |
| * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE |
| * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY |
| * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES |
| * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; |
| * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON |
| * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
| * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
| * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
| */ |
| |
| #include "config.h" |
| #include "TextCombinerPadGStreamer.h" |
| |
| #if ENABLE(VIDEO) && USE(GSTREAMER) |
| |
| #include "GStreamerCommon.h" |
| #include "TextCombinerGStreamer.h" |
| #include <wtf/glib/WTFGType.h> |
| |
| struct _WebKitTextCombinerPadPrivate { |
| GRefPtr<GstTagList> tags; |
| GRefPtr<GstPad> innerCombinerPad; |
| bool shouldProcessStickyEvents { true }; |
| }; |
| |
| enum { |
| PROP_PAD_0, |
| PROP_PAD_TAGS, |
| PROP_INNER_COMBINER_PAD, |
| N_PROPERTIES, |
| }; |
| |
| static GParamSpec* sObjProperties[N_PROPERTIES] = { nullptr, }; |
| |
| #define webkit_text_combiner_pad_parent_class parent_class |
| WEBKIT_DEFINE_TYPE(WebKitTextCombinerPad, webkit_text_combiner_pad, GST_TYPE_GHOST_PAD); |
| |
| static gboolean webkitTextCombinerPadEvent(GstPad* pad, GstObject* parent, GstEvent* event) |
| { |
| switch (GST_EVENT_TYPE(event)) { |
| case GST_EVENT_TAG: { |
| auto* combinerPad = WEBKIT_TEXT_COMBINER_PAD(pad); |
| GstTagList* tags; |
| gst_event_parse_tag(event, &tags); |
| ASSERT(tags); |
| |
| { |
| auto locker = GstObjectLocker(pad); |
| if (!combinerPad->priv->tags) |
| combinerPad->priv->tags = adoptGRef(gst_tag_list_copy(tags)); |
| else |
| gst_tag_list_insert(combinerPad->priv->tags.get(), tags, GST_TAG_MERGE_REPLACE); |
| } |
| |
| g_object_notify_by_pspec(G_OBJECT(pad), sObjProperties[PROP_PAD_TAGS]); |
| break; |
| } |
| default: |
| break; |
| } |
| return gst_pad_event_default(pad, parent, event); |
| } |
| |
| static GstFlowReturn webkitTextCombinerPadChain(GstPad* pad, GstObject* parent, GstBuffer* buffer) |
| { |
| auto* combinerPad = WEBKIT_TEXT_COMBINER_PAD(pad); |
| |
| if (combinerPad->priv->shouldProcessStickyEvents) { |
| gst_pad_sticky_events_foreach(pad, [](GstPad* pad, GstEvent** event, gpointer) -> gboolean { |
| if (GST_EVENT_TYPE(*event) != GST_EVENT_CAPS) |
| return TRUE; |
| |
| auto* combinerPad = WEBKIT_TEXT_COMBINER_PAD(pad); |
| auto parent = adoptGRef(gst_pad_get_parent(pad)); |
| GstCaps* caps; |
| gst_event_parse_caps(*event, &caps); |
| combinerPad->priv->shouldProcessStickyEvents = false; |
| webKitTextCombinerHandleCaps(WEBKIT_TEXT_COMBINER(parent.get()), pad, caps); |
| return FALSE; |
| }, nullptr); |
| } |
| |
| return gst_proxy_pad_chain_default(pad, parent, buffer); |
| } |
| |
| static void webkitTextCombinerPadGetProperty(GObject* object, unsigned propertyId, GValue* value, GParamSpec* pspec) |
| { |
| auto* pad = WEBKIT_TEXT_COMBINER_PAD(object); |
| switch (propertyId) { |
| case PROP_PAD_TAGS: { |
| auto locker = GstObjectLocker(object); |
| if (pad->priv->tags) |
| g_value_take_boxed(value, gst_tag_list_copy(pad->priv->tags.get())); |
| break; |
| } |
| case PROP_INNER_COMBINER_PAD: { |
| auto locker = GstObjectLocker(object); |
| g_value_set_object(value, pad->priv->innerCombinerPad.get()); |
| break; |
| } |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); |
| break; |
| } |
| } |
| |
| static void webkitTextCombinerPadSetProperty(GObject* object, guint propertyId, const GValue* value, GParamSpec* pspec) |
| { |
| auto* pad = WEBKIT_TEXT_COMBINER_PAD(object); |
| switch (propertyId) { |
| case PROP_INNER_COMBINER_PAD: { |
| auto locker = GstObjectLocker(object); |
| pad->priv->innerCombinerPad = adoptGRef(GST_PAD_CAST(g_value_get_object(value))); |
| break; |
| } |
| default: |
| G_OBJECT_WARN_INVALID_PROPERTY_ID(object, propertyId, pspec); |
| break; |
| } |
| } |
| |
| static void webkitTextCombinerPadConstructed(GObject* object) |
| { |
| GST_CALL_PARENT(G_OBJECT_CLASS, constructed, (object)); |
| gst_ghost_pad_construct(GST_GHOST_PAD(object)); |
| gst_pad_set_event_function(GST_PAD_CAST(object), webkitTextCombinerPadEvent); |
| gst_pad_set_chain_function(GST_PAD_CAST(object), webkitTextCombinerPadChain); |
| } |
| |
| static void webkit_text_combiner_pad_class_init(WebKitTextCombinerPadClass* klass) |
| { |
| auto* gobjectClass = G_OBJECT_CLASS(klass); |
| |
| gobjectClass->constructed = webkitTextCombinerPadConstructed; |
| gobjectClass->get_property = GST_DEBUG_FUNCPTR(webkitTextCombinerPadGetProperty); |
| gobjectClass->set_property = GST_DEBUG_FUNCPTR(webkitTextCombinerPadSetProperty); |
| |
| sObjProperties[PROP_PAD_TAGS] = |
| g_param_spec_boxed("tags", "Tags", "The currently active tags on the pad", GST_TYPE_TAG_LIST, |
| static_cast<GParamFlags>(G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); |
| |
| sObjProperties[PROP_INNER_COMBINER_PAD] = |
| g_param_spec_object("inner-combiner-pad", "Internal Combiner Pad", "The internal funnel (or concat) pad associated with this pad", GST_TYPE_PAD, |
| static_cast<GParamFlags>(G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS)); |
| |
| g_object_class_install_properties(gobjectClass, N_PROPERTIES, sObjProperties); |
| } |
| |
| GstPad* webKitTextCombinerPadLeakInternalPadRef(WebKitTextCombinerPad* pad) |
| { |
| return pad->priv->innerCombinerPad.leakRef(); |
| } |
| |
| #endif |