summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--video/decode/lavc.h3
-rw-r--r--video/decode/vaapi.c21
-rw-r--r--video/decode/vd_lavc.c13
-rw-r--r--video/out/gl_hwdec_vaglx.c6
-rw-r--r--video/out/vo_vaapi.c10
-rw-r--r--video/vaapi.c28
-rw-r--r--video/vaapi.h5
7 files changed, 84 insertions, 2 deletions
diff --git a/video/decode/lavc.h b/video/decode/lavc.h
index 14dc6dda4e..f6b3c700d9 100644
--- a/video/decode/lavc.h
+++ b/video/decode/lavc.h
@@ -60,6 +60,9 @@ struct vd_lavc_hwdec {
int w, int h);
// Process the image returned by the libavcodec decoder.
struct mp_image *(*process_image)(struct lavc_ctx *ctx, struct mp_image *img);
+ // For horrible Intel shit-drivers only
+ void (*lock)(struct lavc_ctx *ctx);
+ void (*unlock)(struct lavc_ctx *ctx);
};
enum {
diff --git a/video/decode/vaapi.c b/video/decode/vaapi.c
index 5f9002762f..de26ac2955 100644
--- a/video/decode/vaapi.c
+++ b/video/decode/vaapi.c
@@ -187,6 +187,8 @@ static void destroy_decoder(struct lavc_ctx *ctx)
{
struct priv *p = ctx->hwdec_priv;
+ va_lock(p->ctx);
+
if (p->va_context->context_id != VA_INVALID_ID) {
vaDestroyContext(p->display, p->va_context->context_id);
p->va_context->context_id = VA_INVALID_ID;
@@ -197,6 +199,8 @@ static void destroy_decoder(struct lavc_ctx *ctx)
p->va_context->config_id = VA_INVALID_ID;
}
+ va_unlock(p->ctx);
+
mp_image_pool_clear(p->pool);
}
@@ -219,6 +223,8 @@ static int init_decoder(struct lavc_ctx *ctx, int fmt, int w, int h)
destroy_decoder(ctx);
+ va_lock(p->ctx);
+
const struct hwdec_profile_entry *pe = hwdec_find_profile(ctx, profiles);
if (!pe) {
MP_ERR(p, "Unsupported codec or profile.\n");
@@ -300,6 +306,7 @@ static int init_decoder(struct lavc_ctx *ctx, int fmt, int w, int h)
res = 0;
error:
+ va_unlock(p->ctx);
talloc_free(tmp);
return res;
}
@@ -455,6 +462,18 @@ static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *img)
return img;
}
+static void intel_shit_lock(struct lavc_ctx *ctx)
+{
+ struct priv *p = ctx->hwdec_priv;
+ va_lock(p->ctx);
+}
+
+static void intel_crap_unlock(struct lavc_ctx *ctx)
+{
+ struct priv *p = ctx->hwdec_priv;
+ va_unlock(p->ctx);
+}
+
const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
.type = HWDEC_VAAPI,
.image_format = IMGFMT_VAAPI,
@@ -463,6 +482,8 @@ const struct vd_lavc_hwdec mp_vd_lavc_vaapi = {
.uninit = uninit,
.init_decoder = init_decoder,
.allocate_image = allocate_image,
+ .lock = intel_shit_lock,
+ .unlock = intel_crap_unlock,
};
const struct vd_lavc_hwdec mp_vd_lavc_vaapi_copy = {
diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c
index 1cd4503968..350f5f16b2 100644
--- a/video/decode/vd_lavc.c
+++ b/video/decode/vd_lavc.c
@@ -160,6 +160,17 @@ static bool hwdec_codec_allowed(struct dec_video *vd, const char *codec)
return false;
}
+static void hwdec_lock(struct lavc_ctx *ctx)
+{
+ if (ctx->hwdec && ctx->hwdec->lock)
+ ctx->hwdec->lock(ctx);
+}
+static void hwdec_unlock(struct lavc_ctx *ctx)
+{
+ if (ctx->hwdec && ctx->hwdec->unlock)
+ ctx->hwdec->unlock(ctx);
+}
+
// Find the correct profile entry for the current codec and profile.
// Assumes the table has higher profiles first (for each codec).
const struct hwdec_profile_entry *hwdec_find_profile(
@@ -608,7 +619,9 @@ static int decode(struct dec_video *vd, struct demux_packet *packet,
mp_set_av_packet(&pkt, packet, NULL);
+ hwdec_lock(ctx);
ret = avcodec_decode_video2(avctx, ctx->pic, &got_picture, &pkt);
+ hwdec_unlock(ctx);
if (ret < 0) {
MP_WARN(vd, "Error while decoding frame!\n");
return -1;
diff --git a/video/out/gl_hwdec_vaglx.c b/video/out/gl_hwdec_vaglx.c
index 08c7f4957f..665b800efb 100644
--- a/video/out/gl_hwdec_vaglx.c
+++ b/video/out/gl_hwdec_vaglx.c
@@ -42,7 +42,9 @@ static void destroy_texture(struct gl_hwdec *hw)
VAStatus status;
if (p->vaglx_surface) {
+ va_lock(p->ctx);
status = vaDestroySurfaceGLX(p->display, p->vaglx_surface);
+ va_unlock(p->ctx);
CHECK_VA_STATUS(p, "vaDestroySurfaceGLX()");
p->vaglx_surface = NULL;
}
@@ -98,8 +100,10 @@ static int reinit(struct gl_hwdec *hw, const struct mp_image_params *params)
GL_RGBA, GL_UNSIGNED_BYTE, NULL);
gl->BindTexture(GL_TEXTURE_2D, 0);
+ va_lock(p->ctx);
status = vaCreateSurfaceGLX(p->display, GL_TEXTURE_2D,
p->gl_texture, &p->vaglx_surface);
+ va_unlock(p->ctx);
return CHECK_VA_STATUS(p, "vaCreateSurfaceGLX()") ? 0 : -1;
}
@@ -112,9 +116,11 @@ static int map_image(struct gl_hwdec *hw, struct mp_image *hw_image,
if (!p->vaglx_surface)
return -1;
+ va_lock(p->ctx);
status = vaCopySurfaceGLX(p->display, p->vaglx_surface,
va_surface_id(hw_image),
va_get_colorspace_flag(hw_image->params.colorspace));
+ va_unlock(p->ctx);
if (!CHECK_VA_STATUS(p, "vaCopySurfaceGLX()"))
return -1;
diff --git a/video/out/vo_vaapi.c b/video/out/vo_vaapi.c
index 3c760ac07c..fa23c931c6 100644
--- a/video/out/vo_vaapi.c
+++ b/video/out/vo_vaapi.c
@@ -212,6 +212,8 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
if (surface == VA_INVALID_ID)
return false;
+ va_lock(p->mpvaapi);
+
for (int n = 0; n < MAX_OSD_PARTS; n++) {
struct vaapi_osd_part *part = &p->osd_parts[n];
if (part->active) {
@@ -261,6 +263,8 @@ static bool render_to_screen(struct priv *p, struct mp_image *mpi)
}
}
+ va_unlock(p->mpvaapi);
+
return true;
}
@@ -427,6 +431,8 @@ static void draw_osd(struct vo *vo)
if (!p->osd_format.fourcc)
return;
+ va_lock(p->mpvaapi);
+
struct mp_osd_res vid_res = osd_res_from_image_params(vo->params);
struct mp_osd_res *res;
@@ -439,6 +445,8 @@ static void draw_osd(struct vo *vo)
for (int n = 0; n < MAX_OSD_PARTS; n++)
p->osd_parts[n].active = false;
osd_draw(vo->osd, *res, pts, 0, osd_formats, draw_osd_cb, p);
+
+ va_unlock(p->mpvaapi);
}
static int get_displayattribtype(const char *name)
@@ -495,7 +503,9 @@ static int set_equalizer(struct priv *p, const char *name, int value)
return VO_NOTIMPL;
attr->value = ((value + 100) * r) / 200 + attr->min_value;
+ va_lock(p->mpvaapi);
status = vaSetDisplayAttributes(p->display, attr, 1);
+ va_unlock(p->mpvaapi);
if (!CHECK_VA_STATUS(p, "vaSetDisplayAttributes()"))
return VO_FALSE;
return VO_TRUE;
diff --git a/video/vaapi.c b/video/vaapi.c
index 212ed4ff73..981b6ee911 100644
--- a/video/vaapi.c
+++ b/video/vaapi.c
@@ -20,6 +20,7 @@
#include "vaapi.h"
#include "common/common.h"
#include "common/msg.h"
+#include "osdep/threads.h"
#include "mp_image.h"
#include "img_format.h"
#include "mp_image_pool.h"
@@ -122,6 +123,7 @@ struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *plog)
.log = talloc_steal(res, log),
.display = display,
};
+ mpthread_mutex_init_recursive(&res->lock);
va_get_formats(res);
if (!res->image_formats)
@@ -142,6 +144,7 @@ void va_destroy(struct mp_vaapi_ctx *ctx)
if (ctx) {
if (ctx->display)
vaTerminate(ctx->display);
+ pthread_mutex_destroy(&ctx->lock);
talloc_free(ctx);
}
}
@@ -192,11 +195,13 @@ static void release_va_surface(void *arg)
{
struct va_surface *surface = arg;
+ va_lock(surface->ctx);
if (surface->id != VA_INVALID_ID) {
if (surface->image.image_id != VA_INVALID_ID)
vaDestroyImage(surface->display, surface->image.image_id);
vaDestroySurfaces(surface->display, &surface->id, 1);
}
+ va_unlock(surface->ctx);
talloc_free(surface);
}
@@ -205,7 +210,9 @@ static struct mp_image *alloc_surface(struct mp_vaapi_ctx *ctx, int rt_format,
{
VASurfaceID id = VA_INVALID_ID;
VAStatus status;
+ va_lock(ctx);
status = vaCreateSurfaces(ctx->display, w, h, rt_format, 1, &id);
+ va_unlock(ctx);
if (!CHECK_VA_STATUS(ctx, "vaCreateSurfaces()"))
return NULL;
@@ -249,6 +256,9 @@ static int va_surface_image_alloc(struct mp_image *img, VAImageFormat *format)
p->image.format.fourcc == format->fourcc)
return 0;
+ int r = 0;
+ va_lock(p->ctx);
+
va_surface_image_destroy(p);
VAStatus status = vaDeriveImage(display, p->id, &p->image);
@@ -269,10 +279,12 @@ static int va_surface_image_alloc(struct mp_image *img, VAImageFormat *format)
status = vaCreateImage(p->display, format, img->w, img->h, &p->image);
if (!CHECK_VA_STATUS(p->ctx, "vaCreateImage()")) {
p->image.image_id = VA_INVALID_ID;
- return -1;
+ r = -1;
}
}
- return 0;
+
+ va_unlock(p->ctx);
+ return r;
}
// img must be a VAAPI surface; make sure its internal VAImage is allocated
@@ -302,7 +314,9 @@ bool va_image_map(struct mp_vaapi_ctx *ctx, VAImage *image, struct mp_image *mpi
if (imgfmt == IMGFMT_NONE)
return false;
void *data = NULL;
+ va_lock(ctx);
const VAStatus status = vaMapBuffer(ctx->display, image->buf, &data);
+ va_unlock(ctx);
if (!CHECK_VA_STATUS(ctx, "vaMapBuffer()"))
return false;
@@ -325,7 +339,9 @@ bool va_image_map(struct mp_vaapi_ctx *ctx, VAImage *image, struct mp_image *mpi
bool va_image_unmap(struct mp_vaapi_ctx *ctx, VAImage *image)
{
+ va_lock(ctx);
const VAStatus status = vaUnmapBuffer(ctx->display, image->buf);
+ va_unlock(ctx);
return CHECK_VA_STATUS(ctx, "vaUnmapBuffer()");
}
@@ -347,10 +363,12 @@ int va_surface_upload(struct mp_image *va_dst, struct mp_image *sw_src)
va_image_unmap(p->ctx, &p->image);
if (!p->is_derived) {
+ va_lock(p->ctx);
VAStatus status = vaPutImage2(p->display, p->id,
p->image.image_id,
0, 0, sw_src->w, sw_src->h,
0, 0, sw_src->w, sw_src->h);
+ va_unlock(p->ctx);
if (!CHECK_VA_STATUS(p->ctx, "vaPutImage()"))
return -1;
}
@@ -373,8 +391,10 @@ static struct mp_image *try_download(struct mp_image *src,
return NULL;
if (!p->is_derived) {
+ va_lock(p->ctx);
status = vaGetImage(p->display, p->id, 0, 0,
src->w, src->h, image->image_id);
+ va_unlock(p->ctx);
if (status != VA_STATUS_SUCCESS)
return NULL;
}
@@ -400,7 +420,9 @@ struct mp_image *va_surface_download(struct mp_image *src,
if (!p)
return NULL;
struct mp_vaapi_ctx *ctx = p->ctx;
+ va_lock(ctx);
VAStatus status = vaSyncSurface(p->display, p->id);
+ va_unlock(ctx);
if (!CHECK_VA_STATUS(ctx, "vaSyncSurface()"))
return NULL;
@@ -452,6 +474,8 @@ void va_pool_set_allocator(struct mp_image_pool *pool, struct mp_vaapi_ctx *ctx,
bool va_guess_if_emulated(struct mp_vaapi_ctx *ctx)
{
+ va_lock(ctx);
const char *s = vaQueryVendorString(ctx->display);
+ va_unlock(ctx);
return s && strstr(s, "VDPAU backend");
}
diff --git a/video/vaapi.h b/video/vaapi.h
index 8a96bb1347..86a9919e27 100644
--- a/video/vaapi.h
+++ b/video/vaapi.h
@@ -3,6 +3,7 @@
#include <stdbool.h>
#include <inttypes.h>
+#include <pthread.h>
#include <va/va.h>
#include <va/va_x11.h>
@@ -79,6 +80,7 @@ struct mp_vaapi_ctx {
struct mp_log *log;
VADisplay display;
struct va_image_formats *image_formats;
+ pthread_mutex_t lock;
};
struct va_image_formats;
@@ -87,6 +89,9 @@ bool check_va_status(struct mp_log *log, VAStatus status, const char *msg);
#define CHECK_VA_STATUS(ctx, msg) check_va_status((ctx)->log, status, msg)
+#define va_lock(ctx) pthread_mutex_lock(&(ctx)->lock)
+#define va_unlock(ctx) pthread_mutex_unlock(&(ctx)->lock)
+
int va_get_colorspace_flag(enum mp_csp csp);
struct mp_vaapi_ctx *va_initialize(VADisplay *display, struct mp_log *log);