2 * Copyright (c) 2012 Stefano Sabatini
4 * This file is part of FFmpeg.
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
23 * bounding box detection filter
26 #include "libavutil/opt.h"
27 #include "libavutil/pixdesc.h"
28 #include "libavutil/timestamp.h"
38 #define OFFSET(x) offsetof(BBoxContext, x)
39 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_FILTERING_PARAM
41 static const AVOption bbox_options
[] = {
42 { "min_val", "set minimum luminance value for bounding box", OFFSET(min_val
), AV_OPT_TYPE_INT
, { .i64
= 16 }, 0, 254, FLAGS
},
46 AVFILTER_DEFINE_CLASS(bbox
);
48 static int query_formats(AVFilterContext
*ctx
)
50 static const enum AVPixelFormat pix_fmts
[] = {
59 ff_set_common_formats(ctx
, ff_make_format_list(pix_fmts
));
63 #define SET_META(key, value) \
64 av_dict_set_int(metadata, key, value, 0);
66 static int filter_frame(AVFilterLink
*inlink
, AVFrame
*frame
)
68 AVFilterContext
*ctx
= inlink
->dst
;
69 BBoxContext
*bbox
= ctx
->priv
;
74 ff_calculate_bounding_box(&box
,
75 frame
->data
[0], frame
->linesize
[0],
76 inlink
->w
, inlink
->h
, bbox
->min_val
);
77 w
= box
.x2
- box
.x1
+ 1;
78 h
= box
.y2
- box
.y1
+ 1;
80 av_log(ctx
, AV_LOG_INFO
,
81 "n:%"PRId64
" pts:%s pts_time:%s", inlink
->frame_count
,
82 av_ts2str(frame
->pts
), av_ts2timestr(frame
->pts
, &inlink
->time_base
));
85 AVDictionary
**metadata
= avpriv_frame_get_metadatap(frame
);
87 SET_META("lavfi.bbox.x1", box
.x1
)
88 SET_META("lavfi.bbox.x2", box
.x2
)
89 SET_META("lavfi.bbox.y1", box
.y1
)
90 SET_META("lavfi.bbox.y2", box
.y2
)
91 SET_META("lavfi.bbox.w", w
)
92 SET_META("lavfi.bbox.h", h
)
94 av_log(ctx
, AV_LOG_INFO
,
95 " x1:%d x2:%d y1:%d y2:%d w:%d h:%d"
96 " crop=%d:%d:%d:%d drawbox=%d:%d:%d:%d",
97 box
.x1
, box
.x2
, box
.y1
, box
.y2
, w
, h
,
98 w
, h
, box
.x1
, box
.y1
, /* crop params */
99 box
.x1
, box
.y1
, w
, h
); /* drawbox params */
101 av_log(ctx
, AV_LOG_INFO
, "\n");
103 return ff_filter_frame(inlink
->dst
->outputs
[0], frame
);
106 static const AVFilterPad bbox_inputs
[] = {
109 .type
= AVMEDIA_TYPE_VIDEO
,
110 .filter_frame
= filter_frame
,
115 static const AVFilterPad bbox_outputs
[] = {
118 .type
= AVMEDIA_TYPE_VIDEO
,
123 AVFilter ff_vf_bbox
= {
125 .description
= NULL_IF_CONFIG_SMALL("Compute bounding box for each frame."),
126 .priv_size
= sizeof(BBoxContext
),
127 .priv_class
= &bbox_class
,
128 .query_formats
= query_formats
,
129 .inputs
= bbox_inputs
,
130 .outputs
= bbox_outputs
,
131 .flags
= AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
,