]> git.sesse.net Git - vlc/blob - modules/video_chroma/i420_yuy2.c
A bit of headers cleanup
[vlc] / modules / video_chroma / i420_yuy2.c
1 /*****************************************************************************
2  * i420_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  *
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 #include <string.h>                                            /* strerror() */
28 #include <stdlib.h>                                      /* malloc(), free() */
29
30 #include <vlc/vlc.h>
31 #include <vlc_vout.h>
32
33 #if defined (MODULE_NAME_IS_i420_yuy2_altivec) && defined(HAVE_ALTIVEC_H)
34 #   include <altivec.h>
35 #endif
36
37 #include "i420_yuy2.h"
38
39 #define SRC_FOURCC  "I420,IYUV,YV12"
40
41 #if defined (MODULE_NAME_IS_i420_yuy2)
42 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
43 #elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
44 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
45 #elif defined (MODULE_NAME_IS_i420_yuy2_altivec)
46 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422"
47 #endif
48
49 /*****************************************************************************
50  * Local and extern prototypes.
51  *****************************************************************************/
52 static int  Activate ( vlc_object_t * );
53
54 static void I420_YUY2           ( vout_thread_t *, picture_t *, picture_t * );
55 static void I420_YVYU           ( vout_thread_t *, picture_t *, picture_t * );
56 static void I420_UYVY           ( vout_thread_t *, picture_t *, picture_t * );
57 #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
58 static void I420_IUYV           ( vout_thread_t *, picture_t *, picture_t * );
59 static void I420_cyuv           ( vout_thread_t *, picture_t *, picture_t * );
60 #endif
61 #if defined (MODULE_NAME_IS_i420_yuy2)
62 static void I420_Y211           ( vout_thread_t *, picture_t *, picture_t * );
63 #endif
64
65 #ifdef MODULE_NAME_IS_i420_yuy2_mmx
66 static uint64_t i_00ffw;
67 static uint64_t i_80w;
68 #endif
69
70 /*****************************************************************************
71  * Module descriptor.
72  *****************************************************************************/
73 vlc_module_begin();
74 #if defined (MODULE_NAME_IS_i420_yuy2)
75     set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
76     set_capability( "chroma", 80 );
77 #elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
78     set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
79     set_capability( "chroma", 100 );
80     add_requirement( MMX );
81     /* Initialize MMX-specific constants */
82     i_00ffw = 0x00ff00ff00ff00ffULL;
83     i_80w   = 0x0000000080808080ULL;
84 #elif defined (MODULE_NAME_IS_i420_yuy2_altivec)
85     set_description(
86             _("AltiVec conversions from " SRC_FOURCC " to " DEST_FOURCC) );
87     set_capability( "chroma", 100 );
88     add_requirement( ALTIVEC );
89 #endif
90     set_callbacks( Activate, NULL );
91 vlc_module_end();
92
93 /*****************************************************************************
94  * Activate: allocate a chroma function
95  *****************************************************************************
96  * This function allocates and initializes a chroma function
97  *****************************************************************************/
98 static int Activate( vlc_object_t *p_this )
99 {
100     vout_thread_t *p_vout = (vout_thread_t *)p_this;
101
102     if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
103     {
104         return -1;
105     }
106
107     switch( p_vout->render.i_chroma )
108     {
109         case VLC_FOURCC('Y','V','1','2'):
110         case VLC_FOURCC('I','4','2','0'):
111         case VLC_FOURCC('I','Y','U','V'):
112             switch( p_vout->output.i_chroma )
113             {
114                 case VLC_FOURCC('Y','U','Y','2'):
115                 case VLC_FOURCC('Y','U','N','V'):
116                     p_vout->chroma.pf_convert = I420_YUY2;
117                     break;
118
119                 case VLC_FOURCC('Y','V','Y','U'):
120                     p_vout->chroma.pf_convert = I420_YVYU;
121                     break;
122
123                 case VLC_FOURCC('U','Y','V','Y'):
124                 case VLC_FOURCC('U','Y','N','V'):
125                 case VLC_FOURCC('Y','4','2','2'):
126                     p_vout->chroma.pf_convert = I420_UYVY;
127                     break;
128
129 #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
130                 case VLC_FOURCC('I','U','Y','V'):
131                     p_vout->chroma.pf_convert = I420_IUYV;
132                     break;
133
134                 case VLC_FOURCC('c','y','u','v'):
135                     p_vout->chroma.pf_convert = I420_cyuv;
136                     break;
137 #endif
138
139 #if defined (MODULE_NAME_IS_i420_yuy2)
140                 case VLC_FOURCC('Y','2','1','1'):
141                     p_vout->chroma.pf_convert = I420_Y211;
142                     break;
143 #endif
144
145                 default:
146                     return -1;
147             }
148             break;
149
150         default:
151             return -1;
152     }
153
154     return 0;
155 }
156
157 /* Following functions are local */
158
159 /*****************************************************************************
160  * I420_YUY2: planar YUV 4:2:0 to packed YUYV 4:2:2
161  *****************************************************************************/
162 static void I420_YUY2( vout_thread_t *p_vout, picture_t *p_source,
163                                               picture_t *p_dest )
164 {
165     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
166     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
167     uint8_t *p_u = p_source->U_PIXELS;
168     uint8_t *p_v = p_source->V_PIXELS;
169
170     int i_x, i_y;
171
172 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
173 #define VEC_NEXT_LINES( ) \
174     p_line1  = p_line2; \
175     p_line2 += p_dest->p->i_pitch; \
176     p_y1     = p_y2; \
177     p_y2    += p_source->p[Y_PLANE].i_pitch;
178
179 #define VEC_LOAD_UV( ) \
180     u_vec = vec_ld( 0, p_u ); p_u += 16; \
181     v_vec = vec_ld( 0, p_v ); p_v += 16;
182
183 #define VEC_MERGE( a ) \
184     uv_vec = a( u_vec, v_vec ); \
185     y_vec = vec_ld( 0, p_y1 ); p_y1 += 16; \
186     vec_st( vec_mergeh( y_vec, uv_vec ), 0, p_line1 ); p_line1 += 16; \
187     vec_st( vec_mergel( y_vec, uv_vec ), 0, p_line1 ); p_line1 += 16; \
188     y_vec = vec_ld( 0, p_y2 ); p_y2 += 16; \
189     vec_st( vec_mergeh( y_vec, uv_vec ), 0, p_line2 ); p_line2 += 16; \
190     vec_st( vec_mergel( y_vec, uv_vec ), 0, p_line2 ); p_line2 += 16;
191
192     vector unsigned char u_vec;
193     vector unsigned char v_vec;
194     vector unsigned char uv_vec;
195     vector unsigned char y_vec;
196
197     if( !( ( p_vout->render.i_width % 32 ) |
198            ( p_vout->render.i_height % 2 ) ) )
199     {
200         /* Width is a multiple of 32, we take 2 lines at a time */
201         for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
202         {
203             VEC_NEXT_LINES( );
204             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
205             {
206                 VEC_LOAD_UV( );
207                 VEC_MERGE( vec_mergeh );
208                 VEC_MERGE( vec_mergel );
209             }
210         }
211     }
212     else if( !( ( p_vout->render.i_width % 16 ) |
213                 ( p_vout->render.i_height % 4 ) ) )
214     {
215         /* Width is only a multiple of 16, we take 4 lines at a time */
216         for( i_y = p_vout->render.i_height / 4 ; i_y-- ; )
217         {
218             /* Line 1 and 2, pixels 0 to ( width - 16 ) */
219             VEC_NEXT_LINES( );
220             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
221             {
222                 VEC_LOAD_UV( );
223                 VEC_MERGE( vec_mergeh );
224                 VEC_MERGE( vec_mergel );
225             }
226
227             /* Line 1 and 2, pixels ( width - 16 ) to ( width ) */
228             VEC_LOAD_UV( );
229             VEC_MERGE( vec_mergeh );
230
231             /* Line 3 and 4, pixels 0 to 16 */
232             VEC_NEXT_LINES( );
233             VEC_MERGE( vec_mergel );
234
235             /* Line 3 and 4, pixels 16 to ( width ) */
236             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
237             {
238                 VEC_LOAD_UV( );
239                 VEC_MERGE( vec_mergeh );
240                 VEC_MERGE( vec_mergel );
241             }
242         }
243     }
244     else
245     {
246         /* Crap, use the C version */
247 #undef VEC_NEXT_LINES
248 #undef VEC_LOAD_UV
249 #undef VEC_MERGE
250 #endif
251
252     const int i_source_margin = p_source->p[0].i_pitch
253                                  - p_source->p[0].i_visible_pitch;
254     const int i_source_margin_c = p_source->p[1].i_pitch
255                                  - p_source->p[1].i_visible_pitch;
256     const int i_dest_margin = p_dest->p->i_pitch
257                                - p_dest->p->i_visible_pitch;
258
259     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
260     {
261         p_line1 = p_line2;
262         p_line2 += p_dest->p->i_pitch;
263
264         p_y1 = p_y2;
265         p_y2 += p_source->p[Y_PLANE].i_pitch;
266
267 #if !defined (MODULE_NAME_IS_i420_yuy2_mmx)
268         for( i_x = p_vout->render.i_width / 2 ; i_x-- ; )
269         {
270             C_YUV420_YUYV( );
271         }
272 #else
273         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
274         {
275             MMX_CALL( MMX_YUV420_YUYV );
276         }
277         for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
278         {
279             C_YUV420_YUYV( );
280         }
281 #endif
282
283         p_y1 += i_source_margin;
284         p_y2 += i_source_margin;
285         p_u += i_source_margin_c;
286         p_v += i_source_margin_c;
287         p_line1 += i_dest_margin;
288         p_line2 += i_dest_margin;
289     }
290
291 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
292     }
293 #endif
294 }
295
296 /*****************************************************************************
297  * I420_YVYU: planar YUV 4:2:0 to packed YVYU 4:2:2
298  *****************************************************************************/
299 static void I420_YVYU( vout_thread_t *p_vout, picture_t *p_source,
300                                               picture_t *p_dest )
301 {
302     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
303     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
304     uint8_t *p_u = p_source->U_PIXELS;
305     uint8_t *p_v = p_source->V_PIXELS;
306
307     int i_x, i_y;
308
309 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
310 #define VEC_NEXT_LINES( ) \
311     p_line1  = p_line2; \
312     p_line2 += p_dest->p->i_pitch; \
313     p_y1     = p_y2; \
314     p_y2    += p_source->p[Y_PLANE].i_pitch;
315
316 #define VEC_LOAD_UV( ) \
317     u_vec = vec_ld( 0, p_u ); p_u += 16; \
318     v_vec = vec_ld( 0, p_v ); p_v += 16;
319
320 #define VEC_MERGE( a ) \
321     vu_vec = a( v_vec, u_vec ); \
322     y_vec = vec_ld( 0, p_y1 ); p_y1 += 16; \
323     vec_st( vec_mergeh( y_vec, vu_vec ), 0, p_line1 ); p_line1 += 16; \
324     vec_st( vec_mergel( y_vec, vu_vec ), 0, p_line1 ); p_line1 += 16; \
325     y_vec = vec_ld( 0, p_y2 ); p_y2 += 16; \
326     vec_st( vec_mergeh( y_vec, vu_vec ), 0, p_line2 ); p_line2 += 16; \
327     vec_st( vec_mergel( y_vec, vu_vec ), 0, p_line2 ); p_line2 += 16;
328
329     vector unsigned char u_vec;
330     vector unsigned char v_vec;
331     vector unsigned char vu_vec;
332     vector unsigned char y_vec;
333
334     if( !( ( p_vout->render.i_width % 32 ) |
335            ( p_vout->render.i_height % 2 ) ) )
336     {
337         /* Width is a multiple of 32, we take 2 lines at a time */
338         for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
339         {
340             VEC_NEXT_LINES( );
341             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
342             {
343                 VEC_LOAD_UV( );
344                 VEC_MERGE( vec_mergeh );
345                 VEC_MERGE( vec_mergel );
346             }
347         }
348     }
349     else if( !( ( p_vout->render.i_width % 16 ) |
350                 ( p_vout->render.i_height % 4 ) ) )
351     {
352         /* Width is only a multiple of 16, we take 4 lines at a time */
353         for( i_y = p_vout->render.i_height / 4 ; i_y-- ; )
354         {
355             /* Line 1 and 2, pixels 0 to ( width - 16 ) */
356             VEC_NEXT_LINES( );
357             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
358             {
359                 VEC_LOAD_UV( );
360                 VEC_MERGE( vec_mergeh );
361                 VEC_MERGE( vec_mergel );
362             }
363
364             /* Line 1 and 2, pixels ( width - 16 ) to ( width ) */
365             VEC_LOAD_UV( );
366             VEC_MERGE( vec_mergeh );
367
368             /* Line 3 and 4, pixels 0 to 16 */
369             VEC_NEXT_LINES( );
370             VEC_MERGE( vec_mergel );
371
372             /* Line 3 and 4, pixels 16 to ( width ) */
373             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
374             {
375                 VEC_LOAD_UV( );
376                 VEC_MERGE( vec_mergeh );
377                 VEC_MERGE( vec_mergel );
378             }
379         }
380     }
381     else
382     {
383         /* Crap, use the C version */
384 #undef VEC_NEXT_LINES
385 #undef VEC_LOAD_UV
386 #undef VEC_MERGE
387 #endif
388
389     const int i_source_margin = p_source->p[0].i_pitch
390                                  - p_source->p[0].i_visible_pitch;
391     const int i_source_margin_c = p_source->p[1].i_pitch
392                                  - p_source->p[1].i_visible_pitch;
393     const int i_dest_margin = p_dest->p->i_pitch
394                                - p_dest->p->i_visible_pitch;
395
396     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
397     {
398         p_line1 = p_line2;
399         p_line2 += p_dest->p->i_pitch;
400
401         p_y1 = p_y2;
402         p_y2 += p_source->p[Y_PLANE].i_pitch;
403
404         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
405         {
406 #if !defined (MODULE_NAME_IS_i420_yuy2_mmx)
407             C_YUV420_YVYU( );
408             C_YUV420_YVYU( );
409             C_YUV420_YVYU( );
410             C_YUV420_YVYU( );
411 #else
412             MMX_CALL( MMX_YUV420_YVYU );
413 #endif
414         }
415
416         p_y1 += i_source_margin;
417         p_y2 += i_source_margin;
418         p_u += i_source_margin_c;
419         p_v += i_source_margin_c;
420         p_line1 += i_dest_margin;
421         p_line2 += i_dest_margin;
422     }
423 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
424     }
425 #endif
426 }
427
428 /*****************************************************************************
429  * I420_UYVY: planar YUV 4:2:0 to packed UYVY 4:2:2
430  *****************************************************************************/
431 static void I420_UYVY( vout_thread_t *p_vout, picture_t *p_source,
432                                               picture_t *p_dest )
433 {
434     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
435     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
436     uint8_t *p_u = p_source->U_PIXELS;
437     uint8_t *p_v = p_source->V_PIXELS;
438
439     int i_x, i_y;
440
441 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
442 #define VEC_NEXT_LINES( ) \
443     p_line1  = p_line2; \
444     p_line2 += p_dest->p->i_pitch; \
445     p_y1     = p_y2; \
446     p_y2    += p_source->p[Y_PLANE].i_pitch;
447
448 #define VEC_LOAD_UV( ) \
449     u_vec = vec_ld( 0, p_u ); p_u += 16; \
450     v_vec = vec_ld( 0, p_v ); p_v += 16;
451
452 #define VEC_MERGE( a ) \
453     uv_vec = a( u_vec, v_vec ); \
454     y_vec = vec_ld( 0, p_y1 ); p_y1 += 16; \
455     vec_st( vec_mergeh( uv_vec, y_vec ), 0, p_line1 ); p_line1 += 16; \
456     vec_st( vec_mergel( uv_vec, y_vec ), 0, p_line1 ); p_line1 += 16; \
457     y_vec = vec_ld( 0, p_y2 ); p_y2 += 16; \
458     vec_st( vec_mergeh( uv_vec, y_vec ), 0, p_line2 ); p_line2 += 16; \
459     vec_st( vec_mergel( uv_vec, y_vec ), 0, p_line2 ); p_line2 += 16;
460
461     vector unsigned char u_vec;
462     vector unsigned char v_vec;
463     vector unsigned char uv_vec;
464     vector unsigned char y_vec;
465
466     if( !( ( p_vout->render.i_width % 32 ) |
467            ( p_vout->render.i_height % 2 ) ) )
468     {
469         /* Width is a multiple of 32, we take 2 lines at a time */
470         for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
471         {
472             VEC_NEXT_LINES( );
473             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
474             {
475                 VEC_LOAD_UV( );
476                 VEC_MERGE( vec_mergeh );
477                 VEC_MERGE( vec_mergel );
478             }
479         }
480     }
481     else if( !( ( p_vout->render.i_width % 16 ) |
482                 ( p_vout->render.i_height % 4 ) ) )
483     {
484         /* Width is only a multiple of 16, we take 4 lines at a time */
485         for( i_y = p_vout->render.i_height / 4 ; i_y-- ; )
486         {
487             /* Line 1 and 2, pixels 0 to ( width - 16 ) */
488             VEC_NEXT_LINES( );
489             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
490             {
491                 VEC_LOAD_UV( );
492                 VEC_MERGE( vec_mergeh );
493                 VEC_MERGE( vec_mergel );
494             }
495
496             /* Line 1 and 2, pixels ( width - 16 ) to ( width ) */
497             VEC_LOAD_UV( );
498             VEC_MERGE( vec_mergeh );
499
500             /* Line 3 and 4, pixels 0 to 16 */
501             VEC_NEXT_LINES( );
502             VEC_MERGE( vec_mergel );
503
504             /* Line 3 and 4, pixels 16 to ( width ) */
505             for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
506             {
507                 VEC_LOAD_UV( );
508                 VEC_MERGE( vec_mergeh );
509                 VEC_MERGE( vec_mergel );
510             }
511         }
512     }
513     else
514     {
515         /* Crap, use the C version */
516 #undef VEC_NEXT_LINES
517 #undef VEC_LOAD_UV
518 #undef VEC_MERGE
519 #endif
520
521     const int i_source_margin = p_source->p[0].i_pitch
522                                  - p_source->p[0].i_visible_pitch;
523     const int i_source_margin_c = p_source->p[1].i_pitch
524                                  - p_source->p[1].i_visible_pitch;
525     const int i_dest_margin = p_dest->p->i_pitch
526                                - p_dest->p->i_visible_pitch;
527
528     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
529     {
530         p_line1 = p_line2;
531         p_line2 += p_dest->p->i_pitch;
532
533         p_y1 = p_y2;
534         p_y2 += p_source->p[Y_PLANE].i_pitch;
535
536         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
537         {
538 #if !defined (MODULE_NAME_IS_i420_yuy2_mmx)
539             C_YUV420_UYVY( );
540             C_YUV420_UYVY( );
541             C_YUV420_UYVY( );
542             C_YUV420_UYVY( );
543 #else
544             MMX_CALL( MMX_YUV420_UYVY );
545 #endif
546         }
547         for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x--; )
548         {
549             C_YUV420_UYVY( );
550         }
551
552         p_y1 += i_source_margin;
553         p_y2 += i_source_margin;
554         p_u += i_source_margin_c;
555         p_v += i_source_margin_c;
556         p_line1 += i_dest_margin;
557         p_line2 += i_dest_margin;
558     }
559
560 #if defined (MODULE_NAME_IS_i420_yuy2_mmx)
561     __asm__ __volatile__("emms" :: );
562 #endif
563
564 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
565     }
566 #endif
567 }
568
569 #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
570 /*****************************************************************************
571  * I420_IUYV: planar YUV 4:2:0 to interleaved packed UYVY 4:2:2
572  *****************************************************************************/
573 static void I420_IUYV( vout_thread_t *p_vout, picture_t *p_source,
574                                               picture_t *p_dest )
575 {
576     /* FIXME: TODO ! */
577     msg_Err( p_vout, "I420_IUYV unimplemented, please harass <sam@zoy.org>" );
578 }
579
580 /*****************************************************************************
581  * I420_cyuv: planar YUV 4:2:0 to upside-down packed UYVY 4:2:2
582  *****************************************************************************/
583 static void I420_cyuv( vout_thread_t *p_vout, picture_t *p_source,
584                                               picture_t *p_dest )
585 {
586     uint8_t *p_line1 = p_dest->p->p_pixels +
587                        p_dest->p->i_visible_lines * p_dest->p->i_pitch
588                        + p_dest->p->i_pitch;
589     uint8_t *p_line2 = p_dest->p->p_pixels +
590                        p_dest->p->i_visible_lines * p_dest->p->i_pitch;
591     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
592     uint8_t *p_u = p_source->U_PIXELS;
593     uint8_t *p_v = p_source->V_PIXELS;
594
595     int i_x, i_y;
596
597     const int i_source_margin = p_source->p[0].i_pitch
598                                  - p_source->p[0].i_visible_pitch;
599     const int i_source_margin_c = p_source->p[1].i_pitch
600                                  - p_source->p[1].i_visible_pitch;
601     const int i_dest_margin = p_dest->p->i_pitch
602                                - p_dest->p->i_visible_pitch;
603
604     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
605     {
606         p_line1 -= 3 * p_dest->p->i_pitch;
607         p_line2 -= 3 * p_dest->p->i_pitch;
608
609         p_y1 = p_y2;
610         p_y2 += p_source->p[Y_PLANE].i_pitch;
611
612         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
613         {
614 #if defined (MODULE_NAME_IS_i420_yuy2)
615             C_YUV420_UYVY( );
616             C_YUV420_UYVY( );
617             C_YUV420_UYVY( );
618             C_YUV420_UYVY( );
619 #else
620             MMX_CALL( MMX_YUV420_UYVY );
621 #endif
622         }
623
624         p_y1 += i_source_margin;
625         p_y2 += i_source_margin;
626         p_u += i_source_margin_c;
627         p_v += i_source_margin_c;
628         p_line1 += i_dest_margin;
629         p_line2 += i_dest_margin;
630     }
631 }
632 #endif // !defined (MODULE_NAME_IS_i420_yuy2_altivec)
633
634 /*****************************************************************************
635  * I420_Y211: planar YUV 4:2:0 to packed YUYV 2:1:1
636  *****************************************************************************/
637 #if defined (MODULE_NAME_IS_i420_yuy2)
638 static void I420_Y211( vout_thread_t *p_vout, picture_t *p_source,
639                                               picture_t *p_dest )
640 {
641     uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
642     uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
643     uint8_t *p_u = p_source->U_PIXELS;
644     uint8_t *p_v = p_source->V_PIXELS;
645
646     int i_x, i_y;
647
648     const int i_source_margin = p_source->p[0].i_pitch
649                                  - p_source->p[0].i_visible_pitch;
650     const int i_source_margin_c = p_source->p[1].i_pitch
651                                  - p_source->p[1].i_visible_pitch;
652     const int i_dest_margin = p_dest->p->i_pitch
653                                - p_dest->p->i_visible_pitch;
654
655     for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
656     {
657         p_line1 = p_line2;
658         p_line2 += p_dest->p->i_pitch;
659
660         p_y1 = p_y2;
661         p_y2 += p_source->p[Y_PLANE].i_pitch;
662
663         for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
664         {
665             C_YUV420_Y211( );
666             C_YUV420_Y211( );
667         }
668
669         p_y1 += i_source_margin;
670         p_y2 += i_source_margin;
671         p_u += i_source_margin_c;
672         p_v += i_source_margin_c;
673         p_line1 += i_dest_margin;
674         p_line2 += i_dest_margin;
675     }
676 }
677 #endif
678