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;
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: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  }
133  errmsg = "named device already exists";
134  goto invalid;
135  }
136 
137  p += 1 + k;
138  } else {
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);
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 
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++) {
277  av_buffer_unref(&hw_devices[i]->device_ref);
278  av_freep(&hw_devices[i]);
279  }
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;
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;
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;
364  if (dev) {
365  av_log(ist->dec_ctx, AV_LOG_INFO, "Using auto "
366  "hwaccel type %s with existing device %s.\n",
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.
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",
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) {
423  ost->enc_ctx->hw_device_ctx = av_buffer_ref(dev->device_ref);
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 
446  if (!output)
447  return AVERROR(ENOMEM);
448 
449  output->format = output_format;
450 
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 
459  if (err < 0) {
461  goto fail;
462  }
463 
467 
468  return 0;
469 
470 fail:
472  return err;
473 }
474 
476 {
477  InputStream *ist = avctx->opaque;
478 
480 
481  return 0;
482 }
AVCodec
AVCodec.
Definition: avcodec.h:3481
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
InputStream::hwaccel_device
char * hwaccel_device
Definition: ffmpeg.h:366
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
AVCodecHWConfig::methods
int methods
Bit set of AV_CODEC_HW_CONFIG_METHOD_* flags, describing the possible setup methods which can be used...
Definition: avcodec.h:3464
InputStream::dec_ctx
AVCodecContext * dec_ctx
Definition: ffmpeg.h:304
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:202
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:295
name
const char * name
Definition: avisynth_c.h:867
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:78
ffmpeg.h
AVDictionary
Definition: dict.c:30
HWDevice
Definition: ffmpeg.h:74
hw_device_default_name
static char * hw_device_default_name(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:67
ost
static AVStream * ost
Definition: vaapi_transcode.c:45
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:31
InputStream
Definition: ffmpeg.h:295
fail
#define fail()
Definition: checkasm.h:120
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:272
src
#define src
Definition: vp8dsp.c:254
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
hw_device_init_from_type
static int hw_device_init_from_type(enum AVHWDeviceType type, const char *device, HWDevice **dev_out)
Definition: ffmpeg_hw.c:229
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
nb_hw_devices
static int nb_hw_devices
Definition: ffmpeg_hw.c:25
HWACCEL_GENERIC
@ HWACCEL_GENERIC
Definition: ffmpeg.h:61
AVHWDeviceType
AVHWDeviceType
Definition: hwcontext.h:27
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:88
InputStream::hwaccel_retrieve_data
int(* hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame)
Definition: ffmpeg.h:373
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:66
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:654
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:125
hw_devices
static HWDevice ** hw_devices
Definition: ffmpeg_hw.c:26
InputStream::hwaccel_id
enum HWAccelID hwaccel_id
Definition: ffmpeg.h:364
InputStream::dec
AVCodec * dec
Definition: ffmpeg.h:305
InputStream::hwaccel_output_format
enum AVPixelFormat hwaccel_output_format
Definition: ffmpeg.h:367
hw_device_add
static HWDevice * hw_device_add(void)
Definition: ffmpeg_hw.c:52
hwaccel_retrieve_data
static int hwaccel_retrieve_data(AVCodecContext *avctx, AVFrame *input)
Definition: ffmpeg_hw.c:433
index
int index
Definition: gxfenc.c:89
hwaccel_decode_init
int hwaccel_decode_init(AVCodecContext *avctx)
Definition: ffmpeg_hw.c:475
hw_device_match_by_codec
static HWDevice * hw_device_match_by_codec(const AVCodec *codec)
Definition: ffmpeg_hw.c:284
options
const OptionDef options[]
InputStream::hwaccel_device_type
enum AVHWDeviceType hwaccel_device_type
Definition: ffmpeg.h:365
HWDevice::device_ref
AVBufferRef * device_ref
Definition: ffmpeg.h:77
av_reallocp_array
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
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:203
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
AV_LOG_INFO
#define AV_LOG_INFO
Standard information.
Definition: log.h:187
HWACCEL_AUTO
@ HWACCEL_AUTO
Definition: ffmpeg.h:60
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:607
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:259
hw_device_setup_for_decode
int hw_device_setup_for_decode(InputStream *ist)
Definition: ffmpeg_hw.c:301
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:582
av_frame_unref
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:553
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:236
AVCodec::name
const char * name
Name of the codec implementation.
Definition: avcodec.h:3488
AVCodecContext::hw_device_ctx
AVBufferRef * hw_device_ctx
A reference to the AVHWDeviceContext describing the device which will be used by a hardware encoder/d...
Definition: avcodec.h:3314
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:571
AVCodecContext::opaque
void * opaque
Private data of the user, can be used to carry app specific stuff.
Definition: avcodec.h:1607
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:439
AVCodecContext
main external API structure.
Definition: avcodec.h:1565
HWDevice::name
const char * name
Definition: ffmpeg.h:75
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:180
hw_device_setup_for_encode
int hw_device_setup_for_encode(OutputStream *ost)
Definition: ffmpeg_hw.c:417
hw_device_init_from_string
int hw_device_init_from_string(const char *arg, HWDevice **dev_out)
Definition: ffmpeg_hw.c:92
av_buffer_ref
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
HWACCEL_NONE
@ HWACCEL_NONE
Definition: ffmpeg.h:59
avcodec_get_hw_config
const AVCodecHWConfig * avcodec_get_hw_config(const AVCodec *codec, int index)
Retrieve supported hardware configurations for a codec.
Definition: utils.c:1824
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:81
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:35
HWDevice::type
enum AVHWDeviceType type
Definition: ffmpeg.h:76
AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX
@ AV_CODEC_HW_CONFIG_METHOD_HW_DEVICE_CTX
The codec supports this format via the hw_device_ctx interface.
Definition: avcodec.h:3427
OutputStream
Definition: muxing.c:53
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:28
AVCodecHWConfig
Definition: avcodec.h:3455
avstring.h
av_strndup
char * av_strndup(const char *s, size_t len)
Duplicate a substring of a string.
Definition: mem.c:263
snprintf
#define snprintf
Definition: snprintf.h:34
AVCodecHWConfig::device_type
enum AVHWDeviceType device_type
The device type associated with the configuration.
Definition: avcodec.h:3471
hw_device_get_by_type
static HWDevice * hw_device_get_by_type(enum AVHWDeviceType type)
Definition: ffmpeg_hw.c:28