FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ffmpeg_vaapi.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 "libavutil/avassert.h"
22 #include "libavutil/frame.h"
23 #include "libavutil/hwcontext.h"
24 #include "libavutil/log.h"
25 
26 #include "ffmpeg.h"
27 
28 
29 static AVClass vaapi_class = {
30  .class_name = "vaapi",
31  .item_name = av_default_item_name,
32  .version = LIBAVUTIL_VERSION_INT,
33 };
34 
35 #define DEFAULT_SURFACES 20
36 
37 typedef struct VAAPIDecoderContext {
38  const AVClass *class;
39 
44 
45  // The output need not have the same format, width and height as the
46  // decoded frames - the copy for non-direct-mapped access is actually
47  // a whole vpp instance which can do arbitrary scaling and format
48  // conversion.
51 
52 
54 {
55  InputStream *ist = avctx->opaque;
57  int err;
58 
59  err = av_hwframe_get_buffer(ctx->frames_ref, frame, 0);
60  if (err < 0) {
61  av_log(ctx, AV_LOG_ERROR, "Failed to allocate decoder surface.\n");
62  } else {
63  av_log(ctx, AV_LOG_DEBUG, "Decoder given surface %#x.\n",
64  (unsigned int)(uintptr_t)frame->data[3]);
65  }
66  return err;
67 }
68 
69 static int vaapi_retrieve_data(AVCodecContext *avctx, AVFrame *input)
70 {
71  InputStream *ist = avctx->opaque;
73  AVFrame *output = 0;
74  int err;
75 
77 
78  if (ctx->output_format == AV_PIX_FMT_VAAPI) {
79  // Nothing to do.
80  return 0;
81  }
82 
83  av_log(ctx, AV_LOG_DEBUG, "Retrieve data from surface %#x.\n",
84  (unsigned int)(uintptr_t)input->data[3]);
85 
86  output = av_frame_alloc();
87  if (!output)
88  return AVERROR(ENOMEM);
89 
90  output->format = ctx->output_format;
91 
92  err = av_hwframe_transfer_data(output, input, 0);
93  if (err < 0) {
94  av_log(ctx, AV_LOG_ERROR, "Failed to transfer data to "
95  "output frame: %d.\n", err);
96  goto fail;
97  }
98 
99  err = av_frame_copy_props(output, input);
100  if (err < 0) {
101  av_frame_unref(output);
102  goto fail;
103  }
104 
105  av_frame_unref(input);
106  av_frame_move_ref(input, output);
107  av_frame_free(&output);
108 
109  return 0;
110 
111 fail:
112  if (output)
113  av_frame_free(&output);
114  return err;
115 }
116 
118 {
119  InputStream *ist = avctx->opaque;
121 
122  if (ctx) {
125  av_free(ctx);
126  }
127 
129 
130  ist->hwaccel_ctx = NULL;
131  ist->hwaccel_uninit = NULL;
132  ist->hwaccel_get_buffer = NULL;
134 }
135 
137 {
138  InputStream *ist = avctx->opaque;
140  int err;
141  int loglevel = (ist->hwaccel_id != HWACCEL_VAAPI ? AV_LOG_VERBOSE
142  : AV_LOG_ERROR);
143 
144  if (ist->hwaccel_ctx)
145  vaapi_decode_uninit(avctx);
146 
147  // We have -hwaccel without -vaapi_device, so just initialise here with
148  // the device passed as -hwaccel_device (if -vaapi_device was passed, it
149  // will always have been called before now).
150  if (!hw_device_ctx) {
151  err = vaapi_device_init(ist->hwaccel_device);
152  if (err < 0)
153  return err;
154  }
155 
156  ctx = av_mallocz(sizeof(*ctx));
157  if (!ctx)
158  return AVERROR(ENOMEM);
159  ctx->class = &vaapi_class;
160  ist->hwaccel_ctx = ctx;
161 
163  ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
164 
166  avctx->pix_fmt = ctx->output_format;
167 
169  if (!ctx->frames_ref) {
170  av_log(ctx, loglevel, "Failed to create VAAPI frame context.\n");
171  err = AVERROR(ENOMEM);
172  goto fail;
173  }
174 
175  ctx->frames = (AVHWFramesContext*)ctx->frames_ref->data;
176 
178  ctx->frames->width = avctx->coded_width;
179  ctx->frames->height = avctx->coded_height;
180 
181  // It would be nice if we could query the available formats here,
182  // but unfortunately we don't have a VAConfigID to do it with.
183  // For now, just assume an NV12 format (or P010 if 10-bit).
184  ctx->frames->sw_format = (avctx->sw_pix_fmt == AV_PIX_FMT_YUV420P10 ?
186 
187  // For frame-threaded decoding, at least one additional surface
188  // is needed for each thread.
190  if (avctx->active_thread_type & FF_THREAD_FRAME)
191  ctx->frames->initial_pool_size += avctx->thread_count;
192 
193  err = av_hwframe_ctx_init(ctx->frames_ref);
194  if (err < 0) {
195  av_log(ctx, loglevel, "Failed to initialise VAAPI frame "
196  "context: %d\n", err);
197  goto fail;
198  }
199 
201  if (!ist->hw_frames_ctx) {
202  err = AVERROR(ENOMEM);
203  goto fail;
204  }
205 
209 
210  return 0;
211 
212 fail:
213  vaapi_decode_uninit(avctx);
214  return err;
215 }
216 
218 
219 av_cold int vaapi_device_init(const char *device)
220 {
221  int err;
222 
224 
226  device, NULL, 0);
227  if (err < 0) {
228  av_log(&vaapi_log, AV_LOG_ERROR, "Failed to create a VAAPI device\n");
229  return err;
230  }
231 
232  return 0;
233 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:55
#define NULL
Definition: coverity.c:32
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:194
AVHWDeviceContext * device
Definition: ffmpeg_vaapi.c:41
#define DEFAULT_SURFACES
Definition: ffmpeg_vaapi.c:35
AVBufferRef * hw_frames_ctx
Definition: ffmpeg.h:374
int coded_width
Bitstream width / height, may be different from width/height e.g.
Definition: avcodec.h:1947
#define LIBAVUTIL_VERSION_INT
Definition: version.h:86
const AVClass * class
Definition: ffmpeg_vaapi.c:38
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:223
enum AVPixelFormat pix_fmt
Pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:1973
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:203
void av_frame_move_ref(AVFrame *dst, AVFrame *src)
Move everything contained in src to dst and reset src.
Definition: frame.c:528
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:222
int(* hwaccel_get_buffer)(AVCodecContext *s, AVFrame *frame, int flags)
Definition: ffmpeg.h:370
int vaapi_decode_init(AVCodecContext *avctx)
Definition: ffmpeg_vaapi.c:136
#define AV_PIX_FMT_P010
Definition: pixfmt.h:394
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
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
#define av_cold
Definition: attributes.h:82
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:150
static AVFrame * frame
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:505
static int flags
Definition: log.c:57
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
static AVClass vaapi_class
Definition: ffmpeg_vaapi.c:29
#define av_log(a,...)
enum AVPixelFormat output_format
Definition: ffmpeg_vaapi.c:49
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
void(* hwaccel_uninit)(AVCodecContext *s)
Definition: ffmpeg.h:369
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:163
int active_thread_type
Which multithreading methods are in use by the codec.
Definition: avcodec.h:3193
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
planar YUV 4:2:0, 12bpp, 1 plane for Y and 1 plane for the UV components, which are interleaved (firs...
Definition: pixfmt.h:90
simple assert() macros that are a bit more flexible than ISO C assert().
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:271
static int vaapi_get_buffer(AVCodecContext *avctx, AVFrame *frame, int flags)
Definition: ffmpeg_vaapi.c:53
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:407
#define fail()
Definition: checkasm.h:90
reference-counted frame API
int av_hwframe_transfer_data(AVFrame *dst, const AVFrame *src, int flags)
Copy data to or from a hw surface.
Definition: hwcontext.c:381
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:193
#define FF_THREAD_FRAME
Decode more than one frame at once.
Definition: avcodec.h:3185
AVHWFramesContext * frames
Definition: ffmpeg_vaapi.c:43
AVFormatContext * ctx
Definition: movenc.c:48
AVBufferRef * frames_ref
Definition: ffmpeg_vaapi.c:42
int(* hwaccel_retrieve_data)(AVCodecContext *s, AVFrame *frame)
Definition: ffmpeg.h:371
int thread_count
thread count is used to decide how many independent tasks should be passed to execute() ...
Definition: avcodec.h:3174
int format
format of the frame, -1 if unknown or unset Values correspond to enum AVPixelFormat for video frames...
Definition: frame.h:267
av_cold int vaapi_device_init(const char *device)
Definition: ffmpeg_vaapi.c:219
main external API structure.
Definition: avcodec.h:1745
uint8_t * data
The data buffer.
Definition: buffer.h:89
AVBufferRef * device_ref
Definition: ffmpeg_vaapi.c:40
#define AV_PIX_FMT_YUV420P10
Definition: pixfmt.h:351
int coded_height
Definition: avcodec.h:1947
Describe the class of an AVClass context structure.
Definition: log.h:67
static int vaapi_retrieve_data(AVCodecContext *avctx, AVFrame *input)
Definition: ffmpeg_vaapi.c:69
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:118
enum AVPixelFormat hwaccel_output_format
Definition: ffmpeg.h:364
void av_frame_unref(AVFrame *frame)
Unreference all the buffers referenced by frame and reset the frame fields.
Definition: frame.c:502
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:208
A reference to a data buffer.
Definition: buffer.h:81
static void vaapi_decode_uninit(AVCodecContext *avctx)
Definition: ffmpeg_vaapi.c:117
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:185
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
AVBufferRef * hw_device_ctx
Definition: ffmpeg_opt.c:93
#define av_free(p)
static AVClass * vaapi_log
Definition: ffmpeg_vaapi.c:217
void * hwaccel_ctx
Definition: ffmpeg.h:368
char * hwaccel_device
Definition: ffmpeg.h:363
enum HWAccelID hwaccel_id
Definition: ffmpeg.h:362
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:216
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
enum AVPixelFormat sw_pix_fmt
Nominal unaccelerated pixel format, see AV_PIX_FMT_xxx.
Definition: avcodec.h:3449
void * opaque
Private data of the user, can be used to carry app specific stuff.
Definition: avcodec.h:1802
int av_frame_copy_props(AVFrame *dst, const AVFrame *src)
Copy only "metadata" fields from src to dst.
Definition: frame.c:600