0
0
mirror of https://github.com/mpv-player/mpv.git synced 2024-09-20 03:52:22 +02:00

vo_vdpau: implement screenshots

This commit is contained in:
wm4 2011-10-06 20:46:01 +02:00 committed by Uoti Urpala
parent a661bd8f0d
commit 0440460d0c
3 changed files with 91 additions and 11 deletions

View File

@ -16,6 +16,7 @@ device_destroy
generate_csc_matrix GenerateCSCMatrix # CSC completely capitalized
output_surface_create
output_surface_destroy
output_surface_get_bits_native
output_surface_put_bits_indexed
output_surface_put_bits_native
output_surface_render_bitmap_surface

View File

@ -18,6 +18,7 @@ VDP_FUNCTION(VdpDeviceDestroy, VDP_FUNC_ID_DEVICE_DESTROY, device_destroy)
VDP_FUNCTION(VdpGenerateCSCMatrix, VDP_FUNC_ID_GENERATE_CSC_MATRIX, generate_csc_matrix)
VDP_FUNCTION(VdpOutputSurfaceCreate, VDP_FUNC_ID_OUTPUT_SURFACE_CREATE, output_surface_create)
VDP_FUNCTION(VdpOutputSurfaceDestroy, VDP_FUNC_ID_OUTPUT_SURFACE_DESTROY, output_surface_destroy)
VDP_FUNCTION(VdpOutputSurfaceGetBitsNative, VDP_FUNC_ID_OUTPUT_SURFACE_GET_BITS_NATIVE, output_surface_get_bits_native)
VDP_FUNCTION(VdpOutputSurfacePutBitsIndexed, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_INDEXED, output_surface_put_bits_indexed)
VDP_FUNCTION(VdpOutputSurfacePutBitsNative, VDP_FUNC_ID_OUTPUT_SURFACE_PUT_BITS_NATIVE, output_surface_put_bits_native)
VDP_FUNCTION(VdpOutputSurfaceRenderBitmapSurface, VDP_FUNC_ID_OUTPUT_SURFACE_RENDER_BITMAP_SURFACE, output_surface_render_bitmap_surface)

View File

@ -88,6 +88,9 @@
/* Initial size of EOSD surface in pixels (x*x) */
#define EOSD_SURFACE_INITIAL_SIZE 256
/* Pixelformat used for output surfaces */
#define OUTPUT_RGBA_FORMAT VDP_RGBA_FORMAT_B8G8R8A8
/*
* Global variable declaration - VDPAU specific
*/
@ -113,7 +116,7 @@ struct vdpctx {
uint64_t last_vdp_time;
unsigned int last_sync_update;
/* an extra last output surface is misused for OSD. */
/* an extra last output surface is used for OSD and screenshots */
VdpOutputSurface output_surfaces[MAX_OUTPUT_SURFACES + 1];
int num_output_surfaces;
struct buffered_video_surface {
@ -158,6 +161,7 @@ struct vdpctx {
bool dropped_frame;
uint64_t dropped_time;
uint32_t vid_width, vid_height;
uint32_t vid_d_width, vid_d_height;
uint32_t image_format;
VdpChromaType vdp_chroma_type;
VdpYCbCrFormat vdp_pixel_format;
@ -242,7 +246,9 @@ static uint64_t convert_to_vdptime(struct vo *vo, unsigned int t)
static void flip_page_timed(struct vo *vo, unsigned int pts_us, int duration);
static int video_to_output_surface(struct vo *vo)
static int render_video_to_output_surface(struct vo *vo,
VdpOutputSurface output_surface,
VdpRect *output_rect)
{
struct vdpctx *vc = vo->priv;
struct vdp_functions *vdp = vc->vdp;
@ -265,7 +271,6 @@ static int video_to_output_surface(struct vo *vo)
bv[(dp+1)/2].surface, bv[(dp+2)/2].surface};
const VdpVideoSurface *future_fields = (const VdpVideoSurface []){
dp >= 1 ? bv[(dp-1)/2].surface : VDP_INVALID_HANDLE};
VdpOutputSurface output_surface = vc->output_surfaces[vc->surface_num];
vdp_st = vdp->presentation_queue_block_until_surface_idle(vc->flip_queue,
output_surface,
&dummy);
@ -276,11 +281,20 @@ static int video_to_output_surface(struct vo *vo)
0, field, 2, past_fields,
bv[dp/2].surface, 1, future_fields,
&vc->src_rect_vid, output_surface,
NULL, &vc->out_rect_vid, 0, NULL);
NULL, output_rect, 0, NULL);
CHECK_ST_WARNING("Error when calling vdp_video_mixer_render");
return 0;
}
static int video_to_output_surface(struct vo *vo)
{
struct vdpctx *vc = vo->priv;
return render_video_to_output_surface(vo,
vc->output_surfaces[vc->surface_num],
&vc->out_rect_vid);
}
static void get_buffered_frame(struct vo *vo, bool eof)
{
struct vdpctx *vc = vo->priv;
@ -393,18 +407,21 @@ 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);
bool had_frames = vc->num_shown_frames;
if (vc->output_surface_width < vo->dwidth
|| vc->output_surface_height < vo->dheight) {
if (vc->output_surface_width < vo->dwidth) {
if (vc->output_surface_width < min_output_width
|| vc->output_surface_height < min_output_height) {
if (vc->output_surface_width < min_output_width) {
vc->output_surface_width += vc->output_surface_width >> 1;
vc->output_surface_width = FFMAX(vc->output_surface_width,
vo->dwidth);
min_output_width);
}
if (vc->output_surface_height < vo->dheight) {
if (vc->output_surface_height < min_output_height) {
vc->output_surface_height += vc->output_surface_height >> 1;
vc->output_surface_height = FFMAX(vc->output_surface_height,
vo->dheight);
min_output_height);
}
// Creation of output_surfaces
for (i = 0; i <= vc->num_output_surfaces; i++) {
@ -414,7 +431,7 @@ static void resize(struct vo *vo)
"vdp_output_surface_destroy");
}
vdp_st = vdp->output_surface_create(vc->vdp_device,
VDP_RGBA_FORMAT_B8G8R8A8,
OUTPUT_RGBA_FORMAT,
vc->output_surface_width,
vc->output_surface_height,
&vc->output_surfaces[i]);
@ -868,6 +885,9 @@ static int config(struct vo *vo, uint32_t width, uint32_t height,
vc->image_format = format;
vc->vid_width = width;
vc->vid_height = height;
vc->vid_d_width = d_width;
vc->vid_d_height = d_height;
free_video_specific(vo);
if (IMGFMT_IS_VDPAU(vc->image_format) && !create_vdp_decoder(vo, 2))
return -1;
@ -1475,6 +1495,56 @@ static void draw_image(struct vo *vo, mp_image_t *mpi, double pts)
return;
}
// 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)
{
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);
void *dst_planes[] = { image->planes[0] };
uint32_t dst_pitches[] = { image->stride[0] };
vdp_st = vdp->output_surface_get_bits_native(surface, NULL, dst_planes,
dst_pitches);
CHECK_ST_WARNING("Error when calling vdp_output_surface_get_bits_native");
return image;
}
static struct mp_image *get_screenshot(struct vo *vo)
{
struct vdpctx *vc = vo->priv;
VdpOutputSurface screenshot_surface =
vc->output_surfaces[vc->num_output_surfaces];
VdpRect rc = { .x1 = vc->vid_width, .y1 = vc->vid_height };
render_video_to_output_surface(vo, screenshot_surface, &rc);
struct mp_image *image = read_output_surface(vc, screenshot_surface);
image->width = vc->vid_width;
image->height = vc->vid_height;
image->w = vc->vid_d_width;
image->h = vc->vid_d_height;
return image;
}
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);
image->width = image->w = vo->dwidth;
image->height = image->h = vo->dheight;
return image;
}
static uint32_t get_image(struct vo *vo, mp_image_t *mpi)
{
struct vdpctx *vc = vo->priv;
@ -1797,6 +1867,14 @@ static int control(struct vo *vo, uint32_t request, void *data)
case VOCTRL_RESET:
forget_frames(vo);
return true;
case VOCTRL_SCREENSHOT: {
struct voctrl_screenshot_args *args = data;
if (args->full_window)
args->out_image = get_window_screenshot(vo);
else
args->out_image = get_screenshot(vo);
return true;
}
}
return VO_NOTIMPL;
}