2024-07-12
한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina
1. When using avcodec_find_encoder_by_name to find the encoder,
const AVCodec * aacencoder = avcodec_find_encoder_by_name("libx264");
The encoder values are:
id AV_CODEC_ID_H264 (27)
long_name libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
name libx264
pix_fmts AV_PIX_FMT_YUV420P (0)
type AVMEDIA_TYPE_VIDEO (0)
2. After calling AVCodecContext *aacencodercontext = avcodec_alloc_context3(aacencoder);
The encoder is the same as above, no changes
The encoder context has the following contents:
The codec_id and codec_type in the encoder context have values, and the others are reassigned to default values.
codec_id AV_CODEC_ID_H264 (27)
codec_type AVMEDIA_TYPE_VIDEO (0)
The default values are as follows:
s->time_base = (AVRational){0,1};
s->framerate = (AVRational){ 0, 1 };
s->pkt_timebase = (AVRational){ 0, 1 };
3. When the avcodec_open2(encoderAVCodecContext, encoderAVCodec, NULL) method is called, many parameters will be set.
We can imagine, assuming that the encoder is AAC, then which parameters will be set?
The first one is how many sample frames an avframe has.
3.1 Start from the very beginning avcodec_find_encoder or avcodec_find_decoder.
The method is in the D:Ctoolyinshipinffmpeg-6.0sourcelibavcodecallcodecs.c file.
const AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
return find_codec(id, av_codec_is_encoder);
}
const AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
return find_codec(id, av_codec_is_decoder);
}
3.2 The core of find_codec method is av_codec_iterate method
static const AVCodec *find_codec(enum AVCodecID id, int (*x)(const AVCodec *))
{
const AVCodec *p, *experimental = NULL;
void *i = 0;
id = remap_deprecated_codec_id(id);
while ((p = av_codec_iterate(&i))) {
if (!x(p))
continue;
if (p->id == id) {
if (p->capabilities & AV_CODEC_CAP_EXPERIMENTAL && !experimental) {
experimental = p;
} else
return p;
}
}
return experimental;
}
3.3 The av_codec_iterate method actually finds the corresponding codec from codec_list. This list is very long and includes the names of all encoders and decoders in ffmepg.
const AVCodec *av_codec_iterate(void **opaque)
{
uintptr_t i = (uintptr_t)*opaque;
const FFCodec *c = codec_list[i];
ff_thread_once(&av_codec_static_init, av_codec_init_static);
if (c) {
*opaque = (void*)(i + 1);
return &c->p;
}
return NULL;
}
We can see that there are multiple aacs corresponding to codec_list. We use ff_aac_encoder to illustrate.
After searching the code, I found that the definition of ff_aac_encoder is in aacenc.c, which has
From D:Ctoolyinshipinffmpeg-6.0sourcelibavcodecaacenc.c, you can see the following information:
field.init = aac_encode_init, which should be a function,
From the aac_encode_init function, we can see that frame_size is 1024
avctx->frame_size = 1024;
const FFCodec ff_aac_encoder = {
.p.name = "aac",
CODEC_LONG_NAME("AAC (Advanced Audio Coding)"),
.p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC,
.p.capabilities = AV_CODEC_CAP_DR1 | AV_CODEC_CAP_DELAY |
AV_CODEC_CAP_SMALL_LAST_FRAME,
.priv_data_size = sizeof(AACEncContext),
.init = aac_encode_init,
FF_CODEC_ENCODE_CB(aac_encode_frame),
.close = aac_encode_end,
.defaults = aac_encode_defaults,
.p.supported_samplerates = ff_mpeg4audio_sample_rates,
.caps_internal = FF_CODEC_CAP_INIT_CLEANUP,
.p.sample_fmts = (const enum AVSampleFormat[]){ AV_SAMPLE_FMT_FLTP,
AV_SAMPLE_FMT_NONE },
.p.priv_class = &aacenc_class,
};
At this point, there is still a question: when is ff_aac_encoder initialized?
In fact, ret = avcodec_open2(avcodecContext,nullptr,nullptr); does this internally.
The core code is in
if (codec2->init) {
In fact, it will call:
static av_cold int aac_encode_init(AVCodecContext *avctx)