1 /*
2 * Copyright (c) 2023 Zhao Zhili <zhilizhao@tencent.com>
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 <VideoToolbox/VideoToolbox.h>
22
27
31
34
39
41 {
44
45 ret = VTPixelRotationSessionCreate(kCFAllocatorDefault, &
s->session);
49 }
50
51 return 0;
52 }
53
55 {
57
59 VTPixelRotationSessionInvalidate(
s->session);
60 CFRelease(
s->session);
62 }
63 }
64
66 {
74
77
82 }
83
87
88 src = (CVPixelBufferRef)in->
data[3];
89 dst = (CVPixelBufferRef)
out->data[3];
90 ret = VTPixelRotationSessionRotateImage(
s->session,
src,
dst);
95 }
96
98
100
105 }
106
108 {
115 int err;
116
118
124 hw_frame_ctx_out->
width = outlink->
w;
125 hw_frame_ctx_out->
height = outlink->
h;
127
129 if (err < 0)
130 return err;
131
133 if (err < 0) {
135 "Failed to init videotoolbox frame context, %s\n",
137 return err;
138 }
139
140 return 0;
141 }
142
144 {
145 int err;
151 CFStringRef rotation = kVTRotation_0;
152 CFBooleanRef vflip = kCFBooleanFalse;
153 CFBooleanRef hflip = kCFBooleanFalse;
154 int swap_w_h = 0;
155
158
162 "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
164 return 0;
165 }
166
168
171 rotation = kVTRotation_CCW90;
172 vflip = kCFBooleanTrue;
173 swap_w_h = 1;
174 break;
176 rotation = kVTRotation_CCW90;
177 swap_w_h = 1;
178 break;
180 rotation = kVTRotation_CW90;
181 swap_w_h = 1;
182 break;
184 rotation = kVTRotation_CW90;
185 vflip = kCFBooleanTrue;
186 swap_w_h = 1;
187 break;
189 rotation = kVTRotation_180;
190 break;
192 hflip = kCFBooleanTrue;
193 break;
195 vflip = kCFBooleanTrue;
196 break;
197 default:
200 }
201
202 err = VTSessionSetProperty(
s->session, kVTPixelRotationPropertyKey_Rotation,
203 rotation);
204 if (err != noErr) {
207 }
208 err = VTSessionSetProperty(
s->session, kVTPixelRotationPropertyKey_FlipVerticalOrientation,
209 vflip);
210 if (err != noErr) {
213 }
214 err = VTSessionSetProperty(
s->session, kVTPixelRotationPropertyKey_FlipHorizontalOrientation,
215 hflip);
216 if (err != noErr) {
219 }
220
221 if (!swap_w_h)
222 return 0;
223
227 }
228
229 #define OFFSET(x) offsetof(TransposeVtContext, x)
230 #define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
232 { "dir", "set transpose direction",
234 { "cclock_flip", "rotate counter-clockwise with vertical flip",
236 { "clock", "rotate clockwise",
238 { "cclock", "rotate counter-clockwise",
240 { "clock_flip", "rotate clockwise with vertical flip",
242 { "reversal", "rotate by half-turn",
244 { "hflip", "flip horizontally",
246 { "vflip", "flip vertically",
248
249 { "passthrough", "do not apply transposition if the input matches the specified geometry",
251 { "none", "always apply transposition",
253 { "portrait", "preserve portrait geometry",
255 { "landscape", "preserve landscape geometry",
257
259 };
260
262
264 {
268 },
269 };
270
272 {
276 },
277 };
278
280 .
name =
"transpose_vt",
288 .priv_class = &transpose_vt_class,
291 };