summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2012-10-21 00:48:01 +0200
committerwm4 <wm4@nowhere>2012-10-21 20:55:02 +0200
commit8bbce10c776f59aff6f21b80f5feee7d1a6d7ea7 (patch)
tree07a8249212269a1624c3ab66abb6b76fe182d018
parent32053a0e10be40800c2b7aee569fd30a3742d156 (diff)
downloadmpv-8bbce10c776f59aff6f21b80f5feee7d1a6d7ea7.tar.bz2
mpv-8bbce10c776f59aff6f21b80f5feee7d1a6d7ea7.tar.xz
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...
-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;