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;
CHAIN_MUTEX_LOCK (dpad->chain);
if (!dpad->exposed && !dpad->chain->deadend) {
GstDecodeElement *delem =
(dpad->chain->elements ? dpad->chain->elements->data : NULL);
if (!dpad->exposed && !dpad->chain->deadend && dpad->chain->elements) {
GstDecodeElement *delem = dpad->chain->elements->data;
if (GST_QUERY_TYPE (query) == GST_QUERY_ALLOCATION) {
g_print ("huh\n");
g_assert_not_reached ();
}
ret = FALSE;
GST_DEBUG_OBJECT (dpad->dbin,
"calling autoplug-query for %s (element %s): %" GST_PTR_FORMAT,
GST_PAD_NAME (dpad), delem ? GST_ELEMENT_NAME (delem->element) : NULL,
query);
GST_PAD_NAME (dpad), GST_ELEMENT_NAME (delem->element), query);
g_signal_emit (G_OBJECT (dpad->dbin),
gst_decode_bin_signals[SIGNAL_AUTOPLUG_QUERY], 0, dpad, delem->element,
query, &ret);
GST_DEBUG_OBJECT (dpad->dbin, "autoplug-query returned %d", ret);
if (ret) {
GstCaps *result, *filter;
GstPad *target = gst_ghost_pad_get_target (GST_GHOST_PAD (dpad));
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);
}
if (ret)
GST_DEBUG_OBJECT (dpad->dbin,
"autoplug-query returned %d: %" GST_PTR_FORMAT, ret, query);
else
GST_DEBUG_OBJECT (dpad->dbin, "autoplug-query returned %d", ret);
}
CHAIN_MUTEX_UNLOCK (dpad->chain);

View file

@ -4086,140 +4086,163 @@ autoplug_query_caps (GstElement * uridecodebin, GstPad * pad,
GstCaps *filter, *result = NULL;
GstElement *sink;
GstPad *sinkpad = NULL;
GValueArray *factories;
gint i, n;
gboolean have_audio_sink = FALSE, have_video_sink = FALSE;
GstElementFactory *factory;
GstElementFactoryListType factory_type;
gboolean have_sink = FALSE;
gst_query_parse_caps (query, &filter);
GST_SOURCE_GROUP_LOCK (group);
gst_query_parse_caps (query, &filter);
if ((sink = group->playbin->text_sink))
sinkpad = gst_element_get_static_pad (sink, "sink");
if (sinkpad) {
GstCaps *sinkcaps;
factory = gst_element_get_factory (element);
if (!factory)
goto done;
/* 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);
if (gst_element_factory_list_is_type (factory,
GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE)) {
factory_type =
GST_ELEMENT_FACTORY_TYPE_MEDIA_VIDEO |
GST_ELEMENT_FACTORY_TYPE_MEDIA_IMAGE;
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);
/* 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;
}
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
* check the audio and video sink */
if (group->suburidecodebin
&& gst_object_has_ancestor (GST_OBJECT_CAST (pad),
GST_OBJECT_CAST (group->suburidecodebin))) {
if ((sink = group->video_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_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;
}
if ((sink = group->audio_sink)) {
sinkpad = gst_element_get_static_pad (sink, "sink");
if (sinkpad) {
GstCaps *sinkcaps;
if (!have_sink) {
GValueArray *factories;
gint i, n;
/* 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);
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 *f = g_value_get_object (v);
const GList *templates;
const GList *l;
GstCaps *templ_caps;
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_audio_sink = TRUE;
}
if (!gst_element_factory_list_is_type (f, factory_type))
continue;
if ((sink = group->video_sink)) {
sinkpad = gst_element_get_static_pad (sink, "sink");
if (sinkpad) {
GstCaps *sinkcaps;
templates = gst_element_factory_get_static_pad_templates (f);
/* 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);
for (l = templates; l; l = l->next) {
templ_caps = gst_static_pad_template_get_caps (l->data);
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_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);
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:
GST_SOURCE_GROUP_UNLOCK (group);
@ -4227,6 +4250,15 @@ done:
if (!result)
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) {
GstCaps *intersection =
gst_caps_intersect_full (filter, result, GST_CAPS_INTERSECT_FIRST);