AVStream 指明的码流的基本信息。对一个码流来说最基本的是 AVCodecID。AVCodecID 指明码流对应的标准,比如h264/h263/mp3/aac。同一个 AVCodecID 可能对应多个不同的编解码器 (AVCodec),他们有不同的 AVCodec.name。ffmpeg在选择时除了优先选择non-EXPERIMENTAL的codec, 不会试图去做其它优先选择,只是简单选取最早注册的那个:
下面是根据AVCodecID寻找编码器的代码选段:
static AVCodec *find_encdec(enum AVCodecID id, int encoder) { AVCodec *p, *experimental = NULL; p = first_avcodec; id= remap_deprecated_codec_id(id); while (p) { if ((encoder ? av_codec_is_encoder(p) : av_codec_is_decoder(p)) && p->id == id) { if (p->capabilities & CODEC_CAP_EXPERIMENTAL && !experimental) { experimental = p; } else return p; } p = p->next; } return experimental; }
以AAC为例,若不在命令行手动指定 "-acodec xxxx", ffmpeg 会优先选择内部的 ff_aac_decoder 作为解码器:
AVCodec ff_aac_decoder = { .name = "aac", .id = AV_CODEC_ID_AAC, .priv_data_size = sizeof(AACContext), }; AVCodec ff_libfdk_aac_decoder = { .name = "libfdk_aac", .id = AV_CODEC_ID_AAC, .priv_data_size = sizeof(FDKAACDecContext), }; void avcodec_register_all(void) { ... REGISTER_ENCDEC (AAC, aac); REGISTER_DECODER(AAC_LATM, aac_latm); REGISTER_ENCODER(LIBFAAC, libfaac); REGISTER_ENCDEC (LIBFDK_AAC, libfdk_aac); REGISTER_ENCODER(LIBVO_AACENC, libvo_aacenc); REGISTER_ENCODER(LIBAACPLUS, libaacplus); REGISTER_PARSER(AAC, aac); REGISTER_PARSER(AAC_LATM, aac_latm); REGISTER_BSF(AAC_ADTSTOASC, aac_adtstoasc); ... }
ffmpeg 内部倒是有一个寻找所有AVCodecID对应的AVCodec的函数,但只用于print cmdl help.
static const AVCodec *next_codec_for_id(enum AVCodecID id, const AVCodec *prev,int encoder);