video_chroma: added I420_ABGR32 support (mostly for opengl), some clean up as well
[vlc.git] / modules / video_chroma / i422_yuy2.c
1 /*****************************************************************************
2  * i422_yuy2.c : YUV to YUV conversion module for vlc
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 the VideoLAN team
5  * $Id$
6  *
7  * Authors: Samuel Hocevar <sam@zoy.org>
8  *          Damien Fouilleul <damienf@videolan.org>
9  *
10  * This program is free software; you can redistribute it and/or modify
11  * it under the terms of the GNU General Public License as published by
12  * the Free Software Foundation; either version 2 of the License, or
13  * (at your option) any later version.
14  * 
15  * This program is distributed in the hope that it will be useful,
16  * but WITHOUT ANY WARRANTY; without even the implied warranty of
17  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
18  * GNU General Public License for more details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with this program; if not, write to the Free Software
22  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
23  *****************************************************************************/
24
25 /*****************************************************************************
26  * Preamble
27  *****************************************************************************/
28 #include <string.h>                                            /* strerror() */
29 #include <stdlib.h>                                      /* malloc(), free() */
30
31 #include <vlc/vlc.h>
32 #include <vlc_vout.h>
33
34 #include "i422_yuy2.h"
35
36 #define SRC_FOURCC  "I422"
37 #if defined (MODULE_NAME_IS_i422_yuy2)
38 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
39 #else
40 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
41 #endif
42
43 /*****************************************************************************
44  * Local and extern prototypes.
45  *****************************************************************************/
46 static int  Activate ( vlc_object_t * );
47
48 static void I422_YUY2           ( vout_thread_t *, picture_t *, picture_t * );
49 static void I422_YVYU           ( vout_thread_t *, picture_t *, picture_t * );
50 static void I422_UYVY           ( vout_thread_t *, picture_t *, picture_t * );
51 static void I422_IUYV           ( vout_thread_t *, picture_t *, picture_t * );
52 static void I422_cyuv           ( vout_thread_t *, picture_t *, picture_t * );
53 #if defined (MODULE_NAME_IS_i422_yuy2)
54 static void I422_Y211           ( vout_thread_t *, picture_t *, picture_t * );
55 static void I422_Y211           ( vout_thread_t *, picture_t *, picture_t * );
56 static void I422_YV12           ( vout_thread_t *, picture_t *, picture_t * );
57 #endif
58
59 /*****************************************************************************
60  * Module descriptor
61  *****************************************************************************/
62 vlc_module_begin();
63 #if defined (MODULE_NAME_IS_i422_yuy2)
64     set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
65     set_capability( "chroma", 80 );
66 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
67     set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
68     set_capability( "chroma", 100 );
69     add_requirement( MMX );
70 #endif
71     set_callbacks( Activate, NULL );
72 vlc_module_end();
73
74 /*****************************************************************************
75  * Activate: allocate a chroma function
76  *****************************************************************************
77  * This function allocates and initializes a chroma function
78  *****************************************************************************/
79 static int Activate( vlc_object_t *p_this )
80 {
81     vout_thread_t *p_vout = (vout_thread_t *)p_this;
82
83     if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
84     {
85         return -1;
86     }
87
88     switch( p_vout->render.i_chroma )
89     {
90         case VLC_FOURCC('I','4','2','2'):
91             switch( p_vout->output.i_chroma )
92             {
93                 case VLC_FOURCC('Y','U','Y','2'):
94                 case VLC_FOURCC('Y','U','N','V'):
95                     p_vout->chroma.pf_convert = I422_YUY2;
96                     break;
97
98                 case VLC_FOURCC('Y','V','Y','U'):
99                     p_vout->chroma.pf_convert = I422_YVYU;
100                     break;
101
102                 case VLC_FOURCC('U','Y','V','Y'):
103                 case VLC_FOURCC('U','Y','N','V'):
104                 case VLC_FOURCC('Y','4','2','2'):
105                     p_vout->chroma.pf_convert = I422_UYVY;
106                     break;
107
108                 case VLC_FOURCC('I','U','Y','V'):
109                     p_vout->chroma.pf_convert = I422_IUYV;
110                     break;
111
112                 case VLC_FOURCC('c','y','u','v'):
113                     p_vout->chroma.pf_convert = I422_cyuv;
114                     break;
115
116 #if defined (MODULE_NAME_IS_i422_yuy2)
117                 case VLC_FOURCC('Y','2','1','1'):
118                     p_vout->chroma.pf_convert = I422_Y211;
119                     break;
120
121                 case VLC_FOURCC('Y','V','1','2'):
122                     p_vout->chroma.pf_convert = I422_YV12;
123                     break;
124 #endif
125
126                 default:
127                     return -1;
128             }
129             break;
130
131         default:
132             return -1;
133     }
134     
135     return 0; 
136 }
137
138 /* Following functions are local */
139
140 /*****************************************************************************
141  * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
142  *****************************************************************************/
143 static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
144                                               picture_t *p_dest )
145 {
146     uint8_t *p_pixels = p_dest->p->p_pixels;
147     int      i_pitch  = p_dest->p->i_pitch;
148     uint8_t *p_y = p_source->Y_PIXELS;
149     uint8_t *p_u = p_source->U_PIXELS;
150     uint8_t *p_v = p_source->V_PIXELS;
151
152     int i_x, i_y;
153
154     for( i_y = p_vout->render.i_height ; i_y-- ; )
155     {
156         uint8_t *p_line = p_pixels;
157         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
158         {
159 #if defined (MODULE_NAME_IS_i422_yuy2)
160             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
161             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
162             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
163             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
164 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
165             MMX_CALL( MMX_YUV422_YUYV );
166 #endif
167         }
168         p_pixels += i_pitch;
169     }
170 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
171     MMX_END;
172 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
173     SSE2_END;
174 #endif
175 }
176
177 /*****************************************************************************
178  * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
179  *****************************************************************************/
180 static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
181                                               picture_t *p_dest )
182 {
183     uint8_t *p_pixels = p_dest->p->p_pixels;
184     int      i_pitch  = p_dest->p->i_pitch;
185     uint8_t *p_y = p_source->Y_PIXELS;
186     uint8_t *p_u = p_source->U_PIXELS;
187     uint8_t *p_v = p_source->V_PIXELS;
188
189     int i_x, i_y;
190
191     for( i_y = p_vout->render.i_height ; i_y-- ; )
192     {
193         uint8_t *p_line = p_pixels;
194         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
195         {
196 #if defined (MODULE_NAME_IS_i422_yuy2)
197             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
198             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
199             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
200             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
201 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
202             MMX_CALL( MMX_YUV422_YVYU );
203 #endif
204         }
205         p_pixels += i_pitch;
206     }
207 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
208     MMX_END;
209 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
210     SSE2_END;
211 #endif
212 }
213
214 /*****************************************************************************
215  * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
216  *****************************************************************************/
217 static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
218                                               picture_t *p_dest )
219 {
220     uint8_t *p_pixels = p_dest->p->p_pixels;
221     int      i_pitch  = p_dest->p->i_pitch;
222     uint8_t *p_y = p_source->Y_PIXELS;
223     uint8_t *p_u = p_source->U_PIXELS;
224     uint8_t *p_v = p_source->V_PIXELS;
225
226     int i_x, i_y;
227
228     for( i_y = p_vout->render.i_height ; i_y-- ; )
229     {
230         uint8_t *p_line = p_pixels;
231         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
232         {
233 #if defined (MODULE_NAME_IS_i422_yuy2)
234             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
235             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
236             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
237             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
238 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
239             MMX_CALL( MMX_YUV422_UYVY );
240 #endif
241         }
242         p_pixels += i_pitch;
243     }
244 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
245     MMX_END;
246 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
247     SSE2_END;
248 #endif
249 }
250
251 /*****************************************************************************
252  * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
253  *****************************************************************************/
254 static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
255                                               picture_t *p_dest )
256 {
257     /* FIXME: TODO ! */
258     msg_Err( p_vout, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
259 }
260
261 /*****************************************************************************
262  * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
263  *****************************************************************************/
264 static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
265                                               picture_t *p_dest )
266 {
267     uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
268     uint8_t *p_y = p_source->Y_PIXELS;
269     uint8_t *p_u = p_source->U_PIXELS;
270     uint8_t *p_v = p_source->V_PIXELS;
271
272     int i_x, i_y;
273
274     for( i_y = p_vout->render.i_height ; i_y-- ; )
275     {
276         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
277         {
278             p_line -= 2 * p_dest->p->i_pitch;
279
280 #if defined (MODULE_NAME_IS_i422_yuy2)
281             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
282             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
283             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
284             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
285 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
286             MMX_CALL( MMX_YUV422_UYVY );
287 #endif
288         }
289     }
290 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
291     MMX_END;
292 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
293     SSE2_END;
294 #endif
295 }
296
297 /*****************************************************************************
298  * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
299  *****************************************************************************/
300 #if defined (MODULE_NAME_IS_i422_yuy2)
301 static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
302                                               picture_t *p_dest )
303 {
304     uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
305     uint8_t *p_y = p_source->Y_PIXELS;
306     uint8_t *p_u = p_source->U_PIXELS;
307     uint8_t *p_v = p_source->V_PIXELS;
308
309     int i_x, i_y;
310
311     for( i_y = p_vout->render.i_height ; i_y-- ; )
312     {
313         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
314         {
315             C_YUV422_Y211( p_line, p_y, p_u, p_v );
316             C_YUV422_Y211( p_line, p_y, p_u, p_v );
317         }
318     }
319 }
320 #endif
321
322
323 /*****************************************************************************
324  * I422_YV12: planar YUV 4:2:2 to planar YV12
325  *****************************************************************************/
326 #if defined (MODULE_NAME_IS_i422_yuy2)
327 static void I422_YV12( vout_thread_t *p_vout, picture_t *p_source,
328                                               picture_t *p_dest )
329 {
330     uint16_t i_dpy = p_dest->p[Y_PLANE].i_pitch;
331     uint16_t i_spy = p_source->p[Y_PLANE].i_pitch;
332     uint16_t i_dpuv = p_dest->p[U_PLANE].i_pitch;
333     uint16_t i_spuv = p_source->p[U_PLANE].i_pitch;
334     uint16_t i_width = p_vout->render.i_width;
335     uint16_t i_y = p_vout->render.i_height;
336     uint8_t *p_dy = p_dest->Y_PIXELS + (i_y-1)*i_dpy;
337     uint8_t *p_y = p_source->Y_PIXELS + (i_y-1)*i_spy;
338     uint8_t *p_du = p_dest->U_PIXELS + (i_y/2-1)*i_dpuv;
339     uint8_t *p_u = p_source->U_PIXELS + (i_y-1)*i_spuv;
340     uint8_t *p_dv = p_dest->V_PIXELS + (i_y/2-1)*i_dpuv;
341     uint8_t *p_v = p_source->V_PIXELS + (i_y-1)*i_spuv;
342     i_y /= 2;
343
344     for ( ; i_y--; )
345     {
346         memcpy(p_dy, p_y, i_width); p_dy -= i_dpy; p_y -= i_spy;
347         memcpy(p_dy, p_y, i_width); p_dy -= i_dpy; p_y -= i_spy;
348         memcpy(p_du, p_u, i_width/2); p_du -= i_dpuv; p_u -= 2*i_spuv;
349         memcpy(p_dv, p_v, i_width/2); p_dv -= i_dpuv; p_v -= 2*i_spuv;
350     }
351
352 }
353 #endif