Three new chroma converters:
[vlc.git] / modules / video_chroma / yuy2_i422.c
1 /*****************************************************************************
2  * yuy2_i422.c : Packed YUV 4:2:2 to Planar YUV conversion module for vlc
3  *****************************************************************************
4  * Copyright (C) 2007 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Antoine Cellerier <dionoea at videolan dot org>
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * GNU General Public License for more details.
18  *
19  * You should have received a copy of the GNU General Public License
20  * along with this program; if not, write to the Free Software
21  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27
28 #include <vlc/vlc.h>
29 #include <vlc_vout.h>
30
31 #define SRC_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,cyuv"
32 #define DEST_FOURCC  "I422"
33
34 /*****************************************************************************
35  * Local and extern prototypes.
36  *****************************************************************************/
37 static int  Activate ( vlc_object_t * );
38
39 static void YUY2_I422           ( vout_thread_t *, picture_t *, picture_t * );
40 static void YVYU_I422           ( vout_thread_t *, picture_t *, picture_t * );
41 static void UYVY_I422           ( vout_thread_t *, picture_t *, picture_t * );
42 static void cyuv_I422           ( vout_thread_t *, picture_t *, picture_t * );
43
44 /*****************************************************************************
45  * Module descriptor
46  *****************************************************************************/
47 vlc_module_begin();
48     set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
49     set_capability( "chroma", 80 );
50     set_callbacks( Activate, NULL );
51 vlc_module_end();
52
53 /*****************************************************************************
54  * Activate: allocate a chroma function
55  *****************************************************************************
56  * This function allocates and initializes a chroma function
57  *****************************************************************************/
58 static int Activate( vlc_object_t *p_this )
59 {
60     vout_thread_t *p_vout = (vout_thread_t *)p_this;
61
62     if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
63     {
64         return -1;
65     }
66
67     switch( p_vout->output.i_chroma )
68     {
69         case VLC_FOURCC('I','4','2','2'):
70             switch( p_vout->render.i_chroma )
71             {
72                 case VLC_FOURCC('Y','U','Y','2'):
73                 case VLC_FOURCC('Y','U','N','V'):
74                     p_vout->chroma.pf_convert = YUY2_I422;
75                     break;
76
77                 case VLC_FOURCC('Y','V','Y','U'):
78                     p_vout->chroma.pf_convert = YVYU_I422;
79                     break;
80
81                 case VLC_FOURCC('U','Y','V','Y'):
82                 case VLC_FOURCC('U','Y','N','V'):
83                 case VLC_FOURCC('Y','4','2','2'):
84                     p_vout->chroma.pf_convert = UYVY_I422;
85                     break;
86
87                 case VLC_FOURCC('c','y','u','v'):
88                     p_vout->chroma.pf_convert = cyuv_I422;
89                     break;
90
91                 default:
92                     return -1;
93             }
94             break;
95
96         default:
97             return -1;
98     }
99     return 0;
100 }
101
102 /* Following functions are local */
103
104 /*****************************************************************************
105  * YUY2_I422: packed YUY2 4:2:2 to planar YUV 4:2:2
106  *****************************************************************************/
107 static void YUY2_I422( vout_thread_t *p_vout, picture_t *p_source,
108                                               picture_t *p_dest )
109 {
110     uint8_t *p_line = p_source->p->p_pixels;
111
112     uint8_t *p_y = p_dest->Y_PIXELS;
113     uint8_t *p_u = p_dest->U_PIXELS;
114     uint8_t *p_v = p_dest->V_PIXELS;
115
116     int i_x, i_y;
117
118     const int i_dest_margin = p_dest->p[0].i_pitch
119                                  - p_dest->p[0].i_visible_pitch;
120     const int i_dest_margin_c = p_dest->p[1].i_pitch
121                                  - p_dest->p[1].i_visible_pitch;
122     const int i_source_margin = p_source->p->i_pitch
123                                - p_source->p->i_visible_pitch;
124
125     for( i_y = p_vout->output.i_height ; i_y-- ; )
126     {
127         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
128         {
129 #define C_YUYV_YUV422( p_line, p_y, p_u, p_v )      \
130             *p_y++ = *p_line++; *p_u++ = *p_line++; \
131             *p_y++ = *p_line++; *p_v++ = *p_line++
132             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
133             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
134             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
135             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
136         }
137         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
138         {
139             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
140         }
141         p_line += i_source_margin;
142         p_y += i_dest_margin;
143         p_u += i_dest_margin_c;
144         p_v += i_dest_margin_c;
145     }
146 }
147
148 /*****************************************************************************
149  * YVYU_I422: packed YVYU 4:2:2 to planar YUV 4:2:2
150  *****************************************************************************/
151 static void YVYU_I422( vout_thread_t *p_vout, picture_t *p_source,
152                                               picture_t *p_dest )
153 {
154     uint8_t *p_line = p_source->p->p_pixels;
155
156     uint8_t *p_y = p_dest->Y_PIXELS;
157     uint8_t *p_u = p_dest->U_PIXELS;
158     uint8_t *p_v = p_dest->V_PIXELS;
159
160     int i_x, i_y;
161
162     const int i_dest_margin = p_dest->p[0].i_pitch
163                                  - p_dest->p[0].i_visible_pitch;
164     const int i_dest_margin_c = p_dest->p[1].i_pitch
165                                  - p_dest->p[1].i_visible_pitch;
166     const int i_source_margin = p_source->p->i_pitch
167                                - p_source->p->i_visible_pitch;
168
169     for( i_y = p_vout->output.i_height ; i_y-- ; )
170     {
171         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
172         {
173 #define C_YVYU_YUV422( p_line, p_y, p_u, p_v )      \
174             *p_y++ = *p_line++; *p_v++ = *p_line++; \
175             *p_y++ = *p_line++; *p_u++ = *p_line++
176             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
177             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
178             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
179             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
180         }
181         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
182         {
183             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
184         }
185         p_line += i_source_margin;
186         p_y += i_dest_margin;
187         p_u += i_dest_margin_c;
188         p_v += i_dest_margin_c;
189     }
190 }
191
192 /*****************************************************************************
193  * UYVY_I422: packed UYVY 4:2:2 to planar YUV 4:2:2
194  *****************************************************************************/
195 static void UYVY_I422( vout_thread_t *p_vout, picture_t *p_source,
196                                               picture_t *p_dest )
197 {
198     uint8_t *p_line = p_source->p->p_pixels;
199
200     uint8_t *p_y = p_dest->Y_PIXELS;
201     uint8_t *p_u = p_dest->U_PIXELS;
202     uint8_t *p_v = p_dest->V_PIXELS;
203
204     int i_x, i_y;
205
206     const int i_dest_margin = p_dest->p[0].i_pitch
207                                  - p_dest->p[0].i_visible_pitch;
208     const int i_dest_margin_c = p_dest->p[1].i_pitch
209                                  - p_dest->p[1].i_visible_pitch;
210     const int i_source_margin = p_source->p->i_pitch
211                                - p_source->p->i_visible_pitch;
212
213     for( i_y = p_vout->output.i_height ; i_y-- ; )
214     {
215         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
216         {
217 #define C_UYVY_YUV422( p_line, p_y, p_u, p_v )      \
218             *p_u++ = *p_line++; *p_y++ = *p_line++; \
219             *p_v++ = *p_line++; *p_y++ = *p_line++
220             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
221             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
222             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
223             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
224         }
225         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
226         {
227             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
228         }
229         p_line += i_source_margin;
230         p_y += i_dest_margin;
231         p_u += i_dest_margin_c;
232         p_v += i_dest_margin_c;
233     }
234 }
235
236 /*****************************************************************************
237  * cyuv_I422: upside-down packed UYVY 4:2:2 to planar YUV 4:2:2
238  * FIXME
239  *****************************************************************************/
240 static void cyuv_I422( vout_thread_t *p_vout, picture_t *p_source,
241                                               picture_t *p_dest )
242 {
243     uint8_t *p_line = p_source->p->p_pixels;
244
245     uint8_t *p_y = p_dest->Y_PIXELS;
246     uint8_t *p_u = p_dest->U_PIXELS;
247     uint8_t *p_v = p_dest->V_PIXELS;
248
249     int i_x, i_y;
250
251     const int i_dest_margin = p_dest->p[0].i_pitch
252                                  - p_dest->p[0].i_visible_pitch;
253     const int i_dest_margin_c = p_dest->p[1].i_pitch
254                                  - p_dest->p[1].i_visible_pitch;
255     const int i_source_margin = p_source->p->i_pitch
256                                - p_source->p->i_visible_pitch;
257
258     for( i_y = p_vout->output.i_height ; i_y-- ; )
259     {
260         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
261         {
262 #define C_cyuv_YUV422( p_line, p_y, p_u, p_v )      \
263             *p_y++ = *p_line++; *p_v++ = *p_line++; \
264             *p_y++ = *p_line++; *p_u++ = *p_line++
265             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
266             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
267             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
268             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
269         }
270         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
271         {
272             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
273         }
274         p_line += i_source_margin;
275         p_y += i_dest_margin;
276         p_u += i_dest_margin_c;
277         p_v += i_dest_margin_c;
278     }
279 }