Move global xpps statistics variables from `srs_app_server.cpp` to
`srs_kernel_kbps.cpp`.
Extract global shared timers from `SrsServer` into new `SrsSharedTimer`
class.
Extract WebRTC session management logic from `SrsServer` into dedicated
`SrsRtcSessionManager` class.
Extract PID file handling into dedicated `SrsPidFileLocker` class.
---------
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
This PR makes WebRTC a core feature of SRS and enforces C++98
compatibility by:
1. Always Enable WebRTC Support
- Remove `--rtc=on|off` configuration option - WebRTC is now always
enabled
- Eliminate all `#ifdef SRS_RTC` conditional compilation blocks
- Include WebRTC-related modules (RTC, SRTP, DTLS) in all builds
- Update build scripts to always link WebRTC dependencies
2. Enforce C++98 Compatibility
- Remove `--cxx11=on|off` and `--cxx14=on|off` configuration options
- Force `SRS_CXX11=NO` and `SRS_CXX14=NO` in build system
- Move these options to deprecated section with warnings
- Ensure codebase maintains C++98 standard compatibility
3. Remove Windows/Cygwin Support
- Remove all Windows and Cygwin64 conditional compilation blocks (#ifdef
_WIN32, #ifdef CYGWIN64)
- Delete Cygwin64 build configurations from build scripts (
auto/options.sh, auto/depends.sh, configure)
- Remove Cygwin64 assembly files and State Threads platform support (
md_cygwin64.S)
- Eliminate Windows-specific GitHub Actions workflows and CI/CD jobs
- Remove NSIS packaging files and Windows installer generation
- Delete Windows documentation and update feature lists to mark support
as removed in v7.0
- Simplify OS detection to only support Unix-like systems (Linux, macOS)
4. Code Cleanup
- Remove conditional WebRTC code blocks throughout the codebase
- Simplify build configuration by removing WebRTC-related conditionals
- Update constructor delegation patterns to be C++98 compatible
- Fix vector initialization to use C++98 syntax
- Eliminate Windows-specific implementations for file operations, time
handling, and networking
- Unified platform handling with consistent POSIX API usage
---------
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
This PR removes the multi-threading infrastructure from SRS and
consolidates the codebase to use single-thread architecture exclusively.
This is a architectural simplification that aligns with SRS's
coroutine-based design philosophy.
* Simplified Architecture: Eliminates complexity of multi-threading
coordination
* Better Alignment: Matches SRS's coroutine-based single-thread design
philosophy
* Reduced Complexity: Removes potential race conditions and threading
bugs
* Cleaner Code: More focused modules with clear responsibilities
* Easier Maintenance: Fewer moving parts and clearer execution flow
---------
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
## Introduce
This PR adds support for viewing streams via the RTSP protocol. Note
that it only supports viewing streams, not publishing streams via RTSP.
Currently, only publishing via RTMP is supported, which is then
converted to RTSP. Further work is needed to support publishing RTC/SRT
streams and converting them to RTSP.
## Usage
Build and run SRS with RTSP support:
```
cd srs/trunk && ./configure --rtsp=on && make -j16
./objs/srs -c conf/rtsp.conf
```
Push stream via RTMP by FFmpeg:
```
ffmpeg -re -i doc/source.flv -c copy -f flv rtmp://localhost/live/livestream
```
View the stream via RTSP protocol, try UDP first, then use TCP:
```
ffplay -i rtsp://localhost:8554/live/livestream
```
Or specify the transport protocol with TCP:
```
ffplay -rtsp_transport tcp -i rtsp://localhost:8554/live/livestream
```
## Unit Test
Run utest for RTSP:
```
./configure --utest=on & make utest -j16
./objs/srs_utest
```
## Regression Test
You need to start SRS for regression testing.
```
./objs/srs -c conf/regression-test-for-clion.conf
```
Then run regression tests for RTSP.
```
cd srs/trunk/3rdparty/srs-bench
go test ./srs -mod=vendor -v -count=1 -run=TestRtmpPublish_RtspPlay
```
## Blackbox Test
For blackbox testing, SRS will be started by utest, so there is no need
to start SRS manually.
```
cd srs/trunk/3rdparty/srs-bench
go test ./blackbox -mod=vendor -v -count=1 -run=TestFast_RtmpPublish_RtspPlay_Basic
```
## UDP Transport
As UDP requires port allocation, this PR doesn't support delivering
media stream via UDP transport, so it will fail if you try to use UDP as
transport:
```
ffplay -rtsp_transport udp -i rtsp://localhost:8554/live/livestream
[rtsp @ 0x7fbc99a14880] method SETUP failed: 461 Unsupported Transport
rtsp://localhost:8554/live/livestream: Protocol not supported
[2025-07-05 21:30:52.738][WARN][14916][7d7gf623][35] RTSP: setup failed: code=2057
(RtspTransportNotSupported) : UDP transport not supported, only TCP/interleaved mode is supported
```
There are no plans to support UDP transport for RTSP. In the real world,
UDP is rarely used; the vast majority of RTSP traffic uses TCP.
## Play Before Publish
RTSP supports audio with AAC and OPUS codecs, which is significantly
different from RTMP or WebRTC.
RTSP uses commands to exchange SDP and specify the audio track to play,
unlike WHEP or HTTP-FLV, which use the query string of the URL. RTSP
depends on the player’s behavior, making it very difficult to use and
describe.
Considering the feature that allows playing the stream before publishing
it, it requires generating some default parameters in the SDP. For OPUS,
the sample rate is 48 kHz with 2 channels, while AAC is more complex,
especially regarding the sample rate, which may be 44.1 kHz, 32 kHz, or
48 kHz.
Therefore, for RTSP, we cannot support play-then-publish. Instead, there
must already be a stream when playing it, so that the audio codec is
determined.
## Opus Codec
No Opus codec support for RTSP, because for RTC2RTSP, it always converts
RTC to RTMP frames, then converts them to RTSP packets. Therefore, the
audio codec is always AAC after converting RTC to RTMP.
This means the bridge architecture needs some changes. We need a new
bridge that binds to the target protocol. For example, RTC2RTMP converts
the audio codec, but RTC2RTSP keeps the original audio codec.
Furthermore, the RTC2RTMP bridge should also support bypassing the Opus
codec if we use enhanced-RTMP, which supports the Opus audio codec. I
think it should be configurable to either transcode or bypass the audio
codec. However, this is not relevant to RTSP.
## AI Contributor
Below commits are contributed by AI:
* [AI: Remove support for media transport via
UDP.](755686229f)
* [AI: Add crutial logs for each RTSP
stage.](9c8cbe7bde)
* [AI: Support AAC doec for
RTSP.](7d7cc12bae)
* [AI: Add option --rtsp for
RTSP.](f67414d9ee)
* [AI: Extract SrsRtpVideoBuilder for RTC and
RTSP.](562e76b904)
---------
Co-authored-by: Jacob Su <suzp1984@gmail.com>
Co-authored-by: winlin <winlinvip@gmail.com>
SrsUniquePtr does not support array or object created by malloc, because
we only use delete to dispose the resource. You can use a custom
function to free the memory allocated by malloc or other allocators.
```cpp
char* p = (char*)malloc(1024);
SrsUniquePtr<char> ptr(p, your_free_chars);
```
This is used to replace the SrsAutoFreeH. For example:
```cpp
addrinfo* r = NULL;
SrsAutoFreeH(addrinfo, r, freeaddrinfo);
getaddrinfo("127.0.0.1", NULL, &hints, &r);
```
Now, this can be replaced by:
```cpp
addrinfo* r = NULL;
getaddrinfo("127.0.0.1", NULL, &hints, &r);
SrsUniquePtr<addrinfo> r2(r, freeaddrinfo);
```
Please aware that there is a slight difference between SrsAutoFreeH and
SrsUniquePtr. SrsAutoFreeH will track the address of pointer, while
SrsUniquePtr will not.
```cpp
addrinfo* r = NULL;
SrsAutoFreeH(addrinfo, r, freeaddrinfo); // r will be freed even r is changed later.
SrsUniquePtr<addrinfo> ptr(r, freeaddrinfo); // crash because r is an invalid pointer.
```
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: john <hondaxiao@tencent.com>
try to fix#3978
**Background**
check #3978
**Research**
I referred the Android platform's solution, because I have android
background, and there is a loop to handle message inside android.
ff007a03c0/core/java/android/os/Handler.java (L701-L706C6)
```
public final boolean sendMessageDelayed(@NonNull Message msg, long delayMillis) {
if (delayMillis < 0) {
delayMillis = 0;
}
return sendMessageAtTime(msg, SystemClock.uptimeMillis() + delayMillis);
}
```
59d9dc1f50/libutils/SystemClock.cpp (L37-L51)
```
/*
* native public static long uptimeMillis();
*/
int64_t uptimeMillis()
{
return nanoseconds_to_milliseconds(uptimeNanos());
}
/*
* public static native long uptimeNanos();
*/
int64_t uptimeNanos()
{
return systemTime(SYSTEM_TIME_MONOTONIC);
}
```
59d9dc1f50/libutils/Timers.cpp (L32-L55)
```
#if defined(__linux__)
nsecs_t systemTime(int clock) {
checkClockId(clock);
static constexpr clockid_t clocks[] = {CLOCK_REALTIME, CLOCK_MONOTONIC,
CLOCK_PROCESS_CPUTIME_ID, CLOCK_THREAD_CPUTIME_ID,
CLOCK_BOOTTIME};
static_assert(clock_id_max == arraysize(clocks));
timespec t = {};
clock_gettime(clocks[clock], &t);
return nsecs_t(t.tv_sec)*1000000000LL + t.tv_nsec;
}
#else
nsecs_t systemTime(int clock) {
// TODO: is this ever called with anything but REALTIME on mac/windows?
checkClockId(clock);
// Clock support varies widely across hosts. Mac OS doesn't support
// CLOCK_BOOTTIME (and doesn't even have clock_gettime until 10.12).
// Windows is windows.
timeval t = {};
gettimeofday(&t, nullptr);
return nsecs_t(t.tv_sec)*1000000000LL + nsecs_t(t.tv_usec)*1000LL;
}
#endif
```
For Linux system, we can use `clock_gettime` api, but it's first
appeared in Mac OSX 10.12.
`man clock_gettime`
The requirement is to find an alternative way to get the timestamp in
microsecond unit, but the `clock_gettime` get nanoseconds, the math
formula is the nanoseconds / 1000 = microsecond. Then I check the
performance of this api + math division.
I used those code to check the `clock_gettime` performance.
```
#include <sys/time.h>
#include <time.h>
#include <stdio.h>
#include <unistd.h>
int main() {
struct timeval tv;
struct timespec ts;
clock_t start;
clock_t end;
long t;
while (1) {
start = clock();
gettimeofday(&tv, NULL);
end = clock();
printf("gettimeofday clock is %lu\n", end - start);
printf("gettimeofday is %lld\n", (tv.tv_sec * 1000000LL + tv.tv_usec));
start = clock();
clock_gettime(CLOCK_MONOTONIC, &ts);
t = ts.tv_sec * 1000000L + ts.tv_nsec / 1000L;
end = clock();
printf("clock_monotonic clock is %lu\n", end - start);
printf("clock_monotonic: seconds is %ld, nanoseconds is %ld, sum is %ld\n", ts.tv_sec, ts.tv_nsec, t);
start = clock();
clock_gettime(CLOCK_MONOTONIC_RAW, &ts);
t = ts.tv_sec * 1000000L + ts.tv_nsec / 1000L;
end = clock();
printf("clock_monotonic_raw clock is %lu\n", end - start);
printf("clock_monotonic_raw: nanoseconds is %ld, sum is %ld\n", ts.tv_nsec, t);
sleep(3);
}
return 0;
}
```
Here is output:
env: Mac OS M2 chip.
```
gettimeofday clock is 11
gettimeofday is 1709775727153949
clock_monotonic clock is 2
clock_monotonic: seconds is 1525204, nanoseconds is 409453000, sum is 1525204409453
clock_monotonic_raw clock is 2
clock_monotonic_raw: nanoseconds is 770493000, sum is 1525222770493
```
We can see the `clock_gettime` is faster than `gettimeofday`, so there
are no performance risks.
**MacOS solution**
`clock_gettime` api only available until mac os 10.12, for the mac os
older than 10.12, just keep the `gettimeofday`.
check osx version in `auto/options.sh`, then add MACRO in
`auto/depends.sh`, the MACRO is `MD_OSX_HAS_NO_CLOCK_GETTIME`.
**CYGWIN**
According to google search, it seems the
`clock_gettime(CLOCK_MONOTONIC)` is not support well at least 10 years
ago, but I didn't own an windows machine, so can't verify it. so keep
win's solution.
---------
Co-authored-by: winlin <winlinvip@gmail.com>
1. Remove the srs_global_dispose, which causes the crash when still
publishing when quit.
2. Always call _srs_thread_pool->initialize for single thread.
3. Support `--signal-api` to send signal by HTTP API, because CLion
eliminate the signals.
---
Co-authored-by: Jacob Su <suzp1984@gmail.com>
HLS typically has a delay of around 30 seconds, roughly comprising three
segments, each lasting 10 seconds. We can reduce the delay to about 5
seconds by lowering the segment duration to 2 seconds and starting
playback from the last segment, achieving a stable delay.
Of course, this requires setting the OBS's GOP to 1 second, and the
profile to baseline, preset to fast, and tune to zerolatency.
Additionally, updating a few configurations in the hls.js player is
necessary, such as setting it to start playback from the last segment,
setting the maximum buffer, and initiating accelerated playback to
reduce latency.
---------
Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: john <hondaxiao@tencent.com>
Accommodate certain complex parameters that include the "=" character,
for example.
`configure --extra-flags="-O2 -D_FORTIFY_SOURCE=2"`
---------
Co-authored-by: john <hondaxiao@tencent.com>
The `-` character, when placed in the middle of a regular expression, is
interpreted as a range. It must be placed at the beginning or end to be
interpreted as a literal character.
---------
`TRANS_BY_GPT4`
---------
Co-authored-by: john <hondaxiao@tencent.com>
1. After enabling FFmpeg opus, the transcoding time for each opus packet
is around 4ms.
2. To speed up case execution, our test publisher sends 400 opus packets
at intervals of 1ms.
3. After the publisher starts, wait for 30ms, then the player starts.
4. Due to the lengthy processing time for each opus packet, SRS
continuously receives packets from the publisher, so it doesn't switch
coroutines and can't accept the player's connection.
5. Only after all opus packets are processed will it accept the player
connection. Therefore, the player doesn't receive any data, leading to
the failure of the case.
---------
Co-authored-by: winlin <winlinvip@gmail.com>
### Description
When converting between AAC and Opus formats (aac2opus or opus2aac), the
`av_frame_get_buffer` API is frequently called.
### Objective
The goal is to optimize the code logic and reduce the frequent
allocation and deallocation of memory.
In the case of aac2opus, av_frame_get_buffer is still frequently called.
In the case of opus2aac, the goal is to avoid calling
av_frame_get_buffer and reduce memory allocations.
### Additional Note
Before calling the `av_audio_fifo_read` API, use
`av_frame_make_writable` to check if the frame is writable. If it is not
writable, create a new frame.
---------
Co-authored-by: john <hondaxiao@tencent.com>
By default, caching is enabled during compilation, which means that data
is cached in Docker. This helps to avoid compiling third-party
dependency libraries. However, sometimes when updating third-party
libraries, it's necessary to disable caching to temporarily verify if
the pipeline can succeed. Therefore, a configure option should be added.
When this option is enabled, the compilation cache will not be used, and
all third-party libraries will be compiled from scratch.
---------
Co-authored-by: winlin <winlinvip@gmail.com>
Follow the example in FFmpeg's doc, before calling the API
`avcodec_send_frame`, always use `av_frame_alloc` to create a new frame.
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
For the DJI M30, there is a bug where empty NALU packets with a size of
zero are causing issues with HLS streaming. This bug leads to random
unpublish events due to the SRS disconnecting the connection for the HLS
module when it fails to handle empty NALU packets.
To address this bug, we have patched the system to ignore any empty NALU
packets with a size of zero. Additionally, we have created a tool in the
srs-bench to replay pcapng files captured by tcpdump or Wireshark. We
have also added utest using mprotect and asan to detect any memory
corruption.
It is important to note that this bug has been fixed in versions 4.0.271
6477f31004 and 5.0.170
939f6b484b. This patch specifically
addresses the issue in SRS 6.0.
Please be aware that there is another commit related to this bug that
partially fixes the issue but still leaves a small problem for asan to
detect memory corruption. This commit,
577cd299e1, only ignores empty NALU
packets but still reads beyond the memory.
---------
Co-authored-by: chundonglinlin <chundonglinlin@163.com>
It is advised to eliminate any instances of _srs_rtc_manager that occur
multiple times.
---------
Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: chundonglinlin <chundonglinlin@163.com>
If your OS is not CentOS, Ubuntu, macOS, cygwin64, run of configure will fail with:
```
Your OS Linux is not supported.
```
For other linux systems, we should support an option:
```
./configure --generic-linux=on
```
Please note that you might still fail for other issues while configuring or building.
-------
Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: ChenGH <chengh_math@126.com>
* Asan: Disable asan for CentOS and use statically link if possible. v5.0.127 (#3347)
1. Disable asan for all CentOS by default, however user could enable it.
2. Link asan statically if possible.
* Update version to v5.0.127
Co-authored-by: winlin <winlin@vip.126.com>
PICK dd0f398296
1. Support configure with --h265=on.
2. Parse HEVC(H.265) from FLV or RTMP packet.
3. Support HEVC over RTMP or HTTP-FLV.
Co-authored-by: runner365 <shi.weibd@hotmail.com>
1. Support github actions on Windows Server 2022.
2. Use cygwin64 in windows-latest to build SRS.
3. Package SRS-xxx-setup.exe by NSIS.exe
4. Patch crypto/include/config.h for libsrtp.
5. Support run as administrator.
6. Apply utest for cygwin.
7. Enable srtp over openssl.
1. Support cygwin by '--cygwin64=on'
2. Detect cygwin automatically.
3. Disalbe sanitizer, srt and srtp with openssl.
4. Disable multiple threads, use single threads.
5. Support utest for cygwin64.
6. Query features for windows by API.
7. Disable stat APIs for cygwin.
8. Use ST select event driver.
Co-authored-by: wenjie.zhao <740936897@qq.com>
1. Replase ln by cp for windows.
2. Refine OS and CPU arch detecting.
3. Support configure from any directory by `SRS_WORKDIR`.
4. Support output to any directory by `SRS_OUTPUT`.
5. Disable sanitizer for gperf.
6. Use parallels build for make.
7. Refine bash variable check.
1. Support Java/log4j log level text.
2. Support configuring by `--log-new-level=on` which is enabled by default.
3. Support `--log-new-level=off` to use SRS 4.0 log level for compatibility.
* Sanitizer: Support address sanitizer for x86_64 platform
* Sanitizer: Not mac os need -static-libasan
* Sanitizer: Add script for docker test.
* Sanitizer: Refine build script.
* Santizer: Fix ossrs/srs:dev-gcc7-cache cannot find libasan bug
* Sanitizer: Support sanitizer when use ossrs/srs:dev-cache and ubuntuxx-cache
* Sanitizer: Add sanitizer-static config
Co-authored-by: winlin <winlin@vip.126.com>