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
7 * Authors: Samuel Hocevar <sam@zoy.org>
8 * Damien Fouilleul <damienf@videolan.org>
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_filter.h>
38 #include "i422_yuy2.h"
40 #define SRC_FOURCC "I422"
41 #if defined (MODULE_NAME_IS_i422_yuy2)
42 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,Y211"
44 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV"
47 /*****************************************************************************
48 * Local and extern prototypes.
49 *****************************************************************************/
50 static int Activate ( vlc_object_t * );
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 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 #if defined (MODULE_NAME_IS_i422_yuy2)
61 static void I422_Y211 ( filter_t *, picture_t *, picture_t * );
62 static picture_t *I422_Y211_Filter ( filter_t *, picture_t * );
65 /*****************************************************************************
67 *****************************************************************************/
69 #if defined (MODULE_NAME_IS_i422_yuy2)
70 set_description( N_("Conversions from " SRC_FOURCC " to " DEST_FOURCC) )
71 set_capability( "video filter2", 80 )
72 # define vlc_CPU_capable() (true)
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 # define vlc_CPU_capable() vlc_CPU_MMX()
78 # define VLC_TARGET VLC_MMX
79 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
80 set_description( N_("SSE2 conversions from " SRC_FOURCC " to " DEST_FOURCC) )
81 set_capability( "video filter2", 120 )
82 # define vlc_CPU_capable() vlc_CPU_SSE2()
83 # define VLC_TARGET VLC_SSE
85 set_callbacks( Activate, NULL )
88 /*****************************************************************************
89 * Activate: allocate a chroma function
90 *****************************************************************************
91 * This function allocates and initializes a chroma function
92 *****************************************************************************/
93 static int Activate( vlc_object_t *p_this )
95 filter_t *p_filter = (filter_t *)p_this;
97 if( !vlc_CPU_capable() )
99 if( p_filter->fmt_in.video.i_width & 1
100 || p_filter->fmt_in.video.i_height & 1 )
105 if( p_filter->fmt_in.video.orientation != p_filter->fmt_out.video.orientation )
110 switch( p_filter->fmt_in.video.i_chroma )
113 switch( p_filter->fmt_out.video.i_chroma )
116 p_filter->pf_video_filter = I422_YUY2_Filter;
120 p_filter->pf_video_filter = I422_YVYU_Filter;
124 p_filter->pf_video_filter = I422_UYVY_Filter;
127 case VLC_FOURCC('I','U','Y','V'):
128 p_filter->pf_video_filter = I422_IUYV_Filter;
131 #if defined (MODULE_NAME_IS_i422_yuy2)
133 p_filter->pf_video_filter = I422_Y211_Filter;
148 /* Following functions are local */
150 VIDEO_FILTER_WRAPPER( I422_YUY2 )
151 VIDEO_FILTER_WRAPPER( I422_YVYU )
152 VIDEO_FILTER_WRAPPER( I422_UYVY )
153 VIDEO_FILTER_WRAPPER( I422_IUYV )
154 #if defined (MODULE_NAME_IS_i422_yuy2)
155 VIDEO_FILTER_WRAPPER( I422_Y211 )
158 /*****************************************************************************
159 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
160 *****************************************************************************/
162 static void I422_YUY2( filter_t *p_filter, picture_t *p_source,
165 uint8_t *p_line = p_dest->p->p_pixels;
166 uint8_t *p_y = p_source->Y_PIXELS;
167 uint8_t *p_u = p_source->U_PIXELS;
168 uint8_t *p_v = p_source->V_PIXELS;
172 const int i_source_margin = p_source->p[0].i_pitch
173 - p_source->p[0].i_visible_pitch;
174 const int i_source_margin_c = p_source->p[1].i_pitch
175 - p_source->p[1].i_visible_pitch;
176 const int i_dest_margin = p_dest->p->i_pitch
177 - p_dest->p->i_visible_pitch;
179 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
181 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
182 ((intptr_t)p_line|(intptr_t)p_y))) )
184 /* use faster SSE2 aligned fetch and store */
185 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
187 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
189 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED );
191 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
193 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
195 p_y += i_source_margin;
196 p_u += i_source_margin_c;
197 p_v += i_source_margin_c;
198 p_line += i_dest_margin;
202 /* use slower SSE2 unaligned fetch and store */
203 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
205 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
207 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED );
209 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
211 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
213 p_y += i_source_margin;
214 p_u += i_source_margin_c;
215 p_v += i_source_margin_c;
216 p_line += i_dest_margin;
223 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
225 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
227 #if defined (MODULE_NAME_IS_i422_yuy2)
228 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
229 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
230 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
231 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
232 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
233 MMX_CALL( MMX_YUV422_YUYV );
236 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
238 C_YUV422_YUYV( p_line, p_y, p_u, p_v );
240 p_y += i_source_margin;
241 p_u += i_source_margin_c;
242 p_v += i_source_margin_c;
243 p_line += i_dest_margin;
245 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
252 /*****************************************************************************
253 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
254 *****************************************************************************/
256 static void I422_YVYU( filter_t *p_filter, picture_t *p_source,
259 uint8_t *p_line = p_dest->p->p_pixels;
260 uint8_t *p_y = p_source->Y_PIXELS;
261 uint8_t *p_u = p_source->U_PIXELS;
262 uint8_t *p_v = p_source->V_PIXELS;
266 const int i_source_margin = p_source->p[0].i_pitch
267 - p_source->p[0].i_visible_pitch;
268 const int i_source_margin_c = p_source->p[1].i_pitch
269 - p_source->p[1].i_visible_pitch;
270 const int i_dest_margin = p_dest->p->i_pitch
271 - p_dest->p->i_visible_pitch;
273 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
275 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
276 ((intptr_t)p_line|(intptr_t)p_y))) )
278 /* use faster SSE2 aligned fetch and store */
279 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
281 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
283 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED );
285 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
287 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
289 p_y += i_source_margin;
290 p_u += i_source_margin_c;
291 p_v += i_source_margin_c;
292 p_line += i_dest_margin;
296 /* use slower SSE2 unaligned fetch and store */
297 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
299 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
301 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED );
303 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
305 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
307 p_y += i_source_margin;
308 p_u += i_source_margin_c;
309 p_v += i_source_margin_c;
310 p_line += i_dest_margin;
317 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
319 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
321 #if defined (MODULE_NAME_IS_i422_yuy2)
322 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
323 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
324 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
325 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
326 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
327 MMX_CALL( MMX_YUV422_YVYU );
330 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
332 C_YUV422_YVYU( p_line, p_y, p_u, p_v );
334 p_y += i_source_margin;
335 p_u += i_source_margin_c;
336 p_v += i_source_margin_c;
337 p_line += i_dest_margin;
339 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
346 /*****************************************************************************
347 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
348 *****************************************************************************/
350 static void I422_UYVY( filter_t *p_filter, picture_t *p_source,
353 uint8_t *p_line = p_dest->p->p_pixels;
354 uint8_t *p_y = p_source->Y_PIXELS;
355 uint8_t *p_u = p_source->U_PIXELS;
356 uint8_t *p_v = p_source->V_PIXELS;
360 const int i_source_margin = p_source->p[0].i_pitch
361 - p_source->p[0].i_visible_pitch;
362 const int i_source_margin_c = p_source->p[1].i_pitch
363 - p_source->p[1].i_visible_pitch;
364 const int i_dest_margin = p_dest->p->i_pitch
365 - p_dest->p->i_visible_pitch;
367 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
369 if( 0 == (15 & (p_source->p[Y_PLANE].i_pitch|p_dest->p->i_pitch|
370 ((intptr_t)p_line|(intptr_t)p_y))) )
372 /* use faster SSE2 aligned fetch and store */
373 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
375 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
377 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED );
379 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
381 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
383 p_y += i_source_margin;
384 p_u += i_source_margin_c;
385 p_v += i_source_margin_c;
386 p_line += i_dest_margin;
390 /* use slower SSE2 unaligned fetch and store */
391 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
393 for( i_x = p_filter->fmt_in.video.i_width / 16 ; i_x-- ; )
395 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED );
397 for( i_x = ( p_filter->fmt_in.video.i_width % 16 ) / 2; i_x-- ; )
399 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
401 p_y += i_source_margin;
402 p_u += i_source_margin_c;
403 p_v += i_source_margin_c;
404 p_line += i_dest_margin;
411 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
413 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
415 #if defined (MODULE_NAME_IS_i422_yuy2)
416 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
417 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
418 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
419 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
420 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
421 MMX_CALL( MMX_YUV422_UYVY );
424 for( i_x = ( p_filter->fmt_in.video.i_width % 8 ) / 2; i_x-- ; )
426 C_YUV422_UYVY( p_line, p_y, p_u, p_v );
428 p_y += i_source_margin;
429 p_u += i_source_margin_c;
430 p_v += i_source_margin_c;
431 p_line += i_dest_margin;
433 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
440 /*****************************************************************************
441 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
442 *****************************************************************************/
443 static void I422_IUYV( filter_t *p_filter, picture_t *p_source,
446 VLC_UNUSED(p_source); VLC_UNUSED(p_dest);
448 msg_Err( p_filter, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
451 /*****************************************************************************
452 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
453 *****************************************************************************/
454 #if defined (MODULE_NAME_IS_i422_yuy2)
455 static void I422_Y211( filter_t *p_filter, picture_t *p_source,
458 uint8_t *p_line = p_dest->p->p_pixels + p_dest->p->i_visible_lines * p_dest->p->i_pitch;
459 uint8_t *p_y = p_source->Y_PIXELS;
460 uint8_t *p_u = p_source->U_PIXELS;
461 uint8_t *p_v = p_source->V_PIXELS;
465 for( i_y = p_filter->fmt_in.video.i_height ; i_y-- ; )
467 for( i_x = p_filter->fmt_in.video.i_width / 8 ; i_x-- ; )
469 C_YUV422_Y211( p_line, p_y, p_u, p_v );
470 C_YUV422_Y211( p_line, p_y, p_u, p_v );