[PR] avformat/asfenc: honor audio block alignment (PR #24308)
Forgejo_Fairy via ffmpeg-devel <[email protected]>
| Newsgroups | gmane.comp.video.ffmpeg.devel |
|---|---|
| Message-ID | <[email protected]> |
PR #24308 opened by Forgejo_Fairy URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24308 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/24308.patch Fixes #21362. The ASF muxer's historical 3,200-byte default packet size can split an audio media object at an offset that is not a multiple of the stream's WAVEFORMATEX Block Alignment. Section 9.1.2 of the Advanced Systems Format Specification requires every audio payload size to be a multiple of that value. Windows Media readers reject such output for WMA blocks larger than the available packet payload. This change: - uses an automatic packet-size default starting at 3,200 bytes and enlarges it enough to hold at least one audio block; - rejects explicitly selected packet sizes that cannot hold one complete audio block; - aligns fragmented audio payload lengths to the codec block size; - documents the automatic behavior; and - adds a FATE remux test using the existing `Californication_cover.wma` sample, whose WMA block alignment is 4,459 bytes. For the issue sample, the automatic size becomes 4,485 bytes: 4,459 bytes of audio plus 26 bytes of ASF single-payload overhead. Tested with: - `make fate-asf-remux-audio-block-align SAMPLES=/opt/fate-suite` - `make fate-microsoft SAMPLES=/opt/fate-suite` - `make fate-lavf-asf SAMPLES=/opt/fate-suite` - `make fate-generic-tags-remux-asf SAMPLES=/opt/fate-suite` - `make fate-wmav1-encode fate-wmav2-encode SAMPLES=/opt/fate-suite` >From 71d5b9636b7446bf5080e25d61d7d8e790612e9f Mon Sep 17 00:00:00 2001 From: Michael Niedermayer <[email protected]> Date: Fri, 28 Aug 2026 16:56:21 +0000 Subject: [PATCH] avformat/asfenc: honor audio block alignment Choose a default packet size large enough to hold one audio block and align fragmented audio payloads to the codec block size. This avoids producing invalid ASF when a WMA block exceeds the historical 3200-byte packet default. Assisted-by: Fairy --- doc/muxers.texi | 5 ++- libavformat/asfenc.c | 43 +++++++++++++++++++++- tests/fate/microsoft.mak | 8 +++- tests/ref/fate/asf-remux-audio-block-align | 19 ++++++++++ 4 files changed, 70 insertions(+), 5 deletions(-) create mode 100644 tests/ref/fate/asf-remux-audio-block-align diff --git a/doc/muxers.texi b/doc/muxers.texi index 99584e2b8d..f110797297 100644 --- a/doc/muxers.texi +++ b/doc/muxers.texi @@ -841,8 +841,9 @@ muxer too. @item packet_size @var{size} Set the muxer packet size as a number of bytes. By tuning this setting you may reduce data fragmentation or muxer overhead depending on your -source. Default value is @code{3200}, minimum is @code{100}, maximum -is @code{64Ki}. +source. By default, the muxer starts with a size of @code{3200} and +increases it when necessary to fit at least one audio block. The minimum +explicit value is @code{100}, and the maximum is @code{64Ki}. @end table @section ass diff --git a/libavformat/asfenc.c b/libavformat/asfenc.c index 59638e7b22..ba56998c8e 100644 --- a/libavformat/asfenc.c +++ b/libavformat/asfenc.c @@ -188,6 +188,7 @@ #define DATA_HEADER_SIZE 50 +#define PACKET_SIZE_DEFAULT 3200 #define PACKET_SIZE_MAX 65536 #define PACKET_SIZE_MIN 100 @@ -738,8 +739,43 @@ fail: static int asf_write_header(AVFormatContext *s) { ASFContext *asf = s->priv_data; + int packet_size = asf->packet_size; + const int auto_packet_size = !packet_size; int ret; + if (auto_packet_size) { + packet_size = PACKET_SIZE_DEFAULT; + } else if (packet_size < PACKET_SIZE_MIN) { + av_log(s, AV_LOG_ERROR, + "Packet size %d is smaller than the minimum %d\n", + packet_size, PACKET_SIZE_MIN); + return AVERROR(EINVAL); + } + + for (unsigned i = 0; i < s->nb_streams; i++) { + const AVCodecParameters *par = s->streams[i]->codecpar; + + if (par->codec_type == AVMEDIA_TYPE_AUDIO && par->block_align) { + const int min_packet_size = par->block_align + SINGLE_PAYLOAD_HEADERS; + + if (min_packet_size > PACKET_SIZE_MAX) { + av_log(s, AV_LOG_ERROR, + "Block alignment %d is too large for an ASF packet\n", + par->block_align); + return AVERROR(EINVAL); + } + if (auto_packet_size) { + packet_size = FFMAX(packet_size, min_packet_size); + } else if (packet_size < min_packet_size) { + av_log(s, AV_LOG_ERROR, + "Packet size %d is too small for block alignment %d\n", + packet_size, par->block_align); + return AVERROR(EINVAL); + } + } + } + + asf->packet_size = packet_size; s->packet_size = asf->packet_size; s->max_interleave_delta = 0; asf->nb_packets = 0; @@ -929,6 +965,11 @@ static void put_frame(AVFormatContext *s, ASFStream *stream, AVStream *avst, } } if (frag_len1 > 0) { + if (payload_len > frag_len1 && + avst->codecpar->codec_type == AVMEDIA_TYPE_AUDIO && + avst->codecpar->block_align) + frag_len1 -= frag_len1 % avst->codecpar->block_align; + if (payload_len > frag_len1) payload_len = frag_len1; else if (payload_len == (frag_len1 - 1)) @@ -1106,7 +1147,7 @@ static void asf_deinit(AVFormatContext *s) } static const AVOption asf_options[] = { - { "packet_size", "Packet size", offsetof(ASFContext, packet_size), AV_OPT_TYPE_INT, {.i64 = 3200}, PACKET_SIZE_MIN, PACKET_SIZE_MAX, AV_OPT_FLAG_ENCODING_PARAM }, + { "packet_size", "Packet size", offsetof(ASFContext, packet_size), AV_OPT_TYPE_INT, {.i64 = 0}, 0, PACKET_SIZE_MAX, AV_OPT_FLAG_ENCODING_PARAM }, { NULL }, }; diff --git a/tests/fate/microsoft.mak b/tests/fate/microsoft.mak index 8d8e92575a..c4d2927e95 100644 --- a/tests/fate/microsoft.mak +++ b/tests/fate/microsoft.mak @@ -80,10 +80,14 @@ fate-vc1-ism: CMD = framecrc -i $(TARGET_SAMPLES)/isom/vc1-wmapro.ism -an FATE_MICROSOFT += $(FATE_VC1-yes) fate-vc1: $(FATE_VC1-yes) +FATE_ASF_REMUX-$(call REMUX, ASF) += fate-asf-remux-audio-block-align +fate-asf-remux-audio-block-align: CMD = transcode asf $(TARGET_SAMPLES)/cover_art/Californication_cover.wma asf "-map 0:a -c copy -map_metadata -1 -frames:a 8" "-map 0:a -c copy" "-of compact -select_streams a -show_packets -show_entries packet=pts,size,pos -read_intervals %+\#3" + FATE_MICROSOFT-$(call ALLYES, PIPE_PROTOCOL ASF_DEMUXER FRAMECRC_MUXER) += fate-asf-repldata fate-asf-repldata: CMD = framecrc -i $(TARGET_SAMPLES)/asf/bug821-2.asf -c copy FATE_MICROSOFT += $(FATE_MICROSOFT-yes) -FATE_SAMPLES_FFMPEG += $(FATE_MICROSOFT) -fate-microsoft: $(FATE_MICROSOFT) +FATE_SAMPLES_FFMPEG += $(FATE_MICROSOFT) +FATE_SAMPLES_FFMPEG_FFPROBE += $(FATE_ASF_REMUX-yes) +fate-microsoft: $(FATE_MICROSOFT) $(FATE_ASF_REMUX-yes) diff --git a/tests/ref/fate/asf-remux-audio-block-align b/tests/ref/fate/asf-remux-audio-block-align new file mode 100644 index 0000000000..1fa6db4a49 --- /dev/null +++ b/tests/ref/fate/asf-remux-audio-block-align @@ -0,0 +1,19 @@ +88407d736bfe38ea866d2a867a7869a5 *tests/data/fate/asf-remux-audio-block-align.asf +36324 tests/data/fate/asf-remux-audio-block-align.asf +#extradata 0: 10, 0x08a50189 +#tb 0: 1/1000 +#media_type 0: audio +#codec_id 0: wmav2 +#sample_rate 0: 44100 +#channel_layout_name 0: stereo +0, 0, 0, 371, 4459, 0x8e6ba76d +0, 324, 324, 371, 4459, 0x893de414 +0, 696, 696, 371, 4459, 0x69a173aa +0, 928, 928, 371, 4459, 0xcc9baf3f +0, 1206, 1206, 371, 4459, 0xc890aa7d +0, 1439, 1439, 371, 4459, 0x4db6ac94 +0, 1763, 1763, 371, 4459, 0x7d2f71bb +0, 2043, 2043, 371, 4459, 0xb0be449f +packet|pts=0|size=4459|pos=444 +packet|pts=324|size=4459|pos=4929 +packet|pts=696|size=4459|pos=9414 -- 2.52.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]