From 3215ec05fe27b1e07c863aadf4402c5bd6dbec33 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 6 Oct 2011 20:46:01 +0200 Subject: vo_xv: implement screenshots Caveat: the OSD will be included in the screenshots when the screenshot is taken during normal playback. This doesn't happen when a screenshot is taken while playback is paused. Fixing this would introduce a small performance reduction during normal playback, which is unacceptable for a possibly rarely used optional feature. Due to the nature of the Xv API, taking a screenshot of the scaled video isn't possible either. --- libvo/vo_xv.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/libvo/vo_xv.c b/libvo/vo_xv.c index 3c8b040195..694dbc048a 100644 --- a/libvo/vo_xv.c +++ b/libvo/vo_xv.c @@ -98,6 +98,8 @@ struct xvctx { uint32_t image_width; uint32_t image_height; uint32_t image_format; + uint32_t image_d_width; + uint32_t image_d_height; int is_paused; struct vo_rect src_rect; struct vo_rect dst_rect; @@ -212,6 +214,8 @@ static int config(struct vo *vo, uint32_t width, uint32_t height, ctx->image_height = height; ctx->image_width = width; ctx->image_format = format; + ctx->image_d_width = d_width; + ctx->image_d_height = d_height; if ((ctx->max_width != 0 && ctx->max_height != 0) && (ctx->image_width > ctx->max_width @@ -521,6 +525,48 @@ static int draw_slice(struct vo *vo, uint8_t *image[], int stride[], int w, return 0; } +static mp_image_t *get_screenshot(struct vo *vo) { + struct xvctx *ctx = vo->priv; + + // try to get an image without OSD + if (ctx->have_visible_image_copy) + copy_backup_image(vo, ctx->visible_buf, ctx->num_buffers); + + XvImage *xv_image = ctx->xvimage[ctx->visible_buf]; + + int w = xv_image->width; + int h = xv_image->height; + + mp_image_t *image = alloc_mpi(w, h, ctx->image_format); + + int bytes = 1; + if (!(image->flags & MP_IMGFLAG_PLANAR) && (image->flags & MP_IMGFLAG_YUV)) + // packed YUV + bytes = image->bpp / 8; + + memcpy_pic(image->planes[0], xv_image->data + xv_image->offsets[0], + bytes * w, h, image->stride[0], xv_image->pitches[0]); + + if (image->flags & MP_IMGFLAG_PLANAR) { + int swap = ctx->image_format == IMGFMT_YV12; + int p1 = swap ? 2 : 1; + int p2 = swap ? 1 : 2; + + w /= 2; + h /= 2; + + memcpy_pic(image->planes[p1], xv_image->data + xv_image->offsets[1], + w, h, image->stride[p1], xv_image->pitches[1]); + memcpy_pic(image->planes[p2], xv_image->data + xv_image->offsets[2], + w, h, image->stride[p2], xv_image->pitches[2]); + } + + image->w = ctx->image_d_width; + image->h = ctx->image_d_height; + + return image; +} + static uint32_t draw_image(struct vo *vo, mp_image_t *mpi) { struct xvctx *ctx = vo->priv; @@ -829,6 +875,11 @@ static int control(struct vo *vo, uint32_t request, void *data) return VO_TRUE; case VOCTRL_REDRAW_OSD: return redraw_osd(vo, data); + case VOCTRL_SCREENSHOT: { + struct voctrl_screenshot_args *args = data; + args->out_image = get_screenshot(vo); + return true; + } } return VO_NOTIMPL; } -- cgit v1.2.3