Commit Graph

8709 Commits

Author SHA1 Message Date
winlin
0a4be9749d Release v6.0-b3, 6.0 beta3, v6.0.183, 170957 lines. v6.0-b3 2025-11-03 10:35:45 -05:00
OSSRS-AI
e82dc112e7 Bridge: Fix heap-use-after-free in SrsCompositeBridge iterator. v6.0.183 (#4535) 2025-10-21 07:35:44 -04:00
Haibo Chen(陈海博)
fcb2992230 HLS: Fix a iterator bug in hls_ctx cleanup function. v6.0.182 (#4534)
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-10-17 07:20:42 -04:00
winlin
54f5048c2a Relase v6.0-b2, 6.0 beta2, v6.0.181, 170948 lines. v6.0-b2 2025-10-16 10:20:12 -04:00
winlin
22e71a39e7 Disable sanitizer by default to fix memory leak. #4364 2025-10-14 20:30:28 -04:00
Winlin
ac868852e4 SRT: Support configurable default_streamid option. v6.0.180 (#4515)
Add a new default_streamid configuration option for the SRT server to
allow customization of the default streamid used when SRT clients
connect without setting the SRTO_STREAMID socket option.

When SRT clients (like VLC) connect without properly setting the
SRTO_STREAMID socket option, SRS previously used a hardcoded default
value of "#!::r=live/livestream,m=publish". This caused conflicts when:

1. A publisher connects without setting streamid (uses default publish
mode)
2. A player tries to connect without setting streamid (also uses default
publish mode)
3. The player gets a "Stream already exists or busy" error because both
are trying to publish

Start SRS with default stream id as viewer:

```bash
./objs/srs -c conf/srt.vlc.conf
```

Publish SRT stream by FFmpeg:

```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'
```

Play SRT stream by ffplay:

```bash
ffplay 'srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=request'
```

Play SRT stream by VLC:

```
 Correct - Use simple URL without streamid parameter:
srt://127.0.0.1:10080

 Wrong - VLC doesn't support streamid parameter:
srt://127.0.0.1:10080?streamid=#!::r=live/livestream,m=request
```

---
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-10-01 21:25:39 -04:00
Winlin
32f78845fe For Edge, only support RTMP or HTTP-FLV. 6.0.179 (#4512) 2025-09-27 18:19:12 -04:00
winlin
31c0ff8815 Fix WHIP source state with transcoding bug. v6.0.179 (#4495) 2025-09-21 08:14:11 -04:00
winlin
f22a5db38a Fix WHIP with transcoding bug. v6.0.178 (#4495) 2025-09-20 22:22:34 -04:00
winlin
e325eec008 Make 6.0 as stable release. 2025-09-16 07:10:44 -04:00
winlin
4da2f3b52c Remove windows/cygwin64 binary from release. v6.0-b1 2025-09-15 20:59:39 -04:00
winlin
3a390f0498 SRS 6 is stable now. 2025-09-15 11:10:51 -04:00
winlin
a591827ef6 Release v6.0-b1, 6.0 beta1, v6.0.177, 170611 lines. 2025-09-15 11:07:42 -04:00
Winlin
3c80544958 RTC2RTMP: Fix sequence number wraparound assertion crashes. v6.0.177 (#4491)
The issue occurred when srs_rtp_seq_distance(start, end) + 1 resulted in
values <= 0
due to sequence number wraparound (e.g., when end < start). This caused
assertion
failures and server crashes.

SrsRtcFrameBuilder::check_frame_complete(): Added validation to return
false
  for invalid sequence ranges instead of asserting.

However, it maybe cause converting RTC to RTMP stream failure, because
this issue
should be caused by the problem of sequence number of RTP, which means
there potentially
be stream problem in RTC stream. Even so, changing assert to warning
logs is better,
because SRS should not crash when stream is corrupt.

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
2025-09-15 10:55:09 -04:00
winlin
c20bce9870 RTX: Fix race condition for timer. v6.0.176 (#4470) (#4474) 2025-09-05 10:03:39 -04:00
Jacob Su
c1a8a5f753 RTC: Fix null pointer crash in RTC2RTMP when start packet is missing. v6.0.175 (#4451)
Try to fix #4450 

## Cause

The SRS transcode rtp packets, whose sequence number in range [start,
end], to one rtmp packet, but when the first rtp packet is empty, then
this crash happens.

check #4450 for details.

## Impact

5.0release and 6.0release branch.
develop branch already has its own solution.

So this PR is targeting to **6.0release**.

## Solution

find the first not empty rtp packet in seq range [start, end].

---------

Co-authored-by: OSSRS-AI <winlinam@gmail.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2025-08-26 18:42:50 -04:00
Jacob Su
2ab3937a68 fix err memory leak in rtc to rtmp bridge. v6.0.174 (#4441)
1. print the error messages before dismiss it;
2. free the err to avoid memory leak;

found this issue when research #4434 .

 1. develop
 2. 5.0release
 3. 6.0release

---------

Co-authored-by: winlin <winlinvip@gmail.com>
2025-08-16 07:58:29 -06:00
Jacob Su
ebc9821ac9 Fix: Remove redundant enabled checks in HLS/DASH cleanup to prevent resource leaks. v6.0.173 (#4161)
HLS and DASH components had redundant `enabled` flag checks in their
`cycle()` and `cleanup_delay()` methods that prevented proper cleanup of
files when components were disabled. This created a race condition
where:

1. Stream stops publishing and HLS/DASH components get disabled
2. `cycle()` returns early without performing disposal operations
3. `cleanup_delay()` returns 0 instead of configured disposal timeout
4. Source cleanup doesn't wait long enough for file disposal
5. HLS/DASH files remain on disk without proper cleanup

The `enabled` flag should control processing of **new incoming
streams**, but should NOT prevent **cleanup of existing files** from
previously enabled streams.

Remove redundant `enabled` checks from:
- `SrsHls::cycle()` and `SrsDash::cycle()` - Allow disposal logic to run
even when disabled
- `SrsHls::cleanup_delay()` and `SrsDash::cleanup_delay()` - Always
return proper disposal timeout

---------

Co-authored-by: winlin <winlinvip@gmail.com>
2025-08-14 06:56:59 -06:00
winlin
1a9b506c45 Relase v6.0-b0, 6.0 beta0, v6.0.172, 170417 lines. 2025-08-12 10:47:09 -04:00
Jacob Su
8e573644c1 MP4 DVR: Fix audio/video synchronization issues in WebRTC recordings. v6.0.172 (#4230)
Fixes #3993 - WebRTC streams recorded to MP4 via DVR exhibit audio/video
synchronization issues, with audio typically ahead of video. **Note:
This issue is specific to MP4 format; FLV recordings are not affected.**

When WebRTC streams are converted to RTMP and then muxed to MP4, the
audio and video tracks may start at different timestamps. The MP4 muxer
was not accounting for this timing offset between the first audio and
video samples in the STTS (Sample Time-to-Sample) table, causing the
tracks to be misaligned in the final MP4 file.

Introduces `SrsMp4DvrJitter` class specifically for MP4 audio/video
synchronization:

- **Timestamp Tracking**: Records the DTS of the first audio and video
samples
- **Offset Calculation**: Computes the timing difference between track
start times
- **MP4 STTS Correction**: Sets appropriate `sample_delta` values in the
MP4 STTS table to maintain proper A/V sync

- Added `SrsMp4DvrJitter` class in `srs_kernel_mp4.hpp/cpp`
- Integrated jitter correction into `SrsMp4SampleManager::write_track()`
for MP4 format only
- Added comprehensive unit tests covering various timing scenarios
- **Scope**: Changes are isolated to MP4 kernel code and do not affect
FLV processing

This fix ensures that MP4 DVR recordings from WebRTC streams maintain
proper audio/video synchronization regardless of the relative timing of
the first audio and video frames, while leaving FLV format processing
unchanged.

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
v6.0-b0
2025-08-12 09:58:40 -04:00
Winlin
02952f25a2 AI: HTTP-FLV: Fix heap-use-after-free crash during stream unmount. v6.0.171 (#4432)
Fixes a critical heap-use-after-free crash in HTTP-FLV streaming that
occurs when a client requests a stream while it's being unmounted
asynchronously.

- **Issue**: #4429 - Heap-use-after-free crash in
`SrsLiveStream::serve_http()`
- **Root Cause**: Race condition between coroutines in single-threaded
SRS server:
1. **Coroutine A**: HTTP client requests FLV stream → `serve_http()`
starts
2. **Coroutine B**: RTMP publisher disconnects → triggers async stream
destruction
3. **Async Worker**: Destroys `SrsLiveStream` object while Coroutine A
is yielded
  4. **Coroutine A**: Resumes and accesses freed memory → **CRASH**

1. **Early viewer registration**: Add HTTP connection to `viewers_` list
immediately in `serve_http()` before any I/O operations that could yield
2. **Lifecycle protection**: Split `serve_http()` into wrapper and
implementation to ensure proper viewer management
3. **Stream availability checks**: Add fast checks for stream disposal
state before critical operations
4. **Improved error handling**: Convert warnings to fatal errors when
trying to free alive streams

- **`SrsLiveStream::serve_http()`**: Now immediately registers viewer
and delegates to `serve_http_impl()`
- **`SrsLiveStream::serve_http_impl()`**: Contains the actual HTTP
serving logic
- **`SrsHttpStreamDestroy::call()`**: Enhanced error handling and longer
wait timeout
- **Stream state validation**: Added checks for `entry->enabled` before
proceeding with stream operations

Fixes #4429
2025-08-11 18:59:52 -04:00
Shengming Yuan
aeca022165 Allow Forward to be configured with Env Var. v6.0.170 (#4245)
Allow Env Var to control forwarding function.

By AI:

* [AI: Add utests for
PR.](1b978d19a5)

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2025-07-28 08:39:32 -04:00
Haibo Chen(陈海博)
45090ce4fc Fix H.264 B-frame detection logic to comply with specification. v6.0.169 (#4414)
For H.264, only when the NAL Type is 1, 2, 3, or 4 is it possible for
B-frames to be present; that is, non-IDR pictures and slice data.

The current `SrsVideoFrame::parse_avc_bframe()` function uses incorrect
logic to determine if a NALU can contain B-frames. The original
implementation only checked for specific NALU types (IDR, SPS, PPS) to
mark as non-B-frames, but this approach misses many other NALU types
that cannot contain B-frames according to the H.264 specification.

According to H.264 specification (ISO_IEC_14496-10-AVC-2012.pdf, Table
7-1), B-frames can **only** exist in these specific NALU types:
- Type 1: Non-IDR coded slice (`SrsAvcNaluTypeNonIDR`)
- Type 2: Coded slice data partition A (`SrsAvcNaluTypeDataPartitionA`)
- Type 3: Coded slice data partition B (`SrsAvcNaluTypeDataPartitionB`)
- Type 4: Coded slice data partition C (`SrsAvcNaluTypeDataPartitionC`)

All other NALU types (IDR=5, SEI=6, SPS=7, PPS=8, AUD=9, etc.) cannot
contain B-frames by definition.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2025-07-10 09:33:42 -04:00
Haibo Chen(陈海博)
014812ea9b Transcode: Bugfix: Fix loop transcoding with host. #3516. v6.0.168 (#4325)
for issue: https://github.com/ossrs/srs/issues/3516
https://github.com/ossrs/srs/issues/4055
https://github.com/ossrs/srs/pull/3618

The issue arises from a mismatch between the `input` and `output`
formats within the
[`SrsEncoder::initialize_ffmpeg`](https://github.com/ossrs/srs/pull/4325/files#diff-a3dd7c498fc26d36def2e8c2c3b7edfe1bf78f0620b1a838aefa70ba119cad03L241-L254)
function.

For example:
Input: `rtmp://127.0.0.1:1935/live?vhost=__defaultVhost__/livestream_ff`
Output:
`rtmp://127.0.0.1:1935/live/livestream_ff?vhost=__defaultVhost__`

This may result in the failure of the [code
segment](https://github.com/ossrs/srs/pull/4325/files#diff-a3dd7c498fc26d36def2e8c2c3b7edfe1bf78f0620b1a838aefa70ba119cad03L292-L298)
responsible for determining whether to loop.

It simply involves modifying the order of `stream` and `vhost`.

The commit introducing this bug is:
7d47017a00
The order of [parameters in the configuration
file](7d47017a00 (diff-428de168925d659dae72bb49273c3b048ed2800906c6848560badae854250126L26-R26))
has been modified to address the `ingest` issue.

Please note that this PR does not entirely resolve the issue; for
example, modifying the `output` format in configuration still results in
exceptions. To comprehensively address this problem, extensive code
modifications would be required.

However, strictly adhering to the configuration file format can
effectively prevent this issue.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2025-06-04 10:20:22 -04:00
pengzhixiang
51d26f26b7 RTMP: Use extended timestamp as delta when chunk fmt=1/2. v6.0.167 (#4356)
1. When the chunk message header employs type 1 and type 2, the extended
timestamp denotes the time delta.
2. When the DTS (Decoding Time Stamp) experiences a jump and exceeds
16777215, there can be errors in DTS calculation, and if the audio and
video delta differs, it may result in audio-video synchronization
issues.

---------

`TRANS_BY_GPT4`

---------

Co-authored-by: 彭治湘 <zuolengchan@douyu.tv>
Co-authored-by: Haibo Chen(陈海博) <495810242@qq.com>
Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2025-05-29 14:24:40 -04:00
winlin
4b64c5c5be Upgrade actions worlflow image to Ubuntu 22.04 v6.0-a2 2025-04-26 00:13:48 -04:00
john
2a7f0090b5 replace values with enums. v6.0.166 (#4303)
---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>

---------

Co-authored-by: Haibo Chen(陈海博) <495810242@qq.com>
Co-authored-by: john <hondaxiao@tencent.com>
2025-03-21 19:12:41 +08:00
john
64e5658f17 free sample to prevent memory leak. v5.0.222 v6.0.164 (#4305)
修复`SrsRtpRawPayload::copy()`方法中sample_覆盖的问题。

---------

Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: winlin <winlinvip@gmail.com>

---------

Co-authored-by: john <hondaxiao@tencent.com>
2025-03-21 10:38:55 +08:00
john
2b5c1ad06d update geekyeggo/delete-artifact to 5.0.0. v5.0.221 v6.0.163 v7.0.25 (#4302)
>
https://github.com/marketplace/actions/delete-artifact?version=v5.0.0#-compatibility

The current version of `actions/upload-artifact` is `v4`, and the
corresponding version for `delete-artifact` should be `v5`.

---------

`TRANS_BY_GPT4`

---------

Co-authored-by: chundonglinlin <chundonglinlin@163.com>
Co-authored-by: winlin <winlinvip@gmail.com>

---------

Co-authored-by: john <hondaxiao@tencent.com>
2025-03-18 08:27:08 +08:00
john
2b89f7e7e8 Dvr: support h265 flv fragments. v6.0.162 v7.0.24 (#4296)
1. Issue
When segmenting H.265 encoded FLV files using a DVR, the system does not
create FLV segments at regular intervals as specified by the
`dvr_wait_keyframe` configuration.

2. Configure dvr.segment.conf
```config

listen              1935;
max_connections     1000;
daemon              off;
srs_log_tank        console;
vhost __defaultVhost__ {
    dvr {
        enabled      on;
        dvr_path     ./objs/nginx/html/[app]/[stream].[timestamp].flv;
        dvr_plan     segment;
        dvr_duration    30;
        dvr_wait_keyframe       on;
    }
}
```

3. Stream Push Testing
Domestic FFmpeg version (codecId=12)
```sh
hevc-12-ffmpeg -stream_loop -1 -re -i 264_aac.flv -c:v libx265 -preset fast -b:v 2000k -maxrate 2000k -bufsize 4000k -bf 0 -c:a aac -b:a 128k -ar 44100 -ac 2 -f flv rtmp://localhost/live/livestream
```
FFmpeg version 6.0 or higher (supports `enhanced RTMP`)
```sh
ffmpeg -stream_loop -1 -re -i 264_aac.flv -c:v libx265 -preset fast -b:v 2000k -maxrate 2000k -bufsize 4000k -bf 0 -c:a aac -b:a 128k -ar 44100 -ac 2 -f flv rtmp://localhost/live/livestream
```

OBS streaming (version 30.0 or above supports `enhanced RTMP`)

![image](https://github.com/user-attachments/assets/fd2806c3-b0e3-44c4-a2d5-e04e6e5386ff)

![image](https://github.com/user-attachments/assets/15ef9c45-e15a-426e-b70c-d4bdd5dc8055)

SRS player (supports both `enhanced RTMP` and `codec=12 FLV`)
```
http://127.0.0.1:8080/players/srs_player.html
```
Domestic ffplay (supports `codec=12 FLV`)
```
hevc-12-ffplay http://127.0.0.1:8080/live/livestream.1740311867638.flv
```
ffplay (versions above ffmpeg 6.0 support `enhanced RTMP`)
```
ffplay http://127.0.0.1:8080/live/livestream.1740311867638.flv
```

![image](https://github.com/user-attachments/assets/711a4182-418c-4134-934f-cba41a08e06f)

---------

`TRANS_BY_GPT4`

---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>

---------

Co-authored-by: john <hondaxiao@tencent.com>
2025-03-18 07:36:46 +08:00
john
b1185d588f fix typo about heartbeat. v6.0.161 (#4253)
---------

Co-authored-by: Haibo Chen <495810242@qq.com>
Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>

---------

Co-authored-by: john <hondaxiao@tencent.com>
2025-02-24 21:03:17 +08:00
john
2ce08750e7 fix ci error. v6.0.160 (#4291)
Starting January 30th, 2025, GitHub Actions customers will no longer be
able to use v3 of
[actions/upload-artifact](https://github.com/actions/upload-artifact) or
[actions/download-artifact](https://github.com/actions/download-artifact).
Customers should update workflows to begin using [v4 of the artifact
actions](https://github.blog/2024-02-12-get-started-with-v4-of-github-actions-artifacts/).
Learn more:
https://github.blog/changelog/2024-04-16-deprecation-notice-v3-of-the-artifact-actions/

---------

Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>

---------

Co-authored-by: john <hondaxiao@tencent.com>
2025-02-24 19:39:20 +08:00
john
02c6e60e3a update copyright to 2025. v6.0.159 (#4271)
update copyright to 2025

---------

Co-authored-by: john <hondaxiao@tencent.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2025-02-24 19:34:34 +08:00
Haibo Chen
c2d75ca395 HLS: Fix error when stream has extension. #4215 v5.0.217 v6.0.158 (#4216)
---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2024-10-31 18:01:32 +08:00
Jacob Su
364bec264e RTC2RTMP: Fix screen sharing stutter caused by packet loss. v6.0.157 (#4160)
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>
2024-10-15 19:46:33 +08:00
Winlin
b830d688be Heartbeat: Report ports for proxy server. v6.0.156 (#4171)
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>
2024-09-09 10:40:46 +08:00
winlin
1bd65f3386 Refine release action. 2024-09-01 17:02:21 +08:00
winlin
dd2cc93421 Release v6.0-a1, 6.0 alpha1, v6.0.155, 169636 lines. v6.0-a1 2024-09-01 15:57:55 +08:00
Winlin
96f89c58ee FLV: Refine source and http handler. v6.0.155 (#4165)
1. Do not create a source when mounting FLV because it may not unmount
FLV when freeing the source. If you access the FLV stream without any
publisher, then wait for source cleanup and review the FLV stream again,
there is an annoying warning message.

```bash
HTTP #0 127.0.0.1:58026 GET http://localhost:8080/live/livestream.flv, content-length=-1
new live source, stream_url=/live/livestream
http: mount flv stream for sid=/live/livestream, mount=/live/livestream.flv

client disconnect peer. ret=1007
Live: cleanup die source, id=[], total=1

HTTP #0 127.0.0.1:58040 GET http://localhost:8080/live/livestream.flv, content-length=-1
serve error code=1097(NoSource)(No source found) : process request=0 : cors serve : serve http : no source for /live/livestream
serve_http() [srs_app_http_stream.cpp:641]
```

> Note: There is an inconsistency. The first time, you can access the
FLV stream and wait for the publisher, but the next time, you cannot.

2. Create a source when starting to serve the FLV client. We do not need
to create the source when creating the HTTP handler. Instead, we should
try to create the source in the cache or stream. Because the source
cleanup does not unmount the HTTP handler, the handler remains after the
source is destroyed. The next time you access the FLV stream, the source
is not found.

```cpp
srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(r.get(), server, live_source)) != srs_success) { }
    if ((err = http_mount(r.get())) != srs_success) { }

srs_error_t SrsBufferCache::cycle() {
    SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(req);
    if (!live_source.get()) {
        return srs_error_new(ERROR_NO_SOURCE, "no source for %s", req->get_stream_url().c_str());
    }

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsSharedPtr<SrsLiveSource> live_source = _srs_sources->fetch(req);
    if (!live_source.get()) {
        return srs_error_new(ERROR_NO_SOURCE, "no source for %s", req->get_stream_url().c_str());
    }
```

> Note: We should not create the source in hijack, instead, we create it
in cache or stream:

```cpp
srs_error_t SrsHttpStreamServer::hijack(ISrsHttpMessage* request, ISrsHttpHandler** ph) {
    if ((err = http_mount(r.get())) != srs_success) { }

srs_error_t SrsBufferCache::cycle() {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) { }

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsSharedPtr<SrsLiveSource> live_source;
    if ((err = _srs_sources->fetch_or_create(req, server_, live_source)) != srs_success) { }
```

> Note: This fixes the failure and annoying warning message, and
maintains consistency by always waiting for the stream to be ready if
there is no publisher.

3. Fail the http request if the HTTP handler is disposing, and also keep
the handler entry when disposing the stream, because we should dispose
the handler entry and stream at the same time.

```cpp
srs_error_t SrsHttpStreamServer::http_mount(SrsRequest* r) {
        entry = streamHandlers[sid];
        if (entry->disposing) {
            return srs_error_new(ERROR_STREAM_DISPOSING, "stream is disposing");
        }

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    std::map<std::string, SrsLiveEntry*>::iterator it = streamHandlers.find(sid);
    SrsUniquePtr<SrsLiveEntry> entry(it->second);
    entry->disposing = true;
```

> Note: If the disposal process takes a long time, this will prevent
unexpected behavior or access to the resource that is being disposed of.

4. In edge mode, the edge ingester will unpublish the source when the
last consumer quits, which is actually triggered by the HTTP stream.
While it also waits for the stream to quit when the HTTP unmounts, there
is a self-destruction risk: the HTTP live stream object destroys itself.

```cpp
srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw); // Trigger destroy.

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    for (;;) { if (!cache->alive() && !stream->alive()) { break; } // A circle reference.
    mux.unhandle(entry->mount, stream.get()); // Free the SrsLiveStream itself.
```

> Note: It also introduces a circular reference in the object
relationships, the stream reference to itself when unmount:

```text
SrsLiveStream::serve_http
    -> SrsLiveConsumer::~SrsLiveConsumer -> SrsEdgeIngester::stop
    -> SrsLiveSource::on_unpublish -> SrsHttpStreamServer::http_unmount
        -> SrsLiveStream::alive
```

> Note: We should use an asynchronous worker to perform the cleanup to
avoid the stream destroying itself and to prevent self-referencing.

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    entry->disposing = true;
    if ((err = async_->execute(new SrsHttpStreamDestroy(&mux, &streamHandlers, sid))) != srs_success) { }
```

> Note: This also ensures there are no circular references and no
self-destruction.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-09-01 13:03:50 +08:00
Winlin
920f87cd38 Edge: Fix flv edge crash when http unmount. v6.0.154 (#4166)
Edge FLV is not working because it is stuck in an infinite loop waiting.
Previously, there was no need to wait for exit since resources were not
being cleaned up. Now, since resources need to be cleaned up, it must
wait for all active connections to exit, which causes this issue.

To reproduce the issue, start SRS edge, run the bellow command and press
`CTRL+C` to stop the request:

```bash
curl http://localhost:8080/live/livestream.flv -v >/dev/null
```

It will cause edge to fetch stream from origin, and free the consumer
when client quit. When `SrsLiveStream::do_serve_http` return, it will
free the consumer:

```cpp
srs_error_t SrsLiveStream::do_serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r) {
    SrsUniquePtr<SrsLiveConsumer> consumer(consumer_raw);
```

Keep in mind that in this moment, the stream is alive, because only set
to not alive after this function return:

```cpp
    alive_viewers_++;
    err = do_serve_http(w, r); // Free 'this' alive stream.
    alive_viewers_--; // Crash here, because 'this' is freed.
```

When freeing the consumer, it will cause the source to unpublish and
attempt to free the HTTP handler, which ultimately waits for the stream
not to be alive:

```cpp
SrsLiveConsumer::~SrsLiveConsumer() {
    source_->on_consumer_destroy(this);

void SrsLiveSource::on_consumer_destroy(SrsLiveConsumer* consumer) {
    if (consumers.empty()) {
        play_edge->on_all_client_stop();

void SrsLiveSource::on_unpublish() {
    handler->on_unpublish(req);

void SrsHttpStreamServer::http_unmount(SrsRequest* r) {
    if (stream->entry) stream->entry->enabled = false;

    for (; i < 1024; i++) {
        if (!cache->alive() && !stream->alive()) {
            break;
        }
        srs_usleep(100 * SRS_UTIME_MILLISECONDS);
    }
```

After 120 seconds, it will free the stream and cause SRS to crash
because the stream is still active. In order to track this potential
issue, also add an important warning log:

```cpp
srs_warn("http: try to free a alive stream, cache=%d, stream=%d", cache->alive(), stream->alive());
```

SRS may crash if got this log.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-09-01 06:45:38 +08:00
Winlin
0bac21df6e Fix #3767: RTMP: Do not response empty data packet. v6.0.153 (#4162)
If SRS responds with this empty data packet, FFmpeg will receive an
empty stream, like `Stream #0:0: Data: none` in following logs:

```bash
ffmpeg -i rtmp://localhost:11935/live/livestream
```

This won't cause the player to fail, but it will inconvenience the user
significantly. It may also cause FFmpeg slower to analysis the stream,
see #3767

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-09-01 06:41:20 +08:00
Winlin
d27e530f84 HTTP-FLV: Notify connection to expire when unpublishing. v6.0.152 (#4164)
When stopping the stream, it will wait for the HTTP Streaming to exit.
If the HTTP Streaming goroutine hangs, it will not exit automatically.

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r)
{
    SrsUniquePtr<SrsLiveStream> stream(entry->stream);
    if (stream->entry) stream->entry->enabled = false;
    srs_usleep(...); // Wait for about 120s.
    mux.unhandle(entry->mount, stream.get()); // Free stream.
}

srs_error_t SrsLiveStream::serve_http(ISrsHttpResponseWriter* w, ISrsHttpMessage* r)
{
    err = do_serve_http(w, r); // If stuck in here for 120s+
    alive_viewers_--; // Crash at here, because stream has been deleted.
```

We should notify http stream connection to interrupt(expire):

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r)
{
    SrsUniquePtr<SrsLiveStream> stream(entry->stream);
    if (stream->entry) stream->entry->enabled = false;
    stream->expire(); // Notify http stream to interrupt.
```

Note that we should notify all viewers pulling stream from this http
stream.

Note that we have tried to fix this issue, but only try to wait for all
viewers to quit, without interrupting the viewers, see
https://github.com/ossrs/srs/pull/4144

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-08-31 23:17:07 +08:00
Winlin
da5683e478 Fix crash when quiting. v6.0.151 (#4157)
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>
2024-08-24 22:41:21 +08:00
Jacob Su
b05f7b4452 Build: Fix srs_mp4_parser compiling error. v6.0.150 (#4156)
`SrsAutoFree` moved to `srs_core_deprecated.hpp`.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
2024-08-24 21:49:32 +08:00
Winlin
41b3623296 API: Support new HTTP API for VALGRIND. v6.0.149 (#4150)
New features for valgrind:

1. ST: Support /api/v1/valgrind for leaking check.
2. ST: Support /api/v1/valgrind?check=full|added|changed|new|quick

To use Valgrind to detect memory leaks in SRS, even though Valgrind
hooks are supported in ST, there are still many false positives. A more
reasonable approach is to have Valgrind report incremental memory leaks.
This way, global and static variables can be avoided, and detection can
be achieved without exiting the program. Follow these steps:

1. Compile SRS with Valgrind support: `./configure --valgrind=on &&
make`
2. Start SRS with memory leak detection enabled: `valgrind
--leak-check=full ./objs/srs -c conf/console.conf`
3. Trigger memory detection by using curl to access the API and generate
calibration data. There will still be many false positives, but these
can be ignored: `curl http://127.0.0.1:1985/api/v1/valgrind?check=added`
4. Perform load testing or test the suspected leaking functionality,
such as RTMP streaming: `ffmpeg -re -i doc/source.flv -c copy -f flv
rtmp://127.0.0.1/live/livestream`
5. Stop streaming and wait for SRS to clean up the Source memory,
approximately 30 seconds.
6. Perform incremental memory leak detection. The reported leaks will be
very accurate at this point: `curl
http://127.0.0.1:1985/api/v1/valgrind?check=added`

> Note: To avoid interference from the HTTP request itself on Valgrind,
SRS uses a separate coroutine to perform periodic checks. Therefore,
after accessing the API, you may need to wait a few seconds for the
detection to be triggered.

---------

Co-authored-by: Jacob Su <suzp1984@gmail.com>
2024-08-21 15:39:59 +08:00
Bahamut
3917422a07 HTTP-FLV: Crash when multiple viewers. v6.0.148 (#4144)
I did some preliminary code inspection. The two playback endpoints share
the same `SrsLiveStream` instance. After the first one disconnects,
`alive_` is set to false.
```
  alive_ = true;
  err = do_serve_http(w, r);
  alive_ = false;
```

In the `SrsHttpStreamServer::http_unmount(SrsRequest* r)` function,
`stream->alive()` is already false, so `mux.unhandle` will free the
`SrsLiveStream`. This causes the other connection coroutine to return to
its execution environment after the `SrsLiveStream` instance has already
been freed.
```
    // Wait for cache and stream to stop.
    int i = 0;
    for (; i < 1024; i++) {
        if (!cache->alive() && !stream->alive()) {
            break;
        }
        srs_usleep(100 * SRS_UTIME_MILLISECONDS);
    }

    // Unmount the HTTP handler, which will free the entry. Note that we must free it after cache and
    // stream stopped for it uses it.
    mux.unhandle(entry->mount, stream.get());
```

`alive_` was changed from a `bool` to an `int` to ensure that
`mux.unhandle` is only executed after each connection's `serve_http` has
exited.

---------

Co-authored-by: liumengte <liumengte@visionular.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2024-08-15 12:13:16 +08:00
Jacob Su
133a39a81d Config: Add more utest for env config. v6.0.147 (#4142)
1. don't use static variable to store the result;
2. add more UT to handle the multi value and values with whitespaces;

related to #4092

16e569d823/trunk/src/app/srs_app_config.cpp (L71-L82)

`static SrsConfDirective* dir` removed, this static var here is to avoid
the memory leak, I add the `SrsConfDirective` instance to the `env_dirs`
directive container, which will destroy itself inside `SrsConfig`
destructor.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
2024-08-15 11:13:00 +08:00
Bahamut
957140db51 Live: Crash for invalid live stream state when unmount HTTP. v6.0.146 (#4141)
When unpublishing, the handler callback that will stop the coroutine:

```cpp
_can_publish = true;
handler->on_unpublish(req);
```

In this handler, the `http_unmount` will be called:

```cpp
void SrsHttpStreamServer::http_unmount(SrsRequest* r)
    cache->stop();
```

In this `http_unmount` function, there could be context switching. In
such a situation, a new connection might publish the stream while the
unpublish process is freeing the stream, leading to a crash.

To prevent a new publisher, we should change the state only after all
handlers and hooks are completed.

---------

Co-authored-by: liumengte <liumengte@visionular.com>
Co-authored-by: winlin <winlinvip@gmail.com>
2024-08-15 10:43:59 +08:00
Jacob Su
fa3dc3bf69 Config: Improve env config to support multi values. v6.0.146 (#4092)
1. add on_connect & on_close directives to conf/full.conf;
2. let http_hooks env overwrite support multi values; e.g.
SRS_VHOST_HTTP_HOOKS_ON_CONNECT="http://127.0.0.1/api/connect
http://localhost/api/connect"

related to
https://github.com/ossrs/srs/issues/1222#issuecomment-2170424703
Above comments said `http_hook` env may not works as expected, as I
found there are still has some issue in `http_hooks` env configuration,
but this PR may not target above problem.

---------

Co-authored-by: winlin <winlinvip@gmail.com>
2024-08-13 11:26:23 +08:00
winlin
1e9133181f Switch to 6.0 release header. 2024-07-27 11:40:10 +08:00