FFmpeg  4.3.9
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  NULL,
42 };
43 
44 typedef struct AddROIContext {
45  const AVClass *class;
46 
49 
52 
53  int clear;
55 
56 static int addroi_config_input(AVFilterLink *inlink)
57 {
58  AVFilterContext *avctx = inlink->dst;
59  AddROIContext *ctx = avctx->priv;
60  int i;
61  double vars[NB_VARS];
62  double val;
63 
64  vars[VAR_IW] = inlink->w;
65  vars[VAR_IH] = inlink->h;
66 
67  for (i = 0; i < NB_PARAMS; i++) {
68  int max_value;
69  switch (i) {
70  case X: max_value = inlink->w; break;
71  case Y: max_value = inlink->h; break;
72  case W: max_value = inlink->w - ctx->region[X]; break;
73  case H: max_value = inlink->h - ctx->region[Y]; break;
74  }
75 
76  val = av_expr_eval(ctx->region_expr[i], vars, NULL);
77  if (val < 0.0) {
78  av_log(avctx, AV_LOG_WARNING, "Calculated value %g for %s is "
79  "less than zero - using zero instead.\n", val,
81  val = 0.0;
82  } else if (val > max_value) {
83  av_log(avctx, AV_LOG_WARNING, "Calculated value %g for %s is "
84  "greater than maximum allowed value %d - "
85  "using %d instead.\n", val, addroi_param_names[i],
86  max_value, max_value);
87  val = max_value;
88  }
89  ctx->region[i] = val;
90  }
91 
92  return 0;
93 }
94 
96 {
97  AVFilterContext *avctx = inlink->dst;
98  AVFilterLink *outlink = avctx->outputs[0];
99  AddROIContext *ctx = avctx->priv;
100  AVRegionOfInterest *roi;
101  AVFrameSideData *sd;
102  int err;
103 
104  if (ctx->clear) {
106  sd = NULL;
107  } else {
109  }
110  if (sd) {
111  const AVRegionOfInterest *old_roi;
112  uint32_t old_roi_size;
113  AVBufferRef *roi_ref;
114  int nb_roi, i;
115 
116  old_roi = (const AVRegionOfInterest*)sd->data;
117  old_roi_size = old_roi->self_size;
118  av_assert0(old_roi_size && sd->size % old_roi_size == 0);
119  nb_roi = sd->size / old_roi_size + 1;
120 
121  roi_ref = av_buffer_alloc(sizeof(*roi) * nb_roi);
122  if (!roi_ref) {
123  err = AVERROR(ENOMEM);
124  goto fail;
125  }
126  roi = (AVRegionOfInterest*)roi_ref->data;
127 
128  for (i = 0; i < nb_roi - 1; i++) {
129  old_roi = (const AVRegionOfInterest*)
130  (sd->data + old_roi_size * i);
131 
132  roi[i] = (AVRegionOfInterest) {
133  .self_size = sizeof(*roi),
134  .top = old_roi->top,
135  .bottom = old_roi->bottom,
136  .left = old_roi->left,
137  .right = old_roi->right,
138  .qoffset = old_roi->qoffset,
139  };
140  }
141 
142  roi[nb_roi - 1] = (AVRegionOfInterest) {
143  .self_size = sizeof(*roi),
144  .top = ctx->region[Y],
145  .bottom = ctx->region[Y] + ctx->region[H],
146  .left = ctx->region[X],
147  .right = ctx->region[X] + ctx->region[W],
148  .qoffset = ctx->qoffset,
149  };
150 
152 
155  roi_ref);
156  if (!sd) {
157  av_buffer_unref(&roi_ref);
158  err = AVERROR(ENOMEM);
159  goto fail;
160  }
161 
162  } else {
164  sizeof(AVRegionOfInterest));
165  if (!sd) {
166  err = AVERROR(ENOMEM);
167  goto fail;
168  }
169  roi = (AVRegionOfInterest*)sd->data;
170  *roi = (AVRegionOfInterest) {
171  .self_size = sizeof(*roi),
172  .top = ctx->region[Y],
173  .bottom = ctx->region[Y] + ctx->region[H],
174  .left = ctx->region[X],
175  .right = ctx->region[X] + ctx->region[W],
176  .qoffset = ctx->qoffset,
177  };
178  }
179 
180  return ff_filter_frame(outlink, frame);
181 
182 fail:
183  av_frame_free(&frame);
184  return err;
185 }
186 
188 {
189  AddROIContext *ctx = avctx->priv;
190  int i, err;
191 
192  for (i = 0; i < NB_PARAMS; i++) {
193  err = av_expr_parse(&ctx->region_expr[i], ctx->region_str[i],
195  0, avctx);
196  if (err < 0) {
197  av_log(ctx, AV_LOG_ERROR,
198  "Error parsing %s expression '%s'.\n",
199  addroi_param_names[i], ctx->region_str[i]);
200  return err;
201  }
202  }
203 
204  return 0;
205 }
206 
208 {
209  AddROIContext *ctx = avctx->priv;
210  int i;
211 
212  for (i = 0; i < NB_PARAMS; i++) {
213  av_expr_free(ctx->region_expr[i]);
214  ctx->region_expr[i] = NULL;
215  }
216 }
217 
218 #define OFFSET(x) offsetof(AddROIContext, x)
219 #define FLAGS AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM
220 static const AVOption addroi_options[] = {
221  { "x", "Region distance from left edge of frame.",
222  OFFSET(region_str[X]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
223  { "y", "Region distance from top edge of frame.",
224  OFFSET(region_str[Y]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
225  { "w", "Region width.",
226  OFFSET(region_str[W]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
227  { "h", "Region height.",
228  OFFSET(region_str[H]), AV_OPT_TYPE_STRING, { .str = "0" }, .flags = FLAGS },
229 
230  { "qoffset", "Quantisation offset to apply in the region.",
231  OFFSET(qoffset), AV_OPT_TYPE_RATIONAL, { .dbl = -0.1 }, -1, +1, FLAGS },
232 
233  { "clear", "Remove any existing regions of interest before adding the new one.",
234  OFFSET(clear), AV_OPT_TYPE_BOOL, { .i64 = 0 }, 0, 1, FLAGS },
235 
236  { NULL }
237 };
238 
239 AVFILTER_DEFINE_CLASS(addroi);
240 
241 static const AVFilterPad addroi_inputs[] = {
242  {
243  .name = "default",
244  .type = AVMEDIA_TYPE_VIDEO,
245  .config_props = addroi_config_input,
246  .filter_frame = addroi_filter_frame,
247  },
248  { NULL }
249 };
250 
251 static const AVFilterPad addroi_outputs[] = {
252  {
253  .name = "default",
254  .type = AVMEDIA_TYPE_VIDEO,
255  },
256  { NULL }
257 };
258 
260  .name = "addroi",
261  .description = NULL_IF_CONFIG_SMALL("Add region of interest to frame."),
262  .init = addroi_init,
263  .uninit = addroi_uninit,
264 
265  .priv_size = sizeof(AddROIContext),
266  .priv_class = &addroi_class,
267 
268  .inputs = addroi_inputs,
269  .outputs = addroi_outputs,
270 };
#define NULL
Definition: coverity.c:32
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:240
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
This structure describes decoded (raw) audio or video data.
Definition: frame.h:300
AVOption.
Definition: opt.h:246
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
Definition: vf_addroi.c:26
Main libavfilter public API header.
static const AVOption addroi_options[]
Definition: vf_addroi.c:220
static av_cold void addroi_uninit(AVFilterContext *avctx)
Definition: vf_addroi.c:207
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
static int addroi_filter_frame(AVFilterLink *inlink, AVFrame *frame)
Definition: vf_addroi.c:95
AVExpr * region_expr[NB_PARAMS]
Definition: vf_addroi.c:48
AVRational qoffset
Quantisation offset.
Definition: frame.h:267
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition: frame.c:739
const char * name
Pad name.
Definition: internal.h:60
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
Definition: vf_addroi.c:26
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition: avfilter.c:1075
#define av_cold
Definition: attributes.h:88
AVOptions.
Definition: eval.c:157
static AVFrame * frame
Structure to hold side data for an AVFrame.
Definition: frame.h:206
Definition: vf_addroi.c:26
uint32_t self_size
Must be set to the size of this data structure (that is, sizeof(AVRegionOfInterest)).
Definition: frame.h:230
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:54
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:188
void * priv
private data for use by the filter
Definition: avfilter.h:353
simple assert() macros that are a bit more flexible than ISO C assert().
#define fail()
Definition: checkasm.h:123
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:695
AVFormatContext * ctx
Definition: movenc.c:48
Structure describing a single Region Of Interest.
Definition: frame.h:225
AVRational qoffset
Definition: vf_addroi.c:51
static const AVFilterPad inputs[]
Definition: af_acontrast.c:193
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
static const uint8_t vars[2][12]
Definition: camellia.c:179
void av_expr_free(AVExpr *e)
Free a parsed expression previously created with av_expr_parse().
Definition: eval.c:336
AVBufferRef * av_buffer_alloc(int size)
Allocate an AVBuffer of the given size using av_malloc().
Definition: buffer.c:67
AVFILTER_DEFINE_CLASS(addroi)
static const char *const addroi_var_names[]
Definition: vf_addroi.c:38
uint8_t * data
The data buffer.
Definition: buffer.h:89
uint8_t * data
Definition: frame.h:208
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:813
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
AVFrameSideData * av_frame_new_side_data(AVFrame *frame, enum AVFrameSideDataType type, int size)
Add a new side data to a frame.
Definition: frame.c:727
Rational number (pair of numerator and denominator).
Definition: rational.h:58
Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of array element is ...
Definition: frame.h:181
static const AVFilterPad addroi_outputs[]
Definition: vf_addroi.c:251
#define OFFSET(x)
Definition: vf_addroi.c:218
const char * name
Filter name.
Definition: avfilter.h:148
static const char * addroi_param_names[]
Definition: vf_addroi.c:29
char * region_str[NB_PARAMS]
Definition: vf_addroi.c:47
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
static av_cold int addroi_init(AVFilterContext *avctx)
Definition: vf_addroi.c:187
A reference to a data buffer.
Definition: buffer.h:81
#define FLAGS
Definition: vf_addroi.c:219
int region[NB_PARAMS]
Definition: vf_addroi.c:50
AVFilter ff_vf_addroi
Definition: vf_addroi.c:259
double av_expr_eval(AVExpr *e, const double *const_values, void *opaque)
Evaluate a previously parsed expression.
Definition: eval.c:766
static int addroi_config_input(AVFilterLink *inlink)
Definition: vf_addroi.c:56
An instance of a filter.
Definition: avfilter.h:338
Definition: vf_addroi.c:26
internal API functions
static double val(void *priv, double ch)
Definition: aeval.c:76
for(j=16;j >0;--j)
simple arithmetic expression evaluator
static const AVFilterPad addroi_inputs[]
Definition: vf_addroi.c:241