summaryrefslogtreecommitdiffstats
path: root/video/vaapi.c
diff options
context:
space:
mode:
Diffstat (limited to 'video/vaapi.c')
-rw-r--r--video/vaapi.c95
1 files changed, 49 insertions, 46 deletions
diff --git a/video/vaapi.c b/video/vaapi.c
index 3b1cb9cc41..a6607b4aeb 100644
--- a/video/vaapi.c
+++ b/video/vaapi.c
@@ -97,36 +97,57 @@ static void va_info_callback(const char *msg)
}
#endif
-static void open_lavu_vaapi_device(struct mp_vaapi_ctx *ctx)
+static void free_device_ref(struct AVHWDeviceContext *hwctx)
{
- ctx->av_device_ref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
- if (!ctx->av_device_ref)
- return;
+ struct mp_vaapi_ctx *ctx = hwctx->user_opaque;
- AVHWDeviceContext *hwctx = (void *)ctx->av_device_ref->data;
- AVVAAPIDeviceContext *vactx = hwctx->hwctx;
+ if (ctx->display)
+ vaTerminate(ctx->display);
- vactx->display = ctx->display;
+ if (ctx->destroy_native_ctx)
+ ctx->destroy_native_ctx(ctx->native_ctx);
- if (av_hwdevice_ctx_init(ctx->av_device_ref) < 0)
- av_buffer_unref(&ctx->av_device_ref);
+#if !VA_CHECK_VERSION(1, 0, 0)
+ pthread_mutex_lock(&va_log_mutex);
+ for (int n = 0; n < num_va_mpv_clients; n++) {
+ if (va_mpv_clients[n] == ctx) {
+ MP_TARRAY_REMOVE_AT(va_mpv_clients, num_va_mpv_clients, n);
+ break;
+ }
+ }
+ if (num_va_mpv_clients == 0)
+ TA_FREEP(&va_mpv_clients); // avoid triggering leak detectors
+ pthread_mutex_unlock(&va_log_mutex);
+#endif
- ctx->hwctx.av_device_ref = ctx->av_device_ref;
+ talloc_free(ctx);
}
struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog,
bool probing)
{
+ AVBufferRef *avref = av_hwdevice_ctx_alloc(AV_HWDEVICE_TYPE_VAAPI);
+ if (!avref)
+ return NULL;
+
+ AVHWDeviceContext *hwctx = (void *)avref->data;
+ AVVAAPIDeviceContext *vactx = hwctx->hwctx;
+
struct mp_vaapi_ctx *res = talloc_ptrtype(NULL, res);
*res = (struct mp_vaapi_ctx) {
.log = mp_log_new(res, plog, "/vaapi"),
.display = display,
+ .av_device_ref = avref,
.hwctx = {
.type = HWDEC_VAAPI,
.ctx = res,
+ .av_device_ref = avref,
},
};
+ hwctx->free = free_device_ref;
+ hwctx->user_opaque = res;
+
#if VA_CHECK_VERSION(1, 0, 0)
vaSetErrorCallback(display, va_error_callback, res);
vaSetInfoCallback(display, va_info_callback, res);
@@ -152,9 +173,10 @@ struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog,
}
MP_VERBOSE(res, "Initialized VAAPI: version %d.%d\n", major, minor);
- // For now, some code will still work even if libavutil fails on old crap
- // libva drivers (such as the vdpau wraper). So don't error out on failure.
- open_lavu_vaapi_device(res);
+ vactx->display = res->display;
+
+ if (av_hwdevice_ctx_init(res->av_device_ref) < 0)
+ goto error;
res->hwctx.emulated = va_guess_if_emulated(res);
@@ -169,30 +191,11 @@ error:
// Undo va_initialize, and close the VADisplay.
void va_destroy(struct mp_vaapi_ctx *ctx)
{
- if (ctx) {
- av_buffer_unref(&ctx->av_device_ref);
-
- if (ctx->display)
- vaTerminate(ctx->display);
-
- if (ctx->destroy_native_ctx)
- ctx->destroy_native_ctx(ctx->native_ctx);
-
-#if !VA_CHECK_VERSION(1, 0, 0)
- pthread_mutex_lock(&va_log_mutex);
- for (int n = 0; n < num_va_mpv_clients; n++) {
- if (va_mpv_clients[n] == ctx) {
- MP_TARRAY_REMOVE_AT(va_mpv_clients, num_va_mpv_clients, n);
- break;
- }
- }
- if (num_va_mpv_clients == 0)
- TA_FREEP(&va_mpv_clients); // avoid triggering leak detectors
- pthread_mutex_unlock(&va_log_mutex);
-#endif
+ if (!ctx)
+ return;
- talloc_free(ctx);
- }
+ AVBufferRef *ref = ctx->av_device_ref;
+ av_buffer_unref(&ref); // frees ctx as well
}
VASurfaceID va_surface_id(struct mp_image *mpi)
@@ -298,20 +301,16 @@ static const struct va_native_display *const native_displays[] = {
NULL
};
-static void va_destroy_ctx(struct mp_hwdec_ctx *ctx)
-{
- va_destroy(ctx->ctx);
-}
-
-struct mp_hwdec_ctx *va_create_standalone(struct mpv_global *global,
- struct mp_log *plog, bool probing)
+static struct AVBufferRef *va_create_standalone(struct mpv_global *global,
+ struct mp_log *log, struct hwcontext_create_dev_params *params)
{
for (int n = 0; native_displays[n]; n++) {
VADisplay *display = NULL;
void *native_ctx = NULL;
native_displays[n]->create(&display, &native_ctx);
if (display) {
- struct mp_vaapi_ctx *ctx = va_initialize(display, plog, probing);
+ struct mp_vaapi_ctx *ctx =
+ va_initialize(display, log, params->probing);
if (!ctx) {
vaTerminate(display);
native_displays[n]->destroy(native_ctx);
@@ -319,9 +318,13 @@ struct mp_hwdec_ctx *va_create_standalone(struct mpv_global *global,
}
ctx->native_ctx = native_ctx;
ctx->destroy_native_ctx = native_displays[n]->destroy;
- ctx->hwctx.destroy = va_destroy_ctx;
- return &ctx->hwctx;
+ return ctx->hwctx.av_device_ref;
}
}
return NULL;
}
+
+const struct hwcontext_fns hwcontext_fns_vaapi = {
+ .av_hwdevice_type = AV_HWDEVICE_TYPE_VAAPI,
+ .create_dev = va_create_standalone,
+};