To manage an object:
```cpp
// Before
MyClass* ptr = new MyClass();
SrsAutoFree(MyClass, ptr);
ptr->do_something();
// Now
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
```
To manage an array of objects:
```cpp
// Before
char* ptr = new char[10];
SrsAutoFreeA(char, ptr);
ptr[0] = 0xf;
// Now
SrsUniquePtr<char[]> ptr(new char[10]);
ptr[0] = 0xf;
```
In fact, SrsUniquePtr is a limited subset of SrsAutoFree, mainly
managing pointers and arrays. SrsUniquePtr is better than SrsAutoFree
because it has the same API to standard unique ptr.
```cpp
SrsUniquePtr<MyClass> ptr(new MyClass());
ptr->do_something();
MyClass* p = ptr.get();
```
SrsAutoFree actually uses a pointer to a pointer, so it can be set to
NULL, allowing the pointer's value to be changed later (this usage is
different from SrsUniquePtr).
```cpp
// OK to free ptr correctly.
MyClass* ptr;
SrsAutoFree(MyClass, ptr);
ptr = new MyClass();
// Crash because ptr is an invalid pointer.
MyClass* ptr;
SrsUniquePtr<MyClass> ptr(ptr);
ptr = new MyClass();
```
Additionally, SrsAutoFreeH can use specific release functions, which
SrsUniquePtr does not support.
---------
Co-authored-by: Jacob Su <suzp1984@gmail.com>
1. fix redundant null check, there is no potential risks by the way,
just redundant null check.
2. Potential use pointer after free, that's not true. So we can ignore
this one, or find a way to make stupid security tool happy.
---------
Co-authored-by: winlin <winlinvip@gmail.com>
1. Add live benchmark support in srs-bench, which only connects and
disconnects without any media transport, to test source creation and
disposal and verify source memory leaks.
2. SmartPtr: Support cleanup of HTTP-FLV stream. Unregister the HTTP-FLV
handler for the pattern and clean up the objects and resources.
3. Support benchmarking RTMP/SRT with srs-bench by integrating the gosrt
and oryx RTMP libraries.
4. Refine SRT and RTC sources by using a timer to clean up the sources,
following the same strategy as the Live source.
---------
Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: Jacob Su <suzp1984@gmail.com>
Detail change log:
1. [Simple,Refactor] Remove member fields of http entry, etc.
e34b3d3aa4
2. [Ignore] Rename source to live_source.
846f95ec96
3. [Ignore] Use directly ptr in consumer.
d38af021ad
4. [Complex, Important] Use shared ptr for live source.
88f922413a
The object relationship:

---
Co-authored-by: Jacob Su <suzp1984@gmail.com>
The object relations:

Session manages SIP and Media object using shared resource or shared
ptr. Note that I actually use SrsExecutorCoroutine to delete the object
when each coroutine is done, because there is always a dedicate
coroutine for each object.
For SIP and Media object, they directly use the session by raw pointer,
it's safe because session always live longer than session and media
object.
---
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>
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>
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>
Description
A crash occurs when a forward relay connection has not been established
and an unpublish event is triggered simultaneously. For instance, if DVR
and forward are configured with a specified DVR path that already
exists, initiating a stream will trigger a crash.
Objective
Fix the crash caused by the forward mechanism.
Additional Information
For detailed reproduction steps, please refer to issue #3901.
---------
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 `ffmpeg-opus` tool allows you to control the delay using the
`opus_delay` option. The minimum delay can be set to 2.5ms. However, in
practice, you cannot set it this low. You need to set at least 10 frames
to allow the audio encoder to lookahead. Otherwise, the sound will be
distorted.
---------
Co-authored-by: chundonglinlin <chundonglinlin@163.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>
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>
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>
1. The comment on the ratio configuration says it can affect the slice
duration, but there is no effect after configuring it.
2. The default hls_td_ratio is 1.5, and after setting it to 1, the
duration is still slightly more than 10 seconds.
3. Even if the GOP is an integer, like 1 second, the slice is still a
non-integer, like 0.998 seconds, which seems a bit unreliable.
4. In the duration of the TS in the m3u8 file, it is one frame less than
the duration of the slice.
5. Set hls_dispose to 120s to dispose HLS files when no stream.
6. Use docker.conf for docker.
Before this patch:
```
#EXTINF:10.983, no desc
livestream-0.ts?hls_ctx=3p095hq0
```
After this patch:
```
#EXTINF:10.000, no desc
livestream-0.ts?hls_ctx=3p095hq0
```
Note: If the fragment is set to 10 seconds, but the GOP size cannot be
divided by 10, such as not 1, 2, 5, or 10, then the duration of ts will
still be more than 10 seconds.
---------
Co-authored-by: john <hondaxiao@tencent.com>
When I compile on OpenHarmony, I encounter an error at the
pthread_setname_np function:
```
./src/app/srs_app_threads.cpp:53:10: error: functions that differ only in their return type cannot be overloaded
void pthread_setname_np(pthread_t trd, const char* name) {
/data/local/ohos-sdk/linux/native/llvm/bin/../../sysroot/usr/include/pthread.h:379:5: note: previous declaration is here
int pthread_setname_np(pthread_t, const char *);
```
Our libc is using musl-libc and has no defined __GLIBC__, so we wanted
to add a judgment that __GLIBC__ already defined.
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>
When the srs have multiple pps in hevc.the srs can't parse for this.
problem fixed this #3604
---------
Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: john <hondaxiao@tencent.com>
When accessing the SRS Stack, you should log in and use a token for each
request, or utilize the HTTP API with a secret Bearer token included in
every request. The SRS Stack HTTP API proxies both /api/v1 and /rtc/v1
to the SRS HTTP API while ensuring secure authentication. Additionally,
there is a console in the SRS Stack that requires the same token to
request the SRS Stack HTTP API, which is then proxied to the SRS HTTP
API.
The SRS Stack runs SRS with the HTTP API listening at 127.0.0.1:1985 on
the local loopback interface, allowing only the SRS Stack to access it
without authentication. All other users must login and access the SRS
Stack through its interface, rather than directly accessing the SRS HTTP
API within the SRS Stack.
---------
Co-authored-by: panda <542638787@qq.com>
remove unreachable links by python scripts:
```
def is_delete_issue(link):
try:
response = requests.get(link)
except RequestException as e:
print(f"An error occurred while trying to get the link: {e}")
return False
return "This issue has been deleted." in response.text
def remove_unreachable_links(dir):
string_to_search = re.compile(r'// @see https://github\.com/ossrs/srs/issues/.*')
file_list = util.find_files_with_extension(dir, ".cpp", True)
for file in file_list:
lines = []
with open(file, "r", encoding="utf-8") as f:
lines = f.readlines()
with open(file, "w", encoding="utf-8", newline="\n") as f:
for line in lines:
if string_to_search.search(line):
result = re.search(r'https://github\.com/ossrs/srs/issues/\d+', line)
if result:
link = result.group()
if is_delete_issue(link):
print("is_delete_issue link: file: %s, line: %s" % (file, line))
continue
f.write(line)
if __name__ == "__main__":
remove_unreachable_links("srs/trunk/src/")
```
## Reload Error Ignore
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 $?
#0
```
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.
## Reload Fetch API
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>
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>