Hi,
I've been testing IAMF stream-copy and hit something I can't tell is intended.
I'd rather ask than file, since I've already been wrong once on this tracker.
Stream-copying an IAMF file with Opus essence drops
num_samples_to_trim_at_start from the Audio Frame OBUs. The demuxer reads it
correctly — ffprobe -show_packets reports skip_samples: 312 — but it isn't
written back out, and the output is 21 bytes shorter (7 substreams × 3 bytes:
the trimming flag cleared, two ULEB128 fields
dropped).num_samples_to_trim_at_end survives.
The relevant part of libavformat/iamf_writer.c:
c
if (side_data && side_data_size >= 10) {
skip_samples = AV_RL32(side_data);
discard_padding = AV_RL32(side_data + 4);
}
if (codec_config->codec_id == AV_CODEC_ID_OPUS) {
// IAMF's num_samples_to_trim_at_start is the same as Opus's pre-skip.
skip_samples = pkt->dts < 0
? av_rescale(-pkt->dts, 48000, pkt->time_base.den)
: 0;
discard_padding = av_rescale(discard_padding, 48000, pkt->time_base.den);
}
The comment suggests the intent is that the value is always the Opus pre-skip
and can be re-derived, which holds on the encode path where the first DTS is
negative by the encoder delay. On copy the demuxer gives dts = 0 and puts the
value in side data, so the branch yields 0.
My question is whether that's deliberate. Two things make me unsure:
discard_padding in the same block is only rescaled, not overwritten — so
end-trim survives a copy and start-trim doesn't, which reads more like an
oversight than a rule.
The override is inside the Opus case, so FLAC/PCM/AAC essence would keep the
side-data value. That asymmetry seems unintentional.
If num_samples_to_trim_at_start is only ever the pre-skip, then nothing is lost
— a decoder gets the same number from the codec config, and I've confirmed
ffmpeg decodes such a copy identically. But if it can legitimately exceed the
codec delay (an edit point, concatenation, a stream starting mid-content), the
copy loses information that isn't recorded anywhere else. On a file with
trim_start 600 and pre_skip 120, ffmpeg decodes the original to 479,520 frames
and the copy to 480,000 — 480 extra leading samples, remainder byte-identical.
Would something like this be the right shape, or am I misreading the intent?
c
if (codec_config->codec_id == AV_CODEC_ID_OPUS) {
if (!side_data && pkt->dts < 0)
skip_samples = av_rescale(-pkt->dts, 48000, pkt->time_base.den);
discard_padding = av_rescale(discard_padding, 48000, pkt->time_base.den);
}
Same behaviour on n8.1.2 and master c6309b5c; happy to send a sample file or
test a patch.
Thanks for any info.
-James
_______________________________________________
ffmpeg-devel mailing list -- [email protected]
To unsubscribe send an email to [email protected]