diff --git a/trunk/conf/full.conf b/trunk/conf/full.conf index 78805a126..ed4a756aa 100644 --- a/trunk/conf/full.conf +++ b/trunk/conf/full.conf @@ -1324,7 +1324,6 @@ vhost stream.control.com { vhost publish.srs.com { # the config for FMLE/Flash publisher, which push RTMP to SRS. publish { - # about MR, read https://github.com/ossrs/srs/issues/241 # when enabled the mr, SRS will read as large as possible. # Overwrite by env SRS_VHOST_PUBLISH_MR for all vhosts. # default: off @@ -1397,7 +1396,6 @@ vhost refer.anti_suck.com { # the security to allow or deny clients. vhost security.srs.com { # security for host to allow or deny clients. - # @see https://github.com/ossrs/srs/issues/211 security { # whether enable the security for vhost. # default: off @@ -1777,7 +1775,6 @@ vhost hls.srs.com { # the hls m3u8 target duration ratio, # EXT-X-TARGETDURATION = hls_td_ratio * hls_fragment // init # EXT-X-TARGETDURATION = max(ts_duration, EXT-X-TARGETDURATION) // for each ts - # @see https://github.com/ossrs/srs/issues/304#issuecomment-74000081 # Overwrite by env SRS_VHOST_HLS_HLS_TD_RATIO for all vhosts. # default: 1.5 hls_td_ratio 1.5; @@ -1796,7 +1793,6 @@ vhost hls.srs.com { # ignore, disable the hls. # disconnect, require encoder republish. # continue, ignore failed try to continue output hls. - # @see https://github.com/ossrs/srs/issues/264 # Overwrite by env SRS_VHOST_HLS_HLS_ON_ERROR for all vhosts. # default: continue hls_on_error continue; diff --git a/trunk/conf/security.deny.publish.conf b/trunk/conf/security.deny.publish.conf index fc2a2e809..574b5fcec 100644 --- a/trunk/conf/security.deny.publish.conf +++ b/trunk/conf/security.deny.publish.conf @@ -1,5 +1,4 @@ # security config for srs, allow play and deny publish. -# @see https://github.com/ossrs/srs/issues/211#issuecomment-68507035 # @see full.conf for detail config. listen 1935; diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index bc0622c25..17acbba61 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2023-09-08, Merge [#3597](https://github.com/ossrs/srs/pull/3597): Fix RBSP stream parsing bug, should drop 0x03. v5.0.178 (#3597) * v5.0, 2023-09-07, Merge [#3795](https://github.com/ossrs/srs/pull/3795): Fix dash crash if format not supported. v5.0.177 (#3795) * v5.0, 2023-08-30, Merge [#3779](https://github.com/ossrs/srs/pull/3779): Support HTTP-API for fetching reload result. v5.0.176 (#3779) * v5.0, 2023-08-28, Merge [#3503](https://github.com/ossrs/srs/pull/3503): SrsContextId assignment can be improved without create a duplicated one. v5.0.175 (#3503) diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 78c2ca80e..163f2a2a6 100644 --- a/trunk/src/core/srs_core_version5.hpp +++ b/trunk/src/core/srs_core_version5.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 5 #define VERSION_MINOR 0 -#define VERSION_REVISION 177 +#define VERSION_REVISION 178 #endif diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index 5ed65a6d4..4b64db537 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -773,6 +773,44 @@ bool SrsFormat::is_avc_sequence_header() && video && video->avc_packet_type == SrsVideoAvcFrameTraitSequenceHeader; } +// Remove the emulation bytes from stream, and return num of bytes of the rbsp. +int srs_rbsp_remove_emulation_bytes(SrsBuffer* stream, std::vector& rbsp) +{ + int nb_rbsp = 0; + while (!stream->empty()) { + rbsp[nb_rbsp] = stream->read_1bytes(); + + // .. 00 00 03 xx, the 03 byte should be drop where xx represents any + // 2 bit pattern: 00, 01, 10, or 11. + if (nb_rbsp >= 2 && rbsp[nb_rbsp - 2] == 0 && rbsp[nb_rbsp - 1] == 0 && rbsp[nb_rbsp] == 3) { + // read 1byte more. + if (stream->empty()) { + nb_rbsp++; + break; + } + + // |---------------------|----------------------------| + // | rbsp | nalu with emulation bytes | + // |---------------------|----------------------------| + // | 0x00 0x00 0x00 | 0x00 0x00 0x03 0x00 | + // | 0x00 0x00 0x01 | 0x00 0x00 0x03 0x01 | + // | 0x00 0x00 0x02 | 0x00 0x00 0x03 0x02 | + // | 0x00 0x00 0x03 | 0x00 0x00 0x03 0x03 | + // | 0x00 0x00 0x03 0x04 | 0x00 0x00 0x03 0x04 | + // |---------------------|----------------------------| + uint8_t ev = stream->read_1bytes(); + if (ev > 3) { + nb_rbsp++; + } + rbsp[nb_rbsp] = ev; + } + + nb_rbsp++; + } + + return nb_rbsp; +} + srs_error_t SrsFormat::video_avc_demux(SrsBuffer* stream, int64_t timestamp) { srs_error_t err = srs_success; @@ -961,31 +999,13 @@ srs_error_t SrsFormat::avc_demux_sps() // decode the rbsp from sps. // rbsp[ i ] a raw byte sequence payload is specified as an ordered sequence of bytes. - std::vector rbsp(vcodec->sequenceParameterSetNALUnit.size()); + std::vector rbsp(vcodec->sequenceParameterSetNALUnit.size()); - int nb_rbsp = 0; - while (!stream.empty()) { - rbsp[nb_rbsp] = stream.read_1bytes(); - - // XX 00 00 03 XX, the 03 byte should be drop. - if (nb_rbsp > 2 && rbsp[nb_rbsp - 2] == 0 && rbsp[nb_rbsp - 1] == 0 && rbsp[nb_rbsp] == 3) { - // read 1byte more. - if (stream.empty()) { - break; - } - rbsp[nb_rbsp] = stream.read_1bytes(); - nb_rbsp++; - - continue; - } - - nb_rbsp++; - } + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&stream, rbsp); return avc_demux_sps_rbsp((char*)&rbsp[0], nb_rbsp); } - srs_error_t SrsFormat::avc_demux_sps_rbsp(char* rbsp, int nb_rbsp) { srs_error_t err = srs_success; diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 43fdd3b06..3ba29239d 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -3861,6 +3861,80 @@ VOID TEST(KernelCodecTest, VideoFormatSepcial) } } +VOID TEST(KernelCoecTest, VideoFormatRbspData) +{ + if (true) { + vector nalu = { + 0x25, 0x00, 0x1f, 0xe2, 0x22, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0xab, 0xff + }; + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)nalu.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), nalu.data(), nb_rbsp)); + } + + if (true) { + SrsFormat f; + vector nalu = { + 0x25, 0x00, 0x1f, 0xe2, 0x22, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x80, 0xab, 0xff + }; + vector expect = { + 0x25, 0x00, 0x1f, 0xe2, 0x22, 0x00, 0x00, 0x02, 0x00, 0x00, 0x80, 0xab, 0xff + }; + + // |----------------|----------------------------| + // | rbsp | nalu with emulation bytes | + // |----------------|----------------------------| + // | 0x00 0x00 0x00 | 0x00 0x00 0x03 0x00 | + // | 0x00 0x00 0x01 | 0x00 0x00 0x03 0x01 | + // | 0x00 0x00 0x02 | 0x00 0x00 0x03 0x02 | + // | 0x00 0x00 0x03 | 0x00 0x00 0x03 0x03 | + // |----------------|----------------------------| + for (int i = 0; i <= 3; ++i) { + nalu[8] = uint8_t(i); + expect[7] = uint8_t(i); + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + // 0x00 0x00 0x04 ~ 0x00 0x00 0xFF, no need to add emulation bytes. + for (int i = 4; i <= 0xff; ++i) { + nalu[8] = uint8_t(i); + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)nalu.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), nalu.data(), nb_rbsp)); + } + } + + if (true) { + vector nalu = { + 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x03, 0x01, 0x00, 0x00, 0x03, 0x02, 0x00, 0x00, 0x03, 0x03, 0x00, 0x00, 0x04 + }; + vector expect = { + 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x03, 0x00, 0x00, 0x04 + }; + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } +} + VOID TEST(KernelCodecTest, VideoFormat) { srs_error_t err; @@ -5995,4 +6069,4 @@ VOID TEST(KernelUtilityTest, Base64Decode) HELPER_EXPECT_FAILED(srs_av_base64_decode("YWRtaW46YWRtaW", plaintext)); EXPECT_STRNE("admin:admin", plaintext.c_str()); } -} \ No newline at end of file +} diff --git a/trunk/src/utest/srs_utest_kernel.hpp b/trunk/src/utest/srs_utest_kernel.hpp index ef93f437f..5f4cbd56f 100644 --- a/trunk/src/utest/srs_utest_kernel.hpp +++ b/trunk/src/utest/srs_utest_kernel.hpp @@ -21,6 +21,7 @@ #include #include #include +#include class MockSrsFile { @@ -155,5 +156,7 @@ public: MockPsHandler* clear(); }; +extern int srs_rbsp_remove_emulation_bytes(SrsBuffer* stream, std::vector& rbsp); + #endif diff --git a/trunk/src/utest/srs_utest_kernel2.cpp b/trunk/src/utest/srs_utest_kernel2.cpp index 3600c02bc..e3cfc1cc9 100644 --- a/trunk/src/utest/srs_utest_kernel2.cpp +++ b/trunk/src/utest/srs_utest_kernel2.cpp @@ -455,3 +455,213 @@ VOID TEST(KernelCodecTest, VideoFormatSepcialAsan_DJI_M30) memcpy(data, "\x27\x01\x00\x00\x00\x00\x00\x00\x00", sizeof(data)); HELPER_EXPECT_SUCCESS(f.on_video(0, data, sizeof(data))); } + +VOID TEST(KernelCodecTest, VideoFormatRbspSimple) +{ + // |---------------------|----------------------------| + // | rbsp | nalu with emulation bytes | + // |---------------------|----------------------------| + // | 0x00 0x00 0x00 | 0x00 0x00 0x03 0x00 | + // | 0x00 0x00 0x01 | 0x00 0x00 0x03 0x01 | + // | 0x00 0x00 0x02 | 0x00 0x00 0x03 0x02 | + // | 0x00 0x00 0x03 | 0x00 0x00 0x03 0x03 | + // | 0x00 0x00 0x03 0x04 | 0x00 0x00 0x03 0x04 | + // |---------------------|----------------------------| + if (true) { + vector nalu = {0x00, 0x00, 0x03, 0x00}; + vector expect = {0x00, 0x00, 0x00}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + if (true) { + vector nalu = {0x00, 0x00, 0x03, 0x01}; + vector expect = {0x00, 0x00, 0x01}; + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + if (true) { + vector nalu = {0x00, 0x00, 0x03, 0x02}; + vector expect = {0x00, 0x00, 0x02}; + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + if (true) { + vector nalu = {0x00, 0x00, 0x03, 0x03}; + vector expect = {0x00, 0x00, 0x03}; + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + if (true) { + vector nalu = {0x00, 0x00, 0x03, 0x04}; + vector expect = {0x00, 0x00, 0x03, 0x04}; + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + if (true) { + vector nalu = {0x00, 0x00, 0x03, 0xff}; + vector expect = {0x00, 0x00, 0x03, 0xff}; + + SrsBuffer b((char*)nalu.data(), nalu.size()); + vector rbsp(nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } +} + +VOID TEST(KernelCodecTest, VideoFormatRbspEdge) +{ + if (true) { + vector nalu = {0x00, 0x00, 0x03}; + vector expect = {0x00, 0x00, 0x03}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + if (true) { + vector nalu = {0xff, 0x00, 0x00, 0x03}; + vector expect = {0xff, 0x00, 0x00, 0x03}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + for (uint16_t v = 0x01; v <= 0xff; v++) { + vector nalu = {(uint8_t)v, 0x00, 0x00, 0x03}; + vector expect = {(uint8_t)v, 0x00, 0x00, 0x03}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } +} + +VOID TEST(KernelCodecTest, VideoFormatRbspNormal) +{ + for (uint16_t v = 0x01; v <= 0xff; v++) { + vector nalu = {0x00, (uint8_t)v, 0x03, 0x00}; + vector expect = {0x00, (uint8_t)v, 0x03, 0x00}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + for (uint16_t v = 0x01; v <= 0xff; v++) { + vector nalu = {(uint8_t)v, 0x00, 0x03, 0x00}; + vector expect = {(uint8_t)v, 0x00, 0x03, 0x00}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + for (uint16_t v = 0x00; v <= 0xff; v++) { + vector nalu = {0x00, 0x00, (uint8_t)v}; + vector expect = {0x00, 0x00, (uint8_t)v}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + for (uint16_t v = 0x00; v <= 0xff; v++) { + vector nalu = {0x00, (uint8_t)v}; + vector expect = {0x00, (uint8_t)v}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + for (uint16_t v = 0x00; v <= 0xff; v++) { + vector nalu = {(uint8_t)v}; + vector expect = {(uint8_t)v}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + for (uint16_t v = 0x00; v <= 0xff; v++) { + vector nalu = {(uint8_t)v, (uint8_t)v}; + vector expect = {(uint8_t)v, (uint8_t)v}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } + + for (uint16_t v = 0x00; v <= 0xff; v++) { + vector nalu = {(uint8_t)v, (uint8_t)v, (uint8_t)v}; + vector expect = {(uint8_t)v, (uint8_t)v, (uint8_t)v}; + + vector rbsp(nalu.size()); + SrsBuffer b((char*)nalu.data(), nalu.size()); + int nb_rbsp = srs_rbsp_remove_emulation_bytes(&b, rbsp); + + ASSERT_EQ(nb_rbsp, (int)expect.size()); + EXPECT_TRUE(srs_bytes_equals(rbsp.data(), expect.data(), nb_rbsp)); + } +}