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>
36 #include <vlc_picture.h>
39 #include "i422_yuy2.h"
41 #define SRC_FOURCC "I422"
42 #if defined (MODULE_NAME_IS_i422_yuy2)
43 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,Y211"
45 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV"
48 /*****************************************************************************
49 * Local and extern prototypes.
50 *****************************************************************************/
51 static int Activate ( vlc_object_t
* );
53 static void I422_YUY2 ( filter_t
*, picture_t
*, picture_t
* );
54 static void I422_YVYU ( filter_t
*, picture_t
*, picture_t
* );
55 static void I422_UYVY ( filter_t
*, picture_t
*, picture_t
* );
56 static void I422_IUYV ( 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 #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 converter", 80 )
73 # define vlc_CPU_capable() (true)
75 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
76 set_description( N_("MMX conversions from " SRC_FOURCC
" to " DEST_FOURCC
) )
77 set_capability( "video converter", 100 )
78 # define vlc_CPU_capable() vlc_CPU_MMX()
79 # define VLC_TARGET VLC_MMX
80 #elif defined (MODULE_NAME_IS_i422_yuy2_sse2)
81 set_description( N_("SSE2 conversions from " SRC_FOURCC
" to " DEST_FOURCC
) )
82 set_capability( "video converter", 120 )
83 # define vlc_CPU_capable() vlc_CPU_SSE2()
84 # define VLC_TARGET VLC_SSE
86 set_callbacks( Activate
, NULL
)
89 /*****************************************************************************
90 * Activate: allocate a chroma function
91 *****************************************************************************
92 * This function allocates and initializes a chroma function
93 *****************************************************************************/
94 static int Activate( vlc_object_t
*p_this
)
96 filter_t
*p_filter
= (filter_t
*)p_this
;
98 if( !vlc_CPU_capable() )
100 if( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) & 1
101 || (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) & 1 )
106 if( p_filter
->fmt_in
.video
.orientation
!= p_filter
->fmt_out
.video
.orientation
)
111 switch( p_filter
->fmt_in
.video
.i_chroma
)
114 switch( p_filter
->fmt_out
.video
.i_chroma
)
117 p_filter
->pf_video_filter
= I422_YUY2_Filter
;
121 p_filter
->pf_video_filter
= I422_YVYU_Filter
;
125 p_filter
->pf_video_filter
= I422_UYVY_Filter
;
128 case VLC_FOURCC('I','U','Y','V'):
129 p_filter
->pf_video_filter
= I422_IUYV_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 #if defined (MODULE_NAME_IS_i422_yuy2)
156 VIDEO_FILTER_WRAPPER( I422_Y211
)
159 /*****************************************************************************
160 * I422_YUY2: planar YUV 4:2:2 to packed YUY2 4:2:2
161 *****************************************************************************/
163 static void I422_YUY2( filter_t
*p_filter
, picture_t
*p_source
,
166 uint8_t *p_line
= p_dest
->p
->p_pixels
;
167 uint8_t *p_y
= p_source
->Y_PIXELS
;
168 uint8_t *p_u
= p_source
->U_PIXELS
;
169 uint8_t *p_v
= p_source
->V_PIXELS
;
173 const int i_source_margin
= p_source
->p
[0].i_pitch
174 - p_source
->p
[0].i_visible_pitch
175 - p_filter
->fmt_in
.video
.i_x_offset
;
176 const int i_source_margin_c
= p_source
->p
[1].i_pitch
177 - p_source
->p
[1].i_visible_pitch
178 - ( p_filter
->fmt_in
.video
.i_x_offset
);
179 const int i_dest_margin
= p_dest
->p
->i_pitch
180 - p_dest
->p
->i_visible_pitch
181 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
183 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
185 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
186 ((intptr_t)p_line
|(intptr_t)p_y
))) )
188 /* use faster SSE2 aligned fetch and store */
189 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
191 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
193 SSE2_CALL( SSE2_YUV422_YUYV_ALIGNED
);
195 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
197 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
199 p_y
+= i_source_margin
;
200 p_u
+= i_source_margin_c
;
201 p_v
+= i_source_margin_c
;
202 p_line
+= i_dest_margin
;
206 /* use slower SSE2 unaligned fetch and store */
207 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
209 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
211 SSE2_CALL( SSE2_YUV422_YUYV_UNALIGNED
);
213 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
215 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
217 p_y
+= i_source_margin
;
218 p_u
+= i_source_margin_c
;
219 p_v
+= i_source_margin_c
;
220 p_line
+= i_dest_margin
;
227 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
229 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
231 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
236 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
237 MMX_CALL( MMX_YUV422_YUYV
);
240 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
242 C_YUV422_YUYV( p_line
, p_y
, p_u
, p_v
);
244 p_y
+= i_source_margin
;
245 p_u
+= i_source_margin_c
;
246 p_v
+= i_source_margin_c
;
247 p_line
+= i_dest_margin
;
249 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
256 /*****************************************************************************
257 * I422_YVYU: planar YUV 4:2:2 to packed YVYU 4:2:2
258 *****************************************************************************/
260 static void I422_YVYU( filter_t
*p_filter
, picture_t
*p_source
,
263 uint8_t *p_line
= p_dest
->p
->p_pixels
;
264 uint8_t *p_y
= p_source
->Y_PIXELS
;
265 uint8_t *p_u
= p_source
->U_PIXELS
;
266 uint8_t *p_v
= p_source
->V_PIXELS
;
270 const int i_source_margin
= p_source
->p
[0].i_pitch
271 - p_source
->p
[0].i_visible_pitch
272 - p_filter
->fmt_in
.video
.i_x_offset
;
273 const int i_source_margin_c
= p_source
->p
[1].i_pitch
274 - p_source
->p
[1].i_visible_pitch
275 - ( p_filter
->fmt_in
.video
.i_x_offset
);
276 const int i_dest_margin
= p_dest
->p
->i_pitch
277 - p_dest
->p
->i_visible_pitch
278 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
280 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
282 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
283 ((intptr_t)p_line
|(intptr_t)p_y
))) )
285 /* use faster SSE2 aligned fetch and store */
286 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
288 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
290 SSE2_CALL( SSE2_YUV422_YVYU_ALIGNED
);
292 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
294 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
296 p_y
+= i_source_margin
;
297 p_u
+= i_source_margin_c
;
298 p_v
+= i_source_margin_c
;
299 p_line
+= i_dest_margin
;
303 /* use slower SSE2 unaligned fetch and store */
304 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
306 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
308 SSE2_CALL( SSE2_YUV422_YVYU_UNALIGNED
);
310 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
312 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
314 p_y
+= i_source_margin
;
315 p_u
+= i_source_margin_c
;
316 p_v
+= i_source_margin_c
;
317 p_line
+= i_dest_margin
;
324 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
326 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
328 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
333 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
334 MMX_CALL( MMX_YUV422_YVYU
);
337 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
339 C_YUV422_YVYU( p_line
, p_y
, p_u
, p_v
);
341 p_y
+= i_source_margin
;
342 p_u
+= i_source_margin_c
;
343 p_v
+= i_source_margin_c
;
344 p_line
+= i_dest_margin
;
346 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
353 /*****************************************************************************
354 * I422_UYVY: planar YUV 4:2:2 to packed UYVY 4:2:2
355 *****************************************************************************/
357 static void I422_UYVY( filter_t
*p_filter
, picture_t
*p_source
,
360 uint8_t *p_line
= p_dest
->p
->p_pixels
;
361 uint8_t *p_y
= p_source
->Y_PIXELS
;
362 uint8_t *p_u
= p_source
->U_PIXELS
;
363 uint8_t *p_v
= p_source
->V_PIXELS
;
367 const int i_source_margin
= p_source
->p
[0].i_pitch
368 - p_source
->p
[0].i_visible_pitch
369 - p_filter
->fmt_in
.video
.i_x_offset
;
370 const int i_source_margin_c
= p_source
->p
[1].i_pitch
371 - p_source
->p
[1].i_visible_pitch
372 - ( p_filter
->fmt_in
.video
.i_x_offset
);
373 const int i_dest_margin
= p_dest
->p
->i_pitch
374 - p_dest
->p
->i_visible_pitch
375 - ( p_filter
->fmt_out
.video
.i_x_offset
* 2 );
377 #if defined (MODULE_NAME_IS_i422_yuy2_sse2)
379 if( 0 == (15 & (p_source
->p
[Y_PLANE
].i_pitch
|p_dest
->p
->i_pitch
|
380 ((intptr_t)p_line
|(intptr_t)p_y
))) )
382 /* use faster SSE2 aligned fetch and store */
383 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
385 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
387 SSE2_CALL( SSE2_YUV422_UYVY_ALIGNED
);
389 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
391 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
393 p_y
+= i_source_margin
;
394 p_u
+= i_source_margin_c
;
395 p_v
+= i_source_margin_c
;
396 p_line
+= i_dest_margin
;
400 /* use slower SSE2 unaligned fetch and store */
401 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
403 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 16 ; i_x
-- ; )
405 SSE2_CALL( SSE2_YUV422_UYVY_UNALIGNED
);
407 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 16 ) / 2; i_x
-- ; )
409 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
411 p_y
+= i_source_margin
;
412 p_u
+= i_source_margin_c
;
413 p_v
+= i_source_margin_c
;
414 p_line
+= i_dest_margin
;
421 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
423 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
425 #if defined (MODULE_NAME_IS_i422_yuy2)
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 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
430 #elif defined (MODULE_NAME_IS_i422_yuy2_mmx)
431 MMX_CALL( MMX_YUV422_UYVY
);
434 for( i_x
= ( (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) % 8 ) / 2; i_x
-- ; )
436 C_YUV422_UYVY( p_line
, p_y
, p_u
, p_v
);
438 p_y
+= i_source_margin
;
439 p_u
+= i_source_margin_c
;
440 p_v
+= i_source_margin_c
;
441 p_line
+= i_dest_margin
;
443 #if defined (MODULE_NAME_IS_i422_yuy2_mmx)
450 /*****************************************************************************
451 * I422_IUYV: planar YUV 4:2:2 to interleaved packed IUYV 4:2:2
452 *****************************************************************************/
453 static void I422_IUYV( filter_t
*p_filter
, picture_t
*p_source
,
456 VLC_UNUSED(p_source
); VLC_UNUSED(p_dest
);
458 msg_Err( p_filter
, "I422_IUYV unimplemented, please harass <sam@zoy.org>" );
461 /*****************************************************************************
462 * I422_Y211: planar YUV 4:2:2 to packed YUYV 2:1:1
463 *****************************************************************************/
464 #if defined (MODULE_NAME_IS_i422_yuy2)
465 static void I422_Y211( filter_t
*p_filter
, picture_t
*p_source
,
468 uint8_t *p_line
= p_dest
->p
->p_pixels
+ p_dest
->p
->i_visible_lines
* p_dest
->p
->i_pitch
;
469 uint8_t *p_y
= p_source
->Y_PIXELS
;
470 uint8_t *p_u
= p_source
->U_PIXELS
;
471 uint8_t *p_v
= p_source
->V_PIXELS
;
475 for( i_y
= (p_filter
->fmt_in
.video
.i_y_offset
+ p_filter
->fmt_in
.video
.i_visible_height
) ; i_y
-- ; )
477 for( i_x
= (p_filter
->fmt_in
.video
.i_x_offset
+ p_filter
->fmt_in
.video
.i_visible_width
) / 8 ; i_x
-- ; )
479 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);
480 C_YUV422_Y211( p_line
, p_y
, p_u
, p_v
);