Condivisione della tecnologia

Dopo che ffmpeg ha trovato il codec e il contesto del codec, come inizializza il codec specifico? Il processo di inizializzazione di aac è più o meno il seguente

2024-07-12

한어Русский языкEnglishFrançaisIndonesianSanskrit日本語DeutschPortuguêsΕλληνικάespañolItalianoSuomalainenLatina

1. Quando si utilizza avcodec_find_encoder_by_name per trovare il codificatore,
const AVCodec * aacencoder = avcodec_find_encoder_by_name("libx264");

I valori dell'encoder sono:
identificativo AV_CODEC_ID_H264 (27)
long_name libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 parte 10
nome libx264
pix_fmts AV_PIX_FMT_YUV420P (0)

tipo AVMEDIA_TYPE_VIDEO (0)


2. Dopo aver chiamato AVCodecContext *aacencodercontext = avcodec_alloc_context3(aacencoder);.
L'encoder è lo stesso di sopra, nessuna modifica


Il contenuto nel contesto del codificatore è:
Codec_id e codec_type nel contesto del codificatore hanno valori e gli altri vengono riassegnati ai rispettivi valori predefiniti.
codice_id AV_CODEC_ID_H264 (27)
tipo_codec AVMEDIA_TYPE_VIDEO (0)
I valori predefiniti sono i seguenti:

s->time_base = (AVRazionale){0,1};
s->framerate = (AVRazionale){ 0, 1 };
s->pkt_timebase = (AVRazionale){ 0, 1 };


3. Quando viene chiamato il metodo avcodec_open2(encoderAVCodecContext, encoderAVCodec, NULL), verranno impostati molti parametri.

Possiamo immaginare che supponendo che l'encoder sia AAC, quali parametri verranno impostati?
Il primo è quanti fotogrammi campione ha un avframe.

3.1 Inizia con avcodec_find_encoder o avcodec_find_decoder all'inizio.
Il metodo è nel file D:Ctoolyinshipinffmpeg-6.0sourcelibavcodecallcodecs.c.


const AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
restituisci find_codec(id, av_codec_is_encoder);
}

const AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
restituisci find_codec(id, av_codec_is_decoder);
}


3.2 Il nucleo del metodo find_codec è il metodo av_codec_iterate

statico const AVCodec *find_codec(enum AVCodecID id, int (*x)(const AVCodec *))
{
const AVCodec *p, *sperimentale = NULL;
vuoto *i = 0;

id = remap_deprecated_codec_id(id);

mentre ((p = av_codec_iterate(&i))) {
se (!x(p))
Continua;
se (p->id == id) {
se (p->capacità & AV_CODEC_CAP_EXPERIMENTAL && !sperimentale) {
sperimentale = p;
} altro
restituisci p;
        }
    }

ritorno sperimentale;
}

3.3 Il metodo av_codec_iterate trova effettivamente il codec corrispondente da codec_list Questo elenco è molto lungo e include i nomi di tutti i codificatori e decodificatori all'interno di ffmepg.
const AVCodec *av_codec_iterate(void **opaco)
{
uintptr_t i = (uintptr_t)*opaco;
const FFCodec *c = codec_list[i];

ff_thread_once(&av_codec_static_init, av_codec_init_static);

se (c) {
*opaco = (vuoto*)(i + 1);
ritorno &c->p;
    }
restituisci NULL;
}


Possiamo vedere che ci sono più aac corrispondenti a codec_list e utilizziamo ff_aac_encoder per illustrarlo.
Dopo aver cercato il codice, ho scoperto che la definizione di ff_aac_encoder è in aacenc.c, che contiene


Le seguenti informazioni possono essere visualizzate da D:Ctoolyinshipinffmpeg-6.0sourcelibavcodecaacenc.c,
Field.init = aac_encode_init, dovrebbe essere una funzione,
Come puoi vedere dalla funzione aac_encode_init, frame_size è 1024
avctx->frame_size = 1024;


const FFCodec ff_aac_encoder = {
.p.name = "aac",
CODEC_LONG_NAME("AAC (codifica audio avanzata)"),
.p.type = AVMEDIA_TYPE_AUDIO,
.p.id = AV_CODEC_ID_AAC,
.p.capacità = 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(frame di codifica aac),
.chiudi = aac_encode_end,
.defaults = aac_encode_defaults,
.p.supported_samplerates = frequenze di campionamento ff_mpeg4audio,
.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,
};

A questo punto c'è ancora una domanda: quando è stato inizializzato ff_aac_encoder?
In effetti, ret = avcodec_open2(avcodecContext,nullptr,nullptr);
Il codice principale è dentro

se (codec2->init) {
        
Si chiamerà infatti:
statico av_cold int aac_encode_init(AVCodecContext *avctx)