[Archvdr-devel] SF.net SVN: archvdr:[305] trunk/archvdr
Brought to you by:
huceke
|
From: <hu...@us...> - 2009-08-05 11:45:55
|
Revision: 305
http://archvdr.svn.sourceforge.net/archvdr/?rev=305&view=rev
Author: huceke
Date: 2009-08-05 11:45:45 +0000 (Wed, 05 Aug 2009)
Log Message:
-----------
Added durchfliegers vdpau crop support in version 8.
Modified Paths:
--------------
trunk/archvdr/vdr-plugin-xineliboutput/PKGBUILD
trunk/archvdr/vdr-plugin-xineliboutput-cvs/PKGBUILD
trunk/archvdr/xine-lib-vdpau/PKGBUILD
trunk/archvdr/xine-lib-vdpau-1.2/PKGBUILD
Added Paths:
-----------
trunk/archvdr/xine-lib-vdpau/xine-vdpau-r275-crop-v8.diff
trunk/archvdr/xine-lib-vdpau-1.2/xine-vdpau-xine-lib-1.2-r273-crop-v8.diff
Modified: trunk/archvdr/vdr-plugin-xineliboutput/PKGBUILD
===================================================================
--- trunk/archvdr/vdr-plugin-xineliboutput/PKGBUILD 2009-08-04 10:46:25 UTC (rev 304)
+++ trunk/archvdr/vdr-plugin-xineliboutput/PKGBUILD 2009-08-05 11:45:45 UTC (rev 305)
@@ -2,7 +2,7 @@
pkgname=vdr-plugin-xineliboutput
pkgver=1.0.4
-pkgrel=4
+pkgrel=5
pkgdesc="VDR-Plugin to use VDR with budget cards. Alternative for vdr-xine."
url="http://sourceforge.net/projects/xineliboutput/"
arch=('i686' 'x86_64')
@@ -10,16 +10,20 @@
depends=('vdr=<1.7.0' 'xine-lib')
source=(http://downloads.sourceforge.net/xineliboutput/vdr-xineliboutput-${pkgver}.tgz?use_mirror=heanet
nosignal.mpg
- plugin.xineliboutput.conf)
+ plugin.xineliboutput.conf
+ xineliboutput-1.0.4-vdpau-support-v8.diff)
backup=('etc/vdr/plugins/plugin.xineliboutput.conf')
md5sums=('1465b36ecb962e4adf8b8e0522bc81b4'
'eff2e86089b8dc182f16b2018d1fd080'
- '0e1bdbbaff3e8e45776383c6584b171b')
+ '0e1bdbbaff3e8e45776383c6584b171b'
+ '5c303bbc60c3560e86fe40d92a220d85')
conflicts=('vdr-plubin-xineliboutput-cvs')
build() {
cd ${srcdir}/xineliboutput-$pkgver
+ patch -p1 -i ../xineliboutput-1.0.4-vdpau-support-v8.diff || return 1
+
make VDRDIR=/usr/include/vdr CXX=g++-4.3 \
LIBDIR=. \
LOCALEDIR="$startdir/pkg/usr/share/locale/" \
Modified: trunk/archvdr/vdr-plugin-xineliboutput-cvs/PKGBUILD
===================================================================
--- trunk/archvdr/vdr-plugin-xineliboutput-cvs/PKGBUILD 2009-08-04 10:46:25 UTC (rev 304)
+++ trunk/archvdr/vdr-plugin-xineliboutput-cvs/PKGBUILD 2009-08-05 11:45:45 UTC (rev 305)
@@ -1,7 +1,7 @@
# Contributor: Edgar Hucek <gimli at dark-green dot com>
pkgname=vdr-plugin-xineliboutput-cvs
-pkgver=20090605
+pkgver=20090805
pkgrel=1
pkgdesc="VDR-Plugin to use VDR with budget cards. Alternative for vdr-xine."
url="http://sourceforge.net/projects/xineliboutput/"
@@ -9,11 +9,12 @@
license=('GPL')
depends=('vdr' 'xine-lib')
source=(nosignal.mpg
- plugin.xineliboutput.conf)
+ plugin.xineliboutput.conf
+ xineliboutput-head-vdpau-support-v8.diff)
backup=('etc/vdr/plugins/plugin.xineliboutput.conf')
md5sums=('eff2e86089b8dc182f16b2018d1fd080'
'0e1bdbbaff3e8e45776383c6584b171b'
- '944897d51cf730e6a2fb5b9e0cf4b541')
+ '1b25981c59c1c2caf8d34c23db2683a1')
conflicts=('vdr-plugin-xineliboutput')
build() {
@@ -31,6 +32,8 @@
cp -r ${srcdir}/$_cvsmod ${srcdir}/$_cvsmod-build
cd ${srcdir}/$_cvsmod-build
+ patch -p1 -i ../xineliboutput-head-vdpau-support-v8.diff || return 1
+
./configure --disable-dbus-glib-1
make VDRDIR=/usr/include/vdr CXX=g++-4.3 \
LIBDIR=. \
Modified: trunk/archvdr/xine-lib-vdpau/PKGBUILD
===================================================================
--- trunk/archvdr/xine-lib-vdpau/PKGBUILD 2009-08-04 10:46:25 UTC (rev 304)
+++ trunk/archvdr/xine-lib-vdpau/PKGBUILD 2009-08-05 11:45:45 UTC (rev 305)
@@ -2,7 +2,7 @@
pkgname=xine-lib-vdpau
pkgver=275
-pkgrel=2
+pkgrel=3
pkgdesc="A free video player for Unix with vdpau support"
arch=('i686' 'x86_64')
url="http://xinehq.de/"
@@ -13,10 +13,12 @@
conflicts=('xine-lib')
source=(xine_aspect.diff
xine-lib.patch
- xine-lib-matroska-simpleblock.patch)
+ xine-lib-matroska-simpleblock.patch
+ xine-vdpau-r275-crop-v8.diff)
md5sums=('dfbfc0e55a6eb04fb350da9d791186b0'
'b2bc2d4d81812280a5ebec980663d6ce'
- '756c947a0b865c41b84a696f64379284')
+ '756c947a0b865c41b84a696f64379284'
+ 'd0b052c96a9099c64e0fbec4cc5bdddf')
build() {
@@ -32,6 +34,7 @@
patch -Np0 -i ../xine_aspect.diff || return 1
patch -Np1 -i ../xine-lib.patch || return 1
patch -Np1 -i ../xine-lib-matroska-simpleblock.patch
+ patch -p1 -i ../xine-vdpau-r275-crop-v8.diff || return 1
CXX=g++-4.3 CC=gcc-4.3 ./autogen.sh --prefix=/usr --disable-fb --disable-vidix --disable-dxr3 --disable-sdl --disable-xvmc --disable-oss --disable-syncfb
Added: trunk/archvdr/xine-lib-vdpau/xine-vdpau-r275-crop-v8.diff
===================================================================
--- trunk/archvdr/xine-lib-vdpau/xine-vdpau-r275-crop-v8.diff (rev 0)
+++ trunk/archvdr/xine-lib-vdpau/xine-vdpau-r275-crop-v8.diff 2009-08-05 11:45:45 UTC (rev 305)
@@ -0,0 +1,742 @@
+diff -Naurb -x '.[a-zA-Z]*' xine-vdpau-orig/include/xine.h.in xine-vdpau-patched/include/xine.h.in
+--- xine-vdpau-orig/include/xine.h.in 2009-07-15 15:40:42.000000000 +0000
++++ xine-vdpau-patched/include/xine.h.in 2009-07-15 15:57:16.000000000 +0000
+@@ -1432,6 +1432,27 @@
+ #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(...)
+ */
+
+@@ -1460,6 +1481,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 -Naurb -x '.[a-zA-Z]*' -x CVS xine-vdpau-orig/src/video_out/video_out_vdpau.c xine-vdpau-patched/src/video_out/video_out_vdpau.c
+--- xine-vdpau-orig/src/video_out/video_out_vdpau.c 2009-07-15 15:40:59.000000000 +0000
++++ xine-vdpau-patched/src/video_out/video_out_vdpau.c 2009-07-17 12:51:47.000000000 +0000
+@@ -52,6 +52,7 @@
+ #include "accel_vdpau.h"
+
+ #define NUM_FRAMES_BACK 1
++#define NUM_QUEUE_OUTPUT_SURFACES 4
+
+ /*#define LOCKDISPLAY*/ /*define this if you have a buggy libX11/xcb*/
+
+@@ -83,6 +84,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,
+@@ -117,7 +126,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;
+@@ -303,11 +314,16 @@
+ uint32_t soft_surface_height;
+ int soft_surface_format;
+
+- VdpOutputSurface output_surface[2];
++ VdpOutputSurface output_surface[NUM_QUEUE_OUTPUT_SURFACES];
+ uint8_t current_output_surface;
+- uint32_t output_surface_width[2];
+- uint32_t output_surface_height[2];
++ uint32_t output_surface_width[NUM_QUEUE_OUTPUT_SURFACES];
++ uint32_t output_surface_height[NUM_QUEUE_OUTPUT_SURFACES];
+ uint8_t init_queue;
++ uint8_t queue_length;
++ uint64_t output_surface_vpts[NUM_QUEUE_OUTPUT_SURFACES];
++ pthread_mutex_t output_surface_lock[NUM_QUEUE_OUTPUT_SURFACES];
++ pthread_cond_t queue_changed;
++ pthread_mutex_t queue_lock;
+
+ VdpVideoMixer video_mixer;
+ VdpChromaType video_mixer_chroma;
+@@ -342,6 +358,7 @@
+ int enable_inverse_telecine;
+ int honor_progressive;
+ int skip_chroma;
++ int sd_only_properties;
+
+ int vdp_runtime_nr;
+ int reinit_needed;
+@@ -843,84 +860,59 @@
+ }
+
+
+-
+-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] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * this->vo_frame.height, (void **)&this->chunk[0]);
+- this->vo_frame.base[1] = xine_xmalloc_aligned(16, this->vo_frame.pitches[1] * ((this->vo_frame.height+1)/2), (void **)&this->chunk[1]);
+- this->vo_frame.base[2] = xine_xmalloc_aligned(16, this->vo_frame.pitches[2] * ((this->vo_frame.height+1)/2), (void **)&this->chunk[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] = xine_xmalloc_aligned(16, this->vo_frame.pitches[0] * this->vo_frame.height, (void **)&this->chunk[0]);
++ 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)
+ printf("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);
+- }
+-
+- if (this->chunk[0])
+- free(this->chunk[0]);
+- if (this->chunk[1])
+- free(this->chunk[1]);
+- if (this->chunk[2])
+- free(this->chunk[2]);
+- this->chunk[0] = this->chunk[1] = this->chunk[2] = NULL;
+ }
+ }
+
+
+-
+ static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original)
+ {
+ vdpau_frame_t *this = (vdpau_frame_t *)this_gen;
+@@ -1240,7 +1232,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 );
+@@ -1269,7 +1261,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 );
+@@ -1292,6 +1284,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;
+@@ -1347,9 +1351,13 @@
+ {
+ 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 ^= 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);
+ }
+
+
+@@ -1493,8 +1501,6 @@
+ vdpau_update_csc( this );
+ }
+
+- vdpau_check_output_size( this_gen );
+-
+ VdpRect vid_source = { this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width+this->sc.displayed_xoffset, this->sc.displayed_height+this->sc.displayed_yoffset };
+ VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height };
+ VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height };
+@@ -1509,11 +1515,6 @@
+ stream_speed = 0; /* still image -> no delay */
+ }
+
+- 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;
+@@ -1555,10 +1556,20 @@
+ }
+ int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive;
+
++ VdpTime last_time;
++
++ if ( this->init_queue>1 )
++ vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time );
++
+ #ifdef LOCKDISPLAY
+ XLockDisplay( this->display );
+ #endif
+
++ 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 && stream_speed && frame_duration>2500 ) {
+ VdpTime current_time = 0;
+ VdpVideoSurface past[2];
+@@ -1574,6 +1585,8 @@
+ if ( st != VDP_STATUS_OK )
+ printf( "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 );
+@@ -1590,6 +1603,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;
+@@ -1604,6 +1622,8 @@
+ if ( st != VDP_STATUS_OK )
+ printf( "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]);
++
+ /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */
+ if (stream_speed > 0)
+ current_time += frame->vo_frame.duration * 100000ull * XINE_FINE_SPEED_NORMAL / (18 * stream_speed);
+@@ -1620,6 +1640,8 @@
+ if ( st != VDP_STATUS_OK )
+ printf( "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 );
+ }
+@@ -1744,6 +1766,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)
+ {
+@@ -1760,7 +1942,7 @@
+ #ifdef LOCKDISPLAY
+ XLockDisplay( this->display );
+ #endif
+- int previous = this->current_output_surface ^ 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 );
+@@ -1814,6 +1996,15 @@
+ 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;
+ }
+@@ -1857,10 +2048,10 @@
+ vdp_output_surface_destroy( this->overlay_unscaled );
+ if ( this->overlay_output!=VDP_INVALID_HANDLE )
+ vdp_output_surface_destroy( this->overlay_output );
+- if ( this->output_surface[0]!=VDP_INVALID_HANDLE )
+- vdp_output_surface_destroy( this->output_surface[0] );
+- if ( this->output_surface[1]!=VDP_INVALID_HANDLE )
+- vdp_output_surface_destroy( this->output_surface[1] );
++ for (i = 0; i < this->queue_length; ++i) {
++ if ( this->output_surface[i]!=VDP_INVALID_HANDLE )
++ vdp_output_surface_destroy( this->output_surface[i] );
++ }
+ }
+
+ if ( vdp_queue != VDP_INVALID_HANDLE )
+@@ -1875,6 +2066,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);
+ }
+
+@@ -1928,21 +2124,19 @@
+
+ this->current_output_surface = 0;
+ this->init_queue = 0;
+- st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] );
+- if ( vdpau_reinit_error( st, "Can't create first output surface !!" ) ) {
++ int 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 !!" ) ) {
++ while (--i > 0)
++ vdp_output_surface_destroy( this->output_surface[i] );
+ orig_vdp_video_surface_destroy( this->soft_surface );
+ return;
+ }
+- st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] );
+- if ( vdpau_reinit_error( st, "Can't create second output surface !!" ) ) {
+- orig_vdp_video_surface_destroy( this->soft_surface );
+- vdp_output_surface_destroy( this->output_surface[0] );
+- return;
+ }
+
+ /* osd overlays need to be recreated */
+
+- int i;
+ for ( i=0; i<XINE_VORAW_MAX_OVL; ++i ) {
+ this->overlays[i].ovl_bitmap = VDP_INVALID_HANDLE;
+ this->overlays[i].bitmap_width = 0;
+@@ -1988,8 +2182,8 @@
+ 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 );
+- vdp_output_surface_destroy( this->output_surface[0] );
+- vdp_output_surface_destroy( this->output_surface[1] );
++ for (i = 0; i < this->queue_length; ++i)
++ vdp_output_surface_destroy( this->output_surface[i] );
+ return;
+ }
+ this->video_mixer_chroma = chroma;
+@@ -2080,8 +2274,8 @@
+ this->vo_driver.redraw_needed = vdpau_redraw_needed;
+
+ this->video_mixer = VDP_INVALID_HANDLE;
+- this->output_surface[0] = VDP_INVALID_HANDLE;
+- this->output_surface[1] = VDP_INVALID_HANDLE;
++ for (i = 0; i < NUM_QUEUE_OUTPUT_SURFACES; ++i)
++ this->output_surface[i] = VDP_INVALID_HANDLE;
+ this->soft_surface = VDP_INVALID_HANDLE;
+ vdp_queue = VDP_INVALID_HANDLE;
+ vdp_queue_target = VDP_INVALID_HANDLE;
+@@ -2188,9 +2382,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;
+@@ -2302,20 +2502,31 @@
+ if ( vdpau_init_error( st, "Can't create video surface !!", &this->vo_driver, 1 ) )
+ return NULL;
+
+- this->output_surface_width[0] = this->output_surface_width[1] = 320;
+- this->output_surface_height[0] = this->output_surface_height[1] = 240;
++ 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 > NUM_QUEUE_OUTPUT_SURFACES)
++ this->queue_length = NUM_QUEUE_OUTPUT_SURFACES;
++
+ this->current_output_surface = 0;
+ this->init_queue = 0;
+- st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] );
+- if ( vdpau_init_error( st, "Can't create first output surface !!", &this->vo_driver, 1 ) ) {
++ pthread_mutex_init(&this->queue_lock, NULL);
++ pthread_cond_init(&this->queue_changed, NULL);
++
++ for (i = 0; i < this->queue_length; ++i) {
++ this->output_surface_width[i] = 320;
++ this->output_surface_height[i] = 240;
++ 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 ) ) {
++ while (--i > 0)
++ vdp_output_surface_destroy( this->output_surface[i] );
+ vdp_video_surface_destroy( this->soft_surface );
+ return NULL;
+ }
+- st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[1], this->output_surface_height[1], &this->output_surface[1] );
+- if ( vdpau_init_error( st, "Can't create second output surface !!", &this->vo_driver, 1 ) ) {
+- vdp_video_surface_destroy( this->soft_surface );
+- vdp_output_surface_destroy( this->output_surface[0] );
+- return NULL;
+ }
+
+ vdp_video_mixer_query_feature_support( vdp_device, VDP_VIDEO_MIXER_FEATURE_DEINTERLACE_TEMPORAL, &this->temporal_is_supported );
+@@ -2358,8 +2569,8 @@
+ 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 );
+- vdp_output_surface_destroy( this->output_surface[0] );
+- vdp_output_surface_destroy( this->output_surface[1] );
++ for (i = 0; i < this->queue_length; ++i)
++ vdp_output_surface_destroy( this->output_surface[i] );
+ return NULL;
+ }
+
+@@ -2424,6 +2635,18 @@
+ 10, vdpau_set_skip_chroma, 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 -Naurb -x '.[a-zA-Z]*' -x CVS xine-vdpau-orig/src/xine-utils/utils.c xine-vdpau-patched/src/xine-utils/utils.c
+--- xine-vdpau-orig/src/xine-utils/utils.c 2009-07-15 15:41:08.000000000 +0000
++++ xine-vdpau-patched/src/xine-utils/utils.c 2009-07-15 15:45:19.000000000 +0000
+@@ -460,21 +460,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 */
+ 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;
Modified: trunk/archvdr/xine-lib-vdpau-1.2/PKGBUILD
===================================================================
--- trunk/archvdr/xine-lib-vdpau-1.2/PKGBUILD 2009-08-04 10:46:25 UTC (rev 304)
+++ trunk/archvdr/xine-lib-vdpau-1.2/PKGBUILD 2009-08-05 11:45:45 UTC (rev 305)
@@ -3,7 +3,7 @@
pkgname=xine-lib-vdpau-1.2
pkgver=275
hgver=10950
-pkgrel=2
+pkgrel=3
pkgdesc="A free video player for Unix with vdpau support"
arch=('i686' 'x86_64')
url="http://hg.debian.org/hg/xine-lib/xine-lib-1.2"
@@ -13,9 +13,11 @@
provides=('xine-lib')
conflicts=('xine-lib' 'xine-lib-vdpau')
source=(http://www.jusst.de/vdpau/files/xine-lib-1.2/xine-lib-1.2-vdpau-r${pkgver}.diff.bz2
- libavcodec_fix.patch)
+ libavcodec_fix.patch
+ xine-vdpau-xine-lib-1.2-r273-crop-v8.diff)
md5sums=('dc4978376ede9161dba402ae868699e9'
- '7bb9d92d050db92a643ad88bc530d6ec')
+ '7bb9d92d050db92a643ad88bc530d6ec'
+ '9d4f6aa07a7e8f529dba0b0ecccda298')
build() {
@@ -46,6 +48,7 @@
patch -p1 -i ../xine-lib-1.2-vdpau-r${pkgver}.diff || return 1
patch -p1 -i ../libavcodec_fix.patch || return 1
+ patch -p1 -i ../xine-vdpau-xine-lib-1.2-r273-crop-v8.diff || return 1
CXX=g++-4.3 CC=gcc-4.3 ./autogen.sh --prefix=/usr --disable-fb --disable-vidix --disable-dxr3 --disable-sdl --disable-xvmc --disable-oss --disable-syncfb
Added: trunk/archvdr/xine-lib-vdpau-1.2/xine-vdpau-xine-lib-1.2-r273-crop-v8.diff
===================================================================
--- trunk/archvdr/xine-lib-vdpau-1.2/xine-vdpau-xine-lib-1.2-r273-crop-v8.diff (rev 0)
+++ trunk/archvdr/xine-lib-vdpau-1.2/xine-vdpau-xine-lib-1.2-r273-crop-v8.diff 2009-08-05 11:45:45 UTC (rev 305)
@@ -0,0 +1,739 @@
+diff -Naurb -x '.[a-zA-Z]*' xine-lib-1.2-orig/include/xine.h xine-lib-1.2/include/xine.h
+--- xine-lib-1.2-orig/include/xine.h 2009-07-15 15:28:30.000000000 +0000
++++ xine-lib-1.2/include/xine.h 2009-07-12 00:29:17.000000000 +0000
+@@ -1378,6 +1378,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(...)
+ */
+@@ -1407,6 +1429,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 -Naurb -x '.[a-zA-Z]*' 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 2009-07-15 15:28:30.000000000 +0000
++++ xine-lib-1.2/src/video_out/video_out_vdpau.c 2009-07-17 12:51:39.000000000 +0000
+@@ -58,6 +58,7 @@
+ #include "accel_vdpau.h"
+
+ #define NUM_FRAMES_BACK 1
++#define NUM_QUEUE_OUTPUT_SURFACES 4
+
+ /*#define LOCKDISPLAY*/ /*define this if you have a buggy libX11/xcb*/
+
+@@ -89,6 +90,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 +132,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;
+@@ -308,11 +319,16 @@
+ uint32_t soft_surface_height;
+ int soft_surface_format;
+
+- VdpOutputSurface output_surface[2];
++ VdpOutputSurface output_surface[NUM_QUEUE_OUTPUT_SURFACES];
+ uint8_t current_output_surface;
+- uint32_t output_surface_width[2];
+- uint32_t output_surface_height[2];
++ uint32_t output_surface_width[NUM_QUEUE_OUTPUT_SURFACES];
++ uint32_t output_surface_height[NUM_QUEUE_OUTPUT_SURFACES];
+ uint8_t init_queue;
++ uint8_t queue_length;
++ uint64_t output_surface_vpts[NUM_QUEUE_OUTPUT_SURFACES];
++ pthread_mutex_t output_surface_lock[NUM_QUEUE_OUTPUT_SURFACES];
++ pthread_cond_t queue_changed;
++ pthread_mutex_t queue_lock;
+
+ VdpVideoMixer video_mixer;
+ VdpChromaType video_mixer_chroma;
+@@ -347,6 +363,7 @@
+ int enable_inverse_telecine;
+ int honor_progressive;
+ int skip_chroma;
++ int sd_only_properties;
+
+ int vdp_runtime_nr;
+ int reinit_needed;
+@@ -842,80 +859,59 @@
+ }
+
+
+-
+-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)
+ printf("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]);
+ }
+ }
+
+
+-
+ static void vdpau_duplicate_frame_data (vo_frame_t *this_gen, vo_frame_t *original)
+ {
+ vdpau_frame_t *this = (vdpau_frame_t *)this_gen;
+@@ -1225,7 +1221,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 );
+@@ -1254,7 +1250,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 );
+@@ -1277,6 +1273,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;
+@@ -1332,9 +1340,13 @@
+ {
+ 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 ^= 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);
+ }
+
+
+@@ -1478,8 +1490,6 @@
+ vdpau_update_csc( this );
+ }
+
+- vdpau_check_output_size( this_gen );
+-
+ VdpRect vid_source = { this->sc.displayed_xoffset, this->sc.displayed_yoffset, this->sc.displayed_width+this->sc.displayed_xoffset, this->sc.displayed_height+this->sc.displayed_yoffset };
+ VdpRect out_dest = { 0, 0, this->sc.gui_width, this->sc.gui_height };
+ VdpRect vid_dest = { this->sc.output_xoffset, this->sc.output_yoffset, this->sc.output_xoffset+this->sc.output_width, this->sc.output_yoffset+this->sc.output_height };
+@@ -1494,11 +1504,6 @@
+ stream_speed = 0; /* still image -> no delay */
+ }
+
+- 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;
+@@ -1540,10 +1545,20 @@
+ }
+ int non_progressive = (this->honor_progressive && !frame->vo_frame.progressive_frame) || !this->honor_progressive;
+
++ VdpTime last_time;
++
++ if ( this->init_queue>1 )
++ vdp_queue_block( vdp_queue, this->output_surface[this->current_output_surface], &last_time );
++
+ #ifdef LOCKDISPLAY
+ XLockDisplay( this->display );
+ #endif
+
++ 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 && stream_speed && frame_duration>2500 ) {
+ VdpTime current_time = 0;
+ VdpVideoSurface past[2];
+@@ -1559,6 +1574,8 @@
+ if ( st != VDP_STATUS_OK )
+ printf( "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 );
+@@ -1575,6 +1592,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 );
+
+ past[0] = surface;
+@@ -1589,6 +1611,8 @@
+ if ( st != VDP_STATUS_OK )
+ printf( "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]);
++
+ /* calculate delay for second field: there should be no delay for still images otherwise, take replay speed into account */
+ if (stream_speed > 0)
+ current_time += frame->vo_frame.duration * 100000ull * XINE_FINE_SPEED_NORMAL / (18 * stream_speed);
+@@ -1605,6 +1629,8 @@
+ if ( st != VDP_STATUS_OK )
+ printf( "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 );
+ }
+@@ -1729,6 +1755,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)
+ {
+@@ -1745,7 +1931,7 @@
+ #ifdef LOCKDISPLAY
+ XLockDisplay( this->display );
+ #endif
+- int previous = this->current_output_surface ^ 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 );
+@@ -1799,6 +1985,15 @@
+ 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;
+ }
+@@ -1842,10 +2037,10 @@
+ vdp_output_surface_destroy( this->overlay_unscaled );
+ if ( this->overlay_output!=VDP_INVALID_HANDLE )
+ vdp_output_surface_destroy( this->overlay_output );
+- if ( this->output_surface[0]!=VDP_INVALID_HANDLE )
+- vdp_output_surface_destroy( this->output_surface[0] );
+- if ( this->output_surface[1]!=VDP_INVALID_HANDLE )
+- vdp_output_surface_destroy( this->output_surface[1] );
++ for (i = 0; i < this->queue_length; ++i) {
++ if ( this->output_surface[i]!=VDP_INVALID_HANDLE )
++ vdp_output_surface_destroy( this->output_surface[i] );
++ }
+ }
+
+ if ( vdp_queue != VDP_INVALID_HANDLE )
+@@ -1860,6 +2055,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);
+ }
+
+@@ -1913,21 +2113,19 @@
+
+ this->current_output_surface = 0;
+ this->init_queue = 0;
+- st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[0] );
+- if ( vdpau_reinit_error( st, "Can't create first output surface !!" ) ) {
++ int 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 !!" ) ) {
++ while (--i > 0)
++ vdp_output_surface_destroy( this->output_surface[i] );
+ orig_vdp_video_surface_destroy( this->soft_surface );
+ return;
+ }
+- st = vdp_output_surface_create( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, this->output_surface_width[0], this->output_surface_height[0], &this->output_surface[1] );
+- if ( vdpau_reinit_error( st, "Can't create second output surface !!" ) ) {
+- orig_vdp_video_surface_destroy( this->soft_surface );
+- vdp_output_surface_destroy( this->output_surface...
[truncated message content] |