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  InputStream *ist = avctx->opaque;
303  AVFrame *output = NULL;
305  int err;
306 
307  if (input->format == output_format) {
308  // Nothing to do.
309  return 0;
310  }
311 
313  if (!output)
314  return AVERROR(ENOMEM);
315 
316  output->format = output_format;
317 
319  if (err < 0) {
320  av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to "
321  "output frame: %d.\n", err);
322  goto fail;
323  }
324 
326  if (err < 0) {
328  goto fail;
329  }
330 
334 
335  return 0;
336 
337 fail:
339  return err;
340 }
341 
343 {
344  // Pick the last hardware device if the user doesn't pick the device for
345  // filters explicitly with the filter_hw_device option.
346  if (filter_hw_device)
348  else if (nb_hw_devices > 0) {
349  HWDevice *dev = hw_devices[nb_hw_devices - 1];
350 
351  if (nb_hw_devices > 1)
352  av_log(NULL, AV_LOG_WARNING, "There are %d hardware devices. device "
353  "%s of type %s is picked for filters by default. Set hardware "
354  "device explicitly with the filter_hw_device option if device "
355  "%s is not usable for filters.\n",
356  nb_hw_devices, dev->name,
357  av_hwdevice_get_type_name(dev->type), dev->name);
358 
359  return dev->device_ref;
360  }
361 
362  return NULL;
363 }
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
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
output
filter_frame For filters that do not use the this method is called when a frame is pushed to the filter s input It can be called at any time except in a reentrant way If the input frame is enough to produce output
Definition: filter_design.txt:225
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:100
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:340
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:83
ffmpeg.h
AVDictionary
Definition: dict.c:34
HWDevice
Definition: ffmpeg.h:83
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
InputStream
Definition: ffmpeg.h:324
fail
#define fail()
Definition: checkasm.h:138
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
hwaccel_retrieve_data
int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
Definition: ffmpeg_hw.c:300
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:88
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:342
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:93
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_frame_copy_props
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:736
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
InputStream::hwaccel_output_format
enum AVPixelFormat hwaccel_output_format
Definition: ffmpeg.h:385
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:86
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:225
input
and forward the test the status of outputs and forward it to the corresponding return FFERROR_NOT_READY If the filters stores internally one or a few frame for some input
Definition: filter_design.txt:172
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:719
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:255
av_frame_move_ref
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition: frame.c:649
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:622
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:615
AVCodecContext::opaque
void * opaque
Private data of the user, can be used to carry app specific stuff.
Definition: avcodec.h:483
av_hwframe_transfer_data
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:448
filter_hw_device
HWDevice * filter_hw_device
Definition: ffmpeg_opt.c:63
AVCodecContext
main external API structure.
Definition: avcodec.h:441
HWDevice::name
const char * name
Definition: ffmpeg.h:84
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:202
output_format
static char * output_format
Definition: ffprobe.c:143
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:85
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