diff options
author | Thiago Santos <thiagoss@osg.samsung.com> | 2015-09-09 19:51:18 -0300 |
---|---|---|
committer | Thiago Santos <thiagoss@osg.samsung.com> | 2015-09-11 18:03:26 -0300 |
commit | ba97ec74bedd3d8e910052d8345becc42ad75813 (patch) | |
tree | d5015b8ef520434aa67a20b1e2980b01e02040dc /gst-libs | |
parent | 9f890c5935b735d57799f6ac82b89cf446dac777 (diff) | |
download | gstreamer-plugins-bad-ba97ec74bedd3d8e910052d8345becc42ad75813.tar.gz |
videoaggregator: fix caps query to properly handle alpha formats
Only accept alpha if downstream has alpha as well. It could
theoretically accept alpha unconditionally if blending is
properly implemented for handle it but at the moment this
is a missing feature.
Improves the caps query by also comparing with the template
caps to filter by what the subclass supports.
https://bugzilla.gnome.org/show_bug.cgi?id=754465
Diffstat (limited to 'gst-libs')
-rw-r--r-- | gst-libs/gst/video/gstvideoaggregator.c | 209 | ||||
-rw-r--r-- | gst-libs/gst/video/gstvideoaggregator.h | 2 |
2 files changed, 199 insertions, 12 deletions
diff --git a/gst-libs/gst/video/gstvideoaggregator.c b/gst-libs/gst/video/gstvideoaggregator.c index 80b10d445..053e81be6 100644 --- a/gst-libs/gst/video/gstvideoaggregator.c +++ b/gst-libs/gst/video/gstvideoaggregator.c @@ -76,6 +76,7 @@ struct _GstVideoAggregatorPadPrivate GstClockTime end_time; }; + G_DEFINE_TYPE (GstVideoAggregatorPad, gst_videoaggregator_pad, GST_TYPE_AGGREGATOR_PAD); @@ -429,9 +430,44 @@ struct _GstVideoAggregatorPrivate gboolean live; }; -G_DEFINE_ABSTRACT_TYPE_WITH_CODE (GstVideoAggregator, gst_videoaggregator, - GST_TYPE_AGGREGATOR, G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY, - gst_videoaggregator_child_proxy_init)); +/* Can't use the G_DEFINE_TYPE macros because we need the + * videoaggregator class in the _init to be able to set + * the sink pad non-alpha caps. Using the G_DEFINE_TYPE there + * seems to be no way of getting the real class being initialized */ +static void gst_videoaggregator_init (GstVideoAggregator * self, + GstVideoAggregatorClass * klass); +static void gst_videoaggregator_class_init (GstVideoAggregatorClass * klass); +static gpointer gst_videoaggregator_parent_class = NULL; +static gint GstVideoAggregator_private_offset; + +_G_DEFINE_TYPE_EXTENDED_CLASS_INIT (GstVideoAggregator, gst_videoaggregator); + +G_GNUC_UNUSED static inline gpointer +gst_videoaggregator_get_instance_private (const GstVideoAggregator * self) +{ + return (G_STRUCT_MEMBER_P (self, GstVideoAggregator_private_offset)); +} + +GType +gst_videoaggregator_get_type (void) +{ + static volatile gsize g_define_type_id_volatile = 0; + if (g_once_init_enter (&g_define_type_id_volatile)) { + GType g_define_type_id = g_type_register_static_simple (GST_TYPE_AGGREGATOR, + g_intern_static_string ("GstVideoAggregator"), + sizeof (GstVideoAggregatorClass), + (GClassInitFunc) gst_videoaggregator_class_intern_init, + sizeof (GstVideoAggregator), + (GInstanceInitFunc) gst_videoaggregator_init, + (GTypeFlags) G_TYPE_FLAG_ABSTRACT); + { + G_IMPLEMENT_INTERFACE (GST_TYPE_CHILD_PROXY, + gst_videoaggregator_child_proxy_init); + } + g_once_init_leave (&g_define_type_id_volatile, g_define_type_id); + } + return g_define_type_id_volatile; +} static void gst_videoaggreagator_find_best_format (GstVideoAggregator * vagg, @@ -833,27 +869,80 @@ beach: return ret; } +static gboolean +gst_videoaggregator_caps_has_alpha (GstCaps * caps) +{ + guint size = gst_caps_get_size (caps); + guint i; + + for (i = 0; i < size; i++) { + GstStructure *s = gst_caps_get_structure (caps, i); + const GValue *formats = gst_structure_get_value (s, "format"); + + if (formats) { + const GstVideoFormatInfo *info; + + if (GST_VALUE_HOLDS_LIST (formats)) { + guint list_size = gst_value_list_get_size (formats); + guint index; + + for (index = 0; index < list_size; index++) { + const GValue *list_item = gst_value_list_get_value (formats, index); + info = + gst_video_format_get_info (gst_video_format_from_string + (g_value_get_string (list_item))); + if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) + return TRUE; + } + + } else if (G_VALUE_HOLDS_STRING (formats)) { + info = + gst_video_format_get_info (gst_video_format_from_string + (g_value_get_string (formats))); + if (GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) + return TRUE; + + } else { + g_assert_not_reached (); + GST_WARNING ("Unexpected type for video 'format' field: %s", + G_VALUE_TYPE_NAME (formats)); + } + + } else { + return TRUE; + } + } + return FALSE; +} + static GstCaps * gst_videoaggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, GstCaps * filter) { GstCaps *srccaps; - GstCaps *template_caps; + GstCaps *template_caps, *sink_template_caps; GstCaps *returned_caps; GstStructure *s; - gboolean had_current_caps = TRUE; gint i, n; GstAggregator *agg = GST_AGGREGATOR (vagg); + GstPad *srcpad = GST_PAD (agg->srcpad); + gboolean has_alpha; - template_caps = gst_pad_get_pad_template_caps (GST_PAD (agg->srcpad)); + template_caps = gst_pad_get_pad_template_caps (srcpad); - srccaps = gst_pad_get_current_caps (GST_PAD (agg->srcpad)); + GST_DEBUG_OBJECT (pad, "Get caps with filter: %" GST_PTR_FORMAT, filter); + + srccaps = gst_pad_get_current_caps (srcpad); if (srccaps == NULL) { - had_current_caps = FALSE; - srccaps = template_caps; + srccaps = gst_pad_peer_query_caps (srcpad, template_caps); + GST_DEBUG_OBJECT (pad, "No output caps, using possible formats: %" + GST_PTR_FORMAT, srccaps); + } else { + GST_DEBUG_OBJECT (pad, "Using output caps: %" GST_PTR_FORMAT, srccaps); } srccaps = gst_caps_make_writable (srccaps); + has_alpha = gst_videoaggregator_caps_has_alpha (srccaps); n = gst_caps_get_size (srccaps); for (i = 0; i < n; i++) { @@ -873,8 +962,23 @@ gst_videoaggregator_pad_sink_getcaps (GstPad * pad, GstVideoAggregator * vagg, returned_caps = srccaps; } - if (had_current_caps) - gst_caps_unref (template_caps); + if (has_alpha) { + sink_template_caps = gst_pad_get_pad_template_caps (pad); + } else { + GstVideoAggregatorClass *klass = GST_VIDEO_AGGREGATOR_GET_CLASS (vagg); + sink_template_caps = gst_caps_ref (klass->sink_non_alpha_caps); + } + + { + GstCaps *intersect = gst_caps_intersect (returned_caps, sink_template_caps); + gst_caps_unref (returned_caps); + returned_caps = intersect; + } + + gst_caps_unref (template_caps); + gst_caps_unref (sink_template_caps); + + GST_DEBUG_OBJECT (pad, "Returning caps: %" GST_PTR_FORMAT, returned_caps); return returned_caps; } @@ -1974,9 +2078,83 @@ gst_videoaggregator_class_init (GstVideoAggregatorClass * klass) g_type_class_ref (GST_TYPE_VIDEO_AGGREGATOR_PAD); } +static inline GstCaps * +_get_non_alpha_caps_from_template (GstVideoAggregatorClass * klass) +{ + GstCaps *result; + GstCaps *templatecaps; + guint i, size; + + templatecaps = + gst_pad_template_get_caps (gst_element_class_get_pad_template + (GST_ELEMENT_CLASS (klass), "sink_%u")); + + size = gst_caps_get_size (templatecaps); + result = gst_caps_new_empty (); + for (i = 0; i < size; i++) { + GstStructure *s = gst_caps_get_structure (templatecaps, i); + const GValue *formats = gst_structure_get_value (s, "format"); + GValue new_formats = { 0, }; + gboolean has_format = FALSE; + + /* FIXME what to do if formats are missing? */ + if (formats) { + const GstVideoFormatInfo *info; + + if (GST_VALUE_HOLDS_LIST (formats)) { + guint list_size = gst_value_list_get_size (formats); + guint index; + + g_value_init (&new_formats, GST_TYPE_LIST); + + for (index = 0; index < list_size; index++) { + const GValue *list_item = gst_value_list_get_value (formats, index); + + info = + gst_video_format_get_info (gst_video_format_from_string + (g_value_get_string (list_item))); + if (!GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) { + has_format = TRUE; + gst_value_list_append_value (&new_formats, list_item); + } + } + + } else if (G_VALUE_HOLDS_STRING (formats)) { + info = + gst_video_format_get_info (gst_video_format_from_string + (g_value_get_string (formats))); + if (!GST_VIDEO_FORMAT_INFO_HAS_ALPHA (info)) { + has_format = TRUE; + gst_value_init_and_copy (&new_formats, formats); + } + + } else { + g_assert_not_reached (); + GST_WARNING ("Unexpected type for video 'format' field: %s", + G_VALUE_TYPE_NAME (formats)); + } + + if (has_format) { + s = gst_structure_copy (s); + gst_structure_take_value (s, "format", &new_formats); + gst_caps_append_structure (result, s); + } + + } + } + + gst_caps_unref (templatecaps); + + return result; +} + +static GMutex sink_caps_mutex; + static void -gst_videoaggregator_init (GstVideoAggregator * vagg) +gst_videoaggregator_init (GstVideoAggregator * vagg, + GstVideoAggregatorClass * klass) { + vagg->priv = G_TYPE_INSTANCE_GET_PRIVATE (vagg, GST_TYPE_VIDEO_AGGREGATOR, GstVideoAggregatorPrivate); @@ -1984,6 +2162,13 @@ gst_videoaggregator_init (GstVideoAggregator * vagg) vagg->priv->current_caps = NULL; g_mutex_init (&vagg->priv->lock); + /* initialize variables */ + g_mutex_lock (&sink_caps_mutex); + if (klass->sink_non_alpha_caps == NULL) { + klass->sink_non_alpha_caps = _get_non_alpha_caps_from_template (klass); + } + g_mutex_unlock (&sink_caps_mutex); + gst_videoaggregator_reset (vagg); } diff --git a/gst-libs/gst/video/gstvideoaggregator.h b/gst-libs/gst/video/gstvideoaggregator.h index b3c5c53e7..f95d0d267 100644 --- a/gst-libs/gst/video/gstvideoaggregator.h +++ b/gst-libs/gst/video/gstvideoaggregator.h @@ -111,6 +111,8 @@ struct _GstVideoAggregatorClass gboolean preserve_update_caps_result; + GstCaps *sink_non_alpha_caps; + /* < private > */ gpointer _gst_reserved[GST_PADDING_LARGE]; }; |