diff options
Diffstat (limited to 'video')
34 files changed, 334 insertions, 258 deletions
diff --git a/video/d3d.h b/video/d3d.h deleted file mode 100644 index b5cf365f7f..0000000000 --- a/video/d3d.h +++ /dev/null @@ -1,15 +0,0 @@ -#ifndef MP_D3D_H_ -#define MP_D3D_H_ - -#include <d3d9.h> -#include <d3d11.h> - -#include "hwdec.h" - -struct mp_d3d_ctx { - struct mp_hwdec_ctx hwctx; - IDirect3DDevice9 *d3d9_device; - ID3D11Device *d3d11_device; -}; - -#endif diff --git a/video/decode/d3d11va.c b/video/decode/d3d11va.c index 246a35ec9a..1626626767 100644 --- a/video/decode/d3d11va.c +++ b/video/decode/d3d11va.c @@ -26,7 +26,6 @@ #include "video/mp_image_pool.h" #include "video/hwdec.h" -#include "video/d3d.h" #include "d3d.h" #define ADDITIONAL_SURFACES (4 + HWDEC_DELAY_QUEUE_COUNT) @@ -492,9 +491,7 @@ static int d3d11va_init(struct lavc_ctx *s) p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); } - if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx) - p->device = s->hwdec_info->hwctx->d3d_ctx->d3d11_device; - + p->device = hwdec_devices_load(s->hwdec_devs, s->hwdec->type); if (p->device) { ID3D11Device_AddRef(p->device); ID3D11Device_GetImmediateContext(p->device, &p->device_ctx); @@ -539,15 +536,12 @@ fail: return -1; } -static int d3d11va_probe(struct vd_lavc_hwdec *hwdec, - struct mp_hwdec_info *info, +static int d3d11va_probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { - hwdec_request_api(info, "d3d11va"); // d3d11va-copy can do without external context; dxva2 requires it. if (hwdec->type != HWDEC_D3D11VA_COPY) { - if (!info || !info->hwctx || !info->hwctx->d3d_ctx || - !info->hwctx->d3d_ctx->d3d11_device) + if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_D3D11VA)) return HWDEC_ERR_NO_CTX; } return d3d_probe_codec(codec); diff --git a/video/decode/dec_video.h b/video/decode/dec_video.h index f4646a97d0..1030973e1c 100644 --- a/video/decode/dec_video.h +++ b/video/decode/dec_video.h @@ -32,7 +32,7 @@ struct dec_video { struct mpv_global *global; struct MPOpts *opts; const struct vd_functions *vd_driver; - struct mp_hwdec_info *hwdec_info; // video output hwdec handles + struct mp_hwdec_devices *hwdec_devs; // video output hwdec handles struct sh_stream *header; struct mp_codec_params *codec; diff --git a/video/decode/dxva2.c b/video/decode/dxva2.c index 70623c8fb4..5d3afda86c 100644 --- a/video/decode/dxva2.c +++ b/video/decode/dxva2.c @@ -32,7 +32,6 @@ #include "video/mp_image_pool.h" #include "video/hwdec.h" -#include "video/d3d.h" #include "video/dxva2.h" #include "d3d.h" @@ -406,9 +405,7 @@ static int dxva2_init(struct lavc_ctx *s) p->sw_pool = talloc_steal(p, mp_image_pool_new(17)); } - if (s->hwdec_info && s->hwdec_info->hwctx && s->hwdec_info->hwctx->d3d_ctx) - p->device = s->hwdec_info->hwctx->d3d_ctx->d3d9_device; - + p->device = hwdec_devices_load(s->hwdec_devs, s->hwdec->type); if (p->device) { IDirect3D9_AddRef(p->device); MP_VERBOSE(p, "Using VO-supplied device %p.\n", p->device); @@ -477,16 +474,15 @@ fail: return -1; } -static int dxva2_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, +static int dxva2_probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { - hwdec_request_api(info, "dxva2"); // dxva2-copy can do without external context; dxva2 requires it. - if (hwdec->type != HWDEC_DXVA2_COPY) { - if (!info || !info->hwctx || !info->hwctx->d3d_ctx || - info->hwctx->type == HWDEC_DXVA2_COPY || - !info->hwctx->d3d_ctx->d3d9_device) + if (hwdec->type == HWDEC_DXVA2) { + if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_DXVA2)) return HWDEC_ERR_NO_CTX; + } else { + hwdec_devices_load(ctx->hwdec_devs, HWDEC_DXVA2_COPY); } return d3d_probe_codec(codec); } diff --git a/video/decode/lavc.h b/video/decode/lavc.h index 73243e16c4..dbefe79ad9 100644 --- a/video/decode/lavc.h +++ b/video/decode/lavc.h @@ -30,7 +30,7 @@ typedef struct lavc_ctx { int max_delay_queue; // From VO - struct mp_hwdec_info *hwdec_info; + struct mp_hwdec_devices *hwdec_devs; // For free use by hwdec implementation void *hwdec_priv; @@ -54,7 +54,7 @@ struct vd_lavc_hwdec { // efficiency by not blocking on the hardware pipeline by reading back // immediately after decoding. int delay_queue; - int (*probe)(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, + int (*probe)(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec); int (*init)(struct lavc_ctx *ctx); int (*init_decoder)(struct lavc_ctx *ctx, int w, int h); diff --git a/video/decode/vaapi.c b/video/decode/vaapi.c index 169564d6c4..4b098a8804 100644 --- a/video/decode/vaapi.c +++ b/video/decode/vaapi.c @@ -357,7 +357,7 @@ static void destroy_va_dummy_ctx(struct priv *p) // Creates a "private" VADisplay, disconnected from the VO. We just create a // new X connection, because that's simpler. (We could also pass the X -// connection along with struct mp_hwdec_info, if we wanted.) +// connection along with struct mp_hwdec_devices, if we wanted.) static bool create_va_dummy_ctx(struct priv *p) { for (int n = 0; native_displays[n]; n++) { @@ -399,21 +399,23 @@ static void uninit(struct lavc_ctx *ctx) ctx->hwdec_priv = NULL; } -static int init_with_vactx(struct lavc_ctx *ctx, struct mp_vaapi_ctx *vactx) +static int init(struct lavc_ctx *ctx, bool direct) { struct priv *p = talloc_ptrtype(NULL, p); *p = (struct priv) { .log = mp_log_new(p, ctx->log, "vaapi"), - .ctx = vactx, .va_context = &p->va_context_storage, .rt_format = VA_RT_FORMAT_YUV420 }; - if (!p->ctx) + if (direct) { + p->ctx = hwdec_devices_get(ctx->hwdec_devs, HWDEC_VAAPI)->ctx; + } else { create_va_dummy_ctx(p); - if (!p->ctx) { - talloc_free(p); - return -1; + if (!p->ctx) { + talloc_free(p); + return -1; + } } p->display = p->ctx->display; @@ -431,25 +433,22 @@ static int init_with_vactx(struct lavc_ctx *ctx, struct mp_vaapi_ctx *vactx) return 0; } -static int init(struct lavc_ctx *ctx) +static int init_direct(struct lavc_ctx *ctx) { - return init_with_vactx(ctx, ctx->hwdec_info->hwctx->vaapi_ctx); + return init(ctx, true); } -static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, +static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { - hwdec_request_api(info, "vaapi"); - if (!info || !info->hwctx || !info->hwctx->vaapi_ctx) + if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_VAAPI)) return HWDEC_ERR_NO_CTX; if (!hwdec_check_codec_support(codec, profiles)) return HWDEC_ERR_NO_CODEC; - if (va_guess_if_emulated(info->hwctx->vaapi_ctx)) - return HWDEC_ERR_EMULATED; return 0; } -static int probe_copy(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, +static int probe_copy(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { struct priv dummy = {mp_null_log}; @@ -466,7 +465,7 @@ static int probe_copy(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, static int init_copy(struct lavc_ctx *ctx) { - return init_with_vactx(ctx, NULL); + return init(ctx, false); } static struct mp_image *copy_image(struct lavc_ctx *ctx, struct mp_image *img) @@ -497,7 +496,7 @@ const struct vd_lavc_hwdec mp_vd_lavc_vaapi = { .type = HWDEC_VAAPI, .image_format = IMGFMT_VAAPI, .probe = probe, - .init = init, + .init = init_direct, .uninit = uninit, .init_decoder = init_decoder, .allocate_image = allocate_image, diff --git a/video/decode/vd_lavc.c b/video/decode/vd_lavc.c index ff97e3446c..bc70b7d348 100644 --- a/video/decode/vd_lavc.c +++ b/video/decode/vd_lavc.c @@ -280,18 +280,13 @@ static bool hwdec_is_wrapper(struct vd_lavc_hwdec *hwdec, const char *decoder) return bstr_endswith0(bstr0(decoder), hwdec->lavc_suffix); } -void hwdec_request_api(struct mp_hwdec_info *info, const char *api_name) -{ - if (info && info->load_api) - info->load_api(info, api_name); -} - -static int hwdec_probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, +static int hwdec_probe(struct dec_video *vd, struct vd_lavc_hwdec *hwdec, const char *codec) { + vd_ffmpeg_ctx *ctx = vd->priv; int r = 0; if (hwdec->probe) - r = hwdec->probe(hwdec, info, codec); + r = hwdec->probe(ctx, hwdec, codec); if (r >= 0) { if (hwdec->lavc_suffix && !hwdec_find_decoder(codec, hwdec->lavc_suffix)) return HWDEC_ERR_NO_CODEC; @@ -309,7 +304,7 @@ static struct vd_lavc_hwdec *probe_hwdec(struct dec_video *vd, bool autoprobe, MP_VERBOSE(vd, "Requested hardware decoder not compiled.\n"); return NULL; } - int r = hwdec_probe(hwdec, vd->hwdec_info, codec); + int r = hwdec_probe(vd, hwdec, codec); if (r == HWDEC_ERR_EMULATED) { if (autoprobe) return NULL; @@ -412,6 +407,7 @@ static int init(struct dec_video *vd, const char *decoder) ctx->log = vd->log; ctx->opts = vd->opts; ctx->decoder = talloc_strdup(ctx, decoder); + ctx->hwdec_devs = vd->hwdec_devs; reinit(vd); @@ -441,8 +437,6 @@ static void init_avctx(struct dec_video *vd, const char *decoder, if (!lavc_codec) return; - ctx->hwdec_info = vd->hwdec_info; - ctx->codec_timebase = (AVRational){0}; if (strstr(decoder, "_mmal") || strstr(decoder, "_mediacodec")) ctx->codec_timebase = (AVRational){1, 1000000}; diff --git a/video/decode/vdpau.c b/video/decode/vdpau.c index 313fabff76..2aba10c13b 100644 --- a/video/decode/vdpau.c +++ b/video/decode/vdpau.c @@ -75,7 +75,7 @@ static int init(struct lavc_ctx *ctx) struct priv *p = talloc_ptrtype(NULL, p); *p = (struct priv) { .log = mp_log_new(p, ctx->log, "vdpau"), - .mpvdp = ctx->hwdec_info->hwctx->vdpau_ctx, + .mpvdp = hwdec_devices_get(ctx->hwdec_devs, HWDEC_VDPAU)->ctx, }; ctx->hwdec_priv = p; @@ -83,14 +83,11 @@ static int init(struct lavc_ctx *ctx) return 0; } -static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, +static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { - hwdec_request_api(info, "vdpau"); - if (!info || !info->hwctx || !info->hwctx->vdpau_ctx) + if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_VDPAU)) return HWDEC_ERR_NO_CTX; - if (mp_vdpau_guess_if_emulated(info->hwctx->vdpau_ctx)) - return HWDEC_ERR_EMULATED; return 0; } diff --git a/video/decode/videotoolbox.c b/video/decode/videotoolbox.c index 2d2f5f735c..c69d5e89e6 100644 --- a/video/decode/videotoolbox.c +++ b/video/decode/videotoolbox.c @@ -27,11 +27,10 @@ #include "config.h" -static int probe(struct vd_lavc_hwdec *hwdec, struct mp_hwdec_info *info, +static int probe(struct lavc_ctx *ctx, struct vd_lavc_hwdec *hwdec, const char *codec) { - hwdec_request_api(info, "videotoolbox"); - if (!info || !info->hwctx || !info->hwctx->get_vt_fmt) + if (!hwdec_devices_load(ctx->hwdec_devs, HWDEC_VIDEOTOOLBOX)) return HWDEC_ERR_NO_CTX; switch (mp_codec_to_av_codec_id(codec)) { case AV_CODEC_ID_H264: @@ -89,8 +88,8 @@ static int init_decoder(struct lavc_ctx *ctx, int w, int h) AVVideotoolboxContext *vtctx = av_videotoolbox_alloc_context(); - struct mp_hwdec_ctx *hwctx = ctx->hwdec_info->hwctx; - vtctx->cv_pix_fmt_type = hwctx->get_vt_fmt(hwctx); + struct mp_vt_ctx *vt = hwdec_devices_load(ctx->hwdec_devs, HWDEC_VIDEOTOOLBOX); + vtctx->cv_pix_fmt_type = vt->get_vt_fmt(vt); int err = av_videotoolbox_default_init2(ctx->avctx, vtctx); if (err < 0) { diff --git a/video/filter/vf.c b/video/filter/vf.c index d8e7f6b4c8..7ca1b08f34 100644 --- a/video/filter/vf.c +++ b/video/filter/vf.c @@ -244,7 +244,7 @@ static struct vf_instance *vf_open(struct vf_chain *c, const char *name, *vf = (vf_instance_t) { .info = desc.p, .log = mp_log_new(vf, c->log, name), - .hwdec = c->hwdec, + .hwdec_devs = c->hwdec_devs, .query_format = vf_default_query_format, .out_pool = talloc_steal(vf, mp_image_pool_new(16)), .chain = c, diff --git a/video/filter/vf.h b/video/filter/vf.h index c982b612e1..02f6f2c8fd 100644 --- a/video/filter/vf.h +++ b/video/filter/vf.h @@ -92,7 +92,7 @@ typedef struct vf_instance { struct mp_image_pool *out_pool; struct vf_priv_s *priv; struct mp_log *log; - struct mp_hwdec_info *hwdec; + struct mp_hwdec_devices *hwdec_devs; struct mp_image **out_queued; int num_out_queued; @@ -120,7 +120,7 @@ struct vf_chain { struct mp_log *log; struct MPOpts *opts; struct mpv_global *global; - struct mp_hwdec_info *hwdec; + struct mp_hwdec_devices *hwdec_devs; // Call when the filter chain wants new processing (for filters with // asynchronous behavior) - must be immutable once filters are created, diff --git a/video/filter/vf_vavpp.c b/video/filter/vf_vavpp.c index 9dab15e2b9..554ddc1a05 100644 --- a/video/filter/vf_vavpp.c +++ b/video/filter/vf_vavpp.c @@ -481,19 +481,17 @@ static bool initialize(struct vf_instance *vf) static int vf_open(vf_instance_t *vf) { + struct vf_priv_s *p = vf->priv; + vf->reconfig = reconfig; vf->filter_ext = filter_ext; vf->query_format = query_format; vf->uninit = uninit; vf->control = control; - struct vf_priv_s *p = vf->priv; - if (!vf->hwdec) - return false; - hwdec_request_api(vf->hwdec, "vaapi"); - p->va = vf->hwdec->hwctx ? vf->hwdec->hwctx->vaapi_ctx : NULL; - if (!p->va || !p->va->display) - return false; + p->va = hwdec_devices_load(vf->hwdec_devs, HWDEC_VAAPI); + if (!p->va) + return 0; p->display = p->va->display; if (initialize(vf)) return true; diff --git a/video/filter/vf_vdpaupp.c b/video/filter/vf_vdpaupp.c index 882b80d9e2..23afeafe6a 100644 --- a/video/filter/vf_vdpaupp.c +++ b/video/filter/vf_vdpaupp.c @@ -223,10 +223,7 @@ static int vf_open(vf_instance_t *vf) vf->control = control; vf->uninit = uninit; - if (!vf->hwdec) - return 0; - hwdec_request_api(vf->hwdec, "vdpau"); - p->ctx = vf->hwdec->hwctx ? vf->hwdec->hwctx->vdpau_ctx : NULL; + p->ctx = hwdec_devices_load(vf->hwdec_devs, HWDEC_VDPAU); if (!p->ctx) return 0; diff --git a/video/filter/vf_vdpaurb.c b/video/filter/vf_vdpaurb.c index 62f7f34af1..92dfa52486 100644 --- a/video/filter/vf_vdpaurb.c +++ b/video/filter/vf_vdpaurb.c @@ -101,14 +101,9 @@ static int vf_open(vf_instance_t *vf) vf->reconfig = reconfig; vf->query_format = query_format; - if (!vf->hwdec) { + p->ctx = hwdec_devices_load(vf->hwdec_devs, HWDEC_VDPAU); + if (!p->ctx) return 0; - } - hwdec_request_api(vf->hwdec, "vdpau"); - p->ctx = vf->hwdec->hwctx ? vf->hwdec->hwctx->vdpau_ctx : NULL; - if (!p->ctx) { - return 0; - } return 1; } diff --git a/video/hwdec.c b/video/hwdec.c new file mode 100644 index 0000000000..6db8d57869 --- /dev/null +++ b/video/hwdec.c @@ -0,0 +1,90 @@ +#include <pthread.h> +#include <assert.h> + +#include "hwdec.h" + +struct mp_hwdec_devices { + pthread_mutex_t lock; + + struct mp_hwdec_ctx *hwctx; + + void (*load_api)(void *ctx, enum hwdec_type type); + void *load_api_ctx; +}; + +struct mp_hwdec_devices *hwdec_devices_create(void) +{ + struct mp_hwdec_devices *devs = talloc_zero(NULL, struct mp_hwdec_devices); + pthread_mutex_init(&devs->lock, NULL); + return devs; +} + +void hwdec_devices_destroy(struct mp_hwdec_devices *devs) +{ + if (!devs) + return; + assert(!devs->hwctx); // must have been hwdec_devices_remove()ed + assert(!devs->load_api); // must have been unset + pthread_mutex_destroy(&devs->lock); + talloc_free(devs); +} + +struct mp_hwdec_ctx *hwdec_devices_get(struct mp_hwdec_devices *devs, + enum hwdec_type type) +{ + struct mp_hwdec_ctx *res = NULL; + pthread_mutex_lock(&devs->lock); + if (devs->hwctx && devs->hwctx->type == type) + res = devs->hwctx; + pthread_mutex_unlock(&devs->lock); + return res; +} + +struct mp_hwdec_ctx *hwdec_devices_get_first(struct mp_hwdec_devices *devs) +{ + pthread_mutex_lock(&devs->lock); + struct mp_hwdec_ctx *res = devs->hwctx; + pthread_mutex_unlock(&devs->lock); + return res; +} + +void hwdec_devices_add(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx) +{ + pthread_mutex_lock(&devs->lock); + // We support only 1 device; ignore the rest. + if (!devs->hwctx) + devs->hwctx = ctx; + pthread_mutex_unlock(&devs->lock); +} + +void hwdec_devices_remove(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx) +{ + pthread_mutex_lock(&devs->lock); + if (devs->hwctx == ctx) + devs->hwctx = NULL; + pthread_mutex_unlock(&devs->lock); +} + +void hwdec_devices_set_loader(struct mp_hwdec_devices *devs, + void (*load_api)(void *ctx, enum hwdec_type type), void *load_api_ctx) +{ + devs->load_api = load_api; + devs->load_api_ctx = load_api_ctx; +} + +// Cause VO to lazily load the requested device, and will block until this is +// done (even if not available). +void hwdec_devices_request(struct mp_hwdec_devices *devs, enum hwdec_type type) +{ + if (devs->load_api && !hwdec_devices_get_first(devs)) + devs->load_api(devs->load_api_ctx, type); +} + +void *hwdec_devices_load(struct mp_hwdec_devices *devs, enum hwdec_type type) +{ + if (!devs) + return NULL; + hwdec_devices_request(devs, type); + struct mp_hwdec_ctx *hwctx = hwdec_devices_get(devs, type); + return hwctx ? hwctx->ctx : NULL; +} diff --git a/video/hwdec.h b/video/hwdec.h index 94667774e7..48ec6a2a21 100644 --- a/video/hwdec.h +++ b/video/hwdec.h @@ -25,16 +25,17 @@ enum hwdec_type { extern const struct m_opt_choice_alternatives mp_hwdec_names[]; struct mp_hwdec_ctx { - enum hwdec_type type; + enum hwdec_type type; // (never HWDEC_NONE or HWDEC_AUTO) const char *driver_name; // NULL if unknown/not loaded - void *priv; // for free use by hwdec implementation - - // API-specific, not needed by all backends. - struct mp_vdpau_ctx *vdpau_ctx; - struct mp_vaapi_ctx *vaapi_ctx; - struct mp_d3d_ctx *d3d_ctx; - uint32_t (*get_vt_fmt)(struct mp_hwdec_ctx *ctx); + // This is never NULL. Its meaning depends on the .type field: + // HWDEC_VDPAU: struct mp_vaapi_ctx* + // HWDEC_VIDEOTOOLBOX: struct mp_vt_ctx* + // HWDEC_VAAPI: struct mp_vaapi_ctx* + // HWDEC_D3D11VA: ID3D11Device* + // HWDEC_DXVA2: IDirect3DDevice9* + // HWDEC_DXVA2_COPY: IDirect3DDevice9* + void *ctx; // Optional. // Allocates a software image from the pool, downloads the hw image from @@ -46,24 +47,50 @@ struct mp_hwdec_ctx { struct mp_image_pool *swpool); }; -// Used to communicate hardware decoder API handles from VO to video decoder. -// The VO can set the context pointer for supported APIs. -struct mp_hwdec_info { - // (Since currently only 1 hwdec API is loaded at a time, this pointer - // simply maps to the loaded one.) - struct mp_hwdec_ctx *hwctx; - - // Can be used to lazily load a requested API. - // api_name is e.g. "vdpau" (like the fields above, without "_ctx") - // Can be NULL, is idempotent, caller checks hwctx fields for success/access. - // Due to threading, the callback is the only code that is allowed to - // change fields in this struct after initialization. - void (*load_api)(struct mp_hwdec_info *info, const char *api_name); - void *load_api_ctx; +struct mp_vt_ctx { + void *priv; + uint32_t (*get_vt_fmt)(struct mp_vt_ctx *ctx); }; -// Trivial helper to call info->load_api(). -// Implemented in vd_lavc.c. -void hwdec_request_api(struct mp_hwdec_info *info, const char *api_name); +// Used to communicate hardware decoder device handles from VO to video decoder. +struct mp_hwdec_devices; + +struct mp_hwdec_devices *hwdec_devices_create(void); +void hwdec_devices_destroy(struct mp_hwdec_devices *devs); + +// Return the device context for the given API type. Returns NULL if none +// available. Logically, the returned pointer remains valid until VO +// uninitialization is started (all users of it must be uninitialized before). +// hwdec_devices_request() may be used before this to lazily load devices. +struct mp_hwdec_ctx *hwdec_devices_get(struct mp_hwdec_devices *devs, + enum hwdec_type type); + +// For code which still strictly assumes there is 1 (or none) device. +struct mp_hwdec_ctx *hwdec_devices_get_first(struct mp_hwdec_devices *devs); + +// Add this to the list of internal devices. Adding the same pointer twice must +// be avoided. +void hwdec_devices_add(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx); + +// Remove this from the list of internal devices. Idempotent/ignores entries +// not added yet. +void hwdec_devices_remove(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx); + +// Can be used to enable lazy loading of an API with hwdec_devices_request(). +// If used at all, this must be set/unset during initialization/uninitialization, +// as concurrent use with hwdec_devices_request() is a race condition. +void hwdec_devices_set_loader(struct mp_hwdec_devices *devs, + void (*load_api)(void *ctx, enum hwdec_type type), void *load_api_ctx); + +// Cause VO to lazily load the requested device, and will block until this is +// done (even if not available). +void hwdec_devices_request(struct mp_hwdec_devices *devs, enum hwdec_type type); + +// Convenience function: +// - return NULL if devs==NULL +// - call hwdec_devices_request(devs, type) +// - call hwdec_devices_get(devs, type) +// - then return the mp_hwdec_ctx.ctx field +void *hwdec_devices_load(struct mp_hwdec_devices *devs, enum hwdec_type type); #endif diff --git a/video/out/opengl/hwdec.c b/video/out/opengl/hwdec.c index 9c3bec1a0f..b4b5c23580 100644 --- a/video/out/opengl/hwdec.c +++ b/video/out/opengl/hwdec.c @@ -61,6 +61,7 @@ static const struct gl_hwdec_driver *const mpgl_hwdec_drivers[] = { static struct gl_hwdec *load_hwdec_driver(struct mp_log *log, GL *gl, struct mpv_global *global, + struct mp_hwdec_devices *devs, const struct gl_hwdec_driver *drv, bool is_auto) { @@ -70,6 +71,7 @@ static struct gl_hwdec *load_hwdec_driver(struct mp_log *log, GL *gl, .log = mp_log_new(hwdec, log, drv->name), .global = global, .gl = gl, + .devs = devs, .gl_texture_target = GL_TEXTURE_2D, .probing = is_auto, }; @@ -79,19 +81,19 @@ static struct gl_hwdec *load_hwdec_driver(struct mp_log *log, GL *gl, mp_verbose(log, "Loading failed.\n"); return NULL; } - if (hwdec->hwctx && !hwdec->hwctx->driver_name) - hwdec->hwctx->driver_name = hwdec->driver->name; return hwdec; } -struct gl_hwdec *gl_hwdec_load_api_id(struct mp_log *log, GL *gl, - struct mpv_global *g, int id) +struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl, + struct mpv_global *g, + struct mp_hwdec_devices *devs, + enum hwdec_type api) { - bool is_auto = id == HWDEC_AUTO; + bool is_auto = api == HWDEC_AUTO; for (int n = 0; mpgl_hwdec_drivers[n]; n++) { const struct gl_hwdec_driver *drv = mpgl_hwdec_drivers[n]; - if (is_auto || id == drv->api) { - struct gl_hwdec *r = load_hwdec_driver(log, gl, g, drv, is_auto); + if (is_auto || api == drv->api) { + struct gl_hwdec *r = load_hwdec_driver(log, gl, g, devs, drv, is_auto); if (r) return r; } @@ -99,19 +101,6 @@ struct gl_hwdec *gl_hwdec_load_api_id(struct mp_log *log, GL *gl, return NULL; } -// Like gl_hwdec_load_api_id(), but use option names. -struct gl_hwdec *gl_hwdec_load_api(struct mp_log *log, GL *gl, - struct mpv_global *g, const char *api_name) -{ - int id = HWDEC_NONE; - for (const struct m_opt_choice_alternatives *c = mp_hwdec_names; c->name; c++) - { - if (strcmp(c->name, api_name) == 0) - id = c->value; - } - return gl_hwdec_load_api_id(log, gl, g, id); -} - void gl_hwdec_uninit(struct gl_hwdec *hwdec) { if (hwdec) diff --git a/video/out/opengl/hwdec.h b/video/out/opengl/hwdec.h index a9d524a1d7..fcc6d3c11e 100644 --- a/video/out/opengl/hwdec.h +++ b/video/out/opengl/hwdec.h @@ -4,14 +4,12 @@ #include "common.h" #include "video/hwdec.h" -struct mp_hwdec_info; - struct gl_hwdec { const struct gl_hwdec_driver *driver; struct mp_log *log; struct mpv_global *global; GL *gl; - struct mp_hwdec_ctx *hwctx; |