]> git.sesse.net Git - vlc/blob - modules/arm_neon/chroma_yuv.c
direct3d11: give enough room for the \0 in the string
[vlc] / modules / arm_neon / chroma_yuv.c
1 /*****************************************************************************
2  * chroma_yuv.c : ARM NEONv1 YUV 4:2:0 to YUV :2:2 chroma conversion for VLC
3  *****************************************************************************
4  * Copyright (C) 2009 RĂ©mi Denis-Courmont
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU Lesser General Public License as published by
8  * the Free Software Foundation; either version 2.1 of the License, or
9  * (at your option) any later version.
10  *
11  * This program 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
14  * GNU Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public License
17  * along with this program; if not, write to the Free Software Foundation,
18  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
19  *****************************************************************************/
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 #endif
24
25 #include <vlc_common.h>
26 #include <vlc_plugin.h>
27 #include <vlc_filter.h>
28 #include <vlc_cpu.h>
29 #include "arm_neon/chroma_neon.h"
30
31 static int Open (vlc_object_t *);
32
33 vlc_module_begin ()
34     set_description (N_("ARM NEON video chroma conversions"))
35     set_capability ("video filter2", 250)
36     set_callbacks (Open, NULL)
37 vlc_module_end ()
38
39 #define DEFINE_PACK(pack, pict) \
40     struct yuv_pack pack = { (pict)->Y_PIXELS, (pict)->Y_PITCH }
41 #define DEFINE_PLANES(planes, pict) \
42     struct yuv_planes planes = { \
43         (pict)->Y_PIXELS, (pict)->U_PIXELS, (pict)->V_PIXELS, (pict)->Y_PITCH }
44 #define DEFINE_PLANES_SWAP(planes, pict) \
45     struct yuv_planes planes = { \
46         (pict)->Y_PIXELS, (pict)->V_PIXELS, (pict)->U_PIXELS, (pict)->Y_PITCH }
47
48 #define DEFINE_UV_PLANES(planes, pict) \
49     struct uv_planes planes = { \
50         (pict)->U_PIXELS, (pict)->V_PIXELS, (pict)->U_PITCH }
51 #define DEFINE_UV_PLANES_SWAP(planes, pict) \
52     struct uv_planes planes = { \
53         (pict)->V_PIXELS, (pict)->U_PIXELS, (pict)->U_PITCH }
54 #define DEFINE_UV_PACK(pack, pict) \
55     struct yuv_pack pack = { (pict)->U_PIXELS, (pict)->U_PITCH }
56
57 /* Planar YUV420 to packed YUV422 */
58 static void I420_YUYV (filter_t *filter, picture_t *src, picture_t *dst)
59 {
60     DEFINE_PACK(out, dst);
61     DEFINE_PLANES(in, src);
62     i420_yuyv_neon (&out, &in, filter->fmt_in.video.i_width,
63                     filter->fmt_in.video.i_height);
64 }
65 VIDEO_FILTER_WRAPPER (I420_YUYV)
66
67 static void I420_YVYU (filter_t *filter, picture_t *src, picture_t *dst)
68 {
69     DEFINE_PACK(out, dst);
70     DEFINE_PLANES_SWAP(in, src);
71     i420_yuyv_neon (&out, &in, filter->fmt_in.video.i_width,
72                     filter->fmt_in.video.i_height);
73 }
74 VIDEO_FILTER_WRAPPER (I420_YVYU)
75
76 static void I420_UYVY (filter_t *filter, picture_t *src, picture_t *dst)
77 {
78     DEFINE_PACK(out, dst);
79     DEFINE_PLANES(in, src);
80     i420_uyvy_neon (&out, &in, filter->fmt_in.video.i_width,
81                     filter->fmt_in.video.i_height);
82 }
83 VIDEO_FILTER_WRAPPER (I420_UYVY)
84
85 static void I420_VYUY (filter_t *filter, picture_t *src, picture_t *dst)
86 {
87     DEFINE_PACK(out, dst);
88     DEFINE_PLANES_SWAP(in, src);
89     i420_uyvy_neon (&out, &in, filter->fmt_in.video.i_width,
90                     filter->fmt_in.video.i_height);
91 }
92 VIDEO_FILTER_WRAPPER (I420_VYUY)
93
94
95 /* Semiplanar NV12/21/16/24 to planar I420/YV12/I422/I444 */
96 static void copy_y_plane(filter_t *filter, picture_t *src, picture_t *dst)
97 {
98     uint8_t *src_y = src->Y_PIXELS;
99     uint8_t *dst_y = dst->Y_PIXELS;
100     if (src->Y_PITCH == dst->Y_PITCH) {
101         memcpy(dst_y, src_y, dst->Y_PITCH * filter->fmt_in.video.i_height);
102     } else {
103         for (unsigned y = 0; y < filter->fmt_in.video.i_height;
104                 y++, dst_y += dst->Y_PITCH, src_y += src->Y_PITCH)
105             memcpy(dst_y, src_y, filter->fmt_in.video.i_width);
106     }
107 }
108
109 #define SEMIPLANAR_FILTERS(name, h_subsamp, v_subsamp)                    \
110 static void name (filter_t *filter, picture_t *src,                       \
111                   picture_t *dst)                                         \
112 {                                                                         \
113     DEFINE_UV_PLANES(out, dst);                                           \
114     DEFINE_UV_PACK(in, src);                                              \
115     copy_y_plane (filter, src, dst);                                      \
116     deinterleave_chroma_neon (&out, &in,                                  \
117                               filter->fmt_in.video.i_width  / h_subsamp,  \
118                               filter->fmt_in.video.i_height / v_subsamp); \
119 }                                                                         \
120 VIDEO_FILTER_WRAPPER (name)                                               \
121
122 #define SEMIPLANAR_FILTERS_SWAP(name, h_subsamp, v_subsamp)               \
123 static void name (filter_t *filter, picture_t *src,                       \
124                   picture_t *dst)                                         \
125 {                                                                         \
126     DEFINE_UV_PLANES_SWAP(out, dst);                                      \
127     DEFINE_UV_PACK(in, src);                                              \
128     copy_y_plane (filter, src, dst);                                      \
129     deinterleave_chroma_neon (&out, &in,                                  \
130                               filter->fmt_in.video.i_width  / h_subsamp,  \
131                               filter->fmt_in.video.i_height / v_subsamp); \
132 }                                                                         \
133 VIDEO_FILTER_WRAPPER (name)                                               \
134
135 SEMIPLANAR_FILTERS (Semiplanar_Planar_420, 2, 2)
136 SEMIPLANAR_FILTERS_SWAP (Semiplanar_Planar_420_Swap, 2, 2)
137 SEMIPLANAR_FILTERS (Semiplanar_Planar_422, 2, 1)
138 SEMIPLANAR_FILTERS (Semiplanar_Planar_444, 1, 1)
139
140
141 /* Planar YUV422 to packed YUV422 */
142 static void I422_YUYV (filter_t *filter, picture_t *src, picture_t *dst)
143 {
144     DEFINE_PACK(out, dst);
145     DEFINE_PLANES(in, src);
146     i422_yuyv_neon (&out, &in, filter->fmt_in.video.i_width,
147                     filter->fmt_in.video.i_height);
148 }
149 VIDEO_FILTER_WRAPPER (I422_YUYV)
150
151 static void I422_YVYU (filter_t *filter, picture_t *src, picture_t *dst)
152 {
153     DEFINE_PACK(out, dst);
154     DEFINE_PLANES_SWAP(in, src);
155     i422_yuyv_neon (&out, &in, filter->fmt_in.video.i_width,
156                     filter->fmt_in.video.i_height);
157 }
158 VIDEO_FILTER_WRAPPER (I422_YVYU)
159
160 static void I422_UYVY (filter_t *filter, picture_t *src, picture_t *dst)
161 {
162     DEFINE_PACK(out, dst);
163     DEFINE_PLANES(in, src);
164     i422_uyvy_neon (&out, &in, filter->fmt_in.video.i_width,
165                     filter->fmt_in.video.i_height);
166 }
167 VIDEO_FILTER_WRAPPER (I422_UYVY)
168
169 static void I422_VYUY (filter_t *filter, picture_t *src, picture_t *dst)
170 {
171     DEFINE_PACK(out, dst);
172     DEFINE_PLANES_SWAP(in, src);
173     i422_uyvy_neon (&out, &in, filter->fmt_in.video.i_width,
174                     filter->fmt_in.video.i_height);
175 }
176 VIDEO_FILTER_WRAPPER (I422_VYUY)
177
178
179 /* Packed YUV422 to planar YUV422 */
180 static void YUYV_I422 (filter_t *filter, picture_t *src, picture_t *dst)
181 {
182     DEFINE_PLANES(out, dst);
183     DEFINE_PACK(in, src);
184     yuyv_i422_neon (&out, &in, filter->fmt_in.video.i_width,
185                     filter->fmt_in.video.i_height);
186 }
187 VIDEO_FILTER_WRAPPER (YUYV_I422)
188
189 static void YVYU_I422 (filter_t *filter, picture_t *src, picture_t *dst)
190 {
191     DEFINE_PLANES_SWAP(out, dst);
192     DEFINE_PACK(in, src);
193     yuyv_i422_neon (&out, &in, filter->fmt_in.video.i_width,
194                     filter->fmt_in.video.i_height);
195 }
196 VIDEO_FILTER_WRAPPER (YVYU_I422)
197
198 static void UYVY_I422 (filter_t *filter, picture_t *src, picture_t *dst)
199 {
200     DEFINE_PLANES(out, dst);
201     DEFINE_PACK(in, src);
202     uyvy_i422_neon (&out, &in, filter->fmt_in.video.i_width,
203                     filter->fmt_in.video.i_height);
204 }
205 VIDEO_FILTER_WRAPPER (UYVY_I422)
206
207 static void VYUY_I422 (filter_t *filter, picture_t *src, picture_t *dst)
208 {
209     DEFINE_PLANES_SWAP(out, dst);
210     DEFINE_PACK(in, src);
211     uyvy_i422_neon (&out, &in, filter->fmt_in.video.i_width,
212                     filter->fmt_in.video.i_height);
213 }
214 VIDEO_FILTER_WRAPPER (VYUY_I422)
215
216 static int Open (vlc_object_t *obj)
217 {
218     filter_t *filter = (filter_t *)obj;
219
220     if (!vlc_CPU_ARM_NEON())
221         return VLC_EGENERIC;
222     if ((filter->fmt_in.video.i_width != filter->fmt_out.video.i_width)
223      || (filter->fmt_in.video.i_height != filter->fmt_out.video.i_height))
224         return VLC_EGENERIC;
225
226     switch (filter->fmt_in.video.i_chroma)
227     {
228         /* Planar to packed */
229         case VLC_CODEC_I420:
230             switch (filter->fmt_out.video.i_chroma)
231             {
232                 case VLC_CODEC_YUYV:
233                     filter->pf_video_filter = I420_YUYV_Filter;
234                     break;
235                 case VLC_CODEC_UYVY:
236                     filter->pf_video_filter = I420_UYVY_Filter;
237                     break;
238                 case VLC_CODEC_YVYU:
239                     filter->pf_video_filter = I420_YVYU_Filter;
240                     break;
241                 case VLC_CODEC_VYUY:
242                     filter->pf_video_filter = I420_VYUY_Filter;
243                     break;
244                 default:
245                     return VLC_EGENERIC;
246             }
247             break;
248
249         case VLC_CODEC_YV12:
250             switch (filter->fmt_out.video.i_chroma)
251             {
252                 case VLC_CODEC_YUYV:
253                     filter->pf_video_filter = I420_YVYU_Filter;
254                     break;
255                 case VLC_CODEC_UYVY:
256                     filter->pf_video_filter = I420_VYUY_Filter;
257                     break;
258                 case VLC_CODEC_YVYU:
259                     filter->pf_video_filter = I420_YUYV_Filter;
260                     break;
261                 case VLC_CODEC_VYUY:
262                     filter->pf_video_filter = I420_UYVY_Filter;
263                     break;
264                 default:
265                     return VLC_EGENERIC;
266             }
267             break;
268
269         case VLC_CODEC_I422:
270             switch (filter->fmt_out.video.i_chroma)
271             {
272                 case VLC_CODEC_YUYV:
273                     filter->pf_video_filter = I422_YUYV_Filter;
274                     break;
275                 case VLC_CODEC_UYVY:
276                     filter->pf_video_filter = I422_UYVY_Filter;
277                     break;
278                 case VLC_CODEC_YVYU:
279                     filter->pf_video_filter = I422_YVYU_Filter;
280                     break;
281                 case VLC_CODEC_VYUY:
282                     filter->pf_video_filter = I422_VYUY_Filter;
283                     break;
284                 default:
285                     return VLC_EGENERIC;
286             }
287             break;
288
289         /* Semiplanar to planar */
290         case VLC_CODEC_NV12:
291             switch (filter->fmt_out.video.i_chroma)
292             {
293                 case VLC_CODEC_I420:
294                     filter->pf_video_filter = Semiplanar_Planar_420_Filter;
295                     break;
296                 case VLC_CODEC_YV12:
297                     filter->pf_video_filter = Semiplanar_Planar_420_Swap_Filter;
298                     break;
299                 default:
300                     return VLC_EGENERIC;
301             }
302             break;
303
304         case VLC_CODEC_NV21:
305             switch (filter->fmt_out.video.i_chroma)
306             {
307                 case VLC_CODEC_I420:
308                     filter->pf_video_filter = Semiplanar_Planar_420_Swap_Filter;
309                     break;
310                 case VLC_CODEC_YV12:
311                     filter->pf_video_filter = Semiplanar_Planar_420_Filter;
312                     break;
313                 default:
314                     return VLC_EGENERIC;
315             }
316             break;
317
318         case VLC_CODEC_NV16:
319             switch (filter->fmt_out.video.i_chroma)
320             {
321                 case VLC_CODEC_I422:
322                     filter->pf_video_filter = Semiplanar_Planar_422_Filter;
323                     break;
324                 default:
325                     return VLC_EGENERIC;
326             }
327             break;
328
329         case VLC_CODEC_NV24:
330             switch (filter->fmt_out.video.i_chroma)
331             {
332                 case VLC_CODEC_I444:
333                     filter->pf_video_filter = Semiplanar_Planar_444_Filter;
334                     break;
335                 default:
336                     return VLC_EGENERIC;
337             }
338             break;
339
340         /* Packed to planar */
341         case VLC_CODEC_YUYV:
342             switch (filter->fmt_out.video.i_chroma)
343             {
344                 case VLC_CODEC_I422:
345                     filter->pf_video_filter = YUYV_I422_Filter;
346                     break;
347                 default:
348                     return VLC_EGENERIC;
349             }
350
351         case VLC_CODEC_UYVY:
352             switch (filter->fmt_out.video.i_chroma)
353             {
354                 case VLC_CODEC_I422:
355                     filter->pf_video_filter = UYVY_I422_Filter;
356                     break;
357                 default:
358                     return VLC_EGENERIC;
359             }
360
361         case VLC_CODEC_YVYU:
362             switch (filter->fmt_out.video.i_chroma)
363             {
364                 case VLC_CODEC_I422:
365                     filter->pf_video_filter = YVYU_I422_Filter;
366                     break;
367                 default:
368                     return VLC_EGENERIC;
369             }
370
371
372         case VLC_CODEC_VYUY:
373             switch (filter->fmt_out.video.i_chroma)
374             {
375                 case VLC_CODEC_I422:
376                     filter->pf_video_filter = VYUY_I422_Filter;
377                     break;
378                 default:
379                     return VLC_EGENERIC;
380             }
381
382         default:
383             return VLC_EGENERIC;
384     }
385     return VLC_SUCCESS;
386 }