PR #25735 opened by Kilian (lusoris) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25735 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25735.patch
When flushing or renaming a segment fails, `dash_flush()` leaves its stream loop and skips writing the manifest, but it still runs the `window_size` eviction. Old media segments are then deleted while the manifest on disk still references them. This change skips the eviction unless the flush succeeded. Reported in the review of pull request 25619. ## Reproducer Two streams (testsrc video, sine audio), `-f dash -seg_duration 0.5 -window_size 1 -extra_window_size 0`. The write of the second audio segment is made to fail in one of two ways: - **Rename fails:** a non-empty directory sits at the final path `chunk-stream1-00002.m4s`. - **Write fails:** `chunk-stream1-00002.m4s.tmp` is a symlink to `/dev/full`. After the run, every media file named in the retained MPD is checked for existence. | Case | Tree | ffmpeg exit | Files the retained MPD names but that are missing | |---|---|---|---| | rename fails | master | 0 | chunk-stream0-00001.m4s | | rename fails | master + this change | 0 | none | | write fails | pull request 25619 | 228 (ENOSPC) | chunk-stream0-00001.m4s | | write fails | pull request 25619 + this change | 228 (ENOSPC) | none | The exit status of 0 in the rename case comes from `dash_write_trailer()` discarding the `dash_flush()` result on master; pull request 25619 changes that. ## Tests `make fate-dash-big-init fate-dash-mpd-timing fate-dash-seek-reference fate-dash-seek-zero fate-hls-discont-start fate-hls-fmp4-big-init fate-hls-iframes-single-fmp4 fate-hls-iframes-single-mpegts fate-hls-independent-segments fate-hls-playlist-type-event fate-hls-playlist-type-vod fate-hls-round-durations fate-hls-start-number fate-source` passes. ## Similar code in other muxers Other segment muxers that delete old files were checked for the same pattern. They are not changed here: - **hlsenc:** a segment rename result is not checked before the old segments are deleted, and close errors on the playlist are discarded. - **segment:** list entries are trimmed after a trailer failure. - **smoothstreamingenc:** an open, parse or rename failure breaks out of the loop, and the unconditional window removal still runs. - **hdsenc:** close errors are discarded before window removal. >From 4b4ba3d3c6eb892568bb4bb373ce3bcdb3e013ec Mon Sep 17 00:00:00 2001 From: lusoris <[email protected]> Date: Tue, 3 Nov 2026 21:46:45 +0100 Subject: [PATCH] avformat/dashenc: do not evict old segments after a failed segment dash_flush() breaks out of its stream loop when flushing or renaming a segment fails, but then still runs the window_size eviction. The manifest is not updated in that case, so the eviction deletes media files that the last written manifest still references. Reproduced by making the rename of the second audio segment fail (target path is a non-empty directory) with -window_size 1 -extra_window_size 0: the retained MPD keeps startNumber=1 while chunk-stream0-00001.m4s is deleted. With this change every file the retained MPD names still exists. The same holds when the temporary segment file is on /dev/full. Skip the eviction unless the flush succeeded. Signed-off-by: lusoris <[email protected]> --- libavformat/dashenc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/libavformat/dashenc.c b/libavformat/dashenc.c index 36f39bd083a..42d2dd7cac4 100644 --- a/libavformat/dashenc.c +++ b/libavformat/dashenc.c @@ -1858,7 +1858,7 @@ static int dash_flush(AVFormatContext *s, int final, int stream) os->pos += range_length; } - if (c->window_size) { + if (ret >= 0 && c->window_size) { for (i = 0; i < s->nb_streams; i++) { OutputStream *os = &c->streams[i]; int remove_count = os->nb_segments - c->window_size - c->extra_window_size; -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
