summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorGuillaume Desmottes <guillaume.desmottes@collabora.co.uk>2017-11-20 17:54:54 +0100
committerSebastian Dröge <sebastian@centricular.com>2017-11-22 17:38:04 +0200
commitd5067b42dedeffab121b9a0359966404b09a7378 (patch)
tree729b787f1d0a0b9aa91b20e5b60477741b4360b3
parent0933b8b45a5888ad9454be25b3e96a8851e67aea (diff)
h264parse: put downstream caps first if possible on sink caps
Try prioritizing downstream's caps over upstream's if possible so the parser can configured in "passthrough" if possible and save it from doing useless conversions. https://bugzilla.gnome.org/show_bug.cgi?id=790628
-rw-r--r--gst/videoparsers/gsth264parse.c35
-rw-r--r--tests/check/elements/h264parse.c54
2 files changed, 75 insertions, 14 deletions
diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c
index 10543eafc..eb5197e75 100644
--- a/gst/videoparsers/gsth264parse.c
+++ b/gst/videoparsers/gsth264parse.c
@@ -2752,7 +2752,7 @@ refuse_caps:
}
static void
-remove_fields (GstCaps * caps)
+remove_fields (GstCaps * caps, gboolean all)
{
guint i, n;
@@ -2760,8 +2760,10 @@ remove_fields (GstCaps * caps)
for (i = 0; i < n; i++) {
GstStructure *s = gst_caps_get_structure (caps, i);
- gst_structure_remove_field (s, "alignment");
- gst_structure_remove_field (s, "stream-format");
+ if (all) {
+ gst_structure_remove_field (s, "alignment");
+ gst_structure_remove_field (s, "stream-format");
+ }
gst_structure_remove_field (s, "parsed");
}
}
@@ -2770,28 +2772,24 @@ static GstCaps *
gst_h264_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
{
GstCaps *peercaps, *templ;
- GstCaps *res;
+ GstCaps *res, *tmp, *pcopy;
templ = gst_pad_get_pad_template_caps (GST_BASE_PARSE_SINK_PAD (parse));
if (filter) {
GstCaps *fcopy = gst_caps_copy (filter);
/* Remove the fields we convert */
- remove_fields (fcopy);
+ remove_fields (fcopy, TRUE);
peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), fcopy);
gst_caps_unref (fcopy);
} else
peercaps = gst_pad_peer_query_caps (GST_BASE_PARSE_SRC_PAD (parse), NULL);
- if (peercaps) {
- peercaps = gst_caps_make_writable (peercaps);
- remove_fields (peercaps);
+ pcopy = gst_caps_copy (peercaps);
+ remove_fields (pcopy, TRUE);
- res = gst_caps_intersect_full (peercaps, templ, GST_CAPS_INTERSECT_FIRST);
- gst_caps_unref (peercaps);
- gst_caps_unref (templ);
- } else {
- res = templ;
- }
+ res = gst_caps_intersect_full (pcopy, templ, GST_CAPS_INTERSECT_FIRST);
+ gst_caps_unref (pcopy);
+ gst_caps_unref (templ);
if (filter) {
GstCaps *tmp = gst_caps_intersect_full (res, filter,
@@ -2800,6 +2798,15 @@ gst_h264_parse_get_caps (GstBaseParse * parse, GstCaps * filter)
res = tmp;
}
+ /* Try if we can put the downstream caps first */
+ remove_fields (peercaps, FALSE);
+ tmp = gst_caps_intersect_full (peercaps, res, GST_CAPS_INTERSECT_FIRST);
+ if (!gst_caps_is_empty (tmp))
+ res = gst_caps_merge (tmp, res);
+ else
+ gst_caps_unref (tmp);
+
+ gst_caps_unref (peercaps);
return res;
}
diff --git a/tests/check/elements/h264parse.c b/tests/check/elements/h264parse.c
index 65fbc90e1..5a6d3e472 100644
--- a/tests/check/elements/h264parse.c
+++ b/tests/check/elements/h264parse.c
@@ -344,6 +344,59 @@ GST_START_TEST (test_parse_detect_stream)
GST_END_TEST;
+static GstStaticPadTemplate srctemplate_avc_au_and_bs_au =
+ GST_STATIC_PAD_TEMPLATE ("src",
+ GST_PAD_SRC,
+ GST_PAD_ALWAYS,
+ GST_STATIC_CAPS (SRC_CAPS_TMPL
+ ", stream-format = (string) avc, alignment = (string) au; "
+ SRC_CAPS_TMPL
+ ", stream-format = (string) byte-stream, alignment = (string) au")
+ );
+
+GST_START_TEST (test_sink_caps_reordering)
+{
+ /* Upstream can handle avc and byte-stream format (in that preference order)
+ * and downstream requires byte-stream.
+ * Parser reorder upstream's caps to prefer the format requested downstream
+ * and so avoid doing useless conversions. */
+ GstElement *parser;
+ GstPad *sink, *src;
+ GstCaps *src_caps, *sink_caps;
+ GstStructure *s;
+
+ parser = gst_check_setup_element ("h264parse");
+ fail_unless (parser);
+
+ src = gst_check_setup_src_pad (parser, &srctemplate_avc_au_and_bs_au);
+ sink = gst_check_setup_sink_pad (parser, &sinktemplate_bs_au);
+
+ src_caps = gst_pad_get_pad_template_caps (src);
+ sink_caps = gst_pad_peer_query_caps (src, src_caps);
+
+ /* Sink pad has both format on its sink caps but prefer to use byte-stream */
+ g_assert_cmpuint (gst_caps_get_size (sink_caps), ==, 2);
+
+ s = gst_caps_get_structure (sink_caps, 0);
+ g_assert_cmpstr (gst_structure_get_name (s), ==, "video/x-h264");
+ g_assert_cmpstr (gst_structure_get_string (s, "alignment"), ==, "au");
+ g_assert_cmpstr (gst_structure_get_string (s, "stream-format"), ==,
+ "byte-stream");
+
+ s = gst_caps_get_structure (sink_caps, 1);
+ g_assert_cmpstr (gst_structure_get_name (s), ==, "video/x-h264");
+ g_assert_cmpstr (gst_structure_get_string (s, "alignment"), ==, "au");
+ g_assert_cmpstr (gst_structure_get_string (s, "stream-format"), ==, "avc");
+
+ gst_caps_unref (src_caps);
+ gst_caps_unref (sink_caps);
+ gst_object_unref (src);
+ gst_object_unref (sink);
+ gst_object_unref (parser);
+}
+
+GST_END_TEST;
+
static Suite *
h264parse_suite (void)
@@ -358,6 +411,7 @@ h264parse_suite (void)
tcase_add_test (tc_chain, test_parse_split);
tcase_add_test (tc_chain, test_parse_skip_garbage);
tcase_add_test (tc_chain, test_parse_detect_stream);
+ tcase_add_test (tc_chain, test_sink_caps_reordering);
return s;
}