Line | Branch | Exec | Source |
---|---|---|---|
1 | /* | ||
2 | * Copyright (c) 2010 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 | * transposition filter | ||
25 | * Based on MPlayer libmpcodecs/vf_rotate.c. | ||
26 | */ | ||
27 | |||
28 | #include <stdio.h> | ||
29 | |||
30 | #include "libavutil/avassert.h" | ||
31 | #include "libavutil/imgutils.h" | ||
32 | #include "libavutil/internal.h" | ||
33 | #include "libavutil/intreadwrite.h" | ||
34 | #include "libavutil/opt.h" | ||
35 | #include "libavutil/pixdesc.h" | ||
36 | |||
37 | #include "avfilter.h" | ||
38 | #include "filters.h" | ||
39 | #include "formats.h" | ||
40 | #include "video.h" | ||
41 | #include "transpose.h" | ||
42 | |||
43 | typedef struct TransContext { | ||
44 | const AVClass *class; | ||
45 | int hsub, vsub; | ||
46 | int planes; | ||
47 | int pixsteps[4]; | ||
48 | |||
49 | int passthrough; ///< PassthroughType, landscape passthrough mode enabled | ||
50 | int dir; ///< TransposeDir | ||
51 | |||
52 | TransVtable vtables[4]; | ||
53 | } TransContext; | ||
54 | |||
55 | 151 | static int query_formats(const AVFilterContext *ctx, | |
56 | AVFilterFormatsConfig **cfg_in, | ||
57 | AVFilterFormatsConfig **cfg_out) | ||
58 | { | ||
59 | 151 | AVFilterFormats *pix_fmts = NULL; | |
60 | const AVPixFmtDescriptor *desc; | ||
61 | int fmt, ret; | ||
62 | |||
63 |
2/2✓ Branch 1 taken 36693 times.
✓ Branch 2 taken 151 times.
|
36844 | for (fmt = 0; desc = av_pix_fmt_desc_get(fmt); fmt++) { |
64 |
2/2✓ Branch 0 taken 36542 times.
✓ Branch 1 taken 151 times.
|
36693 | if (!(desc->flags & AV_PIX_FMT_FLAG_PAL || |
65 |
2/2✓ Branch 0 taken 34428 times.
✓ Branch 1 taken 2114 times.
|
36542 | desc->flags & AV_PIX_FMT_FLAG_HWACCEL || |
66 |
2/2✓ Branch 0 taken 33522 times.
✓ Branch 1 taken 906 times.
|
34428 | desc->flags & AV_PIX_FMT_FLAG_BITSTREAM || |
67 |
3/4✓ Branch 0 taken 26274 times.
✓ Branch 1 taken 7248 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 26274 times.
|
59796 | desc->log2_chroma_w != desc->log2_chroma_h) && |
68 | 26274 | (ret = ff_add_format(&pix_fmts, fmt)) < 0) | |
69 | ✗ | return ret; | |
70 | } | ||
71 | |||
72 | |||
73 | 151 | return ff_set_common_formats2(ctx, cfg_in, cfg_out, pix_fmts); | |
74 | } | ||
75 | |||
76 | 473278 | static inline void transpose_block_8_c(uint8_t *src, ptrdiff_t src_linesize, | |
77 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
78 | int w, int h) | ||
79 | { | ||
80 | int x, y; | ||
81 |
2/2✓ Branch 0 taken 3781824 times.
✓ Branch 1 taken 473278 times.
|
4255102 | for (y = 0; y < h; y++, dst += dst_linesize, src++) |
82 |
2/2✓ Branch 0 taken 31473792 times.
✓ Branch 1 taken 3781824 times.
|
35255616 | for (x = 0; x < w; x++) |
83 | 31473792 | dst[x] = src[x*src_linesize]; | |
84 | 473278 | } | |
85 | |||
86 | 471978 | static void transpose_8x8_8_c(uint8_t *src, ptrdiff_t src_linesize, | |
87 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
88 | { | ||
89 | 471978 | transpose_block_8_c(src, src_linesize, dst, dst_linesize, 8, 8); | |
90 | 471978 | } | |
91 | |||
92 | 303336 | static inline void transpose_block_16_c(uint8_t *src, ptrdiff_t src_linesize, | |
93 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
94 | int w, int h) | ||
95 | { | ||
96 | int x, y; | ||
97 |
2/2✓ Branch 0 taken 2426688 times.
✓ Branch 1 taken 303336 times.
|
2730024 | for (y = 0; y < h; y++, dst += dst_linesize, src += 2) |
98 |
2/2✓ Branch 0 taken 19413504 times.
✓ Branch 1 taken 2426688 times.
|
21840192 | for (x = 0; x < w; x++) |
99 | 19413504 | *((uint16_t *)(dst + 2*x)) = *((uint16_t *)(src + x*src_linesize)); | |
100 | 303336 | } | |
101 | |||
102 | 303336 | static void transpose_8x8_16_c(uint8_t *src, ptrdiff_t src_linesize, | |
103 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
104 | { | ||
105 | 303336 | transpose_block_16_c(src, src_linesize, dst, dst_linesize, 8, 8); | |
106 | 303336 | } | |
107 | |||
108 | 4752 | static inline void transpose_block_24_c(uint8_t *src, ptrdiff_t src_linesize, | |
109 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
110 | int w, int h) | ||
111 | { | ||
112 | int x, y; | ||
113 |
2/2✓ Branch 0 taken 38016 times.
✓ Branch 1 taken 4752 times.
|
42768 | for (y = 0; y < h; y++, dst += dst_linesize) { |
114 |
2/2✓ Branch 0 taken 304128 times.
✓ Branch 1 taken 38016 times.
|
342144 | for (x = 0; x < w; x++) { |
115 | 304128 | int32_t v = AV_RB24(src + x*src_linesize + y*3); | |
116 | 304128 | AV_WB24(dst + 3*x, v); | |
117 | } | ||
118 | } | ||
119 | 4752 | } | |
120 | |||
121 | 4752 | static void transpose_8x8_24_c(uint8_t *src, ptrdiff_t src_linesize, | |
122 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
123 | { | ||
124 | 4752 | transpose_block_24_c(src, src_linesize, dst, dst_linesize, 8, 8); | |
125 | 4752 | } | |
126 | |||
127 | 65736 | static inline void transpose_block_32_c(uint8_t *src, ptrdiff_t src_linesize, | |
128 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
129 | int w, int h) | ||
130 | { | ||
131 | int x, y; | ||
132 |
2/2✓ Branch 0 taken 525888 times.
✓ Branch 1 taken 65736 times.
|
591624 | for (y = 0; y < h; y++, dst += dst_linesize, src += 4) { |
133 |
2/2✓ Branch 0 taken 4207104 times.
✓ Branch 1 taken 525888 times.
|
4732992 | for (x = 0; x < w; x++) |
134 | 4207104 | *((uint32_t *)(dst + 4*x)) = *((uint32_t *)(src + x*src_linesize)); | |
135 | } | ||
136 | 65736 | } | |
137 | |||
138 | 65736 | static void transpose_8x8_32_c(uint8_t *src, ptrdiff_t src_linesize, | |
139 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
140 | { | ||
141 | 65736 | transpose_block_32_c(src, src_linesize, dst, dst_linesize, 8, 8); | |
142 | 65736 | } | |
143 | |||
144 | 9504 | static inline void transpose_block_48_c(uint8_t *src, ptrdiff_t src_linesize, | |
145 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
146 | int w, int h) | ||
147 | { | ||
148 | int x, y; | ||
149 |
2/2✓ Branch 0 taken 76032 times.
✓ Branch 1 taken 9504 times.
|
85536 | for (y = 0; y < h; y++, dst += dst_linesize, src += 6) { |
150 |
2/2✓ Branch 0 taken 608256 times.
✓ Branch 1 taken 76032 times.
|
684288 | for (x = 0; x < w; x++) { |
151 | 608256 | int64_t v = AV_RB48(src + x*src_linesize); | |
152 | 608256 | AV_WB48(dst + 6*x, v); | |
153 | } | ||
154 | } | ||
155 | 9504 | } | |
156 | |||
157 | 9504 | static void transpose_8x8_48_c(uint8_t *src, ptrdiff_t src_linesize, | |
158 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
159 | { | ||
160 | 9504 | transpose_block_48_c(src, src_linesize, dst, dst_linesize, 8, 8); | |
161 | 9504 | } | |
162 | |||
163 | 15840 | static inline void transpose_block_64_c(uint8_t *src, ptrdiff_t src_linesize, | |
164 | uint8_t *dst, ptrdiff_t dst_linesize, | ||
165 | int w, int h) | ||
166 | { | ||
167 | int x, y; | ||
168 |
2/2✓ Branch 0 taken 126720 times.
✓ Branch 1 taken 15840 times.
|
142560 | for (y = 0; y < h; y++, dst += dst_linesize, src += 8) |
169 |
2/2✓ Branch 0 taken 1013760 times.
✓ Branch 1 taken 126720 times.
|
1140480 | for (x = 0; x < w; x++) |
170 | 1013760 | *((uint64_t *)(dst + 8*x)) = *((uint64_t *)(src + x*src_linesize)); | |
171 | 15840 | } | |
172 | |||
173 | 15840 | static void transpose_8x8_64_c(uint8_t *src, ptrdiff_t src_linesize, | |
174 | uint8_t *dst, ptrdiff_t dst_linesize) | ||
175 | { | ||
176 | 15840 | transpose_block_64_c(src, src_linesize, dst, dst_linesize, 8, 8); | |
177 | 15840 | } | |
178 | |||
179 | 150 | static int config_props_output(AVFilterLink *outlink) | |
180 | { | ||
181 | 150 | AVFilterContext *ctx = outlink->src; | |
182 | 150 | TransContext *s = ctx->priv; | |
183 | 150 | AVFilterLink *inlink = ctx->inputs[0]; | |
184 | 150 | const AVPixFmtDescriptor *desc_out = av_pix_fmt_desc_get(outlink->format); | |
185 | 150 | const AVPixFmtDescriptor *desc_in = av_pix_fmt_desc_get(inlink->format); | |
186 | |||
187 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
|
150 | if (s->dir&4) { |
188 | ✗ | av_log(ctx, AV_LOG_WARNING, | |
189 | "dir values greater than 3 are deprecated, use the passthrough option instead\n"); | ||
190 | ✗ | s->dir &= 3; | |
191 | ✗ | s->passthrough = TRANSPOSE_PT_TYPE_LANDSCAPE; | |
192 | } | ||
193 | |||
194 |
2/4✓ Branch 0 taken 150 times.
✗ Branch 1 not taken.
✓ Branch 2 taken 150 times.
✗ Branch 3 not taken.
|
150 | if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) || |
195 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
150 | (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) { |
196 | ✗ | av_log(ctx, AV_LOG_VERBOSE, | |
197 | "w:%d h:%d -> w:%d h:%d (passthrough mode)\n", | ||
198 | inlink->w, inlink->h, inlink->w, inlink->h); | ||
199 | ✗ | return 0; | |
200 | } else { | ||
201 | 150 | s->passthrough = TRANSPOSE_PT_TYPE_NONE; | |
202 | } | ||
203 | |||
204 | 150 | s->hsub = desc_in->log2_chroma_w; | |
205 | 150 | s->vsub = desc_in->log2_chroma_h; | |
206 | 150 | s->planes = av_pix_fmt_count_planes(outlink->format); | |
207 | |||
208 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
|
150 | av_assert0(desc_in->nb_components == desc_out->nb_components); |
209 | |||
210 | |||
211 | 150 | av_image_fill_max_pixsteps(s->pixsteps, NULL, desc_out); | |
212 | |||
213 | 150 | outlink->w = inlink->h; | |
214 | 150 | outlink->h = inlink->w; | |
215 | |||
216 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 150 times.
|
150 | if (inlink->sample_aspect_ratio.num) |
217 | ✗ | outlink->sample_aspect_ratio = av_div_q((AVRational) { 1, 1 }, | |
218 | inlink->sample_aspect_ratio); | ||
219 | else | ||
220 | 150 | outlink->sample_aspect_ratio = inlink->sample_aspect_ratio; | |
221 | |||
222 |
2/2✓ Branch 0 taken 600 times.
✓ Branch 1 taken 150 times.
|
750 | for (int i = 0; i < 4; i++) { |
223 | 600 | TransVtable *v = &s->vtables[i]; | |
224 |
7/7✓ Branch 0 taken 45 times.
✓ Branch 1 taken 217 times.
✓ Branch 2 taken 3 times.
✓ Branch 3 taken 46 times.
✓ Branch 4 taken 6 times.
✓ Branch 5 taken 10 times.
✓ Branch 6 taken 273 times.
|
600 | switch (s->pixsteps[i]) { |
225 | 45 | case 1: v->transpose_block = transpose_block_8_c; | |
226 | 45 | v->transpose_8x8 = transpose_8x8_8_c; break; | |
227 | 217 | case 2: v->transpose_block = transpose_block_16_c; | |
228 | 217 | v->transpose_8x8 = transpose_8x8_16_c; break; | |
229 | 3 | case 3: v->transpose_block = transpose_block_24_c; | |
230 | 3 | v->transpose_8x8 = transpose_8x8_24_c; break; | |
231 | 46 | case 4: v->transpose_block = transpose_block_32_c; | |
232 | 46 | v->transpose_8x8 = transpose_8x8_32_c; break; | |
233 | 6 | case 6: v->transpose_block = transpose_block_48_c; | |
234 | 6 | v->transpose_8x8 = transpose_8x8_48_c; break; | |
235 | 10 | case 8: v->transpose_block = transpose_block_64_c; | |
236 | 10 | v->transpose_8x8 = transpose_8x8_64_c; break; | |
237 | } | ||
238 | } | ||
239 | |||
240 | #if ARCH_X86 | ||
241 |
2/2✓ Branch 0 taken 600 times.
✓ Branch 1 taken 150 times.
|
750 | for (int i = 0; i < 4; i++) { |
242 | 600 | TransVtable *v = &s->vtables[i]; | |
243 | |||
244 | 600 | ff_transpose_init_x86(v, s->pixsteps[i]); | |
245 | } | ||
246 | #endif | ||
247 | |||
248 | 300 | av_log(ctx, AV_LOG_VERBOSE, | |
249 | "w:%d h:%d dir:%d -> w:%d h:%d rotation:%s vflip:%d\n", | ||
250 | inlink->w, inlink->h, s->dir, outlink->w, outlink->h, | ||
251 |
3/4✓ Branch 0 taken 149 times.
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 149 times.
|
150 | s->dir == 1 || s->dir == 3 ? "clockwise" : "counterclockwise", |
252 |
3/4✓ Branch 0 taken 1 times.
✓ Branch 1 taken 149 times.
✗ Branch 2 not taken.
✓ Branch 3 taken 1 times.
|
150 | s->dir == 0 || s->dir == 3); |
253 | 150 | return 0; | |
254 | } | ||
255 | |||
256 | 147 | static AVFrame *get_video_buffer(AVFilterLink *inlink, int w, int h) | |
257 | { | ||
258 | 147 | TransContext *s = inlink->dst->priv; | |
259 | |||
260 | 147 | return s->passthrough ? | |
261 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 147 times.
|
294 | ff_null_get_video_buffer (inlink, w, h) : |
262 | 147 | ff_default_get_video_buffer(inlink, w, h); | |
263 | } | ||
264 | |||
265 | typedef struct ThreadData { | ||
266 | AVFrame *in, *out; | ||
267 | } ThreadData; | ||
268 | |||
269 | 703 | static int filter_slice(AVFilterContext *ctx, void *arg, int jobnr, | |
270 | int nb_jobs) | ||
271 | { | ||
272 | 703 | TransContext *s = ctx->priv; | |
273 | 703 | ThreadData *td = arg; | |
274 | 703 | AVFrame *out = td->out; | |
275 | 703 | AVFrame *in = td->in; | |
276 | int plane; | ||
277 | |||
278 |
2/2✓ Branch 0 taken 1986 times.
✓ Branch 1 taken 703 times.
|
2689 | for (plane = 0; plane < s->planes; plane++) { |
279 |
4/4✓ Branch 0 taken 1350 times.
✓ Branch 1 taken 636 times.
✓ Branch 2 taken 620 times.
✓ Branch 3 taken 730 times.
|
1986 | int hsub = plane == 1 || plane == 2 ? s->hsub : 0; |
280 |
4/4✓ Branch 0 taken 1350 times.
✓ Branch 1 taken 636 times.
✓ Branch 2 taken 620 times.
✓ Branch 3 taken 730 times.
|
1986 | int vsub = plane == 1 || plane == 2 ? s->vsub : 0; |
281 | 1986 | int pixstep = s->pixsteps[plane]; | |
282 | 1986 | int inh = AV_CEIL_RSHIFT(in->height, vsub); | |
283 | 1986 | int outw = AV_CEIL_RSHIFT(out->width, hsub); | |
284 | 1986 | int outh = AV_CEIL_RSHIFT(out->height, vsub); | |
285 | 1986 | int start = (outh * jobnr ) / nb_jobs; | |
286 | 1986 | int end = (outh * (jobnr+1)) / nb_jobs; | |
287 | uint8_t *dst, *src; | ||
288 | int dstlinesize, srclinesize; | ||
289 | int x, y; | ||
290 | 1986 | TransVtable *v = &s->vtables[plane]; | |
291 | |||
292 | 1986 | dstlinesize = out->linesize[plane]; | |
293 | 1986 | dst = out->data[plane] + start * dstlinesize; | |
294 | 1986 | src = in->data[plane]; | |
295 | 1986 | srclinesize = in->linesize[plane]; | |
296 | |||
297 |
2/2✓ Branch 0 taken 315 times.
✓ Branch 1 taken 1671 times.
|
1986 | if (s->dir & 1) { |
298 | 315 | src += in->linesize[plane] * (inh - 1); | |
299 | 315 | srclinesize *= -1; | |
300 | } | ||
301 | |||
302 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 1986 times.
|
1986 | if (s->dir & 2) { |
303 | ✗ | dst = out->data[plane] + dstlinesize * (outh - start - 1); | |
304 | ✗ | dstlinesize *= -1; | |
305 | } | ||
306 | |||
307 |
2/2✓ Branch 0 taken 29296 times.
✓ Branch 1 taken 1986 times.
|
31282 | for (y = start; y < end - 7; y += 8) { |
308 |
2/2✓ Branch 0 taken 871146 times.
✓ Branch 1 taken 29296 times.
|
900442 | for (x = 0; x < outw - 7; x += 8) { |
309 | 871146 | v->transpose_8x8(src + x * srclinesize + y * pixstep, | |
310 | srclinesize, | ||
311 | 871146 | dst + (y - start) * dstlinesize + x * pixstep, | |
312 | dstlinesize); | ||
313 | } | ||
314 |
1/4✗ Branch 0 not taken.
✓ Branch 1 taken 29296 times.
✗ Branch 2 not taken.
✗ Branch 3 not taken.
|
29296 | if (outw - x > 0 && end - y > 0) |
315 | ✗ | v->transpose_block(src + x * srclinesize + y * pixstep, | |
316 | srclinesize, | ||
317 | ✗ | dst + (y - start) * dstlinesize + x * pixstep, | |
318 | dstlinesize, outw - x, end - y); | ||
319 | } | ||
320 | |||
321 |
2/2✓ Branch 0 taken 1300 times.
✓ Branch 1 taken 686 times.
|
1986 | if (end - y > 0) |
322 | 1300 | v->transpose_block(src + 0 * srclinesize + y * pixstep, | |
323 | srclinesize, | ||
324 | 1300 | dst + (y - start) * dstlinesize + 0 * pixstep, | |
325 | dstlinesize, outw, end - y); | ||
326 | } | ||
327 | |||
328 | 703 | return 0; | |
329 | } | ||
330 | |||
331 | 303 | static int filter_frame(AVFilterLink *inlink, AVFrame *in) | |
332 | { | ||
333 | 303 | int err = 0; | |
334 | 303 | AVFilterContext *ctx = inlink->dst; | |
335 | 303 | TransContext *s = ctx->priv; | |
336 | 303 | AVFilterLink *outlink = ctx->outputs[0]; | |
337 | ThreadData td; | ||
338 | AVFrame *out; | ||
339 | |||
340 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (s->passthrough) |
341 | ✗ | return ff_filter_frame(outlink, in); | |
342 | |||
343 | 303 | out = ff_get_video_buffer(outlink, outlink->w, outlink->h); | |
344 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (!out) { |
345 | ✗ | err = AVERROR(ENOMEM); | |
346 | ✗ | goto fail; | |
347 | } | ||
348 | |||
349 | 303 | err = av_frame_copy_props(out, in); | |
350 |
1/2✗ Branch 0 not taken.
✓ Branch 1 taken 303 times.
|
303 | if (err < 0) |
351 | ✗ | goto fail; | |
352 | |||
353 |
1/2✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
|
303 | if (in->sample_aspect_ratio.num == 0) { |
354 | 303 | out->sample_aspect_ratio = in->sample_aspect_ratio; | |
355 | } else { | ||
356 | ✗ | out->sample_aspect_ratio.num = in->sample_aspect_ratio.den; | |
357 | ✗ | out->sample_aspect_ratio.den = in->sample_aspect_ratio.num; | |
358 | } | ||
359 | |||
360 | 303 | td.in = in, td.out = out; | |
361 | 303 | ff_filter_execute(ctx, filter_slice, &td, NULL, | |
362 |
1/2✓ Branch 0 taken 303 times.
✗ Branch 1 not taken.
|
303 | FFMIN(outlink->h, ff_filter_get_nb_threads(ctx))); |
363 | 303 | av_frame_free(&in); | |
364 | 303 | return ff_filter_frame(outlink, out); | |
365 | |||
366 | ✗ | fail: | |
367 | ✗ | av_frame_free(&in); | |
368 | ✗ | av_frame_free(&out); | |
369 | ✗ | return err; | |
370 | } | ||
371 | |||
372 | #define OFFSET(x) offsetof(TransContext, x) | ||
373 | #define FLAGS AV_OPT_FLAG_FILTERING_PARAM|AV_OPT_FLAG_VIDEO_PARAM | ||
374 | |||
375 | static const AVOption transpose_options[] = { | ||
376 | { "dir", "set transpose direction", OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 7, FLAGS, .unit = "dir" }, | ||
377 | { "cclock_flip", "rotate counter-clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "dir" }, | ||
378 | { "clock", "rotate clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "dir" }, | ||
379 | { "cclock", "rotate counter-clockwise", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "dir" }, | ||
380 | { "clock_flip", "rotate clockwise with vertical flip", 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "dir" }, | ||
381 | |||
382 | { "passthrough", "do not apply transposition if the input matches the specified geometry", | ||
383 | OFFSET(passthrough), AV_OPT_TYPE_INT, {.i64=TRANSPOSE_PT_TYPE_NONE}, 0, INT_MAX, FLAGS, .unit = "passthrough" }, | ||
384 | { "none", "always apply transposition", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_NONE}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" }, | ||
385 | { "portrait", "preserve portrait geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_PORTRAIT}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" }, | ||
386 | { "landscape", "preserve landscape geometry", 0, AV_OPT_TYPE_CONST, {.i64=TRANSPOSE_PT_TYPE_LANDSCAPE}, INT_MIN, INT_MAX, FLAGS, .unit = "passthrough" }, | ||
387 | |||
388 | { NULL } | ||
389 | }; | ||
390 | |||
391 | AVFILTER_DEFINE_CLASS(transpose); | ||
392 | |||
393 | static const AVFilterPad avfilter_vf_transpose_inputs[] = { | ||
394 | { | ||
395 | .name = "default", | ||
396 | .type = AVMEDIA_TYPE_VIDEO, | ||
397 | .get_buffer.video = get_video_buffer, | ||
398 | .filter_frame = filter_frame, | ||
399 | }, | ||
400 | }; | ||
401 | |||
402 | static const AVFilterPad avfilter_vf_transpose_outputs[] = { | ||
403 | { | ||
404 | .name = "default", | ||
405 | .config_props = config_props_output, | ||
406 | .type = AVMEDIA_TYPE_VIDEO, | ||
407 | }, | ||
408 | }; | ||
409 | |||
410 | const AVFilter ff_vf_transpose = { | ||
411 | .name = "transpose", | ||
412 | .description = NULL_IF_CONFIG_SMALL("Transpose input video."), | ||
413 | .priv_size = sizeof(TransContext), | ||
414 | .priv_class = &transpose_class, | ||
415 | FILTER_INPUTS(avfilter_vf_transpose_inputs), | ||
416 | FILTER_OUTPUTS(avfilter_vf_transpose_outputs), | ||
417 | FILTER_QUERY_FUNC2(query_formats), | ||
418 | .flags = AVFILTER_FLAG_SLICE_THREADS, | ||
419 | }; | ||
420 |