diff --git a/trunk/doc/CHANGELOG.md b/trunk/doc/CHANGELOG.md
index 8a234a6b1..7414816c6 100644
--- a/trunk/doc/CHANGELOG.md
+++ b/trunk/doc/CHANGELOG.md
@@ -7,6 +7,7 @@ The changelog for SRS.
## SRS 7.0 Changelog
+* v7.0, 2025-08-26, Merge [#4451](https://github.com/ossrs/srs/pull/4451): RTC: Fix null pointer crash in RTC2RTMP when start packet is missing. v7.0.63 (#4451)
* v7.0, 2025-08-25, Merge [#4452](https://github.com/ossrs/srs/pull/4452): AI: Implement stream publish token system to prevent race conditions across all protocols. v7.0.62 (#4452)
* v7.0, 2025-08-22, Merge [#4449](https://github.com/ossrs/srs/pull/4449): Refine source lock. v7.0.61 (#4449)
* v7.0, 2025-08-21, Merge [#4447](https://github.com/ossrs/srs/pull/4447): AI: Always enable WebRTC and enforce C++98 compatibility. v7.0.60 (#4447)
@@ -76,6 +77,7 @@ The changelog for SRS.
## SRS 6.0 Changelog
+* v6.0, 2025-08-26, Merge [#4451](https://github.com/ossrs/srs/pull/4451): RTC: Fix null pointer crash in RTC2RTMP when start packet is missing. v6.0.175 (#4451)
* v6.0, 2025-08-16, Merge [#4441](https://github.com/ossrs/srs/pull/4441): fix err memory leak in rtc to rtmp bridge. v6.0.174 (#4441)
* v6.0, 2025-08-14, Merge [#4161](https://github.com/ossrs/srs/pull/4161): fix hls & dash segments cleanup. v6.0.173 (#4161)
* v6.0, 2025-08-12, Merge [#4230](https://github.com/ossrs/srs/pull/4230): MP4 DVR: Fix audio/video synchronization issues in WebRTC recordings. v6.0.172 (#4230)
diff --git a/trunk/src/core/srs_core_version6.hpp b/trunk/src/core/srs_core_version6.hpp
index ea7f3c7c6..37016a7b0 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 174
+#define VERSION_REVISION 175
#endif
diff --git a/trunk/src/core/srs_core_version7.hpp b/trunk/src/core/srs_core_version7.hpp
index 81028ea37..666238901 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 62
+#define VERSION_REVISION 63
#endif
\ No newline at end of file
diff --git a/trunk/src/utest/srs_utest_rtc2.cpp b/trunk/src/utest/srs_utest_rtc2.cpp
index f585f06e0..ebdca443c 100644
--- a/trunk/src/utest/srs_utest_rtc2.cpp
+++ b/trunk/src/utest/srs_utest_rtc2.cpp
@@ -1514,3 +1514,120 @@ VOID TEST(KernelRTC2Test, SrsRtcFrameBuilderVideoFrameDetectorNullPacketHandling
EXPECT_FALSE(frame_ready); // Should not be ready without packets
}
}
+
+// Mock bridge for testing SrsRtcFrameBuilder
+class MockStreamBridge : public ISrsStreamBridge
+{
+public:
+ srs_error_t last_error;
+ int frame_count;
+
+ MockStreamBridge()
+ {
+ last_error = srs_success;
+ frame_count = 0;
+ }
+
+ virtual ~MockStreamBridge()
+ {
+ srs_freep(last_error);
+ }
+
+ virtual srs_error_t initialize(ISrsRequest *r)
+ {
+ return srs_success;
+ }
+
+ virtual srs_error_t on_publish()
+ {
+ return srs_success;
+ }
+
+ virtual srs_error_t on_frame(SrsSharedPtrMessage *frame)
+ {
+ frame_count++;
+ return srs_success;
+ }
+
+ virtual void on_unpublish()
+ {
+ }
+};
+
+VOID TEST(KernelRTC2Test, SrsRtcFrameBuilderPacketVideoRtmpNullPointerCrash)
+{
+ srs_error_t err;
+
+ // Test reproducing the null pointer crash from issue #4450 fixed by PR #4451
+ //
+ // ISSUE BACKGROUND:
+ // Before PR 4451, the packet_video_rtmp() function assumed that the packet at the
+ // 'start' sequence number would always be available in the cache. However, due to
+ // network packet loss or reordering, the packet at the start position could be missing.
+ //
+ // THE CRASH:
+ // The original code did: pkt = cache_video_pkts_[cache_index(start)].pkt;
+ // When pkt was NULL, calling pkt->get_avsync_time() caused a segmentation fault.
+ //
+ // THE FIX:
+ // PR #4451 added a loop to find the first non-null packet in the sequence range
+ // instead of blindly using the packet at the start position.
+ //
+ // This test simulates the crash scenario: packets exist at positions 101, 102, 103
+ // but the start packet (100) is missing. With the fix, the function should use
+ // packet 101 (first available) instead of crashing on the missing packet 100.
+ if (true) {
+ MockStreamBridge bridge;
+ SrsRtcFrameBuilder frame_builder(&bridge);
+
+ // Skip initialization and directly set up the test scenario
+ // We only need to test the packet_video_rtmp function, not the full initialization
+
+ // Manually populate the video cache to simulate the crash scenario
+ // We'll store packets at positions 101, 102, 103 but NOT at position 100 (start)
+ // This simulates network packet loss where the first packet is missing
+
+ // Create test packets with payload to ensure nb_payload > 0
+ SrsRtpPacket *pkt101 = mock_create_test_rtp_packet(101, 1000, false);
+ SrsRtpPacket *pkt102 = mock_create_test_rtp_packet(102, 1000, false);
+ SrsRtpPacket *pkt103 = mock_create_test_rtp_packet(103, 1000, true); // marker bit
+
+ // Add some payload to ensure packets are not empty
+ char payload_data[] = "test_payload_data";
+ SrsRtpRawPayload *payload101 = new SrsRtpRawPayload();
+ payload101->payload = (char *)payload_data;
+ payload101->nn_payload = strlen(payload_data);
+ pkt101->set_payload(payload101, SrsRtpPacketPayloadTypeRaw);
+
+ SrsRtpRawPayload *payload102 = new SrsRtpRawPayload();
+ payload102->payload = (char *)payload_data;
+ payload102->nn_payload = strlen(payload_data);
+ pkt102->set_payload(payload102, SrsRtpPacketPayloadTypeRaw);
+
+ SrsRtpRawPayload *payload103 = new SrsRtpRawPayload();
+ payload103->payload = (char *)payload_data;
+ payload103->nn_payload = strlen(payload_data);
+ pkt103->set_payload(payload103, SrsRtpPacketPayloadTypeRaw);
+
+ // Set the avsync time for the packets to avoid other null pointer issues
+ pkt101->set_avsync_time(1000);
+ pkt102->set_avsync_time(1000);
+ pkt103->set_avsync_time(1000);
+
+ // Store packets in cache (but skip sequence 100 - this is the missing start packet)
+ frame_builder.video_cache_->store_packet(pkt101);
+ frame_builder.video_cache_->store_packet(pkt102);
+ frame_builder.video_cache_->store_packet(pkt103);
+
+ // Before the fix in PR #4451, calling packet_video_rtmp(100, 103) would crash
+ // because it would try to access cache_video_pkts_[cache_index(100)].pkt which is NULL
+ // and then call pkt->get_avsync_time() causing a null pointer dereference
+
+ // The fix ensures we find the first non-null packet (101) instead of assuming
+ // the start packet (100) exists
+ HELPER_EXPECT_SUCCESS(frame_builder.packet_video_rtmp(100, 103));
+
+ // Verify that a frame was successfully processed
+ EXPECT_EQ(1, bridge.frame_count);
+ }
+}