From 2810d32d6059739a68eb9bf4dee46f4a664451b1 Mon Sep 17 00:00:00 2001 From: OSSRS-AI Date: Wed, 22 Oct 2025 22:05:23 -0400 Subject: [PATCH] AI: Only support AAC/MP3/Opus audio codec. v7.0.102 (#4516) --- .augment-guidelines | 9 +- trunk/doc/CHANGELOG.md | 3 +- trunk/src/core/srs_core_version7.hpp | 2 +- trunk/src/kernel/srs_kernel_packet.cpp | 2 +- trunk/src/utest/srs_utest_kernel.cpp | 121 ++++++++++++++++++++++++- 5 files changed, 132 insertions(+), 5 deletions(-) diff --git a/.augment-guidelines b/.augment-guidelines index d73cfe45b..ed7c6602d 100644 --- a/.augment-guidelines +++ b/.augment-guidelines @@ -896,7 +896,7 @@ documentation: When looking for documentation or need to update docs, check this directory for markdown files and documentation structure. Do not search ossrs.io or ossrs.net for documentation, use the local files instead. - + faq: rtmps_forward: question: "Why doesn't SRS support RTMPS in the forward feature?" @@ -923,3 +923,10 @@ faq: Why not fixed: Properly fixing this requires significant changes to WebRTC signaling protocol, heartbeat mechanisms, and session management across server and all client SDKs. The complexity and maintenance cost is too high for this edge case. + pcm_audio_not_supported: + question: "PCM audio codec not working in RTMP/FLV streaming" + answer: | + PCM audio codec is not supported in SRS. Only AAC, MP3, and Opus audio codecs are supported for RTMP/FLV streaming. + As of v7.0.102 (#4516), SRS explicitly returns an error for unsupported audio codecs instead of silently ignoring them. + Solution: Use FFmpeg to convert PCM audio to AAC: ffmpeg -i input -c:v copy -c:a aac -b:a 128k -f flv rtmp://server/live/stream + diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 60ef8e207..e8b2454d4 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,7 +7,8 @@ The changelog for SRS. ## SRS 7.0 Changelog -* v7.0, 2025-11-04, AI: Fix AAC audio sample rate reporting in API. v7.0.101 (#4518) +* v7.0, 2025-10-22, AI: Only support AAC/MP3/Opus audio codec. v7.0.102 (#4516) +* v7.0, 2025-10-22, AI: Fix AAC audio sample rate reporting in API. v7.0.101 (#4518) * v7.0, 2025-10-20, Merge [#4537](https://github.com/ossrs/srs/pull/4537): Forward: Reject RTMPS destinations with clear error message. v7.0.100 (#4537) * v7.0, 2025-10-17, Merge [#4534](https://github.com/ossrs/srs/pull/4534): HLS: Fix a iterator bug in hls_ctx cleanup function. v7.0.99 (#4534) * v7.0, 2025-10-16, Merge [#4530](https://github.com/ossrs/srs/pull/4530): fix crash issue caused by reload configuration file. v7.0.98 (#4530) diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp index 1c1366458..1058c066c 100644 --- a/trunk/src/core/srs_core_version7.hpp +++ b/trunk/src/core/srs_core_version7.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 7 #define VERSION_MINOR 0 -#define VERSION_REVISION 101 +#define VERSION_REVISION 102 #endif \ No newline at end of file diff --git a/trunk/src/kernel/srs_kernel_packet.cpp b/trunk/src/kernel/srs_kernel_packet.cpp index 23f3d6182..790306e15 100644 --- a/trunk/src/kernel/srs_kernel_packet.cpp +++ b/trunk/src/kernel/srs_kernel_packet.cpp @@ -414,7 +414,7 @@ srs_error_t SrsFormat::on_audio(int64_t timestamp, char *data, int size) SrsAudioCodecId codec = (SrsAudioCodecId)((v >> 4) & 0x0f); if (codec != SrsAudioCodecIdMP3 && codec != SrsAudioCodecIdAAC && codec != SrsAudioCodecIdOpus) { - return err; + return srs_error_new(ERROR_RTC_RTP_MUXER, "unsupported audio codec=%d(%s)", codec, srs_audio_codec_id2str(codec).c_str()); } bool fresh = !acodec_; diff --git a/trunk/src/utest/srs_utest_kernel.cpp b/trunk/src/utest/srs_utest_kernel.cpp index 3fbfb763e..7aca88a5f 100644 --- a/trunk/src/utest/srs_utest_kernel.cpp +++ b/trunk/src/utest/srs_utest_kernel.cpp @@ -4474,13 +4474,27 @@ VOID TEST(KernelCodecTest, AudioFormat) { srs_error_t err; + // Test edge cases with NULL/empty audio data if (true) { SrsFormat f; HELPER_EXPECT_SUCCESS(f.initialize()); + // NULL data should return success (early return) HELPER_EXPECT_SUCCESS(f.on_audio(0, NULL, 0)); + // Zero size should return success (early return) HELPER_EXPECT_SUCCESS(f.on_audio(0, (char *)"\x00", 0)); - HELPER_EXPECT_SUCCESS(f.on_audio(0, (char *)"\x00", 1)); + // Single byte with valid codec (MP3: 0x2F = codec ID 2) should succeed + HELPER_EXPECT_SUCCESS(f.on_audio(0, (char *)"\x2F", 1)); + } + + // Test that unsupported codec (PCM) now returns error + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // PCM codec (0x00) should now return error + err = f.on_audio(0, (char *)"\x00", 1); + HELPER_EXPECT_FAILED(err); } // For MP3 @@ -4604,6 +4618,111 @@ VOID TEST(KernelCodecTest, AudioFormat) } } +VOID TEST(KernelCodecTest, UnsupportedAudioCodecs) +{ + srs_error_t err; + + // Test PCM codec (codec ID 0 = Linear PCM, platform endian) + // Should return error instead of silently ignoring + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // PCM audio: 0x0F = (0 << 4) | 0x0F (codec=0, 44kHz, 16-bit, stereo) + err = f.on_audio(0, (char *)"\x0F\x00\x01\x02", 4); + HELPER_EXPECT_FAILED(err); + EXPECT_TRUE(NULL == f.acodec_); // acodec_ should remain NULL + } + + // Test PCM little endian codec (codec ID 3) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // PCM little endian: 0x3F = (3 << 4) | 0x0F + err = f.on_audio(0, (char *)"\x3F\x00\x01\x02", 4); + HELPER_EXPECT_FAILED(err); + EXPECT_TRUE(NULL == f.acodec_); + } + + // Test ADPCM codec (codec ID 1) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // ADPCM: 0x1F = (1 << 4) | 0x0F + err = f.on_audio(0, (char *)"\x1F\x00\x01\x02", 4); + HELPER_EXPECT_FAILED(err); + EXPECT_TRUE(NULL == f.acodec_); + } + + // Test Speex codec (codec ID 11) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // Speex: 0xBF = (11 << 4) | 0x0F + err = f.on_audio(0, (char *)"\xBF\x00\x01\x02", 4); + HELPER_EXPECT_FAILED(err); + EXPECT_TRUE(NULL == f.acodec_); + } + + // Test Nellymoser codec (codec ID 6) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // Nellymoser: 0x6F = (6 << 4) | 0x0F + err = f.on_audio(0, (char *)"\x6F\x00\x01\x02", 4); + HELPER_EXPECT_FAILED(err); + EXPECT_TRUE(NULL == f.acodec_); + } + + // Test G.711 A-law codec (codec ID 7) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // G.711 A-law: 0x7F = (7 << 4) | 0x0F + err = f.on_audio(0, (char *)"\x7F\x00\x01\x02", 4); + HELPER_EXPECT_FAILED(err); + EXPECT_TRUE(NULL == f.acodec_); + } + + // Test G.711 mu-law codec (codec ID 8) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // G.711 mu-law: 0x8F = (8 << 4) | 0x0F + err = f.on_audio(0, (char *)"\x8F\x00\x01\x02", 4); + HELPER_EXPECT_FAILED(err); + EXPECT_TRUE(NULL == f.acodec_); + } + + // Verify that supported codecs still work: AAC (codec ID 10) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // AAC sequence header should still work + HELPER_EXPECT_SUCCESS(f.on_audio(0, (char *)"\xAF\x00\x12\x10", 4)); + EXPECT_TRUE(NULL != f.acodec_); + EXPECT_EQ(SrsAudioCodecIdAAC, f.acodec_->id_); + } + + // Verify that supported codecs still work: MP3 (codec ID 2) + if (true) { + SrsFormat f; + HELPER_EXPECT_SUCCESS(f.initialize()); + + // MP3: 0x2F = (2 << 4) | 0x0F + HELPER_EXPECT_SUCCESS(f.on_audio(0, (char *)"\x2F\x00", 2)); + EXPECT_TRUE(NULL != f.acodec_); + EXPECT_EQ(SrsAudioCodecIdMP3, f.acodec_->id_); + } +} + VOID TEST(KernelCodecTest, VideoFormatSepcial) { srs_error_t err;