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
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
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.
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.
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 *****************************************************************************/
25 /*****************************************************************************
27 *****************************************************************************/
33 #include <vlc_common.h>
34 #include <vlc_plugin.h>
35 #include <vlc_filter.h>
37 #include "i422_yuy2.h"
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"
43 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
46 /*****************************************************************************
47 * Local and extern prototypes.
48 *****************************************************************************/
49 static int Activate ( vlc_object_t
* );
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
* );
66 /*****************************************************************************
68 *****************************************************************************/
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 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
77 set_description( N_("SSE2 conversions from " SRC_FOURCC
" to " DEST_FOURCC
) )
78 set_capability( "video filter2", 120 )
80 set_callbacks( Activate
, NULL
)
83 /*****************************************************************************
84 * Activate: allocate a chroma function
85 *****************************************************************************
86 * This function allocates and initializes a chroma function
87 *****************************************************************************/
88 static int Activate( vlc_object_t
*p_this
)
90 filter_t
*p_filter
= (filter_t
*)p_this
;
92 if( p_filter
->fmt_in
.video
.i_width
& 1
93 || p_filter
->fmt_in
.video
.i_height
& 1 )
98 switch( p_filter
->fmt_in
.video
.i_chroma
)
101 switch( p_filter
->fmt_out
.video
.i_chroma
)
104 p_filter
->pf_video_filter
= I422_YUY2_Filter
;
108 p_filter
->pf_video_filter
= I422_YVYU_Filter
;
112 p_filter
->pf_video_filter
= I422_UYVY_Filter
;
115 p_filter
->pf_video_filter
= I422_IUYV_Filter
;
119 p_filter
->pf_video_filter
= I422_cyuv_Filter
;
122 #if defined (MODULE_NAME_IS_i422_yuy2)
124 p_filter
->pf_video_filter
= I422_Y211_Filter
;
139 /* Following functions are local */
141 VIDEO_FILTER_WRAPPER( I422_YUY2
)
142 VIDEO_FILTER_WRAPPER( I422_YVYU
)
143 VIDEO_FILTER_WRAPPER( I422_UYVY
)
144 VIDEO_FILTER_WRAPPER( I422_IUYV
)
145 VIDEO_FILTER_WRAPPER( I422_cyuv
)
146 #if defined (MODULE_NAME_IS_i422_yuy2)
147 VIDEO_FILTER_WRAPPER( I422_Y211
)
150 /*****************************************************************************
151 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
152 *****************************************************************************/
153 static void I422_YUY2( filter_t
*p_filter
, picture_t
*p_source
,
156 uint8_t *p_line
= p_dest
->p
->p_pixels
;
157 uint8_t *p_y
= p_source
->Y_PIXELS
;
158 uint8_t *p_u
= p_source
->U_PIXELS
;
159 uint8_t *p_v
= p_source
->V_PIXELS
;
163 const int i_source_margin
= p_source
->p
[0].i_pitch
164 - p_source
->p
[0].i_visible_pitch
;
165 const int i_source_margin_c
= p_source
->p
[1].i_pitch
166 - p_source
->p
[1].i_visible_pitch
;
167 const int i_dest_margin
= p_dest
->p
->i_pitch
168 - p_dest
->p
->i_visible_pitch
;
170 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
172 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
173 ((intptr_t)p_line
|(intptr_t)p_y
))) )
175 /* use faster SSE2 aligned fetch and store */
176 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
178 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
180 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED
);
182 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
184 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
186 p_y
+= i_source_margin
;
187 p_u
+= i_source_margin_c
;
188 p_v
+= i_source_margin_c
;
189 p_line
+= i_dest_margin
;
193 /* use slower SSE2 unaligned fetch and store */
194 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
196 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
198 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED
);
200 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
202 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
204 p_y
+= i_source_margin
;
205 p_u
+= i_source_margin_c
;
206 p_v
+= i_source_margin_c
;
207 p_line
+= i_dest_margin
;
214 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
216 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
218 #if defined (MODULE_NAME_IS_i422_yuy2)
219 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
220 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
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 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
224 MMX_CALL( MMX_YUV422_YUYV
);
227 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 8 ) / 2; i_x
-- ; )
229 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
231 p_y
+= i_source_margin
;
232 p_u
+= i_source_margin_c
;
233 p_v
+= i_source_margin_c
;
234 p_line
+= i_dest_margin
;
236 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
243 /*****************************************************************************
244 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
245 *****************************************************************************/
246 static void I422_YVYU( filter_t
*p_filter
, picture_t
*p_source
,
249 uint8_t *p_line
= p_dest
->p
->p_pixels
;
250 uint8_t *p_y
= p_source
->Y_PIXELS
;
251 uint8_t *p_u
= p_source
->U_PIXELS
;
252 uint8_t *p_v
= p_source
->V_PIXELS
;
256 const int i_source_margin
= p_source
->p
[0].i_pitch
257 - p_source
->p
[0].i_visible_pitch
;
258 const int i_source_margin_c
= p_source
->p
[1].i_pitch
259 - p_source
->p
[1].i_visible_pitch
;
260 const int i_dest_margin
= p_dest
->p
->i_pitch
261 - p_dest
->p
->i_visible_pitch
;
263 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
265 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
266 ((intptr_t)p_line
|(intptr_t)p_y
))) )
268 /* use faster SSE2 aligned fetch and store */
269 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
271 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
273 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED
);
275 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
277 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
279 p_y
+= i_source_margin
;
280 p_u
+= i_source_margin_c
;
281 p_v
+= i_source_margin_c
;
282 p_line
+= i_dest_margin
;
286 /* use slower SSE2 unaligned fetch and store */
287 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
289 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
291 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED
);
293 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
295 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
297 p_y
+= i_source_margin
;
298 p_u
+= i_source_margin_c
;
299 p_v
+= i_source_margin_c
;
300 p_line
+= i_dest_margin
;
307 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
309 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
311 #if defined (MODULE_NAME_IS_i422_yuy2)
312 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
313 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
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 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
317 MMX_CALL( MMX_YUV422_YVYU
);
320 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 8 ) / 2; i_x
-- ; )
322 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
324 p_y
+= i_source_margin
;
325 p_u
+= i_source_margin_c
;
326 p_v
+= i_source_margin_c
;
327 p_line
+= i_dest_margin
;
329 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
336 /*****************************************************************************
337 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
338 *****************************************************************************/
339 static void I422_UYVY( filter_t
*p_filter
, picture_t
*p_source
,
342 uint8_t *p_line
= p_dest
->p
->p_pixels
;
343 uint8_t *p_y
= p_source
->Y_PIXELS
;
344 uint8_t *p_u
= p_source
->U_PIXELS
;
345 uint8_t *p_v
= p_source
->V_PIXELS
;
349 const int i_source_margin
= p_source
->p
[0].i_pitch
350 - p_source
->p
[0].i_visible_pitch
;
351 const int i_source_margin_c
= p_source
->p
[1].i_pitch
352 - p_source
->p
[1].i_visible_pitch
;
353 const int i_dest_margin
= p_dest
->p
->i_pitch
354 - p_dest
->p
->i_visible_pitch
;
356 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
358 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
359 ((intptr_t)p_line
|(intptr_t)p_y
))) )
361 /* use faster SSE2 aligned fetch and store */
362 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
364 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
366 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED
);
368 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
370 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
372 p_y
+= i_source_margin
;
373 p_u
+= i_source_margin_c
;
374 p_v
+= i_source_margin_c
;
375 p_line
+= i_dest_margin
;
379 /* use slower SSE2 unaligned fetch and store */
380 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
382 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
384 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED
);
386 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
388 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
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
;
400 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
402 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
404 #if defined (MODULE_NAME_IS_i422_yuy2)
405 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
406 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
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 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
410 MMX_CALL( MMX_YUV422_UYVY
);
413 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 8 ) / 2; i_x
-- ; )
415 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
417 p_y
+= i_source_margin
;
418 p_u
+= i_source_margin_c
;
419 p_v
+= i_source_margin_c
;
420 p_line
+= i_dest_margin
;
422 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
429 /*****************************************************************************
430 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
431 *****************************************************************************/
432 static void I422_IUYV( filter_t
*p_filter
, picture_t
*p_source
,
435 VLC_UNUSED(p_source
); VLC_UNUSED(p_dest
);
437 msg_Err( p_filter
, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
440 /*****************************************************************************
441 * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
442 *****************************************************************************/
443 static void I422_cyuv( filter_t
*p_filter
, picture_t
*p_source
,
446 uint8_t *p_line
= p_dest
->p
->p_pixels
+ p_dest
->p
->i_visible_lines
* p_dest
->p
->i_pitch
;
447 uint8_t *p_y
= p_source
->Y_PIXELS
;
448 uint8_t *p_u
= p_source
->U_PIXELS
;
449 uint8_t *p_v
= p_source
->V_PIXELS
;
453 const int i_source_margin
= p_source
->p
[0].i_pitch
454 - p_source
->p
[0].i_visible_pitch
;
455 const int i_source_margin_c
= p_source
->p
[1].i_pitch
456 - p_source
->p
[1].i_visible_pitch
;
457 const int i_dest_margin
= p_dest
->p
->i_pitch
458 - p_dest
->p
->i_visible_pitch
;
460 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
462 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
463 ((intptr_t)p_line
|(intptr_t)p_y
))) )
465 /* use faster SSE2 aligned fetch and store */
466 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
468 p_line
-= 2 * p_dest
->p
->i_pitch
;
470 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
472 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED
);
474 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
476 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
478 p_y
+= i_source_margin
;
479 p_u
+= i_source_margin_c
;
480 p_v
+= i_source_margin_c
;
481 p_line
+= i_dest_margin
;
485 /* use slower SSE2 unaligned fetch and store */
486 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
488 p_line
-= 2 * p_dest
->p
->i_pitch
;
490 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
492 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED
);
494 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
496 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
498 p_y
+= i_source_margin
;
499 p_u
+= i_source_margin_c
;
500 p_v
+= i_source_margin_c
;
501 p_line
+= i_dest_margin
;
508 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
510 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
512 p_line
-= 2 * p_dest
->p
->i_pitch
;
514 #if defined (MODULE_NAME_IS_i422_yuy2)
515 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
516 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
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 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
520 MMX_CALL( MMX_YUV422_UYVY
);
523 p_y
+= i_source_margin
;
524 p_u
+= i_source_margin_c
;
525 p_v
+= i_source_margin_c
;
526 p_line
+= i_dest_margin
;
528 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
530 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
537 /*****************************************************************************
538 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
539 *****************************************************************************/
540 #if defined (MODULE_NAME_IS_i422_yuy2)
541 static void I422_Y211( filter_t
*p_filter
, picture_t
*p_source
,
544 uint8_t *p_line
= p_dest
->p
->p_pixels
+ p_dest
->p
->i_visible_lines
* p_dest
->p
->i_pitch
;
545 uint8_t *p_y
= p_source
->Y_PIXELS
;
546 uint8_t *p_u
= p_source
->U_PIXELS
;
547 uint8_t *p_v
= p_source
->V_PIXELS
;
551 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
553 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
555 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);
556 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);