PR #25348 opened by Forgejo_Fairy URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25348 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25348.patch
An RTSP server that stops sending without closing its connection leaves ffplay retrying read timeouts indefinitely, even with `-autoexit -timeout 5000000`. RTSP manages its transport internally, so ffplay's `ic->pb->error` check cannot see those failures. This series preserves underlying errors when reading interleaved RTP headers and payloads, then makes ffplay exit on `AVERROR(ETIMEDOUT)` when autoexit is enabled. Nonnegative short packet reads retain `EIO`; ffplay's EOF draining and retry paths for other errors remain intact. Fixes #25212. The TCP regression was verified at f1c8c25832777 against its immediate parent 6d42af02f56: preserving the correct RTSP error exposed ffplay's missing timeout handling. UDP stalls also reproduce on release/4.4. Validation on ARM64 Linux with SDL's dummy audio driver: generated local RTSP/PCMU playback followed by TCP and UDP stalls, stalls inside interleaved headers and payloads, normal TCP EOF, a brief interruption below the timeout, and operation without autoexit. Local WAV EOF and two-pass looping also pass. With a five-second TCP timeout, unmodified master remains running through 17.50 seconds after PLAY; the fix exits around 7.81 seconds, including two seconds of media and cleanup against a silent server. Build and whitespace checks pass. The manual reproducer, exact release revisions, historical comparison and result logs are preserved on `fairy/issue25212-tooling`, commit 023a924b2987, under `tools/issue25212/`. No full FATE or cross-platform run was performed. >From d77401ffed08b8b21ff9d3e35c4c1bc237df69b4 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 22 Oct 2026 10:19:25 +0000 Subject: [PATCH 1/2] avformat/rtspdec: preserve errors reading interleaved packets Return the underlying read error when reading the interleaved packet header or payload fails. In particular, do not replace ETIMEDOUT with EIO: callers need to distinguish a configured read timeout from other errors. Keep EIO for a nonnegative short read, as in ff_rtsp_skip_packet(). Assisted-by: Fairy --- libavformat/rtspdec.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libavformat/rtspdec.c b/libavformat/rtspdec.c index 0e592eebaed..d1bacadccf5 100644 --- a/libavformat/rtspdec.c +++ b/libavformat/rtspdec.c @@ -926,7 +926,7 @@ redo: } ret = ffurl_read_complete(rt->rtsp_hd, buf, 3); if (ret != 3) - return AVERROR(EIO); + return ret < 0 ? ret : AVERROR(EIO); rt->pending_packet = 0; id = buf[0]; len = AV_RB16(buf + 1); @@ -936,7 +936,7 @@ redo: /* get the data */ ret = ffurl_read_complete(rt->rtsp_hd, buf, len); if (ret != len) - return AVERROR(EIO); + return ret < 0 ? ret : AVERROR(EIO); if (rt->transport == RTSP_TRANSPORT_RDT && (ret = ff_rdt_parse_header(buf, len, &id, NULL, NULL, NULL, NULL)) < 0) return ret; -- 2.54.0 >From f6fd4585866ab0280429ba5fea4628b50800b923 Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Thu, 22 Oct 2026 10:19:25 +0000 Subject: [PATCH 2/2] ffplay: honor autoexit on read timeouts RTSP manages its transport internally and has no top-level AVIOContext. Consequently, checking ic->pb->error misses its read timeouts and ffplay keeps retrying even with -autoexit enabled. Exit on AVERROR(ETIMEDOUT) with -autoexit. Leave EOF draining, retryable errors and playback without -autoexit on their existing paths. This also fixes the TCP playback regression exposed by f1c8c25832777, which correctly propagated RTSP read errors instead of reporting EOF. UDP playback is affected independently of that commit. Fixes: #25212 Assisted-by: Fairy --- fftools/ffplay.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/fftools/ffplay.c b/fftools/ffplay.c index d17aa1c4224..94d5d483335 100644 --- a/fftools/ffplay.c +++ b/fftools/ffplay.c @@ -3544,6 +3544,8 @@ static int read_thread(void *arg) } ret = av_read_frame(ic, pkt); if (ret < 0) { + if (autoexit && ret == AVERROR(ETIMEDOUT)) + goto fail; if ((ret == AVERROR_EOF || avio_feof(ic->pb)) && !is->eof) { if (is->video_stream >= 0) { ret = do_bsf_flush(ic, is); -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
