mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-11-27 20:21:24 +00:00
glbasemixer: actually attempt to propose an allocation upstream
We were always failing the allocation query as a flag was never being set to signal a successful negotiation. Fix by setting the required flag on a successful caps event from upstream.
This commit is contained in:
parent
dfa6fb3c86
commit
90da62bc25
2 changed files with 151 additions and 100 deletions
|
@ -122,6 +122,131 @@ _default_propose_allocation (GstGLBaseMixer * mix, GstGLBaseMixerPad * pad,
|
||||||
return TRUE;
|
return TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
gst_gl_base_mixer_sink_event (GstAggregator * agg, GstAggregatorPad * bpad,
|
||||||
|
GstEvent * event)
|
||||||
|
{
|
||||||
|
GstGLBaseMixerPad *pad = GST_GL_BASE_MIXER_PAD (bpad);
|
||||||
|
|
||||||
|
switch (GST_EVENT_TYPE (event)) {
|
||||||
|
case GST_EVENT_CAPS:
|
||||||
|
if (!GST_AGGREGATOR_CLASS (parent_class)->sink_event (agg, bpad, event))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
pad->negotiated = TRUE;
|
||||||
|
return TRUE;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return GST_AGGREGATOR_CLASS (parent_class)->sink_event (agg, bpad, event);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_find_local_gl_context (GstGLBaseMixer * mix)
|
||||||
|
{
|
||||||
|
GstQuery *query;
|
||||||
|
GstContext *context;
|
||||||
|
const GstStructure *s;
|
||||||
|
|
||||||
|
if (mix->context)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
query = gst_query_new_context ("gst.gl.local_context");
|
||||||
|
if (!mix->context && gst_gl_run_query (GST_ELEMENT (mix), query, GST_PAD_SRC)) {
|
||||||
|
gst_query_parse_context (query, &context);
|
||||||
|
if (context) {
|
||||||
|
s = gst_context_get_structure (context);
|
||||||
|
gst_structure_get (s, "context", GST_GL_TYPE_CONTEXT, &mix->context,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (!mix->context
|
||||||
|
&& gst_gl_run_query (GST_ELEMENT (mix), query, GST_PAD_SINK)) {
|
||||||
|
gst_query_parse_context (query, &context);
|
||||||
|
if (context) {
|
||||||
|
s = gst_context_get_structure (context);
|
||||||
|
gst_structure_get (s, "context", GST_GL_TYPE_CONTEXT, &mix->context,
|
||||||
|
NULL);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
GST_DEBUG_OBJECT (mix, "found local context %p", mix->context);
|
||||||
|
|
||||||
|
gst_query_unref (query);
|
||||||
|
|
||||||
|
if (mix->context)
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_get_gl_context (GstGLBaseMixer * mix)
|
||||||
|
{
|
||||||
|
GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
|
||||||
|
GError *error = NULL;
|
||||||
|
|
||||||
|
if (!gst_gl_ensure_element_data (mix, &mix->display,
|
||||||
|
&mix->priv->other_context))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);
|
||||||
|
|
||||||
|
_find_local_gl_context (mix);
|
||||||
|
|
||||||
|
if (!mix->context) {
|
||||||
|
GST_OBJECT_LOCK (mix->display);
|
||||||
|
do {
|
||||||
|
if (mix->context) {
|
||||||
|
gst_object_unref (mix->context);
|
||||||
|
mix->context = NULL;
|
||||||
|
}
|
||||||
|
/* just get a GL context. we don't care */
|
||||||
|
mix->context =
|
||||||
|
gst_gl_display_get_gl_context_for_thread (mix->display, NULL);
|
||||||
|
if (!mix->context) {
|
||||||
|
if (!gst_gl_display_create_context (mix->display,
|
||||||
|
mix->priv->other_context, &mix->context, &error)) {
|
||||||
|
GST_OBJECT_UNLOCK (mix->display);
|
||||||
|
goto context_error;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (!gst_gl_display_add_context (mix->display, mix->context));
|
||||||
|
GST_OBJECT_UNLOCK (mix->display);
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
GstGLAPI current_gl_api = gst_gl_context_get_gl_api (mix->context);
|
||||||
|
if ((current_gl_api & mix_class->supported_gl_api) == 0)
|
||||||
|
goto unsupported_gl_api;
|
||||||
|
}
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
unsupported_gl_api:
|
||||||
|
{
|
||||||
|
GstGLAPI gl_api = gst_gl_context_get_gl_api (mix->context);
|
||||||
|
gchar *gl_api_str = gst_gl_api_to_string (gl_api);
|
||||||
|
gchar *supported_gl_api_str =
|
||||||
|
gst_gl_api_to_string (mix_class->supported_gl_api);
|
||||||
|
GST_ELEMENT_ERROR (mix, RESOURCE, BUSY,
|
||||||
|
("GL API's not compatible context: %s supported: %s", gl_api_str,
|
||||||
|
supported_gl_api_str), (NULL));
|
||||||
|
|
||||||
|
g_free (supported_gl_api_str);
|
||||||
|
g_free (gl_api_str);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
context_error:
|
||||||
|
{
|
||||||
|
GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message),
|
||||||
|
(NULL));
|
||||||
|
g_clear_error (&error);
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_base_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
|
gst_gl_base_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
|
||||||
GstQuery * query)
|
GstQuery * query)
|
||||||
|
@ -139,16 +264,20 @@ gst_gl_base_mixer_sink_query (GstAggregator * agg, GstAggregatorPad * bpad,
|
||||||
GstQuery *decide_query = NULL;
|
GstQuery *decide_query = NULL;
|
||||||
|
|
||||||
GST_OBJECT_LOCK (mix);
|
GST_OBJECT_LOCK (mix);
|
||||||
if (G_UNLIKELY (!mix->priv->negotiated)) {
|
if (G_UNLIKELY (!pad->negotiated)) {
|
||||||
GST_DEBUG_OBJECT (mix,
|
GST_DEBUG_OBJECT (mix,
|
||||||
"not negotiated yet, can't answer ALLOCATION query");
|
"not negotiated yet, can't answer ALLOCATION query");
|
||||||
GST_OBJECT_UNLOCK (mix);
|
GST_OBJECT_UNLOCK (mix);
|
||||||
return FALSE;
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((decide_query = mix->priv->query))
|
if ((decide_query = mix->priv->query))
|
||||||
gst_query_ref (decide_query);
|
gst_query_ref (decide_query);
|
||||||
GST_OBJECT_UNLOCK (mix);
|
GST_OBJECT_UNLOCK (mix);
|
||||||
|
|
||||||
|
if (!_get_gl_context (mix))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mix,
|
GST_DEBUG_OBJECT (mix,
|
||||||
"calling propose allocation with query %" GST_PTR_FORMAT,
|
"calling propose allocation with query %" GST_PTR_FORMAT,
|
||||||
decide_query);
|
decide_query);
|
||||||
|
@ -273,6 +402,7 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
|
||||||
|
|
||||||
agg_class->sinkpads_type = GST_TYPE_GL_BASE_MIXER_PAD;
|
agg_class->sinkpads_type = GST_TYPE_GL_BASE_MIXER_PAD;
|
||||||
agg_class->sink_query = gst_gl_base_mixer_sink_query;
|
agg_class->sink_query = gst_gl_base_mixer_sink_query;
|
||||||
|
agg_class->sink_event = gst_gl_base_mixer_sink_event;
|
||||||
agg_class->src_query = gst_gl_base_mixer_src_query;
|
agg_class->src_query = gst_gl_base_mixer_src_query;
|
||||||
agg_class->src_activate = gst_gl_base_mixer_src_activate_mode;
|
agg_class->src_activate = gst_gl_base_mixer_src_activate_mode;
|
||||||
agg_class->stop = gst_gl_base_mixer_stop;
|
agg_class->stop = gst_gl_base_mixer_stop;
|
||||||
|
@ -294,11 +424,24 @@ gst_gl_base_mixer_class_init (GstGLBaseMixerClass * klass)
|
||||||
klass->supported_gl_api = GST_GL_API_ANY;
|
klass->supported_gl_api = GST_GL_API_ANY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gboolean
|
||||||
|
_reset_pad (GstAggregator * self, GstAggregatorPad * base_pad,
|
||||||
|
gpointer user_data)
|
||||||
|
{
|
||||||
|
GstGLBaseMixerPad *mix_pad = GST_GL_BASE_MIXER_PAD (base_pad);
|
||||||
|
|
||||||
|
mix_pad->negotiated = FALSE;
|
||||||
|
|
||||||
|
return TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
gst_gl_base_mixer_reset (GstGLBaseMixer * mix)
|
gst_gl_base_mixer_reset (GstGLBaseMixer * mix)
|
||||||
{
|
{
|
||||||
/* clean up collect data */
|
/* clean up collect data */
|
||||||
mix->priv->negotiated = FALSE;
|
|
||||||
|
gst_aggregator_iterate_sinkpads (GST_AGGREGATOR (mix),
|
||||||
|
(GstAggregatorPadForeachFunc) _reset_pad, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
|
@ -414,113 +557,19 @@ gst_gl_base_mixer_src_query (GstAggregator * agg, GstQuery * query)
|
||||||
return GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query);
|
return GST_AGGREGATOR_CLASS (parent_class)->src_query (agg, query);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
|
||||||
_find_local_gl_context (GstGLBaseMixer * mix)
|
|
||||||
{
|
|
||||||
GstQuery *query;
|
|
||||||
GstContext *context;
|
|
||||||
const GstStructure *s;
|
|
||||||
|
|
||||||
if (mix->context)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
query = gst_query_new_context ("gst.gl.local_context");
|
|
||||||
if (!mix->context && gst_gl_run_query (GST_ELEMENT (mix), query, GST_PAD_SRC)) {
|
|
||||||
gst_query_parse_context (query, &context);
|
|
||||||
if (context) {
|
|
||||||
s = gst_context_get_structure (context);
|
|
||||||
gst_structure_get (s, "context", GST_GL_TYPE_CONTEXT, &mix->context,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (!mix->context
|
|
||||||
&& gst_gl_run_query (GST_ELEMENT (mix), query, GST_PAD_SINK)) {
|
|
||||||
gst_query_parse_context (query, &context);
|
|
||||||
if (context) {
|
|
||||||
s = gst_context_get_structure (context);
|
|
||||||
gst_structure_get (s, "context", GST_GL_TYPE_CONTEXT, &mix->context,
|
|
||||||
NULL);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
GST_DEBUG_OBJECT (mix, "found local context %p", mix->context);
|
|
||||||
|
|
||||||
gst_query_unref (query);
|
|
||||||
|
|
||||||
if (mix->context)
|
|
||||||
return TRUE;
|
|
||||||
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
gst_gl_base_mixer_decide_allocation (GstGLBaseMixer * mix, GstQuery * query)
|
gst_gl_base_mixer_decide_allocation (GstGLBaseMixer * mix, GstQuery * query)
|
||||||
{
|
{
|
||||||
GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
|
GstGLBaseMixerClass *mix_class = GST_GL_BASE_MIXER_GET_CLASS (mix);
|
||||||
GError *error = NULL;
|
|
||||||
gboolean ret = TRUE;
|
|
||||||
|
|
||||||
if (!gst_gl_ensure_element_data (mix, &mix->display,
|
if (!_get_gl_context (mix))
|
||||||
&mix->priv->other_context))
|
|
||||||
return FALSE;
|
return FALSE;
|
||||||
|
|
||||||
gst_gl_display_filter_gl_api (mix->display, mix_class->supported_gl_api);
|
|
||||||
|
|
||||||
_find_local_gl_context (mix);
|
|
||||||
|
|
||||||
if (!mix->context) {
|
|
||||||
GST_OBJECT_LOCK (mix->display);
|
|
||||||
do {
|
|
||||||
if (mix->context) {
|
|
||||||
gst_object_unref (mix->context);
|
|
||||||
mix->context = NULL;
|
|
||||||
}
|
|
||||||
/* just get a GL context. we don't care */
|
|
||||||
mix->context =
|
|
||||||
gst_gl_display_get_gl_context_for_thread (mix->display, NULL);
|
|
||||||
if (!mix->context) {
|
|
||||||
if (!gst_gl_display_create_context (mix->display,
|
|
||||||
mix->priv->other_context, &mix->context, &error)) {
|
|
||||||
GST_OBJECT_UNLOCK (mix->display);
|
|
||||||
goto context_error;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (!gst_gl_display_add_context (mix->display, mix->context));
|
|
||||||
GST_OBJECT_UNLOCK (mix->display);
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
GstGLAPI current_gl_api = gst_gl_context_get_gl_api (mix->context);
|
|
||||||
if ((current_gl_api & mix_class->supported_gl_api) == 0)
|
|
||||||
goto unsupported_gl_api;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mix_class->decide_allocation)
|
if (mix_class->decide_allocation)
|
||||||
ret = mix_class->decide_allocation (mix, query);
|
if (!mix_class->decide_allocation (mix, query))
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
return ret;
|
return TRUE;
|
||||||
|
|
||||||
unsupported_gl_api:
|
|
||||||
{
|
|
||||||
GstGLAPI gl_api = gst_gl_context_get_gl_api (mix->context);
|
|
||||||
gchar *gl_api_str = gst_gl_api_to_string (gl_api);
|
|
||||||
gchar *supported_gl_api_str =
|
|
||||||
gst_gl_api_to_string (mix_class->supported_gl_api);
|
|
||||||
GST_ELEMENT_ERROR (mix, RESOURCE, BUSY,
|
|
||||||
("GL API's not compatible context: %s supported: %s", gl_api_str,
|
|
||||||
supported_gl_api_str), (NULL));
|
|
||||||
|
|
||||||
g_free (supported_gl_api_str);
|
|
||||||
g_free (gl_api_str);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
context_error:
|
|
||||||
{
|
|
||||||
GST_ELEMENT_ERROR (mix, RESOURCE, NOT_FOUND, ("%s", error->message),
|
|
||||||
(NULL));
|
|
||||||
g_clear_error (&error);
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/* takes ownership of the pool, allocator and query */
|
/* takes ownership of the pool, allocator and query */
|
||||||
|
|
|
@ -47,6 +47,8 @@ typedef struct _GstGLBaseMixerPadClass GstGLBaseMixerPadClass;
|
||||||
struct _GstGLBaseMixerPad
|
struct _GstGLBaseMixerPad
|
||||||
{
|
{
|
||||||
GstVideoAggregatorPad parent; /* subclass the pad */
|
GstVideoAggregatorPad parent; /* subclass the pad */
|
||||||
|
|
||||||
|
gboolean negotiated;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct _GstGLBaseMixerPadClass
|
struct _GstGLBaseMixerPadClass
|
||||||
|
|
Loading…
Reference in a new issue