diff --git a/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c b/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c index 3c7380af85..0fb4652f08 100644 --- a/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c +++ b/subprojects/gst-plugins-bad/gst/videoparsers/gsth265parse.c @@ -3180,11 +3180,14 @@ gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps) off = 23; for (i = 0; i < num_nal_arrays; i++) { + guint8 nalu_type; + if (off + 3 >= size) { gst_buffer_unmap (codec_data, &map); goto hvcc_too_small; } + nalu_type = data[off] & 0x3f; num_nals = GST_READ_UINT16_BE (data + off + 1); off += 3; for (j = 0; j < num_nals; j++) { @@ -3192,6 +3195,15 @@ gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps) data, off, size, 2, &nalu); if (parseres != GST_H265_PARSER_OK) { + if (i + 1 == num_nal_arrays && j + 1 == num_nals && + nalu_type != GST_H265_NAL_VPS && nalu_type != GST_H265_NAL_SPS && + nalu_type != GST_H265_NAL_PPS) { + GST_WARNING_OBJECT (h265parse, + "Couldn't parse the last nalu, type %d at array %d / %d", + nalu_type, i, j); + goto codec_data_done; + } + GST_ERROR ("aaa, %d", nalu_type); gst_buffer_unmap (codec_data, &map); goto hvcc_too_small; } @@ -3200,6 +3212,7 @@ gst_h265_parse_set_caps (GstBaseParse * parse, GstCaps * caps) off = nalu.offset + nalu.size; } } + codec_data_done: gst_buffer_unmap (codec_data, &map); /* don't confuse codec_data with inband vps/sps/pps */ diff --git a/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c b/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c index a2c4f3de80..7cd941fdec 100644 --- a/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c +++ b/subprojects/gst-plugins-bad/tests/check/elements/h265parse.c @@ -1116,6 +1116,68 @@ GST_START_TEST (test_drain) GST_END_TEST; +GST_START_TEST (test_invalid_sei_in_hvcc) +{ + GstHarness *h; + GstCaps *caps; + GstBuffer *codec_data; + /* Consists of 4 arrays (VPS, SPS, PPS, SEI -> broken) and each array contains + * single nalu + * Captured from the log at + * https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2905 + */ + static const guint8 hvcc_data[] = { + 0x01, 0x01, 0x01, 0x01, 0x60, 0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0xf0, 0x00, 0xfc, 0xfd, 0xf8, 0xf8, 0x00, 0x00, 0x0f, 0x04, 0x20, + 0x00, 0x01, 0x00, 0x17, 0x40, 0x01, 0x0c, 0x01, 0xff, 0xff, 0x01, 0x60, + 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, 0x00, + 0x7b, 0xac, 0x09, 0x21, 0x00, 0x01, 0x00, 0x42, 0x42, 0x01, 0x01, 0x01, + 0x60, 0x00, 0x00, 0x03, 0x00, 0x80, 0x00, 0x00, 0x03, 0x00, 0x00, 0x03, + 0x00, 0x7b, 0xa0, 0x02, 0x80, 0x80, 0x2d, 0x1f, 0xe3, 0x6b, 0xbb, 0x53, + 0x77, 0x72, 0x5d, 0x60, 0x2d, 0xc0, 0x40, 0x40, 0x41, 0x00, 0x00, 0x03, + 0x03, 0xe8, 0x00, 0x00, 0x4e, 0x20, 0x72, 0x1d, 0xee, 0x51, 0x00, 0x05, + 0xdc, 0x00, 0x00, 0x1a, 0x5e, 0x00, 0x00, 0x2e, 0xe0, 0x00, 0x00, 0xd2, + 0xf0, 0x08, 0x22, 0x00, 0x01, 0x00, 0x0b, 0x44, 0x01, 0xc1, 0x72, 0xb0, + 0x9c, 0x38, 0x77, 0x06, 0x0c, 0x24, 0x27, 0x00, 0x01, 0x00, 0x00, 0x00 + }; + + caps = gst_caps_new_simple ("video/x-h265", "stream-format", G_TYPE_STRING, + "hvc1", "alignment", G_TYPE_STRING, "au", NULL); + codec_data = gst_buffer_new_memdup (hvcc_data, sizeof (hvcc_data)); + gst_caps_set_simple (caps, "codec_data", GST_TYPE_BUFFER, codec_data, NULL); + gst_buffer_unref (codec_data); + + h = gst_harness_new ("h265parse"); + gst_harness_set_src_caps (h, caps); + gst_harness_push_event (h, gst_event_new_eos ()); + + while (TRUE) { + GstEvent *event = gst_harness_pull_event (h); + fail_unless (event); + + if (GST_EVENT_TYPE (event) == GST_EVENT_CAPS) { + GstStructure *s; + gint width, height; + + gst_event_parse_caps (event, &caps); + s = gst_caps_get_structure (caps, 0); + + fail_unless (gst_structure_get_int (s, "width", &width)); + fail_unless_equals_int (width, 1280); + fail_unless (gst_structure_get_int (s, "height", &height)); + fail_unless_equals_int (height, 720); + + gst_event_unref (event); + break; + } + + gst_event_unref (event); + } + + gst_harness_teardown (h); +} + +GST_END_TEST; static Suite * h265parse_harnessed_suite (void) @@ -1152,6 +1214,8 @@ h265parse_harnessed_suite (void) tcase_add_test (tc_chain, test_drain); + tcase_add_test (tc_chain, test_invalid_sei_in_hvcc); + return s; }