diff options
author | xylosper <darklin20@gmail.com> | 2013-09-20 22:55:13 +0900 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2013-09-25 13:53:42 +0200 |
commit | 39d1ab82e5a3ac30e5495c6b6773823c2ff56594 (patch) | |
tree | 03d5ab170fe12046bff32234e4e0b55d67457ce2 /video/decode | |
parent | 1ee8d0210d8ad613e462eab10a1a4139b62de367 (diff) | |
download | mpv-39d1ab82e5a3ac30e5495c6b6773823c2ff56594.tar.bz2 mpv-39d1ab82e5a3ac30e5495c6b6773823c2ff56594.tar.xz |
vaapi: add vf_vavpp and use it for deinterlacing
Merged from pull request #246 by xylosper. Minor cosmetic changes, some
adjustments (compatibility with older libva versions), and manpage
additions by wm4.
Signed-off-by: wm4 <wm4@nowhere>
Diffstat (limited to 'video/decode')
-rw-r--r-- | video/decode/vaapi.c | 65 |
1 files changed, 29 insertions, 36 deletions
diff --git a/video/decode/vaapi.c b/video/decode/vaapi.c index 9064389afe..8bec94d950 100644 --- a/video/decode/vaapi.c +++ b/video/decode/vaapi.c @@ -31,6 +31,7 @@ #include "video/fmt-conversion.h" #include "video/vaapi.h" #include "video/decode/dec_video.h" +#include "video/filter/vf.h" /* * The VAAPI decoder can work only with surfaces passed to the decoder at @@ -60,6 +61,9 @@ struct priv { int format, w, h; VASurfaceID surfaces[MAX_SURFACES]; + + struct va_surface_pool *pool; + int rt_format; }; struct profile_entry { @@ -159,36 +163,23 @@ static int is_direct_mapping(VADisplay display) return 0; } -// Make vo_vaapi.c pool the required number of surfaces. -// This is very touchy: vo_vaapi.c must not free surfaces while we decode, -// and we must allocate only surfaces that were passed to the decoder on -// creation. -// We achieve this by deleting all previous surfaces, then allocate every -// surface needed. Then we free these surfaces, and rely on the fact that -// vo_vaapi.c keeps the released surfaces in the pool, and only allocates -// new surfaces out of that pool. -static int preallocate_surfaces(struct lavc_ctx *ctx, int va_rt_format, int num) +// We must allocate only surfaces that were passed to the decoder on creation. +// We achieve this by reserving surfaces in the pool as needed. +// Releasing surfaces is necessary after filling the surface id list so +// that reserved surfaces can be reused for decoding. +static bool preallocate_surfaces(struct lavc_ctx *ctx, int num) { struct priv *p = ctx->hwdec_priv; - int res = -1; - - struct mp_image *tmp_surfaces[MAX_SURFACES] = {0}; - - p->ctx->flush(p->ctx); // free previously allocated surfaces - - for (int n = 0; n < num; n++) { - tmp_surfaces[n] = p->ctx->get_surface(p->ctx, va_rt_format, p->format, - p->w, p->h); - if (!tmp_surfaces[n]) - goto done; - p->surfaces[n] = (uintptr_t)tmp_surfaces[n]->planes[3]; + if (!va_surface_pool_reserve(p->pool, num, p->w, p->h)) { + mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Could not allocate surfaces.\n"); + return false; } - res = 0; - -done: - for (int n = 0; n < num; n++) - talloc_free(tmp_surfaces[n]); - return res; + for (int i = 0; i < num; i++) { + struct va_surface *s = va_surface_pool_get(p->pool, p->w, p->h); + p->surfaces[i] = s->id; + va_surface_release(s); + } + return true; } static void destroy_decoder(struct lavc_ctx *ctx) @@ -274,7 +265,7 @@ static int create_decoder(struct lavc_ctx *ctx) goto error; } - if (preallocate_surfaces(ctx, VA_RT_FORMAT_YUV420, num_surfaces) < 0) { + if (!preallocate_surfaces(ctx, num_surfaces)) { mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Could not allocate surfaces.\n"); goto error; } @@ -298,7 +289,7 @@ static int create_decoder(struct lavc_ctx *ctx) &attrib, 1); if (!check_va_status(status, "vaGetConfigAttributes()")) goto error; - if ((attrib.value & VA_RT_FORMAT_YUV420) == 0) { + if ((attrib.value & p->rt_format) == 0) { mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Chroma format not supported.\n"); goto error; } @@ -339,14 +330,13 @@ static struct mp_image *allocate_image(struct lavc_ctx *ctx, int format, return NULL; } - struct mp_image *img = p->ctx->get_surface(p->ctx, VA_RT_FORMAT_YUV420, - format, p->w, p->h); - if (img) { + struct va_surface *s = va_surface_pool_get(p->pool, p->w, p->h); + if (s) { for (int n = 0; n < MAX_SURFACES; n++) { - if (p->surfaces[n] == (uintptr_t)img->planes[3]) - return img; + if (p->surfaces[n] == s->id) + return va_surface_wrap(s); } - talloc_free(img); + va_surface_release(s); } mp_msg(MSGT_VO, MSGL_ERR, "[vaapi] Insufficient number of surfaces.\n"); return NULL; @@ -361,6 +351,7 @@ static void uninit(struct lavc_ctx *ctx) destroy_decoder(ctx); + va_surface_pool_release(p->pool); talloc_free(p); ctx->hwdec_priv = NULL; } @@ -371,16 +362,18 @@ static int init(struct lavc_ctx *ctx) *p = (struct priv) { .ctx = ctx->hwdec_info->vaapi_ctx, .va_context = &p->va_context_storage, + .rt_format = VA_RT_FORMAT_YUV420 }; - ctx->hwdec_priv = p; p->display = p->ctx->display; + p->pool = va_surface_pool_alloc(p->display, p->rt_format); p->va_context->display = p->display; p->va_context->config_id = VA_INVALID_ID; p->va_context->context_id = VA_INVALID_ID; ctx->avctx->hwaccel_context = p->va_context; + ctx->hwdec_priv = p; return 0; } |