summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/vaapi.c61
1 files changed, 61 insertions, 0 deletions
diff --git a/video/vaapi.c b/video/vaapi.c
index 1af1251b76..3db82d21fc 100644
--- a/video/vaapi.c
+++ b/video/vaapi.c
@@ -108,6 +108,44 @@ static void va_get_formats(struct mp_vaapi_ctx *ctx)
ctx->image_formats = formats;
}
+// VA message callbacks are global and do not have a context parameter, so it's
+// impossible to know from which VADisplay they originate. Try to route them
+// to existing mpv/libmpv instances within this process.
+static pthread_mutex_t va_log_mutex = PTHREAD_MUTEX_INITIALIZER;
+static struct mp_vaapi_ctx **va_mpv_clients;
+static int num_va_mpv_clients;
+
+static void va_message_callback(const char *msg, int mp_level)
+{
+ pthread_mutex_lock(&va_log_mutex);
+
+ if (num_va_mpv_clients) {
+ struct mp_log *dst = va_mpv_clients[num_va_mpv_clients - 1]->log;
+ mp_msg(dst, mp_level, "libva: %s", msg);
+ } else {
+ // We can't get or call the original libva handler (vaSet... return
+ // them, but it might be from some other lib etc.). So just do what
+ // libva happened to do at the time of this writing.
+ if (mp_level <= MSGL_ERR) {
+ fprintf(stderr, "libva error: %s", msg);
+ } else {
+ fprintf(stderr, "libva info: %s", msg);
+ }
+ }
+
+ pthread_mutex_unlock(&va_log_mutex);
+}
+
+static void va_error_callback(const char *msg)
+{
+ va_message_callback(msg, MSGL_ERR);
+}
+
+static void va_info_callback(const char *msg)
+{
+ va_message_callback(msg, MSGL_V);
+}
+
struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog,
bool probing)
{
@@ -123,6 +161,17 @@ struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog,
};
mpthread_mutex_init_recursive(&res->lock);
+ pthread_mutex_lock(&va_log_mutex);
+ MP_TARRAY_APPEND(NULL, va_mpv_clients, num_va_mpv_clients, res);
+ pthread_mutex_unlock(&va_log_mutex);
+
+ // Check some random symbol added after message callbacks.
+ // VA_MICRO_VERSION wasn't bumped at the time.
+#ifdef VA_FOURCC_I010
+ vaSetErrorCallback(va_error_callback);
+ vaSetInfoCallback(va_info_callback);
+#endif
+
int major_version, minor_version;
int status = vaInitialize(display, &major_version, &minor_version);
if (status != VA_STATUS_SUCCESS && probing)
@@ -149,6 +198,18 @@ void va_destroy(struct mp_vaapi_ctx *ctx)
if (ctx) {
if (ctx->display)
vaTerminate(ctx->display);
+
+ 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);
+
pthread_mutex_destroy(&ctx->lock);
talloc_free(ctx);
}