diff --git a/libvo/vo_vdpau.c b/libvo/vo_vdpau.c index 053405a806..c1c8e8facd 100644 --- a/libvo/vo_vdpau.c +++ b/libvo/vo_vdpau.c @@ -109,8 +109,8 @@ struct vdpctx { uint64_t last_vdp_time; unsigned int last_sync_update; - /* an extra last output surface is used for OSD and screenshots */ VdpOutputSurface output_surfaces[MAX_OUTPUT_SURFACES]; + VdpOutputSurface screenshot_surface; int num_output_surfaces; struct buffered_video_surface { VdpVideoSurface surface; @@ -401,20 +401,17 @@ static void resize(struct vo *vo) int flip_offset_ms = vo_fs ? vc->flip_offset_fs : vc->flip_offset_window; vo->flip_queue_offset = flip_offset_ms / 1000.; - int min_output_width = FFMAX(vo->dwidth, vc->vid_width); - int min_output_height = FFMAX(vo->dheight, vc->vid_height); - - if (vc->output_surface_width < min_output_width - || vc->output_surface_height < min_output_height) { - if (vc->output_surface_width < min_output_width) { + if (vc->output_surface_width < vo->dwidth + || vc->output_surface_height < vo->dheight) { + if (vc->output_surface_width < vo->dwidth) { vc->output_surface_width += vc->output_surface_width >> 1; vc->output_surface_width = FFMAX(vc->output_surface_width, - min_output_width); + vo->dwidth); } - if (vc->output_surface_height < min_output_height) { + if (vc->output_surface_height < vo->dheight) { vc->output_surface_height += vc->output_surface_height >> 1; vc->output_surface_height = FFMAX(vc->output_surface_height, - min_output_height); + vo->dheight); } // Creation of output_surfaces for (int i = 0; i < vc->num_output_surfaces; i++) @@ -716,6 +713,12 @@ static void free_video_specific(struct vo *vo) CHECK_ST_WARNING("Error when calling vdp_video_mixer_destroy"); } vc->video_mixer = VDP_INVALID_HANDLE; + + if (vc->screenshot_surface != VDP_INVALID_HANDLE) { + vdp_st = vdp->output_surface_destroy(vc->screenshot_surface); + CHECK_ST_WARNING("Error when calling vdp_output_surface_destroy"); + } + vc->screenshot_surface = VDP_INVALID_HANDLE; } static int create_vdp_decoder(struct vo *vo, int max_refs) @@ -811,6 +814,7 @@ static void mark_vdpau_objects_uninitialized(struct vo *vo) vc->flip_target = VDP_INVALID_HANDLE; for (int i = 0; i < MAX_OUTPUT_SURFACES; i++) vc->output_surfaces[i] = VDP_INVALID_HANDLE; + vc->screenshot_surface = VDP_INVALID_HANDLE; vc->vdp_device = VDP_INVALID_HANDLE; talloc_free(vc->osd_surface.packer); talloc_free(vc->eosd_surface.packer); @@ -1498,12 +1502,12 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts) // warning: the size and pixel format of surface must match that of the // surfaces in vc->output_surfaces static struct mp_image *read_output_surface(struct vdpctx *vc, - VdpOutputSurface surface) + VdpOutputSurface surface, + int width, int height) { VdpStatus vdp_st; struct vdp_functions *vdp = vc->vdp; - struct mp_image *image = alloc_mpi(vc->output_surface_width, - vc->output_surface_height, IMGFMT_BGR32); + struct mp_image *image = alloc_mpi(width, height, IMGFMT_BGR32); void *dst_planes[] = { image->planes[0] }; uint32_t dst_pitches[] = { image->stride[0] }; @@ -1517,14 +1521,22 @@ static struct mp_image *read_output_surface(struct vdpctx *vc, static struct mp_image *get_screenshot(struct vo *vo) { struct vdpctx *vc = vo->priv; + VdpStatus vdp_st; + struct vdp_functions *vdp = vc->vdp; - VdpOutputSurface screenshot_surface = - vc->output_surfaces[vc->num_output_surfaces]; + if (vc->screenshot_surface == VDP_INVALID_HANDLE) { + vdp_st = vdp->output_surface_create(vc->vdp_device, + OUTPUT_RGBA_FORMAT, + vc->vid_width, vc->vid_height, + &vc->screenshot_surface); + CHECK_ST_WARNING("Error when calling vdp_output_surface_create"); + } VdpRect rc = { .x1 = vc->vid_width, .y1 = vc->vid_height }; - render_video_to_output_surface(vo, screenshot_surface, &rc); + render_video_to_output_surface(vo, vc->screenshot_surface, &rc); - struct mp_image *image = read_output_surface(vc, screenshot_surface); + struct mp_image *image = read_output_surface(vc, vc->screenshot_surface, + vc->vid_width, vc->vid_height); image->width = vc->vid_width; image->height = vc->vid_height; @@ -1539,7 +1551,9 @@ static struct mp_image *get_window_screenshot(struct vo *vo) struct vdpctx *vc = vo->priv; int last_surface = WRAP_ADD(vc->surface_num, -1, vc->num_output_surfaces); VdpOutputSurface screen = vc->output_surfaces[last_surface]; - struct mp_image *image = read_output_surface(vo->priv, screen); + struct mp_image *image = read_output_surface(vo->priv, screen, + vc->output_surface_width, + vc->output_surface_height); image->width = image->w = vo->dwidth; image->height = image->h = vo->dheight; return image;