1cabdff1aSopenharmony_ci/*
2cabdff1aSopenharmony_ci * This file is part of FFmpeg.
3cabdff1aSopenharmony_ci *
4cabdff1aSopenharmony_ci * FFmpeg is free software; you can redistribute it and/or
5cabdff1aSopenharmony_ci * modify it under the terms of the GNU Lesser General Public
6cabdff1aSopenharmony_ci * License as published by the Free Software Foundation; either
7cabdff1aSopenharmony_ci * version 2.1 of the License, or (at your option) any later version.
8cabdff1aSopenharmony_ci *
9cabdff1aSopenharmony_ci * FFmpeg is distributed in the hope that it will be useful,
10cabdff1aSopenharmony_ci * but WITHOUT ANY WARRANTY; without even the implied warranty of
11cabdff1aSopenharmony_ci * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12cabdff1aSopenharmony_ci * Lesser General Public License for more details.
13cabdff1aSopenharmony_ci *
14cabdff1aSopenharmony_ci * You should have received a copy of the GNU Lesser General Public
15cabdff1aSopenharmony_ci * License along with FFmpeg; if not, write to the Free Software
16cabdff1aSopenharmony_ci * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17cabdff1aSopenharmony_ci */
18cabdff1aSopenharmony_ci
19cabdff1aSopenharmony_ci#include <stdio.h>
20cabdff1aSopenharmony_ci
21cabdff1aSopenharmony_ci#include "libavutil/hwcontext.h"
22cabdff1aSopenharmony_ci
23cabdff1aSopenharmony_cistatic int test_derivation(AVBufferRef *src_ref, const char *src_name)
24cabdff1aSopenharmony_ci{
25cabdff1aSopenharmony_ci    enum AVHWDeviceType derived_type;
26cabdff1aSopenharmony_ci    const char *derived_name;
27cabdff1aSopenharmony_ci    AVBufferRef *derived_ref = NULL, *back_ref = NULL;
28cabdff1aSopenharmony_ci    AVHWDeviceContext *src_dev, *derived_dev;
29cabdff1aSopenharmony_ci    int err;
30cabdff1aSopenharmony_ci
31cabdff1aSopenharmony_ci    src_dev = (AVHWDeviceContext*)src_ref->data;
32cabdff1aSopenharmony_ci
33cabdff1aSopenharmony_ci    derived_type = AV_HWDEVICE_TYPE_NONE;
34cabdff1aSopenharmony_ci    while (1) {
35cabdff1aSopenharmony_ci        derived_type = av_hwdevice_iterate_types(derived_type);
36cabdff1aSopenharmony_ci        if (derived_type == AV_HWDEVICE_TYPE_NONE)
37cabdff1aSopenharmony_ci            break;
38cabdff1aSopenharmony_ci
39cabdff1aSopenharmony_ci        derived_name = av_hwdevice_get_type_name(derived_type);
40cabdff1aSopenharmony_ci
41cabdff1aSopenharmony_ci        err = av_hwdevice_ctx_create_derived(&derived_ref, derived_type,
42cabdff1aSopenharmony_ci                                             src_ref, 0);
43cabdff1aSopenharmony_ci        if (err < 0) {
44cabdff1aSopenharmony_ci            fprintf(stderr, "Unable to derive %s -> %s: %d.\n",
45cabdff1aSopenharmony_ci                    src_name, derived_name, err);
46cabdff1aSopenharmony_ci            continue;
47cabdff1aSopenharmony_ci        }
48cabdff1aSopenharmony_ci
49cabdff1aSopenharmony_ci        derived_dev = (AVHWDeviceContext*)derived_ref->data;
50cabdff1aSopenharmony_ci        if (derived_dev->type != derived_type) {
51cabdff1aSopenharmony_ci            fprintf(stderr, "Device derived as type %d has type %d.\n",
52cabdff1aSopenharmony_ci                    derived_type, derived_dev->type);
53cabdff1aSopenharmony_ci            goto fail;
54cabdff1aSopenharmony_ci        }
55cabdff1aSopenharmony_ci
56cabdff1aSopenharmony_ci        if (derived_type == src_dev->type) {
57cabdff1aSopenharmony_ci            if (derived_dev != src_dev) {
58cabdff1aSopenharmony_ci                fprintf(stderr, "Derivation of %s from itself succeeded "
59cabdff1aSopenharmony_ci                        "but did not return the same device.\n", src_name);
60cabdff1aSopenharmony_ci                goto fail;
61cabdff1aSopenharmony_ci            }
62cabdff1aSopenharmony_ci            av_buffer_unref(&derived_ref);
63cabdff1aSopenharmony_ci            continue;
64cabdff1aSopenharmony_ci        }
65cabdff1aSopenharmony_ci
66cabdff1aSopenharmony_ci        err = av_hwdevice_ctx_create_derived(&back_ref, src_dev->type,
67cabdff1aSopenharmony_ci                                             derived_ref, 0);
68cabdff1aSopenharmony_ci        if (err < 0) {
69cabdff1aSopenharmony_ci            fprintf(stderr, "Derivation %s to %s succeeded, but derivation "
70cabdff1aSopenharmony_ci                    "back again failed: %d.\n",
71cabdff1aSopenharmony_ci                    src_name, derived_name, err);
72cabdff1aSopenharmony_ci            goto fail;
73cabdff1aSopenharmony_ci        }
74cabdff1aSopenharmony_ci
75cabdff1aSopenharmony_ci        if (back_ref->data != src_ref->data) {
76cabdff1aSopenharmony_ci            fprintf(stderr, "Derivation %s to %s succeeded, but derivation "
77cabdff1aSopenharmony_ci                    "back again did not return the original device.\n",
78cabdff1aSopenharmony_ci                   src_name, derived_name);
79cabdff1aSopenharmony_ci            goto fail;
80cabdff1aSopenharmony_ci        }
81cabdff1aSopenharmony_ci
82cabdff1aSopenharmony_ci        fprintf(stderr, "Successfully tested derivation %s -> %s.\n",
83cabdff1aSopenharmony_ci                src_name, derived_name);
84cabdff1aSopenharmony_ci
85cabdff1aSopenharmony_ci        av_buffer_unref(&derived_ref);
86cabdff1aSopenharmony_ci        av_buffer_unref(&back_ref);
87cabdff1aSopenharmony_ci    }
88cabdff1aSopenharmony_ci
89cabdff1aSopenharmony_ci    return 0;
90cabdff1aSopenharmony_ci
91cabdff1aSopenharmony_cifail:
92cabdff1aSopenharmony_ci    av_buffer_unref(&derived_ref);
93cabdff1aSopenharmony_ci    av_buffer_unref(&back_ref);
94cabdff1aSopenharmony_ci    return -1;
95cabdff1aSopenharmony_ci}
96cabdff1aSopenharmony_ci
97cabdff1aSopenharmony_cistatic int test_device(enum AVHWDeviceType type, const char *name,
98cabdff1aSopenharmony_ci                       const char *device, AVDictionary *opts, int flags)
99cabdff1aSopenharmony_ci{
100cabdff1aSopenharmony_ci    AVBufferRef *ref;
101cabdff1aSopenharmony_ci    AVHWDeviceContext *dev;
102cabdff1aSopenharmony_ci    int err;
103cabdff1aSopenharmony_ci
104cabdff1aSopenharmony_ci    err = av_hwdevice_ctx_create(&ref, type, device, opts, flags);
105cabdff1aSopenharmony_ci    if (err < 0) {
106cabdff1aSopenharmony_ci        fprintf(stderr, "Failed to create %s device: %d.\n", name, err);
107cabdff1aSopenharmony_ci        return 1;
108cabdff1aSopenharmony_ci    }
109cabdff1aSopenharmony_ci
110cabdff1aSopenharmony_ci    dev = (AVHWDeviceContext*)ref->data;
111cabdff1aSopenharmony_ci    if (dev->type != type) {
112cabdff1aSopenharmony_ci        fprintf(stderr, "Device created as type %d has type %d.\n",
113cabdff1aSopenharmony_ci                type, dev->type);
114cabdff1aSopenharmony_ci        av_buffer_unref(&ref);
115cabdff1aSopenharmony_ci        return -1;
116cabdff1aSopenharmony_ci    }
117cabdff1aSopenharmony_ci
118cabdff1aSopenharmony_ci    fprintf(stderr, "Device type %s successfully created.\n", name);
119cabdff1aSopenharmony_ci
120cabdff1aSopenharmony_ci    err = test_derivation(ref, name);
121cabdff1aSopenharmony_ci
122cabdff1aSopenharmony_ci    av_buffer_unref(&ref);
123cabdff1aSopenharmony_ci
124cabdff1aSopenharmony_ci    return err;
125cabdff1aSopenharmony_ci}
126cabdff1aSopenharmony_ci
127cabdff1aSopenharmony_cistatic const struct {
128cabdff1aSopenharmony_ci    enum AVHWDeviceType type;
129cabdff1aSopenharmony_ci    const char *possible_devices[5];
130cabdff1aSopenharmony_ci} test_devices[] = {
131cabdff1aSopenharmony_ci    { AV_HWDEVICE_TYPE_CUDA,
132cabdff1aSopenharmony_ci      { "0", "1", "2" } },
133cabdff1aSopenharmony_ci    { AV_HWDEVICE_TYPE_DRM,
134cabdff1aSopenharmony_ci      { "/dev/dri/card0", "/dev/dri/card1",
135cabdff1aSopenharmony_ci        "/dev/dri/renderD128", "/dev/dri/renderD129" } },
136cabdff1aSopenharmony_ci    { AV_HWDEVICE_TYPE_DXVA2,
137cabdff1aSopenharmony_ci      { "0", "1", "2" } },
138cabdff1aSopenharmony_ci    { AV_HWDEVICE_TYPE_D3D11VA,
139cabdff1aSopenharmony_ci      { "0", "1", "2" } },
140cabdff1aSopenharmony_ci    { AV_HWDEVICE_TYPE_OPENCL,
141cabdff1aSopenharmony_ci      { "0.0", "0.1", "1.0", "1.1" } },
142cabdff1aSopenharmony_ci    { AV_HWDEVICE_TYPE_VAAPI,
143cabdff1aSopenharmony_ci      { "/dev/dri/renderD128", "/dev/dri/renderD129", ":0" } },
144cabdff1aSopenharmony_ci};
145cabdff1aSopenharmony_ci
146cabdff1aSopenharmony_cistatic int test_device_type(enum AVHWDeviceType type)
147cabdff1aSopenharmony_ci{
148cabdff1aSopenharmony_ci    enum AVHWDeviceType check;
149cabdff1aSopenharmony_ci    const char *name;
150cabdff1aSopenharmony_ci    int i, j, found, err;
151cabdff1aSopenharmony_ci
152cabdff1aSopenharmony_ci    name = av_hwdevice_get_type_name(type);
153cabdff1aSopenharmony_ci    if (!name) {
154cabdff1aSopenharmony_ci        fprintf(stderr, "No name available for device type %d.\n", type);
155cabdff1aSopenharmony_ci        return -1;
156cabdff1aSopenharmony_ci    }
157cabdff1aSopenharmony_ci
158cabdff1aSopenharmony_ci    check = av_hwdevice_find_type_by_name(name);
159cabdff1aSopenharmony_ci    if (check != type) {
160cabdff1aSopenharmony_ci        fprintf(stderr, "Type %d maps to name %s maps to type %d.\n",
161cabdff1aSopenharmony_ci               type, name, check);
162cabdff1aSopenharmony_ci        return -1;
163cabdff1aSopenharmony_ci    }
164cabdff1aSopenharmony_ci
165cabdff1aSopenharmony_ci    found = 0;
166cabdff1aSopenharmony_ci
167cabdff1aSopenharmony_ci    err = test_device(type, name, NULL, NULL, 0);
168cabdff1aSopenharmony_ci    if (err < 0) {
169cabdff1aSopenharmony_ci        fprintf(stderr, "Test failed for %s with default options.\n", name);
170cabdff1aSopenharmony_ci        return -1;
171cabdff1aSopenharmony_ci    }
172cabdff1aSopenharmony_ci    if (err == 0) {
173cabdff1aSopenharmony_ci        fprintf(stderr, "Test passed for %s with default options.\n", name);
174cabdff1aSopenharmony_ci        ++found;
175cabdff1aSopenharmony_ci    }
176cabdff1aSopenharmony_ci
177cabdff1aSopenharmony_ci    for (i = 0; i < FF_ARRAY_ELEMS(test_devices); i++) {
178cabdff1aSopenharmony_ci        if (test_devices[i].type != type)
179cabdff1aSopenharmony_ci            continue;
180cabdff1aSopenharmony_ci
181cabdff1aSopenharmony_ci        for (j = 0; test_devices[i].possible_devices[j]; j++) {
182cabdff1aSopenharmony_ci            err = test_device(type, name,
183cabdff1aSopenharmony_ci                              test_devices[i].possible_devices[j],
184cabdff1aSopenharmony_ci                              NULL, 0);
185cabdff1aSopenharmony_ci            if (err < 0) {
186cabdff1aSopenharmony_ci                fprintf(stderr, "Test failed for %s with device %s.\n",
187cabdff1aSopenharmony_ci                       name, test_devices[i].possible_devices[j]);
188cabdff1aSopenharmony_ci                return -1;
189cabdff1aSopenharmony_ci            }
190cabdff1aSopenharmony_ci            if (err == 0) {
191cabdff1aSopenharmony_ci                fprintf(stderr, "Test passed for %s with device %s.\n",
192cabdff1aSopenharmony_ci                        name, test_devices[i].possible_devices[j]);
193cabdff1aSopenharmony_ci                ++found;
194cabdff1aSopenharmony_ci            }
195cabdff1aSopenharmony_ci        }
196cabdff1aSopenharmony_ci    }
197cabdff1aSopenharmony_ci
198cabdff1aSopenharmony_ci    return !found;
199cabdff1aSopenharmony_ci}
200cabdff1aSopenharmony_ci
201cabdff1aSopenharmony_ciint main(void)
202cabdff1aSopenharmony_ci{
203cabdff1aSopenharmony_ci    enum AVHWDeviceType type = AV_HWDEVICE_TYPE_NONE;
204cabdff1aSopenharmony_ci    int pass, fail, skip, err;
205cabdff1aSopenharmony_ci
206cabdff1aSopenharmony_ci    pass = fail = skip = 0;
207cabdff1aSopenharmony_ci    while (1) {
208cabdff1aSopenharmony_ci        type = av_hwdevice_iterate_types(type);
209cabdff1aSopenharmony_ci        if (type == AV_HWDEVICE_TYPE_NONE)
210cabdff1aSopenharmony_ci            break;
211cabdff1aSopenharmony_ci
212cabdff1aSopenharmony_ci        err = test_device_type(type);
213cabdff1aSopenharmony_ci        if (err == 0)
214cabdff1aSopenharmony_ci            ++pass;
215cabdff1aSopenharmony_ci        else if (err < 0)
216cabdff1aSopenharmony_ci            ++fail;
217cabdff1aSopenharmony_ci        else
218cabdff1aSopenharmony_ci            ++skip;
219cabdff1aSopenharmony_ci    }
220cabdff1aSopenharmony_ci
221cabdff1aSopenharmony_ci    fprintf(stderr, "Attempted to test %d device types: "
222cabdff1aSopenharmony_ci            "%d passed, %d failed, %d skipped.\n",
223cabdff1aSopenharmony_ci            pass + fail + skip, pass, fail, skip);
224cabdff1aSopenharmony_ci
225cabdff1aSopenharmony_ci    return fail > 0;
226cabdff1aSopenharmony_ci}
227