19 ffmpeg中的AVClass和AVOption

先看它的使用,知道使用后就非常简单了。如果不看使用,直接看实现的话,那可够看的。


AVCodec ff_libx264_encoder = {
    .name           = "libx264",
    .type           = AVMEDIA_TYPE_VIDEO,
    .id             = CODEC_ID_H264,
    .priv_data_size = sizeof(X264Context),
    .init           = X264_init,
    .encode         = X264_frame,
    .close          = X264_close,
    .capabilities   = CODEC_CAP_DELAY,
    .pix_fmts       = (const enum PixelFormat[]) { PIX_FMT_YUV420P, PIX_FMT_YUVJ420P, PIX_FMT_NONE },
    .long_name      = NULL_IF_CONFIG_SMALL("libx264 H.264 / AVC / MPEG-4 AVC / MPEG-4 part 10"),
    .priv_class     = &class,
};

static const AVClass class = { "libx264", av_default_item_name, options, LIBAVUTIL_VERSION_INT };

static const AVOption options[] = {
    {"preset", "Set the encoding preset", OFFSET(preset), FF_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    {"tune", "Tune the encoding params", OFFSET(tune), FF_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    {"fastfirstpass", "Use fast settings when encoding first pass", OFFSET(fastfirstpass), FF_OPT_TYPE_INT, {.dbl=1}, 0, 1, VE},
    {"profile", "Set profile restrictions", OFFSET(profile), FF_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    {"level", "Specify level (as defined by Annex A)", OFFSET(level), FF_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    {"passlogfile", "Filename for 2 pass stats", OFFSET(stats), FF_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    {"wpredp", "Weighted prediction for P-frames", OFFSET(weightp), FF_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    {"x264opts", "x264 options", OFFSET(x264opts), FF_OPT_TYPE_STRING, {.str=NULL}, 0, 0, VE},
    { NULL },
};

typedef struct X264Context {
    AVClass        *class;
    x264_param_t    params;
    x264_t         *enc;
    x264_picture_t  pic;
    uint8_t        *sei;
    int             sei_size;
    AVFrame         out_pic;
    char *preset;
    char *tune;
    char *profile;
    char *level;
    int fastfirstpass;
    char *stats;
    char *weightp;
    char *x264opts;
} X264Context;

这是ffmpeg中libx264.h中对于AVClass和AVOption的使用。看它们的关系,static变量class为 AVCodec.priv_classs,options为变量class.option,sizeof(X264Context)为ff_libx264_encoder.priv_data_size。

有一个很明显的东西看options.name,譬如”preset”,在X264Context中有一个preset变量。这让我想起了java中的映射,通过一个字符串,也就是名字来获取到这个以字符串为名字的变量的值。

有一个特点是AVClass *class;是X264Context的第一个变量,并且必须是。在实现中,通过opeion中的一个偏移量来获取到这个变量的地址,那么必须得保证X264Context的地址和AVClass的地址必须一样,这样才能使用偏移量。

option有很多针对于int,double,string等类型的get,set操作,而真正操作的option里面的dictionary。看一个set的例子,我去掉很多代码后,真正的代码就两步:一步find,一步赋值。

static int av_set_number2(void *obj, const char *name, double num, int den, int64_t intnum, const AVOption **o_out)
{
    const AVOption *o = av_opt_find(obj, name, NULL, 0, 0);
    void *dst;
    dst= ((uint8_t*)obj) + o->offset;

    switch (o->type) {
    case FF_OPT_TYPE_FLAGS:
    case FF_OPT_TYPE_INT:   *(int       *)dst= llrint(num/den)*intnum; break;
    default:
        return AVERROR(EINVAL);
    }
    return 0;
}

虽然说实现的时候ffmpeg考虑到了很多东东。但是功能非常清晰了。

你可能感兴趣的:(ffmpeg)