diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/video_out/alphablend.c | 215 |
1 files changed, 163 insertions, 52 deletions
diff --git a/src/video_out/alphablend.c b/src/video_out/alphablend.c index 17859a022..9bc8bb47f 100644 --- a/src/video_out/alphablend.c +++ b/src/video_out/alphablend.c @@ -28,6 +28,10 @@ * */ +/* +#define LOG_BLEND_YUV +*/ + #include <string.h> #include <stdlib.h> #include <inttypes.h> @@ -395,7 +399,6 @@ void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl, { clut_t *my_clut; uint8_t *my_trans; - int i; int src_width = img_overl->width; int src_height = img_overl->height; @@ -403,78 +406,183 @@ void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl, rle_elem_t *rle_limit = rle + img_overl->num_rle; int x_off = img_overl->x; int y_off = img_overl->y; - int mask; + int ymask,xmask; + int rle_this_bite; + int rle_remainder; + int rlelen; int x, y; - + uint8_t *dst_y = dst_img + dst_width * y_off + x_off; uint8_t *dst_cr = dst_img + dst_width * dst_height + (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; uint8_t *dst_cb = dst_cr + (dst_width * dst_height) / 4; - +#ifdef LOG_BLEND_YUV + printf("overlay_blend started x=%d, y=%d, w=%d h=%d\n",img_overl->x,img_overl->y,img_overl->width,img_overl->height); +#endif my_clut = (clut_t*) img_overl->clip_color; my_trans = img_overl->clip_trans; - for(i=0;i<4;i++) { -// printf("video_out:[%d] clut=0x%04x trans=0x%02x\n",i, img_overl->clip_color[i],my_trans[i]); - } + rlelen=rle_remainder=0; for (y = 0; y < src_height; y++) { - mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); + ymask = ((img_overl->clip_top > y) || (img_overl->clip_bottom < y)); + xmask = 0; +#ifdef LOG_BLEND_YUV + printf("X started ymask=%d y=%d src_height=%d\n",ymask, y, src_height); +#endif for (x = 0; x < src_width;) { - uint8_t clr; - uint16_t o; - int rlelen; - - clr = rle->color; - o = my_trans[clr]; - rlelen = rle->len; - - if (o && mask) { - /* threat cases where clipping border is inside rle->len pixels */ - if ( img_overl->clip_left > x ) { - if( img_overl->clip_left < x + rlelen ) { - rlelen -= img_overl->clip_left - x; - x += img_overl->clip_left - x; + uint8_t clr=0; + uint16_t o=0; +#ifdef LOG_BLEND_YUV + printf("1:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); +#endif + + if (rlelen < 0 || rle_remainder < 0) { + printf("alphablend: major bug in blend_yuv < 0\n"); + } + if (rlelen == 0) { + rle_remainder = rlelen = rle->len; + clr = rle->color; + rle++; + } + if (rle_remainder == 0) { + rle_remainder = rlelen; + } + if (rle_remainder + x > src_width) { + /* Do something for long rlelengths */ + rle_remainder = src_width - x; + ; + } +#ifdef LOG_BLEND_YUV + printf("2:rle_len=%d, remainder=%d, x=%d\n",rlelen, rle_remainder, x); +#endif + + if (ymask == 0) { + if (x <= img_overl->clip_left) { + /* Starts outside clip area */ + if (x + rle_remainder > img_overl->clip_left ) { +#ifdef LOG_BLEND_YUV + printf("Outside clip left %d, ending inside\n", img_overl->clip_left); +#endif + /* Cutting needed, starts outside, ends inside */ + rle_this_bite = (img_overl->clip_left - x + 1); + rle_remainder -= rle_this_bite; + rlelen -= rle_this_bite; + my_clut = (clut_t*) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; } else { - o = 0; +#ifdef LOG_BLEND_YUV + printf("Outside clip left %d, ending outside\n", img_overl->clip_left); +#endif + /* no cutting needed, starts outside, ends outside */ + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (clut_t*) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; } - } else if( img_overl->clip_right < x + rlelen ) { - if( img_overl->clip_right > x ) { - mem_blend8(dst_y + x, my_clut[clr].y, o, (img_overl->clip_right-x) ); - if (y & 1) { - mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, - (img_overl->clip_right-x+1) >> 1); - mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, - (img_overl->clip_right-x+1) >> 1); - } - o = 0; + } else if (x < img_overl->clip_right) { + /* Starts inside clip area */ + if (x + rle_remainder >= img_overl->clip_right ) { +#ifdef LOG_BLEND_YUV + printf("Inside clip right %d, ending outside\n", img_overl->clip_right); +#endif + /* Cutting needed, starts inside, ends outside */ + rle_this_bite = (img_overl->clip_right - x + 1); + rle_remainder -= rle_this_bite; + rlelen -= rle_this_bite; + my_clut = (clut_t*) img_overl->clip_color; + my_trans = img_overl->clip_trans; + xmask++; } else { - o = 0; +#ifdef LOG_BLEND_YUV + printf("Inside clip right %d, ending inside\n", img_overl->clip_right); +#endif + /* no cutting needed, starts inside, ends inside */ + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (clut_t*) img_overl->clip_color; + my_trans = img_overl->clip_trans; + xmask++; } - } + } else if (x >= img_overl->clip_right) { + /* Starts outside clip area, ends outsite clip area */ + if (x + rle_remainder > src_width ) { +#ifdef LOG_BLEND_YUV + printf("Outside clip right %d, ending eol\n", img_overl->clip_right); +#endif + /* Cutting needed, starts outside, ends at right edge */ + /* It should never reach here due to the earlier test of src_width */ + rle_this_bite = (src_width - x ); + rle_remainder -= rle_this_bite; + rlelen -= rle_this_bite; + my_clut = (clut_t*) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; + } else { + /* no cutting needed, starts outside, ends outside */ +#ifdef LOG_BLEND_YUV + printf("Outside clip right %d, ending outside\n", img_overl->clip_right); +#endif + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (clut_t*) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; + } + } + } else { + /* Outside clip are due to y */ + /* no cutting needed, starts outside, ends outside */ + rle_this_bite = rle_remainder; + rle_remainder = 0; + rlelen -= rle_this_bite; + my_clut = (clut_t*) img_overl->color; + my_trans = img_overl->trans; + xmask = 0; } - - if (o && mask) { - if (o >= 15) { - memset(dst_y + x, my_clut[clr].y, rlelen); + o = my_trans[clr]; +#ifdef LOG_BLEND_YUV + printf("Trans=%d clr=%d xmask=%d my_clut[clr]=%d\n",o, clr, xmask, my_clut[clr].y); +#endif + if (o) { + if(o >= 15) { + memset(dst_y + x, my_clut[clr].y, rle_this_bite); if (y & 1) { - memset(dst_cr + (x >> 1), my_clut[clr].cr, (rlelen+1) >> 1); - memset(dst_cb + (x >> 1), my_clut[clr].cb, (rlelen+1) >> 1); + memset(dst_cr + (x >> 1), my_clut[clr].cr, (rle_this_bite+1) >> 1); + memset(dst_cb + (x >> 1), my_clut[clr].cb, (rle_this_bite+1) >> 1); } - } else { - mem_blend8(dst_y + x, my_clut[clr].y, o, rlelen); + } else { + mem_blend8(dst_y + x, my_clut[clr].y, o, rle_this_bite); if (y & 1) { - mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rlelen+1) >> 1); - mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rlelen+1) >> 1); + /* Blending cr and cb should use a different function, with pre -128 to each sample */ + mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, (rle_this_bite+1) >> 1); + mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, (rle_this_bite+1) >> 1); } - } - } + } - x += rlelen; - rle++; - if (rle >= rle_limit) break; + } +#ifdef LOG_BLEND_YUV + printf("rle_this_bite=%d, remainder=%d, x=%d\n",rle_this_bite, rle_remainder, x); +#endif + x += rle_this_bite; + if (rle >= rle_limit) { +#ifdef LOG_BLEND_YUV + printf("x-rle_limit\n"); +#endif + break; + } + } + if (rle >= rle_limit) { +#ifdef LOG_BLEND_YUV + printf("x-rle_limit\n"); +#endif + break; } - if (rle >= rle_limit) break; dst_y += dst_width; @@ -483,8 +591,11 @@ void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl, dst_cb += (dst_width + 1) / 2; } } +#ifdef LOG_BLEND_YUV + printf("overlay_blend ended\n"); +#endif } - + void blend_yuy2 (uint8_t * dst_img, vo_overlay_t * img_overl, int dst_width, int dst_height) { |