FFmpeg
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 
25 static 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 
52 static HWDevice *hw_device_add(void)
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 
92 int 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  }
120  type = av_hwdevice_find_type_by_name(type_name);
121  if (type == AV_HWDEVICE_TYPE_NONE) {
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;
225 done:
226  av_freep(&type_name);
227  av_freep(&name);
228  av_freep(&device);
230  return err;
231 invalid:
233  "Invalid device specification \"%s\": %s\n", arg, errmsg);
234  err = AVERROR(EINVAL);
235  goto done;
236 fail:
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 
280 fail:
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);
292  av_freep(&hw_devices[i]);
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.
302  if (filter_hw_device)
304  else if (nb_hw_devices > 0) {
305  HWDevice *dev = hw_devices[nb_hw_devices - 1];
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,
313  av_hwdevice_get_type_name(dev->type), dev->name);
314 
315  return dev->device_ref;
316  }
317 
318  return NULL;
319 }
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
name
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf default minimum maximum flags name is the option name
Definition: writing_filters.txt:88
AVERROR
Filter the word “frame” indicates either a video frame or a group of audio as stored in an AVFrame structure Format for each input and each output the list of supported formats For video that means pixel format For audio that means channel sample they are references to shared objects When the negotiation mechanism computes the intersection of the formats supported at each end of a all references to both lists are replaced with a reference to the intersection And when a single format is eventually chosen for a link amongst the remaining all references to the list are updated That means that if a filter requires that its input and output have the same format amongst a supported all it has to do is use a reference to the same list of formats query_formats can leave some formats unset and return AVERROR(EAGAIN) to cause the negotiation mechanism toagain later. That can be used by filters with complex requirements to use the format negotiated on one link to set the formats supported on another. Frame references ownership and permissions
hw_device_init_from_type
int hw_device_init_from_type(enum AVHWDeviceType type, const char *device, HWDevice **dev_out)
Definition: ffmpeg_hw.c:243
AV_HWDEVICE_TYPE_NONE
@ AV_HWDEVICE_TYPE_NONE
Definition: hwcontext.h:28
av_hwdevice_find_type_by_name
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition: hwcontext.c:102
ffmpeg.h
AVDictionary
Definition: dict.c:34
HWDevice
Definition: ffmpeg.h:109
hw_device_default_name
static char * hw_device_default_name(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:67
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
fail
#define fail()
Definition: checkasm.h:185
type
it s the only field you need to keep assuming you have a context There is some magic you don t need to care about around this just let it vf type
Definition: writing_filters.txt:86
hw_device_free_all
void hw_device_free_all(void)
Definition: ffmpeg_hw.c:286
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
nb_hw_devices
static int nb_hw_devices
Definition: ffmpeg_hw.c:25
AVHWDeviceType
AVHWDeviceType
Definition: hwcontext.h:27
hw_device_for_filter
AVBufferRef * hw_device_for_filter(void)
Get a hardware device to be used with this filtergraph.
Definition: ffmpeg_hw.c:298
av_hwdevice_get_type_name
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition: hwcontext.c:112
hw_device_get_by_name
HWDevice * hw_device_get_by_name(const char *name)
Definition: ffmpeg_hw.c:42
arg
const char * arg
Definition: jacosubdec.c:67
NULL
#define NULL
Definition: coverity.c:32
av_buffer_unref
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
hw_devices
static HWDevice ** hw_devices
Definition: ffmpeg_hw.c:26
hw_device_add
static HWDevice * hw_device_add(void)
Definition: ffmpeg_hw.c:52
index
int index
Definition: gxfenc.c:90
options
const OptionDef options[]
HWDevice::device_ref
AVBufferRef * device_ref
Definition: ffmpeg.h:112
av_reallocp_array
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
av_dict_free
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:223
av_hwdevice_ctx_create_derived
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:703
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:256
av_mallocz
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:256
av_hwdevice_ctx_create
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:600
filter_hw_device
HWDevice * filter_hw_device
Definition: ffmpeg_opt.c:50
HWDevice::name
const char * name
Definition: ffmpeg.h:110
av_dict_parse_string
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:200
hw_device_init_from_string
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
Definition: ffmpeg_hw.c:92
mem.h
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
HWDevice::type
enum AVHWDeviceType type
Definition: ffmpeg.h:111
src
INIT_CLIP pixel * src
Definition: h264pred_template.c:418
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
hw_device_get_by_type
HWDevice * hw_device_get_by_type(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:28
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:284
snprintf
#define snprintf
Definition: snprintf.h:34