diff options
-rw-r--r-- | src/libspudec/spu.c | 40 | ||||
-rw-r--r-- | src/video_out/alphablend.c | 434 | ||||
-rw-r--r-- | src/xine-engine/video_out.h | 11 |
3 files changed, 235 insertions, 250 deletions
diff --git a/src/libspudec/spu.c b/src/libspudec/spu.c index fa502e2b1..e0f0a4aec 100644 --- a/src/libspudec/spu.c +++ b/src/libspudec/spu.c @@ -19,7 +19,7 @@ * along with this program; see the file COPYING. If not, write to * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. * -* $Id: spu.c,v 1.9 2001/08/17 07:26:14 richwareham Exp $ +* $Id: spu.c,v 1.10 2001/08/17 15:54:31 ehasenle Exp $ * *****/ @@ -120,7 +120,7 @@ int spuNextEvent(spu_state_t *state, spu_seq_t* seq, int pts) uint8_t *buf = state->cmd_ptr; if (state->next_pts == -1) { /* timestamp valid? */ - state->next_pts = seq->PTS + ((buf[0] << 8) + buf[1]) * 1100; + state->next_pts = seq->PTS + ((buf[0] << 8) + buf[1]) * 1024; buf += 2; state->cmd_ptr = buf; } @@ -180,7 +180,6 @@ void spuDoCommands(spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) case CMD_SPU_SET_ALPHA: { /* transparency palette */ spu_clut_t *trans = (spu_clut_t *) (buf+1); - /* TODO: bswap32? */ ovl->trans[3] = trans->entry0; ovl->trans[2] = trans->entry1; ovl->trans[1] = trans->entry2; @@ -262,12 +261,6 @@ static u_int get_bits (u_int bits) return ret; } -static inline void spu_put_pixel (vo_overlay_t *spu, int len, uint8_t colorid) -{ - memset (spu->data + put_x + put_y * spu->width, colorid, len); - put_x += len; -} - static int spu_next_line (vo_overlay_t *spu) { get_bits (0); // byte align rle data @@ -285,6 +278,8 @@ static int spu_next_line (vo_overlay_t *spu) void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) { + rle_elem_t *rle; + field = 0; bit_ptr[0] = seq->buf + state->field_offs[0]; bit_ptr[1] = seq->buf + state->field_offs[1]; @@ -303,18 +298,20 @@ void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) spuUpdateMenu(state, ovl); - if (ovl->width * ovl->height > ovl->data_size) { - if (ovl->data) - free(ovl->data); - ovl->data_size = ovl->width * ovl->height; - ovl->data = malloc(ovl->data_size); + /* buffer is believed to be sufficiently large + * with cmd_offs * 2 * sizeof(rle_elem_t), is that true? */ + if (seq->cmd_offs * 2 * sizeof(rle_elem_t) > ovl->data_size) { + if (ovl->rle) + free(ovl->rle); + ovl->data_size = seq->cmd_offs * 2 * sizeof(rle_elem_t); + ovl->rle = malloc(ovl->data_size); } state->modified = 0; /* mark as already processed */ + rle = ovl->rle; while (bit_ptr[1] < seq->buf + seq->cmd_offs) { u_int len; - u_int color; u_int vlc; vlc = get_bits (4); @@ -328,25 +325,24 @@ void spuDrawPicture (spu_state_t *state, spu_seq_t* seq, vo_overlay_t *ovl) } } - color = vlc & 0x03; len = vlc >> 2; /* if len == 0 -> end sequence - fill to end of line */ if (len == 0) len = ovl->width - put_x; - spu_put_pixel (ovl, len, color); + rle->len = len; + rle->color = vlc & 0x03; + rle++; + put_x += len; if (put_x >= ovl->width) { if (spu_next_line (ovl) < 0) - return; + break; } } - /* Like the eof-line escape, fill the rest of the sp. with background */ - do { - spu_put_pixel (ovl, ovl->width, 0); - } while (!spu_next_line (ovl)); + ovl->num_rle = rle - ovl->rle; } void spuUpdateMenu (spu_state_t *state, vo_overlay_t *ovl) { diff --git a/src/video_out/alphablend.c b/src/video_out/alphablend.c index bba685418..b7add0e31 100644 --- a/src/video_out/alphablend.c +++ b/src/video_out/alphablend.c @@ -38,184 +38,202 @@ #define BLEND_COLOR(dst, src, mask, o) ((((src&mask)*o + ((dst&mask)*(0x0f-o)))/0xf) & mask) -static inline uint16_t blendpixel_rgb16 (uint16_t dst, uint16_t src, - uint8_t o) -{ - return BLEND_COLOR (dst, src, 0xf800, o) | - BLEND_COLOR (dst, src, 0x07e0, o) | - BLEND_COLOR (dst, src, 0x001f, o); +#define BLEND_BYTE(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) + +static void mem_blend16(uint16_t *mem, uint16_t clr, uint8_t o, int len) { + uint16_t *limit = mem + len; + while (mem < limit) { + *mem = + BLEND_COLOR(*mem, clr, 0xf800, o) | + BLEND_COLOR(*mem, clr, 0x07e0, o) | + BLEND_COLOR(*mem, clr, 0x001f, o); + mem++; + } } -static inline uint32_t blendpixel_rgb24 (uint32_t dst, uint32_t src, - uint8_t o) -{ - return BLEND_COLOR (dst, src, 0xff0000, o) | - BLEND_COLOR (dst, src, 0x00ff00, o) | - BLEND_COLOR (dst, src, 0x0000ff, o); +static void mem_blend24(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b, + uint8_t o, int len) { + uint8_t *limit = mem + len*3; + while (mem < limit) { + *mem = BLEND_BYTE(*mem, r, o); + mem++; + *mem = BLEND_BYTE(*mem, g, o); + mem++; + *mem = BLEND_BYTE(*mem, b, o); + mem++; + } } -static inline uint32_t blendpixel_rgb32 (uint32_t dst, uint32_t src, - uint8_t o) -{ - return BLEND_COLOR (dst, src, 0xff0000, o) | - BLEND_COLOR (dst, src, 0x00ff00, o) | - BLEND_COLOR (dst, src, 0x0000ff, o); -} -/* -void blend_tux_rgb16 (uint8_t * img, int dst_width, int dst_height) -{ - int src_width = bg_width; - int src_height = bg_height; - uint8_t *src = (uint8_t *) bg_img_data; - static int x_off; - static int y_off; - static int x_dir = 1; - static int y_dir = 1; - static int o = 5; - static int o_dir = 1; - -// align right bottom - x_off += x_dir; - if (x_off > (dst_width - src_width)) - x_dir = -x_dir; - if (x_off <= 0) - x_dir = -x_dir; - - y_off += y_dir; - if (y_off > (dst_height - src_height)) - y_dir = -y_dir; - if (y_off <= 0) - y_dir = -y_dir; - -// cycle parameters - o += o_dir; - if (o >= 0xf) - o_dir = -o_dir; - if (o <= 1) - o_dir = -o_dir; -// - { - uint16_t *dst = (uint16_t *) img; - int x, - y; - - dst += y_off * dst_width; - for (y = 0; y < src_height; y++) { - dst += x_off; - for (x = 0; x < src_width; x++) { - if ((*src) - bg_start_index) - *dst = blendpixel_rgb16 (bg_palette_to_rgb [(*src) - bg_start_index], *dst, o); - src++; - dst++; - } - dst += dst_width - x - x_off; - } - } -} -*/ -// convenience - -#define uint24_t uint32_t - -#define BLEND(bpp, img, img_overl, dst_width, dst_height)\ -{ \ - static int o=5; \ - uint8_t *src = (uint8_t *) img_overl->data; \ - uint##bpp##_t *dst = (uint##bpp##_t *) img; \ - int x, y; \ - \ - dst += img_overl->y*dst_width; \ - for (y=0; y<img_overl->height; y++) { \ - dst += img_overl->x; \ - for (x=0; x<img_overl->width; x++) { \ - o = img_overl->trans[*src]; \ - \ - if (o) /* if alpha is != 0 */ \ - *dst = blendpixel_rgb##bpp (*dst, myclut[*src], o); \ - src++; \ - dst++; \ - } \ - dst += dst_width - x - img_overl->x; \ - } \ +static void mem_blend32(uint8_t *mem, uint8_t r, uint8_t g, uint8_t b, + uint8_t o, int len) { + uint8_t *limit = mem + len*4; + while (mem < limit) { + *mem = BLEND_BYTE(*mem, r, o); + mem++; + *mem = BLEND_BYTE(*mem, g, o); + mem++; + *mem = BLEND_BYTE(*mem, b, o); + mem += 2; + } } +/* TODO: RGB color clut, only b/w now */ void blend_rgb16 (uint8_t * img, vo_overlay_t * img_overl, int dst_width, int dst_height) { - u_int myclut[] = { - 0x0000, - 0x20e2, - 0x83ac, - 0x4227, - 0xa381, - 0xad13, - 0xbdf8, - 0xd657, - 0xee67, - 0x6a40, - 0xd4c1, - 0xf602, - 0xf664, - 0xe561, - 0xad13, - 0xffdf, - }; - - BLEND (16, img, img_overl, dst_width, dst_height); - //blend_tux_rgb16 (img, dst_width, dst_height); + uint8_t *my_trans; + uint16_t my_clut[4]; + clut_t* clut = (clut_t*) img_overl->color; + + int src_width = img_overl->width; + int src_height = img_overl->height; + rle_elem_t *rle = img_overl->rle; + 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 x, y; + + uint16_t *dst_pix = (uint16_t *) img; + dst_pix += dst_width * y_off + x_off; + + for (x = 0; x < 4; x++) { + uint16_t clr = clut[x].y >> 2; + my_clut[x] = (clr & 0xfe) << 10 | clr << 5 | (clr >> 1); + } + my_trans = img_overl->trans; + + for (y = 0; y < src_height; y++) { + mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); + + for (x = 0; x < src_width;) { + uint8_t clr; + uint16_t o; + + clr = rle->color; + o = my_trans[clr]; + + if (o) if (img_overl->clip_left > x || + img_overl->clip_right < x) + o = 0; + + if (o && mask) { + mem_blend16(dst_pix+x, my_clut[clr], o, rle->len); + } + + x += rle->len; + rle++; + if (rle >= rle_limit) break; + } + if (rle >= rle_limit) break; + dst_pix += dst_width; + } } +/* TODO: RGB color clut, only b/w now */ void blend_rgb24 (uint8_t * img, vo_overlay_t * img_overl, int dst_width, int dst_height) { -//FIXME CLUT - u_int myclut[] = { - 0x0000, - 0x20e2, - 0x83ac, - 0x4227, - 0xa381, - 0xad13, - 0xbdf8, - 0xd657, - 0xee67, - 0x6a40, - 0xd4c1, - 0xf602, - 0xf664, - 0xe561, - 0xad13, - 0xffdf, - }; - BLEND (24, img, img_overl, dst_width, dst_height); + clut_t *my_clut; + uint8_t *my_trans; + int src_width = img_overl->width; + int src_height = img_overl->height; + rle_elem_t *rle = img_overl->rle; + 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 x, y; + + uint8_t *dst_pix = img + (dst_width * y_off + x_off) * 3; + + my_clut = (clut_t*) img_overl->color; + my_trans = img_overl->trans; + + for (y = 0; y < src_height; y++) { + mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); + + for (x = 0; x < src_width;) { + uint8_t clr; + uint16_t o; + + clr = rle->color; + o = my_trans[clr]; + + if (o) if (img_overl->clip_left > x || + img_overl->clip_right < x) + o = 0; + + if (o && mask) { + uint8_t v = my_clut[clr].y; + mem_blend24(dst_pix + x*3, v, v, v, o, rle->len); + } + + x += rle->len; + rle++; + if (rle >= rle_limit) break; + } + if (rle >= rle_limit) break; + dst_pix += dst_width * 3; + } } +/* TODO: RGB color clut, only b/w now */ void blend_rgb32 (uint8_t * img, vo_overlay_t * img_overl, int dst_width, int dst_height) { -//FIXME CLUT - u_int myclut[] = { - 0x0000, - 0x20e2, - 0x83ac, - 0x4227, - 0xa381, - 0xad13, - 0xbdf8, - 0xd657, - 0xee67, - 0x6a40, - 0xd4c1, - 0xf602, - 0xf664, - 0xe561, - 0xad13, - 0xffdf, - }; - BLEND (32, img, img_overl, dst_width, dst_height); + clut_t *my_clut; + uint8_t *my_trans; + int src_width = img_overl->width; + int src_height = img_overl->height; + rle_elem_t *rle = img_overl->rle; + 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 x, y; + + uint8_t *dst_pix = img + (dst_width * y_off + x_off) * 4; + + my_clut = (clut_t*) img_overl->color; + my_trans = img_overl->trans; + + for (y = 0; y < src_height; y++) { + mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); + + for (x = 0; x < src_width;) { + uint8_t clr; + uint16_t o; + + clr = rle->color; + o = my_trans[clr]; + + if (o) if (img_overl->clip_left > x || + img_overl->clip_right < x) + o = 0; + + if (o && mask) { + uint8_t v = my_clut[clr].y; + mem_blend32(dst_pix + x*4, v, v, v, o, rle->len); + } + + x += rle->len; + rle++; + if (rle >= rle_limit) break; + } + if (rle >= rle_limit) break; + dst_pix += dst_width * 4; + } } -#define BLEND_YUV(dst, src, o) (((src)*o + ((dst)*(0xf-o)))/0xf) +static void mem_blend8(uint8_t *mem, uint8_t val, uint8_t o, size_t sz) +{ + uint8_t *limit = mem + sz; + while (mem < limit) { + *mem = BLEND_BYTE(*mem, val, o); + mem++; + } +} void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl, int dst_width, int dst_height) @@ -225,100 +243,64 @@ void blend_yuv (uint8_t * dst_img, vo_overlay_t * img_overl, int src_width = img_overl->width; int src_height = img_overl->height; - uint8_t *src_data = img_overl->data; - int step=dst_width - src_width; + rle_elem_t *rle = img_overl->rle; + 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 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_img + (dst_width * dst_height * 5) / 4 + - (y_off / 2) * (dst_width / 2) + (x_off / 2) + 1; - - int x, y; + uint8_t *dst_cb = dst_cr + (dst_width * dst_height) / 4; my_clut = (clut_t*) img_overl->color; my_trans = img_overl->trans; for (y = 0; y < src_height; y++) { - for (x = 0; x < src_width; x++) { + mask = !(img_overl->clip_top > y || img_overl->clip_bottom < y); + + for (x = 0; x < src_width;) { uint8_t clr; uint16_t o; - clr = *src_data & 3; + clr = rle->color; o = my_trans[clr]; - /* OK, this looks time consuming. - * But it gets only evaluated if (o != 0) */ + /* These three lines assume that menu buttons are "clean" separated + * and do not overlap with the button clip borders */ if (o) if (img_overl->clip_left > x || - img_overl->clip_right < x || - img_overl->clip_top > y || - img_overl->clip_bottom < y) + img_overl->clip_right < x) o = 0; - if (o) - *dst_y = BLEND_YUV (*dst_y, my_clut[clr].y, o); - dst_y++; - - if (y & x & 1) { - if(o) { - *dst_cr = BLEND_YUV (*dst_cr, my_clut[clr].cr, o); - *dst_cb = BLEND_YUV (*dst_cb, my_clut[clr].cb, o); + if (o && mask) { + if (o >= 15) { + memset(dst_y + x, my_clut[clr].y, rle->len); + if (y & 1) { + memset(dst_cr + (x >> 1), my_clut[clr].cr, rle->len >> 1); + memset(dst_cb + (x >> 1), my_clut[clr].cb, rle->len >> 1); + } + } else { + mem_blend8(dst_y + x, my_clut[clr].y, o, rle->len); + if (y & 1) { + mem_blend8(dst_cr + (x >> 1), my_clut[clr].cr, o, rle->len >> 1); + mem_blend8(dst_cb + (x >> 1), my_clut[clr].cb, o, rle->len >> 1); + } } - dst_cr++; - dst_cb++; } - src_data++; + + x += rle->len; + rle++; + if (rle >= rle_limit) break; } + if (rle >= rle_limit) break; - dst_y += step; + dst_y += dst_width; if (y & 1) { - dst_cr += (step + 1) / 2; - dst_cb += (step + 1) / 2; + dst_cr += (dst_width + 1) / 2; + dst_cb += (dst_width + 1) / 2; } } } - -inline int is_blank (uint8_t * ptr, int width) -{ - int x; - - for (x = 0; x < width; x++) { - if ((*ptr & 0x0f) && (*ptr >> 4)) - return 0; // color != 0 && alpha != 0 - ptr++; - } - - return 1; // blank line -} - -void crop_overlay (vo_overlay_t * overlay) -{ - uint8_t *data = overlay->data; - int height = overlay->height; - int width = overlay->width; - int y; - - /* - * Shrink from bottom - */ - - for (y=height - 1;y >= 0 && is_blank (&data[y * width], width); y--); - height = y + 1; - - /* - * Shrink from top - */ - for (y=0; y < height && is_blank (&data[y * width], width); y++); - height -= y; - - /* - * Shift data - */ - overlay->y -= y; - overlay->height = height; - - memcpy (data, &data[y * width], height * width); -} diff --git a/src/xine-engine/video_out.h b/src/xine-engine/video_out.h index fbe2b9c60..03c68a7ca 100644 --- a/src/xine-engine/video_out.h +++ b/src/xine-engine/video_out.h @@ -17,7 +17,7 @@ * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA * - * $Id: video_out.h,v 1.16 2001/08/13 12:52:33 ehasenle Exp $ + * $Id: video_out.h,v 1.17 2001/08/17 15:54:31 ehasenle Exp $ * * * xine version of video_out.h @@ -263,9 +263,16 @@ struct vo_driver_s { }; +typedef struct rle_elem_s { + uint16_t len; + uint16_t color; +} rle_elem_t; + struct vo_overlay_s { - uint8_t *data; /* 7-4: mixer key, 3-0: color index */ + + rle_elem_t *rle; /* rle code buffer */ int data_size; /* useful for deciding realloc */ + int num_rle; /* number of active rle codes */ int x; /* x start of subpicture area */ int y; /* y start of subpicture area */ int width; /* width of subpicture area */ |