diff options
-rw-r--r-- | include/xine/video_overlay.h | 1 | ||||
-rw-r--r-- | src/video_out/video_out_opengl2.c | 132 | ||||
-rw-r--r-- | src/video_out/video_out_raw.c | 45 | ||||
-rw-r--r-- | src/video_out/video_out_vaapi.c | 51 | ||||
-rw-r--r-- | src/xine-engine/alphablend.c | 9 | ||||
-rw-r--r-- | src/xine-engine/video_overlay.c | 162 |
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); } } |