Hi Max, What player are you using? spdifenc can't reliably detect seeks based on the timing/padding alone. Most seeks will look like a broken stream with timing that doesn't work, which is the "Unusual TrueHD output_timing discontinuity" and "Unusual frame timing" conditions. But some seeks could still result in a valid- looking amount of padding. In those cases that could still cause spdifenc retain the current stale MATs with TrueHD AUs and padding from before the seek, plus add up to another almost 40ms of padding before the first post-seek AU.
The player knows exactly when it is seeking, so I think it is preferable to have the player drive the reset by recreating the spdifenc context when it seeks. This was done recently in mpv. On Wed, Sep 23, 2026 at 11:25 PM Max via ffmpeg-devel <[email protected]> wrote: > > When seeking backward or jumping around in a video that has TrueHD audio > track selected, audio can suddenly go silent - padding_remaining can > evaluate to negative or exceed max_padding_per_packet. Previously, > spdifenc clamped padding_remaining to 0 and requested a sample, leaving > truehd_output_timing_valid intact and retaining the partially filled > hd_buf_filled buffer. > > This desynchronizes subsequent 61,440-byte IEC 61937 MAT burst > boundaries, causing AV receivers to lose framing sync and mute audio > until playback is restarted. > > Fix this by flushing any partial MAT burst buffer (hd_buf_filled = 0) > and re-anchoring the timing counters to the incoming access unit upon > encountering an un-bridgeable timeline discontinuity. > > To test this, play a video with TrueHD selected (preferably a lossless > track to increase chance of a framing desync) and jump around the video. > Big chapter jumps and little 5 second or 10 second jumps, forwards and > backwards. There should be no loss of audio at any point. > --- > This fix has been verified on Linux (ALSA bitstreaming over HDMI to a Denon > AVR) > resolving dropouts on backward seeks and chapter jumps. > > Branch available on code.ffmpeg.org: > https://code.ffmpeg.org/ParcelRot/FFmpeg.git (branch: fix/truehd-mat-seek) > > libavformat/spdifenc.c | 25 ++++++++++++++++--------- > 1 file changed, 16 insertions(+), 9 deletions(-) > > diff --git a/libavformat/spdifenc.c b/libavformat/spdifenc.c > index 0b8d8c5886..04f58ee557 100644 > --- a/libavformat/spdifenc.c > +++ b/libavformat/spdifenc.c > @@ -632,15 +632,22 @@ static int spdif_header_truehd(AVFormatContext *s, > AVPacket *pkt) > padding_remaining = prev_padding + discontinuity_padding; > > if (padding_remaining < 0 || padding_remaining > > max_padding_per_packet) { > - avpriv_request_sample(s, > - "Unusual TrueHD output_timing > discontinuity: " > - "expected %"PRIu16" got %"PRIu16", " > - "timing delta %d => %d, prev padding > %d, " > - "discontinuity padding %d, " > - "total padding %d ignored", > - ctx->truehd_output_timing, > au.output_timing, > - previous_oi_delta, current_oi_delta, > prev_padding, > - discontinuity_padding, > padding_remaining); > + av_log(s, AV_LOG_DEBUG, > + "TrueHD output_timing discontinuity: %d bytes (timing > %u -> %u), resetting MAT burst\n", > + padding_remaining, input_timing, au.output_timing); > + > + /* Un-bridgeable timeline discontinuity (e.g. seek). > + * Flush any incomplete partial frame in the active MAT > buffer > + * so the new AU starts cleanly aligned to a fresh burst. */ > + ctx->hd_buf_filled = 0; > + > + /* Reset timing state so the incoming access unit re-seeds > the baseline */ > + ctx->truehd_prev_size = 0; > + ctx->truehd_prev_time = input_timing; > + ctx->truehd_output_timing = au.output_timing; > + ctx->truehd_oi_delta = current_oi_delta; > + ctx->truehd_output_timing_valid = 1; > + > padding_remaining = 0; > } else { > av_log(s, AV_LOG_VERBOSE, > -- > 2.39.5 > > _______________________________________________ > ffmpeg-devel mailing list -- [email protected] > To unsubscribe send an email to [email protected] _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
