From 826f5121c5dfafb39ef093c6d587d328942b25f2 Mon Sep 17 00:00:00 2001 From: Haibo Chen Date: Fri, 27 Aug 2021 07:27:33 +0800 Subject: [PATCH] Support for multiple SPS/PPS, then pick the first one. (#2544) --- trunk/src/kernel/srs_kernel_codec.cpp | 62 ++++++++++++++++----------- trunk/src/utest/srs_utest_kernel.cpp | 16 +++++++ 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 1bb324c12..48a2c96b5 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -806,41 +806,55 @@ srs_error_t SrsFormat::avc_demux_sps_pps(SrsBuffer* stream) } int8_t numOfSequenceParameterSets = stream->read_1bytes(); numOfSequenceParameterSets &= 0x1f; - if (numOfSequenceParameterSets != 1) { + if (numOfSequenceParameterSets < 1) { return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS"); } - if (!stream->require(2)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS size"); - } - uint16_t sequenceParameterSetLength = stream->read_2bytes(); - if (!stream->require(sequenceParameterSetLength)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS data"); - } - if (sequenceParameterSetLength > 0) { - vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength); - stream->read_bytes(&vcodec->sequenceParameterSetNALUnit[0], sequenceParameterSetLength); + // Support for multiple SPS, then pick the first non-empty one. + for (int i = 0; i < numOfSequenceParameterSets; ++i) { + if (!stream->require(2)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS size"); + } + uint16_t sequenceParameterSetLength = stream->read_2bytes(); + if (!stream->require(sequenceParameterSetLength)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS data"); + } + if (vcodec->sequenceParameterSetNALUnit.size() > 0) { + stream->skip(sequenceParameterSetLength); + continue; + } + if (sequenceParameterSetLength > 0) { + vcodec->sequenceParameterSetNALUnit.resize(sequenceParameterSetLength); + stream->read_bytes(&vcodec->sequenceParameterSetNALUnit[0], sequenceParameterSetLength); + } } + // 1 pps if (!stream->require(1)) { return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS"); } int8_t numOfPictureParameterSets = stream->read_1bytes(); numOfPictureParameterSets &= 0x1f; - if (numOfPictureParameterSets != 1) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS"); + if (numOfPictureParameterSets < 1) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode SPS"); } - if (!stream->require(2)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS size"); + // Support for multiple PPS, then pick the first non-empty one. + for (int i = 0; i < numOfPictureParameterSets; ++i) { + if (!stream->require(2)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS size"); + } + uint16_t pictureParameterSetLength = stream->read_2bytes(); + if (!stream->require(pictureParameterSetLength)) { + return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS data"); + } + if (vcodec->pictureParameterSetNALUnit.size() > 0) { + stream->skip(pictureParameterSetLength); + continue; + } + if (pictureParameterSetLength > 0) { + vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength); + stream->read_bytes(&vcodec->pictureParameterSetNALUnit[0], pictureParameterSetLength); + } } - uint16_t pictureParameterSetLength = stream->read_2bytes(); - if (!stream->require(pictureParameterSetLength)) { - return srs_error_new(ERROR_HLS_DECODE_ERROR, "decode PPS data"); - } - if (pictureParameterSetLength > 0) { - vcodec->pictureParameterSetNALUnit.resize(pictureParameterSetLength); - stream->read_bytes(&vcodec->pictureParameterSetNALUnit[0], pictureParameterSetLength); - } - return avc_demux_sps(); } diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index e2e93c14c..b613a4963 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -3723,6 +3723,22 @@ VOID TEST(KernelCodecTest, VideoFormatSepcial) }; HELPER_EXPECT_SUCCESS(f.on_video(0, (char*)buf, sizeof(buf))); } + + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + uint8_t buf[] = { + 0x17, // 1, Keyframe; 7, AVC. + 0x00, // 0, Sequence header. + 0x00, 0x00, 0x00, // Timestamp. + // AVC extra data, SPS/PPS. + 0x00, 0x00, 0x00, 0x00, + 0x00, // lengthSizeMinusOne + 0x02, 0x00, 0x00, 0x00, 0x00, // 2 SPS, + 0x02, 0x00, 0x00, 0x00, 0x00 // 2 PPS, + }; + HELPER_EXPECT_SUCCESS(f.on_video(0, (char*)buf, sizeof(buf))); + } } VOID TEST(KernelCodecTest, VideoFormat)