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 ( 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 converter", 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 converter", 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 converter", 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_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) & 1
100 || (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_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 - p_filter
->fmt_in
.video
.i_x_offset
;
175 const int i_source_margin_c
= p_source
->p
[1].i_pitch
176 - p_source
->p
[1].i_visible_pitch
177 - ( p_filter
->fmt_in
.video
.i_x_offset
);
178 const int i_dest_margin
= p_dest
->p
->i_pitch
179 - p_dest
->p
->i_visible_pitch
180 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
182 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
184 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
185 ((intptr_t)p_line
|(intptr_t)p_y
))) )
187 /* use faster SSE2 aligned fetch and store */
188 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
190 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
192 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED
);
194 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
196 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
198 p_y
+= i_source_margin
;
199 p_u
+= i_source_margin_c
;
200 p_v
+= i_source_margin_c
;
201 p_line
+= i_dest_margin
;
205 /* use slower SSE2 unaligned fetch and store */
206 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
208 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
210 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED
);
212 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
214 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
216 p_y
+= i_source_margin
;
217 p_u
+= i_source_margin_c
;
218 p_v
+= i_source_margin_c
;
219 p_line
+= i_dest_margin
;
226 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
228 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
230 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
235 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
236 MMX_CALL( MMX_YUV422_YUYV
);
239 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
241 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
243 p_y
+= i_source_margin
;
244 p_u
+= i_source_margin_c
;
245 p_v
+= i_source_margin_c
;
246 p_line
+= i_dest_margin
;
248 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
255 /*****************************************************************************
256 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
257 *****************************************************************************/
259 static void I422_YVYU( filter_t
*p_filter
, picture_t
*p_source
,
262 uint8_t *p_line
= p_dest
->p
->p_pixels
;
263 uint8_t *p_y
= p_source
->Y_PIXELS
;
264 uint8_t *p_u
= p_source
->U_PIXELS
;
265 uint8_t *p_v
= p_source
->V_PIXELS
;
269 const int i_source_margin
= p_source
->p
[0].i_pitch
270 - p_source
->p
[0].i_visible_pitch
271 - p_filter
->fmt_in
.video
.i_x_offset
;
272 const int i_source_margin_c
= p_source
->p
[1].i_pitch
273 - p_source
->p
[1].i_visible_pitch
274 - ( p_filter
->fmt_in
.video
.i_x_offset
);
275 const int i_dest_margin
= p_dest
->p
->i_pitch
276 - p_dest
->p
->i_visible_pitch
277 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
279 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
281 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
282 ((intptr_t)p_line
|(intptr_t)p_y
))) )
284 /* use faster SSE2 aligned fetch and store */
285 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
287 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
289 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED
);
291 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
293 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
295 p_y
+= i_source_margin
;
296 p_u
+= i_source_margin_c
;
297 p_v
+= i_source_margin_c
;
298 p_line
+= i_dest_margin
;
302 /* use slower SSE2 unaligned fetch and store */
303 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
305 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
307 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED
);
309 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
311 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
313 p_y
+= i_source_margin
;
314 p_u
+= i_source_margin_c
;
315 p_v
+= i_source_margin_c
;
316 p_line
+= i_dest_margin
;
323 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
325 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
327 #if defined (MODULE_NAME_IS_i422_yuy2)
328 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
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 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
333 MMX_CALL( MMX_YUV422_YVYU
);
336 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
338 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
340 p_y
+= i_source_margin
;
341 p_u
+= i_source_margin_c
;
342 p_v
+= i_source_margin_c
;
343 p_line
+= i_dest_margin
;
345 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
352 /*****************************************************************************
353 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
354 *****************************************************************************/
356 static void I422_UYVY( filter_t
*p_filter
, picture_t
*p_source
,
359 uint8_t *p_line
= p_dest
->p
->p_pixels
;
360 uint8_t *p_y
= p_source
->Y_PIXELS
;
361 uint8_t *p_u
= p_source
->U_PIXELS
;
362 uint8_t *p_v
= p_source
->V_PIXELS
;
366 const int i_source_margin
= p_source
->p
[0].i_pitch
367 - p_source
->p
[0].i_visible_pitch
368 - p_filter
->fmt_in
.video
.i_x_offset
;
369 const int i_source_margin_c
= p_source
->p
[1].i_pitch
370 - p_source
->p
[1].i_visible_pitch
371 - ( p_filter
->fmt_in
.video
.i_x_offset
);
372 const int i_dest_margin
= p_dest
->p
->i_pitch
373 - p_dest
->p
->i_visible_pitch
374 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
376 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
378 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
379 ((intptr_t)p_line
|(intptr_t)p_y
))) )
381 /* use faster SSE2 aligned fetch and store */
382 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
384 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
386 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED
);
388 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
390 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
392 p_y
+= i_source_margin
;
393 p_u
+= i_source_margin_c
;
394 p_v
+= i_source_margin_c
;
395 p_line
+= i_dest_margin
;
399 /* use slower SSE2 unaligned fetch and store */
400 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
402 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
404 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED
);
406 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
408 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
410 p_y
+= i_source_margin
;
411 p_u
+= i_source_margin_c
;
412 p_v
+= i_source_margin_c
;
413 p_line
+= i_dest_margin
;
420 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
422 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
424 #if defined (MODULE_NAME_IS_i422_yuy2)
425 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
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 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
430 MMX_CALL( MMX_YUV422_UYVY
);
433 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
435 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
437 p_y
+= i_source_margin
;
438 p_u
+= i_source_margin_c
;
439 p_v
+= i_source_margin_c
;
440 p_line
+= i_dest_margin
;
442 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
449 /*****************************************************************************
450 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
451 *****************************************************************************/
452 static void I422_IUYV( filter_t
*p_filter
, picture_t
*p_source
,
455 VLC_UNUSED(p_source
); VLC_UNUSED(p_dest
);
457 msg_Err( p_filter
, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
460 /*****************************************************************************
461 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
462 *****************************************************************************/
463 #if defined (MODULE_NAME_IS_i422_yuy2)
464 static void I422_Y211( filter_t
*p_filter
, picture_t
*p_source
,
467 uint8_t *p_line
= p_dest
->p
->p_pixels
+ p_dest
->p
->i_visible_lines
* p_dest
->p
->i_pitch
;
468 uint8_t *p_y
= p_source
->Y_PIXELS
;
469 uint8_t *p_u
= p_source
->U_PIXELS
;
470 uint8_t *p_v
= p_source
->V_PIXELS
;
474 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
476 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
478 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);
479 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);