1. Refer this commit, which contains the web demo to capture screen as
video stream through RTC.
2. Copy the `trunk/research/players/whip.html` and
`trunk/research/players/js/srs.sdk.js` to replace the `develop` branch
source code.
3. `./configure && make`
4. `./objs/srs -c conf/rtc2rtmp.conf`
5. open `http://localhost:8080/players/whip.html?schema=http`
6. check `Screen` radio option.
7. click `publish`, then check the screen to share.
8. play the rtmp live stream: `rtmp://localhost/live/livestream`
9. check the video stuttering.
When capture screen by the chrome web browser, which send RTP packet
with empty payload frequently, then all the cached RTP packets are
dropped before next key frame arrive in this case.
The OBS screen stream and camera stream do not have such problem.
><img width="581" alt="Screenshot 2024-08-28 at 2 49 46 PM"
src="https://github.com/user-attachments/assets/9557dbd2-c799-4dfd-b336-5bbf2e4f8fb8">
---------
Co-authored-by: winlin <winlinvip@gmail.com>
The heartbeat of SRS is a timer that requests an HTTP URL. We can use
this heartbeat to report the necessary information for registering the
backend server with the proxy server.
```text
SRS(backend) --heartbeat---> Proxy server
```
A proxy server is a specialized load balancer for media servers. It
operates at the application level rather than the TCP level. For more
information about the proxy server, see issue #4158.
Note that we will merge this PR into SRS 5.0+, allowing the use of SRS
5.0+ as the backend server, not limited to SRS 7.0. However, the proxy
server is introduced in SRS 7.0.
It's also possible to implement a registration service, allowing you to
use other media servers as backend servers. For example, if you gather
information about an nginx-rtmp server and register it with the proxy
server, the proxy will forward RTMP streams to nginx-rtmp. The backend
server is not limited to SRS.
---------
Co-authored-by: Jacob Su <suzp1984@gmail.com>
1. Should always stop coroutine before close fd, see #511, #1784
2. When edge forwarder coroutine quit, always set the error code.
3. Do not unpublish if invalid state.
---------
Co-authored-by: Jacob Su <suzp1984@gmail.com>
Fix#4037 SRS should not send the publish start message
`onStatus(NetStream.Publish.Start)` if hooks fail, which causes OBS to
repeatedly reconnect.
Note that this fix does not send an RTMP error message when publishing
fails, because neither OBS nor FFmpeg process this specific error
message; they only display a general error.
Apart from the order of messages, nothing else has been changed.
Previously, we sent the publish start message
`onStatus(NetStream.Publish.Start)` before the HTTP hook `on_publish`;
now, we have modified it to send this message after the HTTP hook.
Fix#3967 There is an API `SSL_use_certificate_chain_file`, which can load the
certification chain and also single certificate.
---------
Co-authored-by: winlin <winlinvip@gmail.com>
1. When converting RTC to RTMP, it is necessary to synchronize the audio
and video timestamps. When the synchronization status changes, whether
it is unsynchronized or synchronized, print logs to facilitate
troubleshooting of such issues.
2. Chrome uses the STAP-A packet, which means a single RTP packet
contains SPS/PPS information. OBS WHIP, on the other hand, sends SPS and
PPS in separate RTP packets. Therefore, SPS and PPS are in two
independent RTP packets, and SRS needs to cache these two packets.
---------
Co-authored-by: john <hondaxiao@tencent.com>
For WebRTC:
when player before publisher, it will happen track pt didn't change.
- At source change step, change track pt
---------
Co-authored-by: mingche.tsai <w41203208.work@gmail.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>
In an SDK that supports RTC Opus stereo, the parameter "stereo=1" may
appear. SRS (Spatial Reference System) needs to handle this correctly
and return an answer to enable WebRTC stereo support.
---------
`TRANS_BY_GPT4`
Security is the built-in IP whitelist feature of SRS, which allows and
denies certain IP and IP range users. Previously, it only supported
RTMP, but this PR now supports HTTP-FLV, HLS, WebRTC, SRT, and other
protocols.
See https://ossrs.io/lts/en-us/docs/v6/doc/security as example.
---------
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>
In pure audio mode, there are no keyframes. Therefore, we can only rely
on the length of the slice to determine whether it should be output.
`hls_aof_ratio` is the coefficient that, once reached, will generate a
new slice.
In scenarios with video, if the `hls_aof_ratio` is too small, for
example 1.2, and the GOP (Group of Pictures) is 10 seconds, then a slice
will definitely be generated at 12 seconds. At this point, if there are
no keyframes, it will cause the next slice to start with a non-keyframe.
A safer coefficient is twice the GOP (Group of Pictures). This way, it
won't trigger incorrectly and prevent the individual transcoding of a ts
segment file.
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
When converting between AAC and Opus formats (aac2opus or opus2aac), the
`av_frame_get_buffer` API is frequently called.
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.
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>
SRS supports TCP WebRTC by reading 2 bytes of length, like `read(buf,
2)`. However, in some cases, it might receive 1 byte, causing subsequent
data to be incorrect and making it unable to push or play streams.
---------
Co-authored-by: john <hondaxiao@tencent.com>
Checking the HTTPS API or UDP connectivity for WHIP tests can be
difficult. For example, if the UDP port isn't available but the API is
fine, OBS only says it can't connect to the server. It's hard to see the
HTTPS API response or check if the UDP port is available.
This feature lets you set the ice username and password in SRS. You can
then send a STUN request using nc and see the response, making it easier
to check UDP port connectivity.
1. Use curl to test the WHIP API, including ice-frag and ice-pwd
queries.
2. Use nc to send a STUN binding request to test UDP connectivity.
3. If both the API and UDP are working, you should get a STUN response.
---------
Co-authored-by: john <hondaxiao@tencent.com>
When using Docker, logs are usually printed to console (stdout and
stderr). However, since Docker detection occurs late, after log
initialization, the default log output may be incorrect. In Docker, logs
may still be written to a file instead of the console as expected.
Additionally, the Dockerfile has been improved with a new environment
variable `SRS_IN_DOCKER=on` to clearly indicate a Docker environment. If
automatic Docker detection fails, the configuration will be read, and
this variable will correctly inform SRS that it's in a Docker
environment.
Lastly, the default configuration values have been improved for Docker
environments. By default, `SRS_LOG_TANK=console` and daemon mode is
disabled.
---------
Co-authored-by: john <hondaxiao@tencent.com>
The fix is for the DH_set_length error. As shown in lines 2-5, OpenSSL
3.0 added a check for length, which allowed this issue to be exposed.
```
1 if (dh->params.q == NULL) {
2 /* secret exponent length, must satisfy 2^(l-1) <= p */
3 if (dh->length != 0
4 && dh->length >= BN_num_bits(dh->params.p))
5 goto err;
6 l = dh->length ? dh->length : BN_num_bits(dh->params.p) - 1;
7 if (!BN_priv_rand_ex(priv_key, l, BN_RAND_TOP_ONE,
8 BN_RAND_BOTTOM_ANY, 0, ctx))
9 goto err;
... ...
}
```
---------
Co-authored-by: john <hondaxiao@tencent.com>
Please see https://github.com/ossrs/srs/issues/3803 for detail:
1. When using FFmpeg with the `-map 0` option, there may be a 4-byte
timecode in the AMF0 Data.
2. SRS should be able to handle this packet without causing a parsing
error, as it's generally expected to be an AMF0 string, not a 4-byte
timecode.
3. Disregard the timecode since SRS doesn't utilize it.
See [Error submitting a packet to the muxer: Broken pipe, Error muxing a
packet](https://trac.ffmpeg.org/ticket/10565)
---------
Co-authored-by: john <hondaxiao@tencent.com>
ISO_IEC_14496-10-AVC-2012.pdf, page 65
7.4.1.1 Encapsulation of an SODB within an RBSP (informative)
... 00 00 03 xx, the 03 byte should be drop where xx represents any 2
bit pattern: 00, 01, 10, or 11.
---------
Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: winlin <winlin@vip.126.com>
During a Reload, several stages will be passed through:
1. Parsing new configurations: Parse.
2. Transforming configurations: Transform.
3. Applying configurations: Apply.
Previously, any error at any stage would result in a direct exit, making
the system completely dependent on configuration checks:
```bash
./objs/srs -c conf/srs.conf -t
echo $?
```
Optimized to: If an error occurs before applying the configuration, it
can be ignored. If an error occurs during the application of the
configuration, some of the configuration may have already taken effect,
leading to unpredictable behavior, so SRS will exit directly.
Added a new HTTP API to query the result of the reload.
```nginx
http_api {
enabled on;
raw_api {
enabled on;
allow_reload on;
}
}
```
```bash
curl http://localhost:1985/api/v1/raw?rpc=reload-fetch
```
```json
{
"code": 0,
"data": {
"err": 0,
"msg": "Success",
"state": 0,
"rid": "0s6y0n9"
}
}
{
"code": 0,
"data": {
"err": 1023,
"msg": "code=1023(ConfigInvalid) : parse file : parse buffer containers/conf/srs.release-local.conf : root parse : parse dir : parse include buffer containers/data/config/srs.vhost.conf : read token, line=0, state=0 : line 3: unexpected end of file, expecting ; or \"}\"",
"state": 1,
"rid": "0g4z471"
}
}
```
This way, you can know if the last reload of the system was successful.
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
SrsContextId object creation can be improved on `srs_protocol_log.cpp`,
No need to create one, then assign it back. It seems a common mistake
for Cpp programmers.
---------
Co-authored-by: john <hondaxiao@tencent.com>
on_hls and hls_dispose are two coroutines, with potential race
conditions. That is, during on_hls, if the API Server being accessed is
slower, it will switch to the hls_dispose coroutine to start cleaning
up. However, when the API Server is processing the slice, a situation
may occur where the slice does not exist, resulting in the following
log:
```
[2023-08-22 12:03:20.309][WARN][40][x5l48q7b][11] ignore task failed code=4005(HttpStatus)(Invalid HTTP status code) : callback on_hls http://localhost:2024/terraform/v1/hooks/srs/hls : http: post http://localhost:2024/terraform/v1/hooks/srs/hls with {"server_id":"vid-5d7dxn8","service_id":"cu153o7g","action":"on_hls","client_id":"x5l48q7b","ip":"172.17.0.1","vhost":"__defaultVhost__","app":"live","tcUrl":"srt://172.17.0.2/live","stream":"stream-44572-2739617660809856576","param":"secret=1ed8e0ffbc53439c8fc8da30ab8c19f0","duration":4.57,"cwd":"/usr/local/srs-stack/platform","file":"./objs/nginx/html/live/stream-44572-2739617660809856576-1.ts","url":"live/stream-44572-2739617660809856576-1.ts","m3u8":"./objs/nginx/html/live/stream-44572-2739617660809856576.m3u8","m3u8_url":"live/stream-44572-2739617660809856576.m3u8","seq_no":1,"stream_url":"/live/stream-44572-2739617660809856576","stream_id":"vid-0n9zoz3"}, status=500, res=invalid ts file ./objs/nginx/html/live/stream-44572-2739617660809856576-1.ts: stat ./objs/nginx/html/live/stream-44572-2739617660809856576-1.ts: no such file or directory
thread [40][x5l48q7b]: call() [./src/app/srs_app_hls.cpp:122][errno=11]
thread [40][x5l48q7b]: on_hls() [./src/app/srs_app_http_hooks.cpp:401][errno=11]
thread [40][x5l48q7b]: do_post() [./src/app/srs_app_http_hooks.cpp:638][errno=11]
[error] 2023/08/22 12:03:20.076984 [52][1001] Serve /terraform/v1/hooks/srs/hls failed, err is stat ./objs/nginx/html/live/stream-44572-2739617660809856576-1.ts: no such file or directory
invalid ts file ./objs/nginx/html/live/stream-44572-2739617660809856576-1.ts
main.handleOnHls.func1.1
/g/platform/srs-hooks.go:684
main.handleOnHls.func1
/g/platform/srs-hooks.go:720
net/http.HandlerFunc.ServeHTTP
/usr/local/go/src/net/http/server.go:2084
net/http.(*ServeMux).ServeHTTP
/usr/local/go/src/net/http/server.go:2462
net/http.serverHandler.ServeHTTP
/usr/local/go/src/net/http/server.go:2916
net/http.(*conn).serve
/usr/local/go/src/net/http/server.go:1966
runtime.goexit
/usr/local/go/src/runtime/asm_amd64.s:1571
```
Similarly, when stopping the stream, on_hls will also be called to
handle the last slice. If the API Server is slower at this time, it will
enter hls_dispose and call unpublish repeatedly. Since the previous
unpublish is still blocked in on_hls, the following interference log
will appear:
```
[2023-08-22 12:03:18.748][INFO][40][6498088c] hls cycle to dispose hls /live/stream-44572-2739617660809856576, timeout=10000000ms
[2023-08-22 12:03:18.752][WARN][40][6498088c][115] flush audio ignored, for segment is not open.
[2023-08-22 12:03:18.752][WARN][40][6498088c][115] ignore the segment close, for segment is not open.
```
Although this log will not cause problems, it can interfere with
judgment.
The solution is to add an 'unpublishing' status. If it is in the
'unpublishing' status, then do not clean up the slices.
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
SRS supports including another configuration in the include package.
When generating configurations, we can only generate the changed
configurations, while the unchanged configurations are in the fixed
files, for example:
```nginx
listen 1935;
include server.conf;
```
In `server.conf`, we can manage the changing configurations with the
program:
```nginx
http_api { enabled on; }
```
However, during system initialization, we often create an empty
`server.conf`, and the content is generated only after the program
starts, so `server.conf` might be an empty file. This also makes it
convenient to use a script to confirm the existence of this file:
```bash
touch server.conf
```
Currently, SRS does not support empty configurations and will report an
error. This PR is to solve this problem, making it more convenient to
use include.
`TRANS_BY_GPT4`
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
When reloading HLS, it directly operates unpublish and publish. At this
time, if HLS is pushed, an exception may occur.
The reason is that these two coroutines operated on the HLS object at
the same time, causing a null pointer.
Solution: Use asynchronous reload. During reload, only set variables and
let the message processing coroutine implement the reload.
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: chundonglinlin <chundonglinlin@163.com>