mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-26 03:31:05 +00:00
autovideoconvert: Handle passing bin description instead of factories
This way we can build our own well know bins for conversion keeping the code simple. Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/899>
This commit is contained in:
parent
292d8453d3
commit
b0fdbcec64
7 changed files with 451 additions and 362 deletions
|
@ -43,6 +43,8 @@
|
|||
#include "gstautoconvert.h"
|
||||
#include <gst/pbutils/pbutils.h>
|
||||
|
||||
GST_DEBUG_CATEGORY (autoconvert_debug);
|
||||
#define GST_CAT_DEFAULT (autoconvert_debug)
|
||||
struct _GstAutoConvert
|
||||
{
|
||||
GstBaseAutoConvert parent;
|
||||
|
@ -155,6 +157,9 @@ gst_auto_convert_class_init (GstAutoConvertClass * klass)
|
|||
GObjectClass *gobject_class = (GObjectClass *) klass;
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (klass);
|
||||
|
||||
GST_DEBUG_CATEGORY_INIT (autoconvert_debug, "autoconvert", 0,
|
||||
"Auto convert element");
|
||||
|
||||
gobject_class->set_property = gst_auto_convert_set_property;
|
||||
gobject_class->get_property = gst_auto_convert_get_property;
|
||||
|
||||
|
@ -187,6 +192,8 @@ gst_auto_convert_class_init (GstAutoConvertClass * klass)
|
|||
"An element factory name", NULL,
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS),
|
||||
G_PARAM_READWRITE | G_PARAM_STATIC_STRINGS));
|
||||
|
||||
GST_BASE_AUTO_CONVERT_CLASS (klass)->registers_filters = FALSE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* GStreamer
|
||||
* Copyright 2010 ST-Ericsson SA
|
||||
* @author: Benjamin Gaignard <benjamin.gaignard@stericsson.com>
|
||||
* Copyright 2023 Igalia S.L.
|
||||
* @author: Thibault Saunier <tsaunier@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
@ -39,215 +41,20 @@ GST_DEBUG_CATEGORY (autovideoconvert_debug);
|
|||
|
||||
struct _GstAutoVideoConvert
|
||||
{
|
||||
GstAutoConvert parent;
|
||||
GstBaseAutoConvert parent;
|
||||
};
|
||||
|
||||
G_DEFINE_TYPE (GstAutoVideoConvert, gst_auto_video_convert,
|
||||
GST_TYPE_AUTO_CONVERT);
|
||||
GST_TYPE_BASE_AUTO_CONVERT);
|
||||
|
||||
GST_ELEMENT_REGISTER_DEFINE (autovideoconvert, "autovideoconvert",
|
||||
GST_RANK_NONE, gst_auto_video_convert_get_type ());
|
||||
|
||||
static gboolean
|
||||
gst_auto_video_convert_element_filter (GstPluginFeature * feature,
|
||||
GstAutoVideoConvert * autovideoconvert)
|
||||
{
|
||||
const gchar *klass;
|
||||
|
||||
/* we only care about element factories */
|
||||
if (G_UNLIKELY (!GST_IS_ELEMENT_FACTORY (feature)))
|
||||
return FALSE;
|
||||
|
||||
if (!g_strcmp0 (GST_OBJECT_NAME (feature), "autovideoconvert"))
|
||||
return FALSE;
|
||||
|
||||
if (gst_plugin_feature_get_rank (feature) <= GST_RANK_NONE)
|
||||
return FALSE;
|
||||
|
||||
klass = gst_element_factory_get_metadata (GST_ELEMENT_FACTORY_CAST (feature),
|
||||
GST_ELEMENT_METADATA_KLASS);
|
||||
/* only select color space converter */
|
||||
if (strstr (klass, "Colorspace") && strstr (klass, "Scaler") &&
|
||||
strstr (klass, "Converter") && strstr (klass, "Video")) {
|
||||
GST_DEBUG_OBJECT (autovideoconvert,
|
||||
"gst_auto_video_convert_element_filter found %s",
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE_CAST (feature)));
|
||||
return TRUE;
|
||||
}
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar *name;
|
||||
const gchar *bindesc;
|
||||
GstRank rank;
|
||||
} KnownBin;
|
||||
|
||||
#define GST_AUTOCONVERT_WNBIN_QUARK g_quark_from_static_string("autovideoconvert-wn-bin-quark")
|
||||
static void
|
||||
gst_auto_convert_wn_bin_class_init (GstBinClass * class)
|
||||
{
|
||||
GstElementClass *element_class = GST_ELEMENT_CLASS (class);
|
||||
KnownBin *b = g_type_get_qdata (G_OBJECT_CLASS_TYPE (class),
|
||||
GST_AUTOCONVERT_WNBIN_QUARK);
|
||||
gchar **factory_names = g_strsplit (b->bindesc, " ! ", -1);
|
||||
gint nfactories = 0;
|
||||
GstElementFactory *factory;
|
||||
GstStaticPadTemplate *template = NULL;
|
||||
|
||||
for (nfactories = 0; factory_names[nfactories + 1]; nfactories++);
|
||||
|
||||
factory = gst_element_factory_find (factory_names[0]);
|
||||
for (GList * tmp =
|
||||
(GList *) gst_element_factory_get_static_pad_templates (factory); tmp;
|
||||
tmp = tmp->next) {
|
||||
if (((GstStaticPadTemplate *) tmp->data)->direction == GST_PAD_SINK) {
|
||||
template = tmp->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
gst_element_class_add_static_pad_template (element_class, template);
|
||||
|
||||
template = NULL;
|
||||
factory = gst_element_factory_find (factory_names[nfactories]);
|
||||
for (GList * tmp =
|
||||
(GList *) gst_element_factory_get_static_pad_templates (factory); tmp;
|
||||
tmp = tmp->next) {
|
||||
if (((GstStaticPadTemplate *) tmp->data)->direction == GST_PAD_SRC) {
|
||||
template = tmp->data;
|
||||
break;
|
||||
}
|
||||
}
|
||||
g_assert (template);
|
||||
gst_element_class_add_static_pad_template (element_class, template);
|
||||
|
||||
gst_element_class_set_metadata (element_class, b->name,
|
||||
"Scaler/Colorspace/Converter/Video", b->name,
|
||||
"Thibault Saunier <tsaunier@igalia.com>");
|
||||
|
||||
g_strfreev (factory_names);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_convert_wn_bin_init (GstBin * self)
|
||||
{
|
||||
KnownBin *b =
|
||||
g_type_get_qdata (G_OBJECT_TYPE (self), GST_AUTOCONVERT_WNBIN_QUARK);
|
||||
GError *err = NULL;
|
||||
GstElement *subbin = gst_parse_bin_from_description (b->bindesc, TRUE, &err);
|
||||
|
||||
if (err)
|
||||
g_error ("%s couldn't be built?!: %s", b->name, err->message);
|
||||
|
||||
gst_bin_add (self, subbin);
|
||||
gst_element_add_pad (GST_ELEMENT (self), gst_ghost_pad_new ("sink",
|
||||
subbin->sinkpads->data));
|
||||
gst_element_add_pad (GST_ELEMENT (self), gst_ghost_pad_new ("src",
|
||||
subbin->srcpads->data));
|
||||
}
|
||||
|
||||
static void
|
||||
register_well_known_bins (void)
|
||||
{
|
||||
GTypeInfo typeinfo = {
|
||||
sizeof (GstBinClass),
|
||||
(GBaseInitFunc) NULL,
|
||||
NULL,
|
||||
(GClassInitFunc) gst_auto_convert_wn_bin_class_init,
|
||||
NULL,
|
||||
NULL,
|
||||
sizeof (GstBin),
|
||||
0,
|
||||
(GInstanceInitFunc) gst_auto_convert_wn_bin_init,
|
||||
};
|
||||
/* *INDENT-OFF* */
|
||||
const KnownBin subbins[] = {
|
||||
{
|
||||
.name = "auto+bayer2rgbcolorconvert",
|
||||
.bindesc = "bayer2rgb ! videoconvertscale ! videoflip method=automatic ! videoconvertscale",
|
||||
.rank = GST_RANK_SECONDARY,
|
||||
},
|
||||
{
|
||||
.name = "auto+colorconvertrgb2bayer",
|
||||
.bindesc = "videoconvertscale ! videoflip method=automatic ! videoconvertscale ! rgb2bayer",
|
||||
.rank = GST_RANK_SECONDARY,
|
||||
},
|
||||
{
|
||||
/* Fallback to only videoconvertscale if videoflip is not available */
|
||||
.name = "auto+colorconvert-fallback",
|
||||
.bindesc = "videoconvertscale",
|
||||
.rank = GST_RANK_MARGINAL,
|
||||
},
|
||||
{
|
||||
.name = "auto+colorconvert",
|
||||
.bindesc = "videoconvertscale ! videoflip method=automatic ! videoconvertscale",
|
||||
.rank = GST_RANK_SECONDARY,
|
||||
},
|
||||
{
|
||||
.name = "auto+glcolorconvert",
|
||||
.bindesc = "glcolorconvert ! glcolorscale ! glvideoflip method=automatic ! glcolorconvert",
|
||||
.rank = GST_RANK_PRIMARY,
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
for (gint i = 0; i < G_N_ELEMENTS (subbins); i++) {
|
||||
GType type = 0;
|
||||
KnownBin *b = NULL;
|
||||
GstElement *subbin = gst_parse_launch (subbins[i].bindesc, NULL);
|
||||
|
||||
if (!subbin) {
|
||||
GST_INFO ("Ignoring possible Converting scaler: %s '%s'", subbins[i].name,
|
||||
subbins[i].bindesc);
|
||||
continue;
|
||||
}
|
||||
|
||||
gst_object_unref (subbin);
|
||||
|
||||
type = g_type_register_static (GST_TYPE_BIN, subbins[i].name, &typeinfo, 0);
|
||||
b = g_malloc0 (sizeof (KnownBin));
|
||||
b->name = g_strdup (subbins[i].name);
|
||||
b->bindesc = g_strdup (subbins[i].bindesc);
|
||||
b->rank = subbins[i].rank;
|
||||
|
||||
g_type_set_qdata (type, GST_AUTOCONVERT_WNBIN_QUARK, b);
|
||||
|
||||
if (!gst_element_register (NULL, b->name, b->rank, type)) {
|
||||
g_warning ("Failed to register %s", "autoglcolorconverter");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static GList *
|
||||
gst_auto_video_convert_create_factory_list (GstAutoConvert * autoconvert)
|
||||
{
|
||||
GList *result = NULL;
|
||||
static gpointer registered_well_known_bins = FALSE;
|
||||
|
||||
if (g_once_init_enter (®istered_well_known_bins)) {
|
||||
register_well_known_bins ();
|
||||
g_once_init_leave (®istered_well_known_bins, (gpointer) TRUE);
|
||||
}
|
||||
|
||||
/* get the feature list using the filter */
|
||||
result = gst_registry_feature_filter (gst_registry_get (),
|
||||
(GstPluginFeatureFilter) gst_auto_video_convert_element_filter,
|
||||
FALSE, autoconvert);
|
||||
|
||||
/* sort on rank and name */
|
||||
result = g_list_sort (result, gst_plugin_feature_rank_compare_func);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_video_convert_class_init (GstAutoVideoConvertClass * klass)
|
||||
{
|
||||
GstElementClass *gstelement_class = (GstElementClass *) klass;
|
||||
|
||||
((GstAutoConvertClass *) klass)->load_factories =
|
||||
gst_auto_video_convert_create_factory_list;
|
||||
GST_DEBUG_CATEGORY_INIT (autovideoconvert_debug, "autovideoconvert", 0,
|
||||
"Auto color space converter");
|
||||
|
||||
|
@ -255,10 +62,123 @@ gst_auto_video_convert_class_init (GstAutoVideoConvertClass * klass)
|
|||
"Select color space converter and scalers based on caps",
|
||||
"Bin/Colorspace/Scale/Video/Converter",
|
||||
"Selects the right color space converter based on the caps",
|
||||
"Benjamin Gaignard <benjamin.gaignard@stericsson.com>");
|
||||
"Thibault Saunier <tsaunier@igalia.com>");
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_video_convert_init (GstAutoVideoConvert * autovideoconvert)
|
||||
{
|
||||
/* *INDENT-OFF* */
|
||||
static const GstAutoVideoFilterGenerator gen[] = {
|
||||
{
|
||||
.first_elements = { "bayer2rgb", NULL},
|
||||
.colorspace_converters = { "videoconvertscale", NULL },
|
||||
.last_elements = { NULL } ,
|
||||
.filters = { NULL},
|
||||
.rank = GST_RANK_SECONDARY,
|
||||
},
|
||||
{
|
||||
.first_elements = { NULL, },
|
||||
.colorspace_converters = { "videoconvertscale", NULL },
|
||||
.last_elements = { "rgb2bayer", NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_SECONDARY,
|
||||
},
|
||||
{
|
||||
.first_elements = { NULL, },
|
||||
.colorspace_converters = { "videoconvertscale", NULL },
|
||||
.last_elements = { NULL, },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_SECONDARY,
|
||||
},
|
||||
{
|
||||
.first_elements = { NULL, },
|
||||
.colorspace_converters = { "glcolorconvert", "glcolorscale", "glcolorconvert", NULL },
|
||||
.last_elements = { NULL, },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_PRIMARY,
|
||||
},
|
||||
{
|
||||
.first_elements = { "glupload", },
|
||||
.colorspace_converters = { "glcolorconvert", "glcolorscale", "glcolorconvert", NULL },
|
||||
.last_elements = { NULL, },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_PRIMARY,
|
||||
},
|
||||
{
|
||||
.first_elements = { "videoconvertscale", "glupload", NULL },
|
||||
.colorspace_converters = { NULL },
|
||||
.last_elements = { NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_MARGINAL + 1,
|
||||
},
|
||||
{
|
||||
.first_elements = { "glcolorconvert", "gldownload", NULL },
|
||||
.colorspace_converters = { NULL },
|
||||
.last_elements = { NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_MARGINAL + 2,
|
||||
},
|
||||
{ /* Worst case we upload/download as required */
|
||||
.first_elements = { "glupload", "gldownload", NULL },
|
||||
.colorspace_converters = { "glcolorconvert", "glcolorscale", "glcolorconvert", NULL },
|
||||
.last_elements = { "glupload", "gldownload", NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_MARGINAL + 1,
|
||||
},
|
||||
{ /* Pure cuda is preferred */
|
||||
.first_elements = { NULL },
|
||||
.colorspace_converters = { "cudaconvertscale", NULL },
|
||||
.last_elements = { NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_PRIMARY,
|
||||
},
|
||||
{ /* CUDA -> GL */
|
||||
.first_elements = { "capsfilter caps=video/x-raw(memory:CUDAMemory)", "cudadownload", NULL },
|
||||
.colorspace_converters = { "glcolorconvert", "glcolorscale", "glcolorconvert", NULL },
|
||||
.last_elements = { "glupload", "gldownload", NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_SECONDARY,
|
||||
},
|
||||
{ /* GL memory to cuda */
|
||||
.first_elements = { NULL },
|
||||
.colorspace_converters = { "glcolorconvert", "glcolorscale", "glcolorconvert", NULL },
|
||||
.last_elements = { "cudaupload", "capsfilter caps=video/x-raw(memory:CUDAMemory)", NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_MARGINAL,
|
||||
},
|
||||
{ /* System memory to cuda */
|
||||
.first_elements = { NULL },
|
||||
.colorspace_converters = { "videoconvertscale", NULL },
|
||||
.last_elements = { "cudaupload", "capsfilter caps=video/x-raw(memory:CUDAMemory)", NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_MARGINAL,
|
||||
},
|
||||
{
|
||||
.first_elements = { NULL, },
|
||||
.colorspace_converters = { "d3d11convert", NULL },
|
||||
.last_elements = { NULL, },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_PRIMARY,
|
||||
},
|
||||
{
|
||||
.first_elements = { "d3d11download", "d3d11upload", NULL},
|
||||
.colorspace_converters = { "glcolorconvert", "glcolorscale", "glcolorconvert", NULL },
|
||||
.last_elements = { "d3d11download", "d3d11upload", NULL },
|
||||
.filters = { NULL },
|
||||
.rank = GST_RANK_MARGINAL,
|
||||
},
|
||||
{ /* Worst case we upload/download as required */
|
||||
.first_elements = { NULL},
|
||||
.colorspace_converters = { NULL },
|
||||
.last_elements = { NULL },
|
||||
.filters = { NULL },
|
||||
.rank = 0,
|
||||
},
|
||||
};
|
||||
/* *INDENT-ON* */
|
||||
|
||||
|
||||
gst_auto_video_register_well_known_bins (GST_BASE_AUTO_CONVERT
|
||||
(autovideoconvert), gen);
|
||||
}
|
||||
|
|
|
@ -1,6 +1,8 @@
|
|||
/* GStreamer
|
||||
* Copyright 2010 ST-Ericsson SA
|
||||
* @author: Benjamin Gaignard <benjamin.gaignard@stericsson.com>
|
||||
* Copyright 2023 Igalia S.L.
|
||||
* @author: Thibault Saunier <tsaunier@igalia.com>
|
||||
*
|
||||
* This library is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU Library General Public
|
||||
|
@ -27,8 +29,20 @@
|
|||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
G_DECLARE_FINAL_TYPE(GstAutoVideoConvert, gst_auto_video_convert, GST, AUTO_VIDEO_CONVERT, GstAutoConvert);
|
||||
G_DECLARE_FINAL_TYPE(GstAutoVideoConvert, gst_auto_video_convert, GST, AUTO_VIDEO_CONVERT, GstBaseAutoConvert);
|
||||
GST_ELEMENT_REGISTER_DECLARE (autovideoconvert);
|
||||
|
||||
typedef struct
|
||||
{
|
||||
const gchar *first_elements[4];
|
||||
const gchar *colorspace_converters[4];
|
||||
const gchar *last_elements[4];
|
||||
|
||||
const gchar *possible_filters[4];
|
||||
GstRank rank;
|
||||
} GstAutoVideoConvertFilterBinsGenerator;
|
||||
|
||||
void gst_auto_video_register_well_known_bins (GstAutoVideoConvert *self, GstAutoVideoConvertFilterBinsGenerator *gen);
|
||||
|
||||
G_END_DECLS
|
||||
#endif /* __GST_AUTO_VIDEO_CONVERT_H__ */
|
||||
|
|
|
@ -102,8 +102,8 @@ static gboolean gst_base_auto_convert_internal_src_event (GstPad * pad,
|
|||
GstObject * parent, GstEvent * event);
|
||||
static gboolean gst_base_auto_convert_internal_src_query (GstPad * pad,
|
||||
GstObject * parent, GstQuery * query);
|
||||
static GList *gst_base_auto_convert_get_or_load_factories (GstBaseAutoConvert *
|
||||
self);
|
||||
static GList *gst_base_auto_convert_get_or_load_filters_info (GstBaseAutoConvert
|
||||
* self);
|
||||
|
||||
G_DECLARE_FINAL_TYPE (GstBaseAutoConvertPad, gst_base_auto_convert_pad, GST,
|
||||
BASE_AUTO_CONVERT_PAD, GstPad);
|
||||
|
@ -184,6 +184,112 @@ gst_base_auto_convert_element_removed (GstBin * bin, GstElement * child)
|
|||
g_hash_table_remove (self->elements, child);
|
||||
}
|
||||
|
||||
static void
|
||||
gst_auto_convert_filter_info_free (GstAutoConvertFilterInfo * knwon_bin)
|
||||
{
|
||||
g_free (knwon_bin->name);
|
||||
g_free (knwon_bin->bindesc);
|
||||
|
||||
g_free (knwon_bin);
|
||||
}
|
||||
|
||||
static gint
|
||||
g_auto_convert_filter_info_compare (GstAutoConvertFilterInfo * b1,
|
||||
GstAutoConvertFilterInfo * b2)
|
||||
{
|
||||
gint diff;
|
||||
|
||||
diff = b2->rank - b1->rank;
|
||||
if (diff != 0)
|
||||
return diff;
|
||||
|
||||
diff = g_strcmp0 (b2->name, b1->name);
|
||||
|
||||
return diff;
|
||||
}
|
||||
|
||||
static GstCaps *
|
||||
gst_base_auto_convert_get_template_caps_for (GstElement * subbin,
|
||||
GstPadDirection dir)
|
||||
{
|
||||
GstElement *element = NULL;
|
||||
GstPad *pad = NULL;
|
||||
GstCaps *res = NULL;
|
||||
|
||||
g_assert (g_list_length (subbin->sinkpads) == 1);
|
||||
g_assert (g_list_length (subbin->srcpads) == 1);
|
||||
if (GST_IS_BIN (subbin)) {
|
||||
GstPad *ghostpad =
|
||||
(dir == GST_PAD_SINK) ? subbin->sinkpads->data : subbin->srcpads->data;
|
||||
GstPad *internal = gst_pad_get_single_internal_link (ghostpad);
|
||||
|
||||
pad = gst_pad_get_peer (internal);
|
||||
|
||||
gst_object_unref (internal);
|
||||
} else {
|
||||
pad =
|
||||
(dir ==
|
||||
GST_PAD_SINK) ? gst_object_ref (subbin->
|
||||
sinkpads->data) : gst_object_ref (subbin->srcpads->data);
|
||||
}
|
||||
|
||||
element = GST_ELEMENT (GST_OBJECT_PARENT (pad));
|
||||
g_assert (element);
|
||||
|
||||
if (!g_strcmp0 (GST_OBJECT_NAME (gst_element_get_factory (element)),
|
||||
"capsfilter")) {
|
||||
g_object_get (G_OBJECT (element), "caps", &res, NULL);
|
||||
} else {
|
||||
res = gst_pad_get_pad_template_caps (pad);
|
||||
}
|
||||
gst_object_unref (pad);
|
||||
|
||||
return gst_caps_make_writable (res);
|
||||
}
|
||||
|
||||
gboolean
|
||||
gst_base_auto_convert_register_filter (GstBaseAutoConvert * self, gchar * name,
|
||||
gchar * bindesc, GstRank rank)
|
||||
{
|
||||
g_assert (name);
|
||||
|
||||
for (GList * tmp = self->filters_info; tmp; tmp = tmp->next) {
|
||||
g_return_val_if_fail (g_strcmp0 (name,
|
||||
((GstAutoConvertFilterInfo *) tmp->data)->name), FALSE);
|
||||
}
|
||||
|
||||
GError *err = NULL;
|
||||
bindesc = g_strchomp (bindesc);
|
||||
GstElement *subbin = gst_parse_bin_from_description_full (bindesc, TRUE,
|
||||
NULL, GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS | GST_PARSE_FLAG_PLACE_IN_BIN,
|
||||
&err);
|
||||
|
||||
if (!subbin) {
|
||||
GST_INFO ("Could not create subbin for %s", name);
|
||||
g_free (name);
|
||||
g_free (bindesc);
|
||||
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
GstAutoConvertFilterInfo *filter_info = g_new0 (GstAutoConvertFilterInfo, 1);
|
||||
filter_info->sink_caps =
|
||||
gst_base_auto_convert_get_template_caps_for (subbin, GST_PAD_SINK);
|
||||
filter_info->src_caps =
|
||||
gst_base_auto_convert_get_template_caps_for (subbin, GST_PAD_SRC);
|
||||
filter_info->name = name;
|
||||
filter_info->bindesc = bindesc;
|
||||
filter_info->rank = rank;
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
self->filters_info =
|
||||
g_list_insert_sorted (self->filters_info, filter_info,
|
||||
(GCompareFunc) g_auto_convert_filter_info_compare);
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
gst_base_auto_convert_class_init (GstBaseAutoConvertClass * klass)
|
||||
{
|
||||
|
@ -201,6 +307,8 @@ gst_base_auto_convert_class_init (GstBaseAutoConvertClass * klass)
|
|||
gobject_class->finalize = GST_DEBUG_FUNCPTR (gst_base_auto_convert_finalize);
|
||||
|
||||
gstbin_class->element_removed = gst_base_auto_convert_element_removed;
|
||||
|
||||
klass->registers_filters = TRUE;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -255,34 +363,12 @@ gst_base_auto_convert_finalize (GObject * object)
|
|||
if (self->factories)
|
||||
gst_plugin_feature_list_free (self->factories);
|
||||
g_hash_table_unref (self->elements);
|
||||
g_list_free_full (self->filters_info,
|
||||
(GDestroyNotify) gst_auto_convert_filter_info_free);
|
||||
|
||||
G_OBJECT_CLASS (gst_base_auto_convert_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
static GstElement *
|
||||
gst_base_auto_convert_get_element_by_type (GstBaseAutoConvert * self,
|
||||
GType type)
|
||||
{
|
||||
GList *item, *elements;
|
||||
GstElement *element = NULL;
|
||||
|
||||
g_return_val_if_fail (type != 0, NULL);
|
||||
|
||||
GST_BASEAUTOCONVERT_LOCK (self);
|
||||
elements = g_hash_table_get_keys (self->elements);
|
||||
for (item = elements; item; item = item->next) {
|
||||
if (G_OBJECT_TYPE (item->data) == type) {
|
||||
element = gst_object_ref (item->data);
|
||||
break;
|
||||
}
|
||||
}
|
||||
GST_BASEAUTOCONVERT_UNLOCK (self);
|
||||
|
||||
g_list_free (elements);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
/**
|
||||
* get_pad_by_direction:
|
||||
* @element: The Element
|
||||
|
@ -401,18 +487,28 @@ gst_base_auto_convert_get_internal_srcpad (GstBaseAutoConvert * self)
|
|||
|
||||
static GstElement *
|
||||
gst_base_auto_convert_add_element (GstBaseAutoConvert * self,
|
||||
GstElementFactory * factory)
|
||||
GstAutoConvertFilterInfo * filter_info)
|
||||
{
|
||||
GstElement *element = NULL;
|
||||
InternalPads *pads;
|
||||
GError *error = NULL;
|
||||
|
||||
GST_DEBUG_OBJECT (self, "Adding element %s to the baseautoconvert bin",
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)));
|
||||
filter_info->name);
|
||||
|
||||
element = gst_parse_bin_from_description_full (filter_info->bindesc, TRUE,
|
||||
NULL, GST_PARSE_FLAG_NO_SINGLE_ELEMENT_BINS | GST_PARSE_FLAG_PLACE_IN_BIN,
|
||||
&error);
|
||||
if (!element) {
|
||||
GST_INFO_OBJECT (self, "Could not build %s: %s", filter_info->name,
|
||||
error->message);
|
||||
|
||||
g_error_free (error);
|
||||
|
||||
element = gst_element_factory_create (factory, NULL);
|
||||
if (!element)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
gst_object_set_name (GST_OBJECT (element), filter_info->name);
|
||||
pads = internal_pads_new (self, GST_OBJECT_NAME (element));
|
||||
g_hash_table_insert (self->elements, element, pads);
|
||||
|
||||
|
@ -434,26 +530,17 @@ gst_base_auto_convert_add_element (GstBaseAutoConvert * self,
|
|||
}
|
||||
|
||||
static GstElement *
|
||||
gst_base_auto_convert_get_or_make_element_from_factory (GstBaseAutoConvert *
|
||||
self, GstElementFactory * factory)
|
||||
gst_base_auto_convert_get_or_make_element_from_filter_info (GstBaseAutoConvert *
|
||||
self, GstAutoConvertFilterInfo * nb)
|
||||
{
|
||||
GstElement *element = NULL;
|
||||
GstElementFactory *loaded_factory =
|
||||
GST_ELEMENT_FACTORY (gst_plugin_feature_load (GST_PLUGIN_FEATURE
|
||||
(factory)));
|
||||
|
||||
if (!loaded_factory)
|
||||
return NULL;
|
||||
|
||||
element = gst_base_auto_convert_get_element_by_type (self,
|
||||
gst_element_factory_get_element_type (loaded_factory));
|
||||
element = gst_bin_get_by_name (GST_BIN (self), nb->name);
|
||||
|
||||
if (!element) {
|
||||
element = gst_base_auto_convert_add_element (self, loaded_factory);
|
||||
element = gst_base_auto_convert_add_element (self, nb);
|
||||
}
|
||||
|
||||
gst_object_unref (loaded_factory);
|
||||
|
||||
return element;
|
||||
}
|
||||
|
||||
|
@ -464,51 +551,25 @@ gst_base_auto_convert_get_or_make_element_from_factory (GstBaseAutoConvert *
|
|||
*/
|
||||
|
||||
static gboolean
|
||||
factory_can_intersect (GstBaseAutoConvert * self,
|
||||
GstElementFactory * factory, GstPadDirection direction, GstCaps * caps)
|
||||
filter_info_can_intersect (GstBaseAutoConvert * self,
|
||||
GstAutoConvertFilterInfo * filter_info, GstPadDirection direction,
|
||||
GstCaps * caps)
|
||||
{
|
||||
const GList *templates;
|
||||
gint has_direction = FALSE;
|
||||
gboolean ret = FALSE;
|
||||
gboolean res;
|
||||
GST_LOG_OBJECT (self, "Checking if %s (bin_desc=%s) supports %s caps:",
|
||||
filter_info->name, filter_info->bindesc,
|
||||
direction == GST_PAD_SINK ? "sink" : "src");
|
||||
GST_LOG_OBJECT (self, "Supported caps: %" GST_PTR_FORMAT,
|
||||
direction ==
|
||||
GST_PAD_SINK ? filter_info->sink_caps : filter_info->src_caps);
|
||||
GST_LOG_OBJECT (self, "Caps: %" GST_PTR_FORMAT, caps);
|
||||
|
||||
g_return_val_if_fail (factory != NULL, FALSE);
|
||||
g_return_val_if_fail (caps != NULL, FALSE);
|
||||
res =
|
||||
gst_caps_can_intersect (direction ==
|
||||
GST_PAD_SINK ? filter_info->sink_caps : filter_info->src_caps, caps);
|
||||
GST_LOG_OBJECT (self, "Intersect result: %d", res);
|
||||
|
||||
templates = gst_element_factory_get_static_pad_templates (factory);
|
||||
|
||||
while (templates) {
|
||||
GstStaticPadTemplate *template = (GstStaticPadTemplate *) templates->data;
|
||||
|
||||
if (template->direction == direction) {
|
||||
GstCaps *tmpl_caps = NULL;
|
||||
gboolean intersect;
|
||||
|
||||
/* If there is more than one pad in this direction, we return FALSE
|
||||
* Only transform elements (with one sink and one source pad)
|
||||
* are accepted
|
||||
*/
|
||||
if (has_direction) {
|
||||
GST_ERROR_OBJECT (self, "Factory %p"
|
||||
" has more than one static template with dir %d",
|
||||
template, direction);
|
||||
return FALSE;
|
||||
}
|
||||
has_direction = TRUE;
|
||||
|
||||
tmpl_caps = gst_static_caps_get (&template->static_caps);
|
||||
intersect = gst_caps_can_intersect (tmpl_caps, caps);
|
||||
GST_DEBUG_OBJECT (self, "Factories %" GST_PTR_FORMAT
|
||||
" static caps %" GST_PTR_FORMAT " and caps %" GST_PTR_FORMAT
|
||||
" can%s intersect", factory, tmpl_caps, caps,
|
||||
intersect ? "" : " not");
|
||||
gst_caps_unref (tmpl_caps);
|
||||
|
||||
ret |= intersect;
|
||||
}
|
||||
templates = g_list_next (templates);
|
||||
}
|
||||
|
||||
return ret;
|
||||
return res;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
@ -633,6 +694,9 @@ gst_base_auto_convert_activate_element (GstBaseAutoConvert * self,
|
|||
GST_OBJECT_NAME (GST_OBJECT (element)));
|
||||
|
||||
done:
|
||||
GST_DEBUG_OBJECT (element, "Activating element %s",
|
||||
res ? "succeeded" : "failed");
|
||||
|
||||
gst_object_unref (element);
|
||||
internal_pads_unref (pads);
|
||||
gst_clear_object (&srcpad);
|
||||
|
@ -677,6 +741,22 @@ gst_base_auto_convert_iterate_internal_links (GstPad * pad, GstObject * parent)
|
|||
return it;
|
||||
}
|
||||
|
||||
static GstAutoConvertFilterInfo *
|
||||
gst_auto_convert_get_filter_info (GstBaseAutoConvert * self,
|
||||
GstElement * element)
|
||||
{
|
||||
GList *tmp;
|
||||
|
||||
for (tmp = self->filters_info; tmp; tmp = tmp->next) {
|
||||
GstAutoConvertFilterInfo *filter_info = tmp->data;
|
||||
|
||||
if (!g_strcmp0 (filter_info->name, GST_OBJECT_NAME (element)))
|
||||
return filter_info;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/*
|
||||
* If there is already an internal element, it will try to call set_caps on it
|
||||
*
|
||||
|
@ -689,9 +769,9 @@ static gboolean
|
|||
gst_base_auto_convert_sink_setcaps (GstBaseAutoConvert * self, GstCaps * caps,
|
||||
gboolean check_downstream)
|
||||
{
|
||||
GList *elem;
|
||||
GList *tmp;
|
||||
GstCaps *other_caps = NULL;
|
||||
GList *factories;
|
||||
GList *filters_info = NULL;
|
||||
GstCaps *current_caps = NULL;
|
||||
gboolean res = FALSE;
|
||||
GstElement *current_subelement = NULL;
|
||||
|
@ -709,66 +789,81 @@ gst_base_auto_convert_sink_setcaps (GstBaseAutoConvert * self, GstCaps * caps,
|
|||
other_caps = gst_pad_peer_query_caps (self->srcpad, NULL);
|
||||
|
||||
current_subelement = gst_base_auto_convert_get_subelement (self);
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"'%" GST_PTR_FORMAT "' Setting caps to: %" GST_PTR_FORMAT
|
||||
" - other caps: %" GST_PTR_FORMAT, current_subelement, caps, other_caps);
|
||||
if (current_subelement) {
|
||||
if (gst_pad_peer_query_accept_caps (self->current_internal_srcpad, caps)) {
|
||||
GstAutoConvertFilterInfo *filter_info =
|
||||
gst_auto_convert_get_filter_info (self, current_subelement);
|
||||
|
||||
res = TRUE;
|
||||
if (other_caps) {
|
||||
GstElementFactory *factory =
|
||||
gst_element_get_factory (current_subelement);
|
||||
|
||||
if (!factory_can_intersect (self, factory, GST_PAD_SRC, other_caps)) {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Checking if known bin %s can intersect with %" GST_PTR_FORMAT,
|
||||
filter_info->name, other_caps);
|
||||
if (!filter_info_can_intersect (self, filter_info, GST_PAD_SRC,
|
||||
other_caps)) {
|
||||
GST_LOG_OBJECT (self,
|
||||
"Factory %s does not accept src caps %" GST_PTR_FORMAT,
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
|
||||
other_caps);
|
||||
"filter_info %s does not accept src caps %" GST_PTR_FORMAT,
|
||||
filter_info->name, other_caps);
|
||||
res = FALSE;
|
||||
}
|
||||
GST_DEBUG_OBJECT (self, "Filter %s can intersect", filter_info->name);
|
||||
}
|
||||
|
||||
if (res) {
|
||||
/* If we can set the new caps on the current element,
|
||||
* then we just get out
|
||||
*/
|
||||
GST_ERROR_OBJECT (self, "Could set %s:%s to %" GST_PTR_FORMAT,
|
||||
GST_DEBUG_PAD_NAME (self->current_internal_srcpad), caps);
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Could set %s:%s to %" GST_PTR_FORMAT " reusing %s",
|
||||
GST_DEBUG_PAD_NAME (self->current_internal_srcpad), caps,
|
||||
filter_info->name);
|
||||
goto get_out;
|
||||
} else {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Can't reuse currently configured subelement: %s",
|
||||
filter_info->name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!check_downstream)
|
||||
other_caps = gst_pad_peer_query_caps (self->srcpad, NULL);
|
||||
/* We already queries downstream caps otherwise */
|
||||
/* We already queried downstream caps otherwise */
|
||||
|
||||
factories = gst_base_auto_convert_get_or_load_factories (self);
|
||||
|
||||
for (elem = factories; elem; elem = g_list_next (elem)) {
|
||||
GstElementFactory *factory = GST_ELEMENT_FACTORY (elem->data);
|
||||
filters_info = gst_base_auto_convert_get_or_load_filters_info (self);
|
||||
for (tmp = filters_info; tmp; tmp = g_list_next (tmp)) {
|
||||
GstAutoConvertFilterInfo *filter_info = tmp->data;
|
||||
GstElement *element;
|
||||
|
||||
/* Lets first check if according to the static pad templates on the factory
|
||||
GST_DEBUG_OBJECT (self, "Trying %s (bin_desc=%s)", filter_info->name,
|
||||
filter_info->bindesc);
|
||||
/* Lets first check if according to the static pad templates on the known bin
|
||||
* these caps have any chance of success
|
||||
*/
|
||||
if (!factory_can_intersect (self, factory, GST_PAD_SINK, caps)) {
|
||||
GST_LOG_OBJECT (self, "Factory %s does not accept sink caps %"
|
||||
GST_PTR_FORMAT,
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)), caps);
|
||||
if (!filter_info_can_intersect (self, filter_info, GST_PAD_SINK, caps)) {
|
||||
GST_DEBUG_OBJECT (self, "Known bin %s does not accept sink caps %"
|
||||
GST_PTR_FORMAT, filter_info->name, caps);
|
||||
continue;
|
||||
}
|
||||
if (other_caps != NULL) {
|
||||
if (!factory_can_intersect (self, factory, GST_PAD_SRC, other_caps)) {
|
||||
GST_LOG_OBJECT (self,
|
||||
"Factory %s does not accept src caps %" GST_PTR_FORMAT,
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
|
||||
other_caps);
|
||||
if (!filter_info_can_intersect (self, filter_info, GST_PAD_SRC,
|
||||
other_caps)) {
|
||||
GST_DEBUG_OBJECT (self,
|
||||
"Known bin %s does not accept src caps %" GST_PTR_FORMAT,
|
||||
filter_info->name, other_caps);
|
||||
continue;
|
||||
}
|
||||
GST_DEBUG_OBJECT (self, "Filter %s can intersect", filter_info->name);
|
||||
}
|
||||
|
||||
/* The element had a chance of success, lets make it */
|
||||
GST_DEBUG_OBJECT (self, "Trying bin %s", filter_info->name);
|
||||
element =
|
||||
gst_base_auto_convert_get_or_make_element_from_factory (self, factory);
|
||||
gst_base_auto_convert_get_or_make_element_from_filter_info (self,
|
||||
filter_info);
|
||||
if (!element)
|
||||
continue;
|
||||
|
||||
|
@ -786,9 +881,10 @@ get_out:
|
|||
gst_clear_caps (&other_caps);
|
||||
gst_clear_caps (¤t_caps);
|
||||
|
||||
if (!res)
|
||||
if (!res) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"Could not find a matching element for caps: %" GST_PTR_FORMAT, caps);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
@ -870,32 +966,51 @@ compare_ranks (GstPluginFeature * f1, GstPluginFeature * f2)
|
|||
}
|
||||
|
||||
static GList *
|
||||
gst_base_auto_convert_get_or_load_factories (GstBaseAutoConvert * self)
|
||||
gst_base_auto_convert_get_or_load_filters_info (GstBaseAutoConvert * self)
|
||||
{
|
||||
GList *all_factories;
|
||||
GstBaseAutoConvertClass *klass = GST_BASE_AUTO_CONVERT_GET_CLASS (self);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
if (self->factories)
|
||||
if (self->filters_info) {
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
goto done;
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
}
|
||||
|
||||
if (GST_BASE_AUTO_CONVERT_GET_CLASS (self)->registers_filters) {
|
||||
GST_ERROR_OBJECT (self,
|
||||
"Filters should have been registered but none found");
|
||||
|
||||
GST_ELEMENT_ERROR (self, CORE, MISSING_PLUGIN, ("No known filter found."),
|
||||
(NULL));
|
||||
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!self->factories) {
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
if (klass->load_factories) {
|
||||
all_factories = klass->load_factories (self);
|
||||
} else {
|
||||
all_factories =
|
||||
g_list_sort (gst_registry_feature_filter (gst_registry_get (),
|
||||
gst_base_auto_convert_default_filter_func, FALSE, NULL),
|
||||
(GCompareFunc) compare_ranks);
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
self->factories = all_factories;
|
||||
}
|
||||
|
||||
GST_OBJECT_LOCK (self);
|
||||
self->factories = all_factories;
|
||||
|
||||
done:
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
|
||||
return self->factories;
|
||||
for (GList * tmp = self->factories; tmp; tmp = g_list_next (tmp)) {
|
||||
GstElementFactory *factory = tmp->data;
|
||||
|
||||
gst_base_auto_convert_register_filter (self,
|
||||
gst_object_get_name (GST_OBJECT (factory)),
|
||||
gst_object_get_name (GST_OBJECT (factory)),
|
||||
gst_plugin_feature_get_rank (GST_PLUGIN_FEATURE (factory))
|
||||
);
|
||||
}
|
||||
|
||||
done:
|
||||
return self->filters_info;
|
||||
}
|
||||
|
||||
/* In this case, we should almost always have an internal element, because
|
||||
|
@ -1078,7 +1193,7 @@ gst_base_auto_convert_getcaps (GstBaseAutoConvert * self, GstCaps * filter,
|
|||
GstPadDirection dir)
|
||||
{
|
||||
GstCaps *caps = NULL, *other_caps = NULL;
|
||||
GList *elem, *factories;
|
||||
GList *kb, *filters_info;
|
||||
|
||||
caps = gst_caps_new_empty ();
|
||||
|
||||
|
@ -1095,35 +1210,35 @@ gst_base_auto_convert_getcaps (GstBaseAutoConvert * self, GstCaps * filter,
|
|||
goto out;
|
||||
}
|
||||
|
||||
factories = gst_base_auto_convert_get_or_load_factories (self);
|
||||
for (elem = factories; elem; elem = g_list_next (elem)) {
|
||||
GstElementFactory *factory = GST_ELEMENT_FACTORY (elem->data);
|
||||
filters_info = gst_base_auto_convert_get_or_load_filters_info (self);
|
||||
for (kb = filters_info; kb; kb = g_list_next (kb)) {
|
||||
GstAutoConvertFilterInfo *filter_info = kb->data;
|
||||
GstElement *element = NULL;
|
||||
GstCaps *element_caps;
|
||||
InternalPads *pads;
|
||||
|
||||
if (filter) {
|
||||
if (!factory_can_intersect (self, factory, dir, filter)) {
|
||||
if (!filter_info_can_intersect (self, filter_info, dir, filter)) {
|
||||
GST_LOG_OBJECT (self,
|
||||
"Factory %s does not accept src caps %" GST_PTR_FORMAT,
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
|
||||
other_caps);
|
||||
"Bin %s does not accept %s caps %" GST_PTR_FORMAT,
|
||||
filter_info->name, dir == GST_PAD_SRC ? "src" : "sink", other_caps);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (other_caps != NULL) {
|
||||
if (!factory_can_intersect (self, factory,
|
||||
if (!filter_info_can_intersect (self, filter_info,
|
||||
dir == GST_PAD_SINK ? GST_PAD_SRC : GST_PAD_SINK, other_caps)) {
|
||||
GST_LOG_OBJECT (self,
|
||||
"Factory %s does not accept src caps %" GST_PTR_FORMAT,
|
||||
gst_plugin_feature_get_name (GST_PLUGIN_FEATURE (factory)),
|
||||
other_caps);
|
||||
"%s does not accept %s caps %" GST_PTR_FORMAT,
|
||||
filter_info->name,
|
||||
dir == GST_PAD_SINK ? "src" : "sink", other_caps);
|
||||
continue;
|
||||
}
|
||||
|
||||
element = gst_base_auto_convert_get_or_make_element_from_factory (self,
|
||||
factory);
|
||||
element =
|
||||
gst_base_auto_convert_get_or_make_element_from_filter_info (self,
|
||||
filter_info);
|
||||
if (element == NULL)
|
||||
continue;
|
||||
|
||||
|
@ -1141,24 +1256,16 @@ gst_base_auto_convert_getcaps (GstBaseAutoConvert * self, GstCaps * filter,
|
|||
if (gst_caps_is_any (caps))
|
||||
goto out;
|
||||
} else {
|
||||
const GList *tmp;
|
||||
GstCaps *static_caps =
|
||||
dir == GST_PAD_SRC ? filter_info->src_caps : filter_info->sink_caps;
|
||||
|
||||
for (tmp = gst_element_factory_get_static_pad_templates (factory);
|
||||
tmp; tmp = g_list_next (tmp)) {
|
||||
GstStaticPadTemplate *template = tmp->data;
|
||||
|
||||
if (GST_PAD_TEMPLATE_DIRECTION (template) == dir) {
|
||||
GstCaps *static_caps = gst_static_pad_template_get_caps (template);
|
||||
|
||||
if (static_caps) {
|
||||
caps = gst_caps_merge (caps, static_caps);
|
||||
}
|
||||
|
||||
/* Early out, any is absorbing */
|
||||
if (gst_caps_is_any (caps))
|
||||
goto out;
|
||||
}
|
||||
if (static_caps) {
|
||||
caps = gst_caps_merge (caps, static_caps);
|
||||
}
|
||||
|
||||
/* Early out, any is absorbing */
|
||||
if (gst_caps_is_any (caps))
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1191,7 +1298,7 @@ gst_base_auto_convert_src_event (GstPad * pad, GstObject * parent,
|
|||
gst_object_unref (internal_sinkpad);
|
||||
} else if (GST_EVENT_TYPE (event) != GST_EVENT_RECONFIGURE) {
|
||||
GST_WARNING_OBJECT (self,
|
||||
"Got upstream event while no element was selected," "forwarding.");
|
||||
"Got upstream event while no element was selected, forwarding.");
|
||||
ret = gst_pad_push_event (self->sinkpad, event);
|
||||
} else
|
||||
gst_event_unref (event);
|
||||
|
@ -1339,3 +1446,14 @@ gst_base_auto_convert_internal_src_query (GstPad * pad, GstObject * parent,
|
|||
|
||||
return gst_pad_peer_query (self->sinkpad, query);
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
gst_base_auto_convert_reset_filters (GstBaseAutoConvert * self)
|
||||
{
|
||||
GST_OBJECT_LOCK (self);
|
||||
g_list_free_full (self->filters_info,
|
||||
(GDestroyNotify) gst_auto_convert_filter_info_free);
|
||||
self->filters_info = NULL;
|
||||
GST_OBJECT_UNLOCK (self);
|
||||
}
|
||||
|
|
|
@ -42,6 +42,7 @@ struct _GstBaseAutoConvert
|
|||
GstBin bin; /* we extend GstBin */
|
||||
|
||||
GList *factories;
|
||||
GList *filters_info;
|
||||
|
||||
GstPad *sinkpad;
|
||||
GstPad *srcpad;
|
||||
|
@ -54,17 +55,36 @@ struct _GstBaseAutoConvert
|
|||
GstPad *current_internal_srcpad;
|
||||
GstPad *current_internal_sinkpad;
|
||||
|
||||
GHashTable * elements;
|
||||
GHashTable *elements;
|
||||
};
|
||||
|
||||
/* This structure is used to allow handling random bin from their description
|
||||
without needing to register a factory. The data it contains is pretty similar
|
||||
but is specific for filters (1sinkpad and 1 srcpad).
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
/* Name of the filter, each instance of should have that name */
|
||||
gchar *name;
|
||||
gchar *bindesc;
|
||||
GstRank rank;
|
||||
GstCaps *sink_caps;
|
||||
GstCaps *src_caps;
|
||||
} GstAutoConvertFilterInfo;
|
||||
|
||||
struct _GstBaseAutoConvertClass
|
||||
{
|
||||
GstBinClass parent_class;
|
||||
|
||||
GList* (*load_factories)(GstBaseAutoConvert *base_autoconvert);
|
||||
gboolean registers_filters;
|
||||
};
|
||||
|
||||
G_DEFINE_AUTOPTR_CLEANUP_FUNC(GstBaseAutoConvert, gst_object_unref)
|
||||
GType gst_base_auto_convert_get_type (void);
|
||||
|
||||
gboolean
|
||||
gst_base_auto_convert_register_filter(GstBaseAutoConvert *self, gchar *name,
|
||||
gchar * bindesc, GstRank rank);
|
||||
void gst_base_auto_convert_reset_filters (GstBaseAutoConvert * self);
|
||||
|
||||
G_END_DECLS
|
||||
|
|
|
@ -3,7 +3,7 @@ meta,
|
|||
"gltestsrc ! gldownload ! autovideoconvert name=convert ! capsfilter name=capsfilter caps=\"video/x-raw(memory:GLMemory)\" ! fakevideosink name=sink",
|
||||
},
|
||||
configs = {
|
||||
"$(validateflow), pad=convert:src, record-buffers=true, ignored-fields=\"stream-start={stream-id,group-id,stream},buffer={meta}\"",
|
||||
"$(validateflow), pad=\"^convert:src$\", record-buffers=true, ignored-fields=\"stream-start={stream-id,group-id,stream},buffer={meta}\"",
|
||||
}
|
||||
|
||||
crank-clock, repeat=2
|
||||
|
@ -15,8 +15,9 @@ foreach,
|
|||
"video/x-raw",
|
||||
>,
|
||||
actions = {
|
||||
[checkpoint, text="Setup capsfilter caps=$(caps)"],
|
||||
[set-properties, capsfilter::caps="$(caps)"],
|
||||
[crank-clock, repeat=2],
|
||||
[wait, on-clock=true],
|
||||
}
|
||||
stop
|
||||
stop
|
||||
|
|
|
@ -4,12 +4,21 @@ event segment: format=TIME, start=0:00:00.000000000, offset=0:00:00.000000000, s
|
|||
buffer: pts=0:00:00.000000000, dur=0:00:00.033333333, flags=discont
|
||||
buffer: pts=0:00:00.033333333, dur=0:00:00.033333333
|
||||
buffer: pts=0:00:00.066666666, dur=0:00:00.033333334
|
||||
event caps: video/x-raw, format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, texture-target=(string)2D, width=(int)320;
|
||||
|
||||
CHECKPOINT: Setup capsfilter caps=video/x-raw
|
||||
|
||||
event caps: video/x-raw, format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, width=(int)320;
|
||||
buffer: pts=0:00:00.100000000, dur=0:00:00.033333333
|
||||
buffer: pts=0:00:00.133333333, dur=0:00:00.033333333
|
||||
|
||||
CHECKPOINT: Setup capsfilter caps=video/x-raw(memory:GLMemory)
|
||||
|
||||
event caps: video/x-raw(memory:GLMemory), format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, texture-target=(string)2D, width=(int)320;
|
||||
buffer: pts=0:00:00.166666666, dur=0:00:00.033333334
|
||||
buffer: pts=0:00:00.200000000, dur=0:00:00.033333333
|
||||
event caps: video/x-raw, format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, texture-target=(string)2D, width=(int)320;
|
||||
|
||||
CHECKPOINT: Setup capsfilter caps=video/x-raw
|
||||
|
||||
event caps: video/x-raw, format=(string)RGBA, framerate=(fraction)30/1, height=(int)240, width=(int)320;
|
||||
buffer: pts=0:00:00.233333333, dur=0:00:00.033333333
|
||||
buffer: pts=0:00:00.266666666, dur=0:00:00.033333334
|
Loading…
Reference in a new issue