Finding FFmpeg Encoders: ID and Name-Based Search Methods

Backgorund

When working with FFmpeg, it's often necessary to locate specific encoders either by their identifier or by their name. This article explores the methods available in FFmpeg for finding encoders and examines the underlying implementation.

Search Methods

FFmpeg provides two primary functions for finding encoders:

  • avcodec_find_encoder - Locates an encoder using its ID
  • avcodec_find_encoder_by_name - Finds an encoder by its name

Source Code Analysis

All supported encoders in FFmpeg are registered in the codec_list.c file, stored in a codec_list structure. This structure contains both encoders and decoders, with the final element being NULL to facilitate iteration within FFmpeg's internal algorithms.

static const FFCodec *codec_list[] = {
    &ff_a64multi_encoder,
    &ff_a64multi5_encoder,
    &ff_alias_pix_encoder,
    &ff_amv_encoder,
    ...
    &ff_av1_decoder,
    NULL
};

The search functions primarily work by iterating through the codec_list structure. The process first checks if an element is an encoder using the av_codec_is_encoder function, then compares the ID with the provided value. Note that many encoders share the same ID (such as NVIDIA, AMD, and x264 all having AV_CODEC_ID_H264), so searching by ID may return the first matching encoder in the list. The avcodec_find_encoder_by_name function follows a similar process but compares names instead of IDs.

The av_codec_iterate function implements an iterator pattern similar to those found in C++, incrementing an index until reaching the NULL terminator in the codec_list structure.

Implementation Details

// From allcodecs.c
const AVCodec *avcodec_find_encoder(enum AVCodecID id)
{
    return find_codec(id, av_codec_is_encoder);
}

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); // Compatibility code

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

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

// Determines if an AVCodec is an encoder
int av_codec_is_encoder(const AVCodec *avcodec)
{
    const FFCodec *const codec = ffcodec(avcodec);
    return codec && (codec->cb_type == FF_CODEC_CB_TYPE_ENCODE     ||
                     codec->cb_type == FF_CODEC_CB_TYPE_ENCODE_SUB ||
                     codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_PACKET);
}

Practical Example

The AAC encoder in aacenc.c demonstrates how a encoder is defined:

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,
};

#define CODEC_LONG_NAME(str) .p.long_name = str
#define FF_CODEC_ENCODE_CB(func)                          \
    .cb_type           = FF_CODEC_CB_TYPE_ENCODE,         \
    .cb.encode         = (func)

Understanding AVCodec to FFCodec Conversion

A key question is why AVCodec can be safely cast to FFCodec:

int av_codec_is_encoder(const AVCodec *avcodec)
{
    const FFCodec *const codec = ffcodec(avcodec);
    return codec && (codec->cb_type == FF_CODEC_CB_TYPE_ENCODE     ||
                     codec->cb_type == FF_CODEC_CB_TYPE_ENCODE_SUB ||
                     codec->cb_type == FF_CODEC_CB_TYPE_RECEIVE_PACKET);
}

The FFCodec structure definition reveals that AVCodec p is defined as the first element in FFCodec. When an AVCodec is created using the FFCodec framwork, a direct cast allows access to the corresponding FFCodec object. However, if an AVCodec is independently created, such a cast would be invalid. This approach relies on following FFmpeg's conventions, as deviating from them can lead to difficult-to-debug issues.

typedef struct FFCodec {
    /**
     * The public AVCodec. See codec.h for it.
     */
    AVCodec p;

    /**
     * Internal codec capabilities FF_CODEC_CAP_*.
     */
    unsigned caps_internal:29;

    /**
     * This field determines the type of the codec (decoder/encoder)
     * and also the exact callback cb implemented by the codec.
     * cb_type uses enum FFCodecType values.
     */
    unsigned cb_type:3;
    
    // ...

    /**
     * List of supported codec_tags, terminated by FF_CODEC_TAGS_END.
     */
    const uint32_t *codec_tags;
} FFCodec;

Tags: ffmpeg AVCodec FFCodec codec-search media-encoding

Posted on Sat, 19 Sep 2026 16:55:20 +0000 by vestax1984