Skip to content

Decoder walkthrough

Luca Barbato edited this page Aug 31, 2013 · 2 revisions

Libavcodec decoder

Completely New Codec

New Codec ID

If the codec ID does not exist in libavcodec, you have to add a new Codec ID, by appending its name to enum AVCodecID in libavcodec/avcodec.h. The enum is partitioned, append the new AV_CODEC_ID_CODECNAME to the right sublist. E.G. a new video code has to be put at the end of the video codec list, before AV_CODEC_ID_FIRST_AUDIO.

Codec Description

The codecs in Libavcodec have a structured description in libavcodec/codec_desc.c, static const AVCodecDescriptor codec_descriptors.

    {
        .id        = AV_CODEC_ID_MPEG1VIDEO,
        .type      = AVMEDIA_TYPE_VIDEO,
        .name      = "mpeg1video",
        .long_name = NULL_IF_CONFIG_SMALL("MPEG-1 video"),
        .props     = AV_CODEC_PROP_LOSSY,
    },

id : The Codec ID previously defined in libavcodec/avcodec.h type : The media type name : The codec string identifier, should be short and a single word, it is used in long_name : A string describing in a more verbose the codec. props : Codec specific properties, defined in libavcodec/avcodec.h using the AV_CODEC_PROP_ namespace

Codec Registry

In order to be used a codec must be registered. The function avcodec_register_all in libavcodec/allcodecs.c registers all the codecs available in the current libav build.

#define REGISTER_DECODER(X, x)                                          \
    {                                                                   \
        extern AVCodec ff_##x##_decoder;                                \
        if (CONFIG_##X##_DECODER)                                       \
            avcodec_register(&ff_##x##_decoder);                        \
    }
    
     REGISTER_DECODER(H264,              h264)
    

You have to add a REGISTER_DECODER entry using the Codec ID and a codec specific namespace, usually it matches the codec name. (e.g. h264)

Files layout

The decoder code lives in libavcodec in a file named after the codec name. If a decode and encoder are present the common layout is to move all the common code in name.c and namedec.c nameenc.c (e.g. ac3.c aac.h ac3dec.c ac3enc.c)

Makefile

OBJS-$(CONFIG_NAME)                 += namedec.o name.o

CONFIG_NAME is automatically generated by configure by reading allcodecs.c

Basic structure

A decoder is actually implemented as an AVCodec structure. The structure contains a numer of ancillary information, capabilities and the actual functions doing the decoding. A decoder implements a decode function, optionally an init, init_static_data flush and close function can be provided when needed.

AVCodec ff_decodername_decoder = {
    .name           = "name",
    .long_name      = NULL_IF_CONFIG_SMALL("descriptive long string"),
    .priv_data_size = sizeof(DecoderNameContext),
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = AV_CODEC_ID_NAME,
    .init           = name_dec_init,
    .init_static_data = name_dec_static_data,
    .decode         = name_dec_frame,
    .flush          = name_dec_flush,
    .close          = name_dec_close,
    .capabilities   = CODEC_CAP_DELAY | CODEC_CAP_PKT_TS,
};

name : Short name e.g. h264, must be unique over all the decoders in Libav. There can be multiple decoders for the same cID long_name : Longer string giving more details, the macro NULL_IF_CONFIG_SMALL drops it if you are targeting memory constrained platform. priv_data_size : Size of the private context if needed, it will hold the codec state type : Type of the codec (video audio or audio or subtitle) id : The Codec ID init : The function used to initialize the decoder state (a private NameContext struct), extradata should be parsed in this function. init_static_data : The function should contain all the static initialization, it is called only once. You should use it to allocate specific global, read-only, state. decode : The function consumes an AVPacket and produces an AVFrame flush : This function is called on seek, it should reset the decoder state. close : Must cleanup all the resources allocated by the decoder

Functions in detail

init

typedef struct NameContext {
    int field;
} NameContext;
static av_cold int name_dec_init(AVCodecContext *avctx)
{
    NameContext *c = avctx->priv_data;
    int err;
    if ((err = parse_extradata(c, avctx->extradata, avctx->extradata_size)) < 0);
        return err;
    
    return 0;
}

init_static_data

static int name_lookup[1024];
static av_cold void name_init_static_data(AVCodec *codec)
{
   initialize(name_lookup);
}

decode

static int name_dec_frame(AVCodecContext *avctx, void *data,
                                            int *got_frame, AVPacket *avpkt)
{
    
    
}