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