mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-25 11:11:08 +00:00
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
This commit is contained in:
parent
f1f8e465f2
commit
ac503aee7d
2 changed files with 200 additions and 13 deletions
|
@ -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 void
|
||||
gst_videoaggregator_init (GstVideoAggregator * vagg)
|
||||
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,
|
||||
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);
|
||||
}
|
||||
|
|
|
@ -111,6 +111,8 @@ struct _GstVideoAggregatorClass
|
|||
|
||||
gboolean preserve_update_caps_result;
|
||||
|
||||
GstCaps *sink_non_alpha_caps;
|
||||
|
||||
/* < private > */
|
||||
gpointer _gst_reserved[GST_PADDING_LARGE];
|
||||
};
|
||||
|
|
Loading…
Reference in a new issue