mirror of
https://github.com/mpv-player/mpv
synced 2025-02-09 08:27:18 +00:00
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.
This commit is contained in:
parent
28eaf11cf3
commit
3215ec05fe
@ -98,6 +98,8 @@ struct xvctx {
|
|||||||
uint32_t image_width;
|
uint32_t image_width;
|
||||||
uint32_t image_height;
|
uint32_t image_height;
|
||||||
uint32_t image_format;
|
uint32_t image_format;
|
||||||
|
uint32_t image_d_width;
|
||||||
|
uint32_t image_d_height;
|
||||||
int is_paused;
|
int is_paused;
|
||||||
struct vo_rect src_rect;
|
struct vo_rect src_rect;
|
||||||
struct vo_rect dst_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_height = height;
|
||||||
ctx->image_width = width;
|
ctx->image_width = width;
|
||||||
ctx->image_format = format;
|
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)
|
if ((ctx->max_width != 0 && ctx->max_height != 0)
|
||||||
&& (ctx->image_width > ctx->max_width
|
&& (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;
|
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)
|
static uint32_t draw_image(struct vo *vo, mp_image_t *mpi)
|
||||||
{
|
{
|
||||||
struct xvctx *ctx = vo->priv;
|
struct xvctx *ctx = vo->priv;
|
||||||
@ -829,6 +875,11 @@ static int control(struct vo *vo, uint32_t request, void *data)
|
|||||||
return VO_TRUE;
|
return VO_TRUE;
|
||||||
case VOCTRL_REDRAW_OSD:
|
case VOCTRL_REDRAW_OSD:
|
||||||
return redraw_osd(vo, data);
|
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;
|
return VO_NOTIMPL;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user