History

avfilter: add transpose_vt for videotoolbox pix_fmt

Zhao Zhili committed 3 years ago

Commit 89f51241 parent c2c96c47 files · +300 −1Browse files

Showing the changes to libavfilter (4 of 7 files). Show all

Unified · Split

4 files
  1. libavfilter/Makefile +1 −0
  2. libavfilter/allfilters.c +1 −0
  3. libavfilter/version.h +1 −1
  4. libavfilter/vf_transpose_vt.c +246 −0
libavfilter/Makefile+1−0
@@ -525,6 +525,7 @@ OBJS-$(CONFIG_TRANSPOSE_FILTER) += vf_transpose.o · 524 unmodified lines
525OBJS-$(CONFIG_TRANSPOSE_NPP_FILTER) += vf_transpose_npp.o525OBJS-$(CONFIG_TRANSPOSE_NPP_FILTER) += vf_transpose_npp.o
526OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER) += vf_transpose_opencl.o opencl.o opencl/transpose.o526OBJS-$(CONFIG_TRANSPOSE_OPENCL_FILTER) += vf_transpose_opencl.o opencl.o opencl/transpose.o
527OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER) += vf_transpose_vaapi.o vaapi_vpp.o527OBJS-$(CONFIG_TRANSPOSE_VAAPI_FILTER) += vf_transpose_vaapi.o vaapi_vpp.o
528OBJS-$(CONFIG_TRANSPOSE_VT_FILTER) += vf_transpose_vt.o
528OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER) += vf_transpose_vulkan.o vulkan.o vulkan_filter.o529OBJS-$(CONFIG_TRANSPOSE_VULKAN_FILTER) += vf_transpose_vulkan.o vulkan.o vulkan_filter.o
529OBJS-$(CONFIG_TRIM_FILTER) += trim.o530OBJS-$(CONFIG_TRIM_FILTER) += trim.o
530OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o531OBJS-$(CONFIG_UNPREMULTIPLY_FILTER) += vf_premultiply.o framesync.o
libavfilter/allfilters.c+1−0
@@ -492,6 +492,7 @@ extern const AVFilter ff_vf_transpose; · 491 unmodified lines
492extern const AVFilter ff_vf_transpose_npp;492extern const AVFilter ff_vf_transpose_npp;
493extern const AVFilter ff_vf_transpose_opencl;493extern const AVFilter ff_vf_transpose_opencl;
494extern const AVFilter ff_vf_transpose_vaapi;494extern const AVFilter ff_vf_transpose_vaapi;
495extern const AVFilter ff_vf_transpose_vt;
495extern const AVFilter ff_vf_transpose_vulkan;496extern const AVFilter ff_vf_transpose_vulkan;
496extern const AVFilter ff_vf_trim;497extern const AVFilter ff_vf_trim;
497extern const AVFilter ff_vf_unpremultiply;498extern const AVFilter ff_vf_unpremultiply;
libavfilter/version.h+1−1
@@ -31,7 +31,7 @@ · 30 unmodified lines
31 31
32#include "version_major.h"32#include "version_major.h"
33 33
34#define LIBAVFILTER_VERSION_MINOR 934#define LIBAVFILTER_VERSION_MINOR 10
35#define LIBAVFILTER_VERSION_MICRO 10035#define LIBAVFILTER_VERSION_MICRO 100
36 36
37 37
libavfilter/vf_transpose_vt.c+246−0
@@ -0,0 +1,246 @@
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
23#include "libavutil/hwcontext.h"
24#include "libavutil/hwcontext_videotoolbox.h"
25#include "libavutil/opt.h"
26#include "libavutil/pixdesc.h"
27#include "internal.h"
28#include "transpose.h"
29
30typedef struct TransposeVtContext {
31 AVClass *class;
32
33 VTPixelRotationSessionRef session;
34 int dir;
35 int passthrough;
36} TransposeVtContext;
37
38static av_cold int transpose_vt_init(AVFilterContext *avctx)
39{
40 TransposeVtContext *s = avctx->priv;
41 int ret;
42
43 ret = VTPixelRotationSessionCreate(kCFAllocatorDefault, &s->session);
44 if (ret != noErr) {
45 av_log(avctx, AV_LOG_ERROR, "Rotation session create failed, %d\n", ret);
46 return AVERROR_EXTERNAL;
47 }
48
49 return 0;
50}
51
52static av_cold void transpose_vt_uninit(AVFilterContext *avctx)
53{
54 TransposeVtContext *s = avctx->priv;
55
56 if (s->session) {
57 VTPixelRotationSessionInvalidate(s->session);
58 CFRelease(s->session);
59 s->session = NULL;
60 }
61}
62
63static int transpose_vt_filter_frame(AVFilterLink *link, AVFrame *in)
64{
65 int ret;
66 AVFilterContext *ctx = link->dst;
67 TransposeVtContext *s = ctx->priv;
68 AVFilterLink *outlink = ctx->outputs[0];
69 CVPixelBufferRef src;
70 CVPixelBufferRef dst;
71
72 if (s->passthrough)
73 return ff_filter_frame(outlink, in);
74
75 AVFrame *out = ff_get_video_buffer(outlink, outlink->w, outlink->h);
76 if (!out) {
77 ret = AVERROR(ENOMEM);
78 goto fail;
79 }
80
81 ret = av_frame_copy_props(out, in);
82 if (ret < 0)
83 goto fail;
84
85 src = (CVPixelBufferRef)in->data[3];
86 dst = (CVPixelBufferRef)out->data[3];
87 ret = VTPixelRotationSessionRotateImage(s->session, src, dst);
88 if (ret != noErr) {
89 av_log(ctx, AV_LOG_ERROR, "transfer image failed, %d\n", ret);
90 ret = AVERROR_EXTERNAL;
91 goto fail;
92 }
93
94 av_frame_free(&in);
95
96 return ff_filter_frame(outlink, out);
97
98fail:
99 av_frame_free(&in);
100 av_frame_free(&out);
101 return ret;
102}
103
104static int transpose_vt_config_output(AVFilterLink *outlink)
105{
106 int err;
107 AVFilterContext *avctx = outlink->src;
108 TransposeVtContext *s = avctx->priv;
109 AVFilterLink *inlink = outlink->src->inputs[0];
110 CFStringRef rotation = kVTRotation_0;
111 CFBooleanRef vflip = kCFBooleanFalse;
112 CFBooleanRef hflip = kCFBooleanFalse;
113 int swap_w_h = 0;
114
115 if ((inlink->w >= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_LANDSCAPE) ||
116 (inlink->w <= inlink->h && s->passthrough == TRANSPOSE_PT_TYPE_PORTRAIT)) {
117 av_log(avctx, AV_LOG_VERBOSE,
118 "w:%d h:%d -> w:%d h:%d (passthrough mode)\n",
119 inlink->w, inlink->h, inlink->w, inlink->h);
120 return 0;
121 }
122
123 s->passthrough = TRANSPOSE_PT_TYPE_NONE;
124
125 switch (s->dir) {
126 case TRANSPOSE_CCLOCK_FLIP:
127 rotation = kVTRotation_CCW90;
128 vflip = kCFBooleanTrue;
129 swap_w_h = 1;
130 break;
131 case TRANSPOSE_CCLOCK:
132 rotation = kVTRotation_CCW90;
133 swap_w_h = 1;
134 break;
135 case TRANSPOSE_CLOCK:
136 rotation = kVTRotation_CW90;
137 swap_w_h = 1;
138 break;
139 case TRANSPOSE_CLOCK_FLIP:
140 rotation = kVTRotation_CW90;
141 vflip = kCFBooleanTrue;
142 swap_w_h = 1;
143 break;
144 case TRANSPOSE_REVERSAL:
145 rotation = kVTRotation_180;
146 break;
147 case TRANSPOSE_HFLIP:
148 hflip = kCFBooleanTrue;
149 break;
150 case TRANSPOSE_VFLIP:
151 vflip = kCFBooleanTrue;
152 break;
153 default:
154 av_log(avctx, AV_LOG_ERROR, "Failed to set direction to %d\n", s->dir);
155 return AVERROR(EINVAL);
156 }
157
158 err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_Rotation,
159 rotation);
160 if (err != noErr) {
161 av_log(avctx, AV_LOG_ERROR, "Set rotation property failed, %d\n", err);
162 return AVERROR_EXTERNAL;
163 }
164 err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_FlipVerticalOrientation,
165 vflip);
166 if (err != noErr) {
167 av_log(avctx, AV_LOG_ERROR, "Set vertical flip property failed, %d\n", err);
168 return AVERROR_EXTERNAL;
169 }
170 err = VTSessionSetProperty(s->session, kVTPixelRotationPropertyKey_FlipHorizontalOrientation,
171 hflip);
172 if (err != noErr) {
173 av_log(avctx, AV_LOG_ERROR, "Set horizontal flip property failed, %d\n", err);
174 return AVERROR_EXTERNAL;
175 }
176
177 if (swap_w_h) {
178 outlink->w = inlink->h;
179 outlink->h = inlink->w;
180 }
181
182 return 0;
183}
184
185#define OFFSET(x) offsetof(TransposeVtContext, x)
186#define FLAGS (AV_OPT_FLAG_FILTERING_PARAM | AV_OPT_FLAG_VIDEO_PARAM)
187static const AVOption transpose_vt_options[] = {
188 { "dir", "set transpose direction",
189 OFFSET(dir), AV_OPT_TYPE_INT, { .i64 = TRANSPOSE_CCLOCK_FLIP }, 0, 6, FLAGS, "dir" },
190 { "cclock_flip", "rotate counter-clockwise with vertical flip",
191 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK_FLIP }, .flags=FLAGS, .unit = "dir" },
192 { "clock", "rotate clockwise",
193 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK }, .flags=FLAGS, .unit = "dir" },
194 { "cclock", "rotate counter-clockwise",
195 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CCLOCK }, .flags=FLAGS, .unit = "dir" },
196 { "clock_flip", "rotate clockwise with vertical flip",
197 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_CLOCK_FLIP }, .flags=FLAGS, .unit = "dir" },
198 { "reversal", "rotate by half-turn",
199 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_REVERSAL }, .flags=FLAGS, .unit = "dir" },
200 { "hflip", "flip horizontally",
201 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_HFLIP }, .flags=FLAGS, .unit = "dir" },
202 { "vflip", "flip vertically",
203 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_VFLIP }, .flags=FLAGS, .unit = "dir" },
204
205 { "passthrough", "do not apply transposition if the input matches the specified geometry",
206 OFFSET(passthrough), AV_OPT_TYPE_INT, { .i64=TRANSPOSE_PT_TYPE_NONE }, 0, INT_MAX, FLAGS, "passthrough" },
207 { "none", "always apply transposition",
208 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_PT_TYPE_NONE }, INT_MIN, INT_MAX, FLAGS, "passthrough" },
209 { "portrait", "preserve portrait geometry",
210 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_PT_TYPE_PORTRAIT }, INT_MIN, INT_MAX, FLAGS, "passthrough" },
211 { "landscape", "preserve landscape geometry",
212 0, AV_OPT_TYPE_CONST, { .i64 = TRANSPOSE_PT_TYPE_LANDSCAPE }, INT_MIN, INT_MAX, FLAGS, "passthrough" },
213
214 { NULL }
215};
216
217AVFILTER_DEFINE_CLASS(transpose_vt);
218
219static const AVFilterPad transpose_vt_inputs[] = {
220 {
221 .name = "default",
222 .type = AVMEDIA_TYPE_VIDEO,
223 .filter_frame = &transpose_vt_filter_frame,
224 },
225};
226
227static const AVFilterPad transpose_vt_outputs[] = {
228 {
229 .name = "default",
230 .type = AVMEDIA_TYPE_VIDEO,
231 .config_props = &transpose_vt_config_output,
232 },
233};
234
235const AVFilter ff_vf_transpose_vt = {
236 .name = "transpose_vt",
237 .description = NULL_IF_CONFIG_SMALL("Transpose Videotoolbox frames"),
238 .priv_size = sizeof(TransposeVtContext),
239 .init = transpose_vt_init,
240 .uninit = transpose_vt_uninit,
241 FILTER_INPUTS(transpose_vt_inputs),
242 FILTER_OUTPUTS(transpose_vt_outputs),
243 FILTER_SINGLE_PIXFMT(AV_PIX_FMT_VIDEOTOOLBOX),
244 .priv_class = &transpose_vt_class,
245 .flags = AVFILTER_FLAG_HWDEVICE,
246};

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t