You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在FFmpeg分支的libavcodec中为视频嵌入自定义元数据

解决FFmpeg Hap编码器全局最大包大小传递到解码器的问题

核心思路

要将编码阶段计算的全局最大编码包大小传递到解码阶段,必须通过编码器的extradata字段——这是FFmpeg中编码器向解码器传递全局元数据的标准通道,其他字段(如priv_data、flags2)要么是实例私有,要么不被容器持久化存储,无法跨编码-解码阶段传递。

具体实现步骤

1. 在编码器私有结构体中存储计算值

在hapenc.c的HapEncContext结构体中新增字段,保存你已经计算好的最大包大小:

typedef struct HapEncContext {
    // 原有字段(如编码参数、临时缓冲区等)
    int max_frame_size; // 新增:存储全局最大编码包大小
} HapEncContext;

在编码流程中完成计算后,将结果赋值给s->max_frame_size。

2. 扩展并更新编码器的extradata

在编码器的收尾阶段(比如hap_encode_close函数),将max_frame_size追加到原有extradata的末尾,确保容器能将该数据写入文件元数据:

static int hap_encode_close(AVCodecContext *avctx) {
    HapEncContext *s = avctx->priv_data;
    int orig_extradata_size = avctx->extradata_size;
    int new_extradata_size = orig_extradata_size + sizeof(int32_t);

    // 重新分配extradata内存,预留空间存储max_frame_size
    uint8_t *new_extradata = av_realloc(avctx->extradata, new_extradata_size);
    if (!new_extradata) {
        // 错误处理
        av_freep(&avctx->extradata);
        return AVERROR(ENOMEM);
    }

    // 用大端序写入数值,保证跨平台兼容性
    AV_WB32(new_extradata + orig_extradata_size, s->max_frame_size);

    // 更新AVCodecContext的extradata指针和大小
    avctx->extradata = new_extradata;
    avctx->extradata_size = new_extradata_size;

    // 原有收尾逻辑...
    return 0;
}

3. 在解码器中读取扩展的extradata

在hapdec.c的解码器初始化函数(比如hap_decode_init)中,读取extradata末尾的max_frame_size:

static int hap_decode_init(AVCodecContext *avctx) {
    HapDecContext *s = avctx->priv_data;

    // 检查extradata是否包含我们追加的最大包大小字段
    if (avctx->extradata_size >= sizeof(int32_t)) {
        // 用大端序读取数值,和编码器保持一致
        s->max_frame_size = AV_RB32(avctx->extradata + avctx->extradata_size - sizeof(int32_t));
    } else {
        // 未获取到自定义数据时,使用默认值(适配原有逻辑)
        s->max_frame_size = YOUR_DEFAULT_MAX_SIZE;
    }

    // 原有初始化逻辑...
    return 0;
}

为什么之前的方法失效

  • priv_data:是编码器/解码器各自的私有结构体实例,编码和解码阶段的AVCodecContext完全独立,数据不会自动传递。
  • flags2:属于通用标志位,无预留位存储自定义数值,且容器不会将该字段写入文件元数据,解码阶段无法读取。
  • 错误的extradata修改方式:如果之前只是直接修改extradata_size但未正确分配内存、或未在容器持久化的阶段更新,数据会丢失——必须在编码器收尾时重新分配并写入,确保容器能将扩展后的extradata存入文件的轨道元数据(如MOV/MP4的stsd atom)。

内容的提问来源于stack exchange,提问作者leavittx

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:43:26