playbin: Refactor autoplug-query handling

We now only check sinks and factories of the corresponding media
type. It doesn't make sense to pass audio/subtitle caps to a video
decoder.
This commit is contained in:
Sebastian Dröge 2013-05-28 13:08:00 +02:00
parent d366613401
commit e5064ee723
2 changed files with 161 additions and 142 deletions

View file

@ -4251,40 +4251,27 @@ gst_decode_pad_query (GstPad * pad, GstObject * parent, GstQuery * query)
gboolean ret = FALSE; gboolean ret = FALSE;
CHAIN_MUTEX_LOCK (dpad->chain); CHAIN_MUTEX_LOCK (dpad->chain);
if (!dpad->exposed && !dpad->chain->deadend) { if (!dpad->exposed && !dpad->chain->deadend && dpad->chain->elements) {
GstDecodeElement *delem = GstDecodeElement *delem = dpad->chain->elements->data;
(dpad->chain->elements ? dpad->chain->elements->data : NULL);
if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION) {
g_print ("huh\n");
g_assert_not_reached ();
}
ret = FALSE; ret = FALSE;
GST_DEBUG_OBJECT (dpad->dbin, GST_DEBUG_OBJECT (dpad->dbin,
"calling autoplug-query for %s (element %s): %" GST_PTR_FORMAT, "calling autoplug-query for %s (element %s): %" GST_PTR_FORMAT,
GST_PAD_NAME (dpad), delem ? GST_ELEMENT_NAME (delem->element) : NULL, GST_PAD_NAME (dpad), GST_ELEMENT_NAME (delem->element), query);
query);
g_signal_emit (G_OBJECT (dpad->dbin), g_signal_emit (G_OBJECT (dpad->dbin),
gst_decode_bin_signals[SIGNAL_AUTOPLUG_QUERY], 0, dpad, delem->element, gst_decode_bin_signals[SIGNAL_AUTOPLUG_QUERY], 0, dpad, delem->element,
query, &ret); query, &ret);
GST_DEBUG_OBJECT (dpad->dbin, "autoplug-query returned %d", ret); if (ret)
if (ret) { GST_DEBUG_OBJECT (dpad->dbin,
GstCaps *result, *filter; "autoplug-query returned %d: %" GST_PTR_FORMAT, ret, query);
GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (dpad)); else
GST_DEBUG_OBJECT (dpad->dbin, "autoplug-query returned %d", ret);
gst_query_parse_caps (query, &filter);
gst_query_parse_caps_result (query, &result);
result =
gst_caps_merge (gst_caps_ref (result),
gst_pad_get_pad_template_caps (target));
if (filter) {
GstCaps *intersection =
gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);
gst_caps_unref (result);
result = intersection;
}
gst_query_set_caps_result (query, result);
gst_caps_unref (result);
gst_object_unref (target);
}
} }
CHAIN_MUTEX_UNLOCK (dpad->chain); CHAIN_MUTEX_UNLOCK (dpad->chain);

View file

@ -4086,140 +4086,163 @@ autoplug_query_caps (GstElement * uridecodebin, GstPad * pad,
GstCaps *filter, *result = NULL; GstCaps *filter, *result = NULL;
GstElement *sink; GstElement *sink;
GstPad *sinkpad = NULL; GstPad *sinkpad = NULL;
GValueArray *factories; GstElementFactory *factory;
gint i, n; GstElementFactoryListType factory_type;
gboolean have_audio_sink = FALSE, have_video_sink = FALSE; gboolean have_sink = FALSE;
gst_query_parse_caps (query, &filter);
GST_SOURCE_GROUP_LOCK (group); GST_SOURCE_GROUP_LOCK (group);
gst_query_parse_caps (query, &filter);
if ((sink = group->playbin->text_sink)) factory = gst_element_get_factory (element);
sinkpad = gst_element_get_static_pad (sink, "sink"); if (!factory)
if (sinkpad) { goto done;
GstCaps *sinkcaps;
/* Ignore errors here, if a custom sink fails to go if (gst_element_factory_list_is_type (factory,
* to READY things are wrong and will error out later GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
*/ GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)) {
if (GST_STATE (sink) < GST_STATE_READY) factory_type =
gst_element_set_state (sink, GST_STATE_READY); GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE;
sinkcaps = gst_pad_query_caps (sinkpad, filter); /* If this is from the subtitle uridecodebin we don't need to
if (!gst_caps_is_any (sinkcaps)) { * check the audio and video sink */
if (!result) if (group->suburidecodebin
result = sinkcaps; && gst_object_has_ancestor (GST_OBJECT_CAST (pad),
else GST_OBJECT_CAST (group->suburidecodebin))) {
result = gst_caps_merge (result, sinkcaps); goto done;
} else {
gst_caps_unref (sinkcaps);
} }
gst_object_unref (sinkpad);
} else {
GstCaps *subcaps = gst_subtitle_overlay_create_factory_caps ();
if (!result)
result = subcaps;
else
result = gst_caps_merge (result, subcaps);
}
/* If this is from the subtitle uridecodebin we don't need to if ((sink = group->video_sink)) {
* check the audio and video sink */ sinkpad = gst_element_get_static_pad (sink, "sink");
if (group->suburidecodebin if (sinkpad) {
&& gst_object_has_ancestor (GST_OBJECT_CAST (pad), GstCaps *sinkcaps;
GST_OBJECT_CAST (group->suburidecodebin))) {
/* Ignore errors here, if a custom sink fails to go
* to READY things are wrong and will error out later
*/
if (GST_STATE (sink) < GST_STATE_READY)
gst_element_set_state (sink, GST_STATE_READY);
sinkcaps = gst_pad_query_caps (sinkpad, filter);
if (!gst_caps_is_any (sinkcaps)) {
if (!result)
result = sinkcaps;
else
result = gst_caps_merge (result, sinkcaps);
} else {
gst_caps_unref (sinkcaps);
}
gst_object_unref (sinkpad);
}
have_sink = TRUE;
}
} else if (gst_element_factory_list_is_type (factory,
GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO)) {
factory_type = GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO;
/* If this is from the subtitle uridecodebin we don't need to
* check the audio and video sink */
if (group->suburidecodebin
&& gst_object_has_ancestor (GST_OBJECT_CAST (pad),
GST_OBJECT_CAST (group->suburidecodebin))) {
goto done;
}
if ((sink = group->audio_sink)) {
sinkpad = gst_element_get_static_pad (sink, "sink");
if (sinkpad) {
GstCaps *sinkcaps;
/* Ignore errors here, if a custom sink fails to go
* to READY things are wrong and will error out later
*/
if (GST_STATE (sink) < GST_STATE_READY)
gst_element_set_state (sink, GST_STATE_READY);
sinkcaps = gst_pad_query_caps (sinkpad, filter);
if (!gst_caps_is_any (sinkcaps)) {
if (!result)
result = sinkcaps;
else
result = gst_caps_merge (result, sinkcaps);
} else {
gst_caps_unref (sinkcaps);
}
gst_object_unref (sinkpad);
}
have_sink = TRUE;
}
} else if (gst_element_factory_list_is_type (factory,
GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE)) {
factory_type = GST_ELEMENT_FACTORY_TYPE_MEDIA_SUBTITLE;
if ((sink = group->playbin->text_sink)) {
sinkpad = gst_element_get_static_pad (sink, "sink");
if (sinkpad) {
GstCaps *sinkcaps;
/* Ignore errors here, if a custom sink fails to go
* to READY things are wrong and will error out later
*/
if (GST_STATE (sink) < GST_STATE_READY)
gst_element_set_state (sink, GST_STATE_READY);
sinkcaps = gst_pad_query_caps (sinkpad, filter);
if (!gst_caps_is_any (sinkcaps)) {
if (!result)
result = sinkcaps;
else
result = gst_caps_merge (result, sinkcaps);
} else {
gst_caps_unref (sinkcaps);
}
gst_object_unref (sinkpad);
}
have_sink = TRUE;
} else {
GstCaps *subcaps = gst_subtitle_overlay_create_factory_caps ();
if (!result)
result = subcaps;
else
result = gst_caps_merge (result, subcaps);
}
} else {
goto done; goto done;
} }
if ((sink = group->audio_sink)) { if (!have_sink) {
sinkpad = gst_element_get_static_pad (sink, "sink"); GValueArray *factories;
if (sinkpad) { gint i, n;
GstCaps *sinkcaps;
/* Ignore errors here, if a custom sink fails to go factories = autoplug_factories_cb (uridecodebin, pad, NULL, group);
* to READY things are wrong and will error out later n = factories->n_values;
*/ for (i = 0; i < n; i++) {
if (GST_STATE (sink) < GST_STATE_READY) GValue *v = g_value_array_get_nth (factories, i);
gst_element_set_state (sink, GST_STATE_READY); GstElementFactory *f = g_value_get_object (v);
const GList *templates;
const GList *l;
GstCaps *templ_caps;
sinkcaps = gst_pad_query_caps (sinkpad, filter); if (!gst_element_factory_list_is_type (f, factory_type))
if (!gst_caps_is_any (sinkcaps)) { continue;
if (!result)
result = sinkcaps;
else
result = gst_caps_merge (result, sinkcaps);
} else {
gst_caps_unref (sinkcaps);
}
gst_object_unref (sinkpad);
}
have_audio_sink = TRUE;
}
if ((sink = group->video_sink)) { templates = gst_element_factory_get_static_pad_templates (f);
sinkpad = gst_element_get_static_pad (sink, "sink");
if (sinkpad) {
GstCaps *sinkcaps;
/* Ignore errors here, if a custom sink fails to go for (l = templates; l; l = l->next) {
* to READY things are wrong and will error out later templ_caps = gst_static_pad_template_get_caps (l->data);
*/
if (GST_STATE (sink) < GST_STATE_READY)
gst_element_set_state (sink, GST_STATE_READY);
sinkcaps = gst_pad_query_caps (sinkpad, filter); if (!gst_caps_is_any (templ_caps)) {
if (!gst_caps_is_any (sinkcaps)) { if (!result)
if (!result) result = templ_caps;
result = sinkcaps; else
else result = gst_caps_merge (result, templ_caps);
result = gst_caps_merge (result, sinkcaps); } else {
} else { gst_caps_unref (templ_caps);
gst_caps_unref (sinkcaps); }
}
gst_object_unref (sinkpad);
}
have_video_sink = TRUE;
}
factories = autoplug_factories_cb (uridecodebin, pad, NULL, group);
n = factories->n_values;
for (i = 0; i < n; i++) {
GValue *v = g_value_array_get_nth (factories, i);
GstElementFactory *factory = g_value_get_object (v);
const GList *templates;
const GList *l;
GstCaps *templ_caps;
if (!gst_element_factory_list_is_type (factory,
GST_ELEMENT_FACTORY_TYPE_SINK))
continue;
if (have_audio_sink
&& gst_element_factory_list_is_type (factory,
GST_ELEMENT_FACTORY_TYPE_MEDIA_AUDIO))
continue;
if (have_video_sink
&& gst_element_factory_list_is_type (factory,
GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE))
continue;
templates = gst_element_factory_get_static_pad_templates (factory);
for (l = templates; l; l = l->next) {
templ_caps = gst_static_pad_template_get_caps (l->data);
if (!gst_caps_is_any (templ_caps)) {
if (!result)
result = templ_caps;
else
result = gst_caps_merge (result, templ_caps);
} else {
gst_caps_unref (templ_caps);
} }
} }
g_value_array_free (factories);
} }
g_value_array_free (factories);
done: done:
GST_SOURCE_GROUP_UNLOCK (group); GST_SOURCE_GROUP_UNLOCK (group);
@ -4227,6 +4250,15 @@ done:
if (!result) if (!result)
return FALSE; return FALSE;
if (0) {
GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (pad));
if (target) {
result = gst_caps_merge (result, gst_pad_get_pad_template_caps (target));
gst_object_unref (target);
}
}
if (filter) { if (filter) {
GstCaps *intersection = GstCaps *intersection =
gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST); gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);