-
Notifications
You must be signed in to change notification settings - Fork 9
Decoder walkthrough
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.
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
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)
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)
OBJS-$(CONFIG_NAME) += namedec.o name.o
CONFIG_NAME is automatically generated by configure by reading allcodecs.c
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
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;
}
static int name_lookup[1024];
static av_cold void name_init_static_data(AVCodec *codec)
{
initialize(name_lookup);
}
static int name_dec_frame(AVCodecContext *avctx, void *data,
int *got_frame, AVPacket *avpkt)
{
}