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