summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/libspudec/spu.c40
-rw-r--r--src/video_out/alphablend.c434
-rw-r--r--src/xine-engine/video_out.h11
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 */