]> git.sesse.net Git - vlc/blob - plugins/chroma/i422_yuy2.c
* ./BUGS: added a list of known bugs. Please add your findings!
[vlc] / plugins / chroma / i422_yuy2.c
1 /*****************************************************************************
2  * i422_yuy2.c : YUV to YUV conversion module for vlc
3  *****************************************************************************
4  * Copyright (C) 2000, 2001 VideoLAN
5  * $Id: i422_yuy2.c,v 1.1 2002/01/04 14:01:34 sam Exp $
6  *
7  * Authors: Samuel Hocevar <sam@zoy.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., 59 Temple Place - Suite 330, Boston, MA  02111, USA.
22  *****************************************************************************/
23
24 /*****************************************************************************
25  * Preamble
26  *****************************************************************************/
27 #include <math.h>                                            /* exp(), pow() */
28 #include <errno.h>                                                 /* ENOMEM */
29 #include <string.h>                                            /* strerror() */
30 #include <stdlib.h>                                      /* malloc(), free() */
31
32 #include <videolan/vlc.h>
33
34 #include "video.h"
35 #include "video_output.h"
36
37 #include "i422_yuy2.h"
38
39 #define SRC_FOURCC  "I422"
40 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
41 #    define DEST_FOURCC "YUY2/YUNV/YVYU/UYVY/UYNV/Y422/IUYV/cyuv/Y211"
42 #else
43 #    define DEST_FOURCC "YUY2/YUNV/YVYU/UYVY/UYNV/Y422/IUYV/cyuv"
44 #endif
45
46 /*****************************************************************************
47  * Local and extern prototypes.
48  *****************************************************************************/
49 static void chroma_getfunctions ( function_list_t * p_function_list );
50
51 static int  chroma_Probe        ( probedata_t *p_data );
52 static int  chroma_Init         ( vout_thread_t *p_vout );
53 static void chroma_End          ( vout_thread_t *p_vout );
54
55 static void I422_YUY2           ( vout_thread_t *, picture_t *, picture_t * );
56 static void I422_YVYU           ( vout_thread_t *, picture_t *, picture_t * );
57 static void I422_UYVY           ( vout_thread_t *, picture_t *, picture_t * );
58 static void I422_IUYV           ( vout_thread_t *, picture_t *, picture_t * );
59 static void I422_cyuv           ( vout_thread_t *, picture_t *, picture_t * );
60 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
61 static void I422_Y211           ( vout_thread_t *, picture_t *, picture_t * );
62 #endif
63
64 /*****************************************************************************
65  * Build configuration tree.
66  *****************************************************************************/
67 MODULE_CONFIG_START
68 MODULE_CONFIG_STOP
69
70 MODULE_INIT_START
71 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
72     SET_DESCRIPTION( "conversions from " SRC_FOURCC " to " DEST_FOURCC )
73     ADD_CAPABILITY( CHROMA, 80 )
74 #elif defined (MODULE_NAME_IS_chroma_i422_yuy2_mmx)
75     SET_DESCRIPTION( "MMX conversions from " SRC_FOURCC " to " DEST_FOURCC )
76     ADD_CAPABILITY( CHROMA, 100 )
77     ADD_REQUIREMENT( MMX )
78 #endif
79 MODULE_INIT_STOP
80
81 MODULE_ACTIVATE_START
82     chroma_getfunctions( &p_module->p_functions->chroma );
83 MODULE_ACTIVATE_STOP
84
85 MODULE_DEACTIVATE_START
86 MODULE_DEACTIVATE_STOP
87
88 /*****************************************************************************
89  * Functions exported as capabilities. They are declared as static so that
90  * we don't pollute the namespace too much.
91  *****************************************************************************/
92 static void chroma_getfunctions( function_list_t * p_function_list )
93 {
94     p_function_list->pf_probe = chroma_Probe;
95     p_function_list->functions.chroma.pf_init = chroma_Init;
96     p_function_list->functions.chroma.pf_end  = chroma_End;
97 }
98
99 /*****************************************************************************
100  * chroma_Probe: return a score
101  *****************************************************************************
102  * This function checks that we can handle the required data
103  *****************************************************************************/
104 static int chroma_Probe( probedata_t *p_data )
105 {
106     if( p_data->chroma.p_render->i_width & 1
107          || p_data->chroma.p_render->i_height & 1 )
108     {
109         return 0;
110     }
111
112     switch( p_data->chroma.p_render->i_chroma )
113     {
114         case FOURCC_I422:
115             switch( p_data->chroma.p_output->i_chroma )
116             {
117                 case FOURCC_YUY2:
118                 case FOURCC_YUNV:
119                     break;
120
121                 case FOURCC_YVYU:
122                     break;
123
124                 case FOURCC_UYVY:
125                 case FOURCC_UYNV:
126                 case FOURCC_Y422:
127                     break;
128
129                 case FOURCC_IUYV:
130                     break;
131
132                 case FOURCC_cyuv:
133                     break;
134
135 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
136                 case FOURCC_Y211:
137                     break;
138 #endif
139
140                 default:
141                     return 0;
142             }
143             break;
144
145         default:
146             return 0;
147     }
148
149     return 100;
150 }
151
152 /*****************************************************************************
153  * chroma_Init: allocate a chroma function
154  *****************************************************************************
155  * This function allocates and initializes a chroma function
156  *****************************************************************************/
157 static int chroma_Init( vout_thread_t *p_vout )
158 {
159     if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
160     {
161         return -1;
162     }
163
164     switch( p_vout->render.i_chroma )
165     {
166         case FOURCC_I422:
167             switch( p_vout->output.i_chroma )
168             {
169                 case FOURCC_YUY2:
170                 case FOURCC_YUNV:
171                     p_vout->chroma.pf_convert = I422_YUY2;
172                     break;
173
174                 case FOURCC_YVYU:
175                     p_vout->chroma.pf_convert = I422_YVYU;
176                     break;
177
178                 case FOURCC_UYVY:
179                 case FOURCC_UYNV:
180                 case FOURCC_Y422:
181                     p_vout->chroma.pf_convert = I422_UYVY;
182                     break;
183
184                 case FOURCC_IUYV:
185                     p_vout->chroma.pf_convert = I422_IUYV;
186                     break;
187
188                 case FOURCC_cyuv:
189                     p_vout->chroma.pf_convert = I422_cyuv;
190                     break;
191
192 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
193                 case FOURCC_Y211:
194                     p_vout->chroma.pf_convert = I422_Y211;
195                     break;
196 #endif
197
198                 default:
199                     return -1;
200             }
201             break;
202
203         default:
204             return -1;
205     }
206     
207     return 0; 
208 }
209
210 /*****************************************************************************
211  * chroma_End: free the chroma function
212  *****************************************************************************
213  * This function frees the previously allocated chroma function
214  *****************************************************************************/
215 static void chroma_End( vout_thread_t *p_vout )
216 {
217     ;
218 }
219
220 /* Following functions are local */
221
222 /*****************************************************************************
223  * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
224  *****************************************************************************/
225 static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
226                                               picture_t *p_dest )
227 {
228     u8 *p_line = p_dest->p->p_pixels;
229     u8 *p_y = p_source->Y_PIXELS;
230     u8 *p_u = p_source->U_PIXELS;
231     u8 *p_v = p_source->V_PIXELS;
232
233     int i_x, i_y;
234
235     for( i_y = p_vout->render.i_height ; i_y-- ; )
236     {
237         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
238         {
239 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
240             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
241             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
242             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
243             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
244 #else
245             __asm__( ".align 8" MMX_YUV422_YUYV
246                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
247
248             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
249
250             __asm__( ".align 8" MMX_YUV422_YUYV
251                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
252
253             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
254 #endif
255         }
256     }
257 }
258
259 /*****************************************************************************
260  * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
261  *****************************************************************************/
262 static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
263                                               picture_t *p_dest )
264 {
265     u8 *p_line = p_dest->p->p_pixels;
266     u8 *p_y = p_source->Y_PIXELS;
267     u8 *p_u = p_source->U_PIXELS;
268     u8 *p_v = p_source->V_PIXELS;
269
270     int i_x, i_y;
271
272     for( i_y = p_vout->render.i_height ; i_y-- ; )
273     {
274         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
275         {
276 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
277             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
278             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
279             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
280             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
281 #else
282             __asm__( ".align 8" MMX_YUV422_YVYU
283                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
284
285             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
286
287             __asm__( ".align 8" MMX_YUV422_YVYU
288                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
289
290             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
291 #endif
292         }
293     }
294 }
295
296 /*****************************************************************************
297  * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
298  *****************************************************************************/
299 static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
300                                               picture_t *p_dest )
301 {
302     u8 *p_line = p_dest->p->p_pixels;
303     u8 *p_y = p_source->Y_PIXELS;
304     u8 *p_u = p_source->U_PIXELS;
305     u8 *p_v = p_source->V_PIXELS;
306
307     int i_x, i_y;
308
309     for( i_y = p_vout->render.i_height ; i_y-- ; )
310     {
311         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
312         {
313 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
314             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
315             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
316             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
317             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
318 #else
319             __asm__( ".align 8" MMX_YUV422_UYVY
320                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
321
322             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
323
324             __asm__( ".align 8" MMX_YUV422_UYVY
325                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
326
327             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
328 #endif
329         }
330     }
331 }
332
333 /*****************************************************************************
334  * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
335  *****************************************************************************/
336 static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
337                                               picture_t *p_dest )
338 {
339     /* FIXME: TODO ! */
340     intf_ErrMsg( "chroma error: I422_IUYV unimplemented, "
341                  "please harass <sam@zoy.org>" );
342 }
343
344 /*****************************************************************************
345  * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
346  *****************************************************************************/
347 static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
348                                               picture_t *p_dest )
349 {
350     u8 *p_line = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
351     u8 *p_y = p_source->Y_PIXELS;
352     u8 *p_u = p_source->U_PIXELS;
353     u8 *p_v = p_source->V_PIXELS;
354
355     int i_x, i_y;
356
357     for( i_y = p_vout->render.i_height ; i_y-- ; )
358     {
359         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
360         {
361             p_line -= 2 * p_dest->p->i_pitch;
362
363 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
364             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
365             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
366             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
367             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
368 #else
369             __asm__( ".align 8" MMX_YUV422_UYVY
370                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
371
372             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
373
374             __asm__( ".align 8" MMX_YUV422_UYVY
375                      : : "r" (p_line), "r" (p_y), "r" (p_u), "r" (p_v) ); 
376
377             p_line += 8; p_y += 4; p_u += 2; p_v += 2;
378 #endif
379         }
380     }
381 }
382
383 /*****************************************************************************
384  * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
385  *****************************************************************************/
386 #if defined (MODULE_NAME_IS_chroma_i422_yuy2)
387 static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
388                                               picture_t *p_dest )
389 {
390     u8 *p_line = p_dest->p->p_pixels + p_dest->p->i_lines * p_dest->p->i_pitch;
391     u8 *p_y = p_source->Y_PIXELS;
392     u8 *p_u = p_source->U_PIXELS;
393     u8 *p_v = p_source->V_PIXELS;
394
395     int i_x, i_y;
396
397     for( i_y = p_vout->render.i_height ; i_y-- ; )
398     {
399         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
400         {
401             C_YUV422_Y211( p_line, p_y, p_u, p_v );
402             C_YUV422_Y211( p_line, p_y, p_u, p_v );
403         }
404     }
405 }
406 #endif
407