diff options
Diffstat (limited to 'video/decode')
-rw-r--r-- | video/decode/lavc.h | 7 | ||||
-rw-r--r-- | video/decode/vaapi.c | 34 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 22 | ||||
-rw-r--r-- | video/decode/vdpau.c | 25 |
4 files changed, 42 insertions, 46 deletions
diff --git a/video/decode/lavc.h b/video/decode/lavc.h index 867488de95..71d568aa8a 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h @@ -38,6 +38,10 @@ typedef struct lavc_ctx { // For free use by hwdec implementation void *hwdec_priv; + int hwdec_fmt; + int hwdec_w; + int hwdec_h; + // Legacy bool do_dr1; struct FramePool *dr1_buffer_pool; @@ -59,7 +63,10 @@ struct vd_lavc_hwdec { int (*probe)(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, const char *decoder); int (*init)(struct lavc_ctx *ctx); + int (*init_decoder)(struct lavc_ctx *ctx, int fmt, int w, int h); void (*uninit)(struct lavc_ctx *ctx); + // Note: if init_decoder is set, this will always use the values from the + // last successful init_decoder call. Otherwise, it's up to you. struct mp_image *(*allocate_image)(struct lavc_ctx *ctx, int fmt, int w, int h); // Process the image returned by the libavcodec decoder. diff --git a/video/decode/vaapi.c b/video/decode/vaapi.c index d4b1c41840..bdddfcc7ef 100644 --- a/video/decode/vaapi.c +++ b/video/decode/vaapi.c @@ -64,7 +64,6 @@ struct priv { struct vaapi_context *va_context; struct vaapi_context va_context_storage; - int format, w, h; VASurfaceID surfaces[MAX_SURFACES]; struct va_surface_pool *pool; @@ -163,15 +162,15 @@ static int is_direct_mapping(VADisplay display) // 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) +static bool preallocate_surfaces(struct lavc_ctx *ctx, int num, int w, int h) { struct priv *p = ctx->hwdec_priv; - if (!va_surface_pool_reserve(p->pool, num, p->w, p->h)) { + if (!va_surface_pool_reserve(p->pool, num, w, h)) { MP_ERR(p, "Could not allocate surfaces.\n"); return false; } for (int i = 0; i < num; i++) { - struct va_surface *s = va_surface_pool_get(p->pool, p->w, p->h); + struct va_surface *s = va_surface_pool_get(p->pool, w, h); p->surfaces[i] = s->id; va_surface_release(s); } @@ -205,7 +204,7 @@ static bool has_profile(VAProfile *va_profiles, int num_profiles, VAProfile p) return false; } -static int create_decoder(struct lavc_ctx *ctx) +static int init_decoder(struct lavc_ctx *ctx, int fmt, int w, int h) { void *tmp = talloc_new(NULL); @@ -213,8 +212,6 @@ static int create_decoder(struct lavc_ctx *ctx) VAStatus status; int res = -1; - assert(p->format == IMGFMT_VAAPI); - destroy_decoder(ctx); const struct hwdec_profile_entry *pe = hwdec_find_profile(ctx, profiles); @@ -254,7 +251,7 @@ static int create_decoder(struct lavc_ctx *ctx) goto error; } - if (!preallocate_surfaces(ctx, num_surfaces)) { + if (!preallocate_surfaces(ctx, num_surfaces, w, h)) { MP_ERR(p, "Could not allocate surfaces.\n"); goto error; } @@ -265,7 +262,7 @@ static int create_decoder(struct lavc_ctx *ctx) if (!CHECK_VA_STATUS(p, "vaQueryConfigEntrypoints()")) goto error; - int entrypoint = find_entrypoint(p->format, ep, num_ep); + int entrypoint = find_entrypoint(IMGFMT_VAAPI, ep, num_ep); if (entrypoint < 0) { MP_ERR(p, "Could not find VA entrypoint.\n"); goto error; @@ -289,7 +286,7 @@ static int create_decoder(struct lavc_ctx *ctx) goto error; status = vaCreateContext(p->display, p->va_context->config_id, - p->w, p->h, VA_PROGRESSIVE, + w, h, VA_PROGRESSIVE, p->surfaces, num_surfaces, &p->va_context->context_id); if (!CHECK_VA_STATUS(p, "vaCreateContext()")) @@ -306,20 +303,7 @@ static struct mp_image *allocate_image(struct lavc_ctx *ctx, int format, { struct priv *p = ctx->hwdec_priv; - if (format != IMGFMT_VAAPI) - return NULL; - - if (format != p->format || w != p->w || h != p->h || - p->va_context->context_id == VA_INVALID_ID) - { - p->format = format; - p->w = w; - p->h = h; - if (create_decoder(ctx) < 0) - return NULL; - } - - struct va_surface *s = va_surface_pool_get(p->pool, p->w, p->h); + struct va_surface *s = va_surface_pool_get(p->pool, w, h); if (s) { for (int n = 0; n < MAX_SURFACES; n++) { if (p->surfaces[n] == s->id) @@ -471,6 +455,7 @@ const struct vd_lavc_hwdec mp_vd_lavc_vaapi = { .probe = probe, .init = init, .uninit = uninit, + .init_decoder = init_decoder, .allocate_image = allocate_image, }; @@ -480,6 +465,7 @@ const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = { .probe = probe_copy, .init = init_copy, .uninit = uninit, + .init_decoder = init_decoder, .allocate_image = allocate_image, .process_image = copy_image, }; diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index df0c098155..eed79e81b1 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -339,6 +339,7 @@ static void init_avctx(struct dec_video *vd, const char *decoder, ctx->do_dr1 = ctx->do_hw_dr1 = 0; ctx->pix_fmt = AV_PIX_FMT_NONE; ctx->hwdec = hwdec; + ctx->hwdec_fmt = 0; ctx->avctx = avcodec_alloc_context3(lavc_codec); AVCodecContext *avctx = ctx->avctx; avctx->opaque = vd; @@ -511,8 +512,20 @@ static enum AVPixelFormat get_format_hwdec(struct AVCodecContext *avctx, for (int i = 0; fmt[i] != AV_PIX_FMT_NONE; i++) { const int *okfmt = ctx->hwdec->image_formats; for (int n = 0; okfmt && okfmt[n]; n++) { - if (imgfmt2pixfmt(okfmt[n]) == fmt[i]) + if (imgfmt2pixfmt(okfmt[n]) == fmt[i]) { + ctx->hwdec_w = avctx->width; + ctx->hwdec_h = avctx->height; + ctx->hwdec_fmt = okfmt[n]; + if (ctx->hwdec->init_decoder) { + if (ctx->hwdec->init_decoder(ctx, ctx->hwdec_fmt, + ctx->hwdec_w, ctx->hwdec_h) < 0) + { + ctx->hwdec_fmt = 0; + break; + } + } return fmt[i]; + } } } @@ -535,7 +548,7 @@ static struct mp_image *get_surface_hwdec(struct dec_video *vd, AVFrame *pic) * get_buffer callback. */ int imgfmt = pixfmt2imgfmt(pic->format); - if (!IMGFMT_IS_HWACCEL(imgfmt)) + if (!IMGFMT_IS_HWACCEL(imgfmt) || !ctx->hwdec) return NULL; // Using frame->width/height is bad. For non-mod 16 video (which would @@ -545,6 +558,11 @@ static struct mp_image *get_surface_hwdec(struct dec_video *vd, AVFrame *pic) int w = ctx->avctx->width; int h = ctx->avctx->height; + if (ctx->hwdec->init_decoder) { + if (imgfmt != ctx->hwdec_fmt && w != ctx->hwdec_w && h != ctx->hwdec_h) + return NULL; + } + struct mp_image *mpi = ctx->hwdec->allocate_image(ctx, imgfmt, w, h); if (mpi) { diff --git a/video/decode/vdpau.c b/video/decode/vdpau.c index 6c0c891ad4..995b5460e8 100644 --- a/video/decode/vdpau.c +++ b/video/decode/vdpau.c @@ -37,9 +37,6 @@ struct priv { uint64_t preemption_counter; AVVDPAUContext context; - - int vid_width; - int vid_height; }; struct profile_entry { @@ -97,7 +94,7 @@ static int handle_preemption(struct lavc_ctx *ctx) return 0; } -static bool create_vdp_decoder(struct lavc_ctx *ctx) +static int init_decoder(struct lavc_ctx *ctx, int fmt, int w, int h) { struct priv *p = ctx->hwdec_priv; struct vdp_functions *vdp = p->mpvdp->vdp; @@ -125,17 +122,16 @@ static bool create_vdp_decoder(struct lavc_ctx *ctx) MP_ERR(p, "Codec or profile not supported by hardware.\n"); goto fail; } - if (p->vid_width > maxw || p->vid_height > maxh) { + if (w > maxw || h > maxh) { MP_ERR(p, "Video resolution(%dx%d) is larger than the maximum size(%dx%d) supported.\n", - p->vid_width, p->vid_height, maxw, maxh); + w, h, maxw, maxh); goto fail; } int maxrefs = hwdec_get_max_refs(ctx); vdp_st = vdp->decoder_create(p->vdp_device, pe->hw_profile, - p->vid_width, p->vid_height, maxrefs, - &p->context.decoder); + w, h, maxrefs, &p->context.decoder); CHECK_VDP_WARNING(p, "Failed creating VDPAU decoder"); if (vdp_st != VDP_STATUS_OK) goto fail; @@ -151,20 +147,8 @@ static struct mp_image *allocate_image(struct lavc_ctx *ctx, int fmt, { struct priv *p = ctx->hwdec_priv; - if (fmt != IMGFMT_VDPAU) - return NULL; - handle_preemption(ctx); - if (w != p->vid_width || h != p->vid_height || - p->context.decoder == VDP_INVALID_HANDLE) - { - p->vid_width = w; - p->vid_height = h; - if (!create_vdp_decoder(ctx)) - return NULL; - } - VdpChromaType chroma; mp_vdpau_get_format(IMGFMT_VDPAU, &chroma, NULL); @@ -226,5 +210,6 @@ const struct vd_lavc_hwdec mp_vd_lavc_vdpau = { .probe = probe, .init = init, .uninit = uninit, + .init_decoder = init_decoder, .allocate_image = allocate_image, }; |