Ticket #11627: 0001-fix-allow-demuxing-mp4-to-iamf-without-specifying-gr.patch

File 0001-fix-allow-demuxing-mp4-to-iamf-without-specifying-gr.patch, 7.7 KB (added by Luiz Stangarlin, 7 months ago)

patch to copy groups when demuxing and remuxing IAMF

  • libavcodec/packet.h

    From 255cf4b917416b7949eb24a21ad2af0d20846b20 Mon Sep 17 00:00:00 2001
    From: Luiz Felipe Stangarlin <luizfelipestang@gmail.com>
    Date: Mon, 17 Nov 2025 15:27:54 -0600
    Subject: [PATCH 1/2] fix: allow demuxing mp4 to iamf without specifying groups
     via command line
    
    ---
     libavcodec/packet.h       |  8 ++++-
     libavformat/dump.c        |  3 ++
     libavformat/iamf_writer.c |  6 ++--
     libavformat/iamf_writer.h |  3 ++
     libavformat/iamfenc.c     | 65 +++++++++++++++++++++++++++++++++++++--
     libavformat/mov.c         | 11 +++++++
     6 files changed, 90 insertions(+), 6 deletions(-)
    
    diff --git a/libavcodec/packet.h b/libavcodec/packet.h
    index 59bfddf4cc..bbc829ddff 100644
    a b enum AVPacketSideDataType {  
    366366     * Extensible image file format metadata. The payload is a buffer containing
    367367     * EXIF metadata, starting with either 49 49 2a 00, or 4d 4d 00 2a.
    368368     */
    369      AV_PKT_DATA_EXIF,
     369    AV_PKT_DATA_EXIF,
     370
     371    /**
     372     * IAMF Descriptors parameter associated with the audio frame. This metadata
     373     * is in the form of the IAMFContext struct, only used when rewrap MP4 -> IAMF.
     374     */
     375    AV_PKT_DATA_IAMF_DESCRIPTORS,
    370376
    371377    /**
    372378     * The number of side data types.
  • libavformat/dump.c

    diff --git a/libavformat/dump.c b/libavformat/dump.c
    index 734a6e0bbf..9f362b64a9 100644
    a b static void dump_sidedata(void *ctx, const AVPacketSideData *side_data, int nb_s  
    532532        case AV_PKT_DATA_3D_REFERENCE_DISPLAYS:
    533533            dump_tdrdi(ctx, sd, log_level);
    534534            break;
     535        case AV_PKT_DATA_IAMF_DESCRIPTORS:
     536            av_log(ctx, log_level, "IAMF descriptors");
     537            break;
    535538        default:
    536539            if (name)
    537540                av_log(ctx, log_level, "(%zu bytes)", sd->size);
  • libavformat/iamf_writer.c

    diff --git a/libavformat/iamf_writer.c b/libavformat/iamf_writer.c
    index fcf7929830..6d5f997a31 100644
    a b static int populate_audio_roll_distance(IAMFCodecConfig *codec_config)  
    105105    return 0;
    106106}
    107107
    108 static int fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg,
    109                              IAMFCodecConfig *codec_config)
     108int ff_iamf_fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg,
     109                              IAMFCodecConfig *codec_config)
    110110{
    111111    const AVStream *st = stg->streams[0];
    112112    IAMFCodecConfig **tmp;
    int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void  
    309309    if (!codec_config)
    310310        return AVERROR(ENOMEM);
    311311
    312     ret = fill_codec_config(iamf, stg, codec_config);
     312    ret = ff_iamf_fill_codec_config(iamf, stg, codec_config);
    313313    if (ret < 0) {
    314314        av_free(codec_config);
    315315        return ret;
  • libavformat/iamf_writer.h

    diff --git a/libavformat/iamf_writer.h b/libavformat/iamf_writer.h
    index 05f3d322b8..c66072564a 100644
    a b  
    3232int ff_iamf_add_audio_element(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx);
    3333int ff_iamf_add_mix_presentation(IAMFContext *iamf, const AVStreamGroup *stg, void *log_ctx);
    3434
     35int ff_iamf_fill_codec_config(IAMFContext *iamf, const AVStreamGroup *stg,
     36                              IAMFCodecConfig *codec_config);
     37
    3538int ff_iamf_write_descriptors(const IAMFContext *iamf, AVIOContext *pb, void *log_ctx);
    3639
    3740int ff_iamf_write_parameter_blocks(const IAMFContext *iamf, AVIOContext *pb,
  • libavformat/iamfenc.c

    diff --git a/libavformat/iamfenc.c b/libavformat/iamfenc.c
    index 3169ff1eb8..bc21988907 100644
    a b  
    2121
    2222#include <stdint.h>
    2323
     24#include "libavutil/intreadwrite.h"
     25#include "libavutil/mem.h"
    2426#include "avformat.h"
     27#include "avio_internal.h"
    2528#include "iamf.h"
     29#include "iamf_parse.h"
    2630#include "iamf_writer.h"
    2731#include "internal.h"
    2832#include "mux.h"
    static int iamf_init(AVFormatContext *s)  
    4044{
    4145    IAMFMuxContext *const c = s->priv_data;
    4246    IAMFContext *const iamf = &c->iamf;
     47    FFIOContext b;
    4348    int nb_audio_elements = 0, nb_mix_presentations = 0;
    4449    int ret;
    4550
    static int iamf_init(AVFormatContext *s)  
    6873    }
    6974
    7075    if (s->nb_stream_groups <= 1) {
    71         av_log(s, AV_LOG_ERROR, "There must be at least two stream groups\n");
    72         return AVERROR(EINVAL);
     76        av_log(s, AV_LOG_WARNING,
     77               "Less than two stream groups provided; falling back to copying IAMF descriptors.\n");
     78
     79        /* Find the descriptors, by default only stored on the first stream */
     80        const AVPacketSideData *sd =
     81            av_packet_side_data_get(s->streams[0]->codecpar->coded_side_data,
     82                                    s->streams[0]->codecpar->nb_coded_side_data,
     83                                    AV_PKT_DATA_IAMF_DESCRIPTORS);
     84        if (!sd) {
     85            av_log(s, AV_LOG_ERROR,
     86                "No IAMF extradata found on the first input stream; cannot rewrap.\n");
     87            return AVERROR_INVALIDDATA;
     88        }
     89
     90        av_log(s, AV_LOG_TRACE,
     91            "Writing IAMF descriptors from extradata (size=%d)\n", sd->size);
     92       
     93        ffio_init_read_context(&b, sd->data, sd->size);
     94        ret = ff_iamfdec_read_descriptors(iamf, &b.pub, sd->size, s);
     95        if (ret < 0)
     96            return ret;
     97       
     98        /* patch the iamf codec struct like the ff_iamf_add_audio_element does */
     99
     100        for (int i = 0; i < iamf->nb_codec_configs; i++) {
     101            av_free(iamf->codec_configs[i]->extradata);
     102            av_free(iamf->codec_configs[i]);
     103        }
     104        av_freep(&iamf->codec_configs);
     105        iamf->nb_codec_configs = 0;
     106
     107        for (int i = 0; i < iamf->nb_audio_elements; i++) {
     108            IAMFAudioElement *audio_element = iamf->audio_elements[i];
     109
     110            /* Create a synthetic stream group */
     111            AVStreamGroup *stg = avformat_stream_group_create(
     112                    s, AV_STREAM_GROUP_PARAMS_IAMF_AUDIO_ELEMENT, NULL);
     113            if (!stg)
     114                return AVERROR(ENOMEM);
     115
     116            int sid = audio_element->substreams[0].audio_substream_id;
     117            for (int j = 0; j < s->nb_streams; j++) {
     118                AVStream *st = s->streams[j];
     119                if (st->id != sid) continue;
     120                avformat_stream_group_add_stream(stg, st);
     121                break;
     122            }
     123
     124            IAMFCodecConfig *cc = av_mallocz(sizeof(*cc));
     125            if (!cc)
     126                return AVERROR(ENOMEM);
     127
     128            ret = ff_iamf_fill_codec_config(iamf, stg, cc);
     129            if (ret < 0)
     130                return ret;
     131        }
     132
     133        return 0;
    73134    }
    74135
    75136    for (int i = 0; i < s->nb_stream_groups; i++) {
  • libavformat/mov.c

    diff --git a/libavformat/mov.c b/libavformat/mov.c
    index 1a4450153f..51cc2e0834 100644
    a b static int mov_read_iacb(MOVContext *c, AVIOContext *pb, MOVAtom atom)  
    980980                if (audio_element->layers[0].substream_count != 1)
    981981                    disposition &= ~AV_DISPOSITION_DEFAULT;
    982982                stream = st;
     983
     984                // save a copy of the descriptors on the side data for later use when encoding raw IAMF
     985                if (!av_packet_side_data_new(&substream->codecpar->coded_side_data,
     986                                             &substream->codecpar->nb_coded_side_data,
     987                                             AV_PKT_DATA_IAMF_DESCRIPTORS,
     988                                             descriptors_size, 0)) {
     989                    ret = AVERROR(ENOMEM);
     990                    goto fail;
     991                }
     992                memcpy(substream->codecpar->coded_side_data->data,
     993                       st->codecpar->extradata, descriptors_size);
    983994            } else
    984995                stream = avformat_new_stream(c->fc, NULL);
    985996            if (!stream) {