discoverer: Get caps from the element's srcpad if possible

The caps put into the stream topology by decodebin are the caps at the
moment the pads are exposed on it. This is usually before decoders
received any buffers.
In discoverer we however wait for pre-roll, which ensures that each
decoder handled buffers already. At this point, there might be more
information known about the caps already that we could make use of.

One example here is extra information stored in the SEI of H264, like
the multiview-mode. This will be known if there is a SEI before the
first keyframe, but decodebin won't put this into the topology as it
only waits for the initial caps of h264parse (which come directly after
SPS/PPS).

With this change, the multiview-mode is in the caps reported by
discoverer in many cases.
This commit is contained in:
Sebastian Dröge 2016-12-17 21:58:29 +02:00
parent ce693174f4
commit 15123c0455

View file

@ -57,6 +57,7 @@ GST_DEBUG_CATEGORY_STATIC (discoverer_debug);
static GQuark _CAPS_QUARK; static GQuark _CAPS_QUARK;
static GQuark _TAGS_QUARK; static GQuark _TAGS_QUARK;
static GQuark _ELEMENT_SRCPAD_QUARK;
static GQuark _TOC_QUARK; static GQuark _TOC_QUARK;
static GQuark _STREAM_ID_QUARK; static GQuark _STREAM_ID_QUARK;
static GQuark _MISSING_PLUGIN_QUARK; static GQuark _MISSING_PLUGIN_QUARK;
@ -139,6 +140,7 @@ _do_init (void)
GST_DEBUG_CATEGORY_INIT (discoverer_debug, "discoverer", 0, "Discoverer"); GST_DEBUG_CATEGORY_INIT (discoverer_debug, "discoverer", 0, "Discoverer");
_CAPS_QUARK = g_quark_from_static_string ("caps"); _CAPS_QUARK = g_quark_from_static_string ("caps");
_ELEMENT_SRCPAD_QUARK = g_quark_from_static_string ("element-srcpad");
_TAGS_QUARK = g_quark_from_static_string ("tags"); _TAGS_QUARK = g_quark_from_static_string ("tags");
_TOC_QUARK = g_quark_from_static_string ("toc"); _TOC_QUARK = g_quark_from_static_string ("toc");
_STREAM_ID_QUARK = g_quark_from_static_string ("stream-id"); _STREAM_ID_QUARK = g_quark_from_static_string ("stream-id");
@ -804,19 +806,28 @@ static GstDiscovererStreamInfo *
collect_information (GstDiscoverer * dc, const GstStructure * st, collect_information (GstDiscoverer * dc, const GstStructure * st,
GstDiscovererStreamInfo * parent) GstDiscovererStreamInfo * parent)
{ {
GstCaps *caps; GstPad *srcpad;
GstCaps *caps = NULL;
GstStructure *caps_st; GstStructure *caps_st;
GstTagList *tags_st; GstTagList *tags_st;
const gchar *name; const gchar *name;
gint tmp, tmp2; gint tmp, tmp2;
guint utmp; guint utmp;
if (!st || !gst_structure_id_has_field (st, _CAPS_QUARK)) { if (!st || (!gst_structure_id_has_field (st, _CAPS_QUARK)
&& !gst_structure_id_has_field (st, _ELEMENT_SRCPAD_QUARK))) {
GST_WARNING ("Couldn't find caps !"); GST_WARNING ("Couldn't find caps !");
return make_info (parent, GST_TYPE_DISCOVERER_STREAM_INFO, NULL); return make_info (parent, GST_TYPE_DISCOVERER_STREAM_INFO, NULL);
} }
gst_structure_id_get (st, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL); if (gst_structure_id_get (st, _ELEMENT_SRCPAD_QUARK, GST_TYPE_PAD, &srcpad,
NULL)) {
caps = gst_pad_get_current_caps (srcpad);
gst_object_unref (srcpad);
}
if (!caps) {
gst_structure_id_get (st, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL);
}
if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) { if (!caps || gst_caps_is_empty (caps) || gst_caps_is_any (caps)) {
GST_WARNING ("Couldn't find caps !"); GST_WARNING ("Couldn't find caps !");
@ -1130,6 +1141,8 @@ parse_stream_topology (GstDiscoverer * dc, const GstStructure * topology,
/* FIXME : aggregate with information from main streams */ /* FIXME : aggregate with information from main streams */
GST_DEBUG ("Coudn't find 'next' ! might be the last entry"); GST_DEBUG ("Coudn't find 'next' ! might be the last entry");
} else { } else {
GstPad *srcpad;
st = (GstStructure *) gst_value_get_structure (nval); st = (GstStructure *) gst_value_get_structure (nval);
GST_DEBUG ("next is a structure %" GST_PTR_FORMAT, st); GST_DEBUG ("next is a structure %" GST_PTR_FORMAT, st);
@ -1137,7 +1150,16 @@ parse_stream_topology (GstDiscoverer * dc, const GstStructure * topology,
if (!parent) if (!parent)
parent = res; parent = res;
if (gst_structure_id_get (st, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL)) { if (gst_structure_id_get (st, _ELEMENT_SRCPAD_QUARK, GST_TYPE_PAD,
&srcpad, NULL)) {
caps = gst_pad_get_current_caps (srcpad);
gst_object_unref (srcpad);
}
if (!caps) {
gst_structure_id_get (st, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL);
}
if (caps) {
if (child_is_same_stream (parent->caps, caps)) { if (child_is_same_stream (parent->caps, caps)) {
/* We sometimes get an extra sub-stream from the parser. If this is /* We sometimes get an extra sub-stream from the parser. If this is
* the case, we just replace the parent caps with this stream's caps * the case, we just replace the parent caps with this stream's caps
@ -1156,8 +1178,7 @@ parse_stream_topology (GstDiscoverer * dc, const GstStructure * topology,
res->next = next; res->next = next;
next->previous = res; next->previous = res;
} }
if (caps) gst_caps_unref (caps);
gst_caps_unref (caps);
} }
} }
@ -1172,9 +1193,18 @@ parse_stream_topology (GstDiscoverer * dc, const GstStructure * topology,
guint i, len; guint i, len;
GstDiscovererContainerInfo *cont; GstDiscovererContainerInfo *cont;
GstTagList *tags; GstTagList *tags;
GstPad *srcpad;
if (!gst_structure_id_get (topology, _CAPS_QUARK, if (gst_structure_id_get (topology, _ELEMENT_SRCPAD_QUARK, GST_TYPE_PAD,
GST_TYPE_CAPS, &caps, NULL)) &srcpad, NULL)) {
caps = gst_pad_get_current_caps (srcpad);
gst_object_unref (srcpad);
}
if (!caps) {
gst_structure_id_get (topology, _CAPS_QUARK, GST_TYPE_CAPS, &caps, NULL);
}
if (!caps)
GST_WARNING ("Couldn't find caps !"); GST_WARNING ("Couldn't find caps !");
len = gst_value_list_get_size (nval); len = gst_value_list_get_size (nval);