Remove most nested headers from <vlc_filter.h>
[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 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_picture.h>
37 #include <vlc_cpu.h>
38
39 #include "i422_yuy2.h"
40
41 #define SRC_FOURCC  "I422"
42 #if defined (MODULE_NAME_IS_i422_yuy2)
43 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,Y211"
44 #else
45 #    define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV"
46 #endif
47
48 /*****************************************************************************
49  * Local and extern prototypes.
50  *****************************************************************************/
51 static int  Activate ( vlc_object_t * );
52
53 static void I422_YUY2               ( filter_t *, picture_t *, picture_t * );
54 static void I422_YVYU               ( filter_t *, picture_t *, picture_t * );
55 static void I422_UYVY               ( filter_t *, picture_t *, picture_t * );
56 static void I422_IUYV               ( 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 #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 filter", 80 )
73 # define vlc_CPU_capable() (true)
74 # define VLC_TARGET
75 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
76     set_description( N_("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) )
77     set_capability( "video filter", 100 )
78 # define vlc_CPU_capable() vlc_CPU_MMX()
79 # define VLC_TARGET VLC_MMX
80 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
81     set_description( N_("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) )
82     set_capability( "video filter", 120 )
83 # define vlc_CPU_capable() vlc_CPU_SSE2()
84 # define VLC_TARGET VLC_SSE
85 #endif
86     set_callbacks( Activate, NULL )
87 vlc_module_end ()
88
89 /*****************************************************************************
90  * Activate: allocate a chroma function
91  *****************************************************************************
92  * This function allocates and initializes a chroma function
93  *****************************************************************************/
94 static int Activate( vlc_object_t *p_this )
95 {
96     filter_t *p_filter = (filter_t *)p_this;
97
98     if( !vlc_CPU_capable() )
99         return VLC_EGENERIC;
100     if( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) & 1
101      || (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) & 1 )
102     {
103         return -1;
104     }
105
106     if( p_filter->fmt_in.video.orientation != p_filter->fmt_out.video.orientation )
107     {
108         return VLC_EGENERIC;
109     }
110
111     switch( p_filter->fmt_in.video.i_chroma )
112     {
113         case VLC_CODEC_I422:
114             switch( p_filter->fmt_out.video.i_chroma )
115             {
116                 case VLC_CODEC_YUYV:
117                     p_filter->pf_video_filter = I422_YUY2_Filter;
118                     break;
119
120                 case VLC_CODEC_YVYU:
121                     p_filter->pf_video_filter = I422_YVYU_Filter;
122                     break;
123
124                 case VLC_CODEC_UYVY:
125                     p_filter->pf_video_filter = I422_UYVY_Filter;
126                     break;
127
128                 case VLC_FOURCC('I','U','Y','V'):
129                     p_filter->pf_video_filter = I422_IUYV_Filter;
130                     break;
131
132 #if defined (MODULE_NAME_IS_i422_yuy2)
133                 case VLC_CODEC_Y211:
134                     p_filter->pf_video_filter = I422_Y211_Filter;
135                     break;
136 #endif
137
138                 default:
139                     return -1;
140             }
141             break;
142
143         default:
144             return -1;
145     }
146     return 0;
147 }
148
149 /* Following functions are local */
150
151 VIDEO_FILTER_WRAPPER( I422_YUY2 )
152 VIDEO_FILTER_WRAPPER( I422_YVYU )
153 VIDEO_FILTER_WRAPPER( I422_UYVY )
154 VIDEO_FILTER_WRAPPER( I422_IUYV )
155 #if defined (MODULE_NAME_IS_i422_yuy2)
156 VIDEO_FILTER_WRAPPER( I422_Y211 )
157 #endif
158
159 /*****************************************************************************
160  * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
161  *****************************************************************************/
162 VLC_TARGET
163 static void I422_YUY2( filter_t *p_filter, picture_t *p_source,
164                                            picture_t *p_dest )
165 {
166     uint8_t *p_line = p_dest->p->p_pixels;
167     uint8_t *p_y = p_source->Y_PIXELS;
168     uint8_t *p_u = p_source->U_PIXELS;
169     uint8_t *p_v = p_source->V_PIXELS;
170
171     int i_x, i_y;
172
173     const int i_source_margin = p_source->p[0].i_pitch
174                                  - p_source->p[0].i_visible_pitch
175                                  - p_filter->fmt_in.video.i_x_offset;
176     const int i_source_margin_c = p_source->p[1].i_pitch
177                                  - p_source->p[1].i_visible_pitch
178                                  - ( p_filter->fmt_in.video.i_x_offset );
179     const int i_dest_margin = p_dest->p->i_pitch
180                                - p_dest->p->i_visible_pitch
181                                - ( p_filter->fmt_out.video.i_x_offset * 2 );
182
183 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
184
185     if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
186         ((intptr_t)p_line|(intptr_t)p_y))) )
187     {
188         /* use faster SSE2 aligned fetch and store */
189         for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
190         {
191             for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
192             {
193                 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
194             }
195             for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
196             {
197                 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
198             }
199             p_y += i_source_margin;
200             p_u += i_source_margin_c;
201             p_v += i_source_margin_c;
202             p_line += i_dest_margin;
203         }
204     }
205     else {
206         /* use slower SSE2 unaligned fetch and store */
207         for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
208         {
209             for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
210             {
211                 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
212             }
213             for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
214             {
215                 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
216             }
217             p_y += i_source_margin;
218             p_u += i_source_margin_c;
219             p_v += i_source_margin_c;
220             p_line += i_dest_margin;
221         }
222     }
223     SSE2_END;
224
225 #else
226
227     for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
228     {
229         for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8 ; i_x-- ; )
230         {
231 #if defined (MODULE_NAME_IS_i422_yuy2)
232             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
233             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
234             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
235             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
236 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
237             MMX_CALL( MMX_YUV422_YUYV );
238 #endif
239         }
240         for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 8 ) / 2; i_x-- ; )
241         {
242             C_YUV422_YUYV( p_line, p_y, p_u, p_v );
243         }
244         p_y += i_source_margin;
245         p_u += i_source_margin_c;
246         p_v += i_source_margin_c;
247         p_line += i_dest_margin;
248     }
249 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
250     MMX_END;
251 #endif
252
253 #endif
254 }
255
256 /*****************************************************************************
257  * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
258  *****************************************************************************/
259 VLC_TARGET
260 static void I422_YVYU( filter_t *p_filter, picture_t *p_source,
261                                            picture_t *p_dest )
262 {
263     uint8_t *p_line = p_dest->p->p_pixels;
264     uint8_t *p_y = p_source->Y_PIXELS;
265     uint8_t *p_u = p_source->U_PIXELS;
266     uint8_t *p_v = p_source->V_PIXELS;
267
268     int i_x, i_y;
269
270     const int i_source_margin = p_source->p[0].i_pitch
271                                  - p_source->p[0].i_visible_pitch
272                                  - p_filter->fmt_in.video.i_x_offset;
273     const int i_source_margin_c = p_source->p[1].i_pitch
274                                  - p_source->p[1].i_visible_pitch
275                                  - ( p_filter->fmt_in.video.i_x_offset );
276     const int i_dest_margin = p_dest->p->i_pitch
277                                - p_dest->p->i_visible_pitch
278                                - ( p_filter->fmt_out.video.i_x_offset * 2 );
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_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
287         {
288             for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
289             {
290                 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
291             }
292             for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_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_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
305         {
306             for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
307             {
308                 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
309             }
310             for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_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_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
325     {
326         for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_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_x_offset + p_filter->fmt_in.video.i_visible_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                                  - p_filter->fmt_in.video.i_x_offset;
370     const int i_source_margin_c = p_source->p[1].i_pitch
371                                  - p_source->p[1].i_visible_pitch
372                                  - ( p_filter->fmt_in.video.i_x_offset );
373     const int i_dest_margin = p_dest->p->i_pitch
374                                - p_dest->p->i_visible_pitch
375                                - ( p_filter->fmt_out.video.i_x_offset * 2 );
376
377 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
378
379     if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
380         ((intptr_t)p_line|(intptr_t)p_y))) )
381     {
382         /* use faster SSE2 aligned fetch and store */
383         for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
384         {
385             for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
386             {
387                 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
388             }
389             for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_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     else {
400         /* use slower SSE2 unaligned fetch and store */
401         for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
402         {
403             for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 16 ; i_x-- ; )
404             {
405                 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
406             }
407             for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 16 ) / 2; i_x-- ; )
408             {
409                 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
410             }
411             p_y += i_source_margin;
412             p_u += i_source_margin_c;
413             p_v += i_source_margin_c;
414             p_line += i_dest_margin;
415         }
416     }
417     SSE2_END;
418
419 #else
420
421     for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
422     {
423         for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8 ; i_x-- ; )
424         {
425 #if defined (MODULE_NAME_IS_i422_yuy2)
426             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
427             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
428             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
429             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
430 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
431             MMX_CALL( MMX_YUV422_UYVY );
432 #endif
433         }
434         for( i_x = ( (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) % 8 ) / 2; i_x-- ; )
435         {
436             C_YUV422_UYVY( p_line, p_y, p_u, p_v );
437         }
438         p_y += i_source_margin;
439         p_u += i_source_margin_c;
440         p_v += i_source_margin_c;
441         p_line += i_dest_margin;
442     }
443 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
444     MMX_END;
445 #endif
446
447 #endif
448 }
449
450 /*****************************************************************************
451  * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
452  *****************************************************************************/
453 static void I422_IUYV( filter_t *p_filter, picture_t *p_source,
454                                            picture_t *p_dest )
455 {
456     VLC_UNUSED(p_source); VLC_UNUSED(p_dest);
457     /* FIXME: TODO ! */
458     msg_Err( p_filter, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
459 }
460
461 /*****************************************************************************
462  * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
463  *****************************************************************************/
464 #if defined (MODULE_NAME_IS_i422_yuy2)
465 static void I422_Y211( filter_t *p_filter, picture_t *p_source,
466                                            picture_t *p_dest )
467 {
468     uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
469     uint8_t *p_y = p_source->Y_PIXELS;
470     uint8_t *p_u = p_source->U_PIXELS;
471     uint8_t *p_v = p_source->V_PIXELS;
472
473     int i_x, i_y;
474
475     for( i_y = (p_filter->fmt_in.video.i_y_offset + p_filter->fmt_in.video.i_visible_height) ; i_y-- ; )
476     {
477         for( i_x = (p_filter->fmt_in.video.i_x_offset + p_filter->fmt_in.video.i_visible_width) / 8 ; i_x-- ; )
478         {
479             C_YUV422_Y211( p_line, p_y, p_u, p_v );
480             C_YUV422_Y211( p_line, p_y, p_u, p_v );
481         }
482     }
483 }
484 #endif