FFmpeg  4.4
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: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 {
194  errmsg = "parse error";
195  goto invalid;
196  }
197 
198  dev = hw_device_add();
199  if (!dev) {
200  err = AVERROR(ENOMEM);
201  goto fail;
202  }
203 
204  dev->name = name;
205  dev->type = type;
206  dev->device_ref = device_ref;
207 
208  if (dev_out)
209  *dev_out = dev;
210 
211  name = NULL;
212  err = 0;
213 done:
214  av_freep(&type_name);
215  av_freep(&name);
216  av_freep(&device);
218  return err;
219 invalid:
221  "Invalid device specification \"%s\": %s\n", arg, errmsg);
222  err = AVERROR(EINVAL);
223  goto done;
224 fail:
226  "Device creation failed: %d.\n", err);
227  av_buffer_unref(&device_ref);
228  goto done;
229 }
230 
232  const char *device,
233  HWDevice **dev_out)
234 {
235  AVBufferRef *device_ref = NULL;
236  HWDevice *dev;
237  char *name;
238  int err;
239 
241  if (!name) {
242  err = AVERROR(ENOMEM);
243  goto fail;
244  }
245 
246  err = av_hwdevice_ctx_create(&device_ref, type, device, NULL, 0);
247  if (err < 0) {
249  "Device creation failed: %d.\n", err);
250  goto fail;
251  }
252 
253  dev = hw_device_add();
254  if (!dev) {
255  err = AVERROR(ENOMEM);
256  goto fail;
257  }
258 
259  dev->name = name;
260  dev->type = type;
261  dev->device_ref = device_ref;
262 
263  if (dev_out)
264  *dev_out = dev;
265 
266  return 0;
267 
268 fail:
269  av_freep(&name);
270  av_buffer_unref(&device_ref);
271  return err;
272 }
273 
275 {
276  int i;
277  for (i = 0; i < nb_hw_devices; i++) {
279  av_buffer_unref(&hw_devices[i]->device_ref);
280  av_freep(&hw_devices[i]);
281  }
283  nb_hw_devices = 0;
284 }
285 
287 {
288  const AVCodecHWConfig *config;
289  HWDevice *dev;
290  int i;
291  for (i = 0;; i++) {
292  config = avcodec_get_hw_config(codec, i);
293  if (!config)
294  return NULL;
296  continue;
297  dev = hw_device_get_by_type(config->device_type);
298  if (dev)
299  return dev;
300  }
301 }
302 
304 {
305  const AVCodecHWConfig *config;
306  enum AVHWDeviceType type;
307  HWDevice *dev = NULL;
308  int err, auto_device = 0;
309 
310  if (ist->hwaccel_device) {
312  if (!dev) {
313  if (ist->hwaccel_id == HWACCEL_AUTO) {
314  auto_device = 1;
315  } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
316  type = ist->hwaccel_device_type;
318  &dev);
319  } else {
320  // This will be dealt with by API-specific initialisation
321  // (using hwaccel_device), so nothing further needed here.
322  return 0;
323  }
324  } else {
325  if (ist->hwaccel_id == HWACCEL_AUTO) {
326  ist->hwaccel_device_type = dev->type;
327  } else if (ist->hwaccel_device_type != dev->type) {
328  av_log(ist->dec_ctx, AV_LOG_ERROR, "Invalid hwaccel device "
329  "specified for decoder: device %s of type %s is not "
330  "usable with hwaccel %s.\n", dev->name,
333  return AVERROR(EINVAL);
334  }
335  }
336  } else {
337  if (ist->hwaccel_id == HWACCEL_AUTO) {
338  auto_device = 1;
339  } else if (ist->hwaccel_id == HWACCEL_GENERIC) {
340  type = ist->hwaccel_device_type;
342  if (!dev)
343  err = hw_device_init_from_type(type, NULL, &dev);
344  } else {
345  dev = hw_device_match_by_codec(ist->dec);
346  if (!dev) {
347  // No device for this codec, but not using generic hwaccel
348  // and therefore may well not need one - ignore.
349  return 0;
350  }
351  }
352  }
353 
354  if (auto_device) {
355  int i;
356  if (!avcodec_get_hw_config(ist->dec, 0)) {
357  // Decoder does not support any hardware devices.
358  return 0;
359  }
360  for (i = 0; !dev; i++) {
361  config = avcodec_get_hw_config(ist->dec, i);
362  if (!config)
363  break;
364  type = config->device_type;
366  if (dev) {
367  av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
368  "hwaccel type %s with existing device %s.\n",
370  }
371  }
372  for (i = 0; !dev; i++) {
373  config = avcodec_get_hw_config(ist->dec, i);
374  if (!config)
375  break;
376  type = config->device_type;
377  // Try to make a new device of this type.
379  &dev);
380  if (err < 0) {
381  // Can't make a device of this type.
382  continue;
383  }
384  if (ist->hwaccel_device) {
385  av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
386  "hwaccel type %s with new device created "
387  "from %s.\n", av_hwdevice_get_type_name(type),
388  ist->hwaccel_device);
389  } else {
390  av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
391  "hwaccel type %s with new default device.\n",
393  }
394  }
395  if (dev) {
396  ist->hwaccel_device_type = type;
397  } else {
398  av_log(ist->dec_ctx, AV_LOG_INFO, "Auto hwaccel "
399  "disabled: no device found.\n");
400  ist->hwaccel_id = HWACCEL_NONE;
401  return 0;
402  }
403  }
404 
405  if (!dev) {
406  av_log(ist->dec_ctx, AV_LOG_ERROR, "No device available "
407  "for decoder: device type %s needed for codec %s.\n",
409  return err;
410  }
411 
413  if (!ist->dec_ctx->hw_device_ctx)
414  return AVERROR(ENOMEM);
415 
416  return 0;
417 }
418 
420 {
421  const AVCodecHWConfig *config;
422  HWDevice *dev = NULL;
423  AVBufferRef *frames_ref = NULL;
424  int i;
425 
426  if (ost->filter) {
427  frames_ref = av_buffersink_get_hw_frames_ctx(ost->filter->filter);
428  if (frames_ref &&
429  ((AVHWFramesContext*)frames_ref->data)->format ==
430  ost->enc_ctx->pix_fmt) {
431  // Matching format, will try to use hw_frames_ctx.
432  } else {
433  frames_ref = NULL;
434  }
435  }
436 
437  for (i = 0;; i++) {
438  config = avcodec_get_hw_config(ost->enc, i);
439  if (!config)
440  break;
441 
442  if (frames_ref &&
444  (config->pix_fmt == AV_PIX_FMT_NONE ||
445  config->pix_fmt == ost->enc_ctx->pix_fmt)) {
446  av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using input "
447  "frames context (format %s) with %s encoder.\n",
448  av_get_pix_fmt_name(ost->enc_ctx->pix_fmt),
449  ost->enc->name);
450  ost->enc_ctx->hw_frames_ctx = av_buffer_ref(frames_ref);
451  if (!ost->enc_ctx->hw_frames_ctx)
452  return AVERROR(ENOMEM);
453  return 0;
454  }
455 
456  if (!dev &&
458  dev = hw_device_get_by_type(config->device_type);
459  }
460 
461  if (dev) {
462  av_log(ost->enc_ctx, AV_LOG_VERBOSE, "Using device %s "
463  "(type %s) with %s encoder.\n", dev->name,
464  av_hwdevice_get_type_name(dev->type), ost->enc->name);
465  ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
466  if (!ost->enc_ctx->hw_device_ctx)
467  return AVERROR(ENOMEM);
468  } else {
469  // No device required, or no device available.
470  }
471  return 0;
472 }
473 
474 static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
475 {
476  InputStream *ist = avctx->opaque;
477  AVFrame *output = NULL;
478  enum AVPixelFormat output_format = ist->hwaccel_output_format;
479  int err;
480 
481  if (input->format == output_format) {
482  // Nothing to do.
483  return 0;
484  }
485 
486  output = av_frame_alloc();
487  if (!output)
488  return AVERROR(ENOMEM);
489 
490  output->format = output_format;
491 
492  err = av_hwframe_transfer_data(output, input, 0);
493  if (err < 0) {
494  av_log(avctx, AV_LOG_ERROR, "Failed to transfer data to "
495  "output frame: %d.\n", err);
496  goto fail;
497  }
498 
499  err = av_frame_copy_props(output, input);
500  if (err < 0) {
501  av_frame_unref(output);
502  goto fail;
503  }
504 
505  av_frame_unref(input);
506  av_frame_move_ref(input, output);
507  av_frame_free(&output);
508 
509  return 0;
510 
511 fail:
512  av_frame_free(&output);
513  return err;
514 }
515 
517 {
518  InputStream *ist = avctx->opaque;
519 
521 
522  return 0;
523 }
524 
526 {
527  HWDevice *dev;
528  int i;
529 
530  // If the user has supplied exactly one hardware device then just
531  // give it straight to every filter for convenience. If more than
532  // one device is available then the user needs to pick one explcitly
533  // with the filter_hw_device option.
534  if (filter_hw_device)
535  dev = filter_hw_device;
536  else if (nb_hw_devices == 1)
537  dev = hw_devices[0];
538  else
539  dev = NULL;
540 
541  if (dev) {
542  for (i = 0; i < fg->graph->nb_filters; i++) {
543  fg->graph->filters[i]->hw_device_ctx =
545  if (!fg->graph->filters[i]->hw_device_ctx)
546  return AVERROR(ENOMEM);
547  }
548  }
549 
550  return 0;
551 }
memory buffer sink API for audio and video
#define fail()
Definition: checkasm.h:133
#define NULL
Definition: coverity.c:32
@ HWACCEL_NONE
Definition: ffmpeg.h:59
@ HWACCEL_GENERIC
Definition: ffmpeg.h:61
@ HWACCEL_AUTO
Definition: ffmpeg.h:60
HWDevice * filter_hw_device
Definition: ffmpeg_opt.c:145
const OptionDef options[]
int hw_device_setup_for_encode(OutputStream *ost)
Definition: ffmpeg_hw.c:419
static HWDevice ** hw_devices
Definition: ffmpeg_hw.c:28
static int nb_hw_devices
Definition: ffmpeg_hw.c:27
static HWDevice * hw_device_add(void)
Definition: ffmpeg_hw.c:54
static char * hw_device_default_name(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:69
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
Definition: ffmpeg_hw.c:94
int hwaccel_decode_init(AVCodecContext *avctx)
Definition: ffmpeg_hw.c:516
static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
Definition: ffmpeg_hw.c:474
int hw_device_setup_for_decode(InputStream *ist)
Definition: ffmpeg_hw.c:303
void hw_device_free_all(void)
Definition: ffmpeg_hw.c:274
int hw_device_setup_for_filter(FilterGraph *fg)
Definition: ffmpeg_hw.c:525
static int hw_device_init_from_type(enum AVHWDeviceType type, const char *device, HWDevice **dev_out)
Definition: ffmpeg_hw.c:231
HWDevice * hw_device_get_by_name(const char *name)
Definition: ffmpeg_hw.c:44
static HWDevice * hw_device_get_by_type(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:30
static HWDevice * hw_device_match_by_codec(const AVCodec *codec)
Definition: ffmpeg_hw.c:286
const AVCodecHWConfig * avcodec_get_hw_config(const AVCodec *codec, int index)
Retrieve supported hardware configurations for a codec.
Definition: utils.c:873
@ AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX
The codec supports this format via the hw_frames_ctx interface.
Definition: codec.h:424
@ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX
The codec supports this format via the hw_device_ctx interface.
Definition: codec.h:411
AVBufferRef * av_buffersink_get_hw_frames_ctx(const AVFilterContext *ctx)
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
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
void av_dict_free(AVDictionary **pm)
Free all the memory allocated for an AVDictionary struct and all keys and values.
Definition: dict.c:203
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 AVERROR(e)
Definition: error.h:43
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:553
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_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:203
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:658
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:190
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:210
#define AV_LOG_INFO
Standard information.
Definition: log.h:205
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:194
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:237
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:206
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:265
int index
Definition: gxfenc.c:89
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:610
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:714
enum AVHWDeviceType av_hwdevice_find_type_by_name(const char *name)
Look up an AVHWDeviceType by name.
Definition: hwcontext.c:82
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:443
const char * av_hwdevice_get_type_name(enum AVHWDeviceType type)
Get the string name of an AVHWDeviceType.
Definition: hwcontext.c:92
AVHWDeviceType
Definition: hwcontext.h:27
@ AV_HWDEVICE_TYPE_NONE
Definition: hwcontext.h:28
cl_device_type type
int i
Definition: input.c:407
const char * arg
Definition: jacosubdec.c:66
const char * av_get_pix_fmt_name(enum AVPixelFormat pix_fmt)
Return the short name for a pixel format, NULL in case pix_fmt is unknown.
Definition: pixdesc.c:2489
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
const char * name
Definition: qsvenc.c:46
#define snprintf
Definition: snprintf.h:34
A reference to a data buffer.
Definition: buffer.h:84
uint8_t * data
The data buffer.
Definition: buffer.h:92
main external API structure.
Definition: avcodec.h:536
void * opaque
Private data of the user, can be used to carry app specific stuff.
Definition: avcodec.h:578
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition: avcodec.h:2270
enum AVHWDeviceType device_type
The device type associated with the configuration.
Definition: codec.h:464
int methods
Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible setup methods which can be used...
Definition: codec.h:457
enum AVPixelFormat pix_fmt
For decoders, a hardware pixel format which that decoder may be able to decode to if suitable hardwar...
Definition: codec.h:452
AVCodec.
Definition: codec.h:197
const char * name
Name of the codec implementation.
Definition: codec.h:204
AVBufferRef * hw_device_ctx
For filters which will create hardware frames, sets the device the filter should create them in.
Definition: avfilter.h:397
unsigned nb_filters
Definition: avfilter.h:853
AVFilterContext ** filters
Definition: avfilter.h:852
This structure describes decoded (raw) audio or video data.
Definition: frame.h:318
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames,...
Definition: frame.h:391
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
AVFilterGraph * graph
Definition: ffmpeg.h:291
AVBufferRef * device_ref
Definition: ffmpeg.h:76
enum AVHWDeviceType type
Definition: ffmpeg.h:75
const char * name
Definition: ffmpeg.h:74
enum AVPixelFormat hwaccel_output_format
Definition: ffmpeg.h:374
AVCodecContext * dec_ctx
Definition: ffmpeg.h:309
enum HWAccelID hwaccel_id
Definition: ffmpeg.h:371
int(* hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame)
Definition: ffmpeg.h:380
char * hwaccel_device
Definition: ffmpeg.h:373
const AVCodec * dec
Definition: ffmpeg.h:310
enum AVHWDeviceType hwaccel_device_type
Definition: ffmpeg.h:372
#define av_freep(p)
#define av_malloc(s)
#define av_log(a,...)
#define src
Definition: vp8dsp.c:255
static AVStream * ost