diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index 5e9b30d453..aac9f81839 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -458,6 +458,17 @@ static void select_and_set_hwdec(struct dec_video *vd) MP_VERBOSE(vd, "Could not create device.\n"); continue; } + + const struct hwcontext_fns *fns = + hwdec_get_hwcontext_fns(hwdec->lavc_device); + if (fns && fns->is_emulated && fns->is_emulated(ctx->hwdec_dev)) { + if (hwdec_auto) { + MP_VERBOSE(vd, "Not using emulated API.\n"); + av_buffer_unref(&ctx->hwdec_dev); + continue; + } + MP_WARN(vd, "Using emulated hardware decoding API.\n"); + } } ctx->use_hwdec = true; diff --git a/video/hwdec.h b/video/hwdec.h index 34dd52e08b..2c0f19b606 100644 --- a/video/hwdec.h +++ b/video/hwdec.h @@ -119,6 +119,8 @@ struct hwcontext_fns { struct AVBufferRef *(*create_dev)(struct mpv_global *global, struct mp_log *log, struct hwcontext_create_dev_params *params); + // Return whether this is using some sort of sub-optimal emulation layer. + bool (*is_emulated)(struct AVBufferRef *hw_device_ctx); }; // The parameter is of type enum AVHWDeviceType (as in int to avoid extensive diff --git a/video/vaapi.c b/video/vaapi.c index a6607b4aeb..00052cec39 100644 --- a/video/vaapi.c +++ b/video/vaapi.c @@ -204,10 +204,19 @@ VASurfaceID va_surface_id(struct mp_image *mpi) (VASurfaceID)(uintptr_t)mpi->planes[3] : VA_INVALID_ID; } +static bool is_emulated(struct AVBufferRef *hw_device_ctx) +{ + AVHWDeviceContext *hwctx = (void *)hw_device_ctx->data; + AVVAAPIDeviceContext *vactx = hwctx->hwctx; + + const char *s = vaQueryVendorString(vactx->display); + return s && strstr(s, "VDPAU backend"); +} + + bool va_guess_if_emulated(struct mp_vaapi_ctx *ctx) { - const char *s = vaQueryVendorString(ctx->display); - return s && strstr(s, "VDPAU backend"); + return is_emulated(ctx->av_device_ref); } struct va_native_display { @@ -327,4 +336,5 @@ static struct AVBufferRef *va_create_standalone(struct mpv_global *global, const struct hwcontext_fns hwcontext_fns_vaapi = { .av_hwdevice_type = AV_HWDEVICE_TYPE_VAAPI, .create_dev = va_create_standalone, + .is_emulated = is_emulated, }; diff --git a/video/vdpau.c b/video/vdpau.c index 1785702fdb..d751849ec3 100644 --- a/video/vdpau.c +++ b/video/vdpau.c @@ -537,6 +537,26 @@ bool mp_vdpau_guess_if_emulated(struct mp_vdpau_ctx *ctx) return vdp_st == VDP_STATUS_OK && info && strstr(info, "VAAPI"); } +// (This clearly works only for contexts wrapped by our code.) +struct mp_vdpau_ctx *mp_vdpau_get_ctx_from_av(AVBufferRef *hw_device_ctx) +{ + AVHWDeviceContext *hwctx = (void *)hw_device_ctx->data; + + if (hwctx->free != free_device_ref) + return NULL; // not ours + + return hwctx->user_opaque; +} + +static bool is_emulated(struct AVBufferRef *hw_device_ctx) +{ + struct mp_vdpau_ctx *ctx = mp_vdpau_get_ctx_from_av(hw_device_ctx); + if (!ctx) + return false; + + return mp_vdpau_guess_if_emulated(ctx); +} + static struct AVBufferRef *vdpau_create_standalone(struct mpv_global *global, struct mp_log *log, struct hwcontext_create_dev_params *params) { @@ -555,11 +575,11 @@ static struct AVBufferRef *vdpau_create_standalone(struct mpv_global *global, vdp->hwctx.emulated = mp_vdpau_guess_if_emulated(vdp); vdp->close_display = true; - mp_warn(log, "idk\n"); return vdp->hwctx.av_device_ref; } const struct hwcontext_fns hwcontext_fns_vdpau = { .av_hwdevice_type = AV_HWDEVICE_TYPE_VDPAU, .create_dev = vdpau_create_standalone, + .is_emulated = is_emulated, }; diff --git a/video/vdpau.h b/video/vdpau.h index 118db8cbfe..b0f402c3f2 100644 --- a/video/vdpau.h +++ b/video/vdpau.h @@ -103,6 +103,8 @@ bool mp_vdpau_get_rgb_format(int imgfmt, VdpRGBAFormat *out_rgba_format); struct mp_image *mp_vdpau_upload_video_surface(struct mp_vdpau_ctx *ctx, struct mp_image *mpi); +struct mp_vdpau_ctx *mp_vdpau_get_ctx_from_av(struct AVBufferRef *hw_device_ctx); + bool mp_vdpau_guess_if_emulated(struct mp_vdpau_ctx *ctx); #endif