summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--libvo/vo_vdpau.c50
1 files changed, 32 insertions, 18 deletions
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;