summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@mplayer2.org>2011-10-06 20:46:01 +0200
committerUoti Urpala <uau@mplayer2.org>2011-11-25 23:56:28 +0200
commit3215ec05fe27b1e07c863aadf4402c5bd6dbec33 (patch)
treec33277348acc0f63d433092151819bb8150b804f
parent28eaf11cf3b220871b97d9ba40d5058a84bcba09 (diff)
downloadmpv-3215ec05fe27b1e07c863aadf4402c5bd6dbec33.tar.bz2
mpv-3215ec05fe27b1e07c863aadf4402c5bd6dbec33.tar.xz
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.
-rw-r--r--libvo/vo_xv.c51
1 files changed, 51 insertions, 0 deletions
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;
}