From ef3d121c9e57ece01434e1de7e027e77eadbef80 Mon Sep 17 00:00:00 2001 From: wm4 Date: Mon, 29 Jun 2015 15:13:45 +0200 Subject: vaapi: treat cropped decoder output slightly more correctly Work around that FFmpeg doesn't distinguish between surface and cropped size. The decoder always aligns the surface size to something "convenient" (e.g. 16 for h264), and to get to the correct cropped size, the output image's width/height is reduced. Using the cropped size instead of the real surface size breaks the libva API in certain cases, so we simply store and use the original size in our per-surface struct. (If data is cropped on the left/top borders, hw decoding will simply display these - FFmpeg doesn't let us do better.) --- video/vaapi.c | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'video') diff --git a/video/vaapi.c b/video/vaapi.c index 7ba07b9a2c..d00d187eba 100644 --- a/video/vaapi.c +++ b/video/vaapi.c @@ -185,6 +185,11 @@ struct va_surface { VASurfaceID id; int rt_format; + // The actually allocated surface size (needed for cropping). + // mp_images can have a smaller size than this, which means they are + // cropped down to a smaller size by removing right/bottom pixels. + int w, h; + VAImage image; // used for software decoding case }; @@ -239,6 +244,8 @@ static struct mp_image *alloc_surface(struct mp_vaapi_ctx *ctx, int rt_format, .ctx = ctx, .id = id, .rt_format = rt_format, + .w = w, + .h = h, .display = ctx->display, .image = { .image_id = VA_INVALID_ID, .buf = VA_INVALID_ID }, }; @@ -274,7 +281,7 @@ static int va_surface_image_alloc(struct mp_image *img, VAImageFormat *format) va_surface_image_destroy(p); - VAStatus status = vaCreateImage(p->display, format, img->w, img->h, &p->image); + VAStatus status = vaCreateImage(p->display, format, p->w, p->h, &p->image); if (!CHECK_VA_STATUS(p->ctx, "vaCreateImage()")) { p->image.image_id = VA_INVALID_ID; r = -1; @@ -355,6 +362,8 @@ int va_surface_upload(struct mp_image *va_dst, struct mp_image *sw_src) struct mp_image img; if (!va_image_map(p->ctx, &p->image, &img)) return -1; + assert(sw_src->w <= img.w && sw_src->h <= img.h); + mp_image_set_size(&img, sw_src->w, sw_src->h); // copy only visible part mp_image_copy(&img, sw_src); va_image_unmap(p->ctx, &p->image); @@ -386,7 +395,7 @@ static struct mp_image *try_download(struct mp_image *src, va_lock(p->ctx); status = vaGetImage(p->display, p->id, 0, 0, - src->w, src->h, image->image_id); + p->w, p->h, image->image_id); va_unlock(p->ctx); if (status != VA_STATUS_SUCCESS) return NULL; @@ -394,6 +403,8 @@ static struct mp_image *try_download(struct mp_image *src, struct mp_image *dst = NULL; struct mp_image tmp; if (va_image_map(p->ctx, image, &tmp)) { + assert(src->w <= tmp.w && src->h <= tmp.h); + mp_image_set_size(&tmp, src->w, src->h); // copy only visible part dst = mp_image_pool_get(pool, tmp.imgfmt, tmp.w, tmp.h); if (dst) { mp_image_copy(dst, &tmp); -- cgit v1.2.3