Libav
hwcontext.c
Go to the documentation of this file.
1 /*
2  * This file is part of Libav.
3  *
4  * Libav 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  * Libav 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 Libav; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17  */
18 
19 #include "config.h"
20 
21 #include "buffer.h"
22 #include "common.h"
23 #include "hwcontext.h"
24 #include "hwcontext_internal.h"
25 #include "imgutils.h"
26 #include "log.h"
27 #include "mem.h"
28 #include "pixdesc.h"
29 #include "pixfmt.h"
30 
31 static const HWContextType *hw_table[] = {
32 #if CONFIG_CUDA
34 #endif
35 #if CONFIG_DXVA2
37 #endif
38 #if CONFIG_LIBMFX
40 #endif
41 #if CONFIG_VAAPI
43 #endif
44 #if CONFIG_VDPAU
46 #endif
47  NULL,
48 };
49 
50 static const AVClass hwdevice_ctx_class = {
51  .class_name = "AVHWDeviceContext",
52  .item_name = av_default_item_name,
53  .version = LIBAVUTIL_VERSION_INT,
54 };
55 
56 static void hwdevice_ctx_free(void *opaque, uint8_t *data)
57 {
59 
60  /* uninit might still want access the hw context and the user
61  * free() callback might destroy it, so uninit has to be called first */
62  if (ctx->internal->hw_type->device_uninit)
63  ctx->internal->hw_type->device_uninit(ctx);
64 
65  if (ctx->free)
66  ctx->free(ctx);
67 
68  av_freep(&ctx->hwctx);
69  av_freep(&ctx->internal->priv);
70  av_freep(&ctx->internal);
71  av_freep(&ctx);
72 }
73 
75 {
77  AVBufferRef *buf;
78  const HWContextType *hw_type = NULL;
79  int i;
80 
81  for (i = 0; hw_table[i]; i++) {
82  if (hw_table[i]->type == type) {
83  hw_type = hw_table[i];
84  break;
85  }
86  }
87  if (!hw_type)
88  return NULL;
89 
90  ctx = av_mallocz(sizeof(*ctx));
91  if (!ctx)
92  return NULL;
93 
94  ctx->internal = av_mallocz(sizeof(*ctx->internal));
95  if (!ctx->internal)
96  goto fail;
97 
98  if (hw_type->device_priv_size) {
99  ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
100  if (!ctx->internal->priv)
101  goto fail;
102  }
103 
104  if (hw_type->device_hwctx_size) {
105  ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
106  if (!ctx->hwctx)
107  goto fail;
108  }
109 
110  buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
113  if (!buf)
114  goto fail;
115 
116  ctx->type = type;
117  ctx->av_class = &hwdevice_ctx_class;
118 
119  ctx->internal->hw_type = hw_type;
120 
121  return buf;
122 
123 fail:
124  if (ctx->internal)
125  av_freep(&ctx->internal->priv);
126  av_freep(&ctx->internal);
127  av_freep(&ctx->hwctx);
128  av_freep(&ctx);
129  return NULL;
130 }
131 
133 {
135  int ret;
136 
137  if (ctx->internal->hw_type->device_init) {
138  ret = ctx->internal->hw_type->device_init(ctx);
139  if (ret < 0)
140  goto fail;
141  }
142 
143  return 0;
144 fail:
145  if (ctx->internal->hw_type->device_uninit)
146  ctx->internal->hw_type->device_uninit(ctx);
147  return ret;
148 }
149 
150 static const AVClass hwframe_ctx_class = {
151  .class_name = "AVHWFramesContext",
152  .item_name = av_default_item_name,
153  .version = LIBAVUTIL_VERSION_INT,
154 };
155 
156 static void hwframe_ctx_free(void *opaque, uint8_t *data)
157 {
159 
160  if (ctx->internal->pool_internal)
162 
163  if (ctx->internal->hw_type->frames_uninit)
164  ctx->internal->hw_type->frames_uninit(ctx);
165 
166  if (ctx->free)
167  ctx->free(ctx);
168 
170 
171  av_freep(&ctx->hwctx);
172  av_freep(&ctx->internal->priv);
173  av_freep(&ctx->internal);
174  av_freep(&ctx);
175 }
176 
178 {
179  AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
180  const HWContextType *hw_type = device_ctx->internal->hw_type;
182  AVBufferRef *buf, *device_ref = NULL;;
183 
184  ctx = av_mallocz(sizeof(*ctx));
185  if (!ctx)
186  return NULL;
187 
188  ctx->internal = av_mallocz(sizeof(*ctx->internal));
189  if (!ctx->internal)
190  goto fail;
191 
192  if (hw_type->frames_priv_size) {
193  ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
194  if (!ctx->internal->priv)
195  goto fail;
196  }
197 
198  if (hw_type->frames_hwctx_size) {
199  ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
200  if (!ctx->hwctx)
201  goto fail;
202  }
203 
204  device_ref = av_buffer_ref(device_ref_in);
205  if (!device_ref)
206  goto fail;
207 
208  buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
211  if (!buf)
212  goto fail;
213 
214  ctx->av_class = &hwframe_ctx_class;
215  ctx->device_ref = device_ref;
216  ctx->device_ctx = device_ctx;
217  ctx->format = AV_PIX_FMT_NONE;
218  ctx->sw_format = AV_PIX_FMT_NONE;
219 
220  ctx->internal->hw_type = hw_type;
221 
222  return buf;
223 
224 fail:
225  if (device_ref)
226  av_buffer_unref(&device_ref);
227  if (ctx->internal)
228  av_freep(&ctx->internal->priv);
229  av_freep(&ctx->internal);
230  av_freep(&ctx->hwctx);
231  av_freep(&ctx);
232  return NULL;
233 }
234 
236 {
238  AVFrame **frames;
239  int i, ret = 0;
240 
242  if (!frames)
243  return AVERROR(ENOMEM);
244 
245  for (i = 0; i < ctx->initial_pool_size; i++) {
246  frames[i] = av_frame_alloc();
247  if (!frames[i])
248  goto fail;
249 
250  ret = av_hwframe_get_buffer(ref, frames[i], 0);
251  if (ret < 0)
252  goto fail;
253  }
254 
255 fail:
256  for (i = 0; i < ctx->initial_pool_size; i++)
257  av_frame_free(&frames[i]);
258  av_freep(&frames);
259 
260  return ret;
261 }
262 
264 {
266  const enum AVPixelFormat *pix_fmt;
267  int ret;
268 
269  /* validate the pixel format */
271  if (*pix_fmt == ctx->format)
272  break;
273  }
274  if (*pix_fmt == AV_PIX_FMT_NONE) {
275  av_log(ctx, AV_LOG_ERROR,
276  "The hardware pixel format '%s' is not supported by the device type '%s'\n",
278  return AVERROR(ENOSYS);
279  }
280 
281  /* validate the dimensions */
282  ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
283  if (ret < 0)
284  return ret;
285 
286  /* format-specific init */
287  if (ctx->internal->hw_type->frames_init) {
288  ret = ctx->internal->hw_type->frames_init(ctx);
289  if (ret < 0)
290  goto fail;
291  }
292 
293  if (ctx->internal->pool_internal && !ctx->pool)
294  ctx->pool = ctx->internal->pool_internal;
295 
296  /* preallocate the frames in the pool, if requested */
297  if (ctx->initial_pool_size > 0) {
298  ret = hwframe_pool_prealloc(ref);
299  if (ret < 0)
300  goto fail;
301  }
302 
303  return 0;
304 fail:
305  if (ctx->internal->hw_type->frames_uninit)
306  ctx->internal->hw_type->frames_uninit(ctx);
307  return ret;
308 }
309 
312  enum AVPixelFormat **formats, int flags)
313 {
314  AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
315 
317  return AVERROR(ENOSYS);
318 
319  return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
320 }
321 
322 static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
323 {
325  AVFrame *frame_tmp;
326  int ret = 0;
327 
328  frame_tmp = av_frame_alloc();
329  if (!frame_tmp)
330  return AVERROR(ENOMEM);
331 
332  /* if the format is set, use that
333  * otherwise pick the first supported one */
334  if (dst->format >= 0) {
335  frame_tmp->format = dst->format;
336  } else {
337  enum AVPixelFormat *formats;
338 
341  &formats, 0);
342  if (ret < 0)
343  goto fail;
344  frame_tmp->format = formats[0];
345  av_freep(&formats);
346  }
347  frame_tmp->width = ctx->width;
348  frame_tmp->height = ctx->height;
349 
350  ret = av_frame_get_buffer(frame_tmp, 32);
351  if (ret < 0)
352  goto fail;
353 
354  ret = av_hwframe_transfer_data(frame_tmp, src, flags);
355  if (ret < 0)
356  goto fail;
357 
358  frame_tmp->width = src->width;
359  frame_tmp->height = src->height;
360 
361  av_frame_move_ref(dst, frame_tmp);
362 
363 fail:
364  av_frame_free(&frame_tmp);
365  return ret;
366 }
367 
369 {
371  int ret;
372 
373  if (!dst->buf[0])
374  return transfer_data_alloc(dst, src, flags);
375 
376  if (src->hw_frames_ctx) {
377  ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
378 
379  ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
380  if (ret < 0)
381  return ret;
382  } else if (dst->hw_frames_ctx) {
383  ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
384 
385  ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
386  if (ret < 0)
387  return ret;
388  } else
389  return AVERROR(ENOSYS);
390 
391  return 0;
392 }
393 
394 int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
395 {
396  AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
397  int ret;
398 
400  return AVERROR(ENOSYS);
401 
402  if (!ctx->pool)
403  return AVERROR(EINVAL);
404 
405  frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
406  if (!frame->hw_frames_ctx)
407  return AVERROR(ENOMEM);
408 
409  ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
410  if (ret < 0) {
412  return ret;
413  }
414 
415  return 0;
416 }
417 
419 {
421  const HWContextType *hw_type = ctx->internal->hw_type;
422 
423  if (hw_type->device_hwconfig_size == 0)
424  return NULL;
425 
426  return av_mallocz(hw_type->device_hwconfig_size);
427 }
428 
430  const void *hwconfig)
431 {
433  const HWContextType *hw_type = ctx->internal->hw_type;
434  AVHWFramesConstraints *constraints;
435 
436  if (!hw_type->frames_get_constraints)
437  return NULL;
438 
439  constraints = av_mallocz(sizeof(*constraints));
440  if (!constraints)
441  return NULL;
442 
443  constraints->min_width = constraints->min_height = 0;
444  constraints->max_width = constraints->max_height = INT_MAX;
445 
446  if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) {
447  return constraints;
448  } else {
449  av_hwframe_constraints_free(&constraints);
450  return NULL;
451  }
452 }
453 
455 {
456  if (*constraints) {
457  av_freep(&(*constraints)->valid_hw_formats);
458  av_freep(&(*constraints)->valid_sw_formats);
459  }
460  av_freep(constraints);
461 }
462 
463 int av_hwdevice_ctx_create(AVBufferRef **pdevice_ref, enum AVHWDeviceType type,
464  const char *device, AVDictionary *opts, int flags)
465 {
466  AVBufferRef *device_ref = NULL;
467  AVHWDeviceContext *device_ctx;
468  int ret = 0;
469 
470  device_ref = av_hwdevice_ctx_alloc(type);
471  if (!device_ref) {
472  ret = AVERROR(ENOMEM);
473  goto fail;
474  }
475  device_ctx = (AVHWDeviceContext*)device_ref->data;
476 
477  if (!device_ctx->internal->hw_type->device_create) {
478  ret = AVERROR(ENOSYS);
479  goto fail;
480  }
481 
482  ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
483  opts, flags);
484  if (ret < 0)
485  goto fail;
486 
487  ret = av_hwdevice_ctx_init(device_ref);
488  if (ret < 0)
489  goto fail;
490 
491  *pdevice_ref = device_ref;
492  return 0;
493 fail:
494  av_buffer_unref(&device_ref);
495  *pdevice_ref = NULL;
496  return ret;
497 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:54
static void hwdevice_ctx_free(void *opaque, uint8_t *data)
Definition: hwcontext.c:56
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:106
This structure describes decoded (raw) audio or video data.
Definition: frame.h:140
void(* frames_uninit)(AVHWFramesContext *ctx)
misc image utilities
memory handling functions
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:308
const HWContextType ff_hwcontext_type_vdpau
av_log(ac->avr, AV_LOG_TRACE, "%d samples - audio_convert: %s to %s (%s)\, len, av_get_sample_fmt_name(ac->in_fmt), av_get_sample_fmt_name(ac->out_fmt), use_generic ? ac->func_descr_generic :ac->func_descr)
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1243
static enum AVSampleFormat formats[]
Definition: avresample.c:163
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:222
void * av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
Allocate a HW-specific configuration structure for a given HW device.
Definition: hwcontext.c:418
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:202
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition: frame.c:319
size_t device_priv_size
size of the private data, i.e.
const HWContextType * hw_type
void av_freep(void *arg)
Free a memory block which has been allocated with av_malloc(z)() or av_realloc() and set the pointer ...
Definition: mem.c:202
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition: hwcontext.c:454
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:365
int(* frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame)
const char * class_name
The name of the class; usually it is the same name as the context structure type to which the AVClass...
Definition: log.h:39
AVBufferPool * pool_internal
uint8_t
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:68
static int hwframe_pool_prealloc(AVBufferRef *ref)
Definition: hwcontext.c:235
size_t device_hwctx_size
size of the public hardware-specific context, i.e.
int(* transfer_data_from)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:85
const HWContextType ff_hwcontext_type_qsv
const char data[16]
Definition: mxf.c:70
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:463
static int flags
Definition: log.c:50
static void hwframe_ctx_free(void *opaque, uint8_t *data)
Definition: hwcontext.c:156
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:113
static const AVClass hwframe_ctx_class
Definition: hwcontext.c:150
int(* device_init)(AVHWDeviceContext *ctx)
void(* device_uninit)(AVHWDeviceContext *ctx)
#define src
Definition: vp8dsp.c:254
int width
width and height of the video frame
Definition: frame.h:179
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:124
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:80
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:28
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:263
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:394
#define fail()
Definition: checkasm.h:80
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:368
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:192
AVDictionary * opts
Definition: movenc.c:50
Transfer the data from the queried hw frame.
Definition: hwcontext.h:340
int av_image_check_size(unsigned int w, unsigned int h, int log_offset, void *log_ctx)
Check if the given dimension of an image is valid, meaning that all bytes of the image can be address...
Definition: imgutils.c:223
enum AVPixelFormat * pix_fmts
An array of pixel formats supported by the AVHWFramesContext instances Terminated by AV_PIX_FMT_NONE...
const char * name
int(* transfer_get_formats)(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
AVFormatContext * ctx
Definition: movenc.c:48
int(* transfer_data_to)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
int frames
Definition: movenc.c:65
enum AVPixelFormat pix_fmt
Definition: movenc.c:853
LIBAVUTIL_VERSION_INT
Definition: eval.c:55
if(ac->has_optimized_func)
void(* free)(struct AVHWFramesContext *ctx)
This field may be set by the caller before calling av_hwframe_ctx_init().
Definition: hwcontext.h:163
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:191
NULL
Definition: eval.c:55
AVBufferRef * av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
Allocate an AVHWDeviceContext for a given pixel format.
Definition: hwcontext.c:74
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:374
av_default_item_name
Definition: dnxhdenc.c:55
const HWContextType ff_hwcontext_type_cuda
AVHWFramesConstraints * av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, const void *hwconfig)
Get the constraints on HW frames given a device and the HW-specific configuration to be used with tha...
Definition: hwcontext.c:429
uint8_t * data
The data buffer.
Definition: buffer.h:89
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:155
int av_hwdevice_ctx_init(AVBufferRef *ref)
Finalize the device context before use.
Definition: hwcontext.c:132
Describe the class of an AVClass context structure.
Definition: log.h:34
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:254
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:117
refcounted data buffer API
static const HWContextType * hw_table[]
Definition: hwcontext.c:31
static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
Definition: hwcontext.c:322
AVHWFramesInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:127
int(* device_create)(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:186
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:134
A reference to a data buffer.
Definition: buffer.h:81
const HWContextType * hw_type
common internal and external API header
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:177
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:92
AVHWFrameTransferDirection
Definition: hwcontext.h:336
pixel format definitions
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:183
AVHWDeviceType
Definition: hwcontext.h:27
static void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.h:205
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
Definition: hwcontext.h:97
int height
Definition: frame.h:179
AVHWDeviceInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:64
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:1704
static const AVClass hwdevice_ctx_class
Definition: hwcontext.c:50
const HWContextType ff_hwcontext_type_dxva2
AVPixelFormat
Pixel format.
Definition: pixfmt.h:57
void * av_mallocz(size_t size)
Allocate a block of size bytes with alignment suitable for all memory accesses (including vectors if ...
Definition: mem.c:211
for(j=16;j >0;--j)
int av_hwframe_transfer_get_formats(AVBufferRef *hwframe_ref, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats, int flags)
Get a list of possible source or target formats usable in av_hwframe_transfer_data().
Definition: hwcontext.c:310
int(* frames_init)(AVHWFramesContext *ctx)
const HWContextType ff_hwcontext_type_vaapi