FFmpeg
Loading...
Searching...
No Matches
ffmpeg_hw.c
Go to the documentation of this file.
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 <string.h>
20
21#include "libavutil/mem.h"
22
23#include "ffmpeg.h"
24
25static int nb_hw_devices;
27
29{
30 HWDevice *found = NULL;
31 int i;
32 for (i = 0; i < nb_hw_devices; i++) {
33 if (hw_devices[i]->type == type) {
34 if (found)
35 return NULL;
36 found = hw_devices[i];
37 }
38 }
39 return found;
40}
41
43{
44 int i;
45 for (i = 0; i < nb_hw_devices; i++) {
46 if (!strcmp(hw_devices[i]->name, name))
47 return hw_devices[i];
48 }
49 return NULL;
50}
51
53{
54 int err;
56 sizeof(*hw_devices));
57 if (err) {
58 nb_hw_devices = 0;
59 return NULL;
60 }
63 return NULL;
64 return hw_devices[nb_hw_devices++];
65}
66
68{
69 // Make an automatic name of the form "type%d". We arbitrarily
70 // limit at 1000 anonymous devices of the same type - there is
71 // probably something else very wrong if you get to this limit.
72 const char *type_name = av_hwdevice_get_type_name(type);
73 char *name;
74 size_t index_pos;
75 int index, index_limit = 1000;
76 index_pos = strlen(type_name);
77 name = av_malloc(index_pos + 4);
78 if (!name)
79 return NULL;
80 for (index = 0; index < index_limit; index++) {
81 snprintf(name, index_pos + 4, "%s%d", type_name, index);
83 break;
84 }
85 if (index >= index_limit) {
86 av_freep(&name);
87 return NULL;
88 }
89 return name;
90}
91
92int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
93{
94 // "type=name"
95 // "type=name,key=value,key2=value2"
96 // "type=name:device,key=value,key2=value2"
97 // "type:device,key=value,key2=value2"
98 // -> av_hwdevice_ctx_create()
99 // "type=name@name"
100 // "type@name"
101 // -> av_hwdevice_ctx_create_derived()
102
104 const char *type_name = NULL, *name = NULL, *device = NULL;
105 enum AVHWDeviceType type;
106 HWDevice *dev, *src;
107 AVBufferRef *device_ref = NULL;
108 int err;
109 const char *errmsg, *p, *q;
110 size_t k;
111
112 k = strcspn(arg, ":=@");
113 p = arg + k;
114
115 type_name = av_strndup(arg, k);
116 if (!type_name) {
117 err = AVERROR(ENOMEM);
118 goto fail;
119 }
122 errmsg = "unknown device type";
123 goto invalid;
124 }
125
126 if (*p == '=') {
127 k = strcspn(p + 1, ":@,");
128
129 name = av_strndup(p + 1, k);
130 if (!name) {
131 err = AVERROR(ENOMEM);
132 goto fail;
133 }
135 errmsg = "named device already exists";
136 goto invalid;
137 }
138
139 p += 1 + k;
140 } else {
142 if (!name) {
143 err = AVERROR(ENOMEM);
144 goto fail;
145 }
146 }
147
148 if (!*p) {
149 // New device with no parameters.
150 err = av_hwdevice_ctx_create(&device_ref, type,
151 NULL, NULL, 0);
152 if (err < 0)
153 goto fail;
154
155 } else if (*p == ':') {
156 // New device with some parameters.
157 ++p;
158 q = strchr(p, ',');
159 if (q) {
160 if (q - p > 0) {
161 device = av_strndup(p, q - p);
162 if (!device) {
163 err = AVERROR(ENOMEM);
164 goto fail;
165 }
166 }
167 err = av_dict_parse_string(&options, q + 1, "=", ",", 0);
168 if (err < 0) {
169 errmsg = "failed to parse options";
170 goto invalid;
171 }
172 }
173
174 err = av_hwdevice_ctx_create(&device_ref, type,
175 q ? device : p[0] ? p : NULL,
176 options, 0);
177 if (err < 0)
178 goto fail;
179
180 } else if (*p == '@') {
181 // Derive from existing device.
182
183 src = hw_device_get_by_name(p + 1);
184 if (!src) {
185 errmsg = "invalid source device name";
186 goto invalid;
187 }
188
189 err = av_hwdevice_ctx_create_derived(&device_ref, type,
190 src->device_ref, 0);
191 if (err < 0)
192 goto fail;
193 } else if (*p == ',') {
194 err = av_dict_parse_string(&options, p + 1, "=", ",", 0);
195
196 if (err < 0) {
197 errmsg = "failed to parse options";
198 goto invalid;
199 }
200
201 err = av_hwdevice_ctx_create(&device_ref, type,
202 NULL, options, 0);
203 if (err < 0)
204 goto fail;
205 } else {
206 errmsg = "parse error";
207 goto invalid;
208 }
209
210 dev = hw_device_add();
211 if (!dev) {
212 err = AVERROR(ENOMEM);
213 goto fail;
214 }
215
216 dev->name = name;
217 dev->type = type;
218 dev->device_ref = device_ref;
219
220 if (dev_out)
221 *dev_out = dev;
222
223 name = NULL;
224 err = 0;
225done:
226 av_freep(&type_name);
227 av_freep(&name);
228 av_freep(&device);
230 return err;
231invalid:
233 "Invalid device specification \"%s\": %s\n", arg, errmsg);
234 err = AVERROR(EINVAL);
235 goto done;
236fail:
238 "Device creation failed: %d.\n", err);
239 av_buffer_unref(&device_ref);
240 goto done;
241}
242
244 const char *device,
245 HWDevice **dev_out)
246{
247 AVBufferRef *device_ref = NULL;
248 HWDevice *dev;
249 char *name;
250 int err;
251
253 if (!name) {
254 err = AVERROR(ENOMEM);
255 goto fail;
256 }
257
258 err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
259 if (err < 0) {
261 "Device creation failed: %d.\n", err);
262 goto fail;
263 }
264
265 dev = hw_device_add();
266 if (!dev) {
267 err = AVERROR(ENOMEM);
268 goto fail;
269 }
270
271 dev->name = name;
272 dev->type = type;
273 dev->device_ref = device_ref;
274
275 if (dev_out)
276 *dev_out = dev;
277
278 return 0;
279
280fail:
281 av_freep(&name);
282 av_buffer_unref(&device_ref);
283 return err;
284}
285
287{
288 int i;
289 for (i = 0; i < nb_hw_devices; i++) {
291 av_buffer_unref(&hw_devices[i]->device_ref);
293 }
295 nb_hw_devices = 0;
296}
297
299{
300 // Pick the last hardware device if the user doesn't pick the device for
301 // filters explicitly with the filter_hw_device option.
303 return filter_hw_device->device_ref;
304 else if (nb_hw_devices > 0) {
306
307 if (nb_hw_devices > 1)
308 av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device "
309 "%s of type %s is picked for filters by default. Set hardware "
310 "device explicitly with the filter_hw_device option if device "
311 "%s is not usable for filters.\n",
312 nb_hw_devices, dev->name,
314
315 return dev->device_ref;
316 }
317
318 return NULL;
319}
#define i(width, name, range_min, range_max)
Definition cbs_h264.c:63
#define NULL
Definition coverity.c:32
HWDevice * filter_hw_device
Definition ffmpeg_opt.c:52
static HWDevice ** hw_devices
Definition ffmpeg_hw.c:26
static int nb_hw_devices
Definition ffmpeg_hw.c:25
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
Definition ffmpeg_hw.c:92
AVBufferRef * hw_device_for_filter(void)
Get a hardware device to be used with this filtergraph.
Definition ffmpeg_hw.c:298
HWDevice * hw_device_get_by_name(const char *name)
Definition ffmpeg_hw.c:42
void hw_device_free_all(void)
Definition ffmpeg_hw.c:286
int hw_device_init_from_type(enum AVHWDeviceType type, const char *device, HWDevice **dev_out)
Definition ffmpeg_hw.c:243
static HWDevice * hw_device_add(void)
Definition ffmpeg_hw.c:52
HWDevice * hw_device_get_by_type(enum AVHWDeviceType type)
Definition ffmpeg_hw.c:28
static char * hw_device_default_name(enum AVHWDeviceType type)
Definition ffmpeg_hw.c:67
#define fail
Definition test.h:479
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
Definition buffer.c:139
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition dict.c:233
int av_dict_parse_string(AVDictionary **pm, const char *str, const char *key_val_sep, const char *pairs_sep, int flags)
Parse the key/value pairs list and add the parsed entries to a dictionary.
Definition dict.c:210
#define AVERROR(e)
Definition error.h:45
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition log.h:216
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition log.h:210
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition mem.c:284
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate an array through a pointer to a pointer.
Definition mem.c:225
int index
Definition gxfenc.c:90
int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type, const char *device, AVDictionary *opts, int flags)
Open a device of the specified type and create an AVHWDeviceContext for it.
Definition hwcontext.c:615
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition hwcontext.c:120
int av_hwdevice_ctx_create_derived(AVBufferRef **dst_ref_ptr, enum AVHWDeviceType type, AVBufferRef *src_ref, int flags)
Create a new device of the specified type from an existing device.
Definition hwcontext.c:718
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition hwcontext.c:110
AVHWDeviceType
Definition hwcontext.h:27
@ AV_HWDEVICE_TYPE_NONE
Definition hwcontext.h:28
cl_device_type type
const char * arg
Definition jacosubdec.c:65
Memory handling functions.
#define av_malloc(s)
Definition ops_static.c:52
const char * name
Definition qsvenc.c:142
#define snprintf
Definition snprintf.h:34
A reference to a data buffer.
Definition buffer.h:82
AVBufferRef * device_ref
Definition ffmpeg.h:100
enum AVHWDeviceType type
Definition ffmpeg.h:99
const char * name
Definition ffmpeg.h:98
#define av_mallocz(s)
#define av_freep(p)
#define av_log(a,...)
#define src
Definition vp8dsp.c:248