ffmpeg过滤器文件结构

1 Context 结构

用于存储过滤器需要的数据,例如vf_drawbox.c中的

typedef struct DrawBoxContext {
    const AVClass *class;
    int x, y, w, h;
    int thickness;
    char *color_str;
    unsigned char yuv_color[4];
    int invert_color; ///< invert luma color
    int vsub, hsub;   ///< chroma subsampling
    char *x_expr, *y_expr; ///< expression for x and y
    char *w_expr, *h_expr; ///< expression for width and height
    char *t_expr;          ///< expression for thickness
    int have_alpha;
} DrawBoxContext;
  1. AVClass的作用参考
    FFmpeg源代码简单分析:结构体成员管理系统-AVClass
  2. x,y是框左上角的坐标
    w,h是框的宽和高
    thick是框线条的厚度,thick=max就变成矩形了
  3. char *x_expr 是为了增加程序的灵活性与健壮性,在命令行里面可以输入表达式,计算后再将其转换为int
  4. have_alpha是透明度,取值区间为[0,1]

2 init函数

把color的字符串转换为rgb数组就是在这里实现的

static av_cold int init(AVFilterContext *ctx)
{
    DrawBoxContext *s = ctx->priv;
    uint8_t rgba_color[4];

    if (!strcmp(s->color_str, "invert"))
        s->invert_color = 1;
    else if (av_parse_color(rgba_color, s->color_str, -1, ctx) < 0)
        return AVERROR(EINVAL);

    if (!s->invert_color) {
        s->yuv_color[Y] = RGB_TO_Y_CCIR(rgba_color[0], rgba_color[1], rgba_color[2]);
        s->yuv_color[U] = RGB_TO_U_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0);
        s->yuv_color[V] = RGB_TO_V_CCIR(rgba_color[0], rgba_color[1], rgba_color[2], 0);
        s->yuv_color[A] = rgba_color[3];
    }

    return 0;
}

3 query_formats

static int query_formats(AVFilterContext *ctx)
{
    static const enum AVPixelFormat pix_fmts[] = {
        AV_PIX_FMT_YUV444P,  AV_PIX_FMT_YUV422P,  AV_PIX_FMT_YUV420P,
        AV_PIX_FMT_YUV411P,  AV_PIX_FMT_YUV410P,
        AV_PIX_FMT_YUVJ444P, AV_PIX_FMT_YUVJ422P, AV_PIX_FMT_YUVJ420P,
        AV_PIX_FMT_YUV440P,  AV_PIX_FMT_YUVJ440P,
        AV_PIX_FMT_YUVA420P, AV_PIX_FMT_YUVA422P, AV_PIX_FMT_YUVA444P,
        AV_PIX_FMT_NONE
    };
    AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
    if (!fmts_list)
        return AVERROR(ENOMEM);
    return ff_set_common_formats(ctx, fmts_list);
}

Query formats supported by the filter on its inputs and outputs.

This callback is called after the filter is initialized (so the inputs and outputs are fixed), shortly before the format negotiation. This callback may be called more than once.

This callback must set AVFilterLink.out_formats on every input link and AVFilterLink.in_formats on every output link to a list of pixel/sample formats that the filter supports on that link. For audio links, this filter must also set in_samplerates / out_samplerates and in_channel_layouts / out_channel_layouts analogously.

This callback may be NULL for filters with one input, in which case libavfilter assumes that it supports all input formats and preserves them on output.

Returns
zero on success, a negative value corresponding to an AVERROR code otherwise

4 config_input

static int config_input(AVFilterLink *inlink)
{
    AVFilterContext *ctx = inlink->dst;
    DrawBoxContext *s = ctx->priv;
    const AVPixFmtDescriptor *desc = av_pix_fmt_desc_get(inlink->format);
    double var_values[VARS_NB], res;
    char *expr;
    int ret;
    int i;

这里在执行DrawBoxContext *s = ctx->priv后s里面的int w,h,x,y等都是0,只是expr有值,执行完后转换出int类型的值

5 filter_frame

static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
{
    DrawBoxContext *s = inlink->dst->priv;
/*执行完config input后再执行这一句,s里面的int x,y,w,h就有值了*/

6 最后定义几个结构体

AVOption

定义位于./libavutil/opt.h:246
格式为

const char * name

const char * help
 //short English help text More...

int offset
 //The offset relative to the context structure where the option value is stored. More...

enum AVOptionType type

union {
   int64_t   i64

   double   dbl

   const char *   str

   AVRational   q

} default_val
// the default value for scalar options More...

double min
 //minimum valid value for the option More...

double max
// maximum valid value for the option More...

int flags

const char * unit
 //The logical unit to which the option belongs. 

参考
FFmpeg源代码简单分析:结构体成员管理系统-AVOption

static const AVOption drawbox_options[] = {
    { "x",         "set horizontal position of the left box edge", OFFSET(x_expr),    AV_OPT_TYPE_STRING, { .str="0" },       CHAR_MIN, CHAR_MAX, FLAGS },
    { "y",         "set vertical position of the top box edge",    OFFSET(y_expr),    AV_OPT_TYPE_STRING, { .str="0" },       CHAR_MIN, CHAR_MAX, FLAGS },
    ......

AVFilterPad用于描述filter的输入输出


static const AVFilterPad drawbox_inputs[] = {
    {
        .name           = "default",
        .type           = AVMEDIA_TYPE_VIDEO,
        .config_props   = config_input,
        .filter_frame   = filter_frame,
        .needs_writable = 1,
    },
    { NULL }
};

static const AVFilterPad drawbox_outputs[] = {
    {
        .name = "default",
        .type = AVMEDIA_TYPE_VIDEO,
    },
    { NULL }
};

AVFilterPad:Definition at line 66 of file avfilter.h.


AVFilter ff_vf_drawbox = {
    .name          = "drawbox",
    .description   = NULL_IF_CONFIG_SMALL("Draw a colored box on the input video."),
    .priv_size     = sizeof(DrawBoxContext),
    .priv_class    = &drawbox_class,
    .init          = init,
    .query_formats = query_formats,
    .inputs        = drawbox_inputs,
    .outputs       = drawbox_outputs,
    .flags         = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
};

执行顺序

采用GDB查看,执行顺序为
init->query_formats->config_input->filter_frame

你可能感兴趣的:(ffmpeg,ffmpeg)