From 5a03862fca0f3c84503796062a092f8712c7cfa0 Mon Sep 17 00:00:00 2001 From: Michael Olbrich Date: Thu, 28 Jan 2021 12:28:03 +0100 Subject: [PATCH] h264parse: don't invalidate the last PPS when parsing a new SPS When a SPS is received then any previous PPS remains valid. So don't clear the PPS flag from the parser state. This is important because there are encoders that don't generated a PPS after every SPS. Closes https://gitlab.freedesktop.org/gstreamer/gst-plugins-bad/-/issues/571 Part-of: --- gst/videoparsers/gsth264parse.c | 2 +- tests/check/elements/h264parse.c | 70 ++++++++++++++++++++++++++++++++ 2 files changed, 71 insertions(+), 1 deletion(-) diff --git a/gst/videoparsers/gsth264parse.c b/gst/videoparsers/gsth264parse.c index a1e6af89c0..621b1b000f 100644 --- a/gst/videoparsers/gsth264parse.c +++ b/gst/videoparsers/gsth264parse.c @@ -953,7 +953,7 @@ gst_h264_parse_process_nal (GstH264Parse * h264parse, GstH264NalUnit * nalu) case GST_H264_NAL_SPS: /* reset state, everything else is obsolete */ - h264parse->state = 0; + h264parse->state &= GST_H264_PARSE_STATE_GOT_PPS; pres = gst_h264_parser_parse_sps (nalparser, nalu, &sps); process_sps: diff --git a/tests/check/elements/h264parse.c b/tests/check/elements/h264parse.c index de5297c974..6ce1e5e0dc 100644 --- a/tests/check/elements/h264parse.c +++ b/tests/check/elements/h264parse.c @@ -1082,6 +1082,75 @@ GST_START_TEST (test_parse_sliced_nal_au) GST_END_TEST; +GST_START_TEST (test_parse_sliced_sps_pps_sps) +{ + GstHarness *h = gst_harness_new ("h264parse"); + GstBuffer *buf; + + gst_harness_set_caps_str (h, + "video/x-h264,stream-format=byte-stream,alignment=nal,parsed=false,framerate=30/1", + "video/x-h264,stream-format=byte-stream,alignment=au,parsed=true"); + + buf = wrap_buffer (h264_slicing_sps, sizeof (h264_slicing_sps), 100, 0); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + buf = wrap_buffer (h264_slicing_pps, sizeof (h264_slicing_pps), 100, 0); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 100, 0); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + /* no output yet, it will be pushed as soon as + * the parser recognizes the new AU */ + fail_unless_equals_int (gst_harness_buffers_in_queue (h), 0); + + buf = wrap_buffer (h264_slicing_sps, sizeof (h264_slicing_sps), 200, 0); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + /* no PP, just a SPS here is valid */ + + buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 200, 0); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + fail_unless_equals_int (gst_harness_buffers_in_queue (h), 1); + + buf = wrap_buffer (h264_idr_slice_1, sizeof (h264_idr_slice_1), 300, 0); + fail_unless_equals_int (gst_harness_push (h, buf), GST_FLOW_OK); + + fail_unless_equals_int (gst_harness_buffers_in_queue (h), 2); + + { + GstMapInfo info; + + buf = composite_buffer (100, 0, 4, + h264_aud, sizeof (h264_aud), + h264_slicing_sps, sizeof (h264_slicing_sps), + h264_slicing_pps, sizeof (h264_slicing_pps), + h264_idr_slice_1, sizeof (h264_idr_slice_1)); + gst_buffer_map (buf, &info, GST_MAP_READ); + + pull_and_check_full (h, info.data, info.size, 100, 0); + + gst_buffer_unmap (buf, &info); + gst_buffer_unref (buf); + + buf = composite_buffer (200, 0, 3, + h264_aud, sizeof (h264_aud), + h264_slicing_sps, sizeof (h264_slicing_sps), + h264_idr_slice_1, sizeof (h264_idr_slice_1)); + gst_buffer_map (buf, &info, GST_MAP_READ); + + pull_and_check_full (h, info.data, info.size, 200, 0); + + gst_buffer_unmap (buf, &info); + gst_buffer_unref (buf); + } + + gst_harness_teardown (h); +} + +GST_END_TEST; + static Suite * h264parse_sliced_suite (void) @@ -1093,6 +1162,7 @@ h264parse_sliced_suite (void) tcase_add_test (tc_chain, test_parse_sliced_nal_nal); tcase_add_test (tc_chain, test_parse_sliced_au_nal); tcase_add_test (tc_chain, test_parse_sliced_nal_au); + tcase_add_test (tc_chain, test_parse_sliced_sps_pps_sps); return s; }