1 /*
2 * Copyright (c) 2013 Stefano Sabatini
3 * Copyright (c) 2008 Vitor Sessak
4 *
5 * This file is part of FFmpeg.
6 *
7 * FFmpeg is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * FFmpeg is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with FFmpeg; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 */
21
22 /**
23 * @file
24 * rotation filter, partially based on the tests/rotozoom.c program
25 */
26
33
38
40 "in_w" , "iw", ///< width of the input video
41 "in_h" , "ih", ///< height of the input video
42 "out_w", "ow", ///< width of the input video
43 "out_h", "oh", ///< height of the input video
44 "hsub", "vsub",
45 "n", ///< number of frame
46 "t", ///< timestamp expressed in seconds
47 NULL
48 };
49
59 };
60
68 uint8_t fillcolor[4];
///< color expressed either in YUVA or RGBA colorspace for the padding area
79
80 #define OFFSET(x) offsetof(RotContext, x)
81 #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM
82
93 { NULL }
94 };
95
97
99 {
101
106 else
108 return 0;
109 }
110
112 {
114
117 }
118
120 {
121 static enum PixelFormat pix_fmts[] = {
134 };
135
137 return 0;
138 }
139
141 {
145 float sinx = sin(angle);
146 float cosx = cos(angle);
147
148 return FFMAX(0, inh * sinx) +
FFMAX(0, -inw * cosx) +
150 }
151
153 {
157 float sinx = sin(angle);
158 float cosx = cos(angle);
159
160 return FFMAX(0, -inh * cosx) +
FFMAX(0, -inw * sinx) +
162 }
163
164 static double (*
const func1[])(
void *, double) = {
167 NULL
168 };
169
171 "rotw",
172 "roth",
173 NULL
174 };
175
177 {
184 char *expr;
185
188
191
200
206 "Error occurred parsing angle expression '%s'\n", rot->
angle_expr_str);
208 }
209
210 #define SET_SIZE_EXPR(name, opt_name) do { \
211 ret = av_expr_parse_and_eval(&res, expr = rot->name##_expr_str, \
212 var_names, rot->var_values, \
213 func1_names, func1, NULL, NULL, rot, 0, ctx); \
214 if (ret < 0 || isnan(res) || isinf(res) || res <= 0) { \
215 av_log(ctx, AV_LOG_ERROR, \
216 "Error parsing or evaluating expression for option %s: " \
217 "invalid expression '%s' or non-positive or indefinite value %f\n", \
218 opt_name, expr, res); \
219 return ret; \
220 } \
221 } while (0)
222
223 /* evaluate width and height */
227 rot->
outw = res + 0.5;
230 rot->
outh = res + 0.5;
231
232 /* evaluate the width again, as it may depend on the evaluated output height */
235 rot->
outw = res + 0.5;
236
237 /* compute number of planes */
239 outlink->
w = rot->
outw;
240 outlink->
h = rot->
outh;
241 return 0;
242 }
243
245 #define INT_PI 205887 //(M_PI * FIXP)
246
247 /**
248 * Compute the sin of a using integer values.
249 * Input and output values are scaled by FIXP.
250 */
252 {
254 int i;
255 if (a < 0) a =
INT_PI-
a;
// 0..inf
256 a %= 2 *
INT_PI;
// 0..2PI
257
260
261 /* compute sin using Taylor series approximated to the third term */
263 for (i = 2; i < 7; i += 2) {
265 a = -a*a2 / (
FIXP*i*(i+1));
266 }
268 }
269
270 /**
271 * Interpolate the color in src at position x and y using bilinear
272 * interpolation.
273 */
275 const uint8_t *
src,
int src_linesize,
int src_linestep,
276 int x,
int y,
int max_x,
int max_y)
277 {
278 int int_x = av_clip(x>>16, 0, max_x);
279 int int_y = av_clip(y>>16, 0, max_y);
280 int frac_x = x&0xFFFF;
281 int frac_y = y&0xFFFF;
282 int i;
283 int int_x1 =
FFMIN(int_x+1, max_x);
284 int int_y1 =
FFMIN(int_y+1, max_y);
285
286 for (i = 0; i < src_linestep; i++) {
287 int s00 = src[src_linestep * int_x + i + src_linesize * int_y ];
288 int s01 = src[src_linestep * int_x1 + i + src_linesize * int_y ];
289 int s10 = src[src_linestep * int_x + i + src_linesize * int_y1];
290 int s11 = src[src_linestep * int_x1 + i + src_linesize * int_y1];
291 int s0 = (((1<<16) - frac_x)*s00 + frac_x*s01);
292 int s1 = (((1<<16) - frac_x)*s10 + frac_x*s11);
293
294 dst_color[i] = ((int64_t)((1<<16) - frac_y)*s0 + (int64_t)frac_y*
s1) >> 32;
295 }
296
297 return dst_color;
298 }
299
300 #define TS2T(ts, tb) ((ts) == AV_NOPTS_VALUE ? NAN : (double)(ts)*av_q2d(tb))
301
303 {
308 int angle_int,
s,
c, plane;
310
312 if (!out) {
315 }
317
321
324
325 angle_int = res *
FIXP;
328
329 /* fill background */
332 0, 0, outlink->
w, outlink->
h);
333
334 for (plane = 0; plane < rot->
nb_planes; plane++) {
335 int hsub = plane == 1 || plane == 2 ? rot->
hsub : 0;
336 int vsub = plane == 1 || plane == 2 ? rot->
vsub : 0;
341
342 const int xi = -outw/2 *
c;
343 const int yi = outw/2 *
s;
344 int xprime = -outh/2 *
s;
345 int yprime = -outh/2 *
c;
347
348 for (j = 0; j < outh; j++) {
349 x = xprime + xi + FIXP*inw/2;
350 y = yprime + yi + FIXP*inh/2;
351
352 for (i = 0; i < outw; i++) {
354 int x1, y1;
358 x1 = x>>16;
359 y1 = y>>16;
360
361 /* the out-of-range values avoid border artifacts */
362 if (x1 >= -1 && x1 <= inw && y1 >= -1 && y1 <= inh) {
363 uint8_t inp_inv[4];
/* interpolated input value */
368 x, y, inw-1, inh-1);
369 } else {
370 int x2 = av_clip(x1, 0, inw-1);
371 int y2 = av_clip(y1, 0, inh-1);
373 }
375 case 1:
376 *pout = *pin;
377 break;
378 case 2:
379 *((uint16_t *)pout) = *((uint16_t *)pin);
380 break;
381 case 3:
384 break;
385 case 4:
386 *((uint32_t *)pout) = *((uint32_t *)pin);
387 break;
388 default:
390 break;
391 }
392 }
393 }
396 }
397 }
398
401 }
402
405 {
408
409 if (!strcmp(cmd, "angle") || !strcmp(cmd, "a")) {
412 NULL, NULL, NULL, NULL, 0, ctx);
413 if (ret < 0) {
415 "Error when parsing the expression '%s' for angle command\n", args);
418 }
420 } else
422
424 }
425
427 {
431 },
432 { NULL }
433 };
434
436 {
440 },
441 { NULL }
442 };
443
454 .priv_class = &rotate_class,
456 };