紧接上一篇文章,字幕内容的修改可以通过av_opt_set修改AVFilterContext的priv来实现,那么字幕和水印的位置是否也可以这样呢?
打开vf_drawtext.c和vf_overlayer.c这两个文件,发现它们都有名为"x"和"y"的设置,然而当我采用av_opt_set将这两个值设置之后,图像位置却没有发生改变,仔细阅读源码,可以看到这两个滤镜都有这样几个变量:
char *x_expr, *y_expr;
AVExpr *x_pexpr, *y_pexpr;
其中x_expr和y_expr是对应滤镜的AVOption中"x"和"y",然而在这两个滤镜在输出时,并不是处理x_expr和y_expr将值赋给AVFilterContext的x和y,而是从x_pexpr和y_pexpr取值,x_pexpr和y_pexpr仅在初始化时从x_expr和y_expr得到设置时的值,这样我就知道需要怎样修改了。
字幕需要修改vf_drawtext.c的draw_text函数,找到
s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng);
修改成:
av_expr_parse(&s->x_pexpr, s->x_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx);
av_expr_parse(&s->y_pexpr, s->y_expr, var_names, NULL, NULL, fun2_names, fun2, 0, ctx);
s->x = s->var_values[VAR_X] = av_expr_eval(s->x_pexpr, s->var_values, &s->prng);
s->y = s->var_values[VAR_Y] = av_expr_eval(s->y_pexpr, s->var_values, &s->prng);
这样滤镜在每次输出文字时就会重新读取一下AVOption的"x"和"y"。
水印需要修改vf_overlayer.c的do_blend函数,找到
eval_expr(ctx);
修改成:
set_expr(&s->x_pexpr, s->x_expr, "x", ctx);
set_expr(&s->y_pexpr, s->y_expr, "y", ctx);
eval_expr(ctx);
这样每次滤镜在每次输出时,就会重读一下"x"和"y"了。
完成修改后,重新编译ffmpeg,然后就可以在程序中使用
av_opt_set(filter_ctx3->priv, "x", str3, 0 );
av_opt_set(filter_ctx3->priv, "y", str4, 0 );
来重新给水印设置坐标了,其中filter_ctx3是参照上篇文章获取的水印的AVFilterContext,str3和str4是要设置的x和y值的字符串