]> git.sesse.net Git - vlc/blob - modules/video_chroma/i422_yuy2.c
Remove stdlib.h
[vlc] / 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
30 #include <vlc/vlc.h>
31 #include <vlc_vout.h>
32
33 #include "i422_yuy2.h"
34
35 #define SRC_FOURCC  "I422"
36 #if defined (MODULE_NAME_IS_i422_yuy2)
37 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
38 #else
39 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
40 #endif
41
42 /*****************************************************************************
43  * Local and extern prototypes.
44  *****************************************************************************/
45 static int  Activate ( vlc_object_t * );
46
47 static void I422_YUY2           ( vout_thread_t *, picture_t *, picture_t * );
48 static void I422_YVYU           ( vout_thread_t *, picture_t *, picture_t * );
49 static void I422_UYVY           ( vout_thread_t *, picture_t *, picture_t * );
50 static void I422_IUYV           ( vout_thread_t *, picture_t *, picture_t * );
51 static void I422_cyuv           ( vout_thread_t *, picture_t *, picture_t * );
52 #if defined (MODULE_NAME_IS_i422_yuy2)
53 static void I422_Y211           ( vout_thread_t *, picture_t *, picture_t * );
54 static void I422_Y211           ( vout_thread_t *, picture_t *, picture_t * );
55 static void I422_YV12           ( vout_thread_t *, picture_t *, picture_t * );
56 #endif
57
58 /*****************************************************************************
59  * Module descriptor
60  *****************************************************************************/
61 vlc_module_begin();
62 #if defined (MODULE_NAME_IS_i422_yuy2)
63     set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
64     set_capability( "chroma", 80 );
65 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
66     set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
67     set_capability( "chroma", 100 );
68     add_requirement( MMX );
69 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
70     set_description( _("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) );
71     set_capability( "chroma", 120 );
72     add_requirement( MMX );
73 #endif
74     set_callbacks( Activate, NULL );
75 vlc_module_end();
76
77 /*****************************************************************************
78  * Activate: allocate a chroma function
79  *****************************************************************************
80  * This function allocates and initializes a chroma function
81  *****************************************************************************/
82 static int Activate( vlc_object_t *p_this )
83 {
84     vout_thread_t *p_vout = (vout_thread_t *)p_this;
85
86     if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
87     {
88         return -1;
89     }
90
91     switch( p_vout->render.i_chroma )
92     {
93         case VLC_FOURCC('I','4','2','2'):
94             switch( p_vout->output.i_chroma )
95             {
96                 case VLC_FOURCC('Y','U','Y','2'):
97                 case VLC_FOURCC('Y','U','N','V'):
98                     p_vout->chroma.pf_convert = I422_YUY2;
99                     break;
100
101                 case VLC_FOURCC('Y','V','Y','U'):
102                     p_vout->chroma.pf_convert = I422_YVYU;
103                     break;
104
105                 case VLC_FOURCC('U','Y','V','Y'):
106                 case VLC_FOURCC('U','Y','N','V'):
107                 case VLC_FOURCC('Y','4','2','2'):
108                     p_vout->chroma.pf_convert = I422_UYVY;
109                     break;
110
111                 case VLC_FOURCC('I','U','Y','V'):
112                     p_vout->chroma.pf_convert = I422_IUYV;
113                     break;
114
115                 case VLC_FOURCC('c','y','u','v'):
116                     p_vout->chroma.pf_convert = I422_cyuv;
117                     break;
118
119 #if defined (MODULE_NAME_IS_i422_yuy2)
120                 case VLC_FOURCC('Y','2','1','1'):
121                     p_vout->chroma.pf_convert = I422_Y211;
122                     break;
123
124                 case VLC_FOURCC('Y','V','1','2'):
125                     p_vout->chroma.pf_convert = I422_YV12;
126                     break;
127 #endif
128
129                 default:
130                     return -1;
131             }
132             break;
133
134         default:
135             return -1;
136     }
137     return 0;
138 }
139
140 /* Following functions are local */
141
142 /*****************************************************************************
143  * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
144  *****************************************************************************/
145 static void I422_YUY2( vout_thread_t *p_vout, picture_t *p_source,
146                                               picture_t *p_dest )
147 {
148     uint8_t *p_line = p_dest->p->p_pixels;
149     uint8_t *p_y = p_source->Y_PIXELS;
150     uint8_t *p_u = p_source->U_PIXELS;
151     uint8_t *p_v = p_source->V_PIXELS;
152
153     int i_x, i_y;
154
155     const int i_source_margin = p_source->p[0].i_pitch
156                                  - p_source->p[0].i_visible_pitch;
157     const int i_source_margin_c = p_source->p[1].i_pitch
158                                  - p_source->p[1].i_visible_pitch;
159     const int i_dest_margin = p_dest->p->i_pitch
160                                - p_dest->p->i_visible_pitch;
161
162 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
163
164     if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
165         ((int)p_line|(int)p_y))) )
166     {
167         /* use faster SSE2 aligned fetch and store */
168         for( i_y = p_vout->render.i_height ; i_y-- ; )
169         {
170             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
171             {
172                 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
173             }
174             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
175             {
176                 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
177             }
178             p_y += i_source_margin;
179             p_u += i_source_margin_c;
180             p_v += i_source_margin_c;
181             p_line += i_dest_margin;
182         }
183     }
184     else {
185         /* use slower SSE2 unaligned fetch and store */
186         for( i_y = p_vout->render.i_height ; i_y-- ; )
187         {
188             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
189             {
190                 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
191             }
192             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
193             {
194                 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
195             }
196             p_y += i_source_margin;
197             p_u += i_source_margin_c;
198             p_v += i_source_margin_c;
199             p_line += i_dest_margin;
200         }
201     }
202     SSE2_END;
203
204 #else
205
206     for( i_y = p_vout->render.i_height ; i_y-- ; )
207     {
208         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
209         {
210 #if defined (MODULE_NAME_IS_i422_yuy2)
211             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
212             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
213             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
214             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
215 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
216             MMX_CALL( MMX_YUV422_YUYV );
217 #endif
218         }
219         for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
220         {
221             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
222         }
223         p_y += i_source_margin;
224         p_u += i_source_margin_c;
225         p_v += i_source_margin_c;
226         p_line += i_dest_margin;
227     }
228 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
229     MMX_END;
230 #endif
231
232 #endif
233 }
234
235 /*****************************************************************************
236  * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
237  *****************************************************************************/
238 static void I422_YVYU( vout_thread_t *p_vout, picture_t *p_source,
239                                               picture_t *p_dest )
240 {
241     uint8_t *p_line = p_dest->p->p_pixels;
242     uint8_t *p_y = p_source->Y_PIXELS;
243     uint8_t *p_u = p_source->U_PIXELS;
244     uint8_t *p_v = p_source->V_PIXELS;
245
246     int i_x, i_y;
247
248     const int i_source_margin = p_source->p[0].i_pitch
249                                  - p_source->p[0].i_visible_pitch;
250     const int i_source_margin_c = p_source->p[1].i_pitch
251                                  - p_source->p[1].i_visible_pitch;
252     const int i_dest_margin = p_dest->p->i_pitch
253                                - p_dest->p->i_visible_pitch;
254
255 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
256
257     if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
258         ((int)p_line|(int)p_y))) )
259     {
260         /* use faster SSE2 aligned fetch and store */
261         for( i_y = p_vout->render.i_height ; i_y-- ; )
262         {
263             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
264             {
265                 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
266             }
267             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
268             {
269                 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
270             }
271             p_y += i_source_margin;
272             p_u += i_source_margin_c;
273             p_v += i_source_margin_c;
274             p_line += i_dest_margin;
275         }
276     }
277     else {
278         /* use slower SSE2 unaligned fetch and store */
279         for( i_y = p_vout->render.i_height ; i_y-- ; )
280         {
281             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
282             {
283                 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
284             }
285             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
286             {
287                 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
288             }
289             p_y += i_source_margin;
290             p_u += i_source_margin_c;
291             p_v += i_source_margin_c;
292             p_line += i_dest_margin;
293         }
294     }
295     SSE2_END;
296
297 #else
298
299     for( i_y = p_vout->render.i_height ; i_y-- ; )
300     {
301         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
302         {
303 #if defined (MODULE_NAME_IS_i422_yuy2)
304             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
305             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
306             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
307             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
308 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
309             MMX_CALL( MMX_YUV422_YVYU );
310 #endif
311         }
312         for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
313         {
314             C_YUV422_YVYU( p_line, p_y, p_u, p_v );
315         }
316         p_y += i_source_margin;
317         p_u += i_source_margin_c;
318         p_v += i_source_margin_c;
319         p_line += i_dest_margin;
320     }
321 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
322     MMX_END;
323 #endif
324
325 #endif
326 }
327
328 /*****************************************************************************
329  * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
330  *****************************************************************************/
331 static void I422_UYVY( vout_thread_t *p_vout, picture_t *p_source,
332                                               picture_t *p_dest )
333 {
334     uint8_t *p_line = p_dest->p->p_pixels;
335     uint8_t *p_y = p_source->Y_PIXELS;
336     uint8_t *p_u = p_source->U_PIXELS;
337     uint8_t *p_v = p_source->V_PIXELS;
338
339     int i_x, i_y;
340
341     const int i_source_margin = p_source->p[0].i_pitch
342                                  - p_source->p[0].i_visible_pitch;
343     const int i_source_margin_c = p_source->p[1].i_pitch
344                                  - p_source->p[1].i_visible_pitch;
345     const int i_dest_margin = p_dest->p->i_pitch
346                                - p_dest->p->i_visible_pitch;
347
348 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
349
350     if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
351         ((int)p_line|(int)p_y))) )
352     {
353         /* use faster SSE2 aligned fetch and store */
354         for( i_y = p_vout->render.i_height ; i_y-- ; )
355         {
356             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
357             {
358                 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
359             }
360             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
361             {
362                 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
363             }
364             p_y += i_source_margin;
365             p_u += i_source_margin_c;
366             p_v += i_source_margin_c;
367             p_line += i_dest_margin;
368         }
369     }
370     else {
371         /* use slower SSE2 unaligned fetch and store */
372         for( i_y = p_vout->render.i_height ; i_y-- ; )
373         {
374             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
375             {
376                 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
377             }
378             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
379             {
380                 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
381             }
382             p_y += i_source_margin;
383             p_u += i_source_margin_c;
384             p_v += i_source_margin_c;
385             p_line += i_dest_margin;
386         }
387     }
388     SSE2_END;
389
390 #else
391
392     for( i_y = p_vout->render.i_height ; i_y-- ; )
393     {
394         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
395         {
396 #if defined (MODULE_NAME_IS_i422_yuy2)
397             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
398             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
399             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
400             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
401 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
402             MMX_CALL( MMX_YUV422_UYVY );
403 #endif
404         }
405         for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
406         {
407             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
408         }
409         p_y += i_source_margin;
410         p_u += i_source_margin_c;
411         p_v += i_source_margin_c;
412         p_line += i_dest_margin;
413     }
414 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
415     MMX_END;
416 #endif
417
418 #endif
419 }
420
421 /*****************************************************************************
422  * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
423  *****************************************************************************/
424 static void I422_IUYV( vout_thread_t *p_vout, picture_t *p_source,
425                                               picture_t *p_dest )
426 {
427     /* FIXME: TODO ! */
428     msg_Err( p_vout, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
429 }
430
431 /*****************************************************************************
432  * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
433  *****************************************************************************/
434 static void I422_cyuv( vout_thread_t *p_vout, picture_t *p_source,
435                                               picture_t *p_dest )
436 {
437     uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
438     uint8_t *p_y = p_source->Y_PIXELS;
439     uint8_t *p_u = p_source->U_PIXELS;
440     uint8_t *p_v = p_source->V_PIXELS;
441
442     int i_x, i_y;
443
444     const int i_source_margin = p_source->p[0].i_pitch
445                                  - p_source->p[0].i_visible_pitch;
446     const int i_source_margin_c = p_source->p[1].i_pitch
447                                  - p_source->p[1].i_visible_pitch;
448     const int i_dest_margin = p_dest->p->i_pitch
449                                - p_dest->p->i_visible_pitch;
450
451 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
452
453     if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
454         ((int)p_line|(int)p_y))) )
455     {
456         /* use faster SSE2 aligned fetch and store */
457         for( i_y = p_vout->render.i_height ; i_y-- ; )
458         {
459             p_line -= 2 * p_dest->p->i_pitch;
460
461             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
462             {
463                 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
464             }
465             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
466             {
467                 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
468             }
469             p_y += i_source_margin;
470             p_u += i_source_margin_c;
471             p_v += i_source_margin_c;
472             p_line += i_dest_margin;
473         }
474     }
475     else {
476         /* use slower SSE2 unaligned fetch and store */
477         for( i_y = p_vout->render.i_height ; i_y-- ; )
478         {
479             p_line -= 2 * p_dest->p->i_pitch;
480
481             for( i_x = p_vout->render.i_width / 16 ; i_x-- ; )
482             {
483                 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
484             }
485             for( i_x = ( p_vout->render.i_width % 16 ) / 2; i_x-- ; )
486             {
487                 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
488             }
489             p_y += i_source_margin;
490             p_u += i_source_margin_c;
491             p_v += i_source_margin_c;
492             p_line += i_dest_margin;
493         }
494     }
495     SSE2_END;
496
497 #else
498
499     for( i_y = p_vout->render.i_height ; i_y-- ; )
500     {
501         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
502         {
503             p_line -= 2 * p_dest->p->i_pitch;
504
505 #if defined (MODULE_NAME_IS_i422_yuy2)
506             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
507             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
508             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
509             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
510 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
511             MMX_CALL( MMX_YUV422_UYVY );
512 #endif
513         }
514         p_y += i_source_margin;
515         p_u += i_source_margin_c;
516         p_v += i_source_margin_c;
517         p_line += i_dest_margin;
518     }
519 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
520     MMX_END;
521 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
522     SSE2_END;
523 #endif
524
525 #endif
526 }
527
528 /*****************************************************************************
529  * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
530  *****************************************************************************/
531 #if defined (MODULE_NAME_IS_i422_yuy2)
532 static void I422_Y211( vout_thread_t *p_vout, picture_t *p_source,
533                                               picture_t *p_dest )
534 {
535     uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
536     uint8_t *p_y = p_source->Y_PIXELS;
537     uint8_t *p_u = p_source->U_PIXELS;
538     uint8_t *p_v = p_source->V_PIXELS;
539
540     int i_x, i_y;
541
542     for( i_y = p_vout->render.i_height ; i_y-- ; )
543     {
544         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
545         {
546             C_YUV422_Y211( p_line, p_y, p_u, p_v );
547             C_YUV422_Y211( p_line, p_y, p_u, p_v );
548         }
549     }
550 }
551 #endif
552
553
554 /*****************************************************************************
555  * I422_YV12: planar YUV 4:2:2 to planar YV12
556  *****************************************************************************/
557 #if defined (MODULE_NAME_IS_i422_yuy2)
558 static void I422_YV12( vout_thread_t *p_vout, picture_t *p_source,
559                                               picture_t *p_dest )
560 {
561     uint16_t i_dpy = p_dest->p[Y_PLANE].i_pitch;
562     uint16_t i_spy = p_source->p[Y_PLANE].i_pitch;
563     uint16_t i_dpuv = p_dest->p[U_PLANE].i_pitch;
564     uint16_t i_spuv = p_source->p[U_PLANE].i_pitch;
565     uint16_t i_width = p_vout->render.i_width;
566     uint16_t i_y = p_vout->render.i_height;
567     uint8_t *p_dy = p_dest->Y_PIXELS + (i_y-1)*i_dpy;
568     uint8_t *p_y = p_source->Y_PIXELS + (i_y-1)*i_spy;
569     uint8_t *p_du = p_dest->U_PIXELS + (i_y/2-1)*i_dpuv;
570     uint8_t *p_u = p_source->U_PIXELS + (i_y-1)*i_spuv;
571     uint8_t *p_dv = p_dest->V_PIXELS + (i_y/2-1)*i_dpuv;
572     uint8_t *p_v = p_source->V_PIXELS + (i_y-1)*i_spuv;
573     i_y /= 2;
574
575     for ( ; i_y--; )
576     {
577         memcpy(p_dy, p_y, i_width); p_dy -= i_dpy; p_y -= i_spy;
578         memcpy(p_dy, p_y, i_width); p_dy -= i_dpy; p_y -= i_spy;
579         memcpy(p_du, p_u, i_width/2); p_du -= i_dpuv; p_u -= 2*i_spuv;
580         memcpy(p_dv, p_v, i_width/2); p_dv -= i_dpuv; p_v -= 2*i_spuv;
581     }
582
583 }
584 #endif