From 4794ac532c445e72e3ea28809af861cd4e5db019 Mon Sep 17 00:00:00 2001 From: Andreas Auras Date: Thu, 3 Mar 2011 13:03:10 +0100 Subject: Complete rewrite of vdpau output driver osd handling. The new implementation has the following advantages towards the existing one: There is now a unique processing of RLE coded images and ARGB based overlay images. For both formats scaled and unscaled images and a video window are supported. Both formats are rendered now in given order into the same output surfaces not using a dedicated output surface for ARGB images any more. Processing of YCBCR overlay images now uses corresponding vdpau bitmap surfaces eliminating the existing (possible slower) conversation to RGB images. Optimized processing of first overlay from stack avoiding unnecessary surface initialization and rendering operations. Currently the new implementation does not take the dirty rect information of a ARGB overlay into account for optimization (but is there actually a existing player implementation that provides this data?). --HG-- extra : rebase_source : 037f67efdabb0b197e4d1ea2ce14d15f3eb3d8fe --- src/video_out/video_out_vdpau.c | 883 +++++++++++++++++++--------------------- 1 file changed, 430 insertions(+), 453 deletions(-) (limited to 'src') diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 66db3b587..ad713ec0d 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -47,7 +47,6 @@ #include #include #include -#include "yuv2rgb.h" #include #include "accel_vdpau.h" @@ -126,7 +125,9 @@ VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; VdpOutputSurfaceCreate *vdp_output_surface_create; VdpOutputSurfaceDestroy *vdp_output_surface_destroy; VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; +VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits; +VdpOutputSurfacePutBitsYCbCr *vdp_output_surface_put_bits_ycbcr; VdpVideoMixerCreate *vdp_video_mixer_create; VdpVideoMixerDestroy *vdp_video_mixer_destroy; @@ -282,26 +283,6 @@ static VdpStatus guarded_vdp_decoder_render(VdpDecoder decoder, VdpVideoSurface -typedef struct { - VdpBitmapSurface ovl_bitmap; - uint32_t bitmap_width, bitmap_height; - int ovl_w, ovl_h; /* overlay's width and height */ - int ovl_x, ovl_y; /* overlay's top-left display position */ - int unscaled; - int expected_overlay_width; /*if >0 scale to video width*/ - int expected_overlay_height; /* if >0 scale to video height */ -} vdpau_overlay_t; - - -typedef struct { - int x; - int y; - int w; - int h; -} -argb_ovl_data_t; - - typedef struct { vo_frame_t vo_frame; @@ -314,6 +295,13 @@ typedef struct { } vdpau_frame_t; +typedef struct { + int x1, y1, x2, y2; +} vdpau_rect_t; + +#define RECT_IS_EQ(a, b) ((a).x1 == (b).x1 && (a).y1 == (b).y1 && (a).x2 == (b).x2 && (a).y2 == (b).y2) + + typedef struct { vo_driver_t vo_driver; @@ -327,27 +315,25 @@ typedef struct { config_values_t *config; int ovl_changed; - vdpau_overlay_t overlays[XINE_VORAW_MAX_OVL]; - yuv2rgb_factory_t *yuv2rgb_factory; - yuv2rgb_t *ovl_yuv2rgb; - VdpOutputSurface overlay_output; + vo_overlay_t *overlays[XINE_VORAW_MAX_OVL]; + uint32_t *overlay_bitmap; + int overlay_bitmap_size; + + VdpOutputSurface overlay_output_surface; uint32_t overlay_output_width; uint32_t overlay_output_height; + vdpau_rect_t overlay_dirty_rect; int has_overlay; - VdpOutputSurface overlay_unscaled; + VdpOutputSurface overlay_unscaled_surface; uint32_t overlay_unscaled_width; uint32_t overlay_unscaled_height; + vdpau_rect_t overlay_unscaled_dirty_rect; int has_unscaled; - VdpOutputSurface argb_overlay; - uint32_t argb_overlay_width; - uint32_t argb_overlay_height; - int has_argb_overlay; - int argb_ovl_count; - vo_overlay_t *argb_ovl[XINE_VORAW_MAX_OVL]; - int argb_ovl_data_count; - argb_ovl_data_t argb_ovl_data[XINE_VORAW_MAX_OVL]; + VdpOutputSurface overlay_render_surface; + uint32_t overlay_render_width; + uint32_t overlay_render_height; int32_t video_window_x; int32_t video_window_y; @@ -424,410 +410,421 @@ typedef struct { } vdpau_class_t; - -static void vdpau_overlay_clut_yuv2rgb(vdpau_driver_t *this, vo_overlay_t *overlay, vdpau_frame_t *frame) -{ - int i; - clut_t* clut = (clut_t*) overlay->color; - - if (!overlay->rgb_clut) { - for ( i=0; icolor)/sizeof(overlay->color[0]); i++ ) { - *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); - } - overlay->rgb_clut++; - } - if (!overlay->hili_rgb_clut) { - clut = (clut_t*) overlay->hili_color; - for ( i=0; icolor)/sizeof(overlay->color[0]); i++) { - *((uint32_t *)&clut[i]) = this->ovl_yuv2rgb->yuv2rgb_single_pixel_fun(this->ovl_yuv2rgb, clut[i].y, clut[i].cb, clut[i].cr); - } - overlay->hili_rgb_clut++; - } -} - - - -static void vdpau_process_argb_ovls(vdpau_driver_t *this_gen, vo_frame_t *frame_gen) +static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - int i, k; - vo_overlay_t *ovl[XINE_VORAW_MAX_OVL]; - argb_ovl_data_t ovl_data[XINE_VORAW_MAX_OVL]; - int ovl_data_count = 0; + if ( !changed ) + return; - int total_extent_width = 0, total_extent_height = 0; + this->has_overlay = this->has_unscaled = 0; this->video_window_x = 0; this->video_window_y = 0; this->video_window_width = 0; this->video_window_height = 0; - - /* lock layers while processing and determine extent */ - for (i = 0; i < this->argb_ovl_count; i++) { - pthread_mutex_lock(&this->argb_ovl[i]->argb_layer->mutex); - - if (this->argb_ovl[i]->argb_layer->buffer != NULL) { - int extent_width = this->argb_ovl[i]->extent_width; - int extent_height = this->argb_ovl[i]->extent_height; - if (extent_width <= 0 || extent_height <= 0) { - extent_width = frame_gen->width; - extent_height = frame_gen->height; - } - if (extent_width > 0 && extent_height > 0) { - if (total_extent_width < extent_width) - total_extent_width = extent_width; - if (total_extent_height < extent_height) - total_extent_height = extent_height; - ovl_data[ovl_data_count].x = this->argb_ovl[i]->x; - ovl_data[ovl_data_count].y = this->argb_ovl[i]->y; - ovl_data[ovl_data_count].w = this->argb_ovl[i]->width; - ovl_data[ovl_data_count].h = this->argb_ovl[i]->height; - ovl[ovl_data_count++] = this->argb_ovl[i]; - } - if (this->argb_ovl[i]->video_window_width > 0 - && this->argb_ovl[i]->video_window_height > 0) { - /* last one wins */ - this->video_window_x = this->argb_ovl[i]->video_window_x; - this->video_window_y = this->argb_ovl[i]->video_window_y; - this->video_window_width = this->argb_ovl[i]->video_window_width; - this->video_window_height = this->argb_ovl[i]->video_window_height; - } - } - } - - /* adjust surface */ - if (total_extent_width > 0 && total_extent_height > 0) { - if (this->argb_overlay_width != total_extent_width || this->argb_overlay_height != total_extent_height || this->argb_overlay == VDP_INVALID_HANDLE) { - if (this->argb_overlay != VDP_INVALID_HANDLE) - vdp_output_surface_destroy(this->argb_overlay); - - VdpStatus st = vdp_output_surface_create(vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, total_extent_width, total_extent_height, &this->argb_overlay); - if (st != VDP_STATUS_OK) - fprintf(stderr, "vdpau_process_argb_ovl: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st)); - - this->argb_overlay_width = total_extent_width; - this->argb_overlay_height = total_extent_height; - - /* change argb_ovl_data to wipe complete surface */ - this->argb_ovl_data_count = 1; - this->argb_ovl_data[0].x = 0; - this->argb_ovl_data[0].y = 0; - this->argb_ovl_data[0].w = total_extent_width; - this->argb_ovl_data[0].h = total_extent_height; - - /* extend dirty areas to maximum for filling wiped surface */ - for (i = 0; i < ovl_data_count; i++) { - ovl[i]->argb_layer->x1 = 0; - ovl[i]->argb_layer->y1 = 0; - ovl[i]->argb_layer->x2 = ovl[i]->width; - ovl[i]->argb_layer->y2 = ovl[i]->height; - } - } - } - - /* wipe surface for gone overlays */ - if (this->argb_overlay != VDP_INVALID_HANDLE) { - uint32_t *zeros = NULL; - for (i = 0; i < this->argb_ovl_data_count; i++) { - argb_ovl_data_t *curr_ovl_data = &this->argb_ovl_data[i]; - int ovl_gone = 1; - for (k = 0; k < ovl_data_count; k++) { - if (0 == memcmp(curr_ovl_data, &ovl_data[k], sizeof (*curr_ovl_data))) { - ovl_gone = 0; - break; - } - } - if (!ovl_gone) - continue; - if (!zeros) - zeros = calloc(4, this->argb_overlay_width * this->argb_overlay_height); - if (zeros) { - uint32_t pitch = curr_ovl_data->w * 4; - VdpRect dest = { curr_ovl_data->x, curr_ovl_data->y, curr_ovl_data->x + curr_ovl_data->w, curr_ovl_data->y + curr_ovl_data->h }; - VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&zeros, &pitch, &dest); - if (st != VDP_STATUS_OK) - fprintf(stderr, "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st)); - } - } - free(zeros); - } - - /* set destination area according to dirty area of argb layer and reset dirty area */ - for (i = 0; i < ovl_data_count; i++) { - uint32_t pitch = ovl[i]->width * 4; - uint32_t *buffer_start = ovl[i]->argb_layer->buffer + ovl[i]->argb_layer->y1 * ovl[i]->width + ovl[i]->argb_layer->x1; - VdpRect dest = { ovl[i]->x + ovl[i]->argb_layer->x1, ovl[i]->y + ovl[i]->argb_layer->y1, ovl[i]->x + ovl[i]->argb_layer->x2, ovl[i]->y + ovl[i]->argb_layer->y2 }; - ovl[i]->argb_layer->x1 = ovl[i]->width; - ovl[i]->argb_layer->y1 = ovl[i]->height; - ovl[i]->argb_layer->x2 = 0; - ovl[i]->argb_layer->y2 = 0; - - VdpStatus st = vdp_output_surface_put_bits(this->argb_overlay, (void *)&buffer_start, &pitch, &dest); - if (st != VDP_STATUS_OK) - fprintf(stderr, "vdpau_process_argb_ovl: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st)); - else - this->has_argb_overlay = 1; - } - - /* store ovl_data */ - memcpy(this->argb_ovl_data, ovl_data, sizeof (ovl_data)); - this->argb_ovl_data_count = ovl_data_count; - - /* unlock layers */ - for (i = 0; i < this->argb_ovl_count; i++) - pthread_mutex_unlock(&this->argb_ovl[i]->argb_layer->mutex); -} - - - -static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay ) -{ - vdpau_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1]; - - if ( overlay->width<=0 || overlay->height<=0 ) - return 0; - - if ( (ovl->bitmap_width < overlay->width ) || (ovl->bitmap_height < overlay->height) || (ovl->ovl_bitmap == VDP_INVALID_HANDLE) ) { - if (ovl->ovl_bitmap != VDP_INVALID_HANDLE) { - vdp_bitmap_destroy( ovl->ovl_bitmap ); - ovl->ovl_bitmap = VDP_INVALID_HANDLE; - } - VdpStatus st = vdp_bitmap_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, overlay->width, overlay->height, 0, &ovl->ovl_bitmap ); - if ( st != VDP_STATUS_OK ) { - fprintf(stderr, "vdpau_process_ovl: vdp_bitmap_create failed : %s\n", vdp_get_error_string(st) ); - } - ovl->bitmap_width = overlay->width; - ovl->bitmap_height = overlay->height; - } - 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->expected_overlay_width = overlay->extent_width; - ovl->expected_overlay_height = overlay->extent_height; - uint32_t *buf = (uint32_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); - if ( !buf ) - return 0; - - int num_rle = overlay->num_rle; - rle_elem_t *rle = overlay->rle; - uint32_t *rgba = buf; - uint32_t red, green, blue, alpha; - 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; - 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; - for ( i=0; iovl_w*4; - VdpRect dest = { 0, 0, ovl->ovl_w, ovl->ovl_h }; - VdpStatus st = vdp_bitmap_put_bits( ovl->ovl_bitmap, &buf, &pitch, &dest); - if ( st != VDP_STATUS_OK ) { - fprintf(stderr, "vdpau_process_ovl: vdp_bitmap_put_bits failed : %s\n", vdp_get_error_string(st) ); - } - free(buf); - return 1; + ++this->ovl_changed; + lprintf("overlay begin\n"); } -static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed) +static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - if ( !changed ) + int i = this->ovl_changed; + if (!i) return; - this->has_overlay = this->has_unscaled = 0; - this->has_argb_overlay = 0; - this->argb_ovl_count = 0; - ++this->ovl_changed; -} - - - -static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay) -{ - vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen; + if (--i >= XINE_VORAW_MAX_OVL) + return; - if (!this->ovl_changed) + if (overlay->width <= 0 || overlay->height <= 0 || (!overlay->rle && (!overlay->argb_layer || !overlay->argb_layer->buffer))) return; - if (overlay->rle) { - if (this->ovl_changed >= XINE_VORAW_MAX_OVL) - return; - if (!overlay->rgb_clut || !overlay->hili_rgb_clut) - vdpau_overlay_clut_yuv2rgb (this, overlay, frame); - if ( vdpau_process_ovl( this, overlay ) ) - ++this->ovl_changed; + if (overlay->rle) + lprintf("overlay[%d] rle %s%s %dx%d@%d,%d hili rect %d,%d-%d,%d\n", i, + overlay->unscaled ? " unscaled ": " scaled ", + (overlay->rgb_clut > 0 || overlay->hili_rgb_clut > 0) ? " rgb ": " ycbcr ", + overlay->width, overlay->height, overlay->x, overlay->y, + overlay->hili_left, overlay->hili_top, + overlay->hili_right, overlay->hili_bottom); + if (overlay->argb_layer && overlay->argb_layer->buffer) + lprintf("overlay[%d] argb %s %dx%d@%d,%d dirty rect %d,%d-%d,%d\n", i, + overlay->unscaled ? " unscaled ": " scaled ", + overlay->width, overlay->height, overlay->x, overlay->y, + overlay->argb_layer->x1, overlay->argb_layer->y1, + overlay->argb_layer->x2, overlay->argb_layer->y2); + + this->overlays[i] = overlay; + + if (overlay->video_window_width > 0 && overlay->video_window_height > 0) { + /* last one wins */ + this->video_window_x = overlay->video_window_x; + this->video_window_y = overlay->video_window_y; + this->video_window_width = overlay->video_window_width; + this->video_window_height = overlay->video_window_height; } - if (overlay->argb_layer) { - if (this->argb_ovl_count >= XINE_VORAW_MAX_OVL) - return; - this->argb_ovl[this->argb_ovl_count++] = overlay; - } + ++this->ovl_changed; } + static void vdpau_overlay_end (vo_driver_t *this_gen, vo_frame_t *frame) { - vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - int i; VdpStatus st; + vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - if ( !this->ovl_changed ) - return; - - if (this->argb_ovl_count || this->argb_ovl_data_count) - vdpau_process_argb_ovls(this, frame); - - if ( !(this->ovl_changed-1) ) { + int novls = this->ovl_changed; + if (novls < 2) { this->ovl_changed = 0; - this->has_overlay = 0; - this->has_unscaled = 0; return; } + --novls; + + uint32_t output_width = frame->width; + uint32_t output_height = frame->height; + uint32_t unscaled_width = 0, unscaled_height = 0; + uint32_t render_width = 0, render_height = 0; + vo_overlay_t *first_scaled = NULL, *first_unscaled = NULL; + vdpau_rect_t dirty_rect, unscaled_dirty_rect; + int has_rle = 0; + + int i; + for (i = 0; i < novls; ++i) { + vo_overlay_t *ovl = this->overlays[i]; + + if (ovl->rle) + has_rle = 1; + + if (ovl->unscaled) { + if (first_unscaled) { + if (ovl->width > render_width) + render_width = ovl->width; + if (ovl->height > render_height) + render_height = ovl->height; + + if (ovl->x < unscaled_dirty_rect.x1) + unscaled_dirty_rect.x1 = ovl->x; + if (ovl->y < unscaled_dirty_rect.y1) + unscaled_dirty_rect.y1 = ovl->y; + if ((ovl->x + ovl->width) > unscaled_dirty_rect.x2) + unscaled_dirty_rect.x2 = ovl->x + ovl->width; + if ((ovl->y + ovl->height) > unscaled_dirty_rect.y2) + unscaled_dirty_rect.y2 = ovl->y + ovl->height; + } else { + first_unscaled = ovl; + unscaled_dirty_rect.x1 = ovl->x; + unscaled_dirty_rect.y1 = ovl->y; + unscaled_dirty_rect.x2 = ovl->x + ovl->width; + unscaled_dirty_rect.y2 = ovl->y + ovl->height; + } - int w=0, h=0; - int scaler = 0; - for ( i=0; iovl_changed-1; ++i ) { - if ( this->overlays[i].unscaled ) - continue; - if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) ) - w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; - if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) ) - h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; - if ( this->overlays[i].expected_overlay_width ) - scaler = 1; - if ( this->overlays[i].expected_overlay_height ) - scaler = 1; + unscaled_width = unscaled_dirty_rect.x2; + unscaled_height = unscaled_dirty_rect.y2; + } else { + if (ovl->width > render_width) + render_width = ovl->width; + if (ovl->height > render_height) + render_height = ovl->height; + + if (first_scaled) { + if (ovl->x < dirty_rect.x1) + dirty_rect.x1 = ovl->x; + if (ovl->y < dirty_rect.y1) + dirty_rect.y1 = ovl->y; + if ((ovl->x + ovl->width) > dirty_rect.x2) + dirty_rect.x2 = ovl->x + ovl->width; + if ((ovl->y + ovl->height) > dirty_rect.y2) + dirty_rect.y2 = ovl->y + ovl->height; + } else { + first_scaled = ovl; + dirty_rect.x1 = ovl->x; + dirty_rect.y1 = ovl->y; + dirty_rect.x2 = ovl->x + ovl->width; + dirty_rect.y2 = ovl->y + ovl->height; + } + + if (dirty_rect.x2 > output_width) + output_width = dirty_rect.x2; + if (dirty_rect.y2 > output_height) + output_height = dirty_rect.y2; + + if (ovl->extent_width > 0 || ovl->extent_height > 0) { + if (this->video_mixer_width > output_width) + output_width = this->video_mixer_width; + if (this->video_mixer_height > output_height) + output_height = this->video_mixer_height; + } + } } - if ( scaler ) { - w = this->video_mixer_width; - h = this->video_mixer_height; + int need_render_surface = (novls > 1); + int need_init = 0; + if (first_scaled) { + vdpau_rect_t dest; + dest.x1 = first_scaled->x; + dest.y1 = first_scaled->y; + dest.x2 = first_scaled->x + first_scaled->width; + dest.y2 = first_scaled->y + first_scaled->height; + if (first_scaled->extent_width > 0 && first_scaled->extent_height > 0) { + double rx = (double)output_width / (double)first_scaled->extent_width; + double ry = (double)output_height / (double)first_scaled->extent_height; + dest.x1 *= rx; dest.y1 *= ry; dest.x2 *= rx; dest.y2 *= ry; + } + if (!RECT_IS_EQ(dest, dirty_rect)) + need_init = 1; + if ((dest.x2 - dest.x1) != first_scaled->width || (dest.y2 - dest.y1) != first_scaled->height) + need_render_surface = 1; } - int out_w = (w>frame->width) ? w : frame->width; - int out_h = (h>frame->height) ? h : frame->height; + int need_unscaled_init = (first_unscaled && + (first_unscaled->x != unscaled_dirty_rect.x1 || + first_unscaled->y != unscaled_dirty_rect.y1 || + (first_unscaled->x + first_unscaled->width) != unscaled_dirty_rect.x2 || + (first_unscaled->y + first_unscaled->height) != unscaled_dirty_rect.y2)); - if ( (this->overlay_output_width!=out_w || this->overlay_output_height!=out_h) && this->overlay_output != VDP_INVALID_HANDLE ) { - st = vdp_output_surface_destroy( this->overlay_output ); + if (this->overlay_render_surface != VDP_INVALID_HANDLE && (!need_render_surface || this->overlay_render_width != render_width || this->overlay_render_height != render_height) ) { + lprintf("overlay destroy render surface\n"); + st = vdp_output_surface_destroy( this->overlay_render_surface ); if ( st != VDP_STATUS_OK ) { fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); } - this->overlay_output = VDP_INVALID_HANDLE; - } - - this->overlay_output_width = out_w; - this->overlay_output_height = out_h; - - w = 64; h = 64; - for ( i=0; iovl_changed-1; ++i ) { - if ( !this->overlays[i].unscaled ) - continue; - if ( w < (this->overlays[i].ovl_x+this->overlays[i].ovl_w) ) - w = this->overlays[i].ovl_x+this->overlays[i].ovl_w; - if ( h < (this->overlays[i].ovl_y+this->overlays[i].ovl_h) ) - h = this->overlays[i].ovl_y+this->overlays[i].ovl_h; + this->overlay_render_surface = VDP_INVALID_HANDLE; } - if ( (this->overlay_unscaled_width!=w || this->overlay_unscaled_height!=h) && this->overlay_unscaled != VDP_INVALID_HANDLE ) { - st = vdp_output_surface_destroy( this->overlay_unscaled ); + if (this->overlay_output_surface != VDP_INVALID_HANDLE && (!first_scaled || this->overlay_output_width != output_width || this->overlay_output_height != output_height) ) { + lprintf("overlay destroy scaled surface\n"); + st = vdp_output_surface_destroy( this->overlay_output_surface ); if ( st != VDP_STATUS_OK ) { fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); } - this->overlay_unscaled = VDP_INVALID_HANDLE; + this->overlay_output_surface = VDP_INVALID_HANDLE; } - this->overlay_unscaled_width = w; - this->overlay_unscaled_height = h; + if (this->overlay_unscaled_surface != VDP_INVALID_HANDLE && (!first_unscaled || this->overlay_unscaled_width != unscaled_width || this->overlay_unscaled_height != unscaled_height) ) { + lprintf("overlay destroy unscaled surface\n"); + st = vdp_output_surface_destroy( this->overlay_unscaled_surface ); + if ( st != VDP_STATUS_OK ) { + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) ); + } + this->overlay_unscaled_surface = VDP_INVALID_HANDLE; + } - if ( this->overlay_unscaled == VDP_INVALID_HANDLE ) { - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_unscaled_width, this->overlay_unscaled_height, &this->overlay_unscaled ); + if (need_render_surface && this->overlay_render_surface == VDP_INVALID_HANDLE ) { + lprintf("overlay create render surface %dx%d\n", render_width, render_height); + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, render_width, render_height, &this->overlay_render_surface ); if ( st != VDP_STATUS_OK ) fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + + this->overlay_render_width = render_width; + this->overlay_render_height = render_height; } - if ( this->overlay_output == VDP_INVALID_HANDLE ) { - st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->overlay_output_width, this->overlay_output_height, &this->overlay_output ); - if ( st != VDP_STATUS_OK ) - fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + if (first_scaled) { + if (this->overlay_output_surface == VDP_INVALID_HANDLE ) { + lprintf("overlay create scaled surface %dx%d\n", output_width, output_height); + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, output_width, output_height, &this->overlay_output_surface ); + if ( st != VDP_STATUS_OK ) + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + + this->overlay_output_width = output_width; + this->overlay_output_height = output_height; + + need_init = 1; + } else if (!RECT_IS_EQ(dirty_rect, this->overlay_dirty_rect)) { + need_init = 1; + } + this->overlay_dirty_rect = dirty_rect; } - w = (this->overlay_unscaled_width>this->overlay_output_width) ? this->overlay_unscaled_width : this->overlay_output_width; - h = (this->overlay_unscaled_height>this->overlay_output_height) ? this->overlay_unscaled_height : this->overlay_output_height; + if (first_unscaled) { + if (this->overlay_unscaled_surface == VDP_INVALID_HANDLE ) { + lprintf("overlay create unscaled surface %dx%d\n", unscaled_width, unscaled_height); + st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, unscaled_width, unscaled_height, &this->overlay_unscaled_surface ); + if ( st != VDP_STATUS_OK ) + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_create failed : %s\n", vdp_get_error_string(st) ); + + this->overlay_unscaled_width = unscaled_width; + this->overlay_unscaled_height = unscaled_height; - uint32_t *buf = (uint32_t*)calloc(w*4,h); - uint32_t pitch = w*4; - VdpRect clear = { 0, 0, this->overlay_output_width, this->overlay_output_height }; - st = vdp_output_surface_put_bits( this->overlay_output, &buf, &pitch, &clear ); - if ( st != VDP_STATUS_OK ) { - fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); + need_unscaled_init = 1; + } else if (!RECT_IS_EQ(unscaled_dirty_rect, this->overlay_unscaled_dirty_rect)) { + need_unscaled_init = 1; + } + this->overlay_unscaled_dirty_rect = unscaled_dirty_rect; } - clear.x1 = this->overlay_unscaled_width; clear.y1 = this->overlay_unscaled_height; - st = vdp_output_surface_put_bits( this->overlay_unscaled, &buf, &pitch, &clear ); - if ( st != VDP_STATUS_OK ) { - fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); - } - free(buf); - - VdpOutputSurface *surface; - for ( i=0; iovl_changed-1; ++i ) { - VdpRect dest = { this->overlays[i].ovl_x, this->overlays[i].ovl_y, this->overlays[i].ovl_x+this->overlays[i].ovl_w, this->overlays[i].ovl_y+this->overlays[i].ovl_h }; - if ( this->overlays[i].expected_overlay_width ) { - double rx = (double)this->overlay_output_width/(double)this->overlays[i].expected_overlay_width; - double ry = (double)this->overlay_output_height/(double)this->overlays[i].expected_overlay_height; - dest.x0 *= rx; dest.y0 *= ry; dest.x1 *=rx; dest.y1 *= ry; - lprintf( "vdpau_overlay_end: overlay_width=%d overlay_height=%d rx=%f ry=%f\n", this->overlay_output_width, this->overlay_output_height, rx, ry ); + + if (has_rle || need_init || need_unscaled_init) { + uint32_t width = (unscaled_width > output_width) ? unscaled_width : output_width; + uint32_t height = (has_rle) ? ((unscaled_height > output_height) ? unscaled_height : output_height): 1; + + if ((width * height) > this->overlay_bitmap_size) { + this->overlay_bitmap_size = width * height; + free(this->overlay_bitmap); + this->overlay_bitmap = calloc(this->overlay_bitmap_size, sizeof(uint32_t)); + } else if (need_init || need_unscaled_init) { + memset(this->overlay_bitmap, 0, (width * sizeof(uint32_t))); } - VdpRect src = { 0, 0, this->overlays[i].ovl_w, this->overlays[i].ovl_h }; - surface = (this->overlays[i].unscaled) ? &this->overlay_unscaled : &this->overlay_output; - st = vdp_output_surface_render_bitmap_surface( *surface, &dest, this->overlays[i].ovl_bitmap, &src, 0, &blend, 0 ); - if ( st != VDP_STATUS_OK ) { - fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_render_bitmap_surface failed : %s\n", vdp_get_error_string(st) ); + + if (need_init) { + lprintf("overlay init scaled surface %dx%d\n", output_width, output_height); + uint32_t pitch = 0; + VdpRect clear = { 0, 0, output_width, output_height }; + st = vdp_output_surface_put_bits( this->overlay_output_surface, &this->overlay_bitmap, &pitch, &clear ); + if ( st != VDP_STATUS_OK ) { + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); + } + } + + if (need_unscaled_init) { + lprintf("overlay init unscaled surface %dx%d\n", unscaled_width, unscaled_height); + uint32_t pitch = 0; + VdpRect clear = { 0, 0, unscaled_width, unscaled_height }; + st = vdp_output_surface_put_bits( this->overlay_unscaled_surface, &this->overlay_bitmap, &pitch, &clear ); + if ( st != VDP_STATUS_OK ) { + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_put_bits (clear) failed : %s\n", vdp_get_error_string(st) ); + } } } - this->has_overlay = 1; + + for (i = 0; i < novls; ++i) { + vo_overlay_t *ovl = this->overlays[i]; + uint32_t *bitmap; + int is_argb = 1; + + if (ovl->rle) { + rle_elem_t *rle = ovl->rle; + bitmap = this->overlay_bitmap; + int pos = 0; + + int num_rle = ovl->num_rle; + while (num_rle > 0) { + int x = pos % ovl->width; + int y = pos / ovl->width; + clut_t *colors; + uint8_t *trans; + if (x >= ovl->hili_left && x <= ovl->hili_right && y >= ovl->hili_top && y <= ovl->hili_bottom) { + colors = (clut_t*)ovl->hili_color; + trans = ovl->hili_trans; + is_argb = ovl->hili_rgb_clut; + } else { + colors = (clut_t*)ovl->color; + trans = ovl->trans; + is_argb = ovl->rgb_clut; + } + + int clr = rle->color; + uint32_t pixel; + if ( trans[clr] == 0 ) + pixel = 0; + else if (is_argb) + pixel = (((uint32_t)trans[clr] * 255 / 15) << 24) | (((uint32_t)colors[clr].y) << 16) | (((uint32_t)colors[clr].cr) << 8) | ((uint32_t)colors[clr].cb); + else + pixel = (((uint32_t)trans[clr] * 255 / 15) << 24) | (((uint32_t)colors[clr].y) << 16) | (((uint32_t)colors[clr].cb) << 8) | ((uint32_t)colors[clr].cr); + + int rlelen = rle->len; + pos += rlelen; + while (rlelen > 0) { + *bitmap++ = pixel; + --rlelen; + } + ++rle; + --num_rle; + } + + int n = ovl->width * ovl->height - pos; + if (n > 0) + memset(bitmap, 0, n * sizeof(uint32_t)); + + bitmap = this->overlay_bitmap; + } else { + pthread_mutex_lock(&ovl->argb_layer->mutex); + bitmap = ovl->argb_layer->buffer; + } + + VdpOutputSurface surface; + VdpRect dest; + VdpOutputSurfaceRenderBlendState *bs = NULL; + if (ovl == first_scaled) { + if (need_render_surface) { + surface = this->overlay_render_surface; + dest.x0 = 0; + dest.y0 = 0; + dest.x1 = ovl->width; + dest.y1 = ovl->height; + } else { + surface = this->overlay_output_surface; + dest.x0 = ovl->x; + dest.y0 = ovl->y; + dest.x1 = ovl->x + ovl->width; + dest.y1 = ovl->y + ovl->height; + } + } else if (ovl == first_unscaled) { + surface = this->overlay_unscaled_surface; + dest.x0 = ovl->x; + dest.y0 = ovl->y; + dest.x1 = ovl->x + ovl->width; + dest.y1 = ovl->y + ovl->height; + } else { + bs = &blend; + surface = this->overlay_render_surface; + dest.x0 = 0; + dest.y0 = 0; + dest.x1 = ovl->width; + dest.y1 = ovl->height; + } + + uint32_t pitch = ovl->width * sizeof(uint32_t); + if (is_argb) { + lprintf("overlay put argb %d,%d-%d,%d\n", dest.x0, dest.y0, dest.x1, dest.y1); + st = vdp_output_surface_put_bits(surface, &bitmap, &pitch, &dest); + if ( st != VDP_STATUS_OK ) + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_put_bits_native failed : %s\n", vdp_get_error_string(st)); + } else { + lprintf("overlay put ycbcr %d,%d-%d,%d\n", dest.x0, dest.y0, dest.x1, dest.y1); + st = vdp_output_surface_put_bits_ycbcr(surface, VDP_YCBCR_FORMAT_V8U8Y8A8, &bitmap, &pitch, &dest, NULL); + if ( st != VDP_STATUS_OK ) + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_put_bits_ycbcr failed : %s\n", vdp_get_error_string(st)); + } + + if (!ovl->rle) + pthread_mutex_unlock(&ovl->argb_layer->mutex); + + if (surface == this->overlay_render_surface) { + VdpRect src = { 0, 0, ovl->width, ovl->height }; + dest.x0 = ovl->x; + dest.y0 = ovl->y; + dest.x1 = ovl->x + ovl->width; + dest.y1 = ovl->y + ovl->height; + if (ovl->unscaled) { + surface = this->overlay_unscaled_surface; + lprintf("overlay render unscaled %d,%d-%d,%d\n", dest.x0, dest.y0, dest.x1, dest.y1); + } else { + if (ovl->extent_width > 0 && ovl->extent_height > 0) { + double rx = (double)output_width / (double)ovl->extent_width; + double ry = (double)output_height / (double)ovl->extent_height; + dest.x0 *= rx; dest.y0 *= ry; dest.x1 *=rx; dest.y1 *= ry; + } + surface = this->overlay_output_surface; + lprintf("overlay render scaled %dx%d -> %d,%d-%d,%d\n", src.x1, src.y1, dest.x0, dest.y0, dest.x1, dest.y1); + } + st = vdp_output_surface_render_output_surface(surface, &dest, this->overlay_render_surface, &src, 0, bs, 0 ); + if ( st != VDP_STATUS_OK ) { + fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_render_output_surface failed : %s\n", vdp_get_error_string(st)); + } + } + } + this->ovl_changed = 0; + this->has_overlay = (first_scaled != NULL); + this->has_unscaled = (first_unscaled != NULL); + + lprintf("overlay has %s %s video window %dx%d@%d,%d\n", + first_scaled ? "scaled": "", first_unscaled ? "unscaled": "", + this->video_window_x, this->video_window_y, this->video_mixer_width, this->video_window_height); } @@ -1703,7 +1700,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) #endif VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 3; + int num_layers = 2; void const *param_values[] = { &mix_w, &mix_h, &chroma, &num_layers }; vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); this->video_mixer_chroma = chroma; @@ -1728,8 +1725,6 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) VdpRect vid_source, out_dest, vid_dest; - vdpau_check_output_size( this_gen ); - vid_source.x0 = this->sc.displayed_xoffset; vid_source.y0 = this->sc.displayed_yoffset; vid_source.x1 = this->sc.displayed_width+this->sc.displayed_xoffset; vid_source.y1 = this->sc.displayed_height+this->sc.displayed_yoffset; out_dest.x0 = out_dest.y0 = 0; @@ -1739,41 +1734,34 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) stream_speed = frame->vo_frame.stream ? xine_get_param(frame->vo_frame.stream, XINE_PARAM_FINE_SPEED) : 0; - VdpTime last_time; - - if ( this->init_queue>1 ) - vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); - - uint32_t layer_count; - VdpLayer layer[3]; - VdpRect unscaledsrc; + uint32_t layer_count = 0; + VdpLayer layer[2]; + VdpRect ovl_source, unscaled_source; if ( this->has_overlay ) { - layer_count = 2; - layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output; layer[0].source_rect = &vid_source; layer[0].destination_rect = &vid_dest; - unscaledsrc.x0 = 0; unscaledsrc.y0 = 0; unscaledsrc.x1 = this->overlay_unscaled_width; unscaledsrc.y1 = this->overlay_unscaled_height; - layer[1].struct_version = VDP_LAYER_VERSION; layer[1].source_surface = this->overlay_unscaled; layer[1].source_rect = &unscaledsrc; layer[1].destination_rect = &unscaledsrc; + ovl_source.x0 = 0; ovl_source.y0 = 0; ovl_source.x1 = this->overlay_output_width; ovl_source.y1 = this->overlay_output_height; + layer[0].struct_version = VDP_LAYER_VERSION; layer[0].source_surface = this->overlay_output_surface; layer[0].source_rect = &ovl_source; layer[0].destination_rect = &vid_dest; + /* recalculate video destination window to match osd's specified video window */ + if (!this->has_unscaled && this->video_window_width > 0 && this->video_window_height > 0) { + VdpRect win_rect = { this->video_window_x, this->video_window_y, this->video_window_x + this->video_window_width, this->video_window_y + this->video_window_height }; + vid_dest.x0 = ((win_rect.x0 - ovl_source.x0) * (vid_dest.x1 - vid_dest.x0) + vid_dest.x0 * (ovl_source.x1 - ovl_source.x0)) / (ovl_source.x1 - ovl_source.x0); + vid_dest.y0 = ((win_rect.y0 - ovl_source.y0) * (vid_dest.y1 - vid_dest.y0) + vid_dest.y0 * (ovl_source.y1 - ovl_source.y0)) / (ovl_source.y1 - ovl_source.y0); + vid_dest.x1 = ((win_rect.x1 - ovl_source.x0) * (vid_dest.x1 - vid_dest.x0) + vid_dest.x0 * (ovl_source.x1 - ovl_source.x0)) / (ovl_source.x1 - ovl_source.x0); + vid_dest.y1 = ((win_rect.y1 - ovl_source.y0) * (vid_dest.y1 - vid_dest.y0) + vid_dest.y0 * (ovl_source.y1 - ovl_source.y0)) / (ovl_source.y1 - ovl_source.y0); + } + ++layer_count; } - else { - layer_count = 0; - } - - VdpRect argb_dest; - VdpRect argb_rect = { 0, 0, this->argb_overlay_width, this->argb_overlay_height }; - if( this->has_argb_overlay ) { - layer_count++; - memcpy(&argb_dest, &vid_dest, sizeof (vid_dest)); - layer[layer_count-1].destination_rect = &argb_dest; - layer[layer_count-1].source_rect = &argb_rect; - layer[layer_count-1].source_surface = this->argb_overlay; - layer[layer_count-1].struct_version = VDP_LAYER_VERSION; + + if ( this->has_unscaled ) { + unscaled_source.x0 = 0; unscaled_source.y0 = 0; unscaled_source.x1 = this->overlay_unscaled_width; unscaled_source.y1 = this->overlay_unscaled_height; + layer[layer_count].struct_version = VDP_LAYER_VERSION; layer[layer_count].source_surface = this->overlay_unscaled_surface; layer[layer_count].source_rect = &unscaled_source; layer[layer_count].destination_rect = &unscaled_source; /* recalculate video destination window to match osd's specified video window */ if (this->video_window_width > 0 && this->video_window_height > 0) { - VdpRect win_rect = { this->video_window_x, this->video_window_y, this->video_window_x + this->video_window_width, this->video_window_y + this->video_window_height }; - vid_dest.x0 = ((win_rect.x0 - argb_rect.x0) * (argb_dest.x1 - argb_dest.x0) + argb_dest.x0 * (argb_rect.x1 - argb_rect.x0)) / (argb_rect.x1 - argb_rect.x0); - vid_dest.y0 = ((win_rect.y0 - argb_rect.y0) * (argb_dest.y1 - argb_dest.y0) + argb_dest.y0 * (argb_rect.y1 - argb_rect.y0)) / (argb_rect.y1 - argb_rect.y0); - vid_dest.x1 = ((win_rect.x1 - argb_rect.x0) * (argb_dest.x1 - argb_dest.x0) + argb_dest.x0 * (argb_rect.x1 - argb_rect.x0)) / (argb_rect.x1 - argb_rect.x0); - vid_dest.y1 = ((win_rect.y1 - argb_rect.y0) * (argb_dest.y1 - argb_dest.y0) + argb_dest.y0 * (argb_rect.y1 - argb_rect.y0)) / (argb_rect.y1 - argb_rect.y0); + vid_dest.x0 = this->video_window_x; + vid_dest.y0 = this->video_window_y; + vid_dest.x1 = this->video_window_x + this->video_window_width; + vid_dest.y1 = this->video_window_y + this->video_window_height; } + ++layer_count; } /* try to get frame duration from previous img->pts when frame->duration is 0 */ @@ -1789,10 +1777,17 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen) else non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive; + VdpTime last_time; + + if ( this->init_queue>1 ) + vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time ); + #ifdef LOCKDISPLAY XLockDisplay( this->display ); #endif + vdpau_check_output_size( this_gen ); + if ( frame->format==XINE_IMGFMT_VDPAU && this->deinterlace && non_progressive && !(frame->vo_frame.flags & VO_STILL_IMAGE) && frame_duration>2500 ) { VdpTime current_time = 0; VdpVideoSurface past[2]; @@ -2088,13 +2083,7 @@ static void vdpau_dispose (vo_driver_t *this_gen) vdpau_driver_t *this = (vdpau_driver_t *) this_gen; int i; - this->ovl_yuv2rgb->dispose(this->ovl_yuv2rgb); - this->yuv2rgb_factory->dispose (this->yuv2rgb_factory); - - for ( i=0; ioverlays[i].ovl_bitmap != VDP_INVALID_HANDLE ) - vdp_bitmap_destroy( this->overlays[i].ovl_bitmap ); - } + free(this->overlay_bitmap); if ( this->video_mixer!=VDP_INVALID_HANDLE ) vdp_video_mixer_destroy( this->video_mixer ); @@ -2102,16 +2091,16 @@ static void vdpau_dispose (vo_driver_t *this_gen) vdp_video_surface_destroy( this->soft_surface ); if ( vdp_output_surface_destroy ) { - if (this->argb_overlay != VDP_INVALID_HANDLE) - vdp_output_surface_destroy(this->argb_overlay); - if ( this->overlay_unscaled!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->overlay_unscaled ); - if ( this->overlay_output!=VDP_INVALID_HANDLE ) - vdp_output_surface_destroy( this->overlay_output ); + if ( this->overlay_unscaled_surface!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->overlay_unscaled_surface ); + if ( this->overlay_output_surface!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->overlay_output_surface ); + if ( this->overlay_render_surface!=VDP_INVALID_HANDLE ) + vdp_output_surface_destroy( this->overlay_render_surface ); for ( i=0; ioutput_surface[i]!=VDP_INVALID_HANDLE ) vdp_output_surface_destroy( this->output_surface[i] ); - } + } } if ( vdp_queue != VDP_INVALID_HANDLE ) @@ -2211,24 +2200,16 @@ static void vdpau_reinit( vo_driver_t *this_gen ) } } - /* osd overlays need to be recreated */ - for ( i=0; ioverlays[i].ovl_bitmap = VDP_INVALID_HANDLE; - this->overlays[i].bitmap_width = 0; - this->overlays[i].bitmap_height = 0; - } - this->overlay_output = VDP_INVALID_HANDLE; + this->overlay_output_surface = VDP_INVALID_HANDLE; this->overlay_output_width = this->overlay_output_height = 0; - this->overlay_unscaled = VDP_INVALID_HANDLE; + this->overlay_unscaled_surface = VDP_INVALID_HANDLE; this->overlay_unscaled_width = this->overlay_unscaled_height = 0; + this->overlay_render_surface = VDP_INVALID_HANDLE; + this->overlay_render_width = this->overlay_render_height = 0; this->ovl_changed = 0; this->has_overlay = 0; this->has_unscaled = 0; - this->argb_overlay = VDP_INVALID_HANDLE; - this->argb_overlay_width = this->argb_overlay_height = 0; - this->has_argb_overlay = 0; - VdpVideoMixerFeature features[15]; int features_count = 0; if ( this->noise_reduction_is_supported ) { @@ -2258,7 +2239,7 @@ static void vdpau_reinit( vo_driver_t *this_gen ) } #endif VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 3; + int num_layers = 2; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_reinit_error( st, "Can't create video mixer !!" ) ) { @@ -2382,28 +2363,18 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo this->skip_chroma_is_supported = 0; this->background_is_supported = 0; - for ( i=0; ioverlays[i].ovl_w = this->overlays[i].ovl_h = 0; - this->overlays[i].bitmap_width = this->overlays[i].bitmap_height = 0; - this->overlays[i].ovl_bitmap = VDP_INVALID_HANDLE; - this->overlays[i].ovl_x = this->overlays[i].ovl_y = 0; - } - this->overlay_output = VDP_INVALID_HANDLE; + this->overlay_output_surface = VDP_INVALID_HANDLE; this->overlay_output_width = this->overlay_output_height = 0; - this->overlay_unscaled = VDP_INVALID_HANDLE; + this->overlay_unscaled_surface = VDP_INVALID_HANDLE; this->overlay_unscaled_width = this->overlay_unscaled_height = 0; + this->overlay_render_surface = VDP_INVALID_HANDLE; + this->overlay_render_width = this->overlay_render_height = 0; + this->overlay_bitmap = NULL; + this->overlay_bitmap_size = 0; this->ovl_changed = 0; this->has_overlay = 0; this->has_unscaled = 0; - this->argb_overlay = VDP_INVALID_HANDLE; - this->argb_overlay_width = this->argb_overlay_height = 0; - this->has_argb_overlay = 0; - - /* overlay converter */ - this->yuv2rgb_factory = yuv2rgb_factory_init (MODE_24_BGR, 0, NULL); - this->ovl_yuv2rgb = this->yuv2rgb_factory->create_converter( this->yuv2rgb_factory ); - VdpStatus st = vdp_device_create_x11( visual->display, visual->screen, &vdp_device, &vdp_get_proc_address ); if ( st != VDP_STATUS_OK ) { fprintf(stderr, "vo_vdpau: Can't create vdp device : " ); @@ -2476,9 +2447,15 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE , (void*)&vdp_output_surface_render_bitmap_surface ); if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_RENDER_BITMAP_SURFACE proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE , (void*)&vdp_output_surface_render_output_surface ); + if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_output_surface_put_bits ); if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_output_surface_put_bits_ycbcr ); + if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_YCBCR proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_MIXER_CREATE , (void*)&vdp_video_mixer_create ); if ( vdpau_init_error( st, "Can't get VIDEO_MIXER_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -2668,7 +2645,7 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo #endif VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 3; + int num_layers = 2; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { -- cgit v1.2.3