vo_vdpau: fix screenshots

Attempting to take screenshots printed vdpau errors on the terminal,
and the resulting screenshots were filled with black.

The problem was that that the screenshot code tried to use an
unallocated output surface (the one at vc->output_surfaces[vc->num_output_surfaces]).
This used to refer to the last allocated surface, until this was
changed by a recently merged commit. That commit also added a separate
screenshot surface. The merge somehow went wrong, and that part was not
integrated.

<uau> wm4: you used an earlier buggy version of a commit

OK...
This commit is contained in:
wm4 2012-10-21 00:48:01 +02:00
parent 32053a0e10
commit 8bbce10c77
1 changed files with 32 additions and 18 deletions

View File

@ -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;