|
31 | 31 | #include "libavutil/eval.h" |
32 | 32 | #include "libavutil/pixdesc.h" |
33 | 33 | #include "libavutil/parseutils.h" |
| 34 | +#include "libavutil/detection_bbox.h" |
34 | 35 | #include "avfilter.h" |
35 | 36 | #include "formats.h" |
36 | 37 | #include "internal.h" |
@@ -79,8 +80,10 @@ typedef struct DrawBoxContext { |
79 | 80 | char *x_expr, *y_expr; ///< expression for x and y |
80 | 81 | char *w_expr, *h_expr; ///< expression for width and height |
81 | 82 | char *t_expr; ///< expression for thickness |
| 83 | + char *box_source_string; ///< string for box data source |
82 | 84 | int have_alpha; |
83 | 85 | int replace; |
| 86 | + enum AVFrameSideDataType box_source; |
84 | 87 | } DrawBoxContext; |
85 | 88 |
|
86 | 89 | static const int NUM_EXPR_EVALS = 5; |
@@ -140,11 +143,30 @@ static void draw_region(AVFrame *frame, DrawBoxContext *ctx, int left, int top, |
140 | 143 | } |
141 | 144 | } |
142 | 145 |
|
| 146 | +static enum AVFrameSideDataType box_source_string_parse(const char *box_source_string) |
| 147 | +{ |
| 148 | + av_assert0(box_source_string); |
| 149 | + if (!strcmp(box_source_string, "side_data_detection_bboxes")) { |
| 150 | + return AV_FRAME_DATA_DETECTION_BBOXES; |
| 151 | + } else { |
| 152 | + // will support side_data_regions_of_interest next |
| 153 | + return AVERROR(EINVAL); |
| 154 | + } |
| 155 | +} |
| 156 | + |
143 | 157 | static av_cold int init(AVFilterContext *ctx) |
144 | 158 | { |
145 | 159 | DrawBoxContext *s = ctx->priv; |
146 | 160 | uint8_t rgba_color[4]; |
147 | 161 |
|
| 162 | + if (s->box_source_string) { |
| 163 | + s->box_source = box_source_string_parse(s->box_source_string); |
| 164 | + if ((int)s->box_source < 0) { |
| 165 | + av_log(ctx, AV_LOG_ERROR, "Error box source: %s\n",s->box_source_string); |
| 166 | + return AVERROR(EINVAL); |
| 167 | + } |
| 168 | + } |
| 169 | + |
148 | 170 | if (!strcmp(s->color_str, "invert")) |
149 | 171 | s->invert_color = 1; |
150 | 172 | else if (av_parse_color(rgba_color, s->color_str, -1, ctx) < 0) |
@@ -272,9 +294,34 @@ static av_pure av_always_inline int pixel_belongs_to_box(DrawBoxContext *s, int |
272 | 294 | static int filter_frame(AVFilterLink *inlink, AVFrame *frame) |
273 | 295 | { |
274 | 296 | DrawBoxContext *s = inlink->dst->priv; |
| 297 | + const AVDetectionBBoxHeader *header = NULL; |
| 298 | + const AVDetectionBBox *bbox; |
| 299 | + AVFrameSideData *sd; |
| 300 | + int loop = 1; |
| 301 | + |
| 302 | + if (s->box_source == AV_FRAME_DATA_DETECTION_BBOXES) { |
| 303 | + sd = av_frame_get_side_data(frame, AV_FRAME_DATA_DETECTION_BBOXES); |
| 304 | + if (sd) { |
| 305 | + header = (AVDetectionBBoxHeader *)sd->data; |
| 306 | + loop = header->nb_bboxes; |
| 307 | + } else { |
| 308 | + av_log(s, AV_LOG_WARNING, "No detection bboxes.\n"); |
| 309 | + return ff_filter_frame(inlink->dst->outputs[0], frame); |
| 310 | + } |
| 311 | + } |
275 | 312 |
|
276 | | - draw_region(frame, s, FFMAX(s->x, 0), FFMAX(s->y, 0), FFMIN(s->x + s->w, frame->width), |
277 | | - FFMIN(s->y + s->h, frame->height), pixel_belongs_to_box); |
| 313 | + for (int i = 0; i < loop; i++) { |
| 314 | + if (header) { |
| 315 | + bbox = av_get_detection_bbox(header, i); |
| 316 | + s->y = bbox->y; |
| 317 | + s->x = bbox->x; |
| 318 | + s->h = bbox->h; |
| 319 | + s->w = bbox->w; |
| 320 | + } |
| 321 | + |
| 322 | + draw_region(frame, s, FFMAX(s->x, 0), FFMAX(s->y, 0), FFMIN(s->x + s->w, frame->width), |
| 323 | + FFMIN(s->y + s->h, frame->height), pixel_belongs_to_box); |
| 324 | + } |
278 | 325 |
|
279 | 326 | return ff_filter_frame(inlink->dst->outputs[0], frame); |
280 | 327 | } |
@@ -329,6 +376,7 @@ static const AVOption drawbox_options[] = { |
329 | 376 | { "thickness", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, 0, 0, FLAGS }, |
330 | 377 | { "t", "set the box thickness", OFFSET(t_expr), AV_OPT_TYPE_STRING, { .str="3" }, 0, 0, FLAGS }, |
331 | 378 | { "replace", "replace color & alpha", OFFSET(replace), AV_OPT_TYPE_BOOL, { .i64=0 }, 0, 1, FLAGS }, |
| 379 | + { "box_source", "use datas from bounding box in side data", OFFSET(box_source_string), AV_OPT_TYPE_STRING, { .str=NULL }, 0, 1, FLAGS }, |
332 | 380 | { NULL } |
333 | 381 | }; |
334 | 382 |
|
|
0 commit comments