diff options
-rw-r--r-- | video/decode/lavc.h | 3 | ||||
-rw-r--r-- | video/decode/vaapi.c | 21 | ||||
-rw-r--r-- | video/decode/vd_lavc.c | 13 | ||||
-rw-r--r-- | video/out/gl_hwdec_vaglx.c | 6 | ||||
-rw-r--r-- | video/out/vo_vaapi.c | 10 | ||||
-rw-r--r-- | video/vaapi.c | 28 | ||||
-rw-r--r-- | video/vaapi.h | 5 |
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); |