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 #include "i420_rgb.h"
00034 #if defined (MODULE_NAME_IS_i420_rgb)
00035 # include "i420_rgb_c.h"
00036 #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
00037 # if defined(HAVE_MMX_INTRINSICS)
00038 # include <mmintrin.h>
00039 # endif
00040 # include "i420_rgb_mmx.h"
00041 #endif
00042
00043 static void SetOffset( int, int, int, int, vlc_bool_t *,
00044 unsigned int *, int * );
00045
00046 #if defined (MODULE_NAME_IS_i420_rgb)
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057 void E_(I420_RGB16_dithering)( vout_thread_t *p_vout, picture_t *p_src,
00058 picture_t *p_dest )
00059 {
00060
00061 uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
00062 uint8_t *p_y = p_src->Y_PIXELS;
00063 uint8_t *p_u = p_src->U_PIXELS;
00064 uint8_t *p_v = p_src->V_PIXELS;
00065
00066 vlc_bool_t b_hscale;
00067 unsigned int i_vscale;
00068 unsigned int i_x, i_y;
00069 unsigned int i_real_y;
00070
00071 int i_right_margin;
00072 int i_rewind;
00073 int i_scale_count;
00074 int i_chroma_width = p_vout->render.i_width / 2;
00075 uint16_t * p_pic_start;
00076 int i_uval, i_vval;
00077 int i_red, i_green, i_blue;
00078 uint16_t * p_yuv = p_vout->chroma.p_sys->p_rgb16;
00079 uint16_t * p_ybase;
00080
00081
00082 uint16_t * p_buffer_start = (uint16_t*)p_vout->chroma.p_sys->p_buffer;
00083 uint16_t * p_buffer;
00084
00085
00086 int * p_offset_start = p_vout->chroma.p_sys->p_offset;
00087 int * p_offset;
00088
00089 const int i_source_margin = p_src->p[0].i_pitch
00090 - p_src->p[0].i_visible_pitch;
00091 const int i_source_margin_c = p_src->p[1].i_pitch
00092 - p_src->p[1].i_visible_pitch;
00093
00094
00095 int dither10[4] = { 0x0, 0x8, 0x2, 0xa };
00096 int dither11[4] = { 0xc, 0x4, 0xe, 0x6 };
00097 int dither12[4] = { 0x3, 0xb, 0x1, 0x9 };
00098 int dither13[4] = { 0xf, 0x7, 0xd, 0x5 };
00099
00100 for(i_x = 0; i_x < 4; i_x++)
00101 {
00102 dither10[i_x] = dither10[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
00103 dither11[i_x] = dither11[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
00104 dither12[i_x] = dither12[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
00105 dither13[i_x] = dither13[i_x] << (SHIFT - 4 + p_vout->output.i_rrshift);
00106 }
00107
00108 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
00109
00110 if( p_vout->render.i_width & 7 )
00111 {
00112 i_rewind = 8 - ( p_vout->render.i_width & 7 );
00113 }
00114 else
00115 {
00116 i_rewind = 0;
00117 }
00118
00119
00120
00121
00122 SetOffset( p_vout->render.i_width, p_vout->render.i_height,
00123 p_vout->output.i_width, p_vout->output.i_height,
00124 &b_hscale, &i_vscale, p_offset_start );
00125
00126
00127
00128
00129 i_scale_count = ( i_vscale == 1 ) ?
00130 p_vout->output.i_height : p_vout->render.i_height;
00131 for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
00132 {
00133 i_real_y = i_y & 0x3;
00134 p_pic_start = p_pic;
00135 p_buffer = b_hscale ? p_buffer_start : p_pic;
00136
00137 for ( i_x = p_vout->render.i_width / 8; i_x--; )
00138 {
00139 int *p_dither = dither10;
00140 CONVERT_YUV_PIXEL_DITHER(2);
00141 p_dither = dither11;
00142 CONVERT_Y_PIXEL_DITHER(2);
00143 p_dither = dither12;
00144 CONVERT_YUV_PIXEL_DITHER(2);
00145 p_dither = dither13;
00146 CONVERT_Y_PIXEL_DITHER(2);
00147 p_dither = dither10;
00148 CONVERT_YUV_PIXEL_DITHER(2);
00149 p_dither = dither11;
00150 CONVERT_Y_PIXEL_DITHER(2);
00151 p_dither = dither12;
00152 CONVERT_YUV_PIXEL_DITHER(2);
00153 p_dither = dither13;
00154 CONVERT_Y_PIXEL_DITHER(2);
00155 }
00156
00157
00158
00159 if( i_rewind )
00160 {
00161 int *p_dither = dither10;
00162 p_y -= i_rewind;
00163 p_u -= i_rewind >> 1;
00164 p_v -= i_rewind >> 1;
00165 p_buffer -= i_rewind;
00166 CONVERT_YUV_PIXEL_DITHER(2);
00167 p_dither = dither11;
00168 CONVERT_Y_PIXEL_DITHER(2);
00169 p_dither = dither12;
00170 CONVERT_YUV_PIXEL_DITHER(2);
00171 p_dither = dither13;
00172 CONVERT_Y_PIXEL_DITHER(2);
00173 p_dither = dither10;
00174 CONVERT_YUV_PIXEL_DITHER(2);
00175 p_dither = dither11;
00176 CONVERT_Y_PIXEL_DITHER(2);
00177 p_dither = dither12;
00178 CONVERT_YUV_PIXEL_DITHER(2);
00179 p_dither = dither13;
00180 CONVERT_Y_PIXEL_DITHER(2);
00181 }
00182 SCALE_WIDTH;
00183 SCALE_HEIGHT( 420, 2 );
00184
00185 p_y += i_source_margin;
00186 if( i_y % 2 )
00187 {
00188 p_u += i_source_margin_c;
00189 p_v += i_source_margin_c;
00190 }
00191 }
00192 }
00193 #endif
00194
00195
00196
00197
00198
00199
00200
00201
00202
00203
00204
00205 void E_(I420_RGB16)( vout_thread_t *p_vout, picture_t *p_src,
00206 picture_t *p_dest )
00207 {
00208
00209 uint16_t *p_pic = (uint16_t*)p_dest->p->p_pixels;
00210 uint8_t *p_y = p_src->Y_PIXELS;
00211 uint8_t *p_u = p_src->U_PIXELS;
00212 uint8_t *p_v = p_src->V_PIXELS;
00213
00214 vlc_bool_t b_hscale;
00215 unsigned int i_vscale;
00216 unsigned int i_x, i_y;
00217
00218 int i_right_margin;
00219 int i_rewind;
00220 int i_scale_count;
00221 int i_chroma_width = p_vout->render.i_width / 2;
00222 uint16_t * p_pic_start;
00223 #if defined (MODULE_NAME_IS_i420_rgb)
00224 int i_uval, i_vval;
00225 int i_red, i_green, i_blue;
00226 uint16_t * p_yuv = p_vout->chroma.p_sys->p_rgb16;
00227 uint16_t * p_ybase;
00228 #endif
00229
00230
00231 uint16_t * p_buffer_start = (uint16_t*)p_vout->chroma.p_sys->p_buffer;
00232 uint16_t * p_buffer;
00233
00234
00235 int * p_offset_start = p_vout->chroma.p_sys->p_offset;
00236 int * p_offset;
00237
00238 const int i_source_margin = p_src->p[0].i_pitch
00239 - p_src->p[0].i_visible_pitch;
00240 const int i_source_margin_c = p_src->p[1].i_pitch
00241 - p_src->p[1].i_visible_pitch;
00242
00243 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
00244
00245 if( p_vout->render.i_width & 7 )
00246 {
00247 i_rewind = 8 - ( p_vout->render.i_width & 7 );
00248 }
00249 else
00250 {
00251 i_rewind = 0;
00252 }
00253
00254
00255
00256
00257 SetOffset( p_vout->render.i_width, p_vout->render.i_height,
00258 p_vout->output.i_width, p_vout->output.i_height,
00259 &b_hscale, &i_vscale, p_offset_start );
00260
00261
00262
00263
00264 i_scale_count = ( i_vscale == 1 ) ?
00265 p_vout->output.i_height : p_vout->render.i_height;
00266 for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
00267 {
00268 p_pic_start = p_pic;
00269 p_buffer = b_hscale ? p_buffer_start : p_pic;
00270
00271 #if defined (MODULE_NAME_IS_i420_rgb)
00272 for ( i_x = p_vout->render.i_width / 8; i_x--; )
00273 {
00274 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00275 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00276 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00277 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00278 }
00279 #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
00280 if( p_vout->output.i_rmask == 0x7c00 )
00281 {
00282
00283 for ( i_x = p_vout->render.i_width / 8; i_x--; )
00284 {
00285 # if defined (HAVE_MMX_INTRINSICS)
00286 __m64 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
00287 uint64_t tmp64;
00288 INTRINSICS_INIT_16
00289 INTRINSICS_YUV_MUL
00290 INTRINSICS_YUV_ADD
00291 INTRINSICS_UNPACK_15
00292 # else
00293 __asm__( MMX_INIT_16
00294 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00295
00296 __asm__( ".align 8"
00297 MMX_YUV_MUL
00298 MMX_YUV_ADD
00299 MMX_UNPACK_15
00300 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00301 # endif
00302
00303 p_y += 8;
00304 p_u += 4;
00305 p_v += 4;
00306 p_buffer += 8;
00307 }
00308 }
00309 else
00310 {
00311
00312 for ( i_x = p_vout->render.i_width / 8; i_x--; )
00313 {
00314 # if defined (HAVE_MMX_INTRINSICS)
00315 __m64 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
00316 uint64_t tmp64;
00317 INTRINSICS_INIT_16
00318 INTRINSICS_YUV_MUL
00319 INTRINSICS_YUV_ADD
00320 INTRINSICS_UNPACK_16
00321 # else
00322 __asm__( MMX_INIT_16
00323 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00324
00325 __asm__( ".align 8"
00326 MMX_YUV_MUL
00327 MMX_YUV_ADD
00328 MMX_UNPACK_16
00329 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00330 # endif
00331
00332 p_y += 8;
00333 p_u += 4;
00334 p_v += 4;
00335 p_buffer += 8;
00336 }
00337 }
00338 #endif
00339
00340
00341
00342 if( i_rewind )
00343 {
00344 #if defined (MODULE_NAME_IS_i420_rgb_mmx)
00345 # if defined (HAVE_MMX_INTRINSICS)
00346 __m64 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
00347 uint64_t tmp64;
00348 # endif
00349 #endif
00350 p_y -= i_rewind;
00351 p_u -= i_rewind >> 1;
00352 p_v -= i_rewind >> 1;
00353 p_buffer -= i_rewind;
00354 #if defined (MODULE_NAME_IS_i420_rgb)
00355 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00356 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00357 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00358 CONVERT_YUV_PIXEL(2); CONVERT_Y_PIXEL(2);
00359 #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
00360
00361 # if defined (HAVE_MMX_INTRINSICS)
00362 INTRINSICS_INIT_16
00363 # else
00364 __asm__( MMX_INIT_16
00365 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00366 # endif
00367
00368 if( p_vout->output.i_rmask == 0x7c00 )
00369 {
00370
00371 # if defined (HAVE_MMX_INTRINSICS)
00372 INTRINSICS_YUV_MUL
00373 INTRINSICS_YUV_ADD
00374 INTRINSICS_UNPACK_15
00375 # else
00376 __asm__( ".align 8"
00377 MMX_YUV_MUL
00378 MMX_YUV_ADD
00379 MMX_UNPACK_15
00380 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00381 # endif
00382 }
00383 else
00384 {
00385 # if defined (HAVE_MMX_INTRINSICS)
00386 INTRINSICS_YUV_MUL
00387 INTRINSICS_YUV_ADD
00388 INTRINSICS_UNPACK_16
00389 # else
00390
00391 __asm__( ".align 8"
00392 MMX_YUV_MUL
00393 MMX_YUV_ADD
00394 MMX_UNPACK_16
00395 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00396 # endif
00397 }
00398
00399 p_y += 8;
00400 p_u += 4;
00401 p_v += 4;
00402 p_buffer += 8;
00403 #endif
00404 }
00405 SCALE_WIDTH;
00406 SCALE_HEIGHT( 420, 2 );
00407
00408 p_y += i_source_margin;
00409 if( i_y % 2 )
00410 {
00411 p_u += i_source_margin_c;
00412 p_v += i_source_margin_c;
00413 }
00414 }
00415 }
00416
00417
00418
00419
00420
00421
00422
00423
00424
00425
00426
00427 void E_(I420_RGB32)( vout_thread_t *p_vout, picture_t *p_src,
00428 picture_t *p_dest )
00429 {
00430
00431 uint32_t *p_pic = (uint32_t*)p_dest->p->p_pixels;
00432 uint8_t *p_y = p_src->Y_PIXELS;
00433 uint8_t *p_u = p_src->U_PIXELS;
00434 uint8_t *p_v = p_src->V_PIXELS;
00435
00436 vlc_bool_t b_hscale;
00437 unsigned int i_vscale;
00438 unsigned int i_x, i_y;
00439
00440 int i_right_margin;
00441 int i_rewind;
00442 int i_scale_count;
00443 int i_chroma_width = p_vout->render.i_width / 2;
00444 uint32_t * p_pic_start;
00445 #if defined (MODULE_NAME_IS_i420_rgb)
00446 int i_uval, i_vval;
00447 int i_red, i_green, i_blue;
00448 uint32_t * p_yuv = p_vout->chroma.p_sys->p_rgb32;
00449 uint32_t * p_ybase;
00450 #endif
00451
00452
00453 uint32_t * p_buffer_start = (uint32_t*)p_vout->chroma.p_sys->p_buffer;
00454 uint32_t * p_buffer;
00455
00456
00457 int * p_offset_start = p_vout->chroma.p_sys->p_offset;
00458 int * p_offset;
00459
00460 const int i_source_margin = p_src->p[0].i_pitch
00461 - p_src->p[0].i_visible_pitch;
00462 const int i_source_margin_c = p_src->p[1].i_pitch
00463 - p_src->p[1].i_visible_pitch;
00464
00465 i_right_margin = p_dest->p->i_pitch - p_dest->p->i_visible_pitch;
00466
00467 if( p_vout->render.i_width & 7 )
00468 {
00469 i_rewind = 8 - ( p_vout->render.i_width & 7 );
00470 }
00471 else
00472 {
00473 i_rewind = 0;
00474 }
00475
00476
00477
00478
00479 SetOffset( p_vout->render.i_width, p_vout->render.i_height,
00480 p_vout->output.i_width, p_vout->output.i_height,
00481 &b_hscale, &i_vscale, p_offset_start );
00482
00483
00484
00485
00486 i_scale_count = ( i_vscale == 1 ) ?
00487 p_vout->output.i_height : p_vout->render.i_height;
00488 for( i_y = 0; i_y < p_vout->render.i_height; i_y++ )
00489 {
00490 p_pic_start = p_pic;
00491 p_buffer = b_hscale ? p_buffer_start : p_pic;
00492
00493 for ( i_x = p_vout->render.i_width / 8; i_x--; )
00494 {
00495 #if defined (MODULE_NAME_IS_i420_rgb)
00496 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00497 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00498 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00499 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00500 #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
00501 # if defined (HAVE_MMX_INTRINSICS)
00502 __m64 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
00503 uint64_t tmp64;
00504 INTRINSICS_INIT_32
00505 INTRINSICS_YUV_MUL
00506 INTRINSICS_YUV_ADD
00507 INTRINSICS_UNPACK_32
00508 # else
00509 __asm__( MMX_INIT_32
00510 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00511
00512 __asm__( ".align 8"
00513 MMX_YUV_MUL
00514 MMX_YUV_ADD
00515 MMX_UNPACK_32
00516 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00517 # endif
00518
00519 p_y += 8;
00520 p_u += 4;
00521 p_v += 4;
00522 p_buffer += 8;
00523 #endif
00524 }
00525
00526
00527
00528 if( i_rewind )
00529 {
00530 #if defined (MODULE_NAME_IS_i420_rgb_mmx)
00531 # if defined (HAVE_MMX_INTRINSICS)
00532 __m64 mm0, mm1, mm2, mm3, mm4, mm5, mm6, mm7;
00533 uint64_t tmp64;
00534 # endif
00535 #endif
00536 p_y -= i_rewind;
00537 p_u -= i_rewind >> 1;
00538 p_v -= i_rewind >> 1;
00539 p_buffer -= i_rewind;
00540 #if defined (MODULE_NAME_IS_i420_rgb)
00541 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00542 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00543 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00544 CONVERT_YUV_PIXEL(4); CONVERT_Y_PIXEL(4);
00545 #elif defined (MODULE_NAME_IS_i420_rgb_mmx)
00546 # if defined (HAVE_MMX_INTRINSICS)
00547 INTRINSICS_INIT_32
00548 INTRINSICS_YUV_MUL
00549 INTRINSICS_YUV_ADD
00550 INTRINSICS_UNPACK_32
00551 # else
00552 __asm__( MMX_INIT_32
00553 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00554
00555 __asm__( ".align 8"
00556 MMX_YUV_MUL
00557 MMX_YUV_ADD
00558 MMX_UNPACK_32
00559 : : "r" (p_y), "r" (p_u), "r" (p_v), "r" (p_buffer) );
00560 # endif
00561
00562 p_y += 8;
00563 p_u += 4;
00564 p_v += 4;
00565 p_buffer += 8;
00566 #endif
00567 }
00568 SCALE_WIDTH;
00569 SCALE_HEIGHT( 420, 4 );
00570
00571 p_y += i_source_margin;
00572 if( i_y % 2 )
00573 {
00574 p_u += i_source_margin_c;
00575 p_v += i_source_margin_c;
00576 }
00577 }
00578 }
00579
00580
00581
00582
00583
00584
00585
00586
00587
00588 static void SetOffset( int i_width, int i_height, int i_pic_width,
00589 int i_pic_height, vlc_bool_t *pb_hscale,
00590 unsigned int *pi_vscale, int *p_offset )
00591 {
00592 int i_x;
00593 int i_scale_count;
00594
00595
00596
00597
00598 if( i_pic_width - i_width == 0 )
00599 {
00600
00601 *pb_hscale = 0;
00602 }
00603 else if( i_pic_width - i_width > 0 )
00604 {
00605
00606 *pb_hscale = 1;
00607 i_scale_count = i_pic_width;
00608 for( i_x = i_width; i_x--; )
00609 {
00610 while( (i_scale_count -= i_width) > 0 )
00611 {
00612 *p_offset++ = 0;
00613 }
00614 *p_offset++ = 1;
00615 i_scale_count += i_pic_width;
00616 }
00617 }
00618 else
00619 {
00620
00621 *pb_hscale = 1;
00622 i_scale_count = i_width;
00623 for( i_x = i_pic_width; i_x--; )
00624 {
00625 *p_offset = 1;
00626 while( (i_scale_count -= i_pic_width) > 0 )
00627 {
00628 *p_offset += 1;
00629 }
00630 p_offset++;
00631 i_scale_count += i_width;
00632 }
00633 }
00634
00635
00636
00637
00638 if( i_pic_height - i_height == 0 )
00639 {
00640 *pi_vscale = 0;
00641 }
00642 else if( i_pic_height - i_height > 0 )
00643 {
00644 *pi_vscale = 1;
00645 }
00646 else
00647 {
00648 *pi_vscale = -1;
00649 }
00650 }
00651