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.

Signed-off-by: Max <[email protected]>
---
v2:
 - Add missing Signed-off-by line.

 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]

Reply via email to