From 45090ce4fc5dc17cbceda03d5885d657e300e2d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Haibo=20Chen=28=E9=99=88=E6=B5=B7=E5=8D=9A=29?= <495810242@qq.com> Date: Thu, 10 Jul 2025 21:08:05 +0800 Subject: [PATCH] Fix H.264 B-frame detection logic to comply with specification. v6.0.169 (#4414) For H.264, only when the NAL Type is 1, 2, 3, or 4 is it possible for B-frames to be present; that is, non-IDR pictures and slice data. The current `SrsVideoFrame::parse_avc_bframe()` function uses incorrect logic to determine if a NALU can contain B-frames. The original implementation only checked for specific NALU types (IDR, SPS, PPS) to mark as non-B-frames, but this approach misses many other NALU types that cannot contain B-frames according to the H.264 specification. According to H.264 specification (ISO_IEC_14496-10-AVC-2012.pdf, Table 7-1), B-frames can **only** exist in these specific NALU types: - Type 1: Non-IDR coded slice (`SrsAvcNaluTypeNonIDR`) - Type 2: Coded slice data partition A (`SrsAvcNaluTypeDataPartitionA`) - Type 3: Coded slice data partition B (`SrsAvcNaluTypeDataPartitionB`) - Type 4: Coded slice data partition C (`SrsAvcNaluTypeDataPartitionC`) All other NALU types (IDR=5, SEI=6, SPS=7, PPS=8, AUD=9, etc.) cannot contain B-frames by definition. --------- Co-authored-by: Jacob Su Co-authored-by: winlin --- trunk/doc/CHANGELOG.md | 2 ++ trunk/src/core/srs_core_version5.hpp | 2 +- trunk/src/core/srs_core_version6.hpp | 2 +- trunk/src/kernel/srs_kernel_codec.cpp | 3 ++- 4 files changed, 6 insertions(+), 3 deletions(-) diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md index 803badf09..6e8bd209d 100644 --- a/trunk/doc/CHANGELOG.md +++ b/trunk/doc/CHANGELOG.md @@ -7,6 +7,7 @@ The changelog for SRS. ## SRS 6.0 Changelog +* v6.0, 2025-07-10, Merge [#4414](https://github.com/ossrs/srs/pull/4414): Fix H.264 B-frame detection logic to comply with specification. v6.0.169 (#4414) * v6.0, 2025-06-04, Merge [#4325](https://github.com/ossrs/srs/pull/4325): fix bug: loop transcoding #3516. v6.0.168 (#4325) * v6.0, 2025-05-29, Merge [#4356](https://github.com/ossrs/srs/pull/4356): RTMP: Use extended timestamp as delta when chunk fmt=1/2. v6.0.167 (#4356) * v6.0, 2025-03-21, Merge [#4303](https://github.com/ossrs/srs/pull/4303): replace values with enums. v6.0.165 (#4303) @@ -179,6 +180,7 @@ The changelog for SRS. ## SRS 5.0 Changelog +* v5.0, 2025-07-10, Merge [#4414](https://github.com/ossrs/srs/pull/4414): Fix H.264 B-frame detection logic to comply with specification. v5.0.224 (#4414) * v5.0, 2025-03-21, Merge [#4303](https://github.com/ossrs/srs/pull/4303): replace values with enums. v5.0.223 (#4303) * v5.0, 2025-03-20, Merge [#4305](https://github.com/ossrs/srs/pull/4305): free sample to prevent memory leak. v5.0.222 (#4305) * v5.0, 2025-03-18, Merge [#4302](https://github.com/ossrs/srs/pull/4302): update geekyeggo/delete-artifact to 5.0.0. v5.0.221 (#4302) diff --git a/trunk/src/core/srs_core_version5.hpp b/trunk/src/core/srs_core_version5.hpp index 489043499..219653f3a 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 223 +#define VERSION_REVISION 224 #endif diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp index cc7d160e2..d7db085e5 100644 --- a/trunk/src/core/srs_core_version6.hpp +++ b/trunk/src/core/srs_core_version6.hpp @@ -9,6 +9,6 @@ #define VERSION_MAJOR 6 #define VERSION_MINOR 0 -#define VERSION_REVISION 168 +#define VERSION_REVISION 169 #endif diff --git a/trunk/src/kernel/srs_kernel_codec.cpp b/trunk/src/kernel/srs_kernel_codec.cpp index ba0257382..63d10041a 100644 --- a/trunk/src/kernel/srs_kernel_codec.cpp +++ b/trunk/src/kernel/srs_kernel_codec.cpp @@ -725,7 +725,8 @@ srs_error_t SrsVideoFrame::parse_avc_b_frame(const SrsSample* sample, bool& is_b return srs_error_wrap(err, "parse avc nalu type error"); } - if (nalu_type != SrsAvcNaluTypeNonIDR && nalu_type != SrsAvcNaluTypeDataPartitionA && nalu_type != SrsAvcNaluTypeIDR) { + if (nalu_type != SrsAvcNaluTypeNonIDR && nalu_type != SrsAvcNaluTypeDataPartitionA + && nalu_type != SrsAvcNaluTypeDataPartitionB && nalu_type != SrsAvcNaluTypeDataPartitionC) { is_b_frame = false; return err; }