summaryrefslogtreecommitdiffstats
path: root/video
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-06-29 15:13:45 +0200
committerwm4 <wm4@nowhere>2015-06-29 15:13:45 +0200
commitef3d121c9e57ece01434e1de7e027e77eadbef80 (patch)
tree18ed17557ff28916d213caca6d3334e25a9a65f5 /video
parente0b1b88e8367f7d31ee4a4dcdc25c8d0676e6911 (diff)
downloadmpv-ef3d121c9e57ece01434e1de7e027e77eadbef80.tar.bz2
mpv-ef3d121c9e57ece01434e1de7e027e77eadbef80.tar.xz
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.)
Diffstat (limited to 'video')
-rw-r--r--video/vaapi.c15
1 files changed, 13 insertions, 2 deletions
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);