FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
hwcontext.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 "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_VAAPI
40 #endif
41 #if CONFIG_VDPAU
43 #endif
44  NULL,
45 };
46 
47 static const AVClass hwdevice_ctx_class = {
48  .class_name = "AVHWDeviceContext",
49  .item_name = av_default_item_name,
50  .version = LIBAVUTIL_VERSION_INT,
51 };
52 
53 static void hwdevice_ctx_free(void *opaque, uint8_t *data)
54 {
56 
57  /* uninit might still want access the hw context and the user
58  * free() callback might destroy it, so uninit has to be called first */
59  if (ctx->internal->hw_type->device_uninit)
60  ctx->internal->hw_type->device_uninit(ctx);
61 
62  if (ctx->free)
63  ctx->free(ctx);
64 
65  av_freep(&ctx->hwctx);
66  av_freep(&ctx->internal->priv);
67  av_freep(&ctx->internal);
68  av_freep(&ctx);
69 }
70 
72 {
75  const HWContextType *hw_type = NULL;
76  int i;
77 
78  for (i = 0; hw_table[i]; i++) {
79  if (hw_table[i]->type == type) {
80  hw_type = hw_table[i];
81  break;
82  }
83  }
84  if (!hw_type)
85  return NULL;
86 
87  ctx = av_mallocz(sizeof(*ctx));
88  if (!ctx)
89  return NULL;
90 
91  ctx->internal = av_mallocz(sizeof(*ctx->internal));
92  if (!ctx->internal)
93  goto fail;
94 
95  if (hw_type->device_priv_size) {
96  ctx->internal->priv = av_mallocz(hw_type->device_priv_size);
97  if (!ctx->internal->priv)
98  goto fail;
99  }
100 
101  if (hw_type->device_hwctx_size) {
102  ctx->hwctx = av_mallocz(hw_type->device_hwctx_size);
103  if (!ctx->hwctx)
104  goto fail;
105  }
106 
107  buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
110  if (!buf)
111  goto fail;
112 
113  ctx->type = type;
115 
116  ctx->internal->hw_type = hw_type;
117 
118  return buf;
119 
120 fail:
121  if (ctx->internal)
122  av_freep(&ctx->internal->priv);
123  av_freep(&ctx->internal);
124  av_freep(&ctx->hwctx);
125  av_freep(&ctx);
126  return NULL;
127 }
128 
130 {
132  int ret;
133 
134  if (ctx->internal->hw_type->device_init) {
135  ret = ctx->internal->hw_type->device_init(ctx);
136  if (ret < 0)
137  goto fail;
138  }
139 
140  return 0;
141 fail:
142  if (ctx->internal->hw_type->device_uninit)
143  ctx->internal->hw_type->device_uninit(ctx);
144  return ret;
145 }
146 
147 static const AVClass hwframe_ctx_class = {
148  .class_name = "AVHWFramesContext",
149  .item_name = av_default_item_name,
150  .version = LIBAVUTIL_VERSION_INT,
151 };
152 
153 static void hwframe_ctx_free(void *opaque, uint8_t *data)
154 {
156 
157  if (ctx->internal->pool_internal)
159 
160  if (ctx->internal->hw_type->frames_uninit)
161  ctx->internal->hw_type->frames_uninit(ctx);
162 
163  if (ctx->free)
164  ctx->free(ctx);
165 
167 
168  av_freep(&ctx->hwctx);
169  av_freep(&ctx->internal->priv);
170  av_freep(&ctx->internal);
171  av_freep(&ctx);
172 }
173 
175 {
176  AVHWDeviceContext *device_ctx = (AVHWDeviceContext*)device_ref_in->data;
177  const HWContextType *hw_type = device_ctx->internal->hw_type;
179  AVBufferRef *buf, *device_ref = NULL;
180 
181  ctx = av_mallocz(sizeof(*ctx));
182  if (!ctx)
183  return NULL;
184 
185  ctx->internal = av_mallocz(sizeof(*ctx->internal));
186  if (!ctx->internal)
187  goto fail;
188 
189  if (hw_type->frames_priv_size) {
190  ctx->internal->priv = av_mallocz(hw_type->frames_priv_size);
191  if (!ctx->internal->priv)
192  goto fail;
193  }
194 
195  if (hw_type->frames_hwctx_size) {
196  ctx->hwctx = av_mallocz(hw_type->frames_hwctx_size);
197  if (!ctx->hwctx)
198  goto fail;
199  }
200 
201  device_ref = av_buffer_ref(device_ref_in);
202  if (!device_ref)
203  goto fail;
204 
205  buf = av_buffer_create((uint8_t*)ctx, sizeof(*ctx),
208  if (!buf)
209  goto fail;
210 
212  ctx->device_ref = device_ref;
213  ctx->device_ctx = device_ctx;
214  ctx->format = AV_PIX_FMT_NONE;
215  ctx->sw_format = AV_PIX_FMT_NONE;
216 
217  ctx->internal->hw_type = hw_type;
218 
219  return buf;
220 
221 fail:
222  if (device_ref)
223  av_buffer_unref(&device_ref);
224  if (ctx->internal)
225  av_freep(&ctx->internal->priv);
226  av_freep(&ctx->internal);
227  av_freep(&ctx->hwctx);
228  av_freep(&ctx);
229  return NULL;
230 }
231 
233 {
235  AVFrame **frames;
236  int i, ret = 0;
237 
239  if (!frames)
240  return AVERROR(ENOMEM);
241 
242  for (i = 0; i < ctx->initial_pool_size; i++) {
243  frames[i] = av_frame_alloc();
244  if (!frames[i])
245  goto fail;
246 
247  ret = av_hwframe_get_buffer(ref, frames[i], 0);
248  if (ret < 0)
249  goto fail;
250  }
251 
252 fail:
253  for (i = 0; i < ctx->initial_pool_size; i++)
254  av_frame_free(&frames[i]);
255  av_freep(&frames);
256 
257  return ret;
258 }
259 
261 {
263  const enum AVPixelFormat *pix_fmt;
264  int ret;
265 
266  /* validate the pixel format */
268  if (*pix_fmt == ctx->format)
269  break;
270  }
271  if (*pix_fmt == AV_PIX_FMT_NONE) {
272  av_log(ctx, AV_LOG_ERROR,
273  "The hardware pixel format '%s' is not supported by the device type '%s'\n",
275  return AVERROR(ENOSYS);
276  }
277 
278  /* validate the dimensions */
279  ret = av_image_check_size(ctx->width, ctx->height, 0, ctx);
280  if (ret < 0)
281  return ret;
282 
283  /* format-specific init */
284  if (ctx->internal->hw_type->frames_init) {
285  ret = ctx->internal->hw_type->frames_init(ctx);
286  if (ret < 0)
287  goto fail;
288  }
289 
290  if (ctx->internal->pool_internal && !ctx->pool)
291  ctx->pool = ctx->internal->pool_internal;
292 
293  /* preallocate the frames in the pool, if requested */
294  if (ctx->initial_pool_size > 0) {
295  ret = hwframe_pool_prealloc(ref);
296  if (ret < 0)
297  goto fail;
298  }
299 
300  return 0;
301 fail:
302  if (ctx->internal->hw_type->frames_uninit)
303  ctx->internal->hw_type->frames_uninit(ctx);
304  return ret;
305 }
306 
309  enum AVPixelFormat **formats, int flags)
310 {
311  AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
312 
314  return AVERROR(ENOSYS);
315 
316  return ctx->internal->hw_type->transfer_get_formats(ctx, dir, formats);
317 }
318 
319 static int transfer_data_alloc(AVFrame *dst, const AVFrame *src, int flags)
320 {
321  AVFrame *frame_tmp;
322  int ret = 0;
323 
324  frame_tmp = av_frame_alloc();
325  if (!frame_tmp)
326  return AVERROR(ENOMEM);
327 
328  /* if the format is set, use that
329  * otherwise pick the first supported one */
330  if (dst->format >= 0) {
331  frame_tmp->format = dst->format;
332  } else {
333  enum AVPixelFormat *formats;
334 
337  &formats, 0);
338  if (ret < 0)
339  goto fail;
340  frame_tmp->format = formats[0];
341  av_freep(&formats);
342  }
343  frame_tmp->width = src->width;
344  frame_tmp->height = src->height;
345 
346  ret = av_frame_get_buffer(frame_tmp, 32);
347  if (ret < 0)
348  goto fail;
349 
350  ret = av_hwframe_transfer_data(frame_tmp, src, flags);
351  if (ret < 0)
352  goto fail;
353 
354  av_frame_move_ref(dst, frame_tmp);
355 
356 fail:
357  av_frame_free(&frame_tmp);
358  return ret;
359 }
360 
362 {
364  int ret;
365 
366  if (!dst->buf[0])
367  return transfer_data_alloc(dst, src, flags);
368 
369  if (src->hw_frames_ctx) {
370  ctx = (AVHWFramesContext*)src->hw_frames_ctx->data;
371 
372  ret = ctx->internal->hw_type->transfer_data_from(ctx, dst, src);
373  if (ret < 0)
374  return ret;
375  } else if (dst->hw_frames_ctx) {
376  ctx = (AVHWFramesContext*)dst->hw_frames_ctx->data;
377 
378  ret = ctx->internal->hw_type->transfer_data_to(ctx, dst, src);
379  if (ret < 0)
380  return ret;
381  } else
382  return AVERROR(ENOSYS);
383 
384  return 0;
385 }
386 
388 {
389  AVHWFramesContext *ctx = (AVHWFramesContext*)hwframe_ref->data;
390  int ret;
391 
393  return AVERROR(ENOSYS);
394 
395  if (!ctx->pool)
396  return AVERROR(EINVAL);
397 
398  frame->hw_frames_ctx = av_buffer_ref(hwframe_ref);
399  if (!frame->hw_frames_ctx)
400  return AVERROR(ENOMEM);
401 
402  ret = ctx->internal->hw_type->frames_get_buffer(ctx, frame);
403  if (ret < 0) {
405  return ret;
406  }
407 
408  return 0;
409 }
410 
412 {
414  const HWContextType *hw_type = ctx->internal->hw_type;
415 
416  if (hw_type->device_hwconfig_size == 0)
417  return NULL;
418 
419  return av_mallocz(hw_type->device_hwconfig_size);
420 }
421 
423  const void *hwconfig)
424 {
426  const HWContextType *hw_type = ctx->internal->hw_type;
427  AVHWFramesConstraints *constraints;
428 
429  if (!hw_type->frames_get_constraints)
430  return NULL;
431 
432  constraints = av_mallocz(sizeof(*constraints));
433  if (!constraints)
434  return NULL;
435 
436  constraints->min_width = constraints->min_height = 0;
437  constraints->max_width = constraints->max_height = INT_MAX;
438 
439  if (hw_type->frames_get_constraints(ctx, hwconfig, constraints) >= 0) {
440  return constraints;
441  } else {
442  av_hwframe_constraints_free(&constraints);
443  return NULL;
444  }
445 }
446 
448 {
449  if (*constraints) {
450  av_freep(&(*constraints)->valid_hw_formats);
451  av_freep(&(*constraints)->valid_sw_formats);
452  }
453  av_freep(constraints);
454 }
455 
457  const char *device, AVDictionary *opts, int flags)
458 {
459  AVBufferRef *device_ref = NULL;
460  AVHWDeviceContext *device_ctx;
461  int ret = 0;
462 
463  device_ref = av_hwdevice_ctx_alloc(type);
464  if (!device_ref) {
465  ret = AVERROR(ENOMEM);
466  goto fail;
467  }
468  device_ctx = (AVHWDeviceContext*)device_ref->data;
469 
470  if (!device_ctx->internal->hw_type->device_create) {
471  ret = AVERROR(ENOSYS);
472  goto fail;
473  }
474 
475  ret = device_ctx->internal->hw_type->device_create(device_ctx, device,
476  opts, flags);
477  if (ret < 0)
478  goto fail;
479 
480  ret = av_hwdevice_ctx_init(device_ref);
481  if (ret < 0)
482  goto fail;
483 
484  *pdevice_ref = device_ref;
485  return 0;
486 fail:
487  av_buffer_unref(&device_ref);
488  *pdevice_ref = NULL;
489  return ret;
490 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:53
#define NULL
Definition: coverity.c:32
static enum AVPixelFormat pix_fmt
static void hwdevice_ctx_free(void *opaque, uint8_t *data)
Definition: hwcontext.c:53
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:124
This structure describes decoded (raw) audio or video data.
Definition: frame.h:184
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
misc image utilities
void(* frames_uninit)(AVHWFramesContext *ctx)
#define LIBAVUTIL_VERSION_INT
Definition: version.h:70
memory handling functions
AVBufferRef * buf[AV_NUM_DATA_POINTERS]
AVBuffer references backing the data for this frame.
Definition: frame.h:363
const HWContextType ff_hwcontext_type_vdpau
AVFormatInternal * internal
An opaque field for libavformat internal usage.
Definition: avformat.h:1752
static enum AVSampleFormat formats[]
Definition: avresample.c:163
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:221
void * av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
Allocate a HW-specific configuration structure for a given HW device.
Definition: hwcontext.c:411
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:201
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition: frame.c:508
size_t device_priv_size
size of the private data, i.e.
const HWContextType * hw_type
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition: hwcontext.c:447
AVBufferRef * hw_frames_ctx
For hwaccel-format frames, this should be a reference to the AVHWFramesContext describing the frame...
Definition: frame.h:434
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:72
AVBufferPool * pool_internal
uint8_t
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:140
static int hwframe_pool_prealloc(AVBufferRef *ref)
Definition: hwcontext.c:232
size_t device_hwctx_size
size of the public hardware-specific context, i.e.
static AVFrame * frame
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:84
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:456
static void hwframe_ctx_free(void *opaque, uint8_t *data)
Definition: hwcontext.c:153
#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:147
#define av_log(a,...)
void(* free)(struct AVHWFramesContext *ctx)
This field may be set by the caller before calling av_hwframe_ctx_init().
Definition: hwcontext.h:162
int width
width and height of the video frame
Definition: frame.h:236
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
void(* free)(struct AVHWDeviceContext *ctx)
This field may be set by the caller before calling av_hwdevice_ctx_init().
Definition: hwcontext.h:96
av_default_item_name
#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:153
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:260
enum AVHWDeviceType type
This field identifies the underlying API used for hardware access.
Definition: hwcontext.h:71
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:387
#define fail()
Definition: checkasm.h:81
void(* device_uninit)(AVHWDeviceContext *ctx)
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:361
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:191
AVDictionary * opts
Definition: movenc.c:50
Transfer the data from the queried hw frame.
Definition: hwcontext.h:331
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:251
enum AVPixelFormat * pix_fmts
An array of pixel formats supported by the AVHWFramesContext instances Terminated by AV_PIX_FMT_NONE...
const char * name
AVFormatContext * ctx
Definition: movenc.c:48
int frames
Definition: movenc.c:65
#define src
Definition: vp9dsp.c:530
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:248
AVBufferRef * av_hwdevice_ctx_alloc(enum AVHWDeviceType type)
Allocate an AVHWDeviceContext for a given pixel format.
Definition: hwcontext.c:71
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:365
int(* device_create)(AVHWDeviceContext *ctx, const char *device, AVDictionary *opts, int flags)
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:422
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:154
const AVClass * av_class
A class for logging.
Definition: hwcontext.h:57
void * buf
Definition: avisynth_c.h:553
GLint GLenum type
Definition: opengl_enc.c:105
int av_hwdevice_ctx_init(AVBufferRef *ref)
Finalize the device context before use.
Definition: hwcontext.c:129
Describe the class of an AVClass context structure.
Definition: log.h:67
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:274
int(* frames_get_buffer)(AVHWFramesContext *ctx, AVFrame *frame)
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:116
const AVClass * av_class
A class for logging and AVOptions.
Definition: avformat.h:1330
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:319
AVHWFramesInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:126
int av_frame_get_buffer(AVFrame *frame, int align)
Allocate new buffer(s) for audio or video data.
Definition: frame.c:270
int(* transfer_data_from)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
static int flags
Definition: cpu.c:47
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:133
int(* transfer_data_to)(AVHWFramesContext *ctx, AVFrame *dst, const AVFrame *src)
A reference to a data buffer.
Definition: buffer.h:81
const HWContextType * hw_type
common internal and external API header
if(ret< 0)
Definition: vf_mcdeint.c:282
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:174
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:92
AVHWFrameTransferDirection
Definition: hwcontext.h:327
pixel format definitions
AVBufferPool * pool
A pool from which the frames are allocated by av_hwframe_get_buffer().
Definition: hwcontext.h:182
AVHWDeviceType
Definition: hwcontext.h:27
int(* transfer_get_formats)(AVHWFramesContext *ctx, enum AVHWFrameTransferDirection dir, enum AVPixelFormat **formats)
static void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.h:229
int height
Definition: frame.h:236
#define av_freep(p)
int(* device_init)(AVHWDeviceContext *ctx)
AVHWDeviceInternal * internal
Private data used internally by libavutil.
Definition: hwcontext.h:63
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:2138
static const AVClass hwdevice_ctx_class
Definition: hwcontext.c:47
int(* frames_init)(AVHWFramesContext *ctx)
const HWContextType ff_hwcontext_type_dxva2
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
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:252
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:307
const HWContextType ff_hwcontext_type_vaapi