From 0dc290269d925bd3bc7ed63a1b63edc13e8b2ab1 Mon Sep 17 00:00:00 2001 From: mplayer-svn Date: Sun, 22 Apr 2012 21:52:39 +0000 Subject: av_sub, spudec: support multiple rectangles av_sub: support multiple rectangles. The "packet_t" structure is renamed with a prefix, because it is used a public header. git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@34872 b3059339-0415-0410-9bf9-f77b7e298cf2 Author: cigaes --- sub/av_sub.c | 52 ++++++++++++++++++++++++++------- sub/spudec.c | 94 ++++++++++++++++++++++++++++++++++++++++-------------------- sub/spudec.h | 8 ++++++ 3 files changed, 113 insertions(+), 41 deletions(-) (limited to 'sub') diff --git a/sub/av_sub.c b/sub/av_sub.c index 3a9e1b4f26..56acfc63ca 100644 --- a/sub/av_sub.c +++ b/sub/av_sub.c @@ -32,6 +32,47 @@ void reset_avsub(struct sh_sub *sh) } } +static void avsub_to_spudec(AVSubtitleRect **rects, int num_rects, + double pts, double endpts) +{ + int i, xmin = INT_MAX, ymin = INT_MAX, xmax = INT_MIN, ymax = INT_MIN; + struct spu_packet_t *packet; + + if (num_rects == 1) { + spudec_set_paletted(vo_spudec, + rects[0]->pict.data[0], + rects[0]->pict.linesize[0], + rects[0]->pict.data[1], + rects[0]->x, + rects[0]->y, + rects[0]->w, + rects[0]->h, + pts, + endpts); + return; + } + for (i = 0; i < num_rects; i++) { + xmin = FFMIN(xmin, rects[i]->x); + ymin = FFMIN(ymin, rects[i]->y); + xmax = FFMAX(xmax, rects[i]->x + rects[i]->w); + ymax = FFMAX(ymax, rects[i]->y + rects[i]->h); + } + packet = spudec_packet_create(xmin, ymin, xmax - xmin, ymax - ymin); + if (!packet) + return; + spudec_packet_clear(packet); + for (i = 0; i < num_rects; i++) + spudec_packet_fill(packet, + rects[i]->pict.data[0], + rects[i]->pict.linesize[0], + rects[i]->pict.data[1], + rects[i]->x - xmin, + rects[i]->y - ymin, + rects[i]->w, + rects[i]->h); + spudec_packet_send(vo_spudec, packet, pts, endpts); +} + /** * Decode a subtitle packet via libavcodec. * \return < 0 on error, > 0 if further processing is needed @@ -96,16 +137,7 @@ int decode_avsub(struct sh_sub *sh, uint8_t *data, int size, case SUBTITLE_BITMAP: if (!vo_spudec) vo_spudec = spudec_new_scaled(NULL, ctx->width, ctx->height, NULL, 0); - spudec_set_paletted(vo_spudec, - sub.rects[0]->pict.data[0], - sub.rects[0]->pict.linesize[0], - sub.rects[0]->pict.data[1], - sub.rects[0]->x, - sub.rects[0]->y, - sub.rects[0]->w, - sub.rects[0]->h, - pts, - endpts); + avsub_to_spudec(sub.rects, sub.num_rects, pts, endpts); vo_osd_changed(OSDTYPE_SPU); break; default: diff --git a/sub/spudec.c b/sub/spudec.c index 6eabaf5723..33a5aabba1 100644 --- a/sub/spudec.c +++ b/sub/spudec.c @@ -60,8 +60,8 @@ int spu_alignment = -1; float spu_gaussvar = 1.0; extern int sub_pos; -typedef struct packet_t packet_t; -struct packet_t { +typedef struct spu_packet_t packet_t; +struct spu_packet_t { int is_decoded; unsigned char *packet; int data_len; @@ -1324,25 +1324,14 @@ void spudec_free(void *this) } } -/** - * palette must contain at least 256 32-bit entries, otherwise crashes - * are possible - */ -void spudec_set_paletted(void *this, const uint8_t *pal_img, int pal_stride, - const void *palette, - int x, int y, int w, int h, - double pts, double endpts) +#define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly + +packet_t *spudec_packet_create(int x, int y, int w, int h) { - int i; - uint16_t g8a8_pal[256]; packet_t *packet; - const uint32_t *pal = palette; - spudec_handle_t *spu = this; - uint8_t *img; - uint8_t *aimg; int stride = (w + 7) & ~7; if ((unsigned)w >= 0x8000 || (unsigned)h > 0x4000) - return; + return NULL; packet = calloc(1, sizeof(packet_t)); packet->is_decoded = 1; packet->width = w; @@ -1352,21 +1341,47 @@ void spudec_set_paletted(void *this, const uint8_t *pal_img, int pal_stride, packet->start_row = y; packet->data_len = 2 * stride * h; if (packet->data_len) { // size 0 is a special "clear" packet - packet->packet = malloc(packet->data_len); - img = packet->packet; - aimg = packet->packet + stride * h; - for (i = 0; i < 256; i++) { - uint32_t pixel = pal[i]; - int alpha = pixel >> 24; - int gray = (((pixel & 0x000000ff) >> 0) + - ((pixel & 0x0000ff00) >> 7) + - ((pixel & 0x00ff0000) >> 16)) >> 2; - gray = FFMIN(gray, alpha); - g8a8_pal[i] = (-alpha << 8) | gray; - } - pal2gray_alpha(g8a8_pal, pal_img, pal_stride, - img, aimg, stride, w, h); + packet->packet = malloc(packet->data_len); + if (!packet->packet) { + free(packet); + packet = NULL; + } + } + return packet; +} + +void spudec_packet_clear(packet_t *packet) +{ + /* clear alpha and value, as value is premultiplied */ + memset(packet->packet, 0, packet->data_len); +} + +void spudec_packet_fill(packet_t *packet, + const uint8_t *pal_img, int pal_stride, + const void *palette, + int x, int y, int w, int h) +{ + const uint32_t *pal = palette; + uint8_t *img = packet->packet + x + y * packet->stride; + uint8_t *aimg = img + packet->stride * packet->height; + int i; + uint16_t g8a8_pal[256]; + + for (i = 0; i < 256; i++) { + uint32_t pixel = pal[i]; + int alpha = pixel >> 24; + int gray = (((pixel & 0x000000ff) >> 0) + + ((pixel & 0x0000ff00) >> 7) + + ((pixel & 0x00ff0000) >> 16)) >> 2; + gray = FFMIN(gray, alpha); + g8a8_pal[i] = (-alpha << 8) | gray; } + pal2gray_alpha(g8a8_pal, pal_img, pal_stride, + img, aimg, packet->stride, w, h); +} + +void spudec_packet_send(void *spu, packet_t *packet, double pts, double endpts) +{ packet->start_pts = 0; packet->end_pts = 0x7fffffff; if (pts != MP_NOPTS_VALUE) @@ -1375,3 +1390,20 @@ void spudec_set_paletted(void *this, const uint8_t *pal_img, int pal_stride, packet->end_pts = endpts * 90000; spudec_queue_packet(spu, packet); } + +/** + * palette must contain at least 256 32-bit entries, otherwise crashes + * are possible + */ +void spudec_set_paletted(void *spu, const uint8_t *pal_img, int pal_stride, + const void *palette, + int x, int y, int w, int h, + double pts, double endpts) +{ + packet_t *packet = spudec_packet_create(x, y, w, h); + if (!packet) + return; + if (packet->data_len) // size 0 is a special "clear" packet + spudec_packet_fill(packet, pal_img, pal_stride, palette, 0, 0, w, h); + spudec_packet_send(spu, packet, pts, endpts); +} diff --git a/sub/spudec.h b/sub/spudec.h index ad7ece4f7a..533ac511e8 100644 --- a/sub/spudec.h +++ b/sub/spudec.h @@ -39,5 +39,13 @@ void spudec_set_paletted(void *this, const uint8_t *pal_img, int stride, const void *palette, int x, int y, int w, int h, double pts, double endpts); +struct spu_packet_t *spudec_packet_create(int x, int y, int w, int h); +void spudec_packet_fill(struct spu_packet_t *packet, + const uint8_t *pal_img, int pal_stride, + const void *palette, + int x, int y, int w, int h); +void spudec_packet_send(void *spu, struct spu_packet_t *packet, + double pts, double endpts); +void spudec_packet_clear(struct spu_packet_t *packet); #endif /* MPLAYER_SPUDEC_H */ -- cgit v1.2.3