Changeset 07d2f3edd5e3c3c64db6feac4c9e4317f470ccbe
- Timestamp:
- 20/08/08 23:23:19 (3 months ago)
- git-parent:
- Files:
-
- modules/video_filter/blend.c (modified) (41 diffs)
Legend:
- Unmodified
- Added
- Removed
- Modified
- Copied
- Moved
modules/video_filter/blend.c
rd750786 r07d2f3e 2 2 * blend.c: alpha blend 2 pictures together 3 3 ***************************************************************************** 4 * Copyright (C) 2003-200 7the VideoLAN team4 * Copyright (C) 2003-2008 the VideoLAN team 5 5 * $Id$ 6 6 * … … 30 30 #endif 31 31 32 #include <assert.h> 32 33 #include <vlc_common.h> 33 34 #include <vlc_plugin.h> … … 36 37 37 38 /***************************************************************************** 39 * Module descriptor 40 *****************************************************************************/ 41 static int OpenFilter ( vlc_object_t * ); 42 static void CloseFilter( vlc_object_t * ); 43 44 vlc_module_begin(); 45 set_description( N_("Video pictures blending") ); 46 set_capability( "video blending", 100 ); 47 set_callbacks( OpenFilter, CloseFilter ); 48 vlc_module_end(); 49 50 51 /***************************************************************************** 38 52 * filter_sys_t : filter descriptor 39 53 *****************************************************************************/ … … 43 57 }; 44 58 59 #define FCC_YUVA VLC_FOURCC('Y','U','V','A') 60 #define FCC_YUVP VLC_FOURCC('Y','U','V','P') 61 #define FCC_RGBA VLC_FOURCC('R','G','B','A') 62 63 #define FCC_I420 VLC_FOURCC('I','4','2','0') 64 #define FCC_YV12 VLC_FOURCC('Y','V','1','2') 65 #define FCC_YUY2 VLC_FOURCC('Y','U','Y','2') 66 #define FCC_UYVY VLC_FOURCC('U','Y','V','Y') 67 #define FCC_YVYU VLC_FOURCC('Y','V','Y','U') 68 #define FCC_RV15 VLC_FOURCC('R','V','1','5') 69 #define FCC_RV16 VLC_FOURCC('R','V','1','6') 70 #define FCC_RV24 VLC_FOURCC('R','V','2','4') 71 #define FCC_RV32 VLC_FOURCC('R','V','3','2') 72 45 73 /**************************************************************************** 46 74 * Local prototypes 47 75 ****************************************************************************/ 48 static int OpenFilter ( vlc_object_t * );49 static void CloseFilter( vlc_object_t * );50 51 76 static void Blend( filter_t *, picture_t *, picture_t *, picture_t *, 52 77 int, int, int ); 53 78 54 /* TODO i_alpha support for BlendR16 */55 79 /* YUVA */ 56 80 static void BlendI420( filter_t *, picture_t *, picture_t *, picture_t *, … … 94 118 int, int, int, int, int ); 95 119 96 /***************************************************************************** 97 * Module descriptor 98 *****************************************************************************/ 99 vlc_module_begin(); 100 set_description( N_("Video pictures blending") ); 101 set_capability( "video blending", 100 ); 102 set_callbacks( OpenFilter, CloseFilter ); 103 vlc_module_end(); 120 static void video_format_FixRgb( video_format_t *p_fmt ); 104 121 105 122 /***************************************************************************** … … 115 132 int in_chroma = p_filter->fmt_in.video.i_chroma; 116 133 int out_chroma = p_filter->fmt_out.video.i_chroma; 117 if( ( in_chroma != VLC_FOURCC('Y','U','V','A') && 118 in_chroma != VLC_FOURCC('I','4','2','0') && 119 in_chroma != VLC_FOURCC('Y','V','1','2') && 120 in_chroma != VLC_FOURCC('Y','U','V','P') && 121 in_chroma != VLC_FOURCC('R','G','B','A') ) || 122 ( out_chroma != VLC_FOURCC('I','4','2','0') && 123 out_chroma != VLC_FOURCC('Y','U','Y','2') && 124 out_chroma != VLC_FOURCC('Y','V','1','2') && 125 out_chroma != VLC_FOURCC('U','Y','V','Y') && 126 out_chroma != VLC_FOURCC('Y','V','Y','U') && 127 out_chroma != VLC_FOURCC('R','V','1','6') && 128 out_chroma != VLC_FOURCC('R','V','2','4') && 129 out_chroma != VLC_FOURCC('R','V','3','2') ) ) 134 if( ( in_chroma != FCC_YUVA && in_chroma != FCC_I420 && 135 in_chroma != FCC_YV12 && in_chroma != FCC_YUVP && 136 in_chroma != FCC_RGBA ) || 137 ( out_chroma != FCC_I420 && out_chroma != FCC_YUY2 && 138 out_chroma != FCC_YV12 && out_chroma != FCC_UYVY && 139 out_chroma != FCC_YVYU && out_chroma != FCC_RV15 && 140 out_chroma != FCC_YVYU && out_chroma != FCC_RV16 && 141 out_chroma != FCC_RV24 && out_chroma != FCC_RV32 ) ) 130 142 { 131 143 return VLC_EGENERIC; … … 133 145 134 146 /* Allocate the memory needed to store the decoder's structure */ 135 if( ( p_filter->p_sys = p_sys =136 (filter_sys_t *)malloc(sizeof(filter_sys_t)) ) == NULL)147 p_filter->p_sys = p_sys = malloc(sizeof(filter_sys_t)); 148 if( !p_sys ) 137 149 return VLC_ENOMEM; 138 150 … … 163 175 * This function is called just after the thread is launched. 164 176 ****************************************************************************/ 177 typedef void (*BlendFunction)( filter_t *, picture_t *, 178 picture_t *, picture_t *, 179 int , int , int , int , int ); 180 181 #define FCC_PLANAR_420 { FCC_I420, FCC_YV12, 0 } 182 #define FCC_PACKED_422 { FCC_YUY2, FCC_UYVY, FCC_YVYU, 0 } 183 #define FCC_RGB_16 { FCC_RV15, FCC_RV16, 0 } 184 #define FCC_RGB_24 { FCC_RV24, FCC_RV32, 0 } 185 186 #define BLEND_CFG( fccSrc, fctPlanar, fctPacked, fctRgb16, fctRgb24 ) \ 187 { .src = fccSrc, .p_dst = FCC_PLANAR_420, .pf_blend = fctPlanar }, \ 188 { .src = fccSrc, .p_dst = FCC_PACKED_422, .pf_blend = fctPacked }, \ 189 { .src = fccSrc, .p_dst = FCC_RGB_16, .pf_blend = fctRgb16 }, \ 190 { .src = fccSrc, .p_dst = FCC_RGB_24, .pf_blend = fctRgb24 } 191 192 static const struct 193 { 194 vlc_fourcc_t src; 195 vlc_fourcc_t p_dst[16]; 196 BlendFunction pf_blend; 197 } p_blend_cfg[] = { 198 199 BLEND_CFG( FCC_YUVA, BlendI420, BlendYUVPacked, BlendR16, BlendR24 ), 200 201 BLEND_CFG( FCC_YUVP, BlendPalI420, BlendPalYUVPacked, BlendPalRV, BlendPalRV ), 202 203 BLEND_CFG( FCC_RGBA, BlendRGBAI420, BlendRGBAYUVPacked, BlendRGBAR16, BlendRGBAR24 ), 204 205 BLEND_CFG( FCC_I420, BlendI420I420, BlendI420YUVPacked, BlendI420R16, BlendI420R24 ), 206 207 BLEND_CFG( FCC_YV12, BlendI420I420, BlendI420YUVPacked, BlendI420R16, BlendI420R24 ), 208 209 { 0, {0,}, NULL } 210 }; 211 165 212 static void Blend( filter_t *p_filter, picture_t *p_dst, 166 213 picture_t *p_dst_orig, picture_t *p_src, … … 169 216 int i_width, i_height; 170 217 171 if( i_alpha == 0 ) return; 218 if( i_alpha == 0 ) 219 return; 172 220 173 221 i_width = __MIN((int)p_filter->fmt_out.video.i_visible_width - i_x_offset, … … 177 225 (int)p_filter->fmt_in.video.i_visible_height); 178 226 179 if( i_width <= 0 || i_height <= 0 ) return; 227 if( i_width <= 0 || i_height <= 0 ) 228 return; 229 230 video_format_FixRgb( &p_filter->fmt_out.video ); 231 video_format_FixRgb( &p_filter->fmt_in.video ); 180 232 181 233 #if 0 … … 185 237 #endif 186 238 187 switch( p_filter->fmt_in.video.i_chroma ) 188 { 189 case VLC_FOURCC('Y','U','V','A'): 190 switch( p_filter->fmt_out.video.i_chroma ) 191 { 192 case VLC_FOURCC('I','4','2','0'): 193 case VLC_FOURCC('Y','V','1','2'): 194 BlendI420( p_filter, p_dst, p_dst_orig, p_src, 195 i_x_offset, i_y_offset, 196 i_width, i_height, i_alpha ); 197 return; 198 case VLC_FOURCC('Y','U','Y','2'): 199 case VLC_FOURCC('U','Y','V','Y'): 200 case VLC_FOURCC('Y','V','Y','U'): 201 BlendYUVPacked( p_filter, p_dst, p_dst_orig, p_src, 202 i_x_offset, i_y_offset, 203 i_width, i_height, i_alpha ); 204 return; 205 case VLC_FOURCC('R','V','1','6'): 206 BlendR16( p_filter, p_dst, p_dst_orig, p_src, 207 i_x_offset, i_y_offset, 208 i_width, i_height, i_alpha ); 209 return; 210 case VLC_FOURCC('R','V','2','4'): 211 case VLC_FOURCC('R','V','3','2'): 212 BlendR24( p_filter, p_dst, p_dst_orig, p_src, 213 i_x_offset, i_y_offset, 214 i_width, i_height, i_alpha ); 215 return; 216 } 217 case VLC_FOURCC('Y','U','V','P'): 218 switch( p_filter->fmt_out.video.i_chroma ) 219 { 220 case VLC_FOURCC('I','4','2','0'): 221 case VLC_FOURCC('Y','V','1','2'): 222 BlendPalI420( p_filter, p_dst, p_dst_orig, p_src, 223 i_x_offset, i_y_offset, 224 i_width, i_height, i_alpha ); 225 return; 226 case VLC_FOURCC('Y','U','Y','2'): 227 case VLC_FOURCC('U','Y','V','Y'): 228 case VLC_FOURCC('Y','V','Y','U'): 229 BlendPalYUVPacked( p_filter, p_dst, p_dst_orig, p_src, 230 i_x_offset, i_y_offset, 231 i_width, i_height, i_alpha ); 232 return; 233 case VLC_FOURCC('R','V','1','6'): 234 case VLC_FOURCC('R','V','2','4'): 235 case VLC_FOURCC('R','V','3','2'): 236 BlendPalRV( p_filter, p_dst, p_dst_orig, p_src, 237 i_x_offset, i_y_offset, 238 i_width, i_height, i_alpha ); 239 return; 240 } 241 case VLC_FOURCC('Y','V','1','2'): 242 case VLC_FOURCC('I','4','2','0'): 243 switch( p_filter->fmt_out.video.i_chroma ) 244 { 245 case VLC_FOURCC('I','4','2','0'): 246 case VLC_FOURCC('Y','V','1','2'): 247 if( i_alpha == 0xff ) 248 BlendI420I420_no_alpha( 249 p_filter, p_dst, p_dst_orig, p_src, 250 i_x_offset, i_y_offset, 251 i_width, i_height ); 252 else 253 BlendI420I420( p_filter, p_dst, p_dst_orig, p_src, 254 i_x_offset, i_y_offset, 255 i_width, i_height, i_alpha ); 256 return; 257 case VLC_FOURCC('Y','U','Y','2'): 258 case VLC_FOURCC('U','Y','V','Y'): 259 case VLC_FOURCC('Y','V','Y','U'): 260 BlendI420YUVPacked( p_filter, p_dst, p_dst_orig, p_src, 261 i_x_offset, i_y_offset, 262 i_width, i_height, i_alpha ); 263 return; 264 case VLC_FOURCC('R','V','1','6'): 265 BlendI420R16( p_filter, p_dst, p_dst_orig, p_src, 266 i_x_offset, i_y_offset, 267 i_width, i_height, i_alpha ); 268 return; 269 case VLC_FOURCC('R','V','2','4'): 270 case VLC_FOURCC('R','V','3','2'): 271 BlendI420R24( p_filter, p_dst, p_dst_orig, p_src, 272 i_x_offset, i_y_offset, 273 i_width, i_height, i_alpha ); 274 return; 275 } 276 case VLC_FOURCC('R','G','B','A'): 277 switch( p_filter->fmt_out.video.i_chroma ) 278 { 279 case VLC_FOURCC('I','4','2','0'): 280 case VLC_FOURCC('Y','V','1','2'): 281 BlendRGBAI420( p_filter, p_dst, p_dst_orig, p_src, 282 i_x_offset, i_y_offset, 283 i_width, i_height, i_alpha ); 284 return; 285 case VLC_FOURCC('Y','U','Y','2'): 286 case VLC_FOURCC('U','Y','V','Y'): 287 case VLC_FOURCC('Y','V','Y','U'): 288 BlendRGBAYUVPacked( p_filter, p_dst, p_dst_orig, p_src, 289 i_x_offset, i_y_offset, 290 i_width, i_height, i_alpha ); 291 return; 292 case VLC_FOURCC('R','V','2','4'): 293 case VLC_FOURCC('R','V','3','2'): 294 BlendRGBAR24( p_filter, p_dst, p_dst_orig, p_src, 295 i_x_offset, i_y_offset, 296 i_width, i_height, i_alpha ); 297 return; 298 case VLC_FOURCC('R','V','1','6'): 299 BlendRGBAR16( p_filter, p_dst, p_dst_orig, p_src, 300 i_x_offset, i_y_offset, 301 i_width, i_height, i_alpha ); 302 return; 303 } 239 for( int i = 0; p_blend_cfg[i].src != 0; i++ ) 240 { 241 if( p_blend_cfg[i].src != p_filter->fmt_in.video.i_chroma ) 242 continue; 243 for( int j = 0; p_blend_cfg[i].p_dst[j] != 0; j++ ) 244 { 245 if( p_blend_cfg[i].p_dst[j] != p_filter->fmt_out.video.i_chroma ) 246 continue; 247 248 p_blend_cfg[i].pf_blend( p_filter, p_dst, p_dst_orig, p_src, 249 i_x_offset, i_y_offset, i_width, i_height, i_alpha ); 250 return; 251 } 304 252 } 305 253 … … 337 285 static inline int vlc_alpha( int t, int a ) 338 286 { 287 if( a == 255 ) 288 return t; 339 289 return (t * a) / 255; 340 290 } … … 391 341 } 392 342 343 static void vlc_yuv_packed_index( int *pi_y, int *pi_u, int *pi_v, vlc_fourcc_t i_chroma ) 344 { 345 static const struct { 346 vlc_fourcc_t chroma; 347 int y, u ,v; 348 } p_index[] = { 349 { FCC_YUY2, 0, 1, 3 }, 350 { FCC_UYVY, 1, 0, 2 }, 351 { FCC_YVYU, 0, 3, 1 }, 352 { 0, 0, 0, 0 } 353 }; 354 int i; 355 356 for( i = 0; p_index[i].chroma != 0; i++ ) 357 { 358 if( p_index[i].chroma == i_chroma ) 359 break; 360 } 361 *pi_y = p_index[i].y; 362 *pi_u = p_index[i].u; 363 *pi_v = p_index[i].v; 364 } 365 366 static void vlc_blend_packed( uint8_t *p_dst, const uint8_t *p_src, 367 int i_offset0, int i_offset1, int i_offset2, 368 int c0, int c1, int c2, int i_alpha, 369 bool b_do12 ) 370 { 371 p_dst[i_offset0] = vlc_blend( c0, p_src[i_offset0], i_alpha ); 372 if( b_do12 ) 373 { 374 p_dst[i_offset1] = vlc_blend( c1, p_src[i_offset1], i_alpha ); 375 p_dst[i_offset2] = vlc_blend( c2, p_src[i_offset2], i_alpha ); 376 } 377 } 378 379 static void vlc_blend_rgb16( uint16_t *p_dst, const uint16_t *p_src, 380 int R, int G, int B, int i_alpha, 381 const video_format_t *p_fmt ) 382 { 383 const int i_pix = *p_src; 384 const int r = ( i_pix & p_fmt->i_rmask ) >> p_fmt->i_lrshift; 385 const int g = ( i_pix & p_fmt->i_gmask ) >> p_fmt->i_lgshift; 386 const int b = ( i_pix & p_fmt->i_bmask ) >> p_fmt->i_lbshift; 387 388 *p_dst = ( vlc_blend( R >> p_fmt->i_rrshift, r, i_alpha ) << p_fmt->i_lrshift ) | 389 ( vlc_blend( G >> p_fmt->i_rgshift, g, i_alpha ) << p_fmt->i_lgshift ) | 390 ( vlc_blend( B >> p_fmt->i_rbshift, b, i_alpha ) << p_fmt->i_lbshift ); 391 } 392 393 /***************************************************************************** 394 * BinaryLog: computes the base 2 log of a binary value 395 ***************************************************************************** 396 * This functions is used by MaskToShift, to get a bit index from a binary 397 * value. 398 *****************************************************************************/ 399 static int BinaryLog( uint32_t i ) 400 { 401 int i_log = 0; 402 403 if( i == 0 ) return -31337; 404 405 if( i & 0xffff0000 ) i_log += 16; 406 if( i & 0xff00ff00 ) i_log += 8; 407 if( i & 0xf0f0f0f0 ) i_log += 4; 408 if( i & 0xcccccccc ) i_log += 2; 409 if( i & 0xaaaaaaaa ) i_log += 1; 410 411 return i_log; 412 } 413 414 /** 415 * It transforms a color mask into right and left shifts 416 * FIXME copied from video_output.c 417 */ 418 #if 1 419 static void vlc_rgb_index( int *pi_rindex, int *pi_gindex, int *pi_bindex, 420 const video_format_t *p_fmt ) 421 { 422 if( p_fmt->i_chroma != FCC_RV24 && p_fmt->i_chroma != FCC_RV32 ) 423 return; 424 425 /* XXX it will works only if mask are 8 bits aligned */ 426 #ifdef WORDS_BIGENDIAN 427 const int i_mask_bits = p_fmt->i_chroma == FCC_RV24 ? 24 : 32; 428 *pi_rindex = ( i_mask_bits - p_fmt->i_lrshift ) / 8; 429 *pi_gindex = ( i_mask_bits - p_fmt->i_lgshift ) / 8; 430 *pi_bindex = ( i_mask_bits - p_fmt->i_lbshift ) / 8; 431 #else 432 *pi_rindex = p_fmt->i_lrshift / 8; 433 *pi_gindex = p_fmt->i_lgshift / 8; 434 *pi_bindex = p_fmt->i_lbshift / 8; 435 #endif 436 } 437 #endif 438 439 440 /* 441 * FIXME copied from video_output.c 442 */ 443 static void MaskToShift( int *pi_left, int *pi_right, uint32_t i_mask ) 444 { 445 uint32_t i_low, i_high; /* lower hand higher bits of the mask */ 446 447 if( !i_mask ) 448 { 449 *pi_left = *pi_right = 0; 450 return; 451 } 452 453 /* Get bits */ 454 i_low = i_high = i_mask; 455 456 i_low &= - (int32_t)i_low; /* lower bit of the mask */ 457 i_high += i_low; /* higher bit of the mask */ 458 459 /* Transform bits into an index. Also deal with i_high overflow, which 460 * is faster than changing the BinaryLog code to handle 64 bit integers. */ 461 i_low = BinaryLog (i_low); 462 i_high = i_high ? BinaryLog (i_high) : 32; 463 464 /* Update pointers and return */ 465 *pi_left = i_low; 466 *pi_right = (8 - i_high + i_low); 467 } 468 469 /* FIXME should be moved to src/ */ 470 static void video_format_FixRgb( video_format_t *p_fmt ) 471 { 472 if( p_fmt->i_chroma != FCC_RV15 && 473 p_fmt->i_chroma != FCC_RV16 && 474 p_fmt->i_chroma != FCC_RV24 && 475 p_fmt->i_chroma != FCC_RV32 ) 476 return; 477 478 /* FIXME find right default mask */ 479 if( !p_fmt->i_rmask || !p_fmt->i_gmask || !p_fmt->i_bmask ) 480 { 481 switch( p_fmt->i_chroma ) 482 { 483 case FCC_RV15: 484 p_fmt->i_rmask = 0x7c00; 485 p_fmt->i_gmask = 0x03e0; 486 p_fmt->i_bmask = 0x001f; 487 break; 488 489 case FCC_RV16: 490 p_fmt->i_rmask = 0xf800; 491 p_fmt->i_gmask = 0x07e0; 492 p_fmt->i_bmask = 0x001f; 493 break; 494 495 case FCC_RV24: 496 p_fmt->i_rmask = 0xff0000; 497 p_fmt->i_gmask = 0x00ff00; 498 p_fmt->i_bmask = 0x0000ff; 499 break; 500 case FCC_RV32: 501 p_fmt->i_rmask = 0x00ff0000; 502 p_fmt->i_gmask = 0x0000ff00; 503 p_fmt->i_bmask = 0x000000ff; 504 break; 505 506 default: 507 assert(0); 508 break; 509 } 510 } 511 512 MaskToShift( &p_fmt->i_lrshift, &p_fmt->i_rrshift, 513 p_fmt->i_rmask ); 514 MaskToShift( &p_fmt->i_lgshift, &p_fmt->i_rgshift, 515 p_fmt->i_gmask ); 516 MaskToShift( &p_fmt->i_lbshift, &p_fmt->i_rbshift, 517 p_fmt->i_bmask ); 518 } 519 393 520 /*********************************************************************** 394 521 * YUVA … … 512 639 513 640 /* Blending */ 514 /* FIXME: do the blending515 * FIXME use rgb shift (when present) */516 641 yuv_to_rgb( &r, &g, &b, 517 642 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] ); 518 643 519 ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); 644 vlc_blend_rgb16( (uint16_t*)&p_dst[i_x * i_pix_pitch], 645 (const uint16_t*)&p_src1[i_x * i_pix_pitch], 646 r, g, b, i_trans, &p_filter->fmt_out.video ); 520 647 } 521 648 } … … 572 699 uint32_t i_rmask, i_gmask, i_bmask; 573 700 574 if( p_dst_pic->p_heap ) 575 { 576 i_rmask = p_dst_pic->p_heap->i_rmask; 577 i_gmask = p_dst_pic->p_heap->i_gmask; 578 i_bmask = p_dst_pic->p_heap->i_bmask; 579 i_rshift = p_dst_pic->p_heap->i_lrshift; 580 i_gshift = p_dst_pic->p_heap->i_lgshift; 581 i_bshift = p_dst_pic->p_heap->i_lbshift; 582 } 583 else 584 { 585 i_rmask = p_dst_pic->format.i_rmask; 586 i_gmask = p_dst_pic->format.i_gmask; 587 i_bmask = p_dst_pic->format.i_bmask; 588 589 if( (i_rmask == 0x00FF0000) 590 && (i_gmask == 0x0000FF00) 591 && (i_bmask == 0x000000FF) ) 592 { 593 /* X8R8G8B8 pixel layout */ 594 i_rshift = 16; 595 i_bshift = 8; 596 i_gshift = 0; 597 } 598 else if( (i_rmask == 0xFF000000) 599 && (i_gmask == 0x00FF0000) 600 && (i_bmask == 0x0000FF00) ) 601 { 602 /* R8G8B8X8 pixel layout */ 603 i_rshift = 24; 604 i_bshift = 16; 605 i_gshift = 8; 606 } 607 else 608 { 609 goto slower; 610 } 611 } 701 i_rmask = p_filter->fmt_out.video.i_rmask; 702 i_gmask = p_filter->fmt_out.video.i_gmask; 703 i_bmask = p_filter->fmt_out.video.i_bmask; 704 i_rshift = p_filter->fmt_out.video.i_lrshift; 705 i_gshift = p_filter->fmt_out.video.i_lgshift; 706 i_bshift = p_filter->fmt_out.video.i_lbshift; 707 612 708 /* Draw until we reach the bottom of the subtitle */ 613 709 for( i_y = 0; i_y < i_height; i_y++, p_trans += i_src2_pitch, … … 650 746 else 651 747 { 652 int i_rindex, i_ bindex, i_gindex;748 int i_rindex, i_gindex, i_bindex; 653 749 uint32_t i_rmask, i_gmask, i_bmask; 654 750 655 slower: 656 657 i_rmask = p_dst_pic->format.i_rmask; 658 i_gmask = p_dst_pic->format.i_gmask; 659 i_bmask = p_dst_pic->format.i_bmask; 660 661 /* 662 ** quick and dirty way to get byte index from mask 663 ** will only work correctly if mask are 8 bit aligned 664 ** and are 8 bit long 665 */ 666 #ifdef WORDS_BIGENDIAN 667 i_rindex = ((i_rmask>>16) & 1) 668 | ((i_rmask>>8) & 2) 669 | ((i_rmask) & 3); 670 i_gindex = ((i_gmask>>16) & 1) 671 | ((i_gmask>>8) & 2) 672 | ((i_gmask) & 3); 673 i_bindex = ((i_bmask>>16) & 1) 674 | ((i_bmask>>8) & 2) 675 | ((i_bmask) & 3); 676 #else 677 i_rindex = ((i_rmask>>24) & 3) 678 | ((i_rmask>>16) & 2) 679 | ((i_rmask>>8) & 1); 680 i_gindex = ((i_gmask>>24) & 3) 681 | ((i_gmask>>16) & 2) 682 | ((i_gmask>>8) & 1); 683 i_bindex = ((i_bmask>>24) & 3) 684 | ((i_bmask>>16) & 2) 685 | ((i_bmask>>8) & 1); 686 #endif 751 i_rmask = p_filter->fmt_out.video.i_rmask; 752 i_gmask = p_filter->fmt_out.video.i_gmask; 753 i_bmask = p_filter->fmt_out.video.i_bmask; 754 755 vlc_rgb_index( &i_rindex, &i_gindex, &i_bindex, &p_filter->fmt_out.video ); 687 756 688 757 /* Draw until we reach the bottom of the subtitle */ … … 700 769 continue; 701 770 702 const int i_pos = i_x * i_pix_pitch; 703 if( i_trans == MAX_TRANS ) 704 { 705 706 /* Completely opaque. Completely overwrite underlying pixel */ 707 yuv_to_rgb( &r, &g, &b, 708 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] ); 709 710 p_dst[i_pos + i_rindex ] = r; 711 p_dst[i_pos + i_gindex ] = g; 712 p_dst[i_pos + i_bindex ] = b; 713 } 714 else 715 { 716 int i_rpos = i_pos + i_rindex; 717 int i_gpos = i_pos + i_gindex; 718 int i_bpos = i_pos + i_bindex; 719 720 /* Blending */ 721 yuv_to_rgb( &r, &g, &b, 722 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] ); 723 724 p_dst[i_rpos] = vlc_blend( r, p_src1[i_rpos], i_trans ); 725 p_dst[i_gpos] = vlc_blend( g, p_src1[i_gpos], i_trans ); 726 p_dst[i_bpos] = vlc_blend( b, p_src1[i_gpos], i_trans ); 727 } 771 /* Blending */ 772 yuv_to_rgb( &r, &g, &b, 773 p_src2_y[i_x], p_src2_u[i_x], p_src2_v[i_x] ); 774 775 vlc_blend_packed( &p_dst[ i_x * i_pix_pitch], 776 &p_src1[i_x * i_pix_pitch], 777 i_rindex, i_gindex, i_bindex, 778 r, g, b, i_alpha, true ); 728 779 } 729 780 } … … 742 793 int i_x, i_y, i_pix_pitch, i_trans = 0; 743 794 bool b_even = !((i_x_offset + p_filter->fmt_out.video.i_x_offset)%2); 744 int i_l_offset = 0, i_u_offset = 0, i_v_offset = 0; 745 746 if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') ) 747 { 748 i_l_offset = 0; 749 i_u_offset = 1; 750 i_v_offset = 3; 751 } 752 else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('U','Y','V','Y') ) 753 { 754 i_l_offset = 1; 755 i_u_offset = 0; 756 i_v_offset = 2; 757 } 758 else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','Y','U') ) 759 { 760 i_l_offset = 0; 761 i_u_offset = 3; 762 i_v_offset = 1; 763 } 795 int i_l_offset, i_u_offset, i_v_offset; 796 797 vlc_yuv_packed_index( &i_l_offset, &i_u_offset, &i_v_offset, 798 p_filter->fmt_out.video.i_chroma ); 764 799 765 800 i_pix_pitch = 2; … … 801 836 802 837 /* Blending */ 803 p_dst[i_x * 2 + i_l_offset] = vlc_blend( p_src2_y[i_x], p_src1[i_x * 2 + i_l_offset], i_trans );804 838 if( b_even ) 805 839 { … … 817 851 i_v = p_src2_v[i_x]; 818 852 } 819 p_dst[i_x * 2 + i_u_offset] = vlc_blend( i_u, p_src1[i_x * 2 + i_u_offset], i_trans ); 820 p_dst[i_x * 2 + i_v_offset] = vlc_blend( i_v, p_src1[i_x * 2 + i_v_offset], i_trans ); 853 854 vlc_blend_packed( &p_dst[i_x * 2], &p_src1[i_x * 2], 855 i_l_offset, i_u_offset, i_v_offset, 856 p_src2_y[i_x], i_u, i_v, i_trans, true ); 857 } 858 else 859 { 860 p_dst[i_x * 2 + i_l_offset] = vlc_blend( p_src2_y[i_x], p_src1[i_x * 2 + i_l_offset], i_trans ); 821 861 } 822 862 } … … 837 877 int i_x, i_y; 838 878 bool b_even_scanline = i_y_offset % 2; 879 880 if( i_alpha == 0xff ) 881 { 882 BlendI420I420_no_alpha( p_filter, p_dst, p_dst_orig, p_src, 883 i_x_offset, i_y_offset, i_width, i_height ); 884 return; 885 } 886 839 887 840 888 i_dst_pitch = p_dst->p[Y_PLANE].i_pitch; … … 1008 1056 for( i_x = 0; i_x < i_width; i_x++ ) 1009 1057 { 1010 if( i_alpha == MAX_TRANS )1011 {1012 /* Completely opaque. Completely overwrite underlying pixel */1013 yuv_to_rgb( &r, &g, &b,1014 p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2] );1015 1016 ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3);1017 continue;1018 }1019 1020 1058 /* Blending */ 1021 /* FIXME: do the blending1022 * FIXME use rgb shifts */1023 1059 yuv_to_rgb( &r, &g, &b, 1024 1060 p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2] ); 1025 1061 1026 ((uint16_t *)(&p_dst[i_x * i_pix_pitch]))[0] = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); 1062 vlc_blend_rgb16( (uint16_t*)&p_dst[i_x * i_pix_pitch], 1063 (const uint16_t*)&p_src1[i_x * i_pix_pitch], 1064 r, g, b, 0xff, &p_filter->fmt_out.video ); 1027 1065 } 1028 1066 if( i_y%2 == 1 ) … … 1043 1081 uint8_t *p_src2_u, *p_src2_v; 1044 1082 int i_x, i_y, i_pix_pitch; 1083 int i_rindex, i_gindex, i_bindex; 1045 1084 int r, g, b; 1046 1085 … … 1065 1104 0, 0, &p_filter->fmt_in.video, 2 ); 1066 1105 1106 vlc_rgb_index( &i_rindex, &i_gindex, &i_bindex, &p_filter->fmt_out.video ); 1067 1107 1068 1108 /* Draw until we reach the bottom of the subtitle */ … … 1082 1122 p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2] ); 1083 1123 1084 p_dst[i_x * i_pix_pitch + 0] = vlc_blend( r, p_src1[i_x * i_pix_pitch + 0], i_alpha ); 1085 p_dst[i_x * i_pix_pitch + 1] = vlc_blend( g, p_src1[i_x * i_pix_pitch + 1], i_alpha ); 1086 p_dst[i_x * i_pix_pitch + 2] = vlc_blend( b, p_src1[i_x * i_pix_pitch + 2], i_alpha ); 1124 vlc_blend_packed( &p_dst[i_x * i_pix_pitch], &p_src1[i_x * i_pix_pitch], 1125 i_rindex, i_gindex, i_bindex, r, g, b, i_alpha, true ); 1087 1126 } 1088 1127 if( i_y%2 == 1 ) … … 1104 1143 int i_x, i_y, i_pix_pitch; 1105 1144 bool b_even = !((i_x_offset + p_filter->fmt_out.video.i_x_offset)%2); 1106 int i_l_offset = 0, i_u_offset = 0, i_v_offset = 0; 1107 1108 if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') ) 1109 { 1110 i_l_offset = 0; 1111 i_u_offset = 1; 1112 i_v_offset = 3; 1113 } 1114 else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('U','Y','V','Y') ) 1115 { 1116 i_l_offset = 1; 1117 i_u_offset = 0; 1118 i_v_offset = 2; 1119 } 1120 else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','Y','U') ) 1121 { 1122 i_l_offset = 0; 1123 i_u_offset = 3; 1124 i_v_offset = 1; 1125 } 1145 int i_l_offset, i_u_offset, i_v_offset; 1146 1147 vlc_yuv_packed_index( &i_l_offset, &i_u_offset, &i_v_offset, 1148 p_filter->fmt_out.video.i_chroma ); 1126 1149 1127 1150 i_pix_pitch = 2; … … 1160 1183 1161 1184 /* Blending */ 1162 p_dst[i_x * 2 + i_l_offset] = vlc_blend( p_src2_y[i_x], p_src1[i_x * 2 + i_l_offset], i_alpha ); 1163 if( b_even ) 1164 { 1165 uint16_t i_u = p_src2_u[i_x/2]; 1166 uint16_t i_v = p_src2_v[i_x/2]; 1167 p_dst[i_x * 2 + i_u_offset] = vlc_blend( i_u, p_src1[i_x * 2 + i_u_offset], i_alpha ); 1168 p_dst[i_x * 2 + i_v_offset] = vlc_blend( i_v, p_src1[i_x * 2 + i_v_offset], i_alpha ); 1169 } 1185 vlc_blend_packed( &p_dst[i_x * 2], &p_src1[i_x * 2], 1186 i_l_offset, i_u_offset, i_v_offset, 1187 p_src2_y[i_x], p_src2_u[i_x/2], p_src2_v[i_x/2], i_alpha, b_even ); 1170 1188 } 1171 1189 if( i_y%2 == 1 ) … … 1266 1284 int i_x, i_y, i_pix_pitch, i_trans; 1267 1285 bool b_even = !((i_x_offset + p_filter->fmt_out.video.i_x_offset)%2); 1268 int i_l_offset = 0, i_u_offset = 0, i_v_offset = 0; 1269 1270 if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','U','Y','2') ) 1271 { 1272 i_l_offset = 0; 1273 i_u_offset = 1; 1274 i_v_offset = 3; 1275 } 1276 else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('U','Y','V','Y') ) 1277 { 1278 i_l_offset = 1; 1279 i_u_offset = 0; 1280 i_v_offset = 2; 1281 } 1282 else if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('Y','V','Y','U') ) 1283 { 1284 i_l_offset = 0; 1285 i_u_offset = 3; 1286 i_v_offset = 1; 1287 } 1286 int i_l_offset, i_u_offset, i_v_offset; 1287 1288 vlc_yuv_packed_index( &i_l_offset, &i_u_offset, &i_v_offset, 1289 p_filter->fmt_out.video.i_chroma ); 1288 1290 1289 1291 i_pix_pitch = 2; … … 1302 1304 i_src2_pitch * p_filter->fmt_in.video.i_y_offset; 1303 1305 1304 i_width = (i_width >> 1) <<1; /* Needs to be a multiple of 2 */1306 i_width &= ~1; /* Needs to be a multiple of 2 */ 1305 1307 1306 1308 const uint8_t *p_trans = p_src2; … … 1319 1321 1320 1322 /* Blending */ 1321 p_dst[i_x * 2 + i_l_offset] = vlc_blend( p_pal[p_src2[i_x]][0], p_src1[i_x * 2 + i_l_offset], i_trans );1322 1323 if( b_even ) 1323 1324 { … … 1335 1336 } 1336 1337 1337 p_dst[i_x * 2 + i_u_offset] = vlc_blend( i_u, p_src1[i_x * 2 + i_u_offset], i_trans ); 1338 p_dst[i_x * 2 + i_v_offset] = vlc_blend( i_v, p_src1[i_x * 2 + i_v_offset], i_trans ); 1338 vlc_blend_packed( &p_dst[i_x * 2], &p_src1[i_x * 2], 1339 i_l_offset, i_u_offset, i_v_offset, 1340 p_pal[p_src2[i_x]][0], i_u, i_v, i_trans, true ); 1341 } 1342 else 1343 { 1344 p_dst[i_x * 2 + i_l_offset] = vlc_blend( p_pal[p_src2[i_x]][0], p_src1[i_x * 2 + i_l_offset], i_trans ); 1339 1345 } 1340 1346 } … … 1353 1359 int r, g, b; 1354 1360 video_palette_t rgbpalette; 1361 int i_rindex, i_gindex, i_bindex; 1355 1362 1356 1363 i_pix_pitch = p_dst_pic->p->i_pixel_pitch; … … 1374 1381 1375 1382 /* Convert palette first */ 1376 for( i_y = 0; i_y < p_filter->fmt_in.video.p_palette->i_entries && 1377 i_y < 256; i_y++ ) 1383 for( i_y = 0; i_y < p_filter->fmt_in.video.p_palette->i_entries && i_y < 256; i_y++ ) 1378 1384 { 1379 1385 yuv_to_rgb( &r, &g, &b, p_pal[i_y][0], p_pal[i_y][1], p_pal[i_y][2] ); 1380 1381 if( p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') ) 1382 { 1383 *(uint16_t *)rgbpal[i_y] = 1384 ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3); 1385 } 1386 else 1387 { 1388 rgbpal[i_y][0] = r; rgbpal[i_y][1] = g; rgbpal[i_y][2] = b; 1389 } 1390 } 1386 rgbpal[i_y][0] = r; rgbpal[i_y][1] = g; rgbpal[i_y][2] = b; 1387 } 1388 1389 /* */ 1390 vlc_rgb_index( &i_rindex, &i_gindex, &i_bindex, &p_filter->fmt_out.video ); 1391 1391 1392 1392 /* Draw until we reach the bottom of the subtitle */ … … 1401 1401 continue; 1402 1402 1403 if( i_trans == MAX_TRANS ||1404 p_filter->fmt_out.video.i_chroma == VLC_FOURCC('R','V','1','6') )1405 {1406 /* FIXME implement blending for RV16 */1407 /* Completely opaque. Completely overwrite underlying pixel */1408 p_dst[i_x * i_pix_pitch] = rgbpal[p_src2[i_x]][0];1409 p_dst[i_x * i_pix_pitch + 1] = rgbpal[p_src2[i_x]][1];1410 if( p_filter->fmt_out.video.i_chroma != VLC_FOURCC('R','V','1','6') )1411 p_dst[i_x * i_pix_pitch + 2] = rgbpal[p_src2[i_x]][2];1412 continue;1413 }1414 1415 1403 /* Blending */ 1416 p_dst[i_x * i_pix_pitch + 0] = vlc_blend( rgbpal[p_src2[i_x]][0], p_src1[i_x * i_pix_pitch + 0], i_trans ); 1417 p_dst[i_x * i_pix_pitch + 1] = vlc_blend( rgbpal[p_src2[i_x]][1], p_src1[i_x * i_pix_pitch + 1], i_trans ); 1418 p_dst[i_x * i_pix_pitch + 2] = vlc_blend( rgbpal[p_src2[i_x]][2], p_src1[i_x * i_pix_pitch + 2], i_trans ); 1404 if( p_filter->fmt_out.video.i_chroma == FCC_RV15 || p_filter->fmt_out.video.i_chroma == FCC_RV16 ) 1405 vlc_blend_rgb16( (uint16_t*)&p_dst[i_x * i_pix_pitch], 1406 (const uint16_t*)&p_src1[i_x * i_pix_pitch], 1407 rgbpal[p_src2[i_x]][0], rgbpal[p_src2[i_x]][1], rgbpal[p_src2[i_x]][3], 1408 i_trans, 1409 &p_filter->fmt_out.video ); 1410 else 1411 vlc_blend_packed( &p_dst[i_x * i_pix_pitch], &p_src1[i_x * i_pix_pitch], 1412 i_rindex, i_gindex, i_bindex, 1413 rgbpal[p_src2[i_x]][0], rgbpal[p_src2[i_x]][1], rgbpal[p_src2[i_x]][3], 1414 i_trans, true ); <
