FFmpeg
vf_dnn_processing.c
Go to the documentation of this file.
1 /*
2  * Copyright (c) 2019 Guo Yejun
3  *
4  * This file is part of FFmpeg.
5  *
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.
10  *
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.
15  *
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
19  */
20 
21 /**
22  * @file
23  * implementing a generic image processing filter using deep learning networks.
24  */
25 
26 #include "libavformat/avio.h"
27 #include "libavutil/opt.h"
28 #include "libavutil/pixdesc.h"
29 #include "libavutil/avassert.h"
30 #include "libavutil/imgutils.h"
31 #include "avfilter.h"
32 #include "dnn_interface.h"
33 #include "formats.h"
34 #include "internal.h"
35 
36 typedef struct DnnProcessingContext {
37  const AVClass *class;
38 
43 
46 
47  // input & output of the model at execution time
51 
52 #define OFFSET(x) offsetof(DnnProcessingContext, x)
53 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM
54 static const AVOption dnn_processing_options[] = {
55  { "dnn_backend", "DNN backend", OFFSET(backend_type), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, "backend" },
56  { "native", "native backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 0 }, 0, 0, FLAGS, "backend" },
57 #if (CONFIG_LIBTENSORFLOW == 1)
58  { "tensorflow", "tensorflow backend flag", 0, AV_OPT_TYPE_CONST, { .i64 = 1 }, 0, 0, FLAGS, "backend" },
59 #endif
60  { "model", "path to model file", OFFSET(model_filename), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
61  { "input", "input name of the model", OFFSET(model_inputname), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
62  { "output", "output name of the model", OFFSET(model_outputname), AV_OPT_TYPE_STRING, { .str = NULL }, 0, 0, FLAGS },
63  { NULL }
64 };
65 
66 AVFILTER_DEFINE_CLASS(dnn_processing);
67 
69 {
70  DnnProcessingContext *ctx = context->priv;
71 
72  if (!ctx->model_filename) {
73  av_log(ctx, AV_LOG_ERROR, "model file for network is not specified\n");
74  return AVERROR(EINVAL);
75  }
76  if (!ctx->model_inputname) {
77  av_log(ctx, AV_LOG_ERROR, "input name of the model network is not specified\n");
78  return AVERROR(EINVAL);
79  }
80  if (!ctx->model_outputname) {
81  av_log(ctx, AV_LOG_ERROR, "output name of the model network is not specified\n");
82  return AVERROR(EINVAL);
83  }
84 
86  if (!ctx->dnn_module) {
87  av_log(ctx, AV_LOG_ERROR, "could not create DNN module for requested backend\n");
88  return AVERROR(ENOMEM);
89  }
90  if (!ctx->dnn_module->load_model) {
91  av_log(ctx, AV_LOG_ERROR, "load_model for network is not specified\n");
92  return AVERROR(EINVAL);
93  }
94 
95  ctx->model = (ctx->dnn_module->load_model)(ctx->model_filename);
96  if (!ctx->model) {
97  av_log(ctx, AV_LOG_ERROR, "could not load DNN model\n");
98  return AVERROR(EINVAL);
99  }
100 
101  return 0;
102 }
103 
105 {
106  static const enum AVPixelFormat pix_fmts[] = {
110  };
111  AVFilterFormats *fmts_list = ff_make_format_list(pix_fmts);
112  return ff_set_common_formats(context, fmts_list);
113 }
114 
115 #define LOG_FORMAT_CHANNEL_MISMATCH() \
116  av_log(ctx, AV_LOG_ERROR, \
117  "the frame's format %s does not match " \
118  "the model input channel %d\n", \
119  av_get_pix_fmt_name(fmt), \
120  model_input->channels);
121 
122 static int check_modelinput_inlink(const DNNData *model_input, const AVFilterLink *inlink)
123 {
124  AVFilterContext *ctx = inlink->dst;
125  enum AVPixelFormat fmt = inlink->format;
126 
127  // the design is to add explicit scale filter before this filter
128  if (model_input->height != -1 && model_input->height != inlink->h) {
129  av_log(ctx, AV_LOG_ERROR, "the model requires frame height %d but got %d\n",
130  model_input->height, inlink->h);
131  return AVERROR(EIO);
132  }
133  if (model_input->width != -1 && model_input->width != inlink->w) {
134  av_log(ctx, AV_LOG_ERROR, "the model requires frame width %d but got %d\n",
135  model_input->width, inlink->w);
136  return AVERROR(EIO);
137  }
138 
139  switch (fmt) {
140  case AV_PIX_FMT_RGB24:
141  case AV_PIX_FMT_BGR24:
142  if (model_input->channels != 3) {
144  return AVERROR(EIO);
145  }
146  if (model_input->dt != DNN_FLOAT && model_input->dt != DNN_UINT8) {
147  av_log(ctx, AV_LOG_ERROR, "only support dnn models with input data type as float32 and uint8.\n");
148  return AVERROR(EIO);
149  }
150  return 0;
151  case AV_PIX_FMT_GRAY8:
152  if (model_input->channels != 1) {
154  return AVERROR(EIO);
155  }
156  if (model_input->dt != DNN_UINT8) {
157  av_log(ctx, AV_LOG_ERROR, "only support dnn models with input data type uint8.\n");
158  return AVERROR(EIO);
159  }
160  return 0;
161  case AV_PIX_FMT_GRAYF32:
162  if (model_input->channels != 1) {
164  return AVERROR(EIO);
165  }
166  if (model_input->dt != DNN_FLOAT) {
167  av_log(ctx, AV_LOG_ERROR, "only support dnn models with input data type float32.\n");
168  return AVERROR(EIO);
169  }
170  return 0;
171  default:
172  av_log(ctx, AV_LOG_ERROR, "%s not supported.\n", av_get_pix_fmt_name(fmt));
173  return AVERROR(EIO);
174  }
175 
176  return 0;
177 }
178 
180 {
181  AVFilterContext *context = inlink->dst;
182  DnnProcessingContext *ctx = context->priv;
184  DNNData model_input;
185  int check;
186 
187  result = ctx->model->get_input(ctx->model->model, &model_input, ctx->model_inputname);
188  if (result != DNN_SUCCESS) {
189  av_log(ctx, AV_LOG_ERROR, "could not get input from the model\n");
190  return AVERROR(EIO);
191  }
192 
193  check = check_modelinput_inlink(&model_input, inlink);
194  if (check != 0) {
195  return check;
196  }
197 
198  ctx->input.width = inlink->w;
199  ctx->input.height = inlink->h;
200  ctx->input.channels = model_input.channels;
201  ctx->input.dt = model_input.dt;
202 
203  result = (ctx->model->set_input_output)(ctx->model->model,
204  &ctx->input, ctx->model_inputname,
205  (const char **)&ctx->model_outputname, 1);
206  if (result != DNN_SUCCESS) {
207  av_log(ctx, AV_LOG_ERROR, "could not set input and output for the model\n");
208  return AVERROR(EIO);
209  }
210 
211  return 0;
212 }
213 
214 static int config_output(AVFilterLink *outlink)
215 {
216  AVFilterContext *context = outlink->src;
217  DnnProcessingContext *ctx = context->priv;
219 
220  // have a try run in case that the dnn model resize the frame
221  result = (ctx->dnn_module->execute_model)(ctx->model, &ctx->output, 1);
222  if (result != DNN_SUCCESS){
223  av_log(ctx, AV_LOG_ERROR, "failed to execute model\n");
224  return AVERROR(EIO);
225  }
226 
227  outlink->w = ctx->output.width;
228  outlink->h = ctx->output.height;
229 
230  return 0;
231 }
232 
233 static int copy_from_frame_to_dnn(DNNData *dnn_input, const AVFrame *frame)
234 {
235  int bytewidth = av_image_get_linesize(frame->format, frame->width, 0);
236 
237  switch (frame->format) {
238  case AV_PIX_FMT_RGB24:
239  case AV_PIX_FMT_BGR24:
240  if (dnn_input->dt == DNN_FLOAT) {
241  float *dnn_input_data = dnn_input->data;
242  for (int i = 0; i < frame->height; i++) {
243  for(int j = 0; j < frame->width * 3; j++) {
244  int k = i * frame->linesize[0] + j;
245  int t = i * frame->width * 3 + j;
246  dnn_input_data[t] = frame->data[0][k] / 255.0f;
247  }
248  }
249  } else {
250  av_assert0(dnn_input->dt == DNN_UINT8);
251  av_image_copy_plane(dnn_input->data, bytewidth,
252  frame->data[0], frame->linesize[0],
253  bytewidth, frame->height);
254  }
255  return 0;
256  case AV_PIX_FMT_GRAY8:
257  case AV_PIX_FMT_GRAYF32:
258  av_image_copy_plane(dnn_input->data, bytewidth,
259  frame->data[0], frame->linesize[0],
260  bytewidth, frame->height);
261  return 0;
262  default:
263  return AVERROR(EIO);
264  }
265 
266  return 0;
267 }
268 
269 static int copy_from_dnn_to_frame(AVFrame *frame, const DNNData *dnn_output)
270 {
271  int bytewidth = av_image_get_linesize(frame->format, frame->width, 0);
272 
273  switch (frame->format) {
274  case AV_PIX_FMT_RGB24:
275  case AV_PIX_FMT_BGR24:
276  if (dnn_output->dt == DNN_FLOAT) {
277  float *dnn_output_data = dnn_output->data;
278  for (int i = 0; i < frame->height; i++) {
279  for(int j = 0; j < frame->width * 3; j++) {
280  int k = i * frame->linesize[0] + j;
281  int t = i * frame->width * 3 + j;
282  frame->data[0][k] = av_clip_uintp2((int)(dnn_output_data[t] * 255.0f), 8);
283  }
284  }
285  } else {
286  av_assert0(dnn_output->dt == DNN_UINT8);
287  av_image_copy_plane(frame->data[0], frame->linesize[0],
288  dnn_output->data, bytewidth,
289  bytewidth, frame->height);
290  }
291  return 0;
292  case AV_PIX_FMT_GRAY8:
293  // it is possible that data type of dnn output is float32,
294  // need to add support for such case when needed.
295  av_assert0(dnn_output->dt == DNN_UINT8);
296  av_image_copy_plane(frame->data[0], frame->linesize[0],
297  dnn_output->data, bytewidth,
298  bytewidth, frame->height);
299  return 0;
300  case AV_PIX_FMT_GRAYF32:
301  av_assert0(dnn_output->dt == DNN_FLOAT);
302  av_image_copy_plane(frame->data[0], frame->linesize[0],
303  dnn_output->data, bytewidth,
304  bytewidth, frame->height);
305  return 0;
306  default:
307  return AVERROR(EIO);
308  }
309 
310  return 0;
311 }
312 
314 {
315  AVFilterContext *context = inlink->dst;
316  AVFilterLink *outlink = context->outputs[0];
317  DnnProcessingContext *ctx = context->priv;
318  DNNReturnType dnn_result;
319  AVFrame *out;
320 
321  copy_from_frame_to_dnn(&ctx->input, in);
322 
323  dnn_result = (ctx->dnn_module->execute_model)(ctx->model, &ctx->output, 1);
324  if (dnn_result != DNN_SUCCESS){
325  av_log(ctx, AV_LOG_ERROR, "failed to execute model\n");
326  av_frame_free(&in);
327  return AVERROR(EIO);
328  }
329 
330  out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
331  if (!out) {
332  av_frame_free(&in);
333  return AVERROR(ENOMEM);
334  }
335 
336  av_frame_copy_props(out, in);
337  copy_from_dnn_to_frame(out, &ctx->output);
338  av_frame_free(&in);
339  return ff_filter_frame(outlink, out);
340 }
341 
343 {
345 
346  if (context->dnn_module)
347  (context->dnn_module->free_model)(&context->model);
348 
349  av_freep(&context->dnn_module);
350 }
351 
353  {
354  .name = "default",
355  .type = AVMEDIA_TYPE_VIDEO,
356  .config_props = config_input,
357  .filter_frame = filter_frame,
358  },
359  { NULL }
360 };
361 
363  {
364  .name = "default",
365  .type = AVMEDIA_TYPE_VIDEO,
366  .config_props = config_output,
367  },
368  { NULL }
369 };
370 
372  .name = "dnn_processing",
373  .description = NULL_IF_CONFIG_SMALL("Apply DNN processing filter to the input."),
374  .priv_size = sizeof(DnnProcessingContext),
375  .init = init,
376  .uninit = uninit,
378  .inputs = dnn_processing_inputs,
379  .outputs = dnn_processing_outputs,
380  .priv_class = &dnn_processing_class,
381 };
void * model
Definition: dnn_interface.h:45
#define NULL
Definition: coverity.c:32
int av_image_get_linesize(enum AVPixelFormat pix_fmt, int width, int plane)
Compute the size of an image line with format pix_fmt and width width for the plane plane...
Definition: imgutils.c:76
Buffered I/O operations.
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
AVOption.
Definition: opt.h:246
static const AVOption dnn_processing_options[]
void(* free_model)(DNNModel **model)
Definition: dnn_interface.h:61
const char * fmt
Definition: avisynth_c.h:861
misc image utilities
Main libavfilter public API header.
packed RGB 8:8:8, 24bpp, RGBRGB...
Definition: pixfmt.h:68
#define OFFSET(x)
int channels
Definition: dnn_interface.h:40
static const AVFilterPad dnn_processing_outputs[]
static int copy_from_frame_to_dnn(DNNData *dnn_input, const AVFrame *frame)
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition: video.c:99
static int copy_from_dnn_to_frame(AVFrame *frame, const DNNData *dnn_output)
static av_cold void uninit(AVFilterContext *ctx)
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
const char * name
Pad name.
Definition: internal.h:60
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
DNNModel *(* load_model)(const char *model_filename)
Definition: dnn_interface.h:57
AVFilter ff_vf_dnn_processing
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:82
AVOptions.
#define f(width, name)
Definition: cbs_vp9.c:255
static int check_modelinput_inlink(const DNNData *model_input, const AVFilterLink *inlink)
static int config_input(AVFilterLink *inlink)
DNNBackendType
Definition: dnn_interface.h:33
#define av_log(a,...)
A filter pad used for either input or output.
Definition: internal.h:54
DNNReturnType(* get_input)(void *model, DNNData *input, const char *input_name)
Definition: dnn_interface.h:48
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
int width
Definition: frame.h:353
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
int ff_set_common_formats(AVFilterContext *ctx, AVFilterFormats *formats)
A helper for query_formats() which sets all links to the same list of formats.
Definition: formats.c:569
int height
Definition: dnn_interface.h:40
static av_cold int init(AVFilterContext *context)
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification. ...
Definition: internal.h:186
void * data
Definition: dnn_interface.h:38
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().
AVFormatContext * ctx
Definition: movenc.c:48
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
packed RGB 8:8:8, 24bpp, BGRBGR...
Definition: pixfmt.h:69
static const AVFilterPad dnn_processing_inputs[]
AVFILTER_DEFINE_CLASS(dnn_processing)
DNN inference engine interface.
DNNReturnType
Definition: dnn_interface.h:31
static const AVFilterPad outputs[]
Definition: af_acontrast.c:203
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
#define AV_PIX_FMT_GRAYF32
Definition: pixfmt.h:419
int linesize[AV_NUM_DATA_POINTERS]
For video, size in bytes of each picture line.
Definition: frame.h:326
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several inputs
uint8_t pi<< 24) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0f/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_U8, uint8_t,(*(const uint8_t *) pi-0x80)*(1.0/(1<< 7))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S16, int16_t,(*(const int16_t *) pi >> 8)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0f/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S16, int16_t,*(const int16_t *) pi *(1.0/(1<< 15))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_S32, int32_t,(*(const int32_t *) pi >> 24)+0x80) CONV_FUNC_GROUP(AV_SAMPLE_FMT_FLT, float, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0f/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_DBL, double, AV_SAMPLE_FMT_S32, int32_t,*(const int32_t *) pi *(1.0/(1U<< 31))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_FLT, float, av_clip_uint8(lrintf(*(const float *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_FLT, float, av_clip_int16(lrintf(*(const float *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_FLT, float, av_clipl_int32(llrintf(*(const float *) pi *(1U<< 31)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_U8, uint8_t, AV_SAMPLE_FMT_DBL, double, av_clip_uint8(lrint(*(const double *) pi *(1<< 7))+0x80)) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S16, int16_t, AV_SAMPLE_FMT_DBL, double, av_clip_int16(lrint(*(const double *) pi *(1<< 15)))) CONV_FUNC_GROUP(AV_SAMPLE_FMT_S32, int32_t, AV_SAMPLE_FMT_DBL, double, av_clipl_int32(llrint(*(const double *) pi *(1U<< 31))))#define SET_CONV_FUNC_GROUP(ofmt, ifmt) static void set_generic_function(AudioConvert *ac){}void ff_audio_convert_free(AudioConvert **ac){if(!*ac) return;ff_dither_free(&(*ac) ->dc);av_freep(ac);}AudioConvert *ff_audio_convert_alloc(AVAudioResampleContext *avr, enum AVSampleFormat out_fmt, enum AVSampleFormat in_fmt, int channels, int sample_rate, int apply_map){AudioConvert *ac;int in_planar, out_planar;ac=av_mallocz(sizeof(*ac));if(!ac) return NULL;ac->avr=avr;ac->out_fmt=out_fmt;ac->in_fmt=in_fmt;ac->channels=channels;ac->apply_map=apply_map;if(avr->dither_method!=AV_RESAMPLE_DITHER_NONE &&av_get_packed_sample_fmt(out_fmt)==AV_SAMPLE_FMT_S16 &&av_get_bytes_per_sample(in_fmt) > 2){ac->dc=ff_dither_alloc(avr, out_fmt, in_fmt, channels, sample_rate, apply_map);if(!ac->dc){av_free(ac);return NULL;}return ac;}in_planar=ff_sample_fmt_is_planar(in_fmt, channels);out_planar=ff_sample_fmt_is_planar(out_fmt, channels);if(in_planar==out_planar){ac->func_type=CONV_FUNC_TYPE_FLAT;ac->planes=in_planar?ac->channels:1;}else if(in_planar) ac->func_type=CONV_FUNC_TYPE_INTERLEAVE;else ac->func_type=CONV_FUNC_TYPE_DEINTERLEAVE;set_generic_function(ac);if(ARCH_AARCH64) ff_audio_convert_init_aarch64(ac);if(ARCH_ARM) ff_audio_convert_init_arm(ac);if(ARCH_X86) ff_audio_convert_init_x86(ac);return ac;}int ff_audio_convert(AudioConvert *ac, AudioData *out, AudioData *in){int use_generic=1;int len=in->nb_samples;int p;if(ac->dc){av_log(ac->avr, AV_LOG_TRACE,"%d samples - audio_convert: %s to %s (dithered)\n", len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt));return ff_convert_dither(ac-> in
Describe the class of an AVClass context structure.
Definition: log.h:67
Filter definition.
Definition: avfilter.h:144
static int query_formats(AVFilterContext *context)
const char * name
Filter name.
Definition: avfilter.h:148
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:275
DNNModule * ff_get_dnn_module(DNNBackendType backend_type)
Definition: dnn_interface.c:31
DNNReturnType(* execute_model)(const DNNModel *model, DNNData *outputs, uint32_t nb_output)
Definition: dnn_interface.h:59
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:309
The exact code depends on how similar the blocks are and how related they are to the and needs to apply these operations to the correct inlink or outlink if there are several Macros are available to factor that when no extra processing is inlink
Y , 8bpp.
Definition: pixfmt.h:74
static int filter_frame(AVFilterLink *inlink, AVFrame *in)
#define LOG_FORMAT_CHANNEL_MISMATCH()
A list of supported formats for one end of a filter link.
Definition: formats.h:64
An instance of a filter.
Definition: avfilter.h:338
and forward the result(frame or status change) to the corresponding input.If nothing is possible
int height
Definition: frame.h:353
FILE * out
Definition: movenc.c:54
#define av_freep(p)
DNNReturnType(* set_input_output)(void *model, DNNData *input, const char *input_name, const char **output_names, uint32_t nb_output)
Definition: dnn_interface.h:51
DNNBackendType backend_type
void av_image_copy_plane(uint8_t *dst, int dst_linesize, const uint8_t *src, int src_linesize, int bytewidth, int height)
Copy image plane from src to dst.
Definition: imgutils.c:338
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2438
internal API functions
static int config_output(AVFilterLink *outlink)
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later.That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another.Frame references ownership and permissions
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option keep it simple and lowercase description are in without and describe what they for example set the foo of the bar offset is the offset of the field in your local context
DNNDataType dt
Definition: dnn_interface.h:39
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
#define FLAGS
#define check(x, y, S, v)