FFmpeg
Loading...
Searching...
No Matches
vf_feedback.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/**
20 * @file
21 * feedback video filter
22 */
23
24#include "libavutil/fifo.h"
25#include "libavutil/imgutils.h"
26#include "libavutil/opt.h"
27#include "libavutil/internal.h"
28#include "avfilter.h"
29#include "filters.h"
30#include "formats.h"
31#include "video.h"
32
33typedef struct FeedbackContext {
34 const AVClass *class;
35
36 int x, y;
37 int w, h;
38
39 int max_step[4];
40 int hsub, vsub;
41
43
46
48{
49 if (s->x + s->w > ctx->inputs[0]->w)
50 s->x = ctx->inputs[0]->w - s->w;
51 if (s->y + s->h > ctx->inputs[0]->h)
52 s->y = ctx->inputs[0]->h - s->h;
53}
54
56{
57 if (s->x >= ctx->inputs[0]->w)
58 s->x = 0;
59 if (s->y >= ctx->inputs[0]->h)
60 s->y = 0;
61
62 if (s->w <= 0)
63 s->w = ctx->inputs[0]->w - s->x;
64 if (s->h <= 0)
65 s->h = ctx->inputs[0]->h - s->y;
66
67 if (s->w > ctx->inputs[0]->w)
68 s->w = ctx->inputs[0]->w;
69 if (s->h > ctx->inputs[0]->h)
70 s->h = ctx->inputs[0]->h;
71
73}
74
75static int config_input(AVFilterLink *inlink)
76{
77 AVFilterContext *ctx = inlink->dst;
78 const AVPixFmtDescriptor *pix_desc = av_pix_fmt_desc_get(inlink->format);
79 FeedbackContext *s = ctx->priv;
80
81 s->hsub = pix_desc->log2_chroma_w;
82 s->vsub = pix_desc->log2_chroma_h;
83
84 av_image_fill_max_pixsteps(s->max_step, NULL, pix_desc);
85
87
88 ctx->inputs[1]->w = s->w;
89 ctx->inputs[1]->h = s->h;
90
91 return 0;
92}
93
94static int config_output(AVFilterLink *outlink)
95{
96 AVFilterContext *ctx = outlink->src;
97 FeedbackContext *s = ctx->priv;
98
100
101 ctx->outputs[0]->w = ctx->inputs[0]->w;
102 ctx->outputs[0]->h = ctx->inputs[0]->h;
103 ctx->outputs[1]->w = s->w;
104 ctx->outputs[1]->h = s->h;
105
106 return 0;
107}
108
118
120{
121 FeedbackContext *s = ctx->priv;
122 int status, ret;
123 int64_t pts;
124
125 adjust_pos(ctx, s);
126
127 for (int i = 0; i < ctx->nb_outputs; i++)
129
130 if (!s->feed) {
131 ret = ff_inlink_consume_frame(ctx->inputs[1], &s->feed);
132 if (ret < 0)
133 return ret;
134 }
135
136 if (s->feed && av_fifo_can_read(s->fifo)) {
137 AVFrame *src = s->feed;
138 AVFrame *dst = NULL;
139
140 av_fifo_read(s->fifo, &dst, 1);
141 if (!dst)
142 return AVERROR_BUG;
143
145 AVFrame *tmp = ff_get_video_buffer(ctx->outputs[0], ctx->outputs[0]->w, ctx->outputs[0]->h);
146
147 if (!tmp) {
149 return AVERROR(ENOMEM);
150 }
151
152 ret = av_frame_copy(tmp, dst);
153 if (ret < 0) {
156 return ret;
157 }
158
161 dst = tmp;
162 }
163
164 for (int y = 0; y < src->height; y++) {
165 memmove(dst->data[0] + (s->y + y) * dst->linesize[0] + s->x * s->max_step[0],
166 src->data[0] + y * src->linesize[0], src->width * s->max_step[0]);
167 }
168
169 for (int i = 1; i < 3; i++) {
170 if (dst->data[i]) {
171 for (int y = 0; y < src->height; y++) {
172 memmove(dst->data[i] + ((s->y + y) >> s->vsub) * dst->linesize[i] + (s->x >> s->hsub) * s->max_step[i],
173 src->data[i] + (y >> s->vsub) * src->linesize[i], (src->width >> s->hsub) * s->max_step[i]);
174 }
175 }
176 }
177
178 if (dst->data[3]) {
179 for (int y = 0; y < src->height; y++) {
180 memmove(dst->data[3] + (s->y + y) * dst->linesize[3] + s->x * s->max_step[3],
181 src->data[3] + y * src->linesize[3], src->width * s->max_step[3]);
182 }
183 }
184
185 ret = ff_filter_frame(ctx->outputs[0], dst);
186 av_frame_free(&s->feed);
187 return ret;
188 }
189
190 if (!s->feed || ctx->is_disabled) {
191 AVFrame *in = NULL;
192
193 ret = ff_inlink_consume_frame(ctx->inputs[0], &in);
194 if (ret < 0)
195 return ret;
196
197 if (ret > 0 && ctx->is_disabled)
198 return ff_filter_frame(ctx->outputs[0], in);
199
200 if (ret > 0) {
201 AVFrame *frame;
202
203 ret = av_fifo_write(s->fifo, &in, 1);
204 if (ret < 0) {
205 av_frame_free(&in);
206 return ret;
207 }
208
209 frame = av_frame_clone(in);
210 if (!frame)
211 return AVERROR(ENOMEM);
212
213 frame->width = s->w;
214 frame->height = s->h;
215
216 frame->data[0] += s->y * frame->linesize[0];
217 frame->data[0] += s->x * s->max_step[0];
218
219 for (int i = 1; i < 3; i ++) {
220 if (frame->data[i]) {
221 frame->data[i] += (s->y >> s->vsub) * frame->linesize[i];
222 frame->data[i] += (s->x >> s->hsub) * s->max_step[i];
223 }
224 }
225
226 if (frame->data[3]) {
227 frame->data[3] += s->y * frame->linesize[3];
228 frame->data[3] += s->x * s->max_step[3];
229 }
230
231 return ff_filter_frame(ctx->outputs[1], frame);
232 }
233 }
234
235 if (ff_inlink_acknowledge_status(ctx->inputs[0], &status, &pts)) {
236 ff_outlink_set_status(ctx->outputs[0], status, pts);
237 ff_outlink_set_status(ctx->outputs[1], status, pts);
238 return 0;
239 }
240
241 if (ff_inlink_acknowledge_status(ctx->inputs[1], &status, &pts)) {
242 ff_outlink_set_status(ctx->outputs[0], status, pts);
243 ff_outlink_set_status(ctx->outputs[1], status, pts);
244 return 0;
245 }
246
247 if (!s->feed || ctx->is_disabled) {
248 if (!ctx->is_disabled && ff_outlink_frame_wanted(ctx->outputs[1])) {
249 ff_inlink_request_frame(ctx->inputs[0]);
250 return 0;
251 }
252 if (ff_outlink_frame_wanted(ctx->outputs[0])) {
253 ff_inlink_request_frame(ctx->inputs[0]);
254 if (!ctx->is_disabled)
255 ff_inlink_request_frame(ctx->inputs[1]);
256 return 0;
257 }
258 }
259
260 return FFERROR_NOT_READY;
261}
262
264{
265 FeedbackContext *s = ctx->priv;
266
267 s->fifo = av_fifo_alloc2(8, sizeof(AVFrame *), AV_FIFO_FLAG_AUTO_GROW);
268 if (!s->fifo)
269 return AVERROR(ENOMEM);
270
271 return 0;
272}
273
275{
276 FeedbackContext *s = ctx->priv;
277 if (s->fifo) {
278 size_t size = av_fifo_can_read(s->fifo);
279
280 for (size_t n = 0; n < size; n++) {
281 AVFrame *frame = NULL;
282
283 av_fifo_read(s->fifo, &frame, 1);
284
286 }
287
288 av_fifo_freep2(&s->fifo);
289 }
290}
291
292static const AVFilterPad inputs[] = {
293 {
294 .name = "default",
295 .type = AVMEDIA_TYPE_VIDEO,
296 .config_props = config_input,
297 },
298 {
299 .name = "feedin",
300 .type = AVMEDIA_TYPE_VIDEO,
301 .config_props = config_input,
302 },
303};
304
305static const AVFilterPad outputs[] = {
306 {
307 .name = "default",
308 .type = AVMEDIA_TYPE_VIDEO,
309 .config_props = config_output,
310 },
311 {
312 .name = "feedout",
313 .type = AVMEDIA_TYPE_VIDEO,
314 .config_props = config_output,
315 },
316};
317
318#define OFFSET(x) offsetof(FeedbackContext, x)
319#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM)
320#define TFLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_RUNTIME_PARAM)
321
322static const AVOption feedback_options[] = {
323 { "x", "set top left crop position", OFFSET(x), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, TFLAGS },
324 { "y", "set top left crop position", OFFSET(y), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, TFLAGS },
325 { "w", "set crop size", OFFSET(w), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
326 { "h", "set crop size", OFFSET(h), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, INT_MAX, FLAGS },
327 { NULL }
328};
329
331
333 .p.name = "feedback",
334 .p.description = NULL_IF_CONFIG_SMALL("Apply feedback video filter."),
335 .p.priv_class = &feedback_class,
337 .priv_size = sizeof(FeedbackContext),
339 .init = init,
340 .uninit = uninit,
344 .process_command = ff_filter_process_command,
345};
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
Definition dsp.h:87
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
Definition aeval.c:246
static const AVFilterPad inputs[]
Definition af_aap.c:299
static const AVFilterPad outputs[]
Definition af_aap.c:310
static int config_input(AVFilterLink *inlink)
#define TFLAGS
Definition af_afade.c:66
const FFFilter ff_vf_feedback
static AVFormatContext * ctx
int ff_inlink_acknowledge_status(AVFilterLink *link, int *rstatus, int64_t *rpts)
Test and acknowledge the change of status on the link.
Definition avfilter.c:1467
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
int ff_outlink_frame_wanted(AVFilterLink *link)
Test if a frame is wanted on an output link.
Definition avfilter.c:1690
int ff_filter_process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Generic processing of user supplied commands that are set in the same way as the filter options.
Definition avfilter.c:906
int ff_inlink_consume_frame(AVFilterLink *link, AVFrame **rframe)
Take a frame from the link's FIFO and update the link's stats.
Definition avfilter.c:1520
void ff_inlink_request_frame(AVFilterLink *link)
Mark that a frame is wanted on the link.
Definition avfilter.c:1623
Main libavfilter public API header.
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
#define NULL
Definition coverity.c:32
long long int64_t
Definition coverity.c:34
static AVFrame * frame
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
A generic FIFO API.
int ff_set_common_formats2(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out, AVFilterFormats *formats)
Definition formats.c:1137
AVFilterFormats * ff_formats_pixdesc_filter(unsigned want, unsigned rej)
Construct a formats list containing all pixel formats with certain properties.
Definition formats.c:620
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
#define AVFILTER_FLAG_SUPPORT_TIMELINE_INTERNAL
Same as AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC, except that the filter will have its filter_frame() c...
Definition avfilter.h:204
#define AVERROR_BUG
Internal bug, also see AVERROR_BUG2.
Definition error.h:52
#define AVERROR(e)
Definition error.h:45
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition fifo.c:47
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition fifo.c:286
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
Definition fifo.h:63
size_t av_fifo_can_read(const AVFifo *f)
Definition fifo.c:87
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition fifo.c:188
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition fifo.c:240
int av_frame_is_writable(AVFrame *frame)
Check if the frame data is writable.
Definition frame.c:535
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition frame.c:64
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition frame.c:599
AVFrame * av_frame_clone(const AVFrame *src)
Create a new frame that references the same data as src.
Definition frame.c:483
int av_frame_copy(AVFrame *dst, const AVFrame *src)
Copy the frame data from src to dst.
Definition frame.c:711
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
void av_image_fill_max_pixsteps(int max_pixsteps[4], int max_pixstep_comps[4], const AVPixFmtDescriptor *pixdesc)
Compute the max pixel step for each plane of an image with a format described by pixdesc.
Definition imgutils.c:35
misc image utilities
static av_cold void uninit(AVBitStreamFilterContext *ctx)
static int activate(AVBitStreamFilterContext *ctx)
static int config_output(AVBitStreamFilterLink *outlink)
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
static void ff_outlink_set_status(AVFilterLink *link, int status, int64_t pts)
Set the status field of a link from the source filter.
Definition filters.h:629
#define FFERROR_NOT_READY
Filters implementation helper functions and internal structures.
Definition filters.h:34
#define FF_FILTER_FORWARD_STATUS_BACK_ALL(outlink, filter)
Forward the status on an output link to all input links.
Definition filters.h:652
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define FILTER_QUERY_FUNC2(func)
Definition filters.h:241
#define av_cold
Definition attributes.h:117
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:88
uint8_t w
Definition llvidencdsp.c:39
AVOptions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_FLAG_BITSTREAM
All values of a component are bit-wise packed end to end.
Definition pixdesc.h:124
#define AV_PIX_FMT_FLAG_HWACCEL
Pixel format is an HW accelerated format.
Definition pixdesc.h:128
#define AV_PIX_FMT_FLAG_PAL
Pixel format has a palette in data[1], values are indexes in this palette.
Definition pixdesc.h:120
Describe the class of an AVClass context structure.
Definition log.h:76
Definition fifo.c:35
An instance of a filter.
Definition avfilter.h:273
Lists of formats / etc.
Definition avfilter.h:120
A filter pad used for either input or output.
Definition filters.h:40
This structure describes decoded (raw) audio or video data.
Definition frame.h:472
AVOption.
Definition opt.h:428
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition pixdesc.h:69
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition pixdesc.h:80
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition pixdesc.h:89
AVFrame * feed
Definition vf_feedback.c:42
static uint8_t tmp[40]
Definition aes_ctr.c:52
#define src
Definition vp8dsp.c:248
static int64_t pts
int size
static int config_input(AVFilterLink *inlink)
Definition vf_feedback.c:75
static void adjust_parameters(AVFilterContext *ctx, FeedbackContext *s)
Definition vf_feedback.c:55
static const AVOption feedback_options[]
static int query_formats(const AVFilterContext *ctx, AVFilterFormatsConfig **cfg_in, AVFilterFormatsConfig **cfg_out)
static int activate(AVFilterContext *ctx)
static av_cold void uninit(AVFilterContext *ctx)
static void adjust_pos(AVFilterContext *ctx, FeedbackContext *s)
Definition vf_feedback.c:47
#define OFFSET(x)
static int config_output(AVFilterLink *outlink)
Definition vf_feedback.c:94
AVFrame * ff_get_video_buffer(AVFilterLink *link, int w, int h)
Request a picture buffer with a specific set of permissions.
Definition video.c:89