Skip to content

ad_spdif: recreate spdif muxer on reset - #18241

Merged
kasper93 merged 2 commits into
mpv-player:masterfrom
nathanlucas:spdif-reset
Jul 29, 2026
Merged

ad_spdif: recreate spdif muxer on reset#18241
kasper93 merged 2 commits into
mpv-player:masterfrom
nathanlucas:spdif-reset

Conversation

@nathanlucas

@nathanlucas nathanlucas commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

This partially addresses https://trac.ffmpeg.org/ticket/9569 by resetting the spdif context on seek so stale avformat/spdifenc timing and buffer state will not be used after the seek. This prevents an incomplete TrueHD MAT frame from remaining muxed with access units before the seek, and prevents invalid MAT padding from being calculated relative to timing before the seek.

This also silences timing discontinuity warnings from avformat/spdifenc caused by seeking.

The second commit reduces unnecessary log spam from determine_codec_params by only logging failed profile and rate probes when those values were necessary for the selected format.

AI disclosure: OpenAI Codex assisted with the research and development of these changes. I have reviewed generated code and understand the changes that are being submitted.

@kasper93

kasper93 commented Jul 8, 2026

Copy link
Copy Markdown
Member

Everyone is throwing their tokens at truehd packing it looks like. See also:
Nevcairiel/LAVFilters#707
xbmc/xbmc#28541

@nathanlucas

Copy link
Copy Markdown
Contributor Author

Everyone is throwing their tokens at truehd packing it looks like. See also: Nevcairiel/LAVFilters#707 xbmc/xbmc#28541

Thanks for pointing these out. Neither of the LAV issues affect the spdifenc changes at https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/23542. Good to see kodi going to the output timing solution too.

Comment thread audio/decode/ad_spdif.c
@nathanlucas

Copy link
Copy Markdown
Contributor Author

A few changes:

  • Updated the PR description and added an AI-assist disclosure.
  • Split the single commit into two. One adds reset for seek. The other addresses unnecessary warnings on reset.

Comment thread audio/decode/ad_spdif.c Outdated
{
return pkt->size >= 8 && pkt->data[4] == 0xf8 &&
pkt->data[5] == 0x72 && pkt->data[6] == 0x6f &&
(pkt->data[7] & 0xfe) == 0xba;

@kasper93 kasper93 Jul 27, 2026

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This should be ... && (AV_RB32(pkt->data + 4) & 0xfffffffe) == 0xf8726fba. I'm not sure though you need MLP too? Comment suggest you do, but it's used only for truehd, no? Otherwise you can drop the mask.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I dropped the MLP check and switched to the avutil helper.

I had previously temporarily modified ad_spdif to support MLP to test 44100/88200 sample rates in a few MLP files I have. All my TrueHD samples are 48000. I can't think of a good reason to keep MLP support here now and it would be easy to add back when/if needed.

@kasper93 kasper93 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't really test this. But given the known issues with spdif output, probably people who use it knows better what works for them.

Minor comments below.

Comment thread audio/decode/ad_spdif.c Outdated
@@ -175,6 +221,8 @@ static int init_filter(struct mp_filter *da)
int c_rate = 0;
determine_codec_params(da, pkt, &profile, &c_rate);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now, we will re-probe on ever re-init (seek). If the probe fails after a seek where it succeeded initially (cut/partial first frame), you get a wrong result rather than the old one. And we end up fallbacking to default values. I think we could cache profile/c_rate after initial open and don't reprobe it each time.

Also truehd parser doesn't give profiles, so we spin whole decoder there, avoiding this too is good.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Probing once should be fine, especially since that's how it currently works. determine_codec_params will now only be called once at start and the profile and rate are cached.

Comment thread audio/decode/ad_spdif.c Outdated

close_lavf_context(spdif_ctx, false);
spdif_ctx->dropped_startup_packets = 0;
TA_FREEP(&spdif_ctx->fmt);

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this should go into close_lavf_context, no? It can be leaked on init failures.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good catch. This was wrong.

Comment thread audio/decode/ad_spdif.c
{
spdif_ctx->dropped_startup_packets++;
drop_packet = true;
goto done;

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I would add here MP_WARN after every N packets, in case we lock ourselves in the infinite loop. It can be big number, so it only is printed when something bad happens.

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done. The interval is 6000 packets, which would be 5 seconds if the stream contained the expected 1200 truehd AU/s.

Comment thread audio/decode/ad_spdif.c Outdated
TA_FREEP(&spdif_ctx->fmt);
}

static bool truehd_has_major_sync(AVPacket *pkt)

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

nit: const AVPacket *

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed

The spdif decoder uses avformat/spdifenc. Some spdifenc paths keep
muxer state across packets, such as partial TrueHD MAT frames. After a
seek, that state belongs to the old stream position and can cause the
next packet to be muxed with stale timing or buffering state.

On decoder reset, discard the current spdif muxer context. The next
usable input packet will recreate the muxer through the existing
initialization path.

Cache codec parameters from the initial probe so recreating the muxer
does not probe a partial packet after a seek or replace known values
with fallbacks.

A fresh TrueHD spdif muxer needs a TrueHD major sync before it can begin
muxing the stream. Startup or post-seek playback may begin on a TrueHD
access unit that does not have major sync, so drop TrueHD packets until
a major sync access unit is seen. This also gives the downstream decoder
a clean restart point after seeks. Warn periodically if no major sync
has been found.

Partially addresses: https://trac.ffmpeg.org/ticket/9569
Signed-off-by: Nathan Lucas <nlucasgit@gmail.com>
determine_codec_params() warns when it cannot determine a codec profile.
Some passthrough formats use fixed output parameters and do not require
the probed profile or sample rate making the warning misleading.

Warn only when a value used to configure the selected passthrough format
is missing: the profile for DTS-HD, or the sample rate for core DTS and
AC-3.

Signed-off-by: Nathan Lucas <nlucasgit@gmail.com>
@nathanlucas

nathanlucas commented Jul 29, 2026

Copy link
Copy Markdown
Contributor Author

I tested with the PR changes so far and haven't seen anything new or unusual. This included seeking around The Martian Extended Edition to trigger the behavior with no major sync after seek. Also tested movies with AC-3 ,E-AC-3, DTS core/MA/HRA.

@kasper93
kasper93 merged commit 74356c0 into mpv-player:master Jul 29, 2026
34 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants