Κοινή χρήση τεχνολογίας

Αφού το ffmpeg βρει το περιβάλλον του κωδικοποιητή και του κωδικοποιητή, πώς αρχικοποιεί τον συγκεκριμένο κωδικοποιητή; Η διαδικασία αρχικοποίησης aac είναι περίπου η εξής

2024-07-12

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

1. Όταν χρησιμοποιείτε avcodec_find_encoder_by_name για να βρείτε τον κωδικοποιητή,
const AVCodec * aacencoder = avcodec_find_encoder_by_name("libx264");

Οι τιμές του κωδικοποιητή είναι:
αναγνωριστικό AV_CODEC_ID_H264 (27)
long_name libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10
όνομα libx264
pix_fmts AV_PIX_FMT_YUV420P (0)

τύπος AVMEDIA_TYPE_VIDEO (0)


2. Αφού καλέσετε το AVCodecContext *aacencodercontext = avcodec_alloc_context3(aacencoder);.
Ο κωδικοποιητής είναι ο ίδιος με τον παραπάνω, καμία αλλαγή


Το περιεχόμενο στο πλαίσιο του κωδικοποιητή είναι:
Τα codec_id και codec_type στο περιβάλλον του κωδικοποιητή έχουν τιμές και τα άλλα αντιστοιχίζονται ξανά στις προεπιλεγμένες τιμές τους.
codec_id AV_CODEC_ID_H264 (27)
codec_type AVMEDIA_TYPE_VIDEO (0)
Οι προεπιλεγμένες τιμές είναι οι εξής:

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


3. Όταν καλείται η μέθοδος avcodec_open2(encoderAVCodecContext, encoderAVCodec, NULL), θα οριστούν πολλές παράμετροι.

Μπορούμε να φανταστούμε ότι αν υποθέσουμε ότι ο κωδικοποιητής είναι AAC, ποιες παράμετροι θα οριστούν;
Το πρώτο είναι πόσα δείγματα καρέ έχει ένα avframe.

3.1 Ξεκινήστε με avcodec_find_encoder ή avcodec_find_decoder στην αρχή.
Η μέθοδος βρίσκεται στο αρχείο D:Ctoolynshipinffmpeg-6.0sourcelibavcodecallcodecs.c.


const AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
επιστροφή find_codec(id, av_codec_is_encoder);
}

const AVCodec *avcodec_find_decoder(enum AVCodecID id)
{
επιστροφή find_codec(id, av_codec_is_decoder);
}


3.2 Ο πυρήνας της μεθόδου find_codec είναι η μέθοδος av_codec_iterate

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);

ενώ ((p = av_codec_iterate(&i))) {
αν (!x(p))
να συνεχίσει;
αν (p->id == id) {
if (p->δυνατότητες & AV_CODEC_CAP_EXPERIMENTAL && !πειραματικό) {
πειραματικό = p;
} άλλο
επιστροφή p;
        }
    }

επιστροφή πειραματικό?
}

3.3 Η μέθοδος av_codec_iterate βρίσκει στην πραγματικότητα τον αντίστοιχο κωδικοποιητή από τη λίστα κωδικοποιητών Αυτή η λίστα είναι πολύ μεγάλη, συμπεριλαμβανομένων των ονομάτων όλων των κωδικοποιητών και αποκωδικοποιητών στο ffmepg.
const AVCodec *av_codec_iterate(void **opaque)
{
uintptr_t i = (uintptr_t)*αδιαφανές;
const FFCodec *c = codec_list[i];

ff_thread_once(&av_codec_static_init, av_codec_init_static);

αν (γ) {
*αδιαφανές = (κενό*)(i + 1);
επιστροφή &c->p;
    }
επιστροφή NULL?
}


Μπορούμε να δούμε ότι υπάρχουν πολλά aacs που αντιστοιχούν στη λίστα κωδικοποιητών και χρησιμοποιούμε το ff_aac_encoder για να το επεξηγήσουμε.
Αφού έψαξα τον κώδικα, βρήκα ότι ο ορισμός του ff_aac_encoder βρίσκεται στο aacenc.c, το οποίο περιέχει


Μπορείτε να δείτε τις ακόλουθες πληροφορίες από το D:Ctoolynshipinffmpeg-6.0sourcelibavavcodecaacenc.c,
Field.init = aac_encode_init, θα πρέπει να είναι συνάρτηση,
Όπως μπορείτε να δείτε από τη συνάρτηση aac_encode_init, το frame_size είναι 1024
avctx->μέγεθος_πλαισίου = 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,
};

Σε αυτό το σημείο, εξακολουθεί να υπάρχει ένα ερώτημα: πότε αρχικοποιήθηκε το ff_aac_encoder;
Στην πραγματικότητα, το ret = avcodec_open2(avcodecContext,nullptr,nullptr) το κάνει αυτό εσωτερικά.
Ο βασικός κώδικας είναι μέσα

if (codec2->init) {
        
Στην πραγματικότητα, θα ονομάζεται:
static av_cold int aac_encode_init(AVCodecContext *avctx)