Don't include config.h from the headers - refs #297.
[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 #ifdef HAVE_CONFIG_H
29 # include "config.h"
30 #endif
31
32 #include <vlc/vlc.h>
33 #include <vlc_vout.h>
34
35 #define SRC_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,cyuv"
36 #define DEST_FOURCC  "I422"
37
38 /*****************************************************************************
39  * Local and extern prototypes.
40  *****************************************************************************/
41 static int  Activate ( vlc_object_t * );
42
43 static void YUY2_I422           ( vout_thread_t *, picture_t *, picture_t * );
44 static void YVYU_I422           ( vout_thread_t *, picture_t *, picture_t * );
45 static void UYVY_I422           ( vout_thread_t *, picture_t *, picture_t * );
46 static void cyuv_I422           ( vout_thread_t *, picture_t *, picture_t * );
47
48 /*****************************************************************************
49  * Module descriptor
50  *****************************************************************************/
51 vlc_module_begin();
52     set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
53     set_capability( "chroma", 80 );
54     set_callbacks( Activate, NULL );
55 vlc_module_end();
56
57 /*****************************************************************************
58  * Activate: allocate a chroma function
59  *****************************************************************************
60  * This function allocates and initializes a chroma function
61  *****************************************************************************/
62 static int Activate( vlc_object_t *p_this )
63 {
64     vout_thread_t *p_vout = (vout_thread_t *)p_this;
65
66     if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
67     {
68         return -1;
69     }
70
71     switch( p_vout->output.i_chroma )
72     {
73         case VLC_FOURCC('I','4','2','2'):
74             switch( p_vout->render.i_chroma )
75             {
76                 case VLC_FOURCC('Y','U','Y','2'):
77                 case VLC_FOURCC('Y','U','N','V'):
78                     p_vout->chroma.pf_convert = YUY2_I422;
79                     break;
80
81                 case VLC_FOURCC('Y','V','Y','U'):
82                     p_vout->chroma.pf_convert = YVYU_I422;
83                     break;
84
85                 case VLC_FOURCC('U','Y','V','Y'):
86                 case VLC_FOURCC('U','Y','N','V'):
87                 case VLC_FOURCC('Y','4','2','2'):
88                     p_vout->chroma.pf_convert = UYVY_I422;
89                     break;
90
91                 case VLC_FOURCC('c','y','u','v'):
92                     p_vout->chroma.pf_convert = cyuv_I422;
93                     break;
94
95                 default:
96                     return -1;
97             }
98             break;
99
100         default:
101             return -1;
102     }
103     return 0;
104 }
105
106 /* Following functions are local */
107
108 /*****************************************************************************
109  * YUY2_I422: packed YUY2 4:2:2 to planar YUV 4:2:2
110  *****************************************************************************/
111 static void YUY2_I422( vout_thread_t *p_vout, picture_t *p_source,
112                                               picture_t *p_dest )
113 {
114     uint8_t *p_line = p_source->p->p_pixels;
115
116     uint8_t *p_y = p_dest->Y_PIXELS;
117     uint8_t *p_u = p_dest->U_PIXELS;
118     uint8_t *p_v = p_dest->V_PIXELS;
119
120     int i_x, i_y;
121
122     const int i_dest_margin = p_dest->p[0].i_pitch
123                                  - p_dest->p[0].i_visible_pitch;
124     const int i_dest_margin_c = p_dest->p[1].i_pitch
125                                  - p_dest->p[1].i_visible_pitch;
126     const int i_source_margin = p_source->p->i_pitch
127                                - p_source->p->i_visible_pitch;
128
129     for( i_y = p_vout->output.i_height ; i_y-- ; )
130     {
131         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
132         {
133 #define C_YUYV_YUV422( p_line, p_y, p_u, p_v )      \
134             *p_y++ = *p_line++; *p_u++ = *p_line++; \
135             *p_y++ = *p_line++; *p_v++ = *p_line++
136             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
137             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
138             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
139             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
140         }
141         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
142         {
143             C_YUYV_YUV422( p_line, p_y, p_u, p_v );
144         }
145         p_line += i_source_margin;
146         p_y += i_dest_margin;
147         p_u += i_dest_margin_c;
148         p_v += i_dest_margin_c;
149     }
150 }
151
152 /*****************************************************************************
153  * YVYU_I422: packed YVYU 4:2:2 to planar YUV 4:2:2
154  *****************************************************************************/
155 static void YVYU_I422( vout_thread_t *p_vout, picture_t *p_source,
156                                               picture_t *p_dest )
157 {
158     uint8_t *p_line = p_source->p->p_pixels;
159
160     uint8_t *p_y = p_dest->Y_PIXELS;
161     uint8_t *p_u = p_dest->U_PIXELS;
162     uint8_t *p_v = p_dest->V_PIXELS;
163
164     int i_x, i_y;
165
166     const int i_dest_margin = p_dest->p[0].i_pitch
167                                  - p_dest->p[0].i_visible_pitch;
168     const int i_dest_margin_c = p_dest->p[1].i_pitch
169                                  - p_dest->p[1].i_visible_pitch;
170     const int i_source_margin = p_source->p->i_pitch
171                                - p_source->p->i_visible_pitch;
172
173     for( i_y = p_vout->output.i_height ; i_y-- ; )
174     {
175         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
176         {
177 #define C_YVYU_YUV422( p_line, p_y, p_u, p_v )      \
178             *p_y++ = *p_line++; *p_v++ = *p_line++; \
179             *p_y++ = *p_line++; *p_u++ = *p_line++
180             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
181             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
182             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
183             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
184         }
185         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
186         {
187             C_YVYU_YUV422( p_line, p_y, p_u, p_v );
188         }
189         p_line += i_source_margin;
190         p_y += i_dest_margin;
191         p_u += i_dest_margin_c;
192         p_v += i_dest_margin_c;
193     }
194 }
195
196 /*****************************************************************************
197  * UYVY_I422: packed UYVY 4:2:2 to planar YUV 4:2:2
198  *****************************************************************************/
199 static void UYVY_I422( vout_thread_t *p_vout, picture_t *p_source,
200                                               picture_t *p_dest )
201 {
202     uint8_t *p_line = p_source->p->p_pixels;
203
204     uint8_t *p_y = p_dest->Y_PIXELS;
205     uint8_t *p_u = p_dest->U_PIXELS;
206     uint8_t *p_v = p_dest->V_PIXELS;
207
208     int i_x, i_y;
209
210     const int i_dest_margin = p_dest->p[0].i_pitch
211                                  - p_dest->p[0].i_visible_pitch;
212     const int i_dest_margin_c = p_dest->p[1].i_pitch
213                                  - p_dest->p[1].i_visible_pitch;
214     const int i_source_margin = p_source->p->i_pitch
215                                - p_source->p->i_visible_pitch;
216
217     for( i_y = p_vout->output.i_height ; i_y-- ; )
218     {
219         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
220         {
221 #define C_UYVY_YUV422( p_line, p_y, p_u, p_v )      \
222             *p_u++ = *p_line++; *p_y++ = *p_line++; \
223             *p_v++ = *p_line++; *p_y++ = *p_line++
224             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
225             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
226             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
227             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
228         }
229         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
230         {
231             C_UYVY_YUV422( p_line, p_y, p_u, p_v );
232         }
233         p_line += i_source_margin;
234         p_y += i_dest_margin;
235         p_u += i_dest_margin_c;
236         p_v += i_dest_margin_c;
237     }
238 }
239
240 /*****************************************************************************
241  * cyuv_I422: upside-down packed UYVY 4:2:2 to planar YUV 4:2:2
242  * FIXME
243  *****************************************************************************/
244 static void cyuv_I422( vout_thread_t *p_vout, picture_t *p_source,
245                                               picture_t *p_dest )
246 {
247     uint8_t *p_line = p_source->p->p_pixels;
248
249     uint8_t *p_y = p_dest->Y_PIXELS;
250     uint8_t *p_u = p_dest->U_PIXELS;
251     uint8_t *p_v = p_dest->V_PIXELS;
252
253     int i_x, i_y;
254
255     const int i_dest_margin = p_dest->p[0].i_pitch
256                                  - p_dest->p[0].i_visible_pitch;
257     const int i_dest_margin_c = p_dest->p[1].i_pitch
258                                  - p_dest->p[1].i_visible_pitch;
259     const int i_source_margin = p_source->p->i_pitch
260                                - p_source->p->i_visible_pitch;
261
262     for( i_y = p_vout->output.i_height ; i_y-- ; )
263     {
264         for( i_x = p_vout->output.i_width / 8 ; i_x-- ; )
265         {
266 #define C_cyuv_YUV422( p_line, p_y, p_u, p_v )      \
267             *p_y++ = *p_line++; *p_v++ = *p_line++; \
268             *p_y++ = *p_line++; *p_u++ = *p_line++
269             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
270             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
271             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
272             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
273         }
274         for( i_x = ( p_vout->output.i_width % 8 ) / 2; i_x-- ; )
275         {
276             C_cyuv_YUV422( p_line, p_y, p_u, p_v );
277         }
278         p_line += i_source_margin;
279         p_y += i_dest_margin;
280         p_u += i_dest_margin_c;
281         p_v += i_dest_margin_c;
282     }
283 }