# HLS/DASH: Fix dispose() to cleanup files after unpublish
## Summary
Fixes a bug where HLS/DASH files are not deleted after the configured
`hls_dispose`/`dash_dispose` timeout.
## Problem
When a stream is unpublished:
1. `on_unpublish()` is called and sets `enabled_ = false`
2. After the dispose timeout, `cycle()` calls `dispose()`
3. `dispose()` immediately returns due to `if (!enabled_)` check at line
2722 (HLS) and line 891 (DASH)
4. `controller_->dispose()` is never called
5. Files remain on disk indefinitely
**Observed behavior**:
- Stream stopped at 11:32:42
- `dispose()` called at 11:33:14 (after 30s timeout)
- Log shows "hls cycle to dispose hls" but no "gracefully dispose hls"
message
- Files remain on disk
## Root Cause
Commit 550760f2d introduced an early return in `dispose()` when
`!enabled_`, which prevents file cleanup after `on_unpublish()` has
already been called and set `enabled_` to false.
## Solution
Reorder the logic in `dispose()` to:
1. Check if dispose is enabled (hls_dispose/dash_dispose > 0) first
2. Call `on_unpublish()` only if `enabled_` is still true (prevents
duplicate calls)
3. Always call `controller_->dispose()` to cleanup files when dispose
timeout occurs
This ensures files are properly cleaned up while still preventing
duplicate `on_unpublish()` calls.
## Changes Made
- **trunk/src/app/srs_app_hls.cpp** (lines 2718-2734): Reordered
dispose() logic
- **trunk/src/app/srs_app_dash.cpp** (lines 887-902): Reordered
dispose() logic
- **trunk/doc/CHANGELOG.md**: Added v7.0.137 entry
## Testing Recommendation
To verify the fix:
1. Start RTMP stream to `/live/test`:
```bash
ffmpeg -re -i test.mp4 -c copy -f flv rtmp://localhost:1935/live/test
```
2. Wait for HLS segments to be created:
```bash
ls -la /path/to/hls/live/test/
```
3. Stop the stream (Ctrl+C)
4. Wait for `hls_dispose` timeout (default 120s, or 30s with your
config):
```bash
# Watch logs for "hls cycle to dispose hls" and "gracefully dispose hls"
tail -f srs.log
```
5. Verify files are deleted:
```bash
ls -la /path/to/hls/live/test/
# Should be empty or directory removed
```
**Expected results**:
- Before fix: Files remain on disk
- After fix: Files are deleted, logs show "gracefully dispose hls"
## Impact
- **Risk**: Low - minimal logic change, only reordering of checks
- **Breaking changes**: None
- **Performance**: No impact
- **Compatibility**: Fixes existing bug, improves expected behavior
## Checklist
- [x] Code follows project style
- [x] Both HLS and DASH are fixed
- [x] CHANGELOG updated
- [x] Tested locally (recommended before merge)
- [x] No breaking changes
## Related Issues
- Regression introduced in: 550760f2d
- Related to: #865 (hls_dispose feature)
---------
Co-authored-by: Jacob Su <suzp1984@gmail.com>
for issue #4418, #4151, #4076 .DVR Missing First Few Seconds of
Audio/Video
### Root Cause
When recording WebRTC streams to FLV files using DVR, the first 4-6
seconds of audio/video are missing. This occurs because:
1. **Packets are discarded before A/V sync is available**: The
RTC-to-RTMP conversion pipeline actively discards all RTP packets when
avsync_time <= 0.
2. **Original algorithm requires 2 RTCP SR packets**: The previous
implementation needed to receive two RTCP Sender Report (SR) packets
before it could calculate the rate for audio/video synchronization
timestamp conversion.
3. **Delay causes packet loss**: Since RTCP SR packets typically arrive
every 2-3 seconds, waiting for 2 SRs means 4-6 seconds of packets are
discarded before A/V sync becomes available.
4. **Audio SR arrives slower than video SR**: As reported in the issue,
video RTCP SR packets arrive much faster than audio SR packets. This
asymmetry causes audio packets to be discarded for a longer period,
resulting in the audio loss observed in DVR recordings.
### Solution
1. **Initialize rate from SDP**: Use the sample rate from SDP (Session
Description Protocol) to calculate the initial rate immediately when the
track is created.
Audio (Opus): 48000 Hz → rate = 48 (RTP units per millisecond)
Video (H.264/H.265): 90000 Hz → rate = 90 (RTP units per millisecond)
2. **Enable immediate A/V sync:** With the SDP rate available,
cal_avsync_time() can calculate valid timestamps from the very first RTP
packet, eliminating packet loss.
3. **Smooth transition to precise rate**: After receiving the 2nd RTCP
SR, update to the precisely calculated rate based on actual RTP/NTP
timestamp mapping.
## Configuration
Added new configuration option `init_rate_from_sdp` in the RTC vhost
section:
```nginx
vhost rtc.vhost.srs.com {
rtc {
# Whether initialize RTP rate from SDP sample rate for immediate A/V sync.
# When enabled, the RTP rate (units per millisecond) is initialized from the SDP
# sample rate (e.g., 90 for video 90kHz, 48 for audio 48kHz) before receiving
# 2 RTCP SR packets. This allows immediate audio/video synchronization.
# The rate will be updated to a more precise value after receiving the 2nd SR.
# Overwrite by env SRS_VHOST_RTC_INIT_RATE_FROM_SDP for all vhosts.
# Default: off
init_rate_from_sdp off;
}
}
```
**⚠️ Important Note**: This config defaults to **off** because:
- ✅ When **enabled**: Fixes the audio loss problem (no missing first 4-6
seconds)
- ❌ When **enabled**: VLC on macOS cannot play the video properly
- ✅ Other platforms work fine (Windows, Linux)
- ✅ FFplay works fine on all platforms
Users experiencing audio loss in DVR recordings can enable this option
if they don't need VLC macOS compatibility. We're investigating the VLC
macOS issue to make this feature safe to enable by default in the
future.
---------
Co-authored-by: winlin <winlinvip@gmail.com>
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
This PR introduces a major refactoring to replace `SrsSharedPtrMessage`
with `SrsMediaPacket` throughout the SRS codebase, providing a more
unified and cleaner approach to media packet handling.
---------
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
This PR modernizes the memory management architecture in SRS by
refactoring RTMP message handling to use shared pointers
(SrsSharedPtr<SrsMemoryBlock>) instead of manual memory management. This
change improves memory safety, reduces the risk of memory leaks, and
provides a cleaner abstraction for message payload handling.
* Introduced `SrsMemoryBlock`: A dedicated class for managing memory
buffers with size information
* Replaced manual memory management: `SrsCommonMessage` and
`SrsSharedPtrMessage` now use `SrsSharedPtr<SrsMemoryBlock>` instead of
raw pointers
* Updated `SrsRtpPacket`: Now uses `SrsSharedPtr<SrsMemoryBlock>` for
shared buffer management
---------
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
This PR introduces a comprehensive stream publish token system that
prevents race conditions when multiple publishers attempt to publish to
the same stream URL simultaneously across different protocols (RTMP,
WebRTC, SRT).
* Race Condition Issue: Multiple publishers could create duplicate
sources for the same stream when context switches occurred during source
initialization in SRS's coroutine-based architecture
* Cross-Protocol Conflicts: Different protocols (RTMP, RTC, SRT) could
simultaneously publish to the same stream URL without coordination
* Resource Management: No centralized mechanism to ensure exclusive
stream publishing access
---------
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
This PR fixes a critical race condition in SRS source managers where
multiple coroutines could create duplicate sources for the same stream.
- **Atomic source creation**: Source lookup, creation, and pool
insertion now happen atomically within lock scope
- **Consistent interface**: Standardize on `ISrsRequest*` interface
throughout codebase
- **Handler simplification**: Remove `ISrsLiveSourceHandler*` parameter,
obtain from global server instance
---------
Co-authored-by: OSSRS-AI <winlinam@gmail.com>
## Problem
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
## Root Cause
The `enabled` flag should control processing of **new incoming
streams**, but should NOT prevent **cleanup of existing files** from
previously enabled streams.
## Solution
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>
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. 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>
* Add utc time utility
* Fix calculate duration in fmp4
* Refine dash code, use segment template timeline
* Shrink m4s file and cleanup
* Support play by dash.js
* Use SegmentTemplate timeline mode with $Number$
Co-authored-by: winlin <winlin@vip.126.com>