FFmpeg  4.0
vaapi_vpp.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/avassert.h"
22 #include "libavutil/pixdesc.h"
23 #include "formats.h"
24 #include "internal.h"
25 #include "vaapi_vpp.h"
26 
28 {
29  enum AVPixelFormat pix_fmts[] = {
31  };
32  int err;
33 
34  if ((err = ff_formats_ref(ff_make_format_list(pix_fmts),
35  &avctx->inputs[0]->out_formats)) < 0)
36  return err;
37  if ((err = ff_formats_ref(ff_make_format_list(pix_fmts),
38  &avctx->outputs[0]->in_formats)) < 0)
39  return err;
40 
41  return 0;
42 }
43 
45 {
46  VAAPIVPPContext *ctx = avctx->priv;
47  int i;
48  for (i = 0; i < ctx->nb_filter_buffers; i++) {
49  if (ctx->filter_buffers[i] != VA_INVALID_ID) {
50  vaDestroyBuffer(ctx->hwctx->display, ctx->filter_buffers[i]);
51  ctx->filter_buffers[i] = VA_INVALID_ID;
52  }
53  }
54  ctx->nb_filter_buffers = 0;
55 
56  if (ctx->va_context != VA_INVALID_ID) {
57  vaDestroyContext(ctx->hwctx->display, ctx->va_context);
58  ctx->va_context = VA_INVALID_ID;
59  }
60 
61  if (ctx->va_config != VA_INVALID_ID) {
62  vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
63  ctx->va_config = VA_INVALID_ID;
64  }
65 
67  ctx->hwctx = NULL;
68 }
69 
71 {
72  AVFilterContext *avctx = inlink->dst;
73  VAAPIVPPContext *ctx = avctx->priv;
74 
75  if (ctx->pipeline_uninit)
76  ctx->pipeline_uninit(avctx);
77 
78  if (!inlink->hw_frames_ctx) {
79  av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
80  "required to associate the processing device.\n");
81  return AVERROR(EINVAL);
82  }
83 
85  if (!ctx->input_frames_ref) {
86  av_log(avctx, AV_LOG_ERROR, "A input frames reference create "
87  "failed.\n");
88  return AVERROR(ENOMEM);
89  }
91 
92  return 0;
93 }
94 
96 {
97  AVFilterContext *avctx = outlink->src;
98  VAAPIVPPContext *ctx = avctx->priv;
99  AVVAAPIHWConfig *hwconfig = NULL;
100  AVHWFramesConstraints *constraints = NULL;
101  AVHWFramesContext *output_frames;
102  AVVAAPIFramesContext *va_frames;
103  VAStatus vas;
104  int err, i;
105 
106  if (ctx->pipeline_uninit)
107  ctx->pipeline_uninit(avctx);
108 
109  if (!ctx->output_width)
110  ctx->output_width = avctx->inputs[0]->w;
111  if (!ctx->output_height)
112  ctx->output_height = avctx->inputs[0]->h;
113 
114  av_assert0(ctx->input_frames);
116  if (!ctx->device_ref) {
117  av_log(avctx, AV_LOG_ERROR, "A device reference create "
118  "failed.\n");
119  return AVERROR(ENOMEM);
120  }
121  ctx->hwctx = ((AVHWDeviceContext*)ctx->device_ref->data)->hwctx;
122 
123  av_assert0(ctx->va_config == VA_INVALID_ID);
124  vas = vaCreateConfig(ctx->hwctx->display, VAProfileNone,
125  VAEntrypointVideoProc, NULL, 0, &ctx->va_config);
126  if (vas != VA_STATUS_SUCCESS) {
127  av_log(avctx, AV_LOG_ERROR, "Failed to create processing pipeline "
128  "config: %d (%s).\n", vas, vaErrorStr(vas));
129  err = AVERROR(EIO);
130  goto fail;
131  }
132 
133  hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
134  if (!hwconfig) {
135  err = AVERROR(ENOMEM);
136  goto fail;
137  }
138  hwconfig->config_id = ctx->va_config;
139 
141  hwconfig);
142  if (!constraints) {
143  err = AVERROR(ENOMEM);
144  goto fail;
145  }
146 
147  if (ctx->output_format == AV_PIX_FMT_NONE)
148  ctx->output_format = ctx->input_frames->sw_format;
149  if (constraints->valid_sw_formats) {
150  for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
151  if (ctx->output_format == constraints->valid_sw_formats[i])
152  break;
153  }
154  if (constraints->valid_sw_formats[i] == AV_PIX_FMT_NONE) {
155  av_log(avctx, AV_LOG_ERROR, "Hardware does not support output "
156  "format %s.\n", av_get_pix_fmt_name(ctx->output_format));
157  err = AVERROR(EINVAL);
158  goto fail;
159  }
160  }
161 
162  if (ctx->output_width < constraints->min_width ||
163  ctx->output_height < constraints->min_height ||
164  ctx->output_width > constraints->max_width ||
165  ctx->output_height > constraints->max_height) {
166  av_log(avctx, AV_LOG_ERROR, "Hardware does not support scaling to "
167  "size %dx%d (constraints: width %d-%d height %d-%d).\n",
168  ctx->output_width, ctx->output_height,
169  constraints->min_width, constraints->max_width,
170  constraints->min_height, constraints->max_height);
171  err = AVERROR(EINVAL);
172  goto fail;
173  }
174 
176  if (!outlink->hw_frames_ctx) {
177  av_log(avctx, AV_LOG_ERROR, "Failed to create HW frame context "
178  "for output.\n");
179  err = AVERROR(ENOMEM);
180  goto fail;
181  }
182 
183  output_frames = (AVHWFramesContext*)outlink->hw_frames_ctx->data;
184 
185  output_frames->format = AV_PIX_FMT_VAAPI;
186  output_frames->sw_format = ctx->output_format;
187  output_frames->width = ctx->output_width;
188  output_frames->height = ctx->output_height;
189 
190  output_frames->initial_pool_size = 4;
191 
192  err = ff_filter_init_hw_frames(avctx, outlink, 10);
193  if (err < 0)
194  goto fail;
195 
196  err = av_hwframe_ctx_init(outlink->hw_frames_ctx);
197  if (err < 0) {
198  av_log(avctx, AV_LOG_ERROR, "Failed to initialise VAAPI frame "
199  "context for output: %d\n", err);
200  goto fail;
201  }
202 
203  va_frames = output_frames->hwctx;
204 
205  av_assert0(ctx->va_context == VA_INVALID_ID);
206  vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
207  ctx->output_width, ctx->output_height,
208  VA_PROGRESSIVE,
209  va_frames->surface_ids, va_frames->nb_surfaces,
210  &ctx->va_context);
211  if (vas != VA_STATUS_SUCCESS) {
212  av_log(avctx, AV_LOG_ERROR, "Failed to create processing pipeline "
213  "context: %d (%s).\n", vas, vaErrorStr(vas));
214  return AVERROR(EIO);
215  }
216 
217  outlink->w = ctx->output_width;
218  outlink->h = ctx->output_height;
219 
220  if (ctx->build_filter_params) {
221  err = ctx->build_filter_params(avctx);
222  if (err < 0)
223  goto fail;
224  }
225 
226  av_freep(&hwconfig);
227  av_hwframe_constraints_free(&constraints);
228  return 0;
229 
230 fail:
231  av_buffer_unref(&outlink->hw_frames_ctx);
232  av_freep(&hwconfig);
233  av_hwframe_constraints_free(&constraints);
234  return err;
235 }
236 
238 {
239  switch(av_cs) {
240 #define CS(av, va) case AVCOL_SPC_ ## av: return VAProcColorStandard ## va;
241  CS(BT709, BT709);
242  CS(BT470BG, BT601);
243  CS(SMPTE170M, SMPTE170M);
244  CS(SMPTE240M, SMPTE240M);
245 #undef CS
246  default:
247  return VAProcColorStandardNone;
248  }
249 }
250 
252  int type,
253  const void *data,
254  size_t size,
255  int count)
256 {
257  VAStatus vas;
258  VABufferID buffer;
259  VAAPIVPPContext *ctx = avctx->priv;
260 
261  av_assert0(ctx->nb_filter_buffers + 1 <= VAProcFilterCount);
262 
263  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
264  type, size, count, (void*)data, &buffer);
265  if (vas != VA_STATUS_SUCCESS) {
266  av_log(avctx, AV_LOG_ERROR, "Failed to create parameter "
267  "buffer (type %d): %d (%s).\n",
268  type, vas, vaErrorStr(vas));
269  return AVERROR(EIO);
270  }
271 
272  ctx->filter_buffers[ctx->nb_filter_buffers++] = buffer;
273 
274  av_log(avctx, AV_LOG_DEBUG, "Param buffer (type %d, %zu bytes, count %d) "
275  "is %#x.\n", type, size, count, buffer);
276  return 0;
277 }
278 
279 
281  VAProcPipelineParameterBuffer *params,
282  VASurfaceID output_surface)
283 {
284  VABufferID params_id;
285  VAStatus vas;
286  int err = 0;
287  VAAPIVPPContext *ctx = avctx->priv;
288 
289  vas = vaBeginPicture(ctx->hwctx->display,
290  ctx->va_context, output_surface);
291  if (vas != VA_STATUS_SUCCESS) {
292  av_log(avctx, AV_LOG_ERROR, "Failed to attach new picture: "
293  "%d (%s).\n", vas, vaErrorStr(vas));
294  err = AVERROR(EIO);
295  goto fail;
296  }
297 
298  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
299  VAProcPipelineParameterBufferType,
300  sizeof(*params), 1, params, &params_id);
301  if (vas != VA_STATUS_SUCCESS) {
302  av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer: "
303  "%d (%s).\n", vas, vaErrorStr(vas));
304  err = AVERROR(EIO);
305  goto fail_after_begin;
306  }
307  av_log(avctx, AV_LOG_DEBUG, "Pipeline parameter buffer is %#x.\n",
308  params_id);
309 
310  vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
311  &params_id, 1);
312  if (vas != VA_STATUS_SUCCESS) {
313  av_log(avctx, AV_LOG_ERROR, "Failed to render parameter buffer: "
314  "%d (%s).\n", vas, vaErrorStr(vas));
315  err = AVERROR(EIO);
316  goto fail_after_begin;
317  }
318 
319  vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
320  if (vas != VA_STATUS_SUCCESS) {
321  av_log(avctx, AV_LOG_ERROR, "Failed to start picture processing: "
322  "%d (%s).\n", vas, vaErrorStr(vas));
323  err = AVERROR(EIO);
324  goto fail_after_render;
325  }
326 
327  if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
329  vas = vaDestroyBuffer(ctx->hwctx->display, params_id);
330  if (vas != VA_STATUS_SUCCESS) {
331  av_log(avctx, AV_LOG_ERROR, "Failed to free parameter buffer: "
332  "%d (%s).\n", vas, vaErrorStr(vas));
333  // And ignore.
334  }
335  }
336 
337  return 0;
338 
339  // We want to make sure that if vaBeginPicture has been called, we also
340  // call vaRenderPicture and vaEndPicture. These calls may well fail or
341  // do something else nasty, but once we're in this failure case there
342  // isn't much else we can do.
343 fail_after_begin:
344  vaRenderPicture(ctx->hwctx->display, ctx->va_context, &params_id, 1);
345 fail_after_render:
346  vaEndPicture(ctx->hwctx->display, ctx->va_context);
347 fail:
348  return err;
349 }
350 
352 {
353  int i;
354  VAAPIVPPContext *ctx = avctx->priv;
355 
356  ctx->va_config = VA_INVALID_ID;
357  ctx->va_context = VA_INVALID_ID;
358  ctx->valid_ids = 1;
359 
360  for (i = 0; i < VAProcFilterCount; i++)
361  ctx->filter_buffers[i] = VA_INVALID_ID;
362  ctx->nb_filter_buffers = 0;
363 }
364 
366 {
367  VAAPIVPPContext *ctx = avctx->priv;
368  if (ctx->valid_ids && ctx->pipeline_uninit)
369  ctx->pipeline_uninit(avctx);
370 
373 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
#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
int size
VAAPI-specific data associated with a frame pool.
int ff_vaapi_vpp_config_input(AVFilterLink *inlink)
Definition: vaapi_vpp.c:70
int ff_vaapi_vpp_config_output(AVFilterLink *outlink)
Definition: vaapi_vpp.c:95
int nb_filter_buffers
Definition: vaapi_vpp.h:48
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
void * av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
Allocate a HW-specific configuration structure for a given HW device.
Definition: hwcontext.c:526
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:208
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:457
AVFilterFormats * ff_make_format_list(const int *fmts)
Create a list of supported formats.
Definition: formats.c:283
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition: hwcontext.c:562
AVFilterLink ** inputs
array of pointers to input links
Definition: avfilter.h:346
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
static char buffer[20]
Definition: seek.c:32
AVColorSpace
YUV colorspace type.
Definition: pixfmt.h:473
const char data[16]
Definition: mxf.c:90
#define CONFIG_VAAPI_1
Definition: config.h:656
#define av_log(a,...)
int ff_vaapi_vpp_render_picture(AVFilterContext *avctx, VAProcPipelineParameterBuffer *params, VASurfaceID output_surface)
Definition: vaapi_vpp.c:280
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
VAAPI hardware pipeline configuration details.
#define CS(av, va)
AVBufferRef * input_frames_ref
Definition: vaapi_vpp.h:40
#define AVERROR(e)
Definition: error.h:43
void * priv
private data for use by the filter
Definition: avfilter.h:353
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
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:329
int ff_vaapi_vpp_make_param_buffers(AVFilterContext *avctx, int type, const void *data, size_t size, int count)
Definition: vaapi_vpp.c:251
#define fail()
Definition: checkasm.h:116
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:198
int ff_formats_ref(AVFilterFormats *f, AVFilterFormats **ref)
Add *ref as a new reference to formats.
Definition: formats.c:440
void ff_vaapi_vpp_pipeline_uninit(AVFilterContext *avctx)
Definition: vaapi_vpp.c:44
AVFormatContext * ctx
Definition: movenc.c:48
VADisplay display
The VADisplay handle, to be filled by the user.
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:450
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:432
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:537
uint8_t * data
The data buffer.
Definition: buffer.h:89
VABufferID filter_buffers[VAProcFilterCount]
Definition: vaapi_vpp.h:47
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:161
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
VAConfigID va_config
Definition: vaapi_vpp.h:37
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
cl_device_type type
AVFilterLink ** outputs
array of pointers to output links
Definition: avfilter.h:350
static enum AVPixelFormat pix_fmts[]
Definition: libkvazaar.c:266
VAContextID va_context
Definition: vaapi_vpp.h:38
enum AVPixelFormat output_format
Definition: vaapi_vpp.h:43
AVVAAPIDeviceContext * hwctx
Definition: vaapi_vpp.h:33
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:140
const char const char * params
Definition: avisynth_c.h:775
int ff_vaapi_vpp_query_formats(AVFilterContext *avctx)
Definition: vaapi_vpp.c:27
void ff_vaapi_vpp_ctx_init(AVFilterContext *avctx)
Definition: vaapi_vpp.c:351
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:243
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
int ff_filter_init_hw_frames(AVFilterContext *avctx, AVFilterLink *link, int default_pool_size)
Perform any additional setup required for hardware frames.
Definition: avfilter.c:1625
int ff_vaapi_vpp_colour_standard(enum AVColorSpace av_cs)
Definition: vaapi_vpp.c:237
AVHWFramesContext * input_frames
Definition: vaapi_vpp.h:41
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:444
VAConfigID config_id
ID of a VAAPI pipeline configuration.
An instance of a filter.
Definition: avfilter.h:338
#define av_freep(p)
void INT64 INT64 count
Definition: avisynth_c.h:690
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
AVBufferRef * device_ref
Definition: vaapi_vpp.h:34
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:2279
int(* build_filter_params)(AVFilterContext *avctx)
Definition: vaapi_vpp.h:50
internal API functions
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:221
AVPixelFormat
Pixel format.
Definition: pixfmt.h:60
void(* pipeline_uninit)(AVFilterContext *avctx)
Definition: vaapi_vpp.h:52
void ff_vaapi_vpp_ctx_uninit(AVFilterContext *avctx)
Definition: vaapi_vpp.c:365