return ret;
}
+static av_pure av_always_inline int pixel_belongs_to_box(DrawBoxContext *s, int x, int y)
+{
+ return (y - s->y < s->thickness) || (s->y + s->h - 1 - y < s->thickness) ||
+ (x - s->x < s->thickness) || (s->x + s->w - 1 - x < s->thickness);
+}
+
static int filter_frame(AVFilterLink *inlink, AVFrame *frame)
{
DrawBoxContext *s = inlink->dst->priv;
if (s->invert_color) {
for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++)
- if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
- (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness))
+ if (pixel_belongs_to_box(s, x, y))
row[0][x] = 0xff - row[0][x];
} else {
for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) {
- if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
- (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) {
+ if (pixel_belongs_to_box(s, x, y)) {
row[0][x ] = s->yuv_color[Y];
row[1][x >> s->hsub] = s->yuv_color[U];
row[2][x >> s->hsub] = s->yuv_color[V];
if (s->invert_color) {
for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++)
- if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
- (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness))
+ if (pixel_belongs_to_box(s, x, y))
row[0][x] = 0xff - row[0][x];
} else {
for (x = FFMAX(xb, 0); x < xb + s->w && x < frame->width; x++) {
double alpha = (double)s->yuv_color[A] / 255;
- if ((y - yb < s->thickness) || (yb + s->h - 1 - y < s->thickness) ||
- (x - xb < s->thickness) || (xb + s->w - 1 - x < s->thickness)) {
+ if (pixel_belongs_to_box(s, x, y)) {
row[0][x ] = (1 - alpha) * row[0][x ] + alpha * s->yuv_color[Y];
row[1][x >> s->hsub] = (1 - alpha) * row[1][x >> s->hsub] + alpha * s->yuv_color[U];
row[2][x >> s->hsub] = (1 - alpha) * row[2][x >> s->hsub] + alpha * s->yuv_color[V];
return ff_filter_frame(inlink->dst->outputs[0], frame);
}
+static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
+{
+ AVFilterLink *inlink = ctx->inputs[0];
+ DrawBoxContext *s = ctx->priv;
+ int old_x = s->x;
+ int old_y = s->y;
+ int old_w = s->w;
+ int old_h = s->h;
+ int old_t = s->thickness;
+ int old_r = s->replace;
+ int ret;
+
+ ret = ff_filter_process_command(ctx, cmd, args, res, res_len, flags);
+ if (ret < 0)
+ return ret;
+
+ ret = init(ctx);
+ if (ret < 0)
+ goto end;
+ ret = config_input(inlink);
+end:
+ if (ret < 0) {
+ s->x = old_x;
+ s->y = old_y;
+ s->w = old_w;
+ s->h = old_h;
+ s->thickness = old_t;
+ s->replace = old_r;
+ }
+
+ return ret;
+}
+
#define OFFSET(x) offsetof(DrawBoxContext, x)
-#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
+#define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
#if CONFIG_DRAWBOX_FILTER
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 },
- { "width", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "w", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "height", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "h", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "color", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "c", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "thickness", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "t", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS },
+ { "x", "set horizontal position of the left box edge", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "y", "set vertical position of the top box edge", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "width", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "w", "set width of the box", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "height", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "h", "set height of the box", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "color", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS },
+ { "c", "set color of the box", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS },
+ { "thickness", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, 0, 0, FLAGS },
+ { "t", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, 0, 0, FLAGS },
+ { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS },
{ NULL }
};
{ NULL }
};
-AVFilter ff_vf_drawbox = {
+const AVFilter ff_vf_drawbox = {
.name = "drawbox",
.description = NULL_IF_CONFIG_SMALL("Draw a colored box on the input video."),
.priv_size = sizeof(DrawBoxContext),
.query_formats = query_formats,
.inputs = drawbox_inputs,
.outputs = drawbox_outputs,
+ .process_command = process_command,
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
};
#endif /* CONFIG_DRAWBOX_FILTER */
}
static const AVOption drawgrid_options[] = {
- { "x", "set horizontal offset", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "y", "set vertical offset", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "width", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "w", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "height", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "h", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "color", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "c", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, CHAR_MIN, CHAR_MAX, FLAGS },
- { "thickness", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS },
- { "t", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, CHAR_MIN, CHAR_MAX, FLAGS },
+ { "x", "set horizontal offset", OFFSET(x_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "y", "set vertical offset", OFFSET(y_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "width", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "w", "set width of grid cell", OFFSET(w_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "height", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "h", "set height of grid cell", OFFSET(h_expr), AV_OPT_TYPE_STRING, { .str="0" }, 0, 0, FLAGS },
+ { "color", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS },
+ { "c", "set color of the grid", OFFSET(color_str), AV_OPT_TYPE_STRING, { .str = "black" }, 0, 0, FLAGS },
+ { "thickness", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, 0, 0, FLAGS },
+ { "t", "set grid line thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, {.str="1"}, 0, 0, FLAGS },
{ "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS },
{ NULL }
};
{ NULL }
};
-AVFilter ff_vf_drawgrid = {
+const AVFilter ff_vf_drawgrid = {
.name = "drawgrid",
.description = NULL_IF_CONFIG_SMALL("Draw a colored grid on the input video."),
.priv_size = sizeof(DrawBoxContext),
.inputs = drawgrid_inputs,
.outputs = drawgrid_outputs,
.flags = AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC,
+ .process_command = process_command,
};
#endif /* CONFIG_DRAWGRID_FILTER */