mirror of
https://github.com/mpv-player/mpv
synced 2024-12-23 23:32:26 +00:00
9c05be8999
In the distant past, the cuviddec backed copy hwaccel could be configured directly using lavc options. However, since that time, we gained support for automatic hw ctx creation which ended up bypassing the lavc options. Rather than trying to find a way to pass those options again, a better idea is to make the 'cuda-decode-device' option, used by the interop hwaccels, work for the copy hwaccels too. And that's pretty simple: we have to add a create function that checks the option and passes it on to ffmpeg. Note that this does require a slight re-jig to the configuration flags, as we now have a scenario where we want to build with support for the cuda copy hwaccels but not the interop ones. So we need a distinct configuration flag for that combination. Fixes #7295.
148 lines
3.8 KiB
C
148 lines
3.8 KiB
C
#include <pthread.h>
|
|
#include <assert.h>
|
|
|
|
#include <libavutil/hwcontext.h>
|
|
|
|
#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_CUDA_HWACCEL
|
|
&hwcontext_fns_cuda,
|
|
#endif
|
|
#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;
|
|
}
|