# HG changeset patch # User cigaes # Date 1335131559 0 # Node ID d180a74b1a898acb7be072e9d0cd617e57a31a0c # Parent 1d4795fbdb67e6d6a4cae5b1701422ed1640d3cb av_sub: support multiple rectangles. The "packet_t" structure is renamed with a prefix, because it is used a public header. diff -r 1d4795fbdb67 -r d180a74b1a89 sub/av_sub.c --- a/sub/av_sub.c Sun Apr 22 12:10:49 2012 +0000 +++ b/sub/av_sub.c Sun Apr 22 21:52:39 2012 +0000 @@ -32,6 +32,47 @@ } } +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 @@ -90,16 +131,7 @@ 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; case SUBTITLE_TEXT: diff -r 1d4795fbdb67 -r d180a74b1a89 sub/spudec.c --- a/sub/spudec.c Sun Apr 22 12:10:49 2012 +0000 +++ b/sub/spudec.c Sun Apr 22 21:52:39 2012 +0000 @@ -57,8 +57,8 @@ int spu_alignment = -1; float spu_gaussvar = 1.0; -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; @@ -1349,25 +1349,12 @@ #define MP_NOPTS_VALUE (-1LL<<63) //both int64_t and double should be able to represent this exactly -/** - * 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) +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; @@ -1377,21 +1364,47 @@ 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) @@ -1400,3 +1413,20 @@ 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 -r 1d4795fbdb67 -r d180a74b1a89 sub/spudec.h --- a/sub/spudec.h Sun Apr 22 12:10:49 2012 +0000 +++ b/sub/spudec.h Sun Apr 22 21:52:39 2012 +0000 @@ -41,5 +41,13 @@ 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 */