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