register all media file container muxers in ffmpeg

本文介绍FFmpeg中如何注册与使用mov和3gp等媒体封装器(muxers),包括注册过程、数据结构及查找指定封装器的方法。通过源代码示例详细解释了这些封装器的工作原理。
register all media file container muxers in ffmpeg

1. muxers such mov and 3gp
libavformat/movenc.c:
#if CONFIG_MOV_MUXER
MOV_CLASS(mov)
AVOutputFormat ff_mov_muxer = {
    .name              = "mov",
    .long_name         = NULL_IF_CONFIG_SMALL("QuickTime / MOV"),
    .extensions        = "mov",
    .priv_data_size    = sizeof(MOVMuxContext),
    .audio_codec       = AV_CODEC_ID_AAC,
    .video_codec       = CONFIG_LIBX264_ENCODER ?
                         AV_CODEC_ID_H264 : AV_CODEC_ID_MPEG4,
    .write_header      = mov_write_header,
    .write_packet      = mov_write_packet,
    .write_trailer     = mov_write_trailer,
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    .codec_tag         = (const AVCodecTag* const []){
        ff_codec_movvideo_tags, ff_codec_movaudio_tags, 0
    },
    .priv_class        = &mov_muxer_class,
};
#endif
#if CONFIG_TGP_MUXER
MOV_CLASS(tgp)
AVOutputFormat ff_tgp_muxer = {
    .name              = "3gp",
    .long_name         = NULL_IF_CONFIG_SMALL("3GP (3GPP file format)"),
    .extensions        = "3gp",
    .priv_data_size    = sizeof(MOVMuxContext),
    .audio_codec       = AV_CODEC_ID_AMR_NB,
    .video_codec       = AV_CODEC_ID_H263,
    .write_header      = mov_write_header,
    .write_packet      = mov_write_packet,
    .write_trailer     = mov_write_trailer,
    .flags             = AVFMT_GLOBALHEADER | AVFMT_ALLOW_FLUSH | AVFMT_TS_NEGATIVE,
    .codec_tag         = (const AVCodecTag* const []){ codec_3gp_tags, 0 },
    .priv_class        = &tgp_muxer_class,
};
#endif


2. so how to register these muxers such as mov and 3gp?
in libavformat/allformats.c:
#define REGISTER_MUXER(X, x)                                            \
    {                                                                   \
        extern AVOutputFormat ff_##x##_muxer;                           \
        if (CONFIG_##X##_MUXER)                                         \
            av_register_output_format(&ff_##x##_muxer);                 \
    }

#define REGISTER_DEMUXER(X, x)                                          \
    {                                                                   \
        extern AVInputFormat ff_##x##_demuxer;                          \
        if (CONFIG_##X##_DEMUXER)                                       \
            av_register_input_format(&ff_##x##_demuxer);                \
    }

#define REGISTER_MUXDEMUX(X, x) REGISTER_MUXER(X, x); REGISTER_DEMUXER(X, x)

also in libavformat/allformats.c
void av_register_all(void)
{
    static int initialized;

    if (initialized)
        return;
    initialized = 1;

    avcodec_register_all();

    /* (de)muxers */
    REGISTER_MUXER   (A64,              a64);
    REGISTER_DEMUXER (AAC,              aac);
    REGISTER_MUXDEMUX(AC3,              ac3);
......
    REGISTER_MUXDEMUX(MOV,              mov);
    REGISTER_MUXER   (MP2,              mp2);
    REGISTER_MUXDEMUX(MP3,              mp3);
    REGISTER_MUXER   (MP4,              mp4);

all the registered muxers are save in the below single linked list:
static AVOutputFormat *first_oformat = NULL;
linked by the below field of AVOutputFormat:
    struct AVOutputFormat *next;


get the target AVOutputFormat(a muxer) according to muxer name, for example mov:
m_pFormatCtx->oformat = av_guess_format("mov", NULL, NULL);

AVOutputFormat *av_guess_format(const char *short_name, const char *filename,
                                const char *mime_type)
    /* Find the proper file type. */
    fmt_found = NULL;
    score_max = 0;
    while ((fmt = av_oformat_next(fmt))) {
        score = 0;
        if (fmt->name && short_name && match_format(short_name, fmt->name))
            score += 100;
        if (fmt->mime_type && mime_type && !strcmp(fmt->mime_type, mime_type))
            score += 10;
        if (filename && fmt->extensions &&
            av_match_ext(filename, fmt->extensions)) {
            score += 5;
        }
        if (score > score_max) {
            score_max = score;
            fmt_found = fmt;
        }
    }
    return fmt_found;

in the above example, only short_name is not null. both filename and mime_type are null












### av_register_all 函数的归属库 `av_register_all` 函数属于 FFmpeg 的 `libavformat` 库[^1]。该函数的作用是注册所有可用的解码器、编码器、协议和封装格式等组件,但在 FFmpeg 3.0 及之后的版本中已经被废弃[^2]。因此,在现代 FFmpeg 版本中,不再需要显式调用此函数。取而代之的是使用 `avformat_network_init()` 来初始化网络相关的功能[^1]。 在编译 FFmpeg API 程序时,如果遇到头文件无法找到的问题,通常是因为缺少正确的编译选项或未正确配置开发环境。确保在编译命令中包含 `-lavformat` 和 `-lavcodec` 链接选项,并且安装了 FFmpeg 的开发包(如 `libavformat-dev` 和 `libavcodec-dev`)[^2]。 以下是一个简单的示例代码,展示如何初始化 FFmpeg 并检查其支持的封装格式: ```c #include <libavformat/avformat.h> int main() { // 在旧版本中需要调用 av_register_all() // av_register_all(); // 初始化网络支持 if (avformat_network_init() < 0) { fprintf(stderr, "Failed to initialize network\n"); return -1; } // 打印支持的封装格式 AVInputFormat *ifmt = NULL; while ((ifmt = av_iformat_next(ifmt)) != NULL) { printf("Supported input format: %s\n", ifmt->name); } AVOutputFormat *ofmt = NULL; while ((ofmt = av_oformat_next(ofmt)) != NULL) { printf("Supported output format: %s\n", ofmt->name); } avformat_network_deinit(); return 0; } ``` 编译上述代码时,可以使用以下命令: ```bash gcc -o ffmpeg_example ffmpeg_example.c -lavformat -lavcodec -lz ``` ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值