rendered paste bodydiff -Naur xine-lib-1.2_orig/include/xine/vdr.h xine-lib-1.2/include/xine/vdr.h--- xine-lib-1.2_orig/include/xine/vdr.h 2010-01-24 22:47:00.000000000 +0100+++ xine-lib-1.2/include/xine/vdr.h 2010-01-24 22:52:20.108397432 +0100@@ -45,6 +45,7 @@ , func_start , func_wait , func_setup+ , func_grab_image_vdpau , func_grab_image , func_get_pts , func_flush@@ -412,6 +413,19 @@ +typedef struct __attribute__((packed)) data_grab_image_vdpau_s+{+ data_header_t header;+ + uint16_t width;+ uint16_t height;+ uint16_t jpeg;+ uint16_t quality;+}+data_grab_image_vdpau_t;+++ typedef struct __attribute__((packed)) data_grab_image_s { data_header_t header;@@ -616,6 +630,7 @@ data_start_t start; data_wait_t wait; data_setup_t setup;+ data_grab_image_vdpau_t grab_image_vdpau; data_grab_image_t grab_image; data_get_pts_t get_pts; data_first_frame_t first_frame;diff -Naur xine-lib-1.2_orig/include/xine.h xine-lib-1.2/include/xine.h--- xine-lib-1.2_orig/include/xine.h 2010-01-24 22:47:00.000000000 +0100+++ xine-lib-1.2/include/xine.h 2010-01-24 22:52:20.108397432 +0100@@ -1392,6 +1392,28 @@ #endif /* WIN32 */ ++/*+ * frame structure used for grabbing raw RGB output frames+ */+typedef struct {+ /* Cropping of source image */+ int crop_left;+ int crop_right;+ int crop_top;+ int crop_bottom;++ /* Parameters of returned image */+ int width;+ int height;+ uint8_t *img;+ uint64_t vpts;++ int timeout; /* Max. time to wait for next frame in milliseconds */++} xine_grab_frame_t;++ /* * "type" constants for xine_port_send_gui_data(...) */@@ -1421,6 +1443,18 @@ /* Gui is about to destroy drawable */ #define XINE_GUI_SEND_WILL_DESTROY_DRAWABLE 9 +/* Allocate grab frame */+/* xine_grab_frame_t **data */+#define XINE_GUI_SEND_ALLOC_GRAB_FRAME 10++/* Free grab frame */+/* xine_grab_frame_t *data */+#define XINE_GUI_SEND_FREE_GRAB_FRAME 11++/* Grab image of last displayed frame */+/* xine_grab_frame_t *data */+#define XINE_GUI_SEND_GRAB_FRAME 12+ /********************************************************************* * xine health check stuff *diff -Naur xine-lib-1.2_orig/src/vdr/Makefile.am xine-lib-1.2/src/vdr/Makefile.am--- xine-lib-1.2_orig/src/vdr/Makefile.am 2010-01-24 22:47:07.000000000 +0100+++ xine-lib-1.2/src/vdr/Makefile.am 2010-01-24 22:52:20.118397559 +0100@@ -9,4 +9,5 @@ endif xineplug_vdr_la_SOURCES = combined_vdr.c combined_vdr.h input_vdr.c post_vdr_video.c post_vdr_audio.c-xineplug_vdr_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS)+xineplug_vdr_la_LIBADD = $(XINE_LIB) $(PTHREAD_LIBS) -ljpeg+diff -Naur xine-lib-1.2_orig/src/vdr/input_vdr.c xine-lib-1.2/src/vdr/input_vdr.c--- xine-lib-1.2_orig/src/vdr/input_vdr.c 2010-01-24 22:47:10.000000000 +0100+++ xine-lib-1.2/src/vdr/input_vdr.c 2010-01-24 22:52:20.118397559 +0100@@ -50,6 +50,14 @@ +#ifdef boolean+# define HAVE_BOOLEAN+#endif+#include <jpeglib.h>+#undef boolean +++ #define VDR_MAX_NUM_WINDOWS 16 #define VDR_ABS_FIFO_DIR "/var/vdr/xine" @@ -184,6 +192,53 @@ +#define JPEGCOMPRESSMEM 500000++typedef struct tJpegCompressData_s {+ int size;+ unsigned char *mem;+} tJpegCompressData;++static void JpegCompressInitDestination(const j_compress_ptr cinfo)+{+ tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;+ if (jcd) {+ cinfo->dest->free_in_buffer = jcd->size = JPEGCOMPRESSMEM;+ cinfo->dest->next_output_byte = jcd->mem = + (unsigned char *)malloc(jcd->size);+ }+}++static boolean JpegCompressEmptyOutputBuffer(const j_compress_ptr cinfo)+{+ tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;+ if (jcd) {+ int Used = jcd->size;+ jcd->size += JPEGCOMPRESSMEM;+ jcd->mem = (unsigned char *)realloc(jcd->mem, jcd->size);+ if (jcd->mem) {+ cinfo->dest->next_output_byte = jcd->mem + Used;+ cinfo->dest->free_in_buffer = jcd->size - Used;+ return TRUE;+ }+ }+ return FALSE;+}++static void JpegCompressTermDestination(const j_compress_ptr cinfo)+{+ tJpegCompressData *jcd = (tJpegCompressData *)cinfo->client_data;+ if (jcd) {+ int Used = cinfo->dest->next_output_byte - jcd->mem;+ if (Used < jcd->size) {+ jcd->size = Used;+ jcd->mem = (unsigned char *)realloc(jcd->mem, jcd->size);+ }+ }+}+++ static int vdr_write(int f, void *b, int n) { int t = 0, r;@@ -427,6 +482,12 @@ if (this->osd_supports_custom_extent && data->w_ref > 0 && data->h_ref > 0) xine_osd_set_extent(this->osd[ data->window ].window, data->w_ref, data->h_ref);++ /*+ * We use a new object type id for osd objects coming from this input plugin so that+ * post plugins like autocrop can do special handling+ */+ this->osd[ data->window ].window->osd.renderer->event.object.object_type = 2; } break; @@ -1088,6 +1149,137 @@ } break; +/* --- neu --- */++ case func_grab_image_vdpau:+ {+ off_t ret_val = -1;+ xine_grab_frame_t *grab_frame;++ READ_DATA_OR_FAIL(grab_image_vdpau, lprintf("got VDPAU-GRABIMAGE\n"));++ if (!data->jpeg) /* convert to PNM */+ {+ if (!xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_ALLOC_GRAB_FRAME, &grab_frame))+ {+ int size;+ result_grab_image_t result_grab_image;++ grab_frame->width = data->width;+ grab_frame->height = data->height;+ if (xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_GRAB_FRAME, grab_frame))+ {+ xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_FREE_GRAB_FRAME, grab_frame);+ return ret_val; + }++ /* allocate memory for result */+ size_t bytes = data->width * data->height * 3;+ uint8_t *pnm = malloc(bytes + 64);+ if (!pnm)+ {+ xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_FREE_GRAB_FRAME, grab_frame);+ return ret_val;+ }++ /* PNM header */+ sprintf((char*)pnm, "P6\n%d\n%d\n255\n", data->width, data->height);+ int hdrlen = strlen((char*)pnm);++ /* copy image */+ xine_fast_memcpy(pnm + hdrlen, grab_frame->img, bytes);++ size = bytes + hdrlen;++ xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_FREE_GRAB_FRAME, grab_frame);++ result_grab_image.header.func = data->header.func;+ result_grab_image.header.len = sizeof (result_grab_image) + size;++ result_grab_image.width = data->width;+ result_grab_image.height = data->height;++ if (sizeof (result_grab_image) == vdr_write(this->fh_result, &result_grab_image, sizeof (result_grab_image)))+ {+ if (!size || (size == vdr_write(this->fh_result, (char*) pnm, size)))+ ret_val = 0;+ }++ free(pnm);+ }+ }+ else /* JPEG */+ {+ if (!xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_ALLOC_GRAB_FRAME, &grab_frame))+ {+ int size;+ result_grab_image_t result_grab_image;++ grab_frame->width = data->width;+ grab_frame->height = data->height;+ if (xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_GRAB_FRAME, grab_frame))+ {+ xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_FREE_GRAB_FRAME, grab_frame);+ return ret_val; + }++ /* Compress JPEG */+ struct jpeg_destination_mgr jdm;+ struct jpeg_compress_struct cinfo;+ struct jpeg_error_mgr jerr;+ tJpegCompressData jcd;++ jdm.init_destination = JpegCompressInitDestination;+ jdm.empty_output_buffer = JpegCompressEmptyOutputBuffer;+ jdm.term_destination = JpegCompressTermDestination;+ cinfo.err = jpeg_std_error(&jerr);+ jpeg_create_compress(&cinfo);+ cinfo.dest = &jdm;+ cinfo.client_data = &jcd;+ cinfo.image_width = data->width;+ cinfo.image_height = data->height;+ cinfo.input_components = 3;+ cinfo.in_color_space = JCS_RGB;++ jpeg_set_defaults(&cinfo);+ jpeg_set_quality(&cinfo, data->quality, TRUE);+ jpeg_start_compress(&cinfo, TRUE);++ JSAMPROW rp[data->height];+ int rs = data->width * 3;+ int k;+ for (k = 0; k < data->height; k++)+ rp[k] = grab_frame->img + k * rs;+ jpeg_write_scanlines(&cinfo, rp, data->height);++ jpeg_finish_compress(&cinfo);+ jpeg_destroy_compress(&cinfo);++ size = jcd.size;++ xine_port_send_gui_data(this->stream->video_out, XINE_GUI_SEND_FREE_GRAB_FRAME, grab_frame);++ result_grab_image.header.func = data->header.func;+ result_grab_image.header.len = sizeof (result_grab_image) + size;+ result_grab_image.width = data->width;+ result_grab_image.height = data->height;++ if (sizeof (result_grab_image) == vdr_write(this->fh_result, &result_grab_image, sizeof (result_grab_image)))+ {+ if (!size || (size == vdr_write(this->fh_result, (char*) jcd.mem, size)))+ ret_val = 0;+ }+ free(jcd.mem);+ }+ }++ if (ret_val != 0)+ return ret_val;+ }+ break;++/* --- */+ case func_grab_image: { READ_DATA_OR_FAIL(grab_image, lprintf("got GRABIMAGE\n"));diff -Naur xine-lib-1.2_orig/src/video_out/video_out_vdpau.c xine-lib-1.2/src/video_out/video_out_vdpau.c--- xine-lib-1.2_orig/src/video_out/video_out_vdpau.c 2010-01-24 22:47:08.000000000 +0100+++ xine-lib-1.2/src/video_out/video_out_vdpau.c 2010-01-24 22:54:20.358397699 +0100@@ -89,6 +89,14 @@ }; +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,@@ -123,7 +131,9 @@ 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;+VdpOutputSurfaceGetBitsNative *vdp_output_surface_get_bits; VdpVideoMixerCreate *vdp_video_mixer_create; VdpVideoMixerDestroy *vdp_video_mixer_destroy;@@ -292,15 +302,6 @@ uint32_t overlay_unscaled_height; 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];- int32_t video_window_x; int32_t video_window_y; int32_t video_window_width;@@ -311,12 +312,17 @@ uint32_t soft_surface_height; int soft_surface_format; -#define NOUTPUTSURFACE 2+#define NOUTPUTSURFACE 4 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;+ uint64_t output_surface_vpts[NOUTPUTSURFACE];+ pthread_mutex_t output_surface_lock[NOUTPUTSURFACE];+ pthread_cond_t queue_changed;+ pthread_mutex_t queue_lock; VdpVideoMixer video_mixer; VdpChromaType video_mixer_chroma;@@ -356,6 +362,7 @@ int honor_progressive; int skip_chroma; int studio_levels;+ int sd_only_properties; int background; int vdp_runtime_nr;@@ -398,139 +405,6 @@ -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;-- vo_overlay_t *ovl[XINE_VORAW_MAX_OVL];- argb_ovl_data_t ovl_data[XINE_VORAW_MAX_OVL];- int ovl_data_count = 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;-- /* 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];@@ -538,6 +412,22 @@ if ( overlay->width<=0 || overlay->height<=0 ) return 0; + 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;++ if (overlay->video_window_width > 0 && overlay->video_window_height > 0) {+ /* last one wins */+ this_gen->video_window_x = overlay->video_window_x;+ this_gen->video_window_y = overlay->video_window_y;+ this_gen->video_window_width = overlay->video_window_width;+ this_gen->video_window_height = overlay->video_window_height;+ }+ 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 );@@ -546,17 +436,13 @@ 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) );+ return 0; } 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;++ if (overlay->rle) { uint32_t *buf = (uint32_t*)malloc(ovl->ovl_w*ovl->ovl_h*4); if ( !buf ) return 0;@@ -612,6 +498,20 @@ fprintf(stderr, "vdpau_process_ovl: vdp_bitmap_put_bits failed : %s\n", vdp_get_error_string(st) ); } free(buf);+ }+ else if (overlay->argb_layer) {+ pthread_mutex_lock(&overlay->argb_layer->mutex);+ if (overlay->argb_layer->buffer) {+ 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, &overlay->argb_layer->buffer, &pitch, &dest);+ if ( st != VDP_STATUS_OK ) {+ printf( "vdpau_process_ovl: vdp_bitmap_put_bits failed : %s\n", vdp_get_error_string(st) );+ }+ }+ pthread_mutex_unlock(&overlay->argb_layer->mutex);+ }+ return 1; } @@ -625,8 +525,10 @@ return; this->has_overlay = this->has_unscaled = 0;- this->has_argb_overlay = 0;- this->argb_ovl_count = 0;+ this->video_window_x = 0;+ this->video_window_y = 0;+ this->video_window_width = 0;+ this->video_window_height = 0; ++this->ovl_changed; } @@ -640,20 +542,15 @@ if (!this->ovl_changed) return; - if (overlay->rle) { if (this->ovl_changed >= XINE_VORAW_MAX_OVL) return;++ if (overlay->rle) { 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->argb_layer) {- if (this->argb_ovl_count >= XINE_VORAW_MAX_OVL)- return;- this->argb_ovl[this->argb_ovl_count++] = overlay; }+ if ( vdpau_process_ovl( this, overlay ) )+ ++this->ovl_changed; } @@ -667,9 +564,6 @@ 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) ) { this->ovl_changed = 0; this->has_overlay = 0;@@ -690,6 +584,7 @@ scaler = 1; if ( this->overlays[i].expected_overlay_height ) scaler = 1;+ this->has_overlay = 1; } if ( scaler ) {@@ -700,7 +595,7 @@ int out_w = (w>frame->width) ? w : frame->width; int out_h = (h>frame->height) ? h : frame->height; - if ( (this->overlay_output_width!=out_w || this->overlay_output_height!=out_h) && this->overlay_output != VDP_INVALID_HANDLE ) {+ if ( (!this->has_overlay || 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) );@@ -719,9 +614,10 @@ 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->has_unscaled = 1; } - if ( (this->overlay_unscaled_width!=w || this->overlay_unscaled_height!=h) && this->overlay_unscaled != VDP_INVALID_HANDLE ) {+ if ( (!this->has_unscaled || 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) );@@ -732,13 +628,13 @@ this->overlay_unscaled_width = w; this->overlay_unscaled_height = h; - if ( this->overlay_unscaled == VDP_INVALID_HANDLE ) {+ if ( this->has_unscaled && 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) ); } - if ( this->overlay_output == VDP_INVALID_HANDLE ) {+ if ( this->has_overlay && 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) );@@ -750,21 +646,25 @@ 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 };+ if (this->has_overlay) { 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) ); }+ }+ if (this->has_unscaled) { 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 ) {+ if ( !this->overlays[i].unscaled && 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;@@ -777,7 +677,6 @@ 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; } @@ -860,74 +759,55 @@ -static void vdpau_provide_standard_frame_data (vo_frame_t *this_gen, xine_current_frame_data_t *data)+static void vdpau_provide_standard_frame_data (vo_frame_t *this, 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->vo_frame.format != XINE_IMGFMT_VDPAU) {- fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->vo_frame.format);+ if (this->format != XINE_IMGFMT_VDPAU) {+ fprintf(stderr, "vdpau_provide_standard_frame_data: unexpected frame format 0x%08x!\n", this->format); return; } - if (!(this->flags & VO_CHROMA_422)) {+ 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) { data->format = XINE_IMGFMT_YV12;- 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);+ data->img_size = this->width * this->height+ + ((this->width + 1) / 2) * ((this->height + 1) / 2)+ + ((this->width + 1) / 2) * ((this->height + 1) / 2); if (data->img) {- 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));+ pitches[0] = this->width;+ pitches[1] = this->width / 2;+ pitches[2] = this->width / 2;+ base[0] = data->img;+ base[1] = data->img + this->width * this->height;+ base[2] = data->img + this->width * this->height + this->width * this->height / 4; format = VDP_YCBCR_FORMAT_YV12; } } else { data->format = XINE_IMGFMT_YUY2;- 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;+ data->img_size = this->width * this->height+ + ((this->width + 1) / 2) * this->height+ + ((this->width + 1) / 2) * this->height; if (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);+ pitches[0] = this->width * 2;+ base[0] = data->img; format = VDP_YCBCR_FORMAT_YUYV; } } if (data->img) {- st = vdp_video_surface_getbits_ycbcr(this->vdpau_accel_data.surface, format, this->vo_frame.base, this->vo_frame.pitches);+ st = vdp_video_surface_getbits_ycbcr(accel->surface, format, base, 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]); } } @@ -1332,7 +1212,7 @@ return; float value = this_gen->noise/100.0;- if ( value==0 ) {+ if ( value==0 || ((this_gen->sd_only_properties & 1) && this_gen->video_mixer_width >= 800)) { 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 );@@ -1361,7 +1241,7 @@ return; float value = this_gen->sharpness/100.0;- if ( value==0 ) {+ if ( value==0 || (this_gen->sd_only_properties >= 2 && this_gen->video_mixer_width >= 800)) { 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 );@@ -1384,6 +1264,18 @@ +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;@@ -1518,11 +1410,14 @@ { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; - if ( this->init_queue<2 )+ pthread_mutex_lock(&this->queue_lock);+ if ( this->init_queue < this->queue_length ) ++this->init_queue; ++this->current_output_surface;- if ( this->current_output_surface > (NOUTPUTSURFACE-1) )+ if ( this->current_output_surface >= this->queue_length ) this->current_output_surface = 0;+ pthread_mutex_unlock(&this->queue_lock);+ pthread_cond_broadcast(&this->queue_changed); } @@ -1688,41 +1583,34 @@ 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; 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); }- else {- layer_count = 0;+ ++layer_count; } - 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; 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 */@@ -1734,10 +1622,20 @@ } int 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 + pthread_mutex_lock(&this->output_surface_lock[this->current_output_surface]);+ this->output_surface_vpts[this->current_output_surface] = frame->vo_frame.vpts;++ 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];@@ -1753,13 +1651,15 @@ if ( st != VDP_STATUS_OK ) fprintf(stderr, "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + pthread_mutex_unlock(&this->output_surface_lock[this->current_output_surface]);+ vdp_queue_get_time( vdp_queue, ¤t_time ); vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); /* display _now_ */ vdpau_shift_queue( this_gen ); int dm = this->deinterlacers_method[this->deinterlace_method]; if ( (dm != DEINT_HALF_TEMPORAL) && (dm != DEINT_HALF_TEMPORAL_SPATIAL) && frame->vo_frame.future_frame ) { /* process second field */- if ( this->init_queue>1 ) {+ if ( this->init_queue>=this->queue_length ) { #ifdef LOCKDISPLAY XUnlockDisplay(this->display); #endif@@ -1769,6 +1669,11 @@ #endif } + pthread_mutex_lock(&this->output_surface_lock[this->current_output_surface]);+ this->output_surface_vpts[this->current_output_surface] = frame->vo_frame.vpts;+ if (stream_speed > 0)+ this->output_surface_vpts[this->current_output_surface] += (uint64_t)frame->vo_frame.duration * XINE_FINE_SPEED_NORMAL / (2 * stream_speed);+ vdpau_check_output_size( this_gen ); picture_structure = ( frame->vo_frame.top_field_first ) ? VDP_VIDEO_MIXER_PICTURE_STRUCTURE_BOTTOM_FIELD : VDP_VIDEO_MIXER_PICTURE_STRUCTURE_TOP_FIELD;@@ -1783,6 +1688,8 @@ if ( st != VDP_STATUS_OK ) fprintf(stderr, "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + pthread_mutex_unlock(&this->output_surface_lock[this->current_output_surface]);+ if ( stream_speed > 0 ) current_time += frame->vo_frame.duration * 1000000ull * XINE_FINE_SPEED_NORMAL / (180 * stream_speed); @@ -1798,6 +1705,8 @@ if ( st != VDP_STATUS_OK ) fprintf(stderr, "vo_vdpau: vdp_video_mixer_render error : %s\n", vdp_get_error_string( st ) ); + pthread_mutex_unlock(&this->output_surface_lock[this->current_output_surface]);+ vdp_queue_display( vdp_queue, this->output_surface[this->current_output_surface], 0, 0, 0 ); vdpau_shift_queue( this_gen ); }@@ -1925,6 +1834,166 @@ } +typedef struct {+ xine_grab_frame_t grab_frame;++ VdpOutputSurface render_surface;+ int vdp_runtime_nr;+ int width, height;+ uint32_t *rgba;+} vdpau_grab_frame_t;+++static int vdpau_alloc_grab_frame(vdpau_driver_t *this, void *data)+{+ vdpau_grab_frame_t *frame = calloc(1, sizeof(vdpau_grab_frame_t));+ if (!frame)+ return -1;++ frame->render_surface = VDP_INVALID_HANDLE;+ frame->grab_frame.vpts = -1;+ *((vdpau_grab_frame_t **) data) = frame;++ return 0;+}+++static int vdpau_free_grab_frame(vdpau_driver_t *this, void *data)+{+ vdpau_grab_frame_t *frame = (vdpau_grab_frame_t *) data;++ free(frame->grab_frame.img);+ free(frame->rgba);+ if (frame->render_surface != VDP_INVALID_HANDLE && frame->vdp_runtime_nr == this->vdp_runtime_nr) {+ if (vdp_output_surface_destroy(frame->render_surface) != VDP_STATUS_OK)+ printf("vo_vdpau: Can't destroy output surface!\n");+ }+ free(frame);+ return 0;+}+++static int vdpau_grab_last_displayed_frame (vdpau_driver_t *this, void *data) {+ vdpau_grab_frame_t *frame = (vdpau_grab_frame_t *) data;+ int previous = -1;++ pthread_mutex_lock(&this->queue_lock);+ if (this->init_queue) {+ previous = this->current_output_surface ? this->current_output_surface - 1: this->queue_length - 1;++ /* Ensure that we do not grab the same frame again */+ if (frame->grab_frame.vpts == this->output_surface_vpts[previous])+ previous = -1;+ }+ if (previous == -1 && frame->grab_frame.timeout > 0) {+ /* wait for next displayed frame */+ struct timeval tvnow, tvdiff, tvtimeout;+ struct timespec ts;+ tvdiff.tv_sec = frame->grab_frame.timeout / 1000;+ tvdiff.tv_usec = frame->grab_frame.timeout % 1000;+ tvdiff.tv_usec *= 1000;+ gettimeofday(&tvnow, NULL);+ timeradd(&tvnow, &tvdiff, &tvtimeout);+ ts.tv_sec = tvtimeout.tv_sec;+ ts.tv_nsec = tvtimeout.tv_usec;+ ts.tv_nsec *= 1000;+ if (!pthread_cond_timedwait(&this->queue_changed, &this->queue_lock, &ts))+ previous = this->current_output_surface ? this->current_output_surface - 1: this->queue_length - 1;+ }+ pthread_mutex_unlock(&this->queue_lock);++ if (previous == -1)+ return 1; /* no frame available */++ pthread_mutex_lock(&this->output_surface_lock[previous]);++ int width = this->output_surface_width[previous] - frame->grab_frame.crop_left - frame->grab_frame.crop_right;+ int height = this->output_surface_height[previous] - frame->grab_frame.crop_top - frame->grab_frame.crop_bottom;+ if (width < 1)+ width = 1;+ if (height < 1)+ height = 1;++ if (frame->grab_frame.width <= 0)+ frame->grab_frame.width = width;+ if (frame->grab_frame.height <= 0)+ frame->grab_frame.height = height;++ if (frame->vdp_runtime_nr != this->vdp_runtime_nr)+ frame->render_surface = VDP_INVALID_HANDLE;++ if (frame->grab_frame.width != frame->width || frame->grab_frame.height != frame->height) {+ free(frame->rgba);+ free(frame->grab_frame.img);+ frame->rgba = NULL;+ frame->grab_frame.img = NULL;++ if (frame->render_surface != VDP_INVALID_HANDLE) {+ if (vdp_output_surface_destroy(frame->render_surface) != VDP_STATUS_OK)+ printf("vo_vdpau: Can't destroy output surface!\n");+ frame->render_surface = VDP_INVALID_HANDLE;+ }++ frame->width = frame->grab_frame.width;+ frame->height = frame->grab_frame.height;+ }++ if (frame->rgba == NULL) {+ frame->rgba = (uint32_t *) calloc(frame->width * frame->height, sizeof(uint32_t));+ if (frame->rgba == NULL)+ return -1;+ frame->grab_frame.img = (uint8_t *) calloc(frame->width * frame->height, 3);+ if (frame->grab_frame.img == NULL)+ return -1;+ }++ VdpStatus st;+ uint32_t pitches = frame->width * sizeof(uint32_t);+ VdpRect src_rect = { frame->grab_frame.crop_left, frame->grab_frame.crop_top, width+frame->grab_frame.crop_left, height+frame->grab_frame.crop_top };+ frame->grab_frame.vpts = this->output_surface_vpts[previous];++ if (frame->width != width || frame->height != height) {+ st = VDP_STATUS_OK;+ if (frame->render_surface == VDP_INVALID_HANDLE) {+ frame->vdp_runtime_nr = this->vdp_runtime_nr;+ st = vdp_output_surface_create(vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, frame->width, frame->height, &frame->render_surface);+ }+ if (st == VDP_STATUS_OK) {+ st = vdp_output_surface_render_output_surface(frame->render_surface, NULL, this->output_surface[previous], &src_rect, NULL, NULL, VDP_OUTPUT_SURFACE_RENDER_ROTATE_0);+ pthread_mutex_unlock(&this->output_surface_lock[previous]);+ if (st == VDP_STATUS_OK) {+ st = vdp_output_surface_get_bits(frame->render_surface, NULL, &frame->rgba, &pitches);+ if (st != VDP_STATUS_OK)+ printf("vo_vdpau: Can't get output surface bits for raw frame grabbing!\n");+ }+ else+ printf("vo_vdpau: Can't render output surface for raw frame grabbing!\n");+ } else {+ pthread_mutex_unlock(&this->output_surface_lock[previous]);+ printf("vo_vdpau: Can't create output surface for raw frame grabbing!\n");+ }+ } else {+ st = vdp_output_surface_get_bits(this->output_surface[previous], &src_rect, &frame->rgba, &pitches);+ pthread_mutex_unlock(&this->output_surface_lock[previous]);+ if (st != VDP_STATUS_OK)+ printf("vo_vdpau: Can't get output surface bits for raw frame grabbing!\n");+ }+ if (st == VDP_STATUS_OK) {+ uint32_t *src = frame->rgba;+ uint8_t *dst = frame->grab_frame.img;+ int n = frame->width * frame->height;+ while (n--) {+ *dst++ = (uint8_t)(*src >> 16); /*R*/+ *dst++ = (uint8_t)(*src >> 8); /*G*/+ *dst++ = (uint8_t)(*src++); /*B*/+ }+ return 0;+ }++ frame->grab_frame.vpts = -1;+ return -1;+}+ static int vdpau_gui_data_exchange (vo_driver_t *this_gen, int data_type, void *data) {@@ -1941,9 +2010,7 @@ #ifdef LOCKDISPLAY XLockDisplay( this->display ); #endif- int previous = this->current_output_surface - 1;- if ( previous < 0 )- previous = NOUTPUTSURFACE - 1;+ int previous = this->current_output_surface ? this->current_output_surface - 1: this->queue_length - 1; vdp_queue_display( vdp_queue, this->output_surface[previous], 0, 0, 0 ); #ifdef LOCKDISPLAY XUnlockDisplay( this->display );@@ -1996,6 +2063,14 @@ rect->h = y2-y1; break; }+ case XINE_GUI_SEND_ALLOC_GRAB_FRAME:+ return vdpau_alloc_grab_frame (this, data);++ case XINE_GUI_SEND_FREE_GRAB_FRAME:+ return vdpau_free_grab_frame (this, data);++ case XINE_GUI_SEND_GRAB_FRAME:+ return vdpau_grab_last_displayed_frame (this, data); default: return -1;@@ -2034,13 +2109,11 @@ 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 );- for ( i=0; i<NOUTPUTSURFACE; ++i ) {+ for ( i=0; i<this->queue_length; ++i ) { if ( this->output_surface[i]!=VDP_INVALID_HANDLE ) vdp_output_surface_destroy( this->output_surface[i] ); }@@ -2058,6 +2131,11 @@ if ( (vdp_device != VDP_INVALID_HANDLE) && vdp_device_destroy ) vdp_device_destroy( vdp_device ); + for (i = 0; i < this->queue_length; ++i)+ pthread_mutex_destroy(&this->output_surface_lock[i]);+ pthread_mutex_destroy(&this->queue_lock);+ pthread_cond_destroy(&this->queue_changed);+ free (this); } @@ -2112,7 +2190,7 @@ this->current_output_surface = 0; this->init_queue = 0; int i;- for ( i=0; i<NOUTPUTSURFACE; ++i ) {+ for ( i=0; i<this->queue_length; ++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;@@ -2137,10 +2215,6 @@ 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 ) {@@ -2175,7 +2249,7 @@ 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<NOUTPUTSURFACE; ++i )+ for ( i=0; i<this->queue_length; ++i ) vdp_output_surface_destroy( this->output_surface[i] ); return; }@@ -2304,10 +2378,6 @@ 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 );@@ -2381,9 +2451,15 @@ 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_GET_BITS_NATIVE , (void*)&vdp_output_surface_get_bits );+ if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE 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;@@ -2447,6 +2523,9 @@ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , (void*)&vdp_queue_query_surface_status ); if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_QUERY_SURFACE_STATUS proc address !!", &this->vo_driver, 1 ) ) return NULL;+ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PRESENTATION_QUEUE_QUERY_SURFACE_STATUS , (void*)&vdp_queue_query_surface_status );+ if ( vdpau_init_error( st, "Can't get PRESENTATION_QUEUE_QUERY_SURFACE_STATUS proc address !!", &this->vo_driver, 1 ) )+ return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_QUERY_CAPABILITIES , (void*)&vdp_decoder_query_capabilities ); if ( vdpau_init_error( st, "Can't get DECODER_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) return NULL;@@ -2498,13 +2577,26 @@ if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) ) return NULL; - for ( i=0; i<NOUTPUTSURFACE; ++i ) {+ this->queue_length = config->register_num (config, "video.output.vdpau_display_queue_length", 2, /* 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;++ for ( i=0; i<this->queue_length; ++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<NOUTPUTSURFACE; ++i ) {+ pthread_mutex_init(&this->queue_lock, NULL);+ pthread_cond_init(&this->queue_changed, NULL);++ for ( i=0; i<this->queue_length; ++i ) {+ pthread_mutex_init(&this->output_surface_lock[i], NULL); 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;@@ -2578,7 +2670,7 @@ 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<NOUTPUTSURFACE; ++i )+ for ( i=0; i<this->queue_length; ++i ) vdp_output_surface_destroy( this->output_surface[i] ); return NULL; }@@ -2663,6 +2755,18 @@ 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"),diff -Naur xine-lib-1.2_orig/src/xine-utils/utils.c xine-lib-1.2/src/xine-utils/utils.c--- xine-lib-1.2_orig/src/xine-utils/utils.c 2010-01-24 22:47:09.000000000 +0100+++ xine-lib-1.2/src/xine-utils/utils.c 2010-01-24 22:52:20.158399316 +0100@@ -482,21 +482,13 @@ /* select does not work on win32 */ Sleep(usec / 1000); #else-# if 0-# if HAVE_NANOSLEEP- /* nanosleep is prefered on solaris, because it's mt-safe */+ # if HAVE_NANOSLEEP struct timespec ts, remaining; ts.tv_sec = usec / 1000000; ts.tv_nsec = (usec % 1000000) * 1000; while (nanosleep (&ts, &remaining) == -1 && errno == EINTR) ts = remaining; # else- usleep(usec);-# endif-# else- if (usec < 10000) {- usec = 10000;- } struct timeval tm; tm.tv_sec = usec / 1000000; tm.tv_usec = usec % 1000000;