fix crash issue caused by reload configuration file. v7.0.98 (#4530)
fix crash issue caused by reload configuration file, which occurs when a vhost is added/removed in the new configuration. Introduced by https://github.com/ossrs/srs/pull/4458 see https://github.com/ossrs/srs/issues/4529
This commit is contained in:
parent
6f526284a3
commit
abaffdd4b9
4
trunk/3rdparty/signaling/Dockerfile
vendored
4
trunk/3rdparty/signaling/Dockerfile
vendored
|
|
@ -2,7 +2,7 @@
|
|||
############################################################
|
||||
# build
|
||||
############################################################
|
||||
FROM registry.cn-hangzhou.aliyuncs.com/ossrs/srs:dev AS build
|
||||
FROM ossrs/srs:ubuntu20 AS build
|
||||
|
||||
COPY . /tmp/signaling
|
||||
RUN cd /tmp/signaling && make
|
||||
|
|
@ -12,7 +12,7 @@ RUN cp -R /tmp/signaling/www /usr/local/
|
|||
############################################################
|
||||
# dist
|
||||
############################################################
|
||||
FROM centos:7 AS dist
|
||||
FROM ubuntu:focal AS dist
|
||||
|
||||
# HTTP/1989
|
||||
EXPOSE 1989
|
||||
|
|
|
|||
9
trunk/3rdparty/srs-docs/doc/edge.md
vendored
9
trunk/3rdparty/srs-docs/doc/edge.md
vendored
|
|
@ -136,6 +136,15 @@ the HLS, all edge server never output HLS util client access the RTMP stream on
|
|||
That is, never config HLS on edge server, it's no use. The HLS delivery must use squid or
|
||||
traffic server to cache the HTTP origin server.
|
||||
|
||||
## WebRTC Edge
|
||||
|
||||
Currently edge cluster only support RTMP and HTTP-FLV, doesn't support WebRTC. A new version
|
||||
of Edge Cluster is planning, see [#4402](https://github.com/ossrs/srs/discussions/4402) for details.
|
||||
|
||||
Note that you can use new version of [Origin Cluster](./origin-cluster.md) for WebRTC, as it
|
||||
can also used to expand the capacity of streams. However, if you need to expand the capacity
|
||||
of viewers for one stream, you still need the new version of Edge Cluster.
|
||||
|
||||
## Transform Vhost
|
||||
|
||||
The design of CDN stream system, always use `up.xxxx` and `down.xxxx` to operate them, for example, user publish to cdn by host `up.srs.com` and play by `down.srs.com`.
|
||||
|
|
|
|||
49
trunk/3rdparty/srs-docs/doc/flv.md
vendored
49
trunk/3rdparty/srs-docs/doc/flv.md
vendored
|
|
@ -209,5 +209,54 @@ Why use HTTP FLV? HTTP FLV streaming is becoming more popular. The main advantag
|
|||
5. Universality: Flash can play both RTMP and HTTP FLV. Custom apps and mainstream players also support HTTP FLV playback.
|
||||
6. Simplicity: FLV is the simplest streaming media encapsulation, and HTTP is the most widely used protocol. Combining these two makes maintenance much easier than RTMP.
|
||||
|
||||
## IPv6
|
||||
|
||||
SRS (v7.0.67+) supports IPv6 for HTTP-FLV streaming, enabling dual-stack (IPv4/IPv6) operation for low-latency live streaming. This allows HTTP-FLV clients to access streams using IPv6 addresses while maintaining full compatibility with existing IPv4 infrastructure.
|
||||
|
||||
IPv6 support is enabled automatically when SRS detects IPv6 addresses in the HTTP server configuration. Configure the HTTP server to listen on IPv6 addresses:
|
||||
|
||||
```bash
|
||||
http_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 8080 [::]:8080;
|
||||
dir ./objs/nginx/html;
|
||||
}
|
||||
```
|
||||
|
||||
Access HTTP-FLV streams via IPv6:
|
||||
|
||||
```bash
|
||||
# HTTP-FLV stream via IPv6
|
||||
http://[::1]:8080/live/livestream.flv
|
||||
```
|
||||
|
||||
Play HTTP-FLV stream via IPv6 using FFplay:
|
||||
|
||||
```bash
|
||||
ffplay 'http://[::1]:8080/live/livestream.flv'
|
||||
```
|
||||
|
||||
SRS supports dual-stack HTTP-FLV operation, allowing both IPv4 and IPv6 clients to access streams simultaneously:
|
||||
|
||||
```bash
|
||||
http_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 8080 [::]:8080;
|
||||
dir ./objs/nginx/html;
|
||||
}
|
||||
vhost __defaultVhost__ {
|
||||
http_remux {
|
||||
enabled on;
|
||||
mount [vhost]/[app]/[stream].flv;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
This configuration allows:
|
||||
- IPv4 clients: `http://192.168.1.100:8080/live/livestream.flv`
|
||||
- IPv6 clients: `http://[2001:db8::1]:8080/live/livestream.flv`
|
||||
|
||||

|
||||
|
||||
|
|
|
|||
47
trunk/3rdparty/srs-docs/doc/hls.md
vendored
47
trunk/3rdparty/srs-docs/doc/hls.md
vendored
|
|
@ -587,5 +587,52 @@ The generated m3u8 playlist will reference fMP4 segments instead of TS segments,
|
|||
|
||||
Play the stream by SRS player: [http://localhost:8080/live/livestream.m3u8](http://localhost:8080/players/srs_player.html?stream=livestream.m3u8)
|
||||
|
||||
## IPv6
|
||||
|
||||
SRS (v7.0.67+) supports IPv6 for HLS streaming, enabling dual-stack (IPv4/IPv6) operation for HTTP-based live streaming. This allows HLS clients to access streams using IPv6 addresses while maintaining full compatibility with existing IPv4 infrastructure.
|
||||
|
||||
IPv6 support is enabled automatically when SRS detects IPv6 addresses in the HTTP server configuration. Configure the HTTP server to listen on IPv6 addresses:
|
||||
|
||||
```bash
|
||||
http_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 8080 [::]:8080;
|
||||
dir ./objs/nginx/html;
|
||||
}
|
||||
```
|
||||
|
||||
Access HLS streams via IPv6:
|
||||
|
||||
```bash
|
||||
# HLS stream via IPv6
|
||||
http://[::1]:8080/live/livestream.m3u8
|
||||
|
||||
# HLS segments are also accessible via IPv6
|
||||
http://[::1]:8080/live/livestream-1.ts
|
||||
http://[::1]:8080/live/livestream-2.ts
|
||||
```
|
||||
|
||||
Play HLS stream via IPv6 using FFplay:
|
||||
|
||||
```bash
|
||||
ffplay 'http://[::1]:8080/live/livestream.m3u8'
|
||||
```
|
||||
|
||||
SRS supports dual-stack HLS operation, allowing both IPv4 and IPv6 clients to access streams simultaneously:
|
||||
|
||||
```bash
|
||||
http_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 8080 [::]:8080;
|
||||
dir ./objs/nginx/html;
|
||||
}
|
||||
```
|
||||
|
||||
This configuration allows:
|
||||
- IPv4 clients: `http://192.168.1.100:8080/live/livestream.m3u8`
|
||||
- IPv6 clients: `http://[2001:db8::1]:8080/live/livestream.m3u8`
|
||||
|
||||

|
||||
|
||||
|
|
|
|||
56
trunk/3rdparty/srs-docs/doc/rtmp.md
vendored
56
trunk/3rdparty/srs-docs/doc/rtmp.md
vendored
|
|
@ -341,6 +341,62 @@ openssl req -new -x509 -key server.key -out server.crt -days 3650 \
|
|||
|
||||
For production environments, use certificates from a trusted Certificate Authority (CA) or Let's Encrypt.
|
||||
|
||||
## IPv6
|
||||
|
||||
SRS (v7.0.67+) supports IPv6 for RTMP and RTMPS protocols, enabling dual-stack (IPv4/IPv6) operation. This allows clients to connect using IPv6 addresses while maintaining full compatibility with existing IPv4 infrastructure.
|
||||
|
||||
IPv6 support is enabled automatically when SRS detects IPv6 addresses in the configuration. You can configure SRS to listen on IPv6 addresses by specifying them in the `listen` directive:
|
||||
|
||||
```bash
|
||||
rtmp {
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 1935 [::]:1935;
|
||||
}
|
||||
|
||||
# For RTMPS
|
||||
rtmps {
|
||||
enabled on;
|
||||
listen 1443 [::]:1443;
|
||||
key ./conf/server.key;
|
||||
cert ./conf/server.crt;
|
||||
}
|
||||
```
|
||||
|
||||
Publish RTMP stream via IPv6:
|
||||
|
||||
```bash
|
||||
ffmpeg -re -i ./doc/source.flv -c copy -f flv 'rtmp://[::1]:1935/live/livestream'
|
||||
```
|
||||
|
||||
Publish RTMPS stream via IPv6:
|
||||
|
||||
```bash
|
||||
ffmpeg -re -i ./doc/source.flv -c copy -f flv 'rtmps://[::1]:1443/live/livestream'
|
||||
```
|
||||
|
||||
Play RTMP stream via IPv6:
|
||||
|
||||
```bash
|
||||
ffplay 'rtmp://[::1]:1935/live/livestream'
|
||||
```
|
||||
|
||||
Play RTMPS stream via IPv6:
|
||||
|
||||
```bash
|
||||
ffplay 'rtmps://[::1]:1443/live/livestream'
|
||||
```
|
||||
|
||||
SRS supports dual-stack operation, allowing both IPv4 and IPv6 clients to connect simultaneously:
|
||||
|
||||
```bash
|
||||
# Listen on both IPv4 and IPv6 addresses
|
||||
listen 1935 [::]:1935;
|
||||
|
||||
# This allows connections from:
|
||||
# - IPv4 clients: rtmp://192.168.1.100:1935/live/stream
|
||||
# - IPv6 clients: rtmp://[2001:db8::1]:1935/live/stream
|
||||
```
|
||||
|
||||
## On Demand Live Streaming
|
||||
|
||||
In some situations, you might want to start streaming only when someone starts watching:
|
||||
|
|
|
|||
60
trunk/3rdparty/srs-docs/doc/rtsp.md
vendored
60
trunk/3rdparty/srs-docs/doc/rtsp.md
vendored
|
|
@ -131,6 +131,66 @@ go test ./blackbox -mod=vendor -v -count=1 -run=TestFast_RtmpPublish_RtspPlay_Ba
|
|||
|
||||
The current version implements only basic functionality. Additional features like authentication, redirection, and RTCP will be planned according to actual needs, possibly in the near future.
|
||||
|
||||
## IPv6
|
||||
|
||||
SRS (v7.0.67+) supports IPv6 for RTSP protocol, enabling dual-stack (IPv4/IPv6) operation for standards-based streaming. This allows RTSP clients to connect using IPv6 addresses while maintaining full compatibility with existing IPv4 infrastructure.
|
||||
|
||||
IPv6 support is enabled automatically when SRS detects IPv6 addresses in the configuration. Configure the RTSP server to listen on IPv6 addresses:
|
||||
|
||||
```bash
|
||||
rtsp_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6 for UDP media
|
||||
listen 8554 [::]:8554;
|
||||
}
|
||||
|
||||
vhost __defaultVhost__ {
|
||||
rtsp {
|
||||
enabled on;
|
||||
rtmp_to_rtsp on;
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Play RTSP stream via IPv6 using FFplay (TCP transport only):
|
||||
|
||||
```bash
|
||||
ffplay -rtsp_transport tcp -i 'rtsp://[::1]:8554/live/livestream'
|
||||
```
|
||||
|
||||
Play RTSP stream via IPv6 using VLC:
|
||||
|
||||
```bash
|
||||
vlc 'rtsp://[::1]:8554/live/livestream'
|
||||
```
|
||||
|
||||
When using IPv6 addresses in RTSP URLs, the IPv6 address must be enclosed in square brackets:
|
||||
|
||||
```bash
|
||||
# Local IPv6 loopback
|
||||
rtsp://[::1]:8554/live/livestream
|
||||
|
||||
# Public IPv6 address
|
||||
rtsp://[2001:db8::1]:8554/live/livestream
|
||||
|
||||
# With authentication (if implemented)
|
||||
rtsp://user:pass@[2001:db8::1]:8554/live/livestream
|
||||
```
|
||||
|
||||
SRS supports dual-stack RTSP operation, allowing both IPv4 and IPv6 clients to connect simultaneously:
|
||||
|
||||
```bash
|
||||
rtsp_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 8554 [::]:8554;
|
||||
}
|
||||
```
|
||||
|
||||
This configuration allows:
|
||||
- IPv4 clients: `rtsp://192.168.1.100:8554/live/livestream`
|
||||
- IPv6 clients: `rtsp://[2001:db8::1]:8554/live/livestream`
|
||||
|
||||
## References
|
||||
|
||||
- [rfc2326-1998-rtsp.pdf](/files/rfc2326-1998-rtsp.pdf)
|
||||
118
trunk/3rdparty/srs-docs/doc/srt.md
vendored
118
trunk/3rdparty/srs-docs/doc/srt.md
vendored
|
|
@ -43,7 +43,8 @@ Open the following page to play the stream (if SRS is not on your local machine,
|
|||
|
||||
* RTMP(VLC/ffplay): `rtmp://localhost/live/livestream`
|
||||
* HLS by SRS player: [http://localhost:8080/live/livestream.flv](http://localhost:8080/players/srs_player.html)
|
||||
* SRT(VLC/ffplay): `srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=request`
|
||||
* SRT(ffplay): `srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=request`
|
||||
* SRT(VLC): `srt://127.0.0.1:10080`
|
||||
|
||||
SRS supports converting SRT to other protocols, which will be described in detail below.
|
||||
|
||||
|
|
@ -381,6 +382,121 @@ How does SRS implement SRT? Based on coroutine-based SRT architecture, we need t
|
|||
|
||||
> Note: Please note that the SRT in SRS 4.0 is a non-ST architecture, and it is implemented by launching a separate thread, which may not have the same level of maintainability as the native ST coroutine architecture.
|
||||
|
||||
## IPv6
|
||||
|
||||
SRS (v7.0.67+) supports IPv6 for SRT protocol, enabling dual-stack (IPv4/IPv6) operation for low-latency streaming. This allows SRT clients to connect using IPv6 addresses while maintaining full compatibility with existing IPv4 infrastructure.
|
||||
|
||||
IPv6 support is enabled automatically when SRS detects IPv6 addresses in the configuration. Configure the SRT server to listen on IPv6 addresses:
|
||||
|
||||
```bash
|
||||
srt_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 10080 [::]:10080;
|
||||
|
||||
# Other SRT parameters remain the same
|
||||
maxbw 1000000000;
|
||||
mss 1500;
|
||||
connect_timeout 4000;
|
||||
peer_idle_timeout 8000;
|
||||
default_app live;
|
||||
peerlatency 0;
|
||||
recvlatency 0;
|
||||
}
|
||||
```
|
||||
|
||||
Publish SRT stream via IPv6 using FFmpeg:
|
||||
|
||||
```bash
|
||||
ffmpeg -re -i ./doc/source.flv -c copy -pes_payload_size 0 -f mpegts \
|
||||
'srt://[::1]:10080?streamid=#!::r=live/livestream,m=publish'
|
||||
```
|
||||
|
||||
Play SRT stream via IPv6 using FFplay:
|
||||
|
||||
```bash
|
||||
ffplay 'srt://[::1]:10080?streamid=#!::r=live/livestream,m=request'
|
||||
```
|
||||
|
||||
When using IPv6 addresses in SRT URLs, the IPv6 address must be enclosed in square brackets:
|
||||
|
||||
```bash
|
||||
# Publishing
|
||||
srt://[2001:db8::1]:10080?streamid=#!::r=live/livestream,m=publish
|
||||
|
||||
# Playing
|
||||
srt://[2001:db8::1]:10080?streamid=#!::r=live/livestream,m=request
|
||||
|
||||
# With vhost support
|
||||
srt://[2001:db8::1]:10080?streamid=#!::h=srs.srt.com.cn,r=live/livestream,m=publish
|
||||
```
|
||||
|
||||
SRS supports dual-stack SRT operation, allowing both IPv4 and IPv6 clients to connect simultaneously:
|
||||
|
||||
```bash
|
||||
srt_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 10080 [::]:10080;
|
||||
}
|
||||
```
|
||||
|
||||
This configuration allows:
|
||||
- IPv4 clients: `srt://192.168.1.100:10080?streamid=#!::r=live/stream,m=publish`
|
||||
- IPv6 clients: `srt://[2001:db8::1]:10080?streamid=#!::r=live/stream,m=publish`
|
||||
|
||||
## VLC
|
||||
|
||||
VLC has an important limitation: it does not support the `streamid` URL parameter. When VLC connects
|
||||
to an SRT server, it always sends an empty `SRTO_STREAMID` socket option, regardless of what you put
|
||||
in the URL. This means VLC can only use the simple URL format `srt://127.0.0.1:10080` without any
|
||||
streamid parameter.
|
||||
|
||||
To support VLC and other clients that don't set `SRTO_STREAMID`, SRS provides a `default_streamid`
|
||||
configuration option. When a client connects without setting streamid, SRS will use this configured
|
||||
default value. By default, SRS uses `#!::r=live/livestream,m=publish` for backward compatibility,
|
||||
but for VLC playback, you should configure it to use `m=request` mode instead.
|
||||
|
||||
SRS provides a ready-to-use configuration file `conf/srt.vlc.conf` optimized for VLC compatibility.
|
||||
Start SRS with this configuration:
|
||||
|
||||
```bash
|
||||
./objs/srs -c conf/srt.vlc.conf
|
||||
```
|
||||
|
||||
You can also set the default streamid using an environment variable, which is useful for Docker deployments:
|
||||
|
||||
```bash
|
||||
env SRS_SRT_SERVER_DEFAULT_STREAMID="#!::r=live/livestream,m=request" \
|
||||
./objs/srs -c conf/srt.conf
|
||||
```
|
||||
|
||||
Here's a complete workflow example. First, publish a stream with FFmpeg (which explicitly sets streamid
|
||||
with `m=publish`):
|
||||
|
||||
```bash
|
||||
ffmpeg -re -i ./doc/source.flv -c copy -pes_payload_size 0 -f mpegts \
|
||||
'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=publish'
|
||||
```
|
||||
|
||||
Then play with VLC using the simple URL (VLC will use the server's default streamid with `m=request`):
|
||||
|
||||
- Open VLC Media Player
|
||||
- Go to Media → Open Network Stream
|
||||
- Enter URL: `srt://127.0.0.1:10080`
|
||||
- Click Play
|
||||
|
||||
> Note: VLC doesn't support SRT with streamid, so you should use the simple URL format `srt://127.0.0.1:10080` without any streamid parameter.
|
||||
|
||||
You can also play with FFplay by explicitly setting the streamid:
|
||||
|
||||
```bash
|
||||
ffplay 'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=request'
|
||||
```
|
||||
|
||||
The key difference between clients: VLC always uses the server's `default_streamid` configuration, while
|
||||
FFmpeg/FFplay/OBS can set streamid in the URL or settings, which overrides the server default.
|
||||
|
||||
## Q&A
|
||||
|
||||
1. Does SRS support forwarding SRT streams to Nginx?
|
||||
|
|
|
|||
69
trunk/3rdparty/srs-docs/doc/webrtc.md
vendored
69
trunk/3rdparty/srs-docs/doc/webrtc.md
vendored
|
|
@ -516,6 +516,75 @@ Output:
|
|||
|
||||
Winlin 2020.02
|
||||
|
||||
## IPv6
|
||||
|
||||
SRS (v7.0.67+) supports IPv6 for WebRTC protocols, enabling dual-stack (IPv4/IPv6) operation for both UDP and TCP media transport. This includes support for WHIP/WHEP signaling and media transmission over IPv6.
|
||||
|
||||
IPv6 support is enabled automatically when SRS detects IPv6 addresses in the configuration. Configure the RTC server to listen on IPv6 addresses:
|
||||
|
||||
```bash
|
||||
rtc_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6 for UDP media
|
||||
listen 8000 [::]:8000;
|
||||
|
||||
# For WebRTC over TCP
|
||||
tcp {
|
||||
enabled on;
|
||||
listen 8000 [::]:8000;
|
||||
}
|
||||
}
|
||||
|
||||
# HTTP API server for WHIP/WHEP over IPv6
|
||||
http_api {
|
||||
enabled on;
|
||||
listen 1985 [::]:1985;
|
||||
}
|
||||
|
||||
# HTTPS API server for secure WHIP/WHEP over IPv6
|
||||
https_api {
|
||||
enabled on;
|
||||
listen 1990 [::]:1990;
|
||||
key ./conf/server.key;
|
||||
cert ./conf/server.crt;
|
||||
}
|
||||
```
|
||||
|
||||
Publish using WHIP via IPv6:
|
||||
- WHIP URL: `http://[::1]:1985/rtc/v1/whip/?app=live&stream=livestream`
|
||||
- Test page: [http://[::1]:8080/players/whip.html](http://[::1]:8080/players/whip.html)
|
||||
|
||||
Play using WHEP via IPv6:
|
||||
- WHEP URL: `http://[::1]:1985/rtc/v1/whep/?app=live&stream=livestream`
|
||||
- Test page: [http://[::1]:8080/players/whep.html](http://[::1]:8080/players/whep.html)
|
||||
|
||||
For secure connections over IPv6:
|
||||
|
||||
Publish using WHIP via HTTPS IPv6:
|
||||
- WHIP URL: `https://[::1]:1990/rtc/v1/whip/?app=live&stream=livestream`
|
||||
- Test page: [https://[::1]:8088/players/whip.html](https://[::1]:8088/players/whip.html)
|
||||
|
||||
Play using WHEP via HTTPS IPv6:
|
||||
- WHEP URL: `https://[::1]:1990/rtc/v1/whep/?app=live&stream=livestream`
|
||||
- Test page: [https://[::1]:8088/players/whep.html](https://[::1]:8088/players/whep.html)
|
||||
|
||||
SRS supports dual-stack WebRTC, allowing both IPv4 and IPv6 clients to connect simultaneously:
|
||||
|
||||
```bash
|
||||
rtc_server {
|
||||
enabled on;
|
||||
# Listen on both IPv4 and IPv6
|
||||
listen 8000 [::]:8000;
|
||||
|
||||
# Configure candidates for both protocols
|
||||
candidate 192.168.1.100 [2001:db8::1];
|
||||
}
|
||||
```
|
||||
|
||||
This enables:
|
||||
- IPv4 clients to connect via: `http://192.168.1.100:1985/rtc/v1/whip/`
|
||||
- IPv6 clients to connect via: `http://[2001:db8::1]:1985/rtc/v1/whip/`
|
||||
|
||||

|
||||
|
||||
|
||||
|
|
|
|||
14
trunk/3rdparty/srs-docs/pages/contact-en.md
vendored
14
trunk/3rdparty/srs-docs/pages/contact-en.md
vendored
|
|
@ -13,19 +13,7 @@ can be resolved through the documentation, and in cases where you still encounte
|
|||
assistance from other community members. Friends in the community might offer help, but they are not
|
||||
obligated to do so, as it's a universal rule of open-source communities.
|
||||
|
||||
I have a full-time job and support the community during my spare time, focusing primarily on code and
|
||||
documentation development. As a result, I have limited time available for community support and prioritize
|
||||
assistance to project contributors. If you wish for me to dedicate time specifically to assist you, you
|
||||
may consider becoming a backer or sponsor of the project.
|
||||
|
||||
Our documentation and code are open and free, so you don't need to sponsor the community to access these resources. We are a truly open-source community. For financial sponsors, we also offer additional support, including:
|
||||
|
||||
* Backer: $5 per month. Online text chat support through Discord. No custom development included.
|
||||
* Sponsor: $100 per month. Online text chat and online meeting support. No custom development included.
|
||||
* Custom Development: Must be a Backer or Sponsor first. Fees based on duration, evaluated separately. Please contact us on Discord.
|
||||
|
||||
Please visit [OpenCollective](https://opencollective.com/srs-server) to become a backer or sponsor,
|
||||
and send me a direct message on [Discord](https://discord.gg/yZ4BnPmHAd).
|
||||
Our documentation and code are open and free, so you don't need to sponsor the community to access these resources. We are a truly open-source community. Please visit [OpenCollective](https://opencollective.com/srs-server) to become a backer or sponsor.
|
||||
|
||||
## Discussion
|
||||
|
||||
|
|
|
|||
4
trunk/configure
vendored
4
trunk/configure
vendored
|
|
@ -384,8 +384,8 @@ if [[ $SRS_UTEST == YES ]]; then
|
|||
"srs_utest_coworkers" "srs_utest_pithy_print" "srs_utest_kernel3" "srs_utest_protocol4"
|
||||
"srs_utest_protocol3" "srs_utest_app" "srs_utest_app2" "srs_utest_app3" "srs_utest_app4"
|
||||
"srs_utest_app5" "srs_utest_app6" "srs_utest_app7" "srs_utest_app8" "srs_utest_app9"
|
||||
"srs_utest_app10" "srs_utest_app11" "srs_utest_app15" "srs_utest_app16"
|
||||
"srs_utest_app17")
|
||||
"srs_utest_app10" "srs_utest_app11" "srs_utest_app15" "srs_utest_app16"
|
||||
"srs_utest_app17" "srs_utest_rtc_playstream")
|
||||
# Always include SRT utest
|
||||
MODULE_FILES+=("srs_utest_srt")
|
||||
if [[ $SRS_GB28181 == YES ]]; then
|
||||
|
|
|
|||
|
|
@ -7,6 +7,7 @@ The changelog for SRS.
|
|||
<a name="v7-changes"></a>
|
||||
|
||||
## SRS 7.0 Changelog
|
||||
* 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)
|
||||
* v7.0, 2025-10-15, Merge [#4520](https://github.com/ossrs/srs/pull/4520): srs_app_rtc_conn: fix illegal memory access. v7.0.97 (#4520)
|
||||
* v7.0, 2025-10-14, Disable sanitizer by default to fix memory leak. (#4364) v7.0.96
|
||||
* v7.0, 2025-10-01, SRT: Support configurable default_streamid option. v7.0.95 (#4515)
|
||||
|
|
|
|||
|
|
@ -1509,6 +1509,12 @@ srs_error_t SrsConfig::reload_conf(SrsConfig *conf)
|
|||
SrsConfDirective *old_vhost = old_root->get("vhost", vhost);
|
||||
SrsConfDirective *new_vhost = root_->get("vhost", vhost);
|
||||
|
||||
// Only compare config when both old and new vhost exist.
|
||||
// @see https://github.com/ossrs/srs/issues/4529
|
||||
if (!old_vhost || !new_vhost) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// chunk_size, only one per vhost.
|
||||
if (!srs_directive_equals(new_vhost->get("chunk_size"), old_vhost->get("chunk_size"))) {
|
||||
for (it = subscribes_.begin(); it != subscribes_.end(); ++it) {
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ using namespace std;
|
|||
|
||||
#include <srs_app_circuit_breaker.hpp>
|
||||
#include <srs_app_config.hpp>
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_http_api.hpp>
|
||||
#include <srs_app_http_hooks.hpp>
|
||||
#include <srs_app_log.hpp>
|
||||
|
|
@ -304,6 +305,14 @@ ISrsRtcPliWorkerHandler::~ISrsRtcPliWorkerHandler()
|
|||
{
|
||||
}
|
||||
|
||||
ISrsRtcPliWorker::ISrsRtcPliWorker()
|
||||
{
|
||||
}
|
||||
|
||||
ISrsRtcPliWorker::~ISrsRtcPliWorker()
|
||||
{
|
||||
}
|
||||
|
||||
SrsRtcPliWorker::SrsRtcPliWorker(ISrsRtcPliWorkerHandler *h)
|
||||
{
|
||||
handler_ = h;
|
||||
|
|
@ -455,6 +464,7 @@ SrsRtcPlayStream::SrsRtcPlayStream(ISrsExecRtcAsyncTask *exec, ISrsExpire *expir
|
|||
config_ = _srs_config;
|
||||
rtc_sources_ = _srs_rtc_sources;
|
||||
stat_ = _srs_stat;
|
||||
app_factory_ = _srs_app_factory;
|
||||
}
|
||||
|
||||
SrsRtcPlayStream::~SrsRtcPlayStream()
|
||||
|
|
@ -491,6 +501,7 @@ SrsRtcPlayStream::~SrsRtcPlayStream()
|
|||
config_ = NULL;
|
||||
rtc_sources_ = NULL;
|
||||
stat_ = NULL;
|
||||
app_factory_ = NULL;
|
||||
}
|
||||
|
||||
srs_error_t SrsRtcPlayStream::initialize(ISrsRequest *req, std::map<uint32_t, SrsRtcTrackDescription *> sub_relations)
|
||||
|
|
@ -617,7 +628,7 @@ srs_error_t SrsRtcPlayStream::start()
|
|||
}
|
||||
|
||||
srs_freep(trd_);
|
||||
trd_ = new SrsFastCoroutine("rtc_sender", this, cid_);
|
||||
trd_ = app_factory_->create_coroutine("rtc_sender", this, cid_);
|
||||
|
||||
if ((err = trd_->start()) != srs_success) {
|
||||
return srs_error_wrap(err, "rtc_sender");
|
||||
|
|
|
|||
|
|
@ -64,6 +64,8 @@ class ISrsSrtSourceManager;
|
|||
class ISrsLiveSourceManager;
|
||||
class SrsRtcPublisherNegotiator;
|
||||
class SrsRtcPlayerNegotiator;
|
||||
class ISrsAppFactory;
|
||||
class ISrsCoroutine;
|
||||
|
||||
const uint8_t kSR = 200;
|
||||
const uint8_t kRR = 201;
|
||||
|
|
@ -192,8 +194,20 @@ public:
|
|||
virtual srs_error_t do_request_keyframe(uint32_t ssrc, SrsContextId cid) = 0;
|
||||
};
|
||||
|
||||
// The interface for PLI worker coroutine.
|
||||
class ISrsRtcPliWorker : public ISrsCoroutineHandler
|
||||
{
|
||||
public:
|
||||
ISrsRtcPliWorker();
|
||||
virtual ~ISrsRtcPliWorker();
|
||||
|
||||
public:
|
||||
virtual srs_error_t start() = 0;
|
||||
virtual void request_keyframe(uint32_t ssrc, SrsContextId cid) = 0;
|
||||
};
|
||||
|
||||
// A worker coroutine to request the PLI.
|
||||
class SrsRtcPliWorker : public ISrsCoroutineHandler
|
||||
class SrsRtcPliWorker : public ISrsRtcPliWorker
|
||||
{
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
|
|
@ -247,6 +261,7 @@ SRS_DECLARE_PRIVATE: // clang-format on
|
|||
ISrsExecRtcAsyncTask *exec_;
|
||||
ISrsExpire *expire_;
|
||||
ISrsRtcPacketSender *sender_;
|
||||
ISrsAppFactory *app_factory_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
|
|
@ -257,8 +272,8 @@ SRS_DECLARE_PRIVATE: // clang-format on
|
|||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
SrsContextId cid_;
|
||||
SrsFastCoroutine *trd_;
|
||||
SrsRtcPliWorker *pli_worker_;
|
||||
ISrsCoroutine *trd_;
|
||||
ISrsRtcPliWorker *pli_worker_;
|
||||
|
||||
// clang-format off
|
||||
SRS_DECLARE_PRIVATE: // clang-format on
|
||||
|
|
|
|||
|
|
@ -9,6 +9,6 @@
|
|||
|
||||
#define VERSION_MAJOR 7
|
||||
#define VERSION_MINOR 0
|
||||
#define VERSION_REVISION 97
|
||||
#define VERSION_REVISION 98
|
||||
|
||||
#endif
|
||||
|
|
@ -111,3 +111,39 @@ VOID TEST(ConfigReloadTest, ReloadVhostChunkSize)
|
|||
EXPECT_EQ(1, handler.count_true());
|
||||
handler.reset();
|
||||
}
|
||||
|
||||
VOID TEST(ConfigReloadTest, ReloadAddNewVhost)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
MockReloadHandler handler;
|
||||
MockSrsReloadConfig conf;
|
||||
|
||||
conf.subscribe(&handler);
|
||||
// Start with one vhost
|
||||
HELPER_EXPECT_SUCCESS(conf.mock_parse(_MIN_OK_CONF "vhost ossrs.net { chunk_size 60000; }"));
|
||||
|
||||
// Add a new vhost - should not crash
|
||||
HELPER_EXPECT_SUCCESS(conf.do_reload(_MIN_OK_CONF "vhost ossrs.net { chunk_size 60000; } vhost new_vhost { chunk_size 65536; }"));
|
||||
// Handler should not be triggered for new vhost
|
||||
EXPECT_TRUE(handler.all_false());
|
||||
handler.reset();
|
||||
}
|
||||
|
||||
VOID TEST(ConfigReloadTest, ReloadRemoveVhost)
|
||||
{
|
||||
srs_error_t err = srs_success;
|
||||
|
||||
MockReloadHandler handler;
|
||||
MockSrsReloadConfig conf;
|
||||
|
||||
conf.subscribe(&handler);
|
||||
// Start with two vhosts
|
||||
HELPER_EXPECT_SUCCESS(conf.mock_parse(_MIN_OK_CONF "vhost ossrs.net { chunk_size 60000; } vhost old_vhost { chunk_size 65536; }"));
|
||||
|
||||
// Remove old_vhost - should not crash
|
||||
HELPER_EXPECT_SUCCESS(conf.do_reload(_MIN_OK_CONF "vhost ossrs.net { chunk_size 60000; }"));
|
||||
// Handler should not be triggered for removed vhost
|
||||
EXPECT_TRUE(handler.all_false());
|
||||
handler.reset();
|
||||
}
|
||||
|
|
|
|||
360
trunk/src/utest/srs_utest_rtc_playstream.cpp
Normal file
360
trunk/src/utest/srs_utest_rtc_playstream.cpp
Normal file
|
|
@ -0,0 +1,360 @@
|
|||
//
|
||||
// Copyright (c) 2013-2025 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#include <srs_utest_rtc_playstream.hpp>
|
||||
|
||||
#include <srs_app_rtc_conn.hpp>
|
||||
#include <srs_kernel_error.hpp>
|
||||
#include <srs_utest_app.hpp>
|
||||
#include <srs_utest_app6.hpp>
|
||||
|
||||
// Mock ISrsCoroutine implementation
|
||||
MockCoroutineForPlayStream::MockCoroutineForPlayStream()
|
||||
{
|
||||
start_error_ = srs_success;
|
||||
start_count_ = 0;
|
||||
stop_count_ = 0;
|
||||
interrupt_count_ = 0;
|
||||
}
|
||||
|
||||
MockCoroutineForPlayStream::~MockCoroutineForPlayStream()
|
||||
{
|
||||
srs_freep(start_error_);
|
||||
}
|
||||
|
||||
srs_error_t MockCoroutineForPlayStream::start()
|
||||
{
|
||||
start_count_++;
|
||||
if (start_error_ != srs_success) {
|
||||
return srs_error_copy(start_error_);
|
||||
}
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockCoroutineForPlayStream::stop()
|
||||
{
|
||||
stop_count_++;
|
||||
}
|
||||
|
||||
void MockCoroutineForPlayStream::interrupt()
|
||||
{
|
||||
interrupt_count_++;
|
||||
}
|
||||
|
||||
srs_error_t MockCoroutineForPlayStream::pull()
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
const SrsContextId &MockCoroutineForPlayStream::cid()
|
||||
{
|
||||
return cid_;
|
||||
}
|
||||
|
||||
void MockCoroutineForPlayStream::set_cid(const SrsContextId &cid)
|
||||
{
|
||||
cid_ = cid;
|
||||
}
|
||||
|
||||
void MockCoroutineForPlayStream::reset()
|
||||
{
|
||||
srs_freep(start_error_);
|
||||
start_count_ = 0;
|
||||
stop_count_ = 0;
|
||||
interrupt_count_ = 0;
|
||||
}
|
||||
|
||||
void MockCoroutineForPlayStream::set_start_error(srs_error_t err)
|
||||
{
|
||||
srs_freep(start_error_);
|
||||
start_error_ = srs_error_copy(err);
|
||||
}
|
||||
|
||||
// Mock ISrsAppFactory implementation
|
||||
MockAppFactoryForPlayStream::MockAppFactoryForPlayStream()
|
||||
{
|
||||
mock_coroutine_ = new MockCoroutineForPlayStream();
|
||||
create_coroutine_error_ = srs_success;
|
||||
create_coroutine_count_ = 0;
|
||||
last_coroutine_handler_ = NULL;
|
||||
}
|
||||
|
||||
MockAppFactoryForPlayStream::~MockAppFactoryForPlayStream()
|
||||
{
|
||||
srs_freep(mock_coroutine_);
|
||||
srs_freep(create_coroutine_error_);
|
||||
}
|
||||
|
||||
ISrsFileWriter *MockAppFactoryForPlayStream::create_file_writer()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsFileWriter *MockAppFactoryForPlayStream::create_enc_file_writer()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsFileReader *MockAppFactoryForPlayStream::create_file_reader()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SrsPath *MockAppFactoryForPlayStream::create_path()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
SrsLiveSource *MockAppFactoryForPlayStream::create_live_source()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsOriginHub *MockAppFactoryForPlayStream::create_origin_hub()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsHourGlass *MockAppFactoryForPlayStream::create_hourglass(const std::string &name, ISrsHourGlassHandler *handler, srs_utime_t interval)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsBasicRtmpClient *MockAppFactoryForPlayStream::create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsHttpClient *MockAppFactoryForPlayStream::create_http_client()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsFileReader *MockAppFactoryForPlayStream::create_http_file_reader(ISrsHttpResponseReader *r)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsFlvDecoder *MockAppFactoryForPlayStream::create_flv_decoder()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SRS_RTSP
|
||||
ISrsRtspSendTrack *MockAppFactoryForPlayStream::create_rtsp_audio_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsRtspSendTrack *MockAppFactoryForPlayStream::create_rtsp_video_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ISrsFlvTransmuxer *MockAppFactoryForPlayStream::create_flv_transmuxer()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsMp4Encoder *MockAppFactoryForPlayStream::create_mp4_encoder()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsDvrSegmenter *MockAppFactoryForPlayStream::create_dvr_flv_segmenter()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsDvrSegmenter *MockAppFactoryForPlayStream::create_dvr_mp4_segmenter()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#ifdef SRS_GB28181
|
||||
ISrsGbMediaTcpConn *MockAppFactoryForPlayStream::create_gb_media_tcp_conn()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsGbSession *MockAppFactoryForPlayStream::create_gb_session()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#endif
|
||||
|
||||
ISrsInitMp4 *MockAppFactoryForPlayStream::create_init_mp4()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsFragmentWindow *MockAppFactoryForPlayStream::create_fragment_window()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsFragmentedMp4 *MockAppFactoryForPlayStream::create_fragmented_mp4()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsIpListener *MockAppFactoryForPlayStream::create_tcp_listener(ISrsTcpHandler *handler)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsRtcConnection *MockAppFactoryForPlayStream::create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsFFMPEG *MockAppFactoryForPlayStream::create_ffmpeg(std::string ffmpeg_bin)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsIngesterFFMPEG *MockAppFactoryForPlayStream::create_ingester_ffmpeg()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsCoroutine *MockAppFactoryForPlayStream::create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid)
|
||||
{
|
||||
create_coroutine_count_++;
|
||||
last_coroutine_name_ = name;
|
||||
last_coroutine_handler_ = handler;
|
||||
last_coroutine_cid_ = cid;
|
||||
|
||||
if (create_coroutine_error_ != srs_success) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return mock_coroutine_;
|
||||
}
|
||||
|
||||
ISrsTime *MockAppFactoryForPlayStream::create_time()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsConfig *MockAppFactoryForPlayStream::create_config()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ISrsCond *MockAppFactoryForPlayStream::create_cond()
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void MockAppFactoryForPlayStream::reset()
|
||||
{
|
||||
mock_coroutine_->reset();
|
||||
srs_freep(create_coroutine_error_);
|
||||
create_coroutine_count_ = 0;
|
||||
last_coroutine_name_ = "";
|
||||
last_coroutine_handler_ = NULL;
|
||||
}
|
||||
|
||||
void MockAppFactoryForPlayStream::set_create_coroutine_error(srs_error_t err)
|
||||
{
|
||||
srs_freep(create_coroutine_error_);
|
||||
create_coroutine_error_ = srs_error_copy(err);
|
||||
}
|
||||
|
||||
// Mock ISrsRtcPliWorker implementation
|
||||
MockRtcPliWorkerForPlayStream::MockRtcPliWorkerForPlayStream()
|
||||
{
|
||||
start_error_ = srs_success;
|
||||
start_count_ = 0;
|
||||
request_keyframe_count_ = 0;
|
||||
}
|
||||
|
||||
MockRtcPliWorkerForPlayStream::~MockRtcPliWorkerForPlayStream()
|
||||
{
|
||||
srs_freep(start_error_);
|
||||
}
|
||||
|
||||
srs_error_t MockRtcPliWorkerForPlayStream::start()
|
||||
{
|
||||
start_count_++;
|
||||
if (start_error_ != srs_success) {
|
||||
return srs_error_copy(start_error_);
|
||||
}
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcPliWorkerForPlayStream::request_keyframe(uint32_t ssrc, SrsContextId cid)
|
||||
{
|
||||
request_keyframe_count_++;
|
||||
}
|
||||
|
||||
srs_error_t MockRtcPliWorkerForPlayStream::cycle()
|
||||
{
|
||||
return srs_success;
|
||||
}
|
||||
|
||||
void MockRtcPliWorkerForPlayStream::reset()
|
||||
{
|
||||
srs_freep(start_error_);
|
||||
start_count_ = 0;
|
||||
request_keyframe_count_ = 0;
|
||||
}
|
||||
|
||||
void MockRtcPliWorkerForPlayStream::set_start_error(srs_error_t err)
|
||||
{
|
||||
srs_freep(start_error_);
|
||||
start_error_ = srs_error_copy(err);
|
||||
}
|
||||
|
||||
// Test SrsRtcPlayStream::start() - Basic success scenario
|
||||
VOID TEST(RtcPlayStreamStartTest, StartSuccess)
|
||||
{
|
||||
srs_error_t err;
|
||||
|
||||
// Create mock objects
|
||||
MockRtcAsyncTaskExecutor mock_exec;
|
||||
MockExpire mock_expire;
|
||||
MockRtcPacketSender mock_sender;
|
||||
SrsContextId cid;
|
||||
cid.set_value("test-play-stream-start-cid");
|
||||
|
||||
// Create RTC play stream
|
||||
SrsUniquePtr<SrsRtcPlayStream> play_stream(new SrsRtcPlayStream(&mock_exec, &mock_expire, &mock_sender, cid));
|
||||
|
||||
// Create and inject mock app factory
|
||||
MockAppFactoryForPlayStream mock_factory;
|
||||
play_stream->app_factory_ = &mock_factory;
|
||||
|
||||
// Create and inject mock PLI worker
|
||||
MockRtcPliWorkerForPlayStream *mock_pli_worker = new MockRtcPliWorkerForPlayStream();
|
||||
play_stream->pli_worker_ = mock_pli_worker;
|
||||
|
||||
// Test: First call to start() should succeed
|
||||
HELPER_EXPECT_SUCCESS(play_stream->start());
|
||||
|
||||
// Verify coroutine was created with correct parameters
|
||||
EXPECT_EQ(1, mock_factory.create_coroutine_count_);
|
||||
EXPECT_STREQ("rtc_sender", mock_factory.last_coroutine_name_.c_str());
|
||||
EXPECT_TRUE(mock_factory.last_coroutine_handler_ == play_stream.get());
|
||||
EXPECT_EQ(0, cid.compare(mock_factory.last_coroutine_cid_));
|
||||
|
||||
// Verify coroutine start was called
|
||||
EXPECT_EQ(1, mock_factory.mock_coroutine_->start_count_);
|
||||
|
||||
// Verify PLI worker start was called
|
||||
EXPECT_EQ(1, mock_pli_worker->start_count_);
|
||||
|
||||
// Verify is_started_ flag is set
|
||||
EXPECT_TRUE(play_stream->is_started_);
|
||||
|
||||
// Clean up - set to NULL to avoid double-free
|
||||
play_stream->trd_ = NULL; // Set to NULL before mock_factory is destroyed
|
||||
play_stream->app_factory_ = NULL;
|
||||
play_stream->pli_worker_ = NULL;
|
||||
srs_freep(mock_pli_worker);
|
||||
}
|
||||
127
trunk/src/utest/srs_utest_rtc_playstream.hpp
Normal file
127
trunk/src/utest/srs_utest_rtc_playstream.hpp
Normal file
|
|
@ -0,0 +1,127 @@
|
|||
//
|
||||
// Copyright (c) 2013-2025 The SRS Authors
|
||||
//
|
||||
// SPDX-License-Identifier: MIT
|
||||
//
|
||||
|
||||
#ifndef SRS_UTEST_RTC_PLAYSTREAM_HPP
|
||||
#define SRS_UTEST_RTC_PLAYSTREAM_HPP
|
||||
|
||||
/*
|
||||
#include <srs_utest_rtc_playstream.hpp>
|
||||
*/
|
||||
#include <srs_utest.hpp>
|
||||
|
||||
#include <srs_app_factory.hpp>
|
||||
#include <srs_app_rtc_conn.hpp>
|
||||
#include <srs_kernel_factory.hpp>
|
||||
|
||||
// Mock ISrsCoroutine for testing SrsRtcPlayStream::start()
|
||||
class MockCoroutineForPlayStream : public ISrsCoroutine
|
||||
{
|
||||
public:
|
||||
srs_error_t start_error_;
|
||||
int start_count_;
|
||||
int stop_count_;
|
||||
int interrupt_count_;
|
||||
SrsContextId cid_;
|
||||
|
||||
public:
|
||||
MockCoroutineForPlayStream();
|
||||
virtual ~MockCoroutineForPlayStream();
|
||||
|
||||
public:
|
||||
virtual srs_error_t start();
|
||||
virtual void stop();
|
||||
virtual void interrupt();
|
||||
virtual srs_error_t pull();
|
||||
virtual const SrsContextId &cid();
|
||||
virtual void set_cid(const SrsContextId &cid);
|
||||
|
||||
public:
|
||||
void reset();
|
||||
void set_start_error(srs_error_t err);
|
||||
};
|
||||
|
||||
// Mock ISrsAppFactory for testing SrsRtcPlayStream::start()
|
||||
class MockAppFactoryForPlayStream : public ISrsAppFactory
|
||||
{
|
||||
public:
|
||||
MockCoroutineForPlayStream *mock_coroutine_;
|
||||
srs_error_t create_coroutine_error_;
|
||||
int create_coroutine_count_;
|
||||
std::string last_coroutine_name_;
|
||||
ISrsCoroutineHandler *last_coroutine_handler_;
|
||||
SrsContextId last_coroutine_cid_;
|
||||
|
||||
public:
|
||||
MockAppFactoryForPlayStream();
|
||||
virtual ~MockAppFactoryForPlayStream();
|
||||
|
||||
public:
|
||||
// ISrsAppFactory interface methods
|
||||
virtual ISrsFileWriter *create_file_writer();
|
||||
virtual ISrsFileWriter *create_enc_file_writer();
|
||||
virtual ISrsFileReader *create_file_reader();
|
||||
virtual SrsPath *create_path();
|
||||
virtual SrsLiveSource *create_live_source();
|
||||
virtual ISrsOriginHub *create_origin_hub();
|
||||
virtual ISrsHourGlass *create_hourglass(const std::string &name, ISrsHourGlassHandler *handler, srs_utime_t interval);
|
||||
virtual ISrsBasicRtmpClient *create_rtmp_client(std::string url, srs_utime_t cto, srs_utime_t sto);
|
||||
virtual ISrsHttpClient *create_http_client();
|
||||
virtual ISrsFileReader *create_http_file_reader(ISrsHttpResponseReader *r);
|
||||
virtual ISrsFlvDecoder *create_flv_decoder();
|
||||
#ifdef SRS_RTSP
|
||||
virtual ISrsRtspSendTrack *create_rtsp_audio_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
virtual ISrsRtspSendTrack *create_rtsp_video_send_track(ISrsRtspConnection *session, SrsRtcTrackDescription *track_desc);
|
||||
#endif
|
||||
virtual ISrsFlvTransmuxer *create_flv_transmuxer();
|
||||
virtual ISrsMp4Encoder *create_mp4_encoder();
|
||||
virtual ISrsDvrSegmenter *create_dvr_flv_segmenter();
|
||||
virtual ISrsDvrSegmenter *create_dvr_mp4_segmenter();
|
||||
#ifdef SRS_GB28181
|
||||
virtual ISrsGbMediaTcpConn *create_gb_media_tcp_conn();
|
||||
virtual ISrsGbSession *create_gb_session();
|
||||
#endif
|
||||
virtual ISrsInitMp4 *create_init_mp4();
|
||||
virtual ISrsFragmentWindow *create_fragment_window();
|
||||
virtual ISrsFragmentedMp4 *create_fragmented_mp4();
|
||||
virtual ISrsIpListener *create_tcp_listener(ISrsTcpHandler *handler);
|
||||
virtual ISrsRtcConnection *create_rtc_connection(ISrsExecRtcAsyncTask *exec, const SrsContextId &cid);
|
||||
virtual ISrsFFMPEG *create_ffmpeg(std::string ffmpeg_bin);
|
||||
virtual ISrsIngesterFFMPEG *create_ingester_ffmpeg();
|
||||
|
||||
// ISrsKernelFactory interface methods
|
||||
virtual ISrsCoroutine *create_coroutine(const std::string &name, ISrsCoroutineHandler *handler, SrsContextId cid);
|
||||
virtual ISrsTime *create_time();
|
||||
virtual ISrsConfig *create_config();
|
||||
virtual ISrsCond *create_cond();
|
||||
|
||||
public:
|
||||
void reset();
|
||||
void set_create_coroutine_error(srs_error_t err);
|
||||
};
|
||||
|
||||
// Mock ISrsRtcPliWorker for testing SrsRtcPlayStream::start()
|
||||
class MockRtcPliWorkerForPlayStream : public ISrsRtcPliWorker
|
||||
{
|
||||
public:
|
||||
srs_error_t start_error_;
|
||||
int start_count_;
|
||||
int request_keyframe_count_;
|
||||
|
||||
public:
|
||||
MockRtcPliWorkerForPlayStream();
|
||||
virtual ~MockRtcPliWorkerForPlayStream();
|
||||
|
||||
public:
|
||||
virtual srs_error_t start();
|
||||
virtual void request_keyframe(uint32_t ssrc, SrsContextId cid);
|
||||
virtual srs_error_t cycle();
|
||||
|
||||
public:
|
||||
void reset();
|
||||
void set_start_error(srs_error_t err);
|
||||
};
|
||||
|
||||
#endif
|
||||
Loading…
Reference in New Issue
Block a user