mirror of
https://gitlab.freedesktop.org/gstreamer/gstreamer.git
synced 2024-12-22 16:26:39 +00:00
h265parser: Allow partially broken hvcC data
Ignores parsing error on the last nalu of the array if the nalu type is not VPS/SPS/PPS Fixes: https://gitlab.freedesktop.org/gstreamer/gstreamer/-/issues/2905 Part-of: <https://gitlab.freedesktop.org/gstreamer/gstreamer/-/merge_requests/5188>
This commit is contained in:
parent
f058eda798
commit
d84c13ab0d
2 changed files with 77 additions and 1 deletions
|
@ -5072,13 +5072,15 @@ gst_h265_parser_parse_decoder_config_record (GstH265Parser * parser,
|
|||
g_assert (gst_bit_reader_get_pos (&br) == 23 * 8);
|
||||
for (i = 0; i < num_of_arrays; i++) {
|
||||
GstH265DecoderConfigRecordNalUnitArray array;
|
||||
guint8 nalu_type;
|
||||
GstH265NalUnit nalu;
|
||||
guint16 num_nalu, j;
|
||||
guint offset;
|
||||
|
||||
READ_CONFIG_UINT8 (array.array_completeness, 1);
|
||||
SKIP_CONFIG_BITS (1);
|
||||
READ_CONFIG_UINT8 (array.nal_unit_type, 6);
|
||||
READ_CONFIG_UINT8 (nalu_type, 6);
|
||||
array.nal_unit_type = nalu_type;
|
||||
|
||||
READ_CONFIG_UINT16 (num_nalu, 16);
|
||||
|
||||
|
@ -5090,6 +5092,15 @@ gst_h265_parser_parse_decoder_config_record (GstH265Parser * parser,
|
|||
2, &nalu);
|
||||
if (result != GST_H265_PARSER_OK) {
|
||||
g_array_unref (array.nalu);
|
||||
/* Ignores parsing error if this is the last nalu and not an essential
|
||||
* nalu for decoding */
|
||||
if (i + 1 == num_of_arrays && j + 1 == num_nalu &&
|
||||
nalu_type != GST_H265_NAL_VPS && nalu_type != GST_H265_NAL_SPS &&
|
||||
nalu_type != GST_H265_NAL_PPS) {
|
||||
GST_WARNING ("Couldn't parse the last nalu, type %d at array %d / %d",
|
||||
nalu_type, i, j);
|
||||
goto out;
|
||||
}
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
@ -5106,6 +5117,7 @@ gst_h265_parser_parse_decoder_config_record (GstH265Parser * parser,
|
|||
}
|
||||
}
|
||||
|
||||
out:
|
||||
*config = ret;
|
||||
return GST_H265_PARSER_OK;
|
||||
|
||||
|
|
|
@ -1170,6 +1170,69 @@ GST_START_TEST (test_parse_sei_userdefinedunregistered)
|
|||
|
||||
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)
|
||||
{
|
||||
|
@ -1206,6 +1269,7 @@ h265parse_harnessed_suite (void)
|
|||
tcase_add_test (tc_chain, test_drain);
|
||||
|
||||
tcase_add_test (tc_chain, test_parse_sei_userdefinedunregistered);
|
||||
tcase_add_test (tc_chain, test_invalid_sei_in_hvcc);
|
||||
|
||||
return s;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue