]> git.sesse.net Git - vlc/blob - modules/arm_neon/yuv_rgb.c
enable the macosx GUI to handle negative stop-time
[vlc] / modules / arm_neon / yuv_rgb.c
1 /*****************************************************************************
2  * yuv_rgb.c : ARM NEONv1 YUV to RGB32 chroma conversion for VLC
3  *****************************************************************************
4  * Copyright (C) 2011 Sébastien Toque
5  *                    Rémi Denis-Courmont
6  *
7  * This program is free software; you can redistribute it and/or modify it
8  * under the terms of the GNU Lesser General Public License as published by
9  * the Free Software Foundation; either version 2.1 of the License, or
10  * (at your option) any later version.
11  *
12  * This program 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
15  * GNU Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public License
18  * along with this program; if not, write to the Free Software Foundation,
19  * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
20  *****************************************************************************/
21
22 #ifdef HAVE_CONFIG_H
23 # include "config.h"
24 #endif
25
26 #include <vlc_common.h>
27 #include <vlc_plugin.h>
28 #include <vlc_filter.h>
29 #include <vlc_cpu.h>
30 #include "arm_neon/chroma_neon.h"
31
32 static int Open (vlc_object_t *);
33
34 vlc_module_begin ()
35     set_description (N_("ARM NEON video chroma YUV->RGBA"))
36     set_capability ("video filter2", 250)
37     set_callbacks (Open, NULL)
38 vlc_module_end ()
39
40 /*
41 static int CoefY[256];
42 static int CoefRV[256];
43 static int CoefGU[256];
44 static int CoefGV[256];
45 static int CoefBU[256];
46
47 // C reference version of the converter
48 static void I420_RGBA_C (filter_t *filter, picture_t *src, picture_t *dst)
49 {
50     const uint8_t *const out = dst->p->p_pixels;
51     const size_t width = src->p[Y_PLANE].i_visible_pitch;
52     const size_t height = src->p[Y_PLANE].i_visible_lines;
53
54     const int ypitch = src->p[Y_PLANE].i_pitch;
55     const int uvpitch = src->p[U_PLANE].i_pitch;
56     const int dpitch = dst->p->i_pitch / dst->p->i_pixel_pitch;
57
58     for (size_t j = 0; j <  height; ++j)
59     {
60         const int y = j * ypitch;
61         const int u = (j>>1) * uvpitch;
62         const int d = j * dpitch;
63
64         for (size_t i = 0; i < width; ++i)
65         {
66             uint8_t Y = src->Y_PIXELS[y + i];
67             uint8_t U = src->U_PIXELS[u + (i>>1)];
68             uint8_t V = src->V_PIXELS[u + (i>>1)];
69
70             //coef = float * Precision + .5 (Precision=32768)
71             int R = CoefY[Y] + CoefRV[V];
72             int G = CoefY[Y] + CoefGU[U] + CoefGV[V];
73             int B = CoefY[Y] + CoefBU[U];
74
75             //rgb = (rgb+Precision/2) / Precision (Precision=32768)
76             R = R >> 15;
77             G = G >> 15;
78             B = B >> 15;
79
80             if (unlikely(R < 0)) R = 0;
81             if (unlikely(G < 0)) G = 0;
82             if (unlikely(B < 0)) B = 0;
83             if (unlikely(R > 255)) R = 255;
84             if (unlikely(G > 255)) G = 255;
85             if (unlikely(B > 255)) B = 255;
86
87             ((uint32_t*)out)[d + i] = R | (G<<8) | (B<<16) | (0xff<<24);
88         }
89     }
90 }*/
91
92 static void I420_RGBA (filter_t *filter, picture_t *src, picture_t *dst)
93 {
94     struct yuv_pack out = { dst->p->p_pixels, dst->p->i_pitch };
95     struct yuv_planes in = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS, src->Y_PITCH };
96     i420_rgb_neon (&out, &in, filter->fmt_in.video.i_visible_width, filter->fmt_in.video.i_visible_height);
97 }
98
99 static void I420_RV16 (filter_t *filter, picture_t *src, picture_t *dst)
100 {
101     struct yuv_pack out = { dst->p->p_pixels, dst->p->i_pitch };
102     struct yuv_planes in = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS, src->Y_PITCH };
103     i420_rv16_neon (&out, &in, filter->fmt_in.video.i_visible_width, filter->fmt_in.video.i_visible_height);
104 }
105
106 static void YV12_RGBA (filter_t *filter, picture_t *src, picture_t *dst)
107 {
108     struct yuv_pack out = { dst->p->p_pixels, dst->p->i_pitch };
109     struct yuv_planes in = { src->Y_PIXELS, src->V_PIXELS, src->U_PIXELS, src->Y_PITCH };
110     i420_rgb_neon (&out, &in, filter->fmt_in.video.i_visible_width, filter->fmt_in.video.i_visible_height);
111 }
112
113 static void NV21_RGBA (filter_t *filter, picture_t *src, picture_t *dst)
114 {
115     struct yuv_pack out = { dst->p->p_pixels, dst->p->i_pitch };
116     struct yuv_planes in = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS, src->Y_PITCH };
117     nv21_rgb_neon (&out, &in, filter->fmt_in.video.i_visible_width, filter->fmt_in.video.i_visible_height);
118 }
119
120 static void NV12_RGBA (filter_t *filter, picture_t *src, picture_t *dst)
121 {
122     struct yuv_pack out = { dst->p->p_pixels, dst->p->i_pitch };
123     struct yuv_planes in = { src->Y_PIXELS, src->U_PIXELS, src->V_PIXELS, src->Y_PITCH };
124     nv12_rgb_neon (&out, &in, filter->fmt_in.video.i_visible_width, filter->fmt_in.video.i_visible_height);
125 }
126
127 VIDEO_FILTER_WRAPPER (I420_RGBA)
128 VIDEO_FILTER_WRAPPER (I420_RV16)
129 VIDEO_FILTER_WRAPPER (YV12_RGBA)
130 VIDEO_FILTER_WRAPPER (NV21_RGBA)
131 VIDEO_FILTER_WRAPPER (NV12_RGBA)
132
133 static int Open (vlc_object_t *obj)
134 {
135     filter_t *filter = (filter_t *)obj;
136
137     if (!vlc_CPU_ARM_NEON())
138         return VLC_EGENERIC;
139
140     if (((filter->fmt_in.video.i_width | filter->fmt_in.video.i_height) & 1)
141      || (filter->fmt_in.video.i_width != filter->fmt_out.video.i_width)
142      || (filter->fmt_in.video.i_height != filter->fmt_out.video.i_height)
143      || (filter->fmt_in.video.orientation != filter->fmt_out.video.orientation))
144         return VLC_EGENERIC;
145
146     switch (filter->fmt_out.video.i_chroma)
147     {
148         case VLC_CODEC_RGB16:
149             switch (filter->fmt_in.video.i_chroma)
150             {
151                 case VLC_CODEC_I420:
152                     filter->pf_video_filter = I420_RV16_Filter;
153                     break;
154                 default:
155                     return VLC_EGENERIC;
156             }
157             break;
158
159         case VLC_CODEC_RGB32:
160             if(        filter->fmt_out.video.i_rmask != 0x000000ff
161                     || filter->fmt_out.video.i_gmask != 0x0000ff00
162                     || filter->fmt_out.video.i_bmask != 0x00ff0000 )
163                 return VLC_EGENERIC;
164
165             switch (filter->fmt_in.video.i_chroma)
166             {
167                 case VLC_CODEC_I420:
168                     filter->pf_video_filter = I420_RGBA_Filter;
169                     break;
170                 case VLC_CODEC_YV12:
171                     filter->pf_video_filter = YV12_RGBA_Filter;
172                     break;
173                 case VLC_CODEC_NV21:
174                     filter->pf_video_filter = NV21_RGBA_Filter;
175                     break;
176                 case VLC_CODEC_NV12:
177                     filter->pf_video_filter = NV12_RGBA_Filter;
178                     break;
179                 default:
180                     return VLC_EGENERIC;
181             }
182             break;
183
184         default:
185             return VLC_EGENERIC;
186     }
187
188     //precompute some values for the C version
189     /*const int coefY  = (int)(1.164 * 32768 + 0.5);
190     const int coefRV = (int)(1.793 * 32768 + 0.5);
191     const int coefGU = (int)(0.213 * 32768 + 0.5);
192     const int coefGV = (int)(0.533 * 32768 + 0.5);
193     const int coefBU = (int)(2.113 * 32768 + 0.5);
194     for (int i=0; i<256; ++i)
195     {
196         CoefY[i] = coefY * (i-16) + 16384;
197         CoefRV[i] = coefRV*(i-128);
198         CoefGU[i] = -coefGU*(i-128);
199         CoefGV[i] = -coefGV*(i-128);
200         CoefBU[i] = coefBU*(i-128);
201     }*/
202
203     msg_Dbg(filter, "%4.4s(%dx%d) to %4.4s(%dx%d)",
204             (char*)&filter->fmt_in.video.i_chroma, filter->fmt_in.video.i_visible_width, filter->fmt_in.video.i_visible_height,
205             (char*)&filter->fmt_out.video.i_chroma, filter->fmt_out.video.i_visible_width, filter->fmt_out.video.i_visible_height);
206
207     return VLC_SUCCESS;
208 }