Skip to content

Commit 7c1e87e

Browse files
winlinvipossrs-ai
andauthored
AI: Add more utests for kernel module. v7.0.81 (#4478)
This PR significantly enhances the kernel module by adding comprehensive unit test coverage and improving interface design for core buffer and load balancer components. - **ISrsDecoder**: New interface for decoding/deserialization operations - **ISrsLbRoundRobin**: Extracted interface from concrete SrsLbRoundRobin class for better abstraction - **Enhanced Documentation**: Added comprehensive inline documentation for ISrsEncoder, ISrsCodec, SrsBuffer, and SrsBitBuffer classes --------- Co-authored-by: OSSRS-AI <[email protected]>
1 parent 8976ce4 commit 7c1e87e

14 files changed

+3106
-245
lines changed

.augment-guidelines

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,60 @@ code_patterns:
162162
- pattern: "srs_freepa"
163163
description: "Custom macro for freeing arrays - use only when smart pointers are not suitable"
164164

165+
naming_conventions:
166+
- pattern: "field_naming"
167+
description: "MANDATORY - All class and struct fields must end with underscore (_)"
168+
usage: |
169+
WRONG: Fields without underscore
170+
class SrsBuffer {
171+
private:
172+
char *p;
173+
int size;
174+
public:
175+
bool enabled;
176+
};
177+
178+
CORRECT: Fields with underscore
179+
class SrsBuffer {
180+
private:
181+
char *p_;
182+
int size_;
183+
public:
184+
bool enabled_;
185+
};
186+
scope: "Applies to ALL fields (private, protected, public) in both classes and structs"
187+
exceptions: "Only applies to SRS-defined classes/structs - do NOT change 3rd party code like llhttp"
188+
rationale: "Consistent naming convention across SRS codebase for better code readability and maintenance"
189+
190+
commenting_style:
191+
- pattern: "C++ style comments"
192+
description: "MANDATORY - Use C++ style comments (//) instead of C style comments (/* */)"
193+
usage: |
194+
WRONG: C style comments
195+
/* This is a comment */
196+
/**
197+
* Multi-line comment
198+
* with multiple lines
199+
*/
200+
201+
CORRECT: C++ style comments
202+
// This is a comment
203+
// Multi-line comment
204+
// with multiple lines
205+
rationale: "Consistent with SRS codebase style and better for single-line documentation"
206+
207+
- pattern: "No thread-safety comments"
208+
description: "Do NOT describe thread-safety in comments since SRS is a single-threaded application"
209+
usage: |
210+
WRONG: Mentioning thread-safety
211+
// This implementation is thread-safe for single-threaded usage but may
212+
// require external synchronization in multi-threaded environments.
213+
214+
CORRECT: Focus on functionality without thread-safety mentions
215+
// This implementation maintains state between calls for consistent
216+
// round-robin behavior across multiple selections.
217+
rationale: "SRS uses single-threaded coroutine-based architecture, so thread-safety discussions are irrelevant and confusing"
218+
165219
error_handling:
166220
- pattern: "srs_error_t"
167221
description: "Custom error handling system - MANDATORY for all functions that return srs_error_t"

trunk/doc/CHANGELOG.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ The changelog for SRS.
77
<a name="v7-changes"></a>
88

99
## SRS 7.0 Changelog
10+
* v7.0, 2025-09-06, Merge [#4478](https://github.com/ossrs/srs/pull/4478): AI: Add more utests for kernel module. v7.0.81 (#4478)
1011
* v7.0, 2025-09-06, Merge [#4475](https://github.com/ossrs/srs/pull/4475): AI: Support anonymous coroutine with code block. v7.0.80 (#4475)
1112
* v7.0, 2025-09-05, Merge [#4474](https://github.com/ossrs/srs/pull/4474): WebRTC: Fix race condition in RTC nack timer callbacks. v7.0.79 (#4474)
1213
* v7.0, 2025-09-04, Merge [#4467](https://github.com/ossrs/srs/pull/4467): WebRTC: Fix NACK recovered packets not being added to receive queue. v7.0.78 (#4467)

trunk/src/app/srs_app_edge.cpp

Lines changed: 3 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ SrsEdgeRtmpUpstream::~SrsEdgeRtmpUpstream()
6262
close();
6363
}
6464

65-
srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, SrsLbRoundRobin *lb)
65+
srs_error_t SrsEdgeRtmpUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
6666
{
6767
srs_error_t err = srs_success;
6868

@@ -173,7 +173,7 @@ SrsEdgeFlvUpstream::~SrsEdgeFlvUpstream()
173173
close();
174174
}
175175

176-
srs_error_t SrsEdgeFlvUpstream::connect(ISrsRequest *r, SrsLbRoundRobin *lb)
176+
srs_error_t SrsEdgeFlvUpstream::connect(ISrsRequest *r, ISrsLbRoundRobin *lb)
177177
{
178178
// Because we might modify the r, which cause retry fail, so we must copy it.
179179
ISrsRequest *cp = r->copy();
@@ -185,7 +185,7 @@ srs_error_t SrsEdgeFlvUpstream::connect(ISrsRequest *r, SrsLbRoundRobin *lb)
185185
return do_connect(cp, lb, 0);
186186
}
187187

188-
srs_error_t SrsEdgeFlvUpstream::do_connect(ISrsRequest *r, SrsLbRoundRobin *lb, int redirect_depth)
188+
srs_error_t SrsEdgeFlvUpstream::do_connect(ISrsRequest *r, ISrsLbRoundRobin *lb, int redirect_depth)
189189
{
190190
srs_error_t err = srs_success;
191191

@@ -458,11 +458,6 @@ void SrsEdgeIngester::stop()
458458
}
459459
}
460460

461-
string SrsEdgeIngester::get_curr_origin()
462-
{
463-
return lb->selected();
464-
}
465-
466461
#ifdef SRS_APM
467462
ISrsApmSpan *SrsEdgeIngester::span()
468463
{
@@ -999,11 +994,6 @@ void SrsPlayEdge::on_all_client_stop()
999994
}
1000995
}
1001996

1002-
string SrsPlayEdge::get_curr_origin()
1003-
{
1004-
return ingester->get_curr_origin();
1005-
}
1006-
1007997
srs_error_t SrsPlayEdge::on_ingest_play()
1008998
{
1009999
srs_error_t err = srs_success;

trunk/src/app/srs_app_edge.hpp

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class SrsRtmpCommonMessage;
2525
class SrsMessageQueue;
2626
class ISrsProtocolReadWriter;
2727
class SrsKbps;
28-
class SrsLbRoundRobin;
28+
class ISrsLbRoundRobin;
2929
class SrsTcpClient;
3030
class SrsSimpleRtmpClient;
3131
class SrsRtmpCommand;
@@ -64,7 +64,7 @@ class SrsEdgeUpstream
6464
virtual ~SrsEdgeUpstream();
6565

6666
public:
67-
virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb) = 0;
67+
virtual srs_error_t connect(ISrsRequest *r, ISrsLbRoundRobin *lb) = 0;
6868
virtual srs_error_t recv_message(SrsRtmpCommonMessage **pmsg) = 0;
6969
virtual srs_error_t decode_message(SrsRtmpCommonMessage *msg, SrsRtmpCommand **ppacket) = 0;
7070
virtual void close() = 0;
@@ -94,7 +94,7 @@ class SrsEdgeRtmpUpstream : public SrsEdgeUpstream
9494
virtual ~SrsEdgeRtmpUpstream();
9595

9696
public:
97-
virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb);
97+
virtual srs_error_t connect(ISrsRequest *r, ISrsLbRoundRobin *lb);
9898
virtual srs_error_t recv_message(SrsRtmpCommonMessage **pmsg);
9999
virtual srs_error_t decode_message(SrsRtmpCommonMessage *msg, SrsRtmpCommand **ppacket);
100100
virtual void close();
@@ -128,10 +128,10 @@ class SrsEdgeFlvUpstream : public SrsEdgeUpstream
128128
virtual ~SrsEdgeFlvUpstream();
129129

130130
public:
131-
virtual srs_error_t connect(ISrsRequest *r, SrsLbRoundRobin *lb);
131+
virtual srs_error_t connect(ISrsRequest *r, ISrsLbRoundRobin *lb);
132132

133133
private:
134-
virtual srs_error_t do_connect(ISrsRequest *r, SrsLbRoundRobin *lb, int redirect_depth);
134+
virtual srs_error_t do_connect(ISrsRequest *r, ISrsLbRoundRobin *lb, int redirect_depth);
135135

136136
public:
137137
virtual srs_error_t recv_message(SrsRtmpCommonMessage **pmsg);
@@ -155,7 +155,7 @@ class SrsEdgeIngester : public ISrsCoroutineHandler
155155
SrsPlayEdge *edge;
156156
ISrsRequest *req;
157157
SrsCoroutine *trd;
158-
SrsLbRoundRobin *lb;
158+
ISrsLbRoundRobin *lb;
159159
SrsEdgeUpstream *upstream;
160160

161161
public:
@@ -166,7 +166,6 @@ class SrsEdgeIngester : public ISrsCoroutineHandler
166166
virtual srs_error_t initialize(SrsSharedPtr<SrsLiveSource> s, SrsPlayEdge *e, ISrsRequest *r);
167167
virtual srs_error_t start();
168168
virtual void stop();
169-
virtual std::string get_curr_origin();
170169

171170
// Interface ISrsReusableThread2Handler
172171
public:
@@ -192,7 +191,7 @@ class SrsEdgeForwarder : public ISrsCoroutineHandler
192191
ISrsRequest *req;
193192
SrsCoroutine *trd;
194193
SrsSimpleRtmpClient *sdk;
195-
SrsLbRoundRobin *lb;
194+
ISrsLbRoundRobin *lb;
196195
// we must ensure one thread one fd principle,
197196
// that is, a fd must be write/read by the one thread.
198197
// The publish service thread will proxy(msg), and the edge forward thread
@@ -243,7 +242,6 @@ class SrsPlayEdge
243242
virtual srs_error_t on_client_play();
244243
// When all client stopped play, disconnect to origin.
245244
virtual void on_all_client_stop();
246-
virtual std::string get_curr_origin();
247245

248246
public:
249247
// When ingester start to play stream.

trunk/src/app/srs_app_source.cpp

Lines changed: 0 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -2521,8 +2521,3 @@ void SrsLiveSource::on_edge_proxy_unpublish()
25212521
{
25222522
publish_edge->on_proxy_unpublish();
25232523
}
2524-
2525-
string SrsLiveSource::get_curr_origin()
2526-
{
2527-
return play_edge->get_curr_origin();
2528-
}

trunk/src/app/srs_app_source.hpp

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -638,9 +638,6 @@ class SrsLiveSource : public ISrsReloadHandler
638638
virtual srs_error_t on_edge_proxy_publish(SrsRtmpCommonMessage *msg);
639639
// For edge, proxy stop publish
640640
virtual void on_edge_proxy_unpublish();
641-
642-
public:
643-
virtual std::string get_curr_origin();
644641
};
645642

646643
#endif

trunk/src/core/srs_core_version7.hpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,6 @@
99

1010
#define VERSION_MAJOR 7
1111
#define VERSION_MINOR 0
12-
#define VERSION_REVISION 80
12+
#define VERSION_REVISION 81
1313

1414
#endif

trunk/src/kernel/srs_kernel_balance.cpp

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,14 @@
1010

1111
using namespace std;
1212

13+
ISrsLbRoundRobin::ISrsLbRoundRobin()
14+
{
15+
}
16+
17+
ISrsLbRoundRobin::~ISrsLbRoundRobin()
18+
{
19+
}
20+
1321
SrsLbRoundRobin::SrsLbRoundRobin()
1422
{
1523
index = -1;

trunk/src/kernel/srs_kernel_balance.hpp

Lines changed: 40 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -12,27 +12,59 @@
1212
#include <string>
1313
#include <vector>
1414

15-
/**
16-
* the round-robin load balance algorithm,
17-
* used for edge pull and other multiple server feature.
18-
*/
19-
class SrsLbRoundRobin
15+
// Interface for round-robin load balance algorithm.
16+
//
17+
// This interface defines the contract for load balancing algorithms that distribute
18+
// requests across multiple servers in a round-robin fashion. It's primarily used
19+
// for edge pull scenarios and other features that require distributing load across
20+
// multiple backend servers.
21+
//
22+
// The round-robin algorithm ensures fair distribution by cycling through available
23+
// servers in sequence, giving each server an equal opportunity to handle requests.
24+
//
25+
class ISrsLbRoundRobin
26+
{
27+
public:
28+
ISrsLbRoundRobin();
29+
virtual ~ISrsLbRoundRobin();
30+
31+
public:
32+
// Select one server from the provided list of servers using the load balancing algorithm.
33+
//
34+
// @param servers A vector of server addresses/URLs to choose from. Must not be empty.
35+
// @return The selected server address/URL as a string.
36+
//
37+
// @remark The implementation should handle the load balancing logic and maintain
38+
// any necessary state to ensure proper distribution across servers.
39+
// @remark Callers must ensure the servers vector is not empty before calling this method.
40+
//
41+
virtual std::string select(const std::vector<std::string> &servers) = 0;
42+
};
43+
44+
// Implementation of round-robin load balance algorithm.
45+
//
46+
// This class provides a concrete implementation of the ISrsLbRoundRobin interface
47+
// that distributes requests across multiple servers using a simple round-robin
48+
// algorithm. It maintains internal state to track the current position in the
49+
// server list and ensures fair distribution by cycling through servers sequentially.
50+
//
51+
class SrsLbRoundRobin : public ISrsLbRoundRobin
2052
{
2153
private:
22-
// current selected index.
2354
int index;
24-
// total scheduled count.
2555
uint32_t count;
26-
// current selected server.
2756
std::string elem;
2857

2958
public:
3059
SrsLbRoundRobin();
3160
virtual ~SrsLbRoundRobin();
3261

3362
public:
63+
// Get the current server index.
3464
virtual uint32_t current();
65+
// Get the currently selected server.
3566
virtual std::string selected();
67+
// Select the next server using round-robin algorithm.
3668
virtual std::string select(const std::vector<std::string> &servers);
3769
};
3870

trunk/src/kernel/srs_kernel_buffer.cpp

Lines changed: 45 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,14 @@ ISrsEncoder::~ISrsEncoder()
2020
{
2121
}
2222

23+
ISrsDecoder::ISrsDecoder()
24+
{
25+
}
26+
27+
ISrsDecoder::~ISrsDecoder()
28+
{
29+
}
30+
2331
ISrsCodec::ISrsCodec()
2432
{
2533
}
@@ -468,14 +476,23 @@ srs_error_t SrsBitBuffer::read_bits_ue(uint32_t &v)
468476
return srs_error_new(ERROR_HEVC_NALU_UEV, "empty stream");
469477
}
470478

479+
// Unsigned Exp-Golomb decoding algorithm from ITU-T H.265 specification
471480
// ue(v) in 9.2 Parsing process for Exp-Golomb codes
472481
// ITU-T-H.265-2021.pdf, page 221.
473-
// Syntax elements coded as ue(v), me(v), or se(v) are Exp-Golomb-coded.
474-
// leadingZeroBits = -1;
475-
// for( b = 0; !b; leadingZeroBits++ )
476-
// b = read_bits( 1 )
477-
// The variable codeNum is then assigned as follows:
478-
// codeNum = (2<<leadingZeroBits) - 1 + read_bits( leadingZeroBits )
482+
//
483+
// Algorithm:
484+
// 1. Count leading zero bits until first '1' bit
485+
// 2. Read the '1' bit (prefix)
486+
// 3. Read leadingZeroBits more bits (suffix)
487+
// 4. Calculate: codeNum = (2^leadingZeroBits) - 1 + suffix_value
488+
//
489+
// Examples:
490+
// "1" -> leadingZeroBits=0, suffix=none -> value=0
491+
// "010" -> leadingZeroBits=1, suffix=0 -> value=1
492+
// "011" -> leadingZeroBits=1, suffix=1 -> value=2
493+
// "00100" -> leadingZeroBits=2, suffix=00 -> value=3
494+
495+
// Step 1: Count leading zero bits
479496
int leadingZeroBits = -1;
480497
for (int8_t b = 0; !b && !empty(); leadingZeroBits++) {
481498
b = read_bit();
@@ -485,7 +502,10 @@ srs_error_t SrsBitBuffer::read_bits_ue(uint32_t &v)
485502
return srs_error_new(ERROR_HEVC_NALU_UEV, "%dbits overflow 31bits", leadingZeroBits);
486503
}
487504

505+
// Step 2: Calculate base value: (2^leadingZeroBits) - 1
488506
v = (1 << leadingZeroBits) - 1;
507+
508+
// Step 3: Read suffix bits and add to base value
489509
for (int i = 0; i < (int)leadingZeroBits; i++) {
490510
if (empty()) {
491511
return srs_error_new(ERROR_HEVC_NALU_UEV, "no bytes for leadingZeroBits=%d", leadingZeroBits);
@@ -506,15 +526,30 @@ srs_error_t SrsBitBuffer::read_bits_se(int32_t &v)
506526
return srs_error_new(ERROR_HEVC_NALU_SEV, "empty stream");
507527
}
508528

509-
// ue(v) in 9.2.1 General Parsing process for Exp-Golomb codes
510-
// ITU-T-H.265-2021.pdf, page 221.
529+
// Signed Exp-Golomb decoding algorithm from ITU-T H.265 specification
530+
// se(v) in 9.2.2 Mapping process for signed Exp-Golomb codes
531+
// ITU-T-H.265-2021.pdf, page 222.
532+
//
533+
// Algorithm:
534+
// 1. First decode as unsigned Exp-Golomb to get codeNum
535+
// 2. Map to signed value using alternating positive/negative pattern:
536+
// - If codeNum is odd: se_value = (codeNum + 1) / 2
537+
// - If codeNum is even: se_value = -(codeNum / 2)
538+
//
539+
// Mapping table:
540+
// codeNum: 0 1 2 3 4 5 6 7 8 ...
541+
// se(v): 0 1 -1 2 -2 3 -3 4 -4 ...
542+
//
543+
// This encoding efficiently represents signed integers with smaller
544+
// absolute values using fewer bits.
545+
546+
// Step 1: Decode unsigned Exp-Golomb value
511547
uint32_t val = 0;
512548
if ((err = read_bits_ue(val)) != srs_success) {
513549
return srs_error_wrap(err, "read uev");
514550
}
515551

516-
// se(v) in 9.2.2 Mapping process for signed Exp-Golomb codes
517-
// ITU-T-H.265-2021.pdf, page 222.
552+
// Step 2: Map unsigned code to signed value
518553
if (val & 0x01) {
519554
v = (val + 1) / 2;
520555
} else {

0 commit comments

Comments
 (0)