FFmpeg
Loading...
Searching...
No Matches
vf_shear.c
Go to the documentation of this file.
1/*
2 * Copyright (c) 2021 Paul B Mahol
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#include "libavutil/avstring.h"
22#include "libavutil/opt.h"
25#include "libavutil/pixdesc.h"
26
27#include "avfilter.h"
28#include "drawutils.h"
29#include "filters.h"
30#include "video.h"
31
32#include <float.h>
33
34typedef struct ShearContext {
35 const AVClass *class;
36
37 float shx, shy;
38 int interp;
39
40 uint8_t fillcolor[4]; ///< color expressed either in YUVA or RGBA colorspace for the padding area
44 int depth;
47
48 int hsub, vsub;
49 int planewidth[4];
51
52 int (*filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs);
54
55typedef struct ThreadData {
56 AVFrame *in, *out;
58
59#define OFFSET(x) offsetof(ShearContext, x)
60#define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM|AV_OPT_FLAG_RUNTIME_PARAM
61
62static const AVOption shear_options[] = {
63 { "shx", "set x shear factor", OFFSET(shx), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -2, 2, .flags=FLAGS },
64 { "shy", "set y shear factor", OFFSET(shy), AV_OPT_TYPE_FLOAT, {.dbl=0.}, -2, 2, .flags=FLAGS },
65 { "fillcolor", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, 0, 0, .flags=FLAGS },
66 { "c", "set background fill color", OFFSET(fillcolor_str), AV_OPT_TYPE_STRING, {.str="black"}, 0, 0, .flags=FLAGS },
67 { "interp", "set interpolation", OFFSET(interp), AV_OPT_TYPE_INT, {.i64=1}, 0, 1, .flags=FLAGS, .unit = "interp" },
68 { "nearest", "nearest neighbour", 0, AV_OPT_TYPE_CONST, {.i64=0}, 0, 0, .flags=FLAGS, .unit = "interp" },
69 { "bilinear", "bilinear", 0, AV_OPT_TYPE_CONST, {.i64=1}, 0, 0, .flags=FLAGS, .unit = "interp" },
70 { NULL }
71};
72
74
76{
77 ShearContext *s = ctx->priv;
78
79 if (!strcmp(s->fillcolor_str, "none"))
80 s->fillcolor_enable = 0;
81 else if (av_parse_color(s->fillcolor, s->fillcolor_str, -1, ctx) >= 0)
82 s->fillcolor_enable = 1;
83 else
84 return AVERROR(EINVAL);
85 return 0;
86}
87
114
115#define NN(type, name) \
116static int filter_slice_nn##name(AVFilterContext *ctx, void *arg, int jobnr, \
117 int nb_jobs) \
118{ \
119 ThreadData *td = arg; \
120 AVFrame *in = td->in; \
121 AVFrame *out = td->out; \
122 ShearContext *s = ctx->priv; \
123 const float shx = s->shx; \
124 const float shy = s->shy; \
125 \
126 for (int p = 0; p < s->nb_planes; p++) { \
127 const int hsub = (p == 1 || p == 2) ? s->hsub: 1; \
128 const int vsub = (p == 1 || p == 2) ? s->vsub: 1; \
129 const int width = s->planewidth[p]; \
130 const int height = s->planeheight[p]; \
131 const int wx = vsub * shx * height * 0.5f / hsub; \
132 const int wy = hsub * shy * width * 0.5f / vsub; \
133 const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
134 const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
135 const int src_linesize = in->linesize[p] / sizeof(type); \
136 const int dst_linesize = out->linesize[p] / sizeof(type); \
137 const type *src = (const type *)in->data[p]; \
138 type *dst = (type *)out->data[p] + slice_start * dst_linesize; \
139 \
140 for (int y = slice_start; y < slice_end; y++) { \
141 for (int x = 0; x < width; x++) { \
142 int sx = x + vsub * shx * y / hsub - wx; \
143 int sy = y + hsub * shy * x / vsub - wy; \
144 \
145 if (sx >= 0 && sx < width - 1 && \
146 sy >= 0 && sy < height - 1) { \
147 dst[x] = src[sy * src_linesize + sx]; \
148 } \
149 } \
150 \
151 dst += dst_linesize; \
152 } \
153 } \
154 \
155 return 0; \
156}
157
158NN(uint8_t, 8)
159NN(uint16_t, 16)
160
161#define BL(type, name) \
162static int filter_slice_bl##name(AVFilterContext *ctx, void *arg, int jobnr, \
163 int nb_jobs) \
164{ \
165 ThreadData *td = arg; \
166 AVFrame *in = td->in; \
167 AVFrame *out = td->out; \
168 ShearContext *s = ctx->priv; \
169 const int depth = s->depth; \
170 const float shx = s->shx; \
171 const float shy = s->shy; \
172 \
173 for (int p = 0; p < s->nb_planes; p++) { \
174 const int hsub = (p == 1 || p == 2) ? s->hsub: 1; \
175 const int vsub = (p == 1 || p == 2) ? s->vsub: 1; \
176 const int width = s->planewidth[p]; \
177 const int height = s->planeheight[p]; \
178 const float wx = vsub * shx * height * 0.5f / hsub; \
179 const float wy = hsub * shy * width * 0.5f / vsub; \
180 const int slice_start = ff_slice_pos(height, jobnr, nb_jobs); \
181 const int slice_end = ff_slice_pos(height, jobnr + 1, nb_jobs); \
182 const int src_linesize = in->linesize[p] / sizeof(type); \
183 const int dst_linesize = out->linesize[p] / sizeof(type); \
184 const type *src = (const type *)in->data[p]; \
185 type *dst = (type *)out->data[p] + slice_start * dst_linesize; \
186 \
187 for (int y = slice_start; y < slice_end; y++) { \
188 for (int x = 0; x < width; x++) { \
189 const float sx = x + vsub * shx * y / hsub - wx; \
190 const float sy = y + hsub * shy * x / vsub - wy; \
191 \
192 if (sx >= 0 && sx < width - 1 && \
193 sy >= 0 && sy < height - 1) { \
194 float sum = 0.f; \
195 int ax = floorf(sx); \
196 int ay = floorf(sy); \
197 float du = sx - ax; \
198 float dv = sy - ay; \
199 int bx = FFMIN(ax + 1, width - 1); \
200 int by = FFMIN(ay + 1, height - 1); \
201 \
202 sum += (1.f - du) * (1.f - dv) * src[ay * src_linesize + ax];\
203 sum += ( du) * (1.f - dv) * src[ay * src_linesize + bx];\
204 sum += (1.f - du) * ( dv) * src[by * src_linesize + ax];\
205 sum += ( du) * ( dv) * src[by * src_linesize + bx];\
206 dst[x] = av_clip_uintp2_c(lrintf(sum), depth); \
207 } \
208 } \
209 \
210 dst += dst_linesize; \
211 } \
212 } \
213 \
214 return 0; \
215}
216
217BL(uint8_t, 8)
218BL(uint16_t, 16)
219
220static int filter_frame(AVFilterLink *inlink, AVFrame *in)
221{
222 AVFilterContext *ctx = inlink->dst;
223 ShearContext *s = ctx->priv;
224 AVFilterLink *outlink = ctx->outputs[0];
225 ThreadData td;
226 AVFrame *out;
227
228 out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
229 if (!out) {
230 av_frame_free(&in);
231 return AVERROR(ENOMEM);
232 }
234
235 /* fill background */
236 if (s->fillcolor_enable)
237 ff_fill_rectangle(&s->draw, &s->color, out->data, out->linesize,
238 0, 0, outlink->w, outlink->h);
239
240 td.in = in, td.out = out;
241 ff_filter_execute(ctx, s->filter_slice[s->interp], &td, NULL,
242 FFMIN(s->planeheight[1], ff_filter_get_nb_threads(ctx)));
243
244 av_frame_free(&in);
245 return ff_filter_frame(outlink, out);
246}
247
248static int config_output(AVFilterLink *outlink)
249{
250 AVFilterContext *ctx = outlink->src;
251 ShearContext *s = ctx->priv;
253 int ret;
254
255 s->nb_planes = av_pix_fmt_count_planes(outlink->format);
256 s->depth = desc->comp[0].depth;
257 s->hsub = 1 << desc->log2_chroma_w;
258 s->vsub = 1 << desc->log2_chroma_h;
259 s->planewidth[1] = s->planewidth[2] = AV_CEIL_RSHIFT(ctx->inputs[0]->w, desc->log2_chroma_w);
260 s->planewidth[0] = s->planewidth[3] = ctx->inputs[0]->w;
261 s->planeheight[1] = s->planeheight[2] = AV_CEIL_RSHIFT(ctx->inputs[0]->h, desc->log2_chroma_h);
262 s->planeheight[0] = s->planeheight[3] = ctx->inputs[0]->h;
263
264 ret = ff_draw_init_from_link(&s->draw, outlink, 0);
265 if (ret < 0) {
266 av_log(ctx, AV_LOG_ERROR, "Failed to initialize FFDrawContext\n");
267 return ret;
268 }
269 ff_draw_color(&s->draw, &s->color, s->fillcolor);
270
271 s->filter_slice[0] = s->depth <= 8 ? filter_slice_nn8 : filter_slice_nn16;
272 s->filter_slice[1] = s->depth <= 8 ? filter_slice_bl8 : filter_slice_bl16;
273
274 return 0;
275}
276
278 const char *cmd,
279 const char *arg,
280 char *res,
281 int res_len,
282 int flags)
283{
284 ShearContext *s = ctx->priv;
285 int ret;
286
287 ret = ff_filter_process_command(ctx, cmd, arg, res, res_len, flags);
288 if (ret < 0)
289 return ret;
290
291 ret = init(ctx);
292 if (ret < 0)
293 return ret;
294 ff_draw_color(&s->draw, &s->color, s->fillcolor);
295
296 return 0;
297}
298
299static const AVFilterPad inputs[] = {
300 {
301 .name = "default",
302 .type = AVMEDIA_TYPE_VIDEO,
303 .filter_frame = filter_frame,
304 },
305};
306
307static const AVFilterPad outputs[] = {
308 {
309 .name = "default",
310 .type = AVMEDIA_TYPE_VIDEO,
311 .config_props = config_output,
312 },
313};
314
316 .p.name = "shear",
317 .p.description = NULL_IF_CONFIG_SMALL("Shear transform the input image."),
318 .p.priv_class = &shear_class,
320 .priv_size = sizeof(ShearContext),
321 .init = init,
325 .process_command = process_command,
326};
static const AVFilterPad inputs[]
Definition af_aap.c:299
static const AVFilterPad outputs[]
Definition af_aap.c:310
static int process_command(AVFilterContext *ctx, const char *cmd, const char *args, char *res, int res_len, int flags)
const FFFilter ff_vf_shear
Definition vf_shear.c:315
static FILE * out
static AVFormatContext * ctx
int ff_filter_frame(AVFilterLink *link, AVFrame *frame)
Send a frame of data to the next filter.
Definition avfilter.c:1068
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_filter_execute(AVFilterContext *ctx, avfilter_action_func *func, void *arg, int *ret, int nb_jobs)
Definition avfilter.c:1696
int ff_filter_get_nb_threads(AVFilterContext *ctx)
Get number of threads for current filter instance.
Definition avfilter.c:846
Main libavfilter public API header.
#define flags(name, subs,...)
Definition cbs_h264.c:74
#define s(width, name)
Definition cbs_vp9.c:198
#define FLAGS
Definition cmdutils.c:598
#define AV_CEIL_RSHIFT(a, b)
Definition common.h:60
#define NULL
Definition coverity.c:32
static int filter_frame(DBEDecodeContext *s, AVFrame *frame)
Definition dolby_e.c:1067
void ff_draw_color(FFDrawContext *draw, FFDrawColor *color, const uint8_t rgba[4])
Prepare a color.
Definition drawutils.c:179
void ff_fill_rectangle(FFDrawContext *draw, FFDrawColor *color, uint8_t *dst[], int dst_linesize[], int dst_x, int dst_y, int w, int h)
Fill a rectangle with an uniform color.
Definition drawutils.c:258
int ff_draw_init_from_link(FFDrawContext *draw, const AVFilterLink *link, unsigned flags)
Init a draw context, taking the format, colorspace and range from the given filter link.
Definition drawutils.c:168
misc drawing utilities
int(* init)(AVBSFContext *ctx)
Definition dts2pts.c:608
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
Definition opt.h:298
@ AV_OPT_TYPE_INT
Underlying C type is int.
Definition opt.h:258
@ AV_OPT_TYPE_FLOAT
Underlying C type is float.
Definition opt.h:270
@ AV_OPT_TYPE_STRING
Underlying C type is a uint8_t* that is either NULL or points to a C string allocated with the av_mal...
Definition opt.h:275
#define AVFILTER_FLAG_SUPPORT_TIMELINE_GENERIC
Some filters support a generic "enable" expression option that can be used to enable or disable a fil...
Definition avfilter.h:196
#define AVFILTER_FLAG_SLICE_THREADS
The filter supports multithreading by splitting frames into multiple parts and processing them concur...
Definition avfilter.h:166
#define AVERROR(e)
Definition error.h:45
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
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
@ AVMEDIA_TYPE_VIDEO
Definition avutil.h:200
static int config_output(AVBitStreamFilterLink *outlink)
const char * arg
Definition jacosubdec.c:65
#define FILTER_INPUTS(array)
Definition filters.h:264
#define FILTER_OUTPUTS(array)
Definition filters.h:265
#define FILTER_PIXFMTS_ARRAY(array)
Definition filters.h:244
#define AVFILTER_DEFINE_CLASS(fname)
Definition filters.h:478
#define av_cold
Definition attributes.h:117
#define NULL_IF_CONFIG_SMALL(x)
Return NULL if CONFIG_SMALL is true, otherwise the argument without modification.
Definition internal.h:88
static enum AVPixelFormat pix_fmts[]
Definition libkvazaar.c:296
const char * desc
Definition libsvtav1.c:83
#define FFMIN(a, b)
Definition macros.h:49
AVOptions.
int av_parse_color(uint8_t *rgba_color, const char *color_string, int slen, void *log_ctx)
Put the RGBA values that correspond to color_string in rgba_color.
Definition parseutils.c:359
misc parsing utilities
int av_pix_fmt_count_planes(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3500
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition pixdesc.c:3460
#define AV_PIX_FMT_GBRAP12
Definition pixfmt.h:569
#define AV_PIX_FMT_YUV420P16
Definition pixfmt.h:556
#define AV_PIX_FMT_YUV444P12
Definition pixfmt.h:552
#define AV_PIX_FMT_YUV444P9
Definition pixfmt.h:544
#define AV_PIX_FMT_YUV420P10
Definition pixfmt.h:545
#define AV_PIX_FMT_YUV440P12
Definition pixfmt.h:551
#define AV_PIX_FMT_GRAY9
Definition pixfmt.h:524
#define AV_PIX_FMT_GBRAP16
Definition pixfmt.h:571
#define AV_PIX_FMT_GBRP9
Definition pixfmt.h:563
#define AV_PIX_FMT_YUV422P9
Definition pixfmt.h:543
#define AV_PIX_FMT_YUVA444P10
Definition pixfmt.h:598
#define AV_PIX_FMT_YUVA420P16
Definition pixfmt.h:601
#define AV_PIX_FMT_YUV420P12
Definition pixfmt.h:549
#define AV_PIX_FMT_YUVA420P10
Definition pixfmt.h:596
#define AV_PIX_FMT_YUVA422P9
Definition pixfmt.h:594
#define AV_PIX_FMT_YUV422P12
Definition pixfmt.h:550
#define AV_PIX_FMT_GBRP10
Definition pixfmt.h:564
#define AV_PIX_FMT_YUV422P10
Definition pixfmt.h:546
#define AV_PIX_FMT_GRAY12
Definition pixfmt.h:526
#define AV_PIX_FMT_GBRP12
Definition pixfmt.h:565
#define AV_PIX_FMT_YUV420P9
Definition pixfmt.h:542
#define AV_PIX_FMT_YUVA420P9
Definition pixfmt.h:593
#define AV_PIX_FMT_YUVA422P10
Definition pixfmt.h:597
#define AV_PIX_FMT_YUV420P14
Definition pixfmt.h:553
AVPixelFormat
Pixel format.
Definition pixfmt.h:71
@ AV_PIX_FMT_NONE
Definition pixfmt.h:72
@ AV_PIX_FMT_YUV420P
planar YUV 4:2:0, 12bpp, (1 Cr & Cb sample per 2x2 Y samples)
Definition pixfmt.h:73
@ AV_PIX_FMT_YUV440P
planar YUV 4:4:0 (1 Cr & Cb sample per 1x2 Y samples)
Definition pixfmt.h:106
@ AV_PIX_FMT_YUV422P
planar YUV 4:2:2, 16bpp, (1 Cr & Cb sample per 2x1 Y samples)
Definition pixfmt.h:77
@ AV_PIX_FMT_GRAY8
Y , 8bpp.
Definition pixfmt.h:81
@ AV_PIX_FMT_YUVA420P
planar YUV 4:2:0, 20bpp, (1 Cr & Cb sample per 2x2 Y & A samples)
Definition pixfmt.h:108
@ AV_PIX_FMT_YUVJ440P
planar YUV 4:4:0 full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV440P and setting color_range
Definition pixfmt.h:107
@ AV_PIX_FMT_YUV410P
planar YUV 4:1:0, 9bpp, (1 Cr & Cb sample per 4x4 Y samples)
Definition pixfmt.h:79
@ AV_PIX_FMT_YUV411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples)
Definition pixfmt.h:80
@ AV_PIX_FMT_YUV444P
planar YUV 4:4:4, 24bpp, (1 Cr & Cb sample per 1x1 Y samples)
Definition pixfmt.h:78
@ AV_PIX_FMT_YUVA444P
planar YUV 4:4:4 32bpp, (1 Cr & Cb sample per 1x1 Y & A samples)
Definition pixfmt.h:174
@ AV_PIX_FMT_YUVJ411P
planar YUV 4:1:1, 12bpp, (1 Cr & Cb sample per 4x1 Y samples) full scale (JPEG), deprecated in favor ...
Definition pixfmt.h:283
@ AV_PIX_FMT_GBRAP
planar GBRA 4:4:4:4 32bpp
Definition pixfmt.h:212
@ AV_PIX_FMT_YUVJ422P
planar YUV 4:2:2, 16bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV422P and setting col...
Definition pixfmt.h:86
@ AV_PIX_FMT_YUVA422P
planar YUV 4:2:2 24bpp, (1 Cr & Cb sample per 2x1 Y & A samples)
Definition pixfmt.h:173
@ AV_PIX_FMT_GBRP
planar GBR 4:4:4 24bpp
Definition pixfmt.h:165
@ AV_PIX_FMT_YUVJ444P
planar YUV 4:4:4, 24bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV444P and setting col...
Definition pixfmt.h:87
@ AV_PIX_FMT_YUVJ420P
planar YUV 4:2:0, 12bpp, full scale (JPEG), deprecated in favor of AV_PIX_FMT_YUV420P and setting col...
Definition pixfmt.h:85
#define AV_PIX_FMT_YUVA422P12
Definition pixfmt.h:599
#define AV_PIX_FMT_YUV422P14
Definition pixfmt.h:554
#define AV_PIX_FMT_GRAY10
Definition pixfmt.h:525
#define AV_PIX_FMT_GRAY14
Definition pixfmt.h:527
#define AV_PIX_FMT_YUV422P16
Definition pixfmt.h:557
#define AV_PIX_FMT_YUV440P10
Definition pixfmt.h:547
#define AV_PIX_FMT_GRAY16
Definition pixfmt.h:528
#define AV_PIX_FMT_GBRAP10
Definition pixfmt.h:568
#define AV_PIX_FMT_YUVA444P16
Definition pixfmt.h:603
#define AV_PIX_FMT_YUVA422P16
Definition pixfmt.h:602
#define AV_PIX_FMT_GBRP16
Definition pixfmt.h:567
#define AV_PIX_FMT_YUV444P14
Definition pixfmt.h:555
#define AV_PIX_FMT_YUVA444P9
Definition pixfmt.h:595
#define AV_PIX_FMT_GBRP14
Definition pixfmt.h:566
#define AV_PIX_FMT_YUVA444P12
Definition pixfmt.h:600
#define AV_PIX_FMT_YUV444P16
Definition pixfmt.h:558
#define AV_PIX_FMT_YUV444P10
Definition pixfmt.h:548
Describe the class of an AVClass context structure.
Definition log.h:76
An instance of a filter.
Definition avfilter.h:273
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
float shx
Definition vf_shear.c:37
int planeheight[4]
Definition vf_shear.c:50
uint8_t fillcolor[4]
color expressed either in YUVA or RGBA colorspace for the padding area
Definition vf_shear.c:40
float shy
Definition vf_shear.c:37
int planewidth[4]
Definition vf_shear.c:49
int fillcolor_enable
Definition vf_shear.c:42
FFDrawContext draw
Definition vf_shear.c:45
FFDrawColor color
Definition vf_shear.c:46
int(* filter_slice[2])(AVFilterContext *ctx, void *arg, int jobnr, int nb_jobs)
Definition vf_shear.c:52
char * fillcolor_str
Definition vf_shear.c:41
int nb_planes
Definition vf_shear.c:43
Used for passing data between threads.
Definition dsddec.c:71
AVFrame * out
#define av_log(a,...)
interp
Definition vf_curves.c:62
static int process_command(AVFilterContext *ctx, const char *cmd, const char *arg, char *res, int res_len, int flags)
Definition vf_shear.c:277
#define NN(type, name)
Definition vf_shear.c:115
static const AVOption shear_options[]
Definition vf_shear.c:62
#define BL(type, name)
Definition vf_shear.c:161
#define OFFSET(x)
Definition vf_shear.c:59
static int config_output(AVFilterLink *outlink)
Definition vf_shear.c:248
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