summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/video_out/video_out_vdpau.c1031
1 files changed, 513 insertions, 518 deletions
diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c
index e807a2399..2c3329743 100644
--- a/src/video_out/video_out_vdpau.c
+++ b/src/video_out/video_out_vdpau.c
@@ -47,6 +47,7 @@
#include <xine/vo_scale.h>
#include <xine/xine_internal.h>
#include <xine/xineutils.h>
+#include "yuv2rgb.h"
#include <vdpau/vdpau_x11.h>
#include "accel_vdpau.h"
@@ -90,14 +91,6 @@ char* vdpau_deinterlacer_description [] = {
};
-char *vdpau_sd_only_properties[] = {
- "none",
- "noise",
- "sharpness",
- "noise+sharpness",
- NULL
-};
-
VdpOutputSurfaceRenderBlendState blend = {
VDP_OUTPUT_SURFACE_RENDER_BLEND_STATE_VERSION,
VDP_OUTPUT_SURFACE_RENDER_BLEND_FACTOR_ONE,
@@ -133,9 +126,7 @@ 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;
@@ -292,6 +283,26 @@ 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;
int width, height, format, flags;
@@ -304,13 +315,6 @@ typedef struct {
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;
vo_scale_t sc;
@@ -323,25 +327,27 @@ typedef struct {
config_values_t *config;
int ovl_changed;
- vo_overlay_t *overlays[XINE_VORAW_MAX_OVL];
- uint32_t *overlay_bitmap;
- int overlay_bitmap_size;
-
- VdpOutputSurface overlay_output_surface;
+ vdpau_overlay_t overlays[XINE_VORAW_MAX_OVL];
+ yuv2rgb_factory_t *yuv2rgb_factory;
+ yuv2rgb_t *ovl_yuv2rgb;
+ VdpOutputSurface overlay_output;
uint32_t overlay_output_width;
uint32_t overlay_output_height;
- vdpau_rect_t overlay_dirty_rect;
int has_overlay;
- VdpOutputSurface overlay_unscaled_surface;
+ VdpOutputSurface overlay_unscaled;
uint32_t overlay_unscaled_width;
uint32_t overlay_unscaled_height;
- vdpau_rect_t overlay_unscaled_dirty_rect;
int has_unscaled;
- VdpOutputSurface overlay_render_surface;
- uint32_t overlay_render_width;
- uint32_t overlay_render_height;
+ 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];
int32_t video_window_x;
int32_t video_window_y;
@@ -353,13 +359,12 @@ typedef struct {
uint32_t soft_surface_height;
int soft_surface_format;
-#define NOUTPUTSURFACE 8
+#define NOUTPUTSURFACE 2
VdpOutputSurface output_surface[NOUTPUTSURFACE];
uint8_t current_output_surface;
uint32_t output_surface_width[NOUTPUTSURFACE];
uint32_t output_surface_height[NOUTPUTSURFACE];
uint8_t init_queue;
- uint8_t queue_length;
VdpVideoMixer video_mixer;
VdpChromaType video_mixer_chroma;
@@ -399,7 +404,6 @@ typedef struct {
int enable_inverse_telecine;
int honor_progressive;
int skip_chroma;
- int sd_only_properties;
int studio_levels;
int background;
@@ -420,421 +424,410 @@ typedef struct {
} vdpau_class_t;
-static void vdpau_overlay_begin (vo_driver_t *this_gen, vo_frame_t *frame_gen, int changed)
+
+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; i<sizeof(overlay->color)/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; i<sizeof(overlay->color)/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)
{
vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
+ int i, k;
- if ( !changed )
- return;
+ vo_overlay_t *ovl[XINE_VORAW_MAX_OVL];
+ argb_ovl_data_t ovl_data[XINE_VORAW_MAX_OVL];
+ int ovl_data_count = 0;
- this->has_overlay = this->has_unscaled = 0;
+ int total_extent_width = 0, total_extent_height = 0;
this->video_window_x = 0;
this->video_window_y = 0;
this->video_window_width = 0;
this->video_window_height = 0;
- ++this->ovl_changed;
- lprintf("overlay begin\n");
+
+ /* 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 void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay)
+static int vdpau_process_ovl( vdpau_driver_t *this_gen, vo_overlay_t *overlay )
{
- vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
+ vdpau_overlay_t *ovl = &this_gen->overlays[this_gen->ovl_changed-1];
- int i = this->ovl_changed;
- if (!i)
- return;
+ if ( overlay->width<=0 || overlay->height<=0 )
+ return 0;
- if (--i >= XINE_VORAW_MAX_OVL)
- return;
+ 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; 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;
+ }
+ uint32_t pitch = ovl->ovl_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;
+}
- if (overlay->width <= 0 || overlay->height <= 0 || (!overlay->rle && (!overlay->argb_layer || !overlay->argb_layer->buffer)))
- return;
- 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;
- }
+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;
+
+ if ( !changed )
+ 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_end (vo_driver_t *this_gen, vo_frame_t *frame)
+static void vdpau_overlay_blend (vo_driver_t *this_gen, vo_frame_t *frame_gen, vo_overlay_t *overlay)
{
- VdpStatus st;
vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
+ vdpau_frame_t *frame = (vdpau_frame_t *) frame_gen;
- int novls = this->ovl_changed;
- if (novls < 2) {
- this->ovl_changed = 0;
+ if (!this->ovl_changed)
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;
}
- --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;
+ if (overlay->argb_layer) {
+ if (this->argb_ovl_count >= XINE_VORAW_MAX_OVL)
+ return;
+ this->argb_ovl[this->argb_ovl_count++] = overlay;
+ }
+}
+
+
+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;
- 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;
- }
+ VdpStatus st;
- 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 ( !this->ovl_changed )
+ return;
- if (dirty_rect.x2 > output_width)
- output_width = dirty_rect.x2;
- if (dirty_rect.y2 > output_height)
- output_height = dirty_rect.y2;
+ if (this->argb_ovl_count || this->argb_ovl_data_count)
+ vdpau_process_argb_ovls(this, frame);
- 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 ( !(this->ovl_changed-1) ) {
+ this->ovl_changed = 0;
+ this->has_overlay = 0;
+ this->has_unscaled = 0;
+ return;
}
- 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 w=0, h=0;
+ int scaler = 0;
+ for ( i=0; i<this->ovl_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;
+ }
+
+ if ( scaler ) {
+ w = this->video_mixer_width;
+ h = this->video_mixer_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));
+ int out_w = (w>frame->width) ? w : frame->width;
+ int out_h = (h>frame->height) ? h : frame->height;
- 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 ( (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 ( st != VDP_STATUS_OK ) {
fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) );
}
- this->overlay_render_surface = VDP_INVALID_HANDLE;
+ this->overlay_output = VDP_INVALID_HANDLE;
}
- 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_output_surface = VDP_INVALID_HANDLE;
+ this->overlay_output_width = out_w;
+ this->overlay_output_height = out_h;
+
+ w = 64; h = 64;
+ for ( i=0; i<this->ovl_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->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 ( (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 ( st != VDP_STATUS_OK ) {
- fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) );
+ fprintf(stderr, "vdpau_overlay_end: vdp_output_surface_destroy failed : %s\n", vdp_get_error_string(st) );
}
- this->overlay_unscaled_surface = VDP_INVALID_HANDLE;
+ this->overlay_unscaled = VDP_INVALID_HANDLE;
}
- 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 );
+ this->overlay_unscaled_width = w;
+ this->overlay_unscaled_height = h;
+
+ 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 ( 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 (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;
- }
-
- 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;
-
- 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;
+ 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 (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)));
- }
+ 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 (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) );
- }
- }
+ 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) );
}
-
- 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));
+ 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; i<this->ovl_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 (!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));
- }
+ 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) );
}
}
-
+ this->has_overlay = 1;
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);
}
@@ -916,55 +909,74 @@ static vo_frame_t *vdpau_alloc_frame (vo_driver_t *this_gen)
-static void vdpau_provide_standard_frame_data (vo_frame_t *this, xine_current_frame_data_t *data)
+static void vdpau_provide_standard_frame_data (vo_frame_t *this_gen, xine_current_frame_data_t *data)
{
+ vdpau_frame_t *this = (vdpau_frame_t *)this_gen;
VdpStatus st;
VdpYCbCrFormat format;
- uint32_t pitches[3];
- void *base[3];
- if (this->format != XINE_IMGFMT_VDPAU) {
- fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->format);
+ if (this->vo_frame.format != XINE_IMGFMT_VDPAU) {
+ fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->vo_frame.format);
return;
}
- vdpau_accel_t *accel = (vdpau_accel_t *) this->accel_data;
-
- if (accel->vdp_runtime_nr != *(accel->current_vdp_runtime_nr))
- return;
-
- this = accel->vo_frame;
-
- if (accel->chroma == VDP_CHROMA_TYPE_420) {
+ if (!(this->flags & VO_CHROMA_422)) {
data->format = XINE_IMGFMT_YV12;
- data->img_size = this->width * this->height
- + ((this->width + 1) / 2) * ((this->height + 1) / 2)
- + ((this->width + 1) / 2) * ((this->height + 1) / 2);
+ data->img_size = this->vo_frame.width * this->vo_frame.height
+ + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2)
+ + ((this->vo_frame.width + 1) / 2) * ((this->vo_frame.height + 1) / 2);
if (data->img) {
- pitches[0] = this->width;
- pitches[2] = this->width / 2;
- pitches[1] = this->width / 2;
- base[0] = data->img;
- base[2] = data->img + this->width * this->height;
- base[1] = data->img + this->width * this->height + this->width * this->height / 4;
+ this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 7) / 8);
+ this->vo_frame.pitches[1] = 8*((this->vo_frame.width + 15) / 16);
+ this->vo_frame.pitches[2] = 8*((this->vo_frame.width + 15) / 16);
+ this->vo_frame.base[0] = av_mallocz(this->vo_frame.pitches[0] * this->vo_frame.height);
+ this->vo_frame.base[1] = av_mallocz(this->vo_frame.pitches[1] * ((this->vo_frame.height+1)/2));
+ this->vo_frame.base[2] = av_mallocz(this->vo_frame.pitches[2] * ((this->vo_frame.height+1)/2));
format = VDP_YCBCR_FORMAT_YV12;
}
} else {
data->format = XINE_IMGFMT_YUY2;
- data->img_size = this->width * this->height
- + ((this->width + 1) / 2) * this->height
- + ((this->width + 1) / 2) * this->height;
+ data->img_size = this->vo_frame.width * this->vo_frame.height
+ + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height
+ + ((this->vo_frame.width + 1) / 2) * this->vo_frame.height;
if (data->img) {
- pitches[0] = this->width * 2;
- base[0] = data->img;
+ this->vo_frame.pitches[0] = 8*((this->vo_frame.width + 3) / 4);
+ this->vo_frame.base[0] = av_mallocz(this->vo_frame.pitches[0] * this->vo_frame.height);
format = VDP_YCBCR_FORMAT_YUYV;
}
}
if (data->img) {
- st = vdp_video_surface_getbits_ycbcr(accel->surface, format, base, pitches);
+ st = vdp_video_surface_getbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches);
if (st != VDP_STATUS_OK)
fprintf(stderr, "vo_vdpau: failed to get surface bits !! %s\n", vdp_get_error_string(st));
+
+ if (format == VDP_YCBCR_FORMAT_YV12) {
+ yv12_to_yv12(
+ /* Y */
+ this->vo_frame.base[0], this->vo_frame.pitches[0],
+ data->img, this->vo_frame.width,
+ /* U */
+ this->vo_frame.base[2], this->vo_frame.pitches[2],
+ data->img+this->vo_frame.width*this->vo_frame.height, this->vo_frame.width/2,
+ /* V */
+ this->vo_frame.base[1], this->vo_frame.pitches[1],
+ data->img+this->vo_frame.width*this->vo_frame.height+this->vo_frame.width*this->vo_frame.height/4, this->vo_frame.width/2,
+ /* width x height */
+ this->vo_frame.width, this->vo_frame.height);
+ } else {
+ yuy2_to_yuy2(
+ /* src */
+ this->vo_frame.base[0], this->vo_frame.pitches[0],
+ /* dst */
+ data->img, this->vo_frame.width*2,
+ /* width x height */
+ this->vo_frame.width, this->vo_frame.height);
+ }
+
+ av_freep (&this->vo_frame.base[0]);
+ av_freep (&this->vo_frame.base[1]);
+ av_freep (&this->vo_frame.base[2]);
}
}
@@ -1362,7 +1374,7 @@ static void vdpau_update_noise( vdpau_driver_t *this_gen )
return;
float value = this_gen->noise/100.0;
- if ( value==0 || ((this_gen->sd_only_properties & 1) && this_gen->video_mixer_width >= 800)) {
+ if ( value==0 ) {
VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_NOISE_REDUCTION };
VdpBool feature_enables[] = { 0 };
vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables );
@@ -1391,7 +1403,7 @@ static void vdpau_update_sharpness( vdpau_driver_t *this_gen )
return;
float value = this_gen->sharpness/100.0;
- if ( value==0 || (this_gen->sd_only_properties >= 2 && this_gen->video_mixer_width >= 800)) {
+ if ( value==0 ) {
VdpVideoMixerFeature features[] = { VDP_VIDEO_MIXER_FEATURE_SHARPNESS };
VdpBool feature_enables[] = { 0 };
vdp_video_mixer_set_feature_enables( this_gen->video_mixer, 1, features, feature_enables );
@@ -1414,18 +1426,6 @@ static void vdpau_update_sharpness( vdpau_driver_t *this_gen )
-static void vdpau_update_sd_only_properties( void *this_gen, xine_cfg_entry_t *entry )
-{
- vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
-
- this->sd_only_properties = entry->num_value;
- printf( "vo_vdpau: enable sd only noise=%d, sd only sharpness %d\n", ((this->sd_only_properties & 1) != 0), (this->sd_only_properties >= 2) );
- vdpau_update_noise(this);
- vdpau_update_sharpness(this);
-}
-
-
-
static void vdpau_update_csc( vdpau_driver_t *this_gen )
{
float hue = this_gen->hue/100.0;
@@ -1560,10 +1560,10 @@ static void vdpau_shift_queue( vo_driver_t *this_gen )
{
vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
- if ( this->init_queue < this->queue_length )
+ if ( this->init_queue<2 )
++this->init_queue;
++this->current_output_surface;
- if ( this->current_output_surface >= this->queue_length )
+ if ( this->current_output_surface > (NOUTPUTSURFACE-1) )
this->current_output_surface = 0;
}
@@ -1703,7 +1703,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 = 2;
+ int num_layers = 3;
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,6 +1728,8 @@ 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;
@@ -1737,34 +1739,41 @@ 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;
- uint32_t layer_count = 0;
- VdpLayer layer[2];
- VdpRect ovl_source, unscaled_source;
+ 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;
if ( this->has_overlay ) {
- 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;
+ 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;
}
-
- 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;
+ 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;
/* recalculate video destination window to match osd's specified video window */
if (this->video_window_width > 0 && this->video_window_height > 0) {
- 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;
+ 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);
}
- ++layer_count;
}
/* try to get frame duration from previous img->pts when frame->duration is 0 */
@@ -1780,17 +1789,10 @@ 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>=this->queue_length )
- 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];
@@ -1817,7 +1819,7 @@ static void vdpau_display_frame (vo_driver_t *this_gen, vo_frame_t *frame_gen)
dm = this->deinterlacers_method[this->deinterlace_method_hd];
if ( (dm != DEINT_HALF_TEMPORAL) && (dm != DEINT_HALF_TEMPORAL_SPATIAL) && frame->vo_frame.future_frame ) { /* process second field */
- if ( this->init_queue>=this->queue_length ) {
+ if ( this->init_queue>1 ) {
#ifdef LOCKDISPLAY
XUnlockDisplay(this->display);
#endif
@@ -2002,11 +2004,9 @@ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *
#ifdef LOCKDISPLAY
XLockDisplay( this->display );
#endif
- int previous;
- if ( this->current_output_surface )
- previous = this->current_output_surface - 1;
- else
- previous = this->queue_length - 1;
+ int previous = this->current_output_surface - 1;
+ if ( previous < 0 )
+ previous = NOUTPUTSURFACE - 1;
vdp_queue_display( vdp_queue, this->output_surface[previous], 0, 0, 0 );
#ifdef LOCKDISPLAY
XUnlockDisplay( this->display );
@@ -2088,7 +2088,13 @@ static void vdpau_dispose (vo_driver_t *this_gen)
vdpau_driver_t *this = (vdpau_driver_t *) this_gen;
int i;
- free(this->overlay_bitmap);
+ this->ovl_yuv2rgb->dispose(this->ovl_yuv2rgb);
+ this->yuv2rgb_factory->dispose (this->yuv2rgb_factory);
+
+ for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) {
+ if ( this->overlays[i].ovl_bitmap != VDP_INVALID_HANDLE )
+ vdp_bitmap_destroy( this->overlays[i].ovl_bitmap );
+ }
if ( this->video_mixer!=VDP_INVALID_HANDLE )
vdp_video_mixer_destroy( this->video_mixer );
@@ -2096,12 +2102,12 @@ static void vdpau_dispose (vo_driver_t *this_gen)
vdp_video_surface_destroy( this->soft_surface );
if ( vdp_output_surface_destroy ) {
- 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 );
+ 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 );
for ( i=0; i<this->queue_length; ++i ) {
if ( this->output_surface[i]!=VDP_INVALID_HANDLE )
vdp_output_surface_destroy( this->output_surface[i] );
@@ -2191,7 +2197,7 @@ static void vdpau_reinit( vo_driver_t *this_gen )
this->current_output_surface = 0;
this->init_queue = 0;
int i;
- for ( i=0; i<this->queue_length; ++i ) {
+ for ( i=0; i<NOUTPUTSURFACE; ++i ) {
st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[i], this->output_surface_height[i], &this->output_surface[i] );
if ( vdpau_reinit_error( st, "Can't create output surface !!" ) ) {
int j;
@@ -2205,16 +2211,24 @@ static void vdpau_reinit( vo_driver_t *this_gen )
}
}
- this->overlay_output_surface = VDP_INVALID_HANDLE;
+ /* osd overlays need to be recreated */
+ for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) {
+ this->overlays[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_width = this->overlay_output_height = 0;
- this->overlay_unscaled_surface = VDP_INVALID_HANDLE;
+ this->overlay_unscaled = 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 ) {
@@ -2244,12 +2258,12 @@ 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 = 2;
+ int num_layers = 3;
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 !!" ) ) {
orig_vdp_video_surface_destroy( this->soft_surface );
- for ( i=0; i<this->queue_length; ++i )
+ for ( i=0; i<NOUTPUTSURFACE; ++i )
vdp_output_surface_destroy( this->output_surface[i] );
#ifdef LOCKDISPLAY
XUnlockDisplay(guarded_display);
@@ -2368,18 +2382,28 @@ 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;
- this->overlay_output_surface = VDP_INVALID_HANDLE;
+ for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) {
+ this->overlays[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_width = this->overlay_output_height = 0;
- this->overlay_unscaled_surface = VDP_INVALID_HANDLE;
+ this->overlay_unscaled = 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 : " );
@@ -2452,15 +2476,9 @@ 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;
@@ -2575,24 +2593,13 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) )
return NULL;
- this->queue_length = config->register_num (config, "video.output.vdpau_display_queue_length", 3, /* default */
- _("default length of display queue"),
- _("The default number of video output surfaces to create for the display queue"),
- 20, NULL, this);
- if (this->queue_length < 2)
- this->queue_length = 2;
- if (this->queue_length > NOUTPUTSURFACE)
- this->queue_length = NOUTPUTSURFACE;
- fprintf(stderr, "vo_vdpau: using %d output surfaces for display queue\n", this->queue_length);
-
- for ( i=0; i<this->queue_length; ++i ) {
+ for ( i=0; i<NOUTPUTSURFACE; ++i ) {
this->output_surface_width[i] = 320;
this->output_surface_height[i] = 240;
}
this->current_output_surface = 0;
this->init_queue = 0;
-
- for ( i=0; i<this->queue_length; ++i ) {
+ for ( i=0; i<NOUTPUTSURFACE; ++i ) {
st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[i], this->output_surface_height[i], &this->output_surface[i] );
if ( vdpau_init_error( st, "Can't create output surface !!", &this->vo_driver, 1 ) ) {
int j;
@@ -2661,12 +2668,12 @@ 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 = 2;
+ int num_layers = 3;
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 ) ) {
vdp_video_surface_destroy( this->soft_surface );
- for ( i=0; i<this->queue_length; ++i )
+ for ( i=0; i<NOUTPUTSURFACE; ++i )
vdp_output_surface_destroy( this->output_surface[i] );
return NULL;
}
@@ -2756,18 +2763,6 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo
10, vdpau_set_background, this );
}
- this->sd_only_properties = config->register_enum( config, "video.output.vdpau_sd_only_properties", 0, vdpau_sd_only_properties,
- _("vdpau: restrict enabling video properties for SD video only"),
- _("none\n"
- "No restrictions\n\n"
- "noise\n"
- "Restrict noise reduction property.\n\n"
- "sharpness\n"
- "Restrict sharpness property.\n\n"
- "noise+sharpness"
- "Restrict noise and sharpness properties.\n\n"),
- 10, vdpau_update_sd_only_properties, this );
-
/* number of video frames from config - register it with the default value. */
int frame_num = config->register_num (config, "engine.buffers.video_num_frames", 15, /* default */
_("default number of video frames"),