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 
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;
55  err = av_reallocp_array(&hw_devices, nb_hw_devices + 1,
56  sizeof(*hw_devices));
57  if (err) {
58  nb_hw_devices = 0;
59  return NULL;
60  }
61  hw_devices[nb_hw_devices] = av_mallocz(sizeof(HWDevice));
62  if (!hw_devices[nb_hw_devices])
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);
82  if (!hw_device_get_by_name(name))
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:device,key=value,key2=value2"
95  // "type:device,key=value,key2=value2"
96  // -> av_hwdevice_ctx_create()
97  // "type=name@name"
98  // "type@name"
99  // -> av_hwdevice_ctx_create_derived()
100 
102  const char *type_name = NULL, *name = NULL, *device = NULL;
103  enum AVHWDeviceType type;
104  HWDevice *dev, *src;
105  AVBufferRef *device_ref = NULL;
106  int err;
107  const char *errmsg, *p, *q;
108  size_t k;
109 
110  k = strcspn(arg, ":=@");
111  p = arg + k;
112 
113  type_name = av_strndup(arg, k);
114  if (!type_name) {
115  err = AVERROR(ENOMEM);
116  goto fail;
117  }
118  type = av_hwdevice_find_type_by_name(type_name);
119  if (type == AV_HWDEVICE_TYPE_NONE) {
120  errmsg = "unknown device type";
121  goto invalid;
122  }
123 
124  if (*p == '=') {
125  k = strcspn(p + 1, ":@");
126 
127  name = av_strndup(p + 1, k);
128  if (!name) {
129  err = AVERROR(ENOMEM);
130  goto fail;
131  }
132  if (hw_device_get_by_name(name)) {
133  errmsg = "named device already exists";
134  goto invalid;
135  }
136 
137  p += 1 + k;
138  } else {
139  name = hw_device_default_name(type);
140  if (!name) {
141  err = AVERROR(ENOMEM);
142  goto fail;
143  }
144  }
145 
146  if (!*p) {
147  // New device with no parameters.
148  err = av_hwdevice_ctx_create(&device_ref, type,
149  NULL, NULL, 0);
150  if (err < 0)
151  goto fail;
152 
153  } else if (*p == ':') {
154  // New device with some parameters.
155  ++p;
156  q = strchr(p, ',');
157  if (q) {
158  if (q - p > 0) {
159  device = av_strndup(p, q - p);
160  if (!device) {
161  err = AVERROR(ENOMEM);
162  goto fail;
163  }
164  }
165  err = av_dict_parse_string(&options, q + 1, "=", ",", 0);
166  if (err < 0) {
167  errmsg = "failed to parse options";
168  goto invalid;
169  }
170  }
171 
172  err = av_hwdevice_ctx_create(&device_ref, type,
173  q ? device : p[0] ? p : NULL,
174  options, 0);
175  if (err < 0)
176  goto fail;
177 
178  } else if (*p == '@') {
179  // Derive from existing device.
180 
181  src = hw_device_get_by_name(p + 1);
182  if (!src) {
183  errmsg = "invalid source device name";
184  goto invalid;
185  }
186 
187  err = av_hwdevice_ctx_create_derived(&device_ref, type,
188  src->device_ref, 0);
189  if (err < 0)
190  goto fail;
191  } else {
192  errmsg = "parse error";
193  goto invalid;
194  }
195 
196  dev = hw_device_add();
197  if (!dev) {
198  err = AVERROR(ENOMEM);
199  goto fail;
200  }
201 
202  dev->name = name;
203  dev->type = type;
204  dev->device_ref = device_ref;
205 
206  if (dev_out)
207  *dev_out = dev;
208 
209  name = NULL;
210  err = 0;
211 done:
212  av_freep(&type_name);
213  av_freep(&name);
214  av_freep(&device);
215  av_dict_free(&options);
216  return err;
217 invalid:
219  "Invalid device specification \"%s\": %s\n", arg, errmsg);
220  err = AVERROR(EINVAL);
221  goto done;
222 fail:
224  "Device creation failed: %d.\n", err);
225  av_buffer_unref(&device_ref);
226  goto done;
227 }
228 
230  const char *device,
231  HWDevice **dev_out)
232 {
233  AVBufferRef *device_ref = NULL;
234  HWDevice *dev;
235  char *name;
236  int err;
237 
238  name = hw_device_default_name(type);
239  if (!name) {
240  err = AVERROR(ENOMEM);
241  goto fail;
242  }
243 
244  err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
245  if (err < 0) {
247  "Device creation failed: %d.\n", err);
248  goto fail;
249  }
250 
251  dev = hw_device_add();
252  if (!dev) {
253  err = AVERROR(ENOMEM);
254  goto fail;
255  }
256 
257  dev->name = name;
258  dev->type = type;
259  dev->device_ref = device_ref;
260 
261  if (dev_out)
262  *dev_out = dev;
263 
264  return 0;
265 
266 fail:
267  av_freep(&name);
268  av_buffer_unref(&device_ref);
269  return err;
270 }
271 
273 {
274  int i;
275  for (i = 0; i < nb_hw_devices; i++) {
276  av_freep(&hw_devices[i]->name);
277  av_buffer_unref(&hw_devices[i]->device_ref);
278  av_freep(&hw_devices[i]);
279  }
280  av_freep(&hw_devices);
281  nb_hw_devices = 0;
282 }
283 
285 {
286  const AVCodecHWConfig *config;
287  HWDevice *dev;
288  int i;
289  for (i = 0;; i++) {
290  config = avcodec_get_hw_config(codec, i);
291  if (!config)
292  return NULL;
294  continue;
295  dev = hw_device_get_by_type(config->device_type);
296  if (dev)
297  return dev;
298  }
299 }
300 
302 {
303  const AVCodecHWConfig *config;
304  enum AVHWDeviceType type;
305  HWDevice *dev = NULL;
306  int err, auto_device = 0;
307 
308  if (ist->hwaccel_device) {
310  if (!dev) {
311  if (ist->hwaccel_id == HWACCEL_AUTO) {
312  auto_device = 1;
313  } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
314  type = ist->hwaccel_device_type;
315  err = hw_device_init_from_type(type, ist->hwaccel_device,
316  &dev);
317  } else {
318  // This will be dealt with by API-specific initialisation
319  // (using hwaccel_device), so nothing further needed here.
320  return 0;
321  }
322  } else {
323  if (ist->hwaccel_id == HWACCEL_AUTO) {
324  ist->hwaccel_device_type = dev->type;
325  } else if (ist->hwaccel_device_type != dev->type) {
326  av_log(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device "
327  "specified for decoder: device %s of type %s is not "
328  "usable with hwaccel %s.\n", dev->name,
331  return AVERROR(EINVAL);
332  }
333  }
334  } else {
335  if (ist->hwaccel_id == HWACCEL_AUTO) {
336  auto_device = 1;
337  } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
338  type = ist->hwaccel_device_type;
339  dev = hw_device_get_by_type(type);
340  if (!dev)
341  err = hw_device_init_from_type(type, NULL, &dev);
342  } else {
343  dev = hw_device_match_by_codec(ist->dec);
344  if (!dev) {
345  // No device for this codec, but not using generic hwaccel
346  // and therefore may well not need one - ignore.
347  return 0;
348  }
349  }
350  }
351 
352  if (auto_device) {
353  int i;
354  if (!avcodec_get_hw_config(ist->dec, 0)) {
355  // Decoder does not support any hardware devices.
356  return 0;
357  }
358  for (i = 0; !dev; i++) {
359  config = avcodec_get_hw_config(ist->dec, i);
360  if (!config)
361  break;
362  type = config->device_type;
363  dev = hw_device_get_by_type(type);
364  if (dev) {
365  av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
366  "hwaccel type %s with existing device %s.\n",
367  av_hwdevice_get_type_name(type), dev->name);
368  }
369  }
370  for (i = 0; !dev; i++) {
371  config = avcodec_get_hw_config(ist->dec, i);
372  if (!config)
373  break;
374  type = config->device_type;
375  // Try to make a new device of this type.
376  err = hw_device_init_from_type(type, ist->hwaccel_device,
377  &dev);
378  if (err < 0) {
379  // Can't make a device of this type.
380  continue;
381  }
382  if (ist->hwaccel_device) {
383  av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
384  "hwaccel type %s with new device created "
385  "from %s.\n", av_hwdevice_get_type_name(type),
386  ist->hwaccel_device);
387  } else {
388  av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
389  "hwaccel type %s with new default device.\n",
391  }
392  }
393  if (dev) {
394  ist->hwaccel_device_type = type;
395  } else {
396  av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel "
397  "disabled: no device found.\n");
398  ist->hwaccel_id = HWACCEL_NONE;
399  return 0;
400  }
401  }
402 
403  if (!dev) {
404  av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available "
405  "for decoder: device type %s needed for codec %s.\n",
406  av_hwdevice_get_type_name(type), ist->dec->name);
407  return err;
408  }
409 
411  if (!ist->dec_ctx->hw_device_ctx)
412  return AVERROR(ENOMEM);
413 
414  return 0;
415 }
416 
418 {
419  HWDevice *dev;
420 
421  dev = hw_device_match_by_codec(ost->enc);
422  if (dev) {
424  if (!ost->enc_ctx->hw_device_ctx)
425  return AVERROR(ENOMEM);
426  return 0;
427  } else {
428  // No device required, or no device available.
429  return 0;
430  }
431 }
432 
434 {
435  InputStream *ist = avctx->opaque;
436  AVFrame *output = NULL;
437  enum AVPixelFormat output_format = ist->hwaccel_output_format;
438  int err;
439 
440  if (input->format == output_format) {
441  // Nothing to do.
442  return 0;
443  }
444 
445  output = av_frame_alloc();
446  if (!output)
447  return AVERROR(ENOMEM);
448 
449  output->format = output_format;
450 
451  err = av_hwframe_transfer_data(output, input, 0);
452  if (err < 0) {
453  av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to "
454  "output frame: %d.\n", err);
455  goto fail;
456  }
457 
458  err = av_frame_copy_props(output, input);
459  if (err < 0) {
460  av_frame_unref(output);
461  goto fail;
462  }
463 
464  av_frame_unref(input);
465  av_frame_move_ref(input, output);
466  av_frame_free(&output);
467 
468  return 0;
469 
470 fail:
471  av_frame_free(&output);
472  return err;
473 }
474 
476 {
477  InputStream *ist = avctx->opaque;
478 
480 
481  return 0;
482 }
#define NULL
Definition: coverity.c:32
static char * hw_device_default_name(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:67
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:125
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition: hwcontext.c:78
GLint GLenum type
Definition: opengl_enc.c:104
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition: frame.c:582
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
#define src
Definition: vp8dsp.c:254
AVCodec.
Definition: avcodec.h:3492
static int hw_device_init_from_type(enum AVHWDeviceType type, const char *device, HWDevice **dev_out)
Definition: ffmpeg_hw.c:229
#define av_malloc(s)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
The codec supports this format via the hw_device_ctx interface.
Definition: avcodec.h:3438
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
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:571
AVCodec * dec
Definition: ffmpeg.h:305
#define av_log(a,...)
int(* hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame)
Definition: ffmpeg.h:373
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
static HWDevice * hw_device_add(void)
Definition: ffmpeg_hw.c:52
void hw_device_free_all(void)
Definition: ffmpeg_hw.c:272
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
int methods
Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible setup methods which can be used...
Definition: avcodec.h:3475
int hwaccel_decode_init(AVCodecContext *avctx)
Definition: ffmpeg_hw.c:475
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values. ...
Definition: dict.c:203
const char * arg
Definition: jacosubdec.c:66
const char * name
Name of the codec implementation.
Definition: avcodec.h:3499
#define fail()
Definition: checkasm.h:122
int av_reallocp_array(void *ptr, size_t nmemb, size_t size)
Allocate, reallocate, or free an array through a pointer to a pointer.
Definition: mem.c:205
const char * name
Definition: ffmpeg.h:75
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:439
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:607
static int nb_hw_devices
Definition: ffmpeg_hw.c:25
AVCodecContext * enc
Definition: muxing.c:55
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:368
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:180
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
enum AVHWDeviceType hwaccel_device_type
Definition: ffmpeg.h:365
main external API structure.
Definition: avcodec.h:1568
const AVCodecHWConfig * avcodec_get_hw_config(const AVCodec *codec, int index)
Retrieve supported hardware configurations for a codec.
Definition: utils.c:1784
HWDevice * hw_device_get_by_name(const char *name)
Definition: ffmpeg_hw.c:42
AVCodecContext * enc_ctx
Definition: ffmpeg.h:465
int hw_device_setup_for_decode(InputStream *ist)
Definition: ffmpeg_hw.c:301
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition: hwcontext.c:88
int index
Definition: gxfenc.c:89
AVCodecContext * dec_ctx
Definition: ffmpeg.h:304
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
static HWDevice ** hw_devices
Definition: ffmpeg_hw.c:26
#define snprintf
Definition: snprintf.h:34
static HWDevice * hw_device_get_by_type(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:28
enum AVPixelFormat hwaccel_output_format
Definition: ffmpeg.h:367
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:553
static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
Definition: ffmpeg_hw.c:433
A reference to a data buffer.
Definition: buffer.h:81
static AVStream * ost
static HWDevice * hw_device_match_by_codec(const AVCodec *codec)
Definition: ffmpeg_hw.c:284
const OptionDef options[]
Definition: ffmpeg_opt.c:3374
enum AVHWDeviceType type
Definition: ffmpeg.h:76
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
Definition: ffmpeg_hw.c:92
AVBufferRef * device_ref
Definition: ffmpeg.h:77
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
AVHWDeviceType
Definition: hwcontext.h:27
char * hwaccel_device
Definition: ffmpeg.h:366
#define av_freep(p)
enum AVHWDeviceType device_type
The device type associated with the configuration.
Definition: avcodec.h:3482
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
enum HWAccelID hwaccel_id
Definition: ffmpeg.h:364
int hw_device_setup_for_encode(OutputStream *ost)
Definition: ffmpeg_hw.c:417
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition: avcodec.h:3317
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263
void * opaque
Private data of the user, can be used to carry app specific stuff.
Definition: avcodec.h:1610
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:654
const char * name
Definition: opengl_enc.c:102