00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027 #include <string.h>
00028 #include <stdlib.h>
00029
00030 #include <vlc/vlc.h>
00031 #include <vlc/vout.h>
00032
00033 #if defined (MODULE_NAME_IS_i420_yuy2_altivec) && defined(HAVE_ALTIVEC_H)
00034 # include <altivec.h>
00035 #endif
00036
00037 #include "i420_yuy2.h"
00038
00039 #define SRC_FOURCC "I420,IYUV,YV12"
00040
00041 #if defined (MODULE_NAME_IS_i420_yuy2)
00042 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv,Y211"
00043 #elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
00044 # define DEST_FOURCC "YUY2,YUNV,YVYU,UYVY,UYNV,Y422,IUYV,cyuv"
00045 #elif defined (MODULE_NAME_IS_i420_yuy2_altivec)
00046 # define DEST_FOURCC "YUY2,YUNV"
00047 #endif
00048
00049
00050
00051
00052 static int Activate ( vlc_object_t * );
00053
00054 static void I420_YUY2 ( vout_thread_t *, picture_t *, picture_t * );
00055 #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
00056 static void I420_YVYU ( vout_thread_t *, picture_t *, picture_t * );
00057 static void I420_UYVY ( vout_thread_t *, picture_t *, picture_t * );
00058 static void I420_IUYV ( vout_thread_t *, picture_t *, picture_t * );
00059 static void I420_cyuv ( vout_thread_t *, picture_t *, picture_t * );
00060 #endif
00061 #if defined (MODULE_NAME_IS_i420_yuy2)
00062 static void I420_Y211 ( vout_thread_t *, picture_t *, picture_t * );
00063 #endif
00064
00065 #ifdef MODULE_NAME_IS_i420_yuy2_mmx
00066 static uint64_t i_00ffw;
00067 static uint64_t i_80w;
00068 #endif
00069
00070
00071
00072
00073 vlc_module_begin();
00074 #if defined (MODULE_NAME_IS_i420_yuy2)
00075 set_description( _("Conversions from " SRC_FOURCC " to " DEST_FOURCC) );
00076 set_capability( "chroma", 80 );
00077 #elif defined (MODULE_NAME_IS_i420_yuy2_mmx)
00078 set_description( _("MMX conversions from " SRC_FOURCC " to " DEST_FOURCC) );
00079 set_capability( "chroma", 100 );
00080 add_requirement( MMX );
00081
00082 i_00ffw = 0x00ff00ff00ff00ffULL;
00083 i_80w = 0x0000000080808080ULL;
00084 #elif defined (MODULE_NAME_IS_i420_yuy2_altivec)
00085 set_description(
00086 _("AltiVec conversions from " SRC_FOURCC " to " DEST_FOURCC) );
00087 set_capability( "chroma", 100 );
00088 add_requirement( ALTIVEC );
00089 #endif
00090 set_callbacks( Activate, NULL );
00091 vlc_module_end();
00092
00093
00094
00095
00096
00097
00098 static int Activate( vlc_object_t *p_this )
00099 {
00100 vout_thread_t *p_vout = (vout_thread_t *)p_this;
00101
00102 if( p_vout->render.i_width & 1 || p_vout->render.i_height & 1 )
00103 {
00104 return -1;
00105 }
00106
00107 switch( p_vout->render.i_chroma )
00108 {
00109 case VLC_FOURCC('Y','V','1','2'):
00110 case VLC_FOURCC('I','4','2','0'):
00111 case VLC_FOURCC('I','Y','U','V'):
00112 switch( p_vout->output.i_chroma )
00113 {
00114 case VLC_FOURCC('Y','U','Y','2'):
00115 case VLC_FOURCC('Y','U','N','V'):
00116 p_vout->chroma.pf_convert = I420_YUY2;
00117 break;
00118
00119 #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
00120 case VLC_FOURCC('Y','V','Y','U'):
00121 p_vout->chroma.pf_convert = I420_YVYU;
00122 break;
00123
00124 case VLC_FOURCC('U','Y','V','Y'):
00125 case VLC_FOURCC('U','Y','N','V'):
00126 case VLC_FOURCC('Y','4','2','2'):
00127 p_vout->chroma.pf_convert = I420_UYVY;
00128 break;
00129
00130 case VLC_FOURCC('I','U','Y','V'):
00131 p_vout->chroma.pf_convert = I420_IUYV;
00132 break;
00133
00134 case VLC_FOURCC('c','y','u','v'):
00135 p_vout->chroma.pf_convert = I420_cyuv;
00136 break;
00137 #endif
00138
00139 #if defined (MODULE_NAME_IS_i420_yuy2)
00140 case VLC_FOURCC('Y','2','1','1'):
00141 p_vout->chroma.pf_convert = I420_Y211;
00142 break;
00143 #endif
00144
00145 default:
00146 return -1;
00147 }
00148 break;
00149
00150 default:
00151 return -1;
00152 }
00153
00154 return 0;
00155 }
00156
00157
00158
00159
00160
00161
00162 static void I420_YUY2( vout_thread_t *p_vout, picture_t *p_source,
00163 picture_t *p_dest )
00164 {
00165 uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
00166 uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
00167 uint8_t *p_u = p_source->U_PIXELS;
00168 uint8_t *p_v = p_source->V_PIXELS;
00169
00170 int i_x, i_y;
00171
00172 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
00173 #define VEC_NEXT_LINES( ) \
00174 p_line1 = p_line2; \
00175 p_line2 += p_dest->p->i_pitch; \
00176 p_y1 = p_y2; \
00177 p_y2 += p_source->p[Y_PLANE].i_pitch;
00178
00179 #define VEC_LOAD_UV( ) \
00180 u_vec = vec_ld( 0, p_u ); p_u += 16; \
00181 v_vec = vec_ld( 0, p_v ); p_v += 16;
00182
00183 #define VEC_MERGE( a ) \
00184 uv_vec = a( u_vec, v_vec ); \
00185 y_vec = vec_ld( 0, p_y1 ); p_y1 += 16; \
00186 vec_st( vec_mergeh( y_vec, uv_vec ), 0, p_line1 ); p_line1 += 16; \
00187 vec_st( vec_mergel( y_vec, uv_vec ), 0, p_line1 ); p_line1 += 16; \
00188 y_vec = vec_ld( 0, p_y2 ); p_y2 += 16; \
00189 vec_st( vec_mergeh( y_vec, uv_vec ), 0, p_line2 ); p_line2 += 16; \
00190 vec_st( vec_mergel( y_vec, uv_vec ), 0, p_line2 ); p_line2 += 16;
00191
00192 vector unsigned char u_vec;
00193 vector unsigned char v_vec;
00194 vector unsigned char uv_vec;
00195 vector unsigned char y_vec;
00196
00197 if( !( ( p_vout->render.i_width % 32 ) |
00198 ( p_vout->render.i_height % 2 ) ) )
00199 {
00200
00201 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
00202 {
00203 VEC_NEXT_LINES( );
00204 for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
00205 {
00206 VEC_LOAD_UV( );
00207 VEC_MERGE( vec_mergeh );
00208 VEC_MERGE( vec_mergel );
00209 }
00210 }
00211 }
00212 else if( !( ( p_vout->render.i_width % 16 ) |
00213 ( p_vout->render.i_height % 4 ) ) )
00214 {
00215
00216 for( i_y = p_vout->render.i_height / 4 ; i_y-- ; )
00217 {
00218
00219 VEC_NEXT_LINES( );
00220 for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
00221 {
00222 VEC_LOAD_UV( );
00223 VEC_MERGE( vec_mergeh );
00224 VEC_MERGE( vec_mergel );
00225 }
00226
00227
00228 VEC_LOAD_UV( );
00229 VEC_MERGE( vec_mergeh );
00230
00231
00232 VEC_NEXT_LINES( );
00233 VEC_MERGE( vec_mergel );
00234
00235
00236 for( i_x = p_vout->render.i_width / 32 ; i_x-- ; )
00237 {
00238 VEC_LOAD_UV( );
00239 VEC_MERGE( vec_mergeh );
00240 VEC_MERGE( vec_mergel );
00241 }
00242 }
00243 }
00244 else
00245 {
00246
00247 #undef VEC_NEXT_LINES
00248 #undef VEC_LOAD_UV
00249 #undef VEC_MERGE
00250 #endif
00251
00252 const int i_source_margin = p_source->p[0].i_pitch
00253 - p_source->p[0].i_visible_pitch;
00254 const int i_source_margin_c = p_source->p[1].i_pitch
00255 - p_source->p[1].i_visible_pitch;
00256 const int i_dest_margin = p_dest->p->i_pitch
00257 - p_dest->p->i_visible_pitch;
00258
00259 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
00260 {
00261 p_line1 = p_line2;
00262 p_line2 += p_dest->p->i_pitch;
00263
00264 p_y1 = p_y2;
00265 p_y2 += p_source->p[Y_PLANE].i_pitch;
00266
00267 #if !defined (MODULE_NAME_IS_i420_yuy2_mmx)
00268 for( i_x = p_vout->render.i_width / 2 ; i_x-- ; )
00269 {
00270 C_YUV420_YUYV( );
00271 }
00272 #else
00273 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
00274 {
00275 MMX_CALL( MMX_YUV420_YUYV );
00276 }
00277 for( i_x = ( p_vout->render.i_width % 8 ) / 2; i_x-- ; )
00278 {
00279 C_YUV420_YUYV( );
00280 }
00281 #endif
00282
00283 p_y1 += i_source_margin;
00284 p_y2 += i_source_margin;
00285 p_u += i_source_margin_c;
00286 p_v += i_source_margin_c;
00287 p_line1 += i_dest_margin;
00288 p_line2 += i_dest_margin;
00289 }
00290
00291 #if defined (MODULE_NAME_IS_i420_yuy2_altivec)
00292 }
00293 #endif
00294 }
00295
00296
00297
00298
00299 #if !defined (MODULE_NAME_IS_i420_yuy2_altivec)
00300 static void I420_YVYU( vout_thread_t *p_vout, picture_t *p_source,
00301 picture_t *p_dest )
00302 {
00303 uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
00304 uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
00305 uint8_t *p_u = p_source->U_PIXELS;
00306 uint8_t *p_v = p_source->V_PIXELS;
00307
00308 int i_x, i_y;
00309
00310 const int i_source_margin = p_source->p[0].i_pitch
00311 - p_source->p[0].i_visible_pitch;
00312 const int i_source_margin_c = p_source->p[1].i_pitch
00313 - p_source->p[1].i_visible_pitch;
00314 const int i_dest_margin = p_dest->p->i_pitch
00315 - p_dest->p->i_visible_pitch;
00316
00317 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
00318 {
00319 p_line1 = p_line2;
00320 p_line2 += p_dest->p->i_pitch;
00321
00322 p_y1 = p_y2;
00323 p_y2 += p_source->p[Y_PLANE].i_pitch;
00324
00325 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
00326 {
00327 #if defined (MODULE_NAME_IS_i420_yuy2)
00328 C_YUV420_YVYU( );
00329 C_YUV420_YVYU( );
00330 C_YUV420_YVYU( );
00331 C_YUV420_YVYU( );
00332 #else
00333 MMX_CALL( MMX_YUV420_YVYU );
00334 #endif
00335 }
00336
00337 p_y1 += i_source_margin;
00338 p_y2 += i_source_margin;
00339 p_u += i_source_margin_c;
00340 p_v += i_source_margin_c;
00341 p_line1 += i_dest_margin;
00342 p_line2 += i_dest_margin;
00343 }
00344 }
00345
00346
00347
00348
00349 static void I420_UYVY( vout_thread_t *p_vout, picture_t *p_source,
00350 picture_t *p_dest )
00351 {
00352 uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
00353 uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
00354 uint8_t *p_u = p_source->U_PIXELS;
00355 uint8_t *p_v = p_source->V_PIXELS;
00356
00357 int i_x, i_y;
00358
00359 const int i_source_margin = p_source->p[0].i_pitch
00360 - p_source->p[0].i_visible_pitch;
00361 const int i_source_margin_c = p_source->p[1].i_pitch
00362 - p_source->p[1].i_visible_pitch;
00363 const int i_dest_margin = p_dest->p->i_pitch
00364 - p_dest->p->i_visible_pitch;
00365
00366 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
00367 {
00368 p_line1 = p_line2;
00369 p_line2 += p_dest->p->i_pitch;
00370
00371 p_y1 = p_y2;
00372 p_y2 += p_source->p[Y_PLANE].i_pitch;
00373
00374 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
00375 {
00376 #if defined (MODULE_NAME_IS_i420_yuy2)
00377 C_YUV420_UYVY( );
00378 C_YUV420_UYVY( );
00379 C_YUV420_UYVY( );
00380 C_YUV420_UYVY( );
00381 #else
00382 MMX_CALL( MMX_YUV420_UYVY );
00383 #endif
00384 }
00385
00386 p_y1 += i_source_margin;
00387 p_y2 += i_source_margin;
00388 p_u += i_source_margin_c;
00389 p_v += i_source_margin_c;
00390 p_line1 += i_dest_margin;
00391 p_line2 += i_dest_margin;
00392 }
00393 }
00394
00395
00396
00397
00398 static void I420_IUYV( vout_thread_t *p_vout, picture_t *p_source,
00399 picture_t *p_dest )
00400 {
00401
00402 msg_Err( p_vout, "I420_IUYV unimplemented, please harass <[email protected]>" );
00403 }
00404
00405
00406
00407
00408 static void I420_cyuv( vout_thread_t *p_vout, picture_t *p_source,
00409 picture_t *p_dest )
00410 {
00411 uint8_t *p_line1 = p_dest->p->p_pixels +
00412 p_dest->p->i_visible_lines * p_dest->p->i_pitch
00413 + p_dest->p->i_pitch;
00414 uint8_t *p_line2 = p_dest->p->p_pixels +
00415 p_dest->p->i_visible_lines * p_dest->p->i_pitch;
00416 uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
00417 uint8_t *p_u = p_source->U_PIXELS;
00418 uint8_t *p_v = p_source->V_PIXELS;
00419
00420 int i_x, i_y;
00421
00422 const int i_source_margin = p_source->p[0].i_pitch
00423 - p_source->p[0].i_visible_pitch;
00424 const int i_source_margin_c = p_source->p[1].i_pitch
00425 - p_source->p[1].i_visible_pitch;
00426 const int i_dest_margin = p_dest->p->i_pitch
00427 - p_dest->p->i_visible_pitch;
00428
00429 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
00430 {
00431 p_line1 -= 3 * p_dest->p->i_pitch;
00432 p_line2 -= 3 * p_dest->p->i_pitch;
00433
00434 p_y1 = p_y2;
00435 p_y2 += p_source->p[Y_PLANE].i_pitch;
00436
00437 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
00438 {
00439 #if defined (MODULE_NAME_IS_i420_yuy2)
00440 C_YUV420_UYVY( );
00441 C_YUV420_UYVY( );
00442 C_YUV420_UYVY( );
00443 C_YUV420_UYVY( );
00444 #else
00445 MMX_CALL( MMX_YUV420_UYVY );
00446 #endif
00447 }
00448
00449 p_y1 += i_source_margin;
00450 p_y2 += i_source_margin;
00451 p_u += i_source_margin_c;
00452 p_v += i_source_margin_c;
00453 p_line1 += i_dest_margin;
00454 p_line2 += i_dest_margin;
00455 }
00456 }
00457 #endif // !defined (MODULE_NAME_IS_i420_yuy2_altivec)
00458
00459
00460
00461
00462 #if defined (MODULE_NAME_IS_i420_yuy2)
00463 static void I420_Y211( vout_thread_t *p_vout, picture_t *p_source,
00464 picture_t *p_dest )
00465 {
00466 uint8_t *p_line1, *p_line2 = p_dest->p->p_pixels;
00467 uint8_t *p_y1, *p_y2 = p_source->Y_PIXELS;
00468 uint8_t *p_u = p_source->U_PIXELS;
00469 uint8_t *p_v = p_source->V_PIXELS;
00470
00471 int i_x, i_y;
00472
00473 const int i_source_margin = p_source->p[0].i_pitch
00474 - p_source->p[0].i_visible_pitch;
00475 const int i_source_margin_c = p_source->p[1].i_pitch
00476 - p_source->p[1].i_visible_pitch;
00477 const int i_dest_margin = p_dest->p->i_pitch
00478 - p_dest->p->i_visible_pitch;
00479
00480 for( i_y = p_vout->render.i_height / 2 ; i_y-- ; )
00481 {
00482 p_line1 = p_line2;
00483 p_line2 += p_dest->p->i_pitch;
00484
00485 p_y1 = p_y2;
00486 p_y2 += p_source->p[Y_PLANE].i_pitch;
00487
00488 for( i_x = p_vout->render.i_width / 8 ; i_x-- ; )
00489 {
00490 C_YUV420_Y211( );
00491 C_YUV420_Y211( );
00492 }
00493
00494 p_y1 += i_source_margin;
00495 p_y2 += i_source_margin;
00496 p_u += i_source_margin_c;
00497 p_v += i_source_margin_c;
00498 p_line1 += i_dest_margin;
00499 p_line2 += i_dest_margin;
00500 }
00501 }
00502 #endif
00503