All pastes #1846624 Raw Edit

Zoolooc

public text v1 · immutable
#1846624 ·published 2010-03-20 13:43 UTC
rendered paste body
diff -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, &current_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;