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
6 * Authors: Samuel Hocevar <sam@zoy.org>
7 * Damien Fouilleul <damienf@videolan.org>
9 * This program is free software; you can redistribute it and/or modify it
10 * under the terms of the GNU Lesser General Public License as published by
11 * the Free Software Foundation; either version 2.1 of the License, or
12 * (at your option) any later version.
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU Lesser General Public License for more details.
19 * You should have received a copy of the GNU Lesser General Public License
20 * along with this program; if not, write to the Free Software Foundation,
21 * Inc., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301, USA.
22 *****************************************************************************/
24 /*****************************************************************************
26 *****************************************************************************/
32 #include <vlc_common.h>
33 #include <vlc_plugin.h>
34 #include <vlc_filter.h>
35 #include <vlc_picture.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 ( filter_t
* );
52 /*****************************************************************************
54 *****************************************************************************/
56 #if defined (MODULE_NAME_IS_i422_yuy2)
57 set_description( N_("Conversions from " SRC_FOURCC
" to " DEST_FOURCC
) )
58 set_callback_video_converter( Activate
, 80 )
59 # define vlc_CPU_capable() (true)
61 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
62 set_description( N_("MMX conversions from " SRC_FOURCC
" to " DEST_FOURCC
) )
63 set_callback_video_converter( Activate
, 100 )
64 # define vlc_CPU_capable() vlc_CPU_MMX()
65 # define VLC_TARGET VLC_MMX
66 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
67 set_description( N_("SSE2 conversions from " SRC_FOURCC
" to " DEST_FOURCC
) )
68 set_callback_video_converter( Activate
, 120 )
69 # define vlc_CPU_capable() vlc_CPU_SSE2()
70 # define VLC_TARGET VLC_SSE
75 VIDEO_FILTER_WRAPPER( I422_YUY2
)
76 VIDEO_FILTER_WRAPPER( I422_YVYU
)
77 VIDEO_FILTER_WRAPPER( I422_UYVY
)
78 VIDEO_FILTER_WRAPPER( I422_IUYV
)
79 #if defined (MODULE_NAME_IS_i422_yuy2)
80 VIDEO_FILTER_WRAPPER( I422_Y211
)
84 static const struct vlc_filter_operations
*
85 GetFilterOperations(filter_t
*filter
)
87 switch( filter
->fmt_out
.video
.i_chroma
)
90 return &I422_YUY2_ops
;
93 return &I422_YVYU_ops
;
96 return &I422_UYVY_ops
;
98 case VLC_FOURCC('I','U','Y','V'):
99 return &I422_IUYV_ops
;
101 #if defined (MODULE_NAME_IS_i422_yuy2)
103 return &I422_Y211_ops
;
112 /*****************************************************************************
113 * Activate: allocate a chroma function
114 *****************************************************************************
115 * This function allocates and initializes a chroma function
116 *****************************************************************************/
117 static int Activate( filter_t
*p_filter
)
119 if( !vlc_CPU_capable() )
121 if( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) & 1
122 || (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) & 1 )
127 if( p_filter
->fmt_in
.video
.orientation
!= p_filter
->fmt_out
.video
.orientation
)
132 /* This is a i422 -> * converter. */
133 if( p_filter
->fmt_in
.video
.i_chroma
!= VLC_CODEC_I422
)
137 p_filter
->ops
= GetFilterOperations( p_filter
);
138 if( p_filter
->ops
== NULL
)
144 /* Following functions are local */
146 /*****************************************************************************
147 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
148 *****************************************************************************/
150 static void I422_YUY2( filter_t
*p_filter
, picture_t
*p_source
,
153 uint8_t *p_line
= p_dest
->p
->p_pixels
;
154 uint8_t *p_y
= p_source
->Y_PIXELS
;
155 uint8_t *p_u
= p_source
->U_PIXELS
;
156 uint8_t *p_v
= p_source
->V_PIXELS
;
160 const int i_source_margin
= p_source
->p
[0].i_pitch
161 - p_source
->p
[0].i_visible_pitch
162 - p_filter
->fmt_in
.video
.i_x_offset
;
163 const int i_source_margin_c
= p_source
->p
[1].i_pitch
164 - p_source
->p
[1].i_visible_pitch
165 - ( p_filter
->fmt_in
.video
.i_x_offset
);
166 const int i_dest_margin
= p_dest
->p
->i_pitch
167 - p_dest
->p
->i_visible_pitch
168 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
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_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
178 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
180 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED
);
182 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_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_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
196 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
198 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED
);
200 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_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_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
216 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_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_x_offset
+ p_filter
->fmt_in
.video
.i_visible_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 *****************************************************************************/
247 static void I422_YVYU( filter_t
*p_filter
, picture_t
*p_source
,
250 uint8_t *p_line
= p_dest
->p
->p_pixels
;
251 uint8_t *p_y
= p_source
->Y_PIXELS
;
252 uint8_t *p_u
= p_source
->U_PIXELS
;
253 uint8_t *p_v
= p_source
->V_PIXELS
;
257 const int i_source_margin
= p_source
->p
[0].i_pitch
258 - p_source
->p
[0].i_visible_pitch
259 - p_filter
->fmt_in
.video
.i_x_offset
;
260 const int i_source_margin_c
= p_source
->p
[1].i_pitch
261 - p_source
->p
[1].i_visible_pitch
262 - ( p_filter
->fmt_in
.video
.i_x_offset
);
263 const int i_dest_margin
= p_dest
->p
->i_pitch
264 - p_dest
->p
->i_visible_pitch
265 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
267 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
269 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
270 ((intptr_t)p_line
|(intptr_t)p_y
))) )
272 /* use faster SSE2 aligned fetch and store */
273 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
275 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
277 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED
);
279 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
281 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
283 p_y
+= i_source_margin
;
284 p_u
+= i_source_margin_c
;
285 p_v
+= i_source_margin_c
;
286 p_line
+= i_dest_margin
;
290 /* use slower SSE2 unaligned fetch and store */
291 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
293 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
295 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED
);
297 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
299 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
301 p_y
+= i_source_margin
;
302 p_u
+= i_source_margin_c
;
303 p_v
+= i_source_margin_c
;
304 p_line
+= i_dest_margin
;
311 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
313 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
315 #if defined (MODULE_NAME_IS_i422_yuy2)
316 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
317 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
318 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
319 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
320 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
321 MMX_CALL( MMX_YUV422_YVYU
);
324 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
326 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
328 p_y
+= i_source_margin
;
329 p_u
+= i_source_margin_c
;
330 p_v
+= i_source_margin_c
;
331 p_line
+= i_dest_margin
;
333 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
340 /*****************************************************************************
341 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
342 *****************************************************************************/
344 static void I422_UYVY( filter_t
*p_filter
, picture_t
*p_source
,
347 uint8_t *p_line
= p_dest
->p
->p_pixels
;
348 uint8_t *p_y
= p_source
->Y_PIXELS
;
349 uint8_t *p_u
= p_source
->U_PIXELS
;
350 uint8_t *p_v
= p_source
->V_PIXELS
;
354 const int i_source_margin
= p_source
->p
[0].i_pitch
355 - p_source
->p
[0].i_visible_pitch
356 - p_filter
->fmt_in
.video
.i_x_offset
;
357 const int i_source_margin_c
= p_source
->p
[1].i_pitch
358 - p_source
->p
[1].i_visible_pitch
359 - ( p_filter
->fmt_in
.video
.i_x_offset
);
360 const int i_dest_margin
= p_dest
->p
->i_pitch
361 - p_dest
->p
->i_visible_pitch
362 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
364 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
366 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
367 ((intptr_t)p_line
|(intptr_t)p_y
))) )
369 /* use faster SSE2 aligned fetch and store */
370 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
372 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
374 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED
);
376 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
378 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
380 p_y
+= i_source_margin
;
381 p_u
+= i_source_margin_c
;
382 p_v
+= i_source_margin_c
;
383 p_line
+= i_dest_margin
;
387 /* use slower SSE2 unaligned fetch and store */
388 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
390 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
392 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED
);
394 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
396 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
398 p_y
+= i_source_margin
;
399 p_u
+= i_source_margin_c
;
400 p_v
+= i_source_margin_c
;
401 p_line
+= i_dest_margin
;
408 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
410 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
412 #if defined (MODULE_NAME_IS_i422_yuy2)
413 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
414 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
415 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
416 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
417 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
418 MMX_CALL( MMX_YUV422_UYVY
);
421 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
423 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
425 p_y
+= i_source_margin
;
426 p_u
+= i_source_margin_c
;
427 p_v
+= i_source_margin_c
;
428 p_line
+= i_dest_margin
;
430 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
437 /*****************************************************************************
438 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
439 *****************************************************************************/
440 static void I422_IUYV( filter_t
*p_filter
, picture_t
*p_source
,
443 VLC_UNUSED(p_source
); VLC_UNUSED(p_dest
);
445 msg_Err( p_filter
, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
448 /*****************************************************************************
449 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
450 *****************************************************************************/
451 #if defined (MODULE_NAME_IS_i422_yuy2)
452 static void I422_Y211( filter_t
*p_filter
, picture_t
*p_source
,
455 uint8_t *p_line
= p_dest
->p
->p_pixels
+ p_dest
->p
->i_visible_lines
* p_dest
->p
->i_pitch
;
456 uint8_t *p_y
= p_source
->Y_PIXELS
;
457 uint8_t *p_u
= p_source
->U_PIXELS
;
458 uint8_t *p_v
= p_source
->V_PIXELS
;
462 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
464 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
466 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);
467 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);