PR #25138 opened by James Almer (jamrial) URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25138 Patch URL: https://code.ffmpeg.org/FFmpeg/FFmpeg/pulls/25138.patch
If the pixel format is a hardware one, components will be unset, and we will end up writing an invalid pixi box. See [libavif/issues/2922](https://github.com/AOMediaCodec/libavif/issues/2922) >From 943c567702a7f074bb05ee33ac833d73d48206e6 Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sat, 17 Oct 2026 00:54:17 -0300 Subject: [PATCH 1/2] tests/fate/mov: add a simple muxing test for AVIF Signed-off-by: James Almer <[email protected]> --- tests/fate/mov.mak | 6 ++++++ tests/ref/fate/mov-avif-mux-still-image-1-item | 9 +++++++++ 2 files changed, 15 insertions(+) create mode 100644 tests/ref/fate/mov-avif-mux-still-image-1-item diff --git a/tests/fate/mov.mak b/tests/fate/mov.mak index e36ddff7ed..226b4cfc0d 100644 --- a/tests/fate/mov.mak +++ b/tests/fate/mov.mak @@ -233,6 +233,12 @@ $(eval $(call FATE_MOV_CENC_TEST,h264_iso,H264,matroska,MATROSKA,h264/dts_5frame $(eval $(call FATE_MOV_CENC_TEST,hevc,HEVC,hevc,HEVC,hevc-conformance/ipcm_A_NEC_3.bit)) $(eval $(call FATE_MOV_CENC_TEST,hevc_iso,HEVC,mov,MOV,hevc/extradata-reload-multi-stsd.mov)) +# avif muxing - still image with 1 item. +FATE_MOV_FFMPEG_SAMPLES-$(call REMUX, AVIF MATROSKA, AV1_DECODER AV1_PARSER) \ + += fate-mov-avif-mux-still-image-1-item +fate-mov-avif-mux-still-image-1-item: CMD = transcode webm $(TARGET_SAMPLES)/av1/rgb.webm avif \ + "-c:v copy" "-c:v copy" "" "" "-c:v av1" + # avif demuxing - still image with 1 item. FATE_MOV_FFMPEG_SAMPLES-$(call FRAMECRC, MOV, AV1, AV1_PARSER) \ += fate-mov-avif-demux-still-image-1-item diff --git a/tests/ref/fate/mov-avif-mux-still-image-1-item b/tests/ref/fate/mov-avif-mux-still-image-1-item new file mode 100644 index 0000000000..4e786ee9c1 --- /dev/null +++ b/tests/ref/fate/mov-avif-mux-still-image-1-item @@ -0,0 +1,9 @@ +efe1d5926b5be6a69224fdb41226cd35 *tests/data/fate/mov-avif-mux-still-image-1-item.avif +1913795 tests/data/fate/mov-avif-mux-still-image-1-item.avif +#extradata 0: 16, 0x2028040f +#tb 0: 1/1 +#media_type 0: video +#codec_id 0: av1 +#dimensions 0: 1920x800 +#sar 0: 0/1 +0, 0, 0, 1, 1913494, 0x133c0bea -- 2.54.0 >From f9a3c8c00d5160f697df3c92420f247d37ea1bdf Mon Sep 17 00:00:00 2001 From: James Almer <[email protected]> Date: Sat, 17 Oct 2026 00:59:06 -0300 Subject: [PATCH 2/2] avformat/movenc: use bitstream information to write AVIF parameters if needed If the pixel format is a hardware one, components will be unset, and we will end up writing an invalid pixi box. Signed-off-by: James Almer <[email protected]> --- libavformat/movenc.c | 41 +++++++++++++++++++++++++++++++++++------ 1 file changed, 35 insertions(+), 6 deletions(-) diff --git a/libavformat/movenc.c b/libavformat/movenc.c index 2c349ef663..52a73ba49f 100644 --- a/libavformat/movenc.c +++ b/libavformat/movenc.c @@ -3831,16 +3831,29 @@ static int mov_write_ispe_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatConte static int mov_write_pixi_tag(AVIOContext *pb, MOVMuxContext *mov, AVFormatContext *s, int stream_index) { + MOVTrack *trk = &mov->tracks[stream_index]; int64_t pos = avio_tell(pb); const AVPixFmtDescriptor *pixdesc = av_pix_fmt_desc_get(s->streams[stream_index]->codecpar->format); + int depth, nb_components; + if (pixdesc->nb_components > 0) { + depth = pixdesc->comp[0].depth; + nb_components = pixdesc->nb_components; + } else { + AV1SequenceParameters seq; + int ret = ff_av1_parse_seq_header(&seq, trk->extradata[trk->last_stsd_index], + trk->extradata_size[trk->last_stsd_index]); + if (ret < 0) + return ret; + depth = seq.bitdepth; + nb_components = seq.monochrome ? 1 : 3; + } avio_wb32(pb, 0); /* size */ ffio_wfourcc(pb, "pixi"); avio_wb32(pb, 0); /* Version & flags */ - avio_w8(pb, pixdesc->nb_components); /* num_channels */ - for (int i = 0; i < pixdesc->nb_components; ++i) { - avio_w8(pb, pixdesc->comp[i].depth); /* bits_per_channel */ - } + avio_w8(pb, nb_components); /* num_channels */ + for (int i = 0; i < nb_components; ++i) + avio_w8(pb, depth); /* bits_per_channel */ return update_size(pb, pos); } @@ -6373,9 +6386,25 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) if (mov->mode == MODE_ISM) { ffio_wfourcc(pb, "piff"); } else if (mov->mode == MODE_AVIF) { + const MOVTrack *trk = &mov->tracks[0]; const AVPixFmtDescriptor *pix_fmt_desc = av_pix_fmt_desc_get(s->streams[0]->codecpar->format); - const int depth = pix_fmt_desc->comp[0].depth; + int depth = 0, log2_chroma_w, log2_chroma_h; + + if (pix_fmt_desc->nb_components > 0) { + depth = pix_fmt_desc->comp[0].depth; + log2_chroma_w = pix_fmt_desc->log2_chroma_w; + log2_chroma_h = pix_fmt_desc->log2_chroma_h; + } else { + AV1SequenceParameters seq; + int ret = ff_av1_parse_seq_header(&seq, trk->extradata[trk->last_stsd_index], + trk->extradata_size[trk->last_stsd_index]); + if (!ret) { + depth = seq.bitdepth; + log2_chroma_w = seq.chroma_subsampling_x; + log2_chroma_h = seq.chroma_subsampling_y; + } + } if (mov->is_animated_avif) { // For animated AVIF, major brand is "avis". Add "avif" as a // compatible brand. @@ -6389,7 +6418,7 @@ static int mov_write_ftyp_tag(AVIOContext *pb, AVFormatContext *s) // MA1B and MA1A brands are based on AV1 profile. Short hand for // computing that is based on chroma subsampling type. 420 chroma // subsampling is MA1B. 444 chroma subsampling is MA1A. - if (!pix_fmt_desc->log2_chroma_w && !pix_fmt_desc->log2_chroma_h) { + if (!log2_chroma_w && !log2_chroma_h) { // 444 chroma subsampling. ffio_wfourcc(pb, "MA1A"); } else { -- 2.54.0 _______________________________________________ ffmpeg-devel mailing list -- [email protected] To unsubscribe send an email to [email protected]
