#include #include #include #include "config.h" #include "hwdec.h" struct mp_hwdec_devices { pthread_mutex_t lock; struct mp_hwdec_ctx **hwctxs; int num_hwctxs; void (*load_api)(void *ctx); 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->num_hwctxs); // 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_by_lavc(struct mp_hwdec_devices *devs, int av_hwdevice_type) { struct mp_hwdec_ctx *res = NULL; pthread_mutex_lock(&devs->lock); for (int n = 0; n < devs->num_hwctxs; n++) { struct mp_hwdec_ctx *dev = devs->hwctxs[n]; if (dev->av_device_ref) { AVHWDeviceContext *hwctx = (void *)dev->av_device_ref->data; if (hwctx->type == av_hwdevice_type) { res = dev; break; } } } pthread_mutex_unlock(&devs->lock); return res; } struct AVBufferRef *hwdec_devices_get_lavc(struct mp_hwdec_devices *devs, int av_hwdevice_type) { struct mp_hwdec_ctx *ctx = hwdec_devices_get_by_lavc(devs, av_hwdevice_type); if (!ctx) return NULL; return av_buffer_ref(ctx->av_device_ref); } struct mp_hwdec_ctx *hwdec_devices_get_first(struct mp_hwdec_devices *devs) { return hwdec_devices_get_n(devs, 0); } struct mp_hwdec_ctx *hwdec_devices_get_n(struct mp_hwdec_devices *devs, int n) { pthread_mutex_lock(&devs->lock); struct mp_hwdec_ctx *res = n < devs->num_hwctxs ? devs->hwctxs[n] : NULL; 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); MP_TARRAY_APPEND(devs, devs->hwctxs, devs->num_hwctxs, 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); for (int n = 0; n < devs->num_hwctxs; n++) { if (devs->hwctxs[n] == ctx) { MP_TARRAY_REMOVE_AT(devs->hwctxs, devs->num_hwctxs, n); break; } } pthread_mutex_unlock(&devs->lock); } void hwdec_devices_set_loader(struct mp_hwdec_devices *devs, void (*load_api)(void *ctx), void *load_api_ctx) { devs->load_api = load_api; devs->load_api_ctx = load_api_ctx; } void hwdec_devices_request_all(struct mp_hwdec_devices *devs) { if (devs->load_api && !hwdec_devices_get_first(devs)) devs->load_api(devs->load_api_ctx); } char *hwdec_devices_get_names(struct mp_hwdec_devices *devs) { char *res = NULL; for (int n = 0; n < devs->num_hwctxs; n++) { if (res) ta_xstrdup_append(&res, ","); ta_xstrdup_append(&res, devs->hwctxs[n]->driver_name); } return res; } static const struct hwcontext_fns *const hwcontext_fns[] = { #if HAVE_D3D_HWACCEL &hwcontext_fns_d3d11, #endif #if HAVE_D3D9_HWACCEL &hwcontext_fns_dxva2, #endif #if HAVE_VAAPI &hwcontext_fns_vaapi, #endif #if HAVE_VDPAU &hwcontext_fns_vdpau, #endif NULL, }; const struct hwcontext_fns *hwdec_get_hwcontext_fns(int av_hwdevice_type) { for (int n = 0; hwcontext_fns[n]; n++) { if (hwcontext_fns[n]->av_hwdevice_type == av_hwdevice_type) return hwcontext_fns[n]; } return NULL; }