FFmpeg  4.4
vf_addroi.c
Go to the documentation of this file.
1 /*
2  * This file is part of FFmpeg.
3  *
4  * FFmpeg is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * FFmpeg is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with FFmpeg; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "libavutil/avassert.h"
20 #include "libavutil/eval.h"
21 #include "libavutil/opt.h"
22 #include "avfilter.h"
23 #include "internal.h"
24 
25 enum {
26  X, Y, W, H,
28 };
29 static const char addroi_param_names[] = {
30  'x', 'y', 'w', 'h',
31 };
32 
33 enum {
37 };
38 static const char *const addroi_var_names[] = {
39  "iw",
40  "ih",
41 };
42 
43 typedef struct AddROIContext {
44  const AVClass *class;
45 
48 
51 
52  int clear;
54 
55 static int addroi_config_input(AVFilterLink *inlink)
56 {
57  AVFilterContext *avctx = inlink->dst;
58  AddROIContext *ctx = avctx->priv;
59  int i;
60  double vars[NB_VARS];
61  double val;
62 
63  vars[VAR_IW] = inlink->w;
64  vars[VAR_IH] = inlink->h;
65 
66  for (i = 0; i < NB_PARAMS; i++) {
67  int max_value;
68  switch (i) {
69  case X: max_value = inlink->w; break;
70  case Y: max_value = inlink->h; break;
71  case W: max_value = inlink->w - ctx->region[X]; break;
72  case H: max_value = inlink->h - ctx->region[Y]; break;
73  }
74 
75  val = av_expr_eval(ctx->region_expr[i], vars, NULL);
76  if (val < 0.0) {
77  av_log(avctx, AV_LOG_WARNING, "Calculated value %g for %c is "
78  "less than zero - using zero instead.\n", val,
80  val = 0.0;
81  } else if (val > max_value) {
82  av_log(avctx, AV_LOG_WARNING, "Calculated value %g for %c is "
83  "greater than maximum allowed value %d - "
84  "using %d instead.\n", val, addroi_param_names[i],
85  max_value, max_value);
86  val = max_value;
87  }
88  ctx->region[i] = val;
89  }
90 
91  return 0;
92 }
93 
95 {
96  AVFilterContext *avctx = inlink->dst;
97  AVFilterLink *outlink = avctx->outputs[0];
98  AddROIContext *ctx = avctx->priv;
99  AVRegionOfInterest *roi;
100  AVFrameSideData *sd;
101  int err;
102 
103  if (ctx->clear) {
105  sd = NULL;
106  } else {
108  }
109  if (sd) {
110  const AVRegionOfInterest *old_roi;
111  uint32_t old_roi_size;
112  AVBufferRef *roi_ref;
113  int nb_roi, i;
114 
115  old_roi = (const AVRegionOfInterest*)sd->data;
116  old_roi_size = old_roi->self_size;
117  av_assert0(old_roi_size && sd->size % old_roi_size == 0);
118  nb_roi = sd->size / old_roi_size + 1;
119 
120  roi_ref = av_buffer_alloc(sizeof(*roi) * nb_roi);
121  if (!roi_ref) {
122  err = AVERROR(ENOMEM);
123  goto fail;
124  }
125  roi = (AVRegionOfInterest*)roi_ref->data;
126 
127  for (i = 0; i < nb_roi - 1; i++) {
128  old_roi = (const AVRegionOfInterest*)
129  (sd->data + old_roi_size * i);
130 
131  roi[i] = (AVRegionOfInterest) {
132  .self_size = sizeof(*roi),
133  .top = old_roi->top,
134  .bottom = old_roi->bottom,
135  .left = old_roi->left,
136  .right = old_roi->right,
137  .qoffset = old_roi->qoffset,
138  };
139  }
140 
141  roi[nb_roi - 1] = (AVRegionOfInterest) {
142  .self_size = sizeof(*roi),
143  .top = ctx->region[Y],
144  .bottom = ctx->region[Y] + ctx->region[H],
145  .left = ctx->region[X],
146  .right = ctx->region[X] + ctx->region[W],
147  .qoffset = ctx->qoffset,
148  };
149 
151 
154  roi_ref);
155  if (!sd) {
156  av_buffer_unref(&roi_ref);
157  err = AVERROR(ENOMEM);
158  goto fail;
159  }
160 
161  } else {
163  sizeof(AVRegionOfInterest));
164  if (!sd) {
165  err = AVERROR(ENOMEM);
166  goto fail;
167  }
168  roi = (AVRegionOfInterest*)sd->data;
169  *roi = (AVRegionOfInterest) {
170  .self_size = sizeof(*roi),
171  .top = ctx->region[Y],
172  .bottom = ctx->region[Y] + ctx->region[H],
173  .left = ctx->region[X],
174  .right = ctx->region[X] + ctx->region[W],
175  .qoffset = ctx->qoffset,
176  };
177  }
178 
179  return ff_filter_frame(outlink, frame);
180 
181 fail:
183  return err;
184 }
185 
187 {
188  AddROIContext *ctx = avctx->priv;
189  int i, err;
190 
191  for (i = 0; i < NB_PARAMS; i++) {
192  err = av_expr_parse(&ctx->region_expr[i], ctx->region_str[i],
194  0, avctx);
195  if (err < 0) {
197  "Error parsing %c expression '%s'.\n",
198  addroi_param_names[i], ctx->region_str[i]);
199  return err;
200  }
201  }
202 
203  return 0;
204 }
205 
207 {
208  AddROIContext *ctx = avctx->priv;
209  int i;
210 
211  for (i = 0; i < NB_PARAMS; i++) {
212  av_expr_free(ctx->region_expr[i]);
213  ctx->region_expr[i] = NULL;
214  }
215 }
216 
217 #define OFFSET(x) offsetof(AddROIContext, x)
218 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
219 static const AVOption addroi_options[] = {
220  { "x", "Region distance from left edge of frame.",
221  OFFSET(region_str[X]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
222  { "y", "Region distance from top edge of frame.",
223  OFFSET(region_str[Y]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
224  { "w", "Region width.",
225  OFFSET(region_str[W]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
226  { "h", "Region height.",
227  OFFSET(region_str[H]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
228 
229  { "qoffset", "Quantisation offset to apply in the region.",
230  OFFSET(qoffset), AV_OPT_TYPE_RATIONAL, { .dbl = -0.1 }, -1, +1, FLAGS },
231 
232  { "clear", "Remove any existing regions of interest before adding the new one.",
233  OFFSET(clear), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
234 
235  { NULL }
236 };
237 
239 
240 static const AVFilterPad addroi_inputs[] = {
241  {
242  .name = "default",
243  .type = AVMEDIA_TYPE_VIDEO,
244  .config_props = addroi_config_input,
245  .filter_frame = addroi_filter_frame,
246  },
247  { NULL }
248 };
249 
250 static const AVFilterPad addroi_outputs[] = {
251  {
252  .name = "default",
253  .type = AVMEDIA_TYPE_VIDEO,
254  },
255  { NULL }
256 };
257 
259  .name = "addroi",
260  .description = NULL_IF_CONFIG_SMALL("Add region of interest to frame."),
261  .init = addroi_init,
262  .uninit = addroi_uninit,
263 
264  .priv_size = sizeof(AddROIContext),
265  .priv_class = &addroi_class,
266 
269 };
static double val(void *priv, double ch)
Definition: aeval.c:76
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
#define av_cold
Definition: attributes.h:88
simple assert() macros that are a bit more flexible than ISO C assert().
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1094
Main libavfilter public API header.
static const uint8_t vars[2][12]
Definition: camellia.c:179
#define fail()
Definition: checkasm.h:133
#define NULL
Definition: coverity.c:32
static AVFrame * frame
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:336
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:766
int av_expr_parse(AVExpr **expr, const char *s, const char *const *const_names, const char *const *func1_names, double(*const *funcs1)(void *, double), const char *const *func2_names, double(*const *funcs2)(void *, double, double), int log_offset, void *log_ctx)
Parse an expression.
Definition: eval.c:685
simple arithmetic expression evaluator
@ AV_OPT_TYPE_RATIONAL
Definition: opt.h:230
@ AV_OPT_TYPE_BOOL
Definition: opt.h:242
@ AV_OPT_TYPE_STRING
Definition: opt.h:229
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition: buffer.c:125
AVBufferRef * av_buffer_alloc(buffer_size_t size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
#define AVERROR(e)
Definition: error.h:43
void av_frame_remove_side_data(AVFrame *frame, enum AVFrameSideDataType type)
Remove and free all side data instances of the given type.
Definition: frame.c:812
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
AVFrameSideData * av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, buffer_size_t size)
Add a new side data to a frame.
Definition: frame.c:726
AVFrameSideData * av_frame_new_side_data_from_buf(AVFrame *frame, enum AVFrameSideDataType type, AVBufferRef *buf)
Add a new side data to a frame from an existing AVBufferRef.
Definition: frame.c:694
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition: frame.c:738
@ AV_FRAME_DATA_REGIONS_OF_INTEREST
Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of array element is ...
Definition: frame.h:181
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:200
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
@ AVMEDIA_TYPE_VIDEO
Definition: avutil.h:201
for(j=16;j >0;--j)
int i
Definition: input.c:407
common internal API header
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition: internal.h:117
AVOptions.
A reference to a data buffer.
Definition: buffer.h:84
uint8_t * data
The data buffer.
Definition: buffer.h:92
Describe the class of an AVClass context structure.
Definition: log.h:67
Definition: eval.c:157
An instance of a filter.
Definition: avfilter.h:341
void * priv
private data for use by the filter
Definition: avfilter.h:356
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:353
A filter pad used for either input or output.
Definition: internal.h:54
const char * name
Pad name.
Definition: internal.h:60
Filter definition.
Definition: avfilter.h:145
const char * name
Filter name.
Definition: avfilter.h:149
Structure to hold side data for an AVFrame.
Definition: frame.h:220
uint8_t * data
Definition: frame.h:222
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
AVOption.
Definition: opt.h:248
Rational number (pair of numerator and denominator).
Definition: rational.h:58
Structure describing a single Region Of Interest.
Definition: frame.h:243
uint32_t self_size
Must be set to the size of this data structure (that is, sizeof(AVRegionOfInterest)).
Definition: frame.h:248
AVRational qoffset
Quantisation offset.
Definition: frame.h:285
int top
Distance in pixels from the top edge of the frame to the top and bottom edges and from the left edge ...
Definition: frame.h:258
char * region_str[NB_PARAMS]
Definition: vf_addroi.c:46
AVExpr * region_expr[NB_PARAMS]
Definition: vf_addroi.c:47
AVRational qoffset
Definition: vf_addroi.c:50
int region[NB_PARAMS]
Definition: vf_addroi.c:49
#define av_log(a,...)
AVFormatContext * ctx
Definition: movenc.c:48
static const char addroi_param_names[]
Definition: vf_addroi.c:29
static const char *const addroi_var_names[]
Definition: vf_addroi.c:38
static av_cold void addroi_uninit(AVFilterContext *avctx)
Definition: vf_addroi.c:206
static const AVFilterPad addroi_inputs[]
Definition: vf_addroi.c:240
#define FLAGS
Definition: vf_addroi.c:218
static int addroi_config_input(AVFilterLink *inlink)
Definition: vf_addroi.c:55
AVFilter ff_vf_addroi
Definition: vf_addroi.c:258
AVFILTER_DEFINE_CLASS(addroi)
static av_cold int addroi_init(AVFilterContext *avctx)
Definition: vf_addroi.c:186
static const AVOption addroi_options[]
Definition: vf_addroi.c:219
#define OFFSET(x)
Definition: vf_addroi.c:217
@ VAR_IW
Definition: vf_addroi.c:34
@ VAR_IH
Definition: vf_addroi.c:35
@ NB_VARS
Definition: vf_addroi.c:36
static const AVFilterPad addroi_outputs[]
Definition: vf_addroi.c:250
@ H
Definition: vf_addroi.c:26
@ Y
Definition: vf_addroi.c:26
@ X
Definition: vf_addroi.c:26
@ NB_PARAMS
Definition: vf_addroi.c:27
@ W
Definition: vf_addroi.c:26
static int addroi_filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition: vf_addroi.c:94