From e76c4817503b563ecf0731b2c33427cbbdb9c47f Mon Sep 17 00:00:00 2001 From: Seungha Yang Date: Wed, 22 Feb 2023 00:47:09 +0900 Subject: [PATCH] h265parse: Always set profile on src caps h265parse should provide profile for autoplugging Part-of: --- .../gst/videoparsers/gsth265parse.c | 54 ++++++++++++++++++ .../tests/check/elements/h265parse.c | 65 ++++++++++++++++++++++ 2 files changed, 119 insertions(+) diff --git a/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c b/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c index 356385c..ec81c54 100644 --- a/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c +++ b/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c @@ -2368,6 +2368,60 @@ gst_h265_parse_update_src_caps (GstH265Parse * h265parse, GstCaps * caps) GstH265Profile p; p = gst_h265_get_profile_from_sps (sps); + /* gst_h265_get_profile_from_sps() method will determine profile + * as defined in spec, with allowing slightly broken profile-tier-level + * bits, then it might not be able to cover all cases. + * If it's still unknown, do guess again */ + if (p == GST_H265_PROFILE_INVALID) { + GST_WARNING_OBJECT (h265parse, "Unknown profile, guessing"); + switch (sps->chroma_format_idc) { + case 0: + if (sps->bit_depth_luma_minus8 == 0) { + p = GST_H265_PROFILE_MONOCHROME; + } else if (sps->bit_depth_luma_minus8 <= 2) { + p = GST_H265_PROFILE_MONOCHROME_10; + } else if (sps->bit_depth_luma_minus8 <= 4) { + p = GST_H265_PROFILE_MONOCHROME_12; + } else { + p = GST_H265_PROFILE_MONOCHROME_16; + } + break; + case 1: + if (sps->bit_depth_luma_minus8 == 0) { + p = GST_H265_PROFILE_MAIN; + } else if (sps->bit_depth_luma_minus8 <= 2) { + p = GST_H265_PROFILE_MAIN_10; + } else if (sps->bit_depth_luma_minus8 <= 4) { + p = GST_H265_PROFILE_MAIN_12; + } else { + p = GST_H265_PROFILE_MAIN_444_16_INTRA; + } + break; + case 2: + if (sps->bit_depth_luma_minus8 <= 2) { + p = GST_H265_PROFILE_MAIN_422_10; + } else if (sps->bit_depth_luma_minus8 <= 4) { + p = GST_H265_PROFILE_MAIN_422_12; + } else { + p = GST_H265_PROFILE_MAIN_444_16_INTRA; + } + break; + case 3: + if (sps->bit_depth_luma_minus8 == 0) { + p = GST_H265_PROFILE_MAIN_444; + } else if (sps->bit_depth_luma_minus8 <= 2) { + p = GST_H265_PROFILE_MAIN_444_10; + } else if (sps->bit_depth_luma_minus8 <= 4) { + p = GST_H265_PROFILE_MAIN_444_12; + } else { + p = GST_H265_PROFILE_MAIN_444_16_INTRA; + } + break; + default: + break; + } + } + profile = gst_h265_profile_to_string (p); if (s && gst_structure_has_field (s, "profile")) { diff --git a/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c b/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c index 6609544..a2c4f3d 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c @@ -332,6 +332,70 @@ GST_START_TEST (test_parse_detect_stream_with_hdr_sei) GST_END_TEST; +/* 8bits 4:4:4 encoded stream, and profile-level-tier is not spec compliant. + * extracted from the file reported at + * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/1009 + */ +static const guint8 broken_profile_codec_data[] = { + 0x01, 0x24, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x99, 0xf0, 0x00, 0xfc, 0xff, 0xf8, 0xf8, 0x00, 0x00, 0x0f, 0x03, 0x20, + 0x00, 0x01, 0x00, 0x18, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x24, 0x08, + 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x99, 0xac, 0x09, 0x21, 0x00, 0x01, 0x00, 0x2c, 0x42, 0x01, 0x01, + 0x24, 0x08, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x00, 0x03, 0x00, 0x99, 0x90, 0x00, 0x3c, 0x04, 0x00, 0x44, 0x0f, 0x84, + 0x72, 0xd6, 0x94, 0x84, 0xb2, 0x5c, 0x40, 0x20, 0x00, 0x00, 0x03, 0x00, + 0x20, 0x00, 0x00, 0x07, 0x81, 0x22, 0x00, 0x01, 0x00, 0x08, 0x44, 0x01, + 0xc0, 0xf7, 0x18, 0x30, 0x0c, 0xc9 +}; + +GST_START_TEST (test_parse_fallback_profile) +{ + GstHarness *h = gst_harness_new ("h265parse"); + GstCaps *caps; + GstBuffer *codec_data; + GstEvent *event; + + codec_data = gst_buffer_new_memdup (broken_profile_codec_data, + sizeof (broken_profile_codec_data)); + + caps = gst_caps_from_string ("video/x-h265, stream-format=(string)hvc1, " + "alignment=(string)au"); + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL); + gst_buffer_unref (codec_data); + + gst_harness_set_src_caps (h, caps); + while ((event = gst_harness_pull_event (h)) != NULL) { + GstStructure *s; + const gchar *profile; + + if (GST_EVENT_TYPE (event) != GST_EVENT_CAPS) { + gst_event_unref (event); + continue; + } + + gst_event_parse_caps (event, &caps); + s = gst_caps_get_structure (caps, 0); + profile = gst_structure_get_string (s, "profile"); + + /* h265parse must provide profile */ + fail_unless (profile); + + /* must not be main profile at least. + * main-444 is expected but we might update the profile parsing + * logic later. At least it should not be main profile + */ + fail_if (g_strcmp0 (profile, "main") == 0); + + gst_event_unref (event); + break; + } + + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * h265parse_suite (void) { @@ -344,6 +408,7 @@ h265parse_suite (void) tcase_add_test (tc_chain, test_parse_split); tcase_add_test (tc_chain, test_parse_detect_stream); tcase_add_test (tc_chain, test_parse_detect_stream_with_hdr_sei); + tcase_add_test (tc_chain, test_parse_fallback_profile); return s; } -- 2.7.4