summaryrefslogtreecommitdiff
path: root/src/xine-engine/video_overlay.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/xine-engine/video_overlay.c')
-rw-r--r--src/xine-engine/video_overlay.c122
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.
*/