From 08712b40469e88b9642ce9c67465789f326b7cc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Reinhard=20Ni=C3=9Fl?= Date: Fri, 28 Jan 2011 23:44:07 +0100 Subject: Improve stability when decoding bad streams. VDPAU applies different constraints to surface size and memory consumption than xine. Hence, when decoding bad streams (due to receptions issues for examples) with broken image sizes, it is likely that segfaults happen due to different memory size assumptions. So by adjusting image size to meet xine and VDPAU constraints, segfaults can be avoided. --HG-- extra : rebase_source : c493fac162bb34ab357783821bc72be85682c1eb --- src/video_out/video_out_vdpau.c | 31 +++++++++++++++++++++++++++++++ 1 file changed, 31 insertions(+) (limited to 'src') diff --git a/src/video_out/video_out_vdpau.c b/src/video_out/video_out_vdpau.c index 0268e8e0d..45fa0c7e2 100644 --- a/src/video_out/video_out_vdpau.c +++ b/src/video_out/video_out_vdpau.c @@ -121,6 +121,7 @@ VdpVideoSurfaceCreate *vdp_video_surface_create; VdpVideoSurfaceDestroy *vdp_video_surface_destroy; VdpVideoSurfacePutBitsYCbCr *vdp_video_surface_putbits_ycbcr; VdpVideoSurfaceGetBitsYCbCr *vdp_video_surface_getbits_ycbcr; +VdpVideoSurfaceGetParameters *vdp_video_surface_get_parameters; VdpOutputSurfaceCreate *vdp_output_surface_create; VdpOutputSurfaceDestroy *vdp_output_surface_destroy; @@ -1034,6 +1035,8 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ { vdpau_driver_t *this = (vdpau_driver_t *) this_gen; vdpau_frame_t *frame = VDPAU_FRAME(frame_gen); + uint32_t requested_width = width; + uint32_t requested_height = height; int clear = 0; @@ -1051,6 +1054,15 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ } } + /* adjust width and height to meet xine and VDPAU constraints */ + width = (width + ((flags & VO_CHROMA_422) ? 3 : 15)) & ~((flags & VO_CHROMA_422) ? 3 : 15); /* xine constraint */ + height = (height + 3) & ~3; /* VDPAU constraint */ + /* any excess pixels from the adjustment will be cropped away */ + frame->vo_frame.width = width; + frame->vo_frame.height = height; + frame->vo_frame.crop_right += width - requested_width; + frame->vo_frame.crop_bottom += height - requested_height; + /* Check frame size and format and reallocate if necessary */ if ( (frame->width != width) || (frame->height != height) || (frame->format != format) || (frame->format==XINE_IMGFMT_VDPAU && frame->vdpau_accel_data.chroma!=chroma) || (frame->vdpau_accel_data.vdp_runtime_nr != this->vdp_runtime_nr)) { @@ -1101,6 +1113,22 @@ static void vdpau_update_frame_format (vo_driver_t *this_gen, vo_frame_t *frame_ ++this->allocated_surfaces; frame->vo_frame.proc_duplicate_frame_data = vdpau_duplicate_frame_data; frame->vo_frame.proc_provide_standard_frame_data = vdpau_provide_standard_frame_data; + + /* check whether allocated surface matches constraints */ + { + VdpChromaType ct = (VdpChromaType)-1; + int w = -1; + int h = -1; + + st = vdp_video_surface_get_parameters(frame->vdpau_accel_data.surface, &ct, &w, &h); + if (st != VDP_STATUS_OK) + fprintf(stderr, "vo_vdpau: failed to get parameters !! %s\n", vdp_get_error_string(st)); + else if (w != width || h != height) { + + fprintf(stderr, "vo_vdpau: video surface doesn't match size contraints (%d x %d) -> (%d x %d) != (%d x %d). Segfaults ahead!\n" + , requested_width, requested_height, width, height, w, h); + } + } } } @@ -2469,6 +2497,9 @@ static vo_driver_t *vdpau_open_plugin (video_driver_class_t *class_gen, const vo st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_GET_BITS_Y_CB_CR , (void*)&vdp_video_surface_getbits_ycbcr ); if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_GET_BITS_Y_CB_CR proc address !!", &this->vo_driver, 1 ) ) return NULL; + st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_VIDEO_SURFACE_GET_PARAMETERS , (void*)&vdp_video_surface_get_parameters ); + if ( vdpau_init_error( st, "Can't get VIDEO_SURFACE_GET_PARAMETERS proc address !!", &this->vo_driver, 1 ) ) + return NULL; st = vdp_get_proc_address( vdp_device, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE , (void*)&orig_vdp_output_surface_create ); vdp_output_surface_create = guarded_vdp_output_surface_create; if ( vdpau_init_error( st, "Can't get OUTPUT_SURFACE_CREATE proc address !!", &this->vo_driver, 1 ) ) return NULL; -- cgit v1.2.3