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:
Matthew Waters 2016-05-14 15:50:57 +03:00
parent dfa6fb3c86
commit 90da62bc25
2 changed files with 151 additions and 100 deletions

View file

@ -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 */

View file

@ -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