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/avstring.h"
22 #include "libavutil/pixdesc.h"
23 #include "libavfilter/buffersink.h"
24 
25 #include "ffmpeg.h"
26 
27 static int nb_hw_devices;
29 
31 {
32  HWDevice *found = NULL;
33  int i;
34  for (i = 0; i < nb_hw_devices; i++) {
35  if (hw_devices[i]->type == type) {
36  if (found)
37  return NULL;
38  found = hw_devices[i];
39  }
40  }
41  return found;
42 }
43 
45 {
46  int i;
47  for (i = 0; i < nb_hw_devices; i++) {
48  if (!strcmp(hw_devices[i]->name, name))
49  return hw_devices[i];
50  }
51  return NULL;
52 }
53 
54 static HWDevice *hw_device_add(void)
55 {
56  int err;
58  sizeof(*hw_devices));
59  if (err) {
60  nb_hw_devices = 0;
61  return NULL;
62  }
65  return NULL;
66  return hw_devices[nb_hw_devices++];
67 }
68 
70 {
71  // Make an automatic name of the form "type%d". We arbitrarily
72  // limit at 1000 anonymous devices of the same type - there is
73  // probably something else very wrong if you get to this limit.
74  const char *type_name = av_hwdevice_get_type_name(type);
75  char *name;
76  size_t index_pos;
77  int index, index_limit = 1000;
78  index_pos = strlen(type_name);
79  name = av_malloc(index_pos + 4);
80  if (!name)
81  return NULL;
82  for (index = 0; index < index_limit; index++) {
83  snprintf(name, index_pos + 4, "%s%d", type_name, index);
85  break;
86  }
87  if (index >= index_limit) {
88  av_freep(&name);
89  return NULL;
90  }
91  return name;
92 }
93 
94 int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
95 {
96  // "type=name"
97  // "type=name,key=value,key2=value2"
98  // "type=name:device,key=value,key2=value2"
99  // "type:device,key=value,key2=value2"
100  // -> av_hwdevice_ctx_create()
101  // "type=name@name"
102  // "type@name"
103  // -> av_hwdevice_ctx_create_derived()
104 
106  const char *type_name = NULL, *name = NULL, *device = NULL;
107  enum AVHWDeviceType type;
108  HWDevice *dev, *src;
109  AVBufferRef *device_ref = NULL;
110  int err;
111  const char *errmsg, *p, *q;
112  size_t k;
113 
114  k = strcspn(arg, ":=@");
115  p = arg + k;
116 
117  type_name = av_strndup(arg, k);
118  if (!type_name) {
119  err = AVERROR(ENOMEM);
120  goto fail;
121  }
122  type = av_hwdevice_find_type_by_name(type_name);
123  if (type == AV_HWDEVICE_TYPE_NONE) {
124  errmsg = "unknown device type";
125  goto invalid;
126  }
127 
128  if (*p == '=') {
129  k = strcspn(p + 1, ":@,");
130 
131  name = av_strndup(p + 1, k);
132  if (!name) {
133  err = AVERROR(ENOMEM);
134  goto fail;
135  }
137  errmsg = "named device already exists";
138  goto invalid;
139  }
140 
141  p += 1 + k;
142  } else {
144  if (!name) {
145  err = AVERROR(ENOMEM);
146  goto fail;
147  }
148  }
149 
150  if (!*p) {
151  // New device with no parameters.
152  err = av_hwdevice_ctx_create(&device_ref, type,
153  NULL, NULL, 0);
154  if (err < 0)
155  goto fail;
156 
157  } else if (*p == ':') {
158  // New device with some parameters.
159  ++p;
160  q = strchr(p, ',');
161  if (q) {
162  if (q - p > 0) {
163  device = av_strndup(p, q - p);
164  if (!device) {
165  err = AVERROR(ENOMEM);
166  goto fail;
167  }
168  }
169  err = av_dict_parse_string(&options, q + 1, "=", ",", 0);
170  if (err < 0) {
171  errmsg = "failed to parse options";
172  goto invalid;
173  }
174  }
175 
176  err = av_hwdevice_ctx_create(&device_ref, type,
177  q ? device : p[0] ? p : NULL,
178  options, 0);
179  if (err < 0)
180  goto fail;
181 
182  } else if (*p == '@') {
183  // Derive from existing device.
184 
185  src = hw_device_get_by_name(p + 1);
186  if (!src) {
187  errmsg = "invalid source device name";
188  goto invalid;
189  }
190 
191  err = av_hwdevice_ctx_create_derived(&device_ref, type,
192  src->device_ref, 0);
193  if (err < 0)
194  goto fail;
195  } else if (*p == ',') {
196  err = av_dict_parse_string(&options, p + 1, "=", ",", 0);
197 
198  if (err < 0) {
199  errmsg = "failed to parse options";
200  goto invalid;
201  }
202 
203  err = av_hwdevice_ctx_create(&device_ref, type,
204  NULL, options, 0);
205  if (err < 0)
206  goto fail;
207  } else {
208  errmsg = "parse error";
209  goto invalid;
210  }
211 
212  dev = hw_device_add();
213  if (!dev) {
214  err = AVERROR(ENOMEM);
215  goto fail;
216  }
217 
218  dev->name = name;
219  dev->type = type;
220  dev->device_ref = device_ref;
221 
222  if (dev_out)
223  *dev_out = dev;
224 
225  name = NULL;
226  err = 0;
227 done:
228  av_freep(&type_name);
229  av_freep(&name);
230  av_freep(&device);
232  return err;
233 invalid:
235  "Invalid device specification \"%s\": %s\n", arg, errmsg);
236  err = AVERROR(EINVAL);
237  goto done;
238 fail:
240  "Device creation failed: %d.\n", err);
241  av_buffer_unref(&device_ref);
242  goto done;
243 }
244 
246  const char *device,
247  HWDevice **dev_out)
248 {
249  AVBufferRef *device_ref = NULL;
250  HWDevice *dev;
251  char *name;
252  int err;
253 
255  if (!name) {
256  err = AVERROR(ENOMEM);
257  goto fail;
258  }
259 
260  err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
261  if (err < 0) {
263  "Device creation failed: %d.\n", err);
264  goto fail;
265  }
266 
267  dev = hw_device_add();
268  if (!dev) {
269  err = AVERROR(ENOMEM);
270  goto fail;
271  }
272 
273  dev->name = name;
274  dev->type = type;
275  dev->device_ref = device_ref;
276 
277  if (dev_out)
278  *dev_out = dev;
279 
280  return 0;
281 
282 fail:
283  av_freep(&name);
284  av_buffer_unref(&device_ref);
285  return err;
286 }
287 
289 {
290  int i;
291  for (i = 0; i < nb_hw_devices; i++) {
293  av_buffer_unref(&hw_devices[i]->device_ref);
294  av_freep(&hw_devices[i]);
295  }
297  nb_hw_devices = 0;
298 }
299 
301 {
302  // Pick the last hardware device if the user doesn't pick the device for
303  // filters explicitly with the filter_hw_device option.
304  if (filter_hw_device)
306  else if (nb_hw_devices > 0) {
307  HWDevice *dev = hw_devices[nb_hw_devices - 1];
308 
309  if (nb_hw_devices > 1)
310  av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device "
311  "%s of type %s is picked for filters by default. Set hardware "
312  "device explicitly with the filter_hw_device option if device "
313  "%s is not usable for filters.\n",
314  nb_hw_devices, dev->name,
315  av_hwdevice_get_type_name(dev->type), dev->name);
316 
317  return dev->device_ref;
318  }
319 
320  return NULL;
321 }
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:245
pixdesc.h
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:69
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
fail
#define fail()
Definition: checkasm.h:179
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:288
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:27
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:300
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:44
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:28
hw_device_add
static HWDevice * hw_device_add(void)
Definition: ffmpeg_hw.c:54
index
int index
Definition: gxfenc.c:89
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:223
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
buffersink.h
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:255
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:254
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:57
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:94
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
avstring.h
hw_device_get_by_type
HWDevice * hw_device_get_by_type(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:30
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:282
snprintf
#define snprintf
Definition: snprintf.h:34