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