Coverage Report

Created: 2025-06-24 07:38

/src/mpv/video/hwdec.c
Line
Count
Source (jump to first uncovered line)
1
#include <assert.h>
2
3
#include <libavutil/hwcontext.h>
4
5
#include "config.h"
6
#include "hwdec.h"
7
#include "osdep/threads.h"
8
9
struct mp_hwdec_devices {
10
    mp_mutex lock;
11
12
    struct mp_hwdec_ctx **hwctxs;
13
    int num_hwctxs;
14
15
    void (*load_api)(void *ctx,
16
                     struct hwdec_imgfmt_request *params);
17
    void *load_api_ctx;
18
};
19
20
struct mp_hwdec_devices *hwdec_devices_create(void)
21
0
{
22
0
    struct mp_hwdec_devices *devs = talloc_zero(NULL, struct mp_hwdec_devices);
23
0
    mp_mutex_init(&devs->lock);
24
0
    return devs;
25
0
}
26
27
void hwdec_devices_destroy(struct mp_hwdec_devices *devs)
28
0
{
29
0
    if (!devs)
30
0
        return;
31
0
    mp_assert(!devs->num_hwctxs); // must have been hwdec_devices_remove()ed
32
0
    mp_assert(!devs->load_api); // must have been unset
33
0
    mp_mutex_destroy(&devs->lock);
34
0
    talloc_free(devs);
35
0
}
36
37
struct mp_hwdec_ctx *hwdec_devices_get_by_imgfmt_and_type(struct mp_hwdec_devices *devs,
38
                                                          int hw_imgfmt,
39
                                                          enum AVHWDeviceType device_type)
40
0
{
41
0
    struct mp_hwdec_ctx *res = NULL;
42
0
    mp_mutex_lock(&devs->lock);
43
0
    for (int n = 0; n < devs->num_hwctxs; n++) {
44
0
        struct mp_hwdec_ctx *dev = devs->hwctxs[n];
45
0
        AVHWDeviceContext *hw_device_ctx =
46
0
            dev->av_device_ref ? (AVHWDeviceContext *)dev->av_device_ref->data : NULL;
47
0
        if (dev->hw_imgfmt == hw_imgfmt &&
48
0
            (!hw_device_ctx || hw_device_ctx->type == device_type)) {
49
0
            res = dev;
50
0
            break;
51
0
        }
52
0
    }
53
0
    mp_mutex_unlock(&devs->lock);
54
0
    return res;
55
0
}
56
57
struct mp_hwdec_ctx *hwdec_devices_get_first(struct mp_hwdec_devices *devs)
58
0
{
59
0
    return hwdec_devices_get_n(devs, 0);
60
0
}
61
62
struct mp_hwdec_ctx *hwdec_devices_get_n(struct mp_hwdec_devices *devs, int n)
63
0
{
64
0
    mp_mutex_lock(&devs->lock);
65
0
    struct mp_hwdec_ctx *res = n < devs->num_hwctxs ? devs->hwctxs[n] : NULL;
66
0
    mp_mutex_unlock(&devs->lock);
67
0
    return res;
68
0
}
69
70
void hwdec_devices_add(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx)
71
0
{
72
0
    mp_mutex_lock(&devs->lock);
73
0
    MP_TARRAY_APPEND(devs, devs->hwctxs, devs->num_hwctxs, ctx);
74
0
    mp_mutex_unlock(&devs->lock);
75
0
}
76
77
void hwdec_devices_remove(struct mp_hwdec_devices *devs, struct mp_hwdec_ctx *ctx)
78
0
{
79
0
    mp_mutex_lock(&devs->lock);
80
0
    for (int n = 0; n < devs->num_hwctxs; n++) {
81
0
        if (devs->hwctxs[n] == ctx) {
82
0
            MP_TARRAY_REMOVE_AT(devs->hwctxs, devs->num_hwctxs, n);
83
0
            break;
84
0
        }
85
0
    }
86
0
    mp_mutex_unlock(&devs->lock);
87
0
}
88
89
void hwdec_devices_set_loader(struct mp_hwdec_devices *devs,
90
    void (*load_api)(void *ctx, struct hwdec_imgfmt_request *params),
91
    void *load_api_ctx)
92
0
{
93
0
    devs->load_api = load_api;
94
0
    devs->load_api_ctx = load_api_ctx;
95
0
}
96
97
void hwdec_devices_request_for_img_fmt(struct mp_hwdec_devices *devs,
98
                                       struct hwdec_imgfmt_request *params)
99
0
{
100
0
    if (devs->load_api)
101
0
        devs->load_api(devs->load_api_ctx, params);
102
0
}
103
104
char *hwdec_devices_get_names(struct mp_hwdec_devices *devs)
105
0
{
106
0
    char *res = NULL;
107
0
    for (int n = 0; n < devs->num_hwctxs; n++) {
108
0
        if (res)
109
0
            ta_xstrdup_append(&res, ",");
110
0
        ta_xstrdup_append(&res, devs->hwctxs[n]->driver_name);
111
0
    }
112
0
    return res;
113
0
}
114
115
static const struct hwcontext_fns *const hwcontext_fns[] = {
116
#if HAVE_CUDA_HWACCEL
117
    &hwcontext_fns_cuda,
118
#endif
119
#if HAVE_D3D_HWACCEL
120
    &hwcontext_fns_d3d11,
121
#endif
122
#if HAVE_D3D9_HWACCEL
123
    &hwcontext_fns_dxva2,
124
#endif
125
#if HAVE_DRM
126
    &hwcontext_fns_drmprime,
127
#endif
128
#if HAVE_VAAPI
129
    &hwcontext_fns_vaapi,
130
#endif
131
#if HAVE_VDPAU
132
    &hwcontext_fns_vdpau,
133
#endif
134
    NULL,
135
};
136
137
const struct hwcontext_fns *hwdec_get_hwcontext_fns(int av_hwdevice_type)
138
0
{
139
0
    for (int n = 0; hwcontext_fns[n]; n++) {
140
0
        if (hwcontext_fns[n]->av_hwdevice_type == av_hwdevice_type)
141
0
            return hwcontext_fns[n];
142
0
    }
143
0
    return NULL;
144
0
}