From: Andreas A. <ya...@in...> - 2012-01-03 18:47:55
|
# HG changeset patch # User Andreas Auras <ya...@in...> # Date 1325586430 -3600 # Node ID 0244b2cec7001d37a5dabbe7ef8f5afe47edbd6c # Branch default # Parent 428234cb878771f167d45857315e57e1f42b791f Complete rewrite of vdpau output driver osd handling. The new implementation has the following advantages towards the existing one: There is now a unique processing of RLE coded images and ARGB based overlay images. For both formats scaled and unscaled images and a video window are supported. Both formats are rendered now in given order into the same output surface not using a dedicated output surface for scaled, unscaled and ARGB images any more. Processing of YCBCR overlay images now uses corresponding vdpau upload functions eliminating the existing (possible slower) conversation to RGB images. Optimized processing of first overlay from stack avoiding unnecessary surface initialization and rendering operations. Currently the new implementation does only take the dirty rect information of a ARGB overlay into account for optimization if this is the only one object that should be displayed. diff --git a/include/xine.h b/include/xine.h --- a/include/xine.h +++ b/include/xine.h @@ -2196,7 +2196,7 @@ #define XINE_OSD_CAP_FREETYPE2 0x0001 /* freetype2 support compiled in */ #define XINE_OSD_CAP_UNSCALED 0x0002 /* unscaled overlays supp. by vo drv */ #define XINE_OSD_CAP_CUSTOM_EXTENT 0x0004 /* hardware scaled to match video output window */ -#define XINE_OSD_CAP_ARGB_LAYER 0x0008 /* supports separate true color layer */ +#define XINE_OSD_CAP_ARGB_LAYER 0x0008 /* supports ARGB true color pixmaps */ #define XINE_OSD_CAP_VIDEO_WINDOW 0x0010 /* can scale video to an area within osd extent */ typedef struct xine_osd_s xine_osd_t; @@ -2264,13 +2264,12 @@ const uint8_t *const trans ) XINE_PROTECTED; /* - * set an argb buffer to be blended into video - * the buffer must exactly match the osd dimensions - * and stay valid while the osd is on screen. pass - * a NULL pointer to safely remove the buffer from - * the osd layer. only the dirty area will be - * updated on screen. for convinience the whole - * osd object will be considered dirty when setting + * Set an ARGB buffer to be blended into video. + * The buffer must stay valid while the OSD is on screen. + * Pass a NULL pointer to safely remove the buffer from + * the OSD layer. Only the dirty area will be + * updated on screen. For convenience the whole + * OSD object will be considered dirty when setting * a different buffer pointer. * see also XINE_OSD_CAP_ARGB_LAYER */ --git a/src/video_out/Makefile.am b/src/video_out/Makefile.am --- a/src/video_out/Makefile.am +++ b/src/video_out/Makefile.am @@ -121,7 +121,7 @@ xineplug_vo_out_none.la xineplug_vo_out_vdpau_la_SOURCES = video_out_vdpau.c -xineplug_vo_out_vdpau_la_LIBADD = $(YUV_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) $(VDPAU_LIBS) -lm +xineplug_vo_out_vdpau_la_LIBADD = $(XINE_LIB) $(MLIB_LIBS) $(AVUTIL_LIBS) $(PTHREAD_LIBS) $(X_LIBS) $(LTLIBINTL) $(VDPAU_LIBS) -lm xineplug_vo_out_vdpau_la_CFLAGS = $(VISIBILITY_FLAG) $(MLIB_CFLAGS) $(X_CFLAGS) $(VDPAU_CFLAGS) $(AVUTIL_CFLAGS) -fno-strict-aliasing xineplug_vo_out_xcbshm_la_SOURCES = video_out_xcbshm.c $(XCBOSD) --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -47,7 +47,6 @@ #include <xine/vo_scale.h> #include <xine/xine_internal.h> #include <xine/xineutils.h> -#include "yuv2rgb.h" #include <vdpau/vdpau_x11.h> #include "accel_vdpau.h" @@ -124,6 +123,7 @@ VdpGetInformationString *vdp_get_information_string; VdpGetErrorString *vdp_get_error_string; +VdpVideoSurfaceQueryCapabilities *vdp_video_surface_query_capabilities; VdpVideoSurfaceQueryGetPutBitsYCbCrCapabilities *vdp_video_surface_query_get_put_bits_ycbcr_capabilities; VdpVideoSurfaceCreate *vdp_video_surface_create; VdpVideoSurfaceDestroy *vdp_video_surface_destroy; @@ -131,12 +131,15 @@ VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_getbits_ycbcr; VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; +VdpOutputSurfaceQueryCapabilities *vdp_output_surface_query_capabilities; +VdpOutputSurfaceQueryGetPutBitsNativeCapabilities *vdp_output_surface_query_get_put_bits_native_capabilities; +VdpOutputSurfaceQueryPutBitsYCbCrCapabilities *vdp_output_surface_query_put_bits_ycbcr_capabilities; VdpOutputSurfaceCreate *vdp_output_surface_create; VdpOutputSurfaceDestroy *vdp_output_surface_destroy; -VdpOutputSurfaceRenderBitmapSurface *vdp_output_surface_render_bitmap_surface; VdpOutputSurfaceRenderOutputSurface *vdp_output_surface_render_output_surface; +VdpOutputSurfaceGetBitsNative *vdp_output_surface_get_bits; VdpOutputSurfacePutBitsNative *vdp_output_surface_put_bits; -VdpOutputSurfaceGetBitsNative *vdp_output_surface_get_bits; +VdpOutputSurfacePutBitsYCbCr *vdp_output_surface_put_bits_ycbcr; VdpVideoMixerCreate *vdp_video_mixer_create; VdpVideoMixerDestroy *vdp_video_mixer_destroy; @@ -162,10 +165,6 @@ VdpPresentationQueueGetTime *vdp_queue_get_time; VdpPresentationQueueQuerySurfaceStatus *vdp_queue_query_surface_status; -VdpBitmapSurfacePutBitsNative *vdp_bitmap_put_bits; -VdpBitmapSurfaceCreate *vdp_bitmap_create; -VdpBitmapSurfaceDestroy *vdp_bitmap_destroy; - VdpDecoderQueryCapabilities *vdp_decoder_query_capabilities; VdpDecoderCreate *vdp_decoder_create; VdpDecoderDestroy *vdp_decoder_destroy; @@ -304,26 +303,6 @@ typedef struct { - VdpBitmapSurface ovl_bitmap; - uint32_t bitmap_width, bitmap_height; - int ovl_w, ovl_h; /* overlay's width and height */ - int ovl_x, ovl_y; /* overlay's top-left display position */ - int unscaled; - int expected_overlay_width; /*if >0 scale to video width*/ - int expected_overlay_height; /* if >0 scale to video height */ -} vdpau_overlay_t; - - -typedef struct { - int x; - int y; - int w; - int h; -} -argb_ovl_data_t; - - -typedef struct { vo_frame_t vo_frame; int width, height, format, flags; @@ -337,6 +316,33 @@ typedef struct { + int x; /* x start of subpicture area */ + int y; /* y start of subpicture area */ + int width; /* width of subpicture area */ + int height; /* height of subpicture area */ + + /* area within osd extent to scale video to */ + int video_window_x; + int video_window_y; + int video_window_width; + int video_window_height; + + /* extent of reference coordinate system */ + int extent_width; + int extent_height; + + int unscaled; /* true if it should be blended unscaled */ + + vo_overlay_t *ovl; + + VdpOutputSurface render_surface; + uint32_t render_width; + uint32_t render_height; +} vdpau_overlay_t; + + +typedef struct { + vo_driver_t vo_driver; vo_scale_t sc; @@ -347,33 +353,24 @@ config_values_t *config; - int ovl_changed; + int ovl_changed; + int num_ovls; + int created_ovls; vdpau_overlay_t overlays[XINE_VORAW_MAX_OVL]; - yuv2rgb_factory_t *yuv2rgb_factory; - yuv2rgb_t *ovl_yuv2rgb; - VdpOutputSurface overlay_output; - uint32_t overlay_output_width; - uint32_t overlay_output_height; - int has_overlay; - - VdpOutputSurface overlay_unscaled; - uint32_t overlay_unscaled_width; - uint32_t overlay_unscaled_height; [... 1068 lines omitted ...] + this->ovl_use_dirty_rect = 0; + this->ovl_src_rect.x0 = 0; + this->ovl_src_rect.y0 = 0; + + for (i = 0; i < XINE_VORAW_MAX_OVL; ++i) + this->overlays[i].render_surface = VDP_INVALID_HANDLE; VdpStatus st = vdp_device_create_x11( visual->display, visual->screen, &vdp_device, &vdp_get_proc_address ); if ( st != VDP_STATUS_OK ) { @@ -2662,10 +2615,32 @@ const char *s; st = vdp_get_information_string( &s ); fprintf(stderr, "vo_vdpau: vdpau implementation description : %s\n", s ); + VdpBool ok; + uint32_t max_surface_width, max_surface_height; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_CAPABILITIES , (void*)&vdp_video_surface_query_capabilities ); + if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_video_surface_query_capabilities( vdp_device, VDP_CHROMA_TYPE_422, &ok, &max_surface_width, &max_surface_height ); + if ( vdpau_init_error( st, "Failed to check vdpau chroma type 4:2:2 capability", &this->vo_driver, 1 ) ) + return NULL; + if ( !ok ) { + fprintf(stderr, "vo_vdpau: VideoSurface doesn't support chroma type 4:2:2, sorry.\n"); + vdpau_dispose( &this->vo_driver ); + return NULL; + } + fprintf(stderr, "vo_vdpau: maximum video surface size for chroma type 4:2:2 is %dx%d\n", (int)max_surface_width, (int)max_surface_height ); + st = vdp_video_surface_query_capabilities( vdp_device, VDP_CHROMA_TYPE_420, &ok, &max_surface_width, &max_surface_height ); + if ( vdpau_init_error( st, "Failed to check vdpau chroma type 4:2:0 capability", &this->vo_driver, 1 ) ) + return NULL; + if ( !ok ) { + fprintf(stderr, "vo_vdpau: VideoSurface doesn't support chroma type 4:2:0, sorry.\n"); + vdpau_dispose( &this->vo_driver ); + return NULL; + } + fprintf(stderr, "vo_vdpau: maximum video surface size for chroma type 4:2:0 is %dx%d\n", (int)max_surface_width, (int)max_surface_height ); st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES , (void*)&vdp_video_surface_query_get_put_bits_ycbcr_capabilities ); if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_QUERY_GET_PUT_BITS_Y_CB_CR_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) return NULL; - VdpBool ok; st = vdp_video_surface_query_get_put_bits_ycbcr_capabilities( vdp_device, VDP_CHROMA_TYPE_422, VDP_YCBCR_FORMAT_YUYV, &ok ); if ( vdpau_init_error( st, "Failed to check vdpau yuy2 capability", &this->vo_driver, 1 ) ) return NULL; @@ -2682,6 +2657,40 @@ vdpau_dispose( &this->vo_driver ); return NULL; } + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_CAPABILITIES , (void*)&vdp_output_surface_query_capabilities ); + if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_QUERY_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_output_surface_query_capabilities( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, &ok, &max_surface_width, &max_surface_height ); + if ( vdpau_init_error( st, "Failed to check vdpau rgba capability", &this->vo_driver, 1 ) ) + return NULL; + if ( !ok ) { + fprintf(stderr, "vo_vdpau: OutputSurface doesn't support rgba, sorry.\n"); + vdpau_dispose( &this->vo_driver ); + return NULL; + } + fprintf(stderr, "vo_vdpau: maximum output surface size is %dx%d\n", (int)max_surface_width, (int)max_surface_height ); + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES , (void*)&vdp_output_surface_query_get_put_bits_native_capabilities ); + if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_QUERY_GET_PUT_BITS_NATIVE_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_output_surface_query_get_put_bits_native_capabilities( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, &ok ); + if ( vdpau_init_error( st, "Failed to check vdpau get/put bits native capability", &this->vo_driver, 1 ) ) + return NULL; + if ( !ok ) { + fprintf(stderr, "vo_vdpau: OutputSurface doesn't support get/put bits native, sorry.\n"); + vdpau_dispose( &this->vo_driver ); + return NULL; + } + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES , (void*)&vdp_output_surface_query_put_bits_ycbcr_capabilities ); + if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_QUERY_PUT_BITS_Y_CB_CR_CAPABILITIES proc address !!", &this->vo_driver, 1 ) ) + return NULL; + st = vdp_output_surface_query_put_bits_ycbcr_capabilities( vdp_device, VDP_RGBA_FORMAT_B8G8R8A8, VDP_YCBCR_FORMAT_V8U8Y8A8, &ok ); + if ( vdpau_init_error( st, "Failed to check vdpau put bits ycbcr capability", &this->vo_driver, 1 ) ) + return NULL; + if ( !ok ) { + fprintf(stderr, "vo_vdpau: OutputSurface doesn't support put bits ycbcr, sorry.\n"); + vdpau_dispose( &this->vo_driver ); + return NULL; + } st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DEVICE_DESTROY , (void*)&vdp_device_destroy ); if ( vdpau_init_error( st, "Can't get DEVICE_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -2706,15 +2715,15 @@ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY , (void*)&orig_vdp_output_surface_destroy ); vdp_output_surface_destroy = guarded_vdp_output_surface_destroy; if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE , (void*)&vdp_output_surface_render_bitmap_surface ); - if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_RENDER_BITMAP_SURFACE proc address !!", &this->vo_driver, 1 ) ) - return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE , (void*)&vdp_output_surface_render_output_surface ); if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_RENDER_OUTPUT_SURFACE proc address !!", &this->vo_driver, 1 ) ) return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_output_surface_put_bits ); if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR , (void*)&vdp_output_surface_put_bits_ycbcr ); + if ( vdpau_init_error( st, "Can't get VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_Y_CB_CR 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; @@ -2793,15 +2802,6 @@ st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_DECODER_RENDER , (void*)&orig_vdp_decoder_render ); vdp_decoder_render = guarded_vdp_decoder_render; if ( vdpau_init_error( st, "Can't get DECODER_RENDER proc address !!", &this->vo_driver, 1 ) ) return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_CREATE , (void*)&vdp_bitmap_create ); - if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) - return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_DESTROY , (void*)&vdp_bitmap_destroy ); - if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_DESTROY proc address !!", &this->vo_driver, 1 ) ) - return NULL; - st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_BITMAP_SURFACE_PUT_BITS_NATIVE , (void*)&vdp_bitmap_put_bits ); - if ( vdpau_init_error( st, "Can't get BITMAP_SURFACE_PUT_BITS_NATIVE proc address !!", &this->vo_driver, 1 ) ) - return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_PREEMPTION_CALLBACK_REGISTER, (void*)&vdp_preemption_callback_register ); if ( vdpau_init_error( st, "Can't get PREEMPTION_CALLBACK_REGISTER proc address !!", &this->vo_driver, 1 ) ) return NULL; @@ -2918,7 +2918,7 @@ #endif VdpVideoMixerParameter params[] = { VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_WIDTH, VDP_VIDEO_MIXER_PARAMETER_VIDEO_SURFACE_HEIGHT, VDP_VIDEO_MIXER_PARAMETER_CHROMA_TYPE, VDP_VIDEO_MIXER_PARAMETER_LAYERS }; - int num_layers = 3; + int num_layers = 1; void const *param_values[] = { &this->video_mixer_width, &this->video_mixer_height, &chroma, &num_layers }; st = vdp_video_mixer_create( vdp_device, features_count, features, 4, params, param_values, &this->video_mixer ); if ( vdpau_init_error( st, "Can't create video mixer !!", &this->vo_driver, 1 ) ) { |