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,cyuv,Y211"
44 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
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 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
* );
67 /*****************************************************************************
69 *****************************************************************************/
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)
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
87 set_callbacks( Activate
, NULL
)
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
)
97 filter_t
*p_filter
= (filter_t
*)p_this
;
99 if( !vlc_CPU_capable() )
101 if( p_filter
->fmt_in
.video
.i_width
& 1
102 || p_filter
->fmt_in
.video
.i_height
& 1 )
107 switch( p_filter
->fmt_in
.video
.i_chroma
)
110 switch( p_filter
->fmt_out
.video
.i_chroma
)
113 p_filter
->pf_video_filter
= I422_YUY2_Filter
;
117 p_filter
->pf_video_filter
= I422_YVYU_Filter
;
121 p_filter
->pf_video_filter
= I422_UYVY_Filter
;
124 case VLC_FOURCC('I','U','Y','V'):
125 p_filter
->pf_video_filter
= I422_IUYV_Filter
;
129 p_filter
->pf_video_filter
= I422_cyuv_Filter
;
132 #if defined (MODULE_NAME_IS_i422_yuy2)
134 p_filter
->pf_video_filter
= I422_Y211_Filter
;
149 /* Following functions are local */
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 VIDEO_FILTER_WRAPPER( I422_cyuv
)
156 #if defined (MODULE_NAME_IS_i422_yuy2)
157 VIDEO_FILTER_WRAPPER( I422_Y211
)
160 /*****************************************************************************
161 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
162 *****************************************************************************/
164 static void I422_YUY2( filter_t
*p_filter
, picture_t
*p_source
,
167 uint8_t *p_line
= p_dest
->p
->p_pixels
;
168 uint8_t *p_y
= p_source
->Y_PIXELS
;
169 uint8_t *p_u
= p_source
->U_PIXELS
;
170 uint8_t *p_v
= p_source
->V_PIXELS
;
174 const int i_source_margin
= p_source
->p
[0].i_pitch
175 - p_source
->p
[0].i_visible_pitch
;
176 const int i_source_margin_c
= p_source
->p
[1].i_pitch
177 - p_source
->p
[1].i_visible_pitch
;
178 const int i_dest_margin
= p_dest
->p
->i_pitch
179 - p_dest
->p
->i_visible_pitch
;
181 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
183 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
184 ((intptr_t)p_line
|(intptr_t)p_y
))) )
186 /* use faster SSE2 aligned fetch and store */
187 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
189 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
191 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED
);
193 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
195 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
197 p_y
+= i_source_margin
;
198 p_u
+= i_source_margin_c
;
199 p_v
+= i_source_margin_c
;
200 p_line
+= i_dest_margin
;
204 /* use slower SSE2 unaligned fetch and store */
205 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
207 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
209 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED
);
211 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
213 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
215 p_y
+= i_source_margin
;
216 p_u
+= i_source_margin_c
;
217 p_v
+= i_source_margin_c
;
218 p_line
+= i_dest_margin
;
225 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
227 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
229 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
233 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
234 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
235 MMX_CALL( MMX_YUV422_YUYV
);
238 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 8 ) / 2; i_x
-- ; )
240 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
242 p_y
+= i_source_margin
;
243 p_u
+= i_source_margin_c
;
244 p_v
+= i_source_margin_c
;
245 p_line
+= i_dest_margin
;
247 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
254 /*****************************************************************************
255 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
256 *****************************************************************************/
258 static void I422_YVYU( filter_t
*p_filter
, picture_t
*p_source
,
261 uint8_t *p_line
= p_dest
->p
->p_pixels
;
262 uint8_t *p_y
= p_source
->Y_PIXELS
;
263 uint8_t *p_u
= p_source
->U_PIXELS
;
264 uint8_t *p_v
= p_source
->V_PIXELS
;
268 const int i_source_margin
= p_source
->p
[0].i_pitch
269 - p_source
->p
[0].i_visible_pitch
;
270 const int i_source_margin_c
= p_source
->p
[1].i_pitch
271 - p_source
->p
[1].i_visible_pitch
;
272 const int i_dest_margin
= p_dest
->p
->i_pitch
273 - p_dest
->p
->i_visible_pitch
;
275 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
277 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
278 ((intptr_t)p_line
|(intptr_t)p_y
))) )
280 /* use faster SSE2 aligned fetch and store */
281 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
283 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
285 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED
);
287 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
289 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
291 p_y
+= i_source_margin
;
292 p_u
+= i_source_margin_c
;
293 p_v
+= i_source_margin_c
;
294 p_line
+= i_dest_margin
;
298 /* use slower SSE2 unaligned fetch and store */
299 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
301 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
303 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED
);
305 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
307 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
309 p_y
+= i_source_margin
;
310 p_u
+= i_source_margin_c
;
311 p_v
+= i_source_margin_c
;
312 p_line
+= i_dest_margin
;
319 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
321 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
323 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
327 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
328 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
329 MMX_CALL( MMX_YUV422_YVYU
);
332 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 8 ) / 2; i_x
-- ; )
334 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
336 p_y
+= i_source_margin
;
337 p_u
+= i_source_margin_c
;
338 p_v
+= i_source_margin_c
;
339 p_line
+= i_dest_margin
;
341 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
348 /*****************************************************************************
349 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
350 *****************************************************************************/
352 static void I422_UYVY( filter_t
*p_filter
, picture_t
*p_source
,
355 uint8_t *p_line
= p_dest
->p
->p_pixels
;
356 uint8_t *p_y
= p_source
->Y_PIXELS
;
357 uint8_t *p_u
= p_source
->U_PIXELS
;
358 uint8_t *p_v
= p_source
->V_PIXELS
;
362 const int i_source_margin
= p_source
->p
[0].i_pitch
363 - p_source
->p
[0].i_visible_pitch
;
364 const int i_source_margin_c
= p_source
->p
[1].i_pitch
365 - p_source
->p
[1].i_visible_pitch
;
366 const int i_dest_margin
= p_dest
->p
->i_pitch
367 - p_dest
->p
->i_visible_pitch
;
369 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
371 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
372 ((intptr_t)p_line
|(intptr_t)p_y
))) )
374 /* use faster SSE2 aligned fetch and store */
375 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
377 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
379 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED
);
381 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
383 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
385 p_y
+= i_source_margin
;
386 p_u
+= i_source_margin_c
;
387 p_v
+= i_source_margin_c
;
388 p_line
+= i_dest_margin
;
392 /* use slower SSE2 unaligned fetch and store */
393 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
395 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
397 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED
);
399 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
401 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
403 p_y
+= i_source_margin
;
404 p_u
+= i_source_margin_c
;
405 p_v
+= i_source_margin_c
;
406 p_line
+= i_dest_margin
;
413 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
415 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
417 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
421 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
422 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
423 MMX_CALL( MMX_YUV422_UYVY
);
426 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 8 ) / 2; i_x
-- ; )
428 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
430 p_y
+= i_source_margin
;
431 p_u
+= i_source_margin_c
;
432 p_v
+= i_source_margin_c
;
433 p_line
+= i_dest_margin
;
435 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
442 /*****************************************************************************
443 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
444 *****************************************************************************/
445 static void I422_IUYV( filter_t
*p_filter
, picture_t
*p_source
,
448 VLC_UNUSED(p_source
); VLC_UNUSED(p_dest
);
450 msg_Err( p_filter
, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
453 /*****************************************************************************
454 * I422_cyuv: planar YUV 4:2:2 to upside-down packed UYVY 4:2:2
455 *****************************************************************************/
457 static void I422_cyuv( filter_t
*p_filter
, picture_t
*p_source
,
460 uint8_t *p_line
= p_dest
->p
->p_pixels
+ p_dest
->p
->i_visible_lines
* p_dest
->p
->i_pitch
;
461 uint8_t *p_y
= p_source
->Y_PIXELS
;
462 uint8_t *p_u
= p_source
->U_PIXELS
;
463 uint8_t *p_v
= p_source
->V_PIXELS
;
467 const int i_source_margin
= p_source
->p
[0].i_pitch
468 - p_source
->p
[0].i_visible_pitch
;
469 const int i_source_margin_c
= p_source
->p
[1].i_pitch
470 - p_source
->p
[1].i_visible_pitch
;
471 const int i_dest_margin
= p_dest
->p
->i_pitch
472 - p_dest
->p
->i_visible_pitch
;
474 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
476 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
477 ((intptr_t)p_line
|(intptr_t)p_y
))) )
479 /* use faster SSE2 aligned fetch and store */
480 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
482 p_line
-= 2 * p_dest
->p
->i_pitch
;
484 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
486 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED
);
488 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
490 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
492 p_y
+= i_source_margin
;
493 p_u
+= i_source_margin_c
;
494 p_v
+= i_source_margin_c
;
495 p_line
+= i_dest_margin
;
499 /* use slower SSE2 unaligned fetch and store */
500 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
502 p_line
-= 2 * p_dest
->p
->i_pitch
;
504 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 16 ; i_x
-- ; )
506 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED
);
508 for( i_x
= ( p_filter
->fmt_in
.video
.i_width
% 16 ) / 2; i_x
-- ; )
510 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
512 p_y
+= i_source_margin
;
513 p_u
+= i_source_margin_c
;
514 p_v
+= i_source_margin_c
;
515 p_line
+= i_dest_margin
;
522 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
524 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
526 p_line
-= 2 * p_dest
->p
->i_pitch
;
528 #if defined (MODULE_NAME_IS_i422_yuy2)
529 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
530 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
531 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
532 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
533 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
534 MMX_CALL( MMX_YUV422_UYVY
);
537 p_y
+= i_source_margin
;
538 p_u
+= i_source_margin_c
;
539 p_v
+= i_source_margin_c
;
540 p_line
+= i_dest_margin
;
542 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
544 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
551 /*****************************************************************************
552 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
553 *****************************************************************************/
554 #if defined (MODULE_NAME_IS_i422_yuy2)
555 static void I422_Y211( filter_t
*p_filter
, picture_t
*p_source
,
558 uint8_t *p_line
= p_dest
->p
->p_pixels
+ p_dest
->p
->i_visible_lines
* p_dest
->p
->i_pitch
;
559 uint8_t *p_y
= p_source
->Y_PIXELS
;
560 uint8_t *p_u
= p_source
->U_PIXELS
;
561 uint8_t *p_v
= p_source
->V_PIXELS
;
565 for( i_y
= p_filter
->fmt_in
.video
.i_height
; i_y
-- ; )
567 for( i_x
= p_filter
->fmt_in
.video
.i_width
/ 8 ; i_x
-- ; )
569 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);
570 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);