summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/xine/video_overlay.h1
-rw-r--r--src/video_out/video_out_opengl2.c132
-rw-r--r--src/video_out/video_out_raw.c45
-rw-r--r--src/video_out/video_out_vaapi.c51
-rw-r--r--src/xine-engine/alphablend.c9
-rw-r--r--src/xine-engine/video_overlay.c162
6 files changed, 171 insertions, 229 deletions
diff --git a/include/xine/video_overlay.h b/include/xine/video_overlay.h
index 9fc9f9202..c82227513 100644
--- a/include/xine/video_overlay.h
+++ b/include/xine/video_overlay.h
@@ -62,5 +62,6 @@ typedef struct video_overlay_event_s {
video_overlay_manager_t *_x_video_overlay_new_manager(xine_t *) XINE_MALLOC XINE_PROTECTED;
void _x_overlay_clut_yuv2rgb(vo_overlay_t *overlay) XINE_PROTECTED;
+void _x_overlay_to_argb32(const vo_overlay_t *overlay, uint32_t *rgba, int stride, const char *format) XINE_PROTECTED;
#endif
diff --git a/src/video_out/video_out_opengl2.c b/src/video_out/video_out_opengl2.c
index 4de8ccfec..0fc66ef6e 100644
--- a/src/video_out/video_out_opengl2.c
+++ b/src/video_out/video_out_opengl2.c
@@ -519,87 +519,33 @@ static int opengl2_check_textures_size( opengl2_driver_t *this_gen, int w, int h
return 1;
}
-static int opengl2_process_ovl( opengl2_driver_t *this_gen, vo_overlay_t *overlay )
-{
- //fprintf(stderr, "opengl2_process_ovl\n");
- opengl2_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1];
- if ( overlay->width<=0 || overlay->height<=0 )
- return 0;
+static void opengl2_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed)
+{
+ //fprintf(stderr, "opengl2_overlay_begin\n");
+ opengl2_driver_t *this = (opengl2_driver_t *) this_gen;
- if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) )
- ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 );
- ovl->ovl_w = overlay->width;
- ovl->ovl_h = overlay->height;
- ovl->ovl_x = overlay->x;
- ovl->ovl_y = overlay->y;
- ovl->unscaled = overlay->unscaled;
- ovl->extent_width = overlay->extent_width;
- ovl->extent_height = overlay->extent_height;
- if ( overlay->extent_width == -1 )
- ovl->vid_scale = 1;
- else
- ovl->vid_scale = 0;
- ovl->type = GL_RGBA;
-
- int num_rle = overlay->num_rle;
- rle_elem_t *rle = overlay->rle;
- uint8_t *rgba = ovl->ovl_rgba;
- clut_t *low_colors = (clut_t*)overlay->color;
- clut_t *hili_colors = (clut_t*)overlay->hili_color;
- uint8_t *low_trans = overlay->trans;
- uint8_t *hili_trans = overlay->hili_trans;
- clut_t *colors;
- uint8_t *trans;
- uint8_t alpha;
- int rlelen = 0;
- uint8_t clr = 0;
- int i, pos=0, x, y;
-
- while ( num_rle>0 ) {
- x = pos%ovl->ovl_w;
- y = pos/ovl->ovl_w;
- if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) {
- colors = hili_colors;
- trans = hili_trans;
- }
- else {
- colors = low_colors;
- trans = low_trans;
- }
- rlelen = rle->len;
- clr = rle->color;
- alpha = trans[clr];
- for ( i=0; i<rlelen; ++i ) {
- if ( alpha == 0 ) {
- rgba[0] = rgba[1] = rgba[2] = rgba[3] = 0;
- }
- else {
- rgba[0] = colors[clr].y;
- rgba[1] = colors[clr].cr;
- rgba[2] = colors[clr].cb;
- rgba[3] = alpha*255/15;
- }
- rgba+= 4;
- ++pos;
- }
- ++rle;
- --num_rle;
- }
- return 1;
+ if ( changed )
+ this->ovl_changed = 1;
}
-static int opengl2_process_rgba_ovl( opengl2_driver_t *this_gen, vo_overlay_t *overlay )
+static void opengl2_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay)
{
- opengl2_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1];
+ opengl2_driver_t *this = (opengl2_driver_t *) this_gen;
+
+ if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL )
+ return;
if ( overlay->width<=0 || overlay->height<=0 )
- return 0;
+ return;
- if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) )
- ovl->ovl_rgba = (uint8_t*)realloc( ovl->ovl_rgba, overlay->width*overlay->height*4 );
+ opengl2_overlay_t *ovl = &this->overlays[this->ovl_changed-1];
+ if ( (overlay->width*overlay->height)!=(ovl->ovl_w*ovl->ovl_h) ) {
+ free(ovl->ovl_rgba);
+ ovl->ovl_rgba = (uint8_t*)malloc( overlay->width*overlay->height*sizeof(uint32_t) );
+ }
ovl->ovl_w = overlay->width;
ovl->ovl_h = overlay->height;
ovl->ovl_x = overlay->x;
@@ -613,46 +559,22 @@ static int opengl2_process_rgba_ovl( opengl2_driver_t *this_gen, vo_overlay_t *o
ovl->vid_scale = 0;
ovl->type = GL_BGRA;
- memcpy(ovl->ovl_rgba, overlay->argb_layer->buffer, overlay->width * overlay->height * 4);
-
- return 1;
-}
-
-
-static void opengl2_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed)
-{
- //fprintf(stderr, "opengl2_overlay_begin\n");
- opengl2_driver_t *this = (opengl2_driver_t *) this_gen;
-
- if ( changed )
- this->ovl_changed = 1;
-}
-
-
-static void opengl2_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay)
-{
- opengl2_driver_t *this = (opengl2_driver_t *) this_gen;
-
- if ( !this->ovl_changed || this->ovl_changed>XINE_VORAW_MAX_OVL )
- return;
-
if (overlay->argb_layer && overlay->argb_layer->buffer) {
-
pthread_mutex_lock(&overlay->argb_layer->mutex); /* buffer can be changed or freed while unlocked */
+ memcpy(ovl->ovl_rgba, overlay->argb_layer->buffer, overlay->width * overlay->height * sizeof(uint32_t));
+ /* TODO: this could be done without this memcpy() ... */
+ pthread_mutex_unlock(&overlay->argb_layer->mutex);
+
+ ++this->ovl_changed;
- if (overlay->argb_layer->buffer) {
- if ( opengl2_process_rgba_ovl( this, overlay ) )
- ++this->ovl_changed;
+ } else if (overlay->rle) {
+ if (!overlay->rgb_clut || !overlay->hili_rgb_clut) {
+ _x_overlay_clut_yuv2rgb(overlay);
}
- pthread_mutex_unlock(&overlay->argb_layer->mutex);
- }
+ _x_overlay_to_argb32(overlay, (uint32_t*)ovl->ovl_rgba, overlay->width, "BGRA");
- else if (overlay->rle) {
- if (!overlay->rgb_clut || !overlay->hili_rgb_clut)
- _x_overlay_clut_yuv2rgb(overlay);
- if ( opengl2_process_ovl( this, overlay ) )
- ++this->ovl_changed;
+ ++this->ovl_changed;
}
}
diff --git a/src/video_out/video_out_raw.c b/src/video_out/video_out_raw.c
index 702c7dc2e..a19285707 100644
--- a/src/video_out/video_out_raw.c
+++ b/src/video_out/video_out_raw.c
@@ -115,50 +115,7 @@ static int raw_process_ovl( raw_driver_t *this_gen, vo_overlay_t *overlay )
ovl->ovl_x = overlay->x;
ovl->ovl_y = overlay->y;
- int num_rle = overlay->num_rle;
- rle_elem_t *rle = overlay->rle;
- uint8_t *rgba = ovl->ovl_rgba;
- clut_t *low_colors = (clut_t*)overlay->color;
- clut_t *hili_colors = (clut_t*)overlay->hili_color;
- uint8_t *low_trans = overlay->trans;
- uint8_t *hili_trans = overlay->hili_trans;
- clut_t *colors;
- uint8_t *trans;
- uint8_t alpha;
- int rlelen = 0;
- uint8_t clr = 0;
- int i, pos=0, x, y;
-
- while ( num_rle>0 ) {
- x = pos%ovl->ovl_w;
- y = pos/ovl->ovl_w;
- if ( (x>=overlay->hili_left && x<=overlay->hili_right) && (y>=overlay->hili_top && y<=overlay->hili_bottom) ) {
- colors = hili_colors;
- trans = hili_trans;
- }
- else {
- colors = low_colors;
- trans = low_trans;
- }
- rlelen = rle->len;
- clr = rle->color;
- alpha = trans[clr];
- for ( i=0; i<rlelen; ++i ) {
- if ( alpha == 0 ) {
- rgba[0] = rgba[1] = rgba[2] = rgba[3] = 0;
- }
- else {
- rgba[0] = colors[clr].y;
- rgba[1] = colors[clr].cr;
- rgba[2] = colors[clr].cb;
- rgba[3] = alpha*255/15;
- }
- rgba+= 4;
- ++pos;
- }
- ++rle;
- --num_rle;
- }
+ _x_overlay_to_argb32(overlay, (uint32_t*)ovl->ovl_rgba, overlay->width, "RGBA");
return 1;
}
diff --git a/src/video_out/video_out_vaapi.c b/src/video_out/video_out_vaapi.c
index af759c2ff..823d0fc5a 100644
--- a/src/video_out/video_out_vaapi.c
+++ b/src/video_out/video_out_vaapi.c
@@ -2717,7 +2717,6 @@ static void vaapi_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
for (i = 0; i < novls; ++i) {
vo_overlay_t *ovl = this->overlays[i];
uint32_t *bitmap = NULL;
- uint32_t *rgba = NULL;
if (ovl->rle) {
if(ovl->width<=0 || ovl->height<=0)
@@ -2726,52 +2725,10 @@ static void vaapi_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame_gen) {
if (!ovl->rgb_clut || !ovl->hili_rgb_clut)
_x_overlay_clut_yuv2rgb (ovl);
- bitmap = rgba = calloc(ovl->width * ovl->height * 4, sizeof(uint32_t));
-
- int num_rle = ovl->num_rle;
- rle_elem_t *rle = ovl->rle;
- uint32_t red, green, blue, alpha;
- clut_t *low_colors = (clut_t*)ovl->color;
- clut_t *hili_colors = (clut_t*)ovl->hili_color;
- uint8_t *low_trans = ovl->trans;
- uint8_t *hili_trans = ovl->hili_trans;
- clut_t *colors;
- uint8_t *trans;
- int rlelen = 0;
- uint8_t clr = 0;
- int i, pos=0, x, y;
-
- while (num_rle > 0) {
- x = pos % ovl->width;
- y = pos / ovl->width;
-
- if ( (x>=ovl->hili_left && x<=ovl->hili_right) && (y>=ovl->hili_top && y<=ovl->hili_bottom) ) {
- colors = hili_colors;
- trans = hili_trans;
- }
- else {
- colors = low_colors;
- trans = low_trans;
- }
- rlelen = rle->len;
- clr = rle->color;
- for ( i=0; i<rlelen; ++i ) {
- if ( trans[clr] == 0 ) {
- alpha = red = green = blue = 0;
- }
- else {
- red = colors[clr].y; // red
- green = colors[clr].cr; // green
- blue = colors[clr].cb; // blue
- alpha = trans[clr]*255/15;
- }
- *rgba = (alpha<<24) | (red<<16) | (green<<8) | blue;
- rgba++;
- ++pos;
- }
- ++rle;
- --num_rle;
- }
+ bitmap = malloc(ovl->width * ovl->height * sizeof(uint32_t));
+
+ _x_overlay_to_argb32(ovl, bitmap, ovl->width, "BGRA");
+
lprintf("width %d height %d pos %d %d\n", ovl->width, ovl->height, pos, ovl->width * ovl->height);
} else {
pthread_mutex_lock(&ovl->argb_layer->mutex);
diff --git a/src/xine-engine/alphablend.c b/src/xine-engine/alphablend.c
index 0b5e3252f..d63cc546b 100644
--- a/src/xine-engine/alphablend.c
+++ b/src/xine-engine/alphablend.c
@@ -1121,7 +1121,7 @@ static uint8_t *(*blend_yuv_grow_extra_data(alphablend_t *extra_data, int osd_wi
if (extra_data->buffer_size < needed_buffer_size) {
- free(extra_data->buffer);
+ _x_freep(&extra_data->buffer);
header = calloc(1, needed_buffer_size);
if (!header) {
extra_data->buffer_size = 0;
@@ -1566,7 +1566,7 @@ static uint8_t *(*blend_yuy2_grow_extra_data(alphablend_t *extra_data, int osd_w
if (extra_data->buffer_size < needed_buffer_size) {
- free(extra_data->buffer);
+ _x_freep(&extra_data->buffer);
header = calloc(1, needed_buffer_size);
if (!header) {
extra_data->buffer_size = 0;
@@ -2163,10 +2163,7 @@ void _x_alphablend_init(alphablend_t *extra_data, xine_t *xine)
void _x_alphablend_free(alphablend_t *extra_data)
{
- if (extra_data->buffer) {
- free(extra_data->buffer);
- extra_data->buffer = NULL;
- }
+ _x_freep(&extra_data->buffer);
extra_data->buffer_size = 0;
}
diff --git a/src/xine-engine/video_overlay.c b/src/xine-engine/video_overlay.c
index fe9caee34..e044d9d90 100644
--- a/src/xine-engine/video_overlay.c
+++ b/src/xine-engine/video_overlay.c
@@ -124,10 +124,8 @@ static void remove_events_handle( video_overlay_t *this, int32_t handle, int loc
/* free its overlay */
if( this->events[this_event].event->object.overlay ) {
- if( this->events[this_event].event->object.overlay->rle )
- free( this->events[this_event].event->object.overlay->rle );
- free(this->events[this_event].event->object.overlay);
- this->events[this_event].event->object.overlay = NULL;
+ _x_freep( &this->events[this_event].event->object.overlay->rle );
+ _x_freep( &this->events[this_event].event->object.overlay );
}
/* mark as free */
@@ -176,10 +174,8 @@ static void internal_video_overlay_free_handle(video_overlay_t *this, int32_t ha
if( this->objects[handle].overlay ) {
set_argb_layer_ptr(&this->objects[handle].overlay->argb_layer, NULL);
- if( this->objects[handle].overlay->rle )
- free( this->objects[handle].overlay->rle );
- free( this->objects[handle].overlay );
- this->objects[handle].overlay = NULL;
+ _x_freep( &this->objects[handle].overlay->rle );
+ _x_freep( &this->objects[handle].overlay );
}
this->objects[handle].handle = -1;
@@ -400,10 +396,8 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) {
if (this->events[this_event].event->object.overlay != NULL) {
set_argb_layer_ptr(&this->events[this_event].event->object.overlay->argb_layer, NULL);
- if( this->events[this_event].event->object.overlay->rle != NULL )
- free( this->events[this_event].event->object.overlay->rle );
- free(this->events[this_event].event->object.overlay);
- this->events[this_event].event->object.overlay = NULL;
+ _x_freep( &this->events[this_event].event->object.overlay->rle );
+ _x_freep( &this->events[this_event].event->object.overlay );
}
remove_showing_handle( this, handle );
break;
@@ -416,10 +410,8 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) {
if( this->events[this_event].event->object.overlay != NULL) {
set_argb_layer_ptr(&this->events[this_event].event->object.overlay->argb_layer, NULL);
- if( this->events[this_event].event->object.overlay->rle != NULL )
- free( this->events[this_event].event->object.overlay->rle );
- free(this->events[this_event].event->object.overlay);
- this->events[this_event].event->object.overlay = NULL;
+ _x_freep( &this->events[this_event].event->object.overlay->rle );
+ _x_freep( &this->events[this_event].event->object.overlay );
}
/* this avoid removing this_event from the queue
* (it will be removed at the end of this loop) */
@@ -480,14 +472,9 @@ static int video_overlay_event( video_overlay_t *this, int64_t vpts ) {
if( this->events[this_event].event->object.overlay->rle ) {
xprintf (this->xine, XINE_VERBOSITY_DEBUG, "video_overlay: warning EVENT_MENU_BUTTON with rle data\n");
- free( this->events[this_event].event->object.overlay->rle );
- this->events[this_event].event->object.overlay->rle = NULL;
- }
-
- if (this->events[this_event].event->object.overlay != NULL) {
- free (this->events[this_event].event->object.overlay);
- this->events[this_event].event->object.overlay = NULL;
+ _x_freep( &this->events[this_event].event->object.overlay->rle );
}
+ _x_freep (&this->events[this_event].event->object.overlay);
break;
default:
@@ -520,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.
*/
@@ -587,11 +696,10 @@ static void video_overlay_dispose(video_overlay_manager_t *this_gen) {
for (i=0; i < MAX_EVENTS; i++) {
if (this->events[i].event != NULL) {
if (this->events[i].event->object.overlay != NULL) {
- if (this->events[i].event->object.overlay->rle)
- free (this->events[i].event->object.overlay->rle);
- free (this->events[i].event->object.overlay);
+ _x_freep (&this->events[i].event->object.overlay->rle);
+ _x_freep (&this->events[i].event->object.overlay);
}
- free (this->events[i].event);
+ _x_freep (&this->events[i].event);
}
}