diff options
Diffstat (limited to 'src/xine-engine/video_overlay.c')
-rw-r--r-- | src/xine-engine/video_overlay.c | 122 |
1 files changed, 122 insertions, 0 deletions
diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c index c45396232..e044d9d90 100644 --- a/src/xine-engine/video_overlay.c +++ b/src/xine-engine/video_overlay.c @@ -507,6 +507,128 @@ void _x_overlay_clut_yuv2rgb(vo_overlay_t *overlay) } } +static void clut_to_argb(const uint32_t *color, const uint8_t *trans, int num_items, uint32_t *argb, const char *format) +{ + int i; + union { + uint32_t u32; + clut_t c; + } tmp ; + + if (!strcmp(format, "BGRA")) { + for (i = 0; i < num_items; i++) { + tmp.u32 = color[i]; + uint8_t *rgba = (uint8_t*)(argb + i); + rgba[0] = tmp.c.cb; + rgba[1] = tmp.c.cr; + rgba[2] = tmp.c.y; + rgba[3] = trans[i] * 255 / 15; + } + } + else if (!strcmp(format, "RGBA")) { + for (i = 0; i < num_items; i++) { + tmp.u32 = color[i]; + uint8_t *rgba = (uint8_t*)(argb + i); + rgba[0] = tmp.c.y; + rgba[1] = tmp.c.cr; + rgba[2] = tmp.c.cb; + rgba[3] = trans[i] * 255 / 15; + } + } + else { + fprintf(stderr, "clut_to_argb: unknown format %s\n", format); + } +} + +#define LUT_SIZE (sizeof(overlay->color)/sizeof(overlay->color[0])) +#define NEXT_BITE \ + do { \ + if (rle_len < 1) { \ + rle++; \ + if (rle >= rle_end) { \ + /* fill with transparent */ \ + memset(rgba, 0, (overlay->width - x) * sizeof(uint32_t)); \ + rgba += stride; \ + for (; y < overlay->height; y++, rgba += stride) { \ + memset(rgba, 0, stride * sizeof(uint32_t)); \ + } \ + return; \ + } \ + rle_len = rle->len; \ + } \ + } while (0) +#define LIMIT_WIDTH \ + do { \ + x_limit = x + rle_len; \ + if (x_limit > overlay->width) { \ + rle_len = x_limit - overlay->width; \ + x_limit = overlay->width; \ + } else { \ + rle_len = 0; \ + } \ + } while (0) +#define BLEND_LINE \ + do { \ + for (x = 0; x < overlay->width; ) { \ + NEXT_BITE; \ + LIMIT_WIDTH; \ + \ + while (x < x_limit) { \ + rgba[x++] = colors[rle->color]; \ + } \ + } \ + rgba += stride; \ + } while (0) + +void _x_overlay_to_argb32(const vo_overlay_t *overlay, uint32_t *rgba, int stride, const char *format) +{ + const rle_elem_t *rle_end = overlay->rle + overlay->num_rle; + const rle_elem_t *rle = overlay->rle; + int x, y, x_limit; + int rle_len = rle->len; + int no_hili = overlay->hili_bottom < 0 || overlay->hili_bottom < overlay->hili_top || + overlay->hili_right < 0 || overlay->hili_right < overlay->hili_left; + + if (overlay->num_rle < 1) + return; + + if (no_hili) { + uint32_t colors[LUT_SIZE]; + clut_to_argb(overlay->color, overlay->trans, LUT_SIZE, colors, format); + + for (y = 0; y < overlay->height; y++) { + BLEND_LINE; + } + + } else { + uint32_t colors[LUT_SIZE * 2]; + clut_to_argb(overlay->color, overlay->trans, LUT_SIZE, colors, format); + clut_to_argb(overlay->hili_color, overlay->hili_trans, LUT_SIZE, colors + LUT_SIZE, format); + + for (y = 0; y < overlay->height; y++) { + int hili_y = (y >= overlay->hili_top && y <= overlay->hili_bottom); + if (!hili_y) { + BLEND_LINE; + } else { + for (x = 0; x < overlay->width; ) { + NEXT_BITE; + LIMIT_WIDTH; + + while (x < x_limit) { + int hili = (x >= overlay->hili_left && x <= overlay->hili_right); + rgba[x++] = colors[rle->color + hili * LUT_SIZE]; + } + } + rgba += stride; + } + } + } +} +#undef LUT_SIZE +#undef NEXT_BITE +#undef LIMIT_WIDTH +#undef BLEND_LINE + /* This is called from video_out.c * must call output->overlay_blend for each active overlay. */ |