FFmpeg
vaapi_encode.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_components.h"
20 
21 #include <inttypes.h>
22 #include <string.h>
23 
24 #include "libavutil/avassert.h"
25 #include "libavutil/common.h"
26 #include "libavutil/internal.h"
27 #include "libavutil/log.h"
28 #include "libavutil/pixdesc.h"
29 
30 #include "vaapi_encode.h"
31 #include "encode.h"
32 #include "avcodec.h"
33 
35  HW_CONFIG_ENCODER_FRAMES(VAAPI, VAAPI),
36  NULL,
37 };
38 
39 static const char * const picture_type_name[] = { "IDR", "I", "P", "B" };
40 
42  VAAPIEncodePicture *pic,
43  int type, char *data, size_t bit_len)
44 {
46  VAStatus vas;
47  VABufferID param_buffer, data_buffer;
48  VABufferID *tmp;
49  VAEncPackedHeaderParameterBuffer params = {
50  .type = type,
51  .bit_length = bit_len,
52  .has_emulation_bytes = 1,
53  };
54 
55  tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), pic->nb_param_buffers + 2);
56  if (!tmp)
57  return AVERROR(ENOMEM);
58  pic->param_buffers = tmp;
59 
60  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
61  VAEncPackedHeaderParameterBufferType,
62  sizeof(params), 1, &params, &param_buffer);
63  if (vas != VA_STATUS_SUCCESS) {
64  av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
65  "for packed header (type %d): %d (%s).\n",
66  type, vas, vaErrorStr(vas));
67  return AVERROR(EIO);
68  }
69  pic->param_buffers[pic->nb_param_buffers++] = param_buffer;
70 
71  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
72  VAEncPackedHeaderDataBufferType,
73  (bit_len + 7) / 8, 1, data, &data_buffer);
74  if (vas != VA_STATUS_SUCCESS) {
75  av_log(avctx, AV_LOG_ERROR, "Failed to create data buffer "
76  "for packed header (type %d): %d (%s).\n",
77  type, vas, vaErrorStr(vas));
78  return AVERROR(EIO);
79  }
80  pic->param_buffers[pic->nb_param_buffers++] = data_buffer;
81 
82  av_log(avctx, AV_LOG_DEBUG, "Packed header buffer (%d) is %#x/%#x "
83  "(%zu bits).\n", type, param_buffer, data_buffer, bit_len);
84  return 0;
85 }
86 
88  VAAPIEncodePicture *pic,
89  int type, char *data, size_t len)
90 {
92  VAStatus vas;
93  VABufferID *tmp;
94  VABufferID buffer;
95 
96  tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), pic->nb_param_buffers + 1);
97  if (!tmp)
98  return AVERROR(ENOMEM);
99  pic->param_buffers = tmp;
100 
101  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
102  type, len, 1, data, &buffer);
103  if (vas != VA_STATUS_SUCCESS) {
104  av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
105  "(type %d): %d (%s).\n", type, vas, vaErrorStr(vas));
106  return AVERROR(EIO);
107  }
108  pic->param_buffers[pic->nb_param_buffers++] = buffer;
109 
110  av_log(avctx, AV_LOG_DEBUG, "Param buffer (%d) is %#x.\n",
111  type, buffer);
112  return 0;
113 }
114 
116  VAAPIEncodePicture *pic,
117  int type,
118  const void *data, size_t len)
119 {
120  // Construct the buffer on the stack - 1KB is much larger than any
121  // current misc parameter buffer type (the largest is EncQuality at
122  // 224 bytes).
123  uint8_t buffer[1024];
124  VAEncMiscParameterBuffer header = {
125  .type = type,
126  };
127  size_t buffer_size = sizeof(header) + len;
128  av_assert0(buffer_size <= sizeof(buffer));
129 
130  memcpy(buffer, &header, sizeof(header));
131  memcpy(buffer + sizeof(header), data, len);
132 
133  return vaapi_encode_make_param_buffer(avctx, pic,
134  VAEncMiscParameterBufferType,
135  buffer, buffer_size);
136 }
137 
139  VAAPIEncodePicture *pic)
140 {
141  VAAPIEncodeContext *ctx = avctx->priv_data;
142  VAStatus vas;
143 
145 
146  if (pic->encode_complete) {
147  // Already waited for this picture.
148  return 0;
149  }
150 
151  av_log(avctx, AV_LOG_DEBUG, "Sync to pic %"PRId64"/%"PRId64" "
152  "(input surface %#x).\n", pic->display_order,
153  pic->encode_order, pic->input_surface);
154 
155 #if VA_CHECK_VERSION(1, 9, 0)
156  if (ctx->has_sync_buffer_func) {
157  vas = vaSyncBuffer(ctx->hwctx->display,
158  pic->output_buffer,
159  VA_TIMEOUT_INFINITE);
160  if (vas != VA_STATUS_SUCCESS) {
161  av_log(avctx, AV_LOG_ERROR, "Failed to sync to output buffer completion: "
162  "%d (%s).\n", vas, vaErrorStr(vas));
163  return AVERROR(EIO);
164  }
165  } else
166 #endif
167  { // If vaSyncBuffer is not implemented, try old version API.
168  vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
169  if (vas != VA_STATUS_SUCCESS) {
170  av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
171  "%d (%s).\n", vas, vaErrorStr(vas));
172  return AVERROR(EIO);
173  }
174  }
175 
176  // Input is definitely finished with now.
177  av_frame_free(&pic->input_image);
178 
179  pic->encode_complete = 1;
180  return 0;
181 }
182 
184  VAAPIEncodePicture *pic)
185 {
186  VAAPIEncodeContext *ctx = avctx->priv_data;
187  VAAPIEncodeSlice *slice;
188  int i, rounding;
189 
190  for (i = 0; i < pic->nb_slices; i++)
191  pic->slices[i].row_size = ctx->slice_size;
192 
193  rounding = ctx->slice_block_rows - ctx->nb_slices * ctx->slice_size;
194  if (rounding > 0) {
195  // Place rounding error at top and bottom of frame.
196  av_assert0(rounding < pic->nb_slices);
197  // Some Intel drivers contain a bug where the encoder will fail
198  // if the last slice is smaller than the one before it. Since
199  // that's straightforward to avoid here, just do so.
200  if (rounding <= 2) {
201  for (i = 0; i < rounding; i++)
202  ++pic->slices[i].row_size;
203  } else {
204  for (i = 0; i < (rounding + 1) / 2; i++)
205  ++pic->slices[pic->nb_slices - i - 1].row_size;
206  for (i = 0; i < rounding / 2; i++)
207  ++pic->slices[i].row_size;
208  }
209  } else if (rounding < 0) {
210  // Remove rounding error from last slice only.
211  av_assert0(rounding < ctx->slice_size);
212  pic->slices[pic->nb_slices - 1].row_size += rounding;
213  }
214 
215  for (i = 0; i < pic->nb_slices; i++) {
216  slice = &pic->slices[i];
217  slice->index = i;
218  if (i == 0) {
219  slice->row_start = 0;
220  slice->block_start = 0;
221  } else {
222  const VAAPIEncodeSlice *prev = &pic->slices[i - 1];
223  slice->row_start = prev->row_start + prev->row_size;
224  slice->block_start = prev->block_start + prev->block_size;
225  }
226  slice->block_size = slice->row_size * ctx->slice_block_cols;
227 
228  av_log(avctx, AV_LOG_DEBUG, "Slice %d: %d-%d (%d rows), "
229  "%d-%d (%d blocks).\n", i, slice->row_start,
230  slice->row_start + slice->row_size - 1, slice->row_size,
231  slice->block_start, slice->block_start + slice->block_size - 1,
232  slice->block_size);
233  }
234 
235  return 0;
236 }
237 
239  VAAPIEncodePicture *pic)
240 {
241  VAAPIEncodeContext *ctx = avctx->priv_data;
242  VAAPIEncodeSlice *slice;
243  int i, j, index;
244 
245  for (i = 0; i < ctx->tile_cols; i++) {
246  for (j = 0; j < ctx->tile_rows; j++) {
247  index = j * ctx->tile_cols + i;
248  slice = &pic->slices[index];
249  slice->index = index;
250 
251  pic->slices[index].block_start = ctx->col_bd[i] +
252  ctx->row_bd[j] * ctx->slice_block_cols;
253  pic->slices[index].block_size = ctx->row_height[j] * ctx->col_width[i];
254 
255  av_log(avctx, AV_LOG_DEBUG, "Slice %2d: (%2d, %2d) start at: %4d "
256  "width:%2d height:%2d (%d blocks).\n", index, ctx->col_bd[i],
257  ctx->row_bd[j], slice->block_start, ctx->col_width[i],
258  ctx->row_height[j], slice->block_size);
259  }
260  }
261 
262  return 0;
263 }
264 
266  VAAPIEncodePicture *pic)
267 {
268  VAAPIEncodeContext *ctx = avctx->priv_data;
269  VAAPIEncodeSlice *slice;
270  VAStatus vas;
271  int err, i;
273  size_t bit_len;
275 
276  av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "
277  "as type %s.\n", pic->display_order, pic->encode_order,
278  picture_type_name[pic->type]);
279  if (pic->nb_refs == 0) {
280  av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n");
281  } else {
282  av_log(avctx, AV_LOG_DEBUG, "Refers to:");
283  for (i = 0; i < pic->nb_refs; i++) {
284  av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
285  pic->refs[i]->display_order, pic->refs[i]->encode_order);
286  }
287  av_log(avctx, AV_LOG_DEBUG, ".\n");
288  }
289 
290  av_assert0(!pic->encode_issued);
291  for (i = 0; i < pic->nb_refs; i++) {
292  av_assert0(pic->refs[i]);
293  av_assert0(pic->refs[i]->encode_issued);
294  }
295 
296  av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface);
297 
298  pic->recon_image = av_frame_alloc();
299  if (!pic->recon_image) {
300  err = AVERROR(ENOMEM);
301  goto fail;
302  }
303 
304  err = av_hwframe_get_buffer(ctx->recon_frames_ref, pic->recon_image, 0);
305  if (err < 0) {
306  err = AVERROR(ENOMEM);
307  goto fail;
308  }
309  pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3];
310  av_log(avctx, AV_LOG_DEBUG, "Recon surface is %#x.\n", pic->recon_surface);
311 
312  pic->output_buffer_ref = av_buffer_pool_get(ctx->output_buffer_pool);
313  if (!pic->output_buffer_ref) {
314  err = AVERROR(ENOMEM);
315  goto fail;
316  }
317  pic->output_buffer = (VABufferID)(uintptr_t)pic->output_buffer_ref->data;
318  av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n",
319  pic->output_buffer);
320 
321  if (ctx->codec->picture_params_size > 0) {
322  pic->codec_picture_params = av_malloc(ctx->codec->picture_params_size);
323  if (!pic->codec_picture_params)
324  goto fail;
325  memcpy(pic->codec_picture_params, ctx->codec_picture_params,
326  ctx->codec->picture_params_size);
327  } else {
328  av_assert0(!ctx->codec_picture_params);
329  }
330 
331  pic->nb_param_buffers = 0;
332 
333  if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) {
334  err = vaapi_encode_make_param_buffer(avctx, pic,
335  VAEncSequenceParameterBufferType,
336  ctx->codec_sequence_params,
337  ctx->codec->sequence_params_size);
338  if (err < 0)
339  goto fail;
340  }
341 
342  if (pic->type == PICTURE_TYPE_IDR) {
343  for (i = 0; i < ctx->nb_global_params; i++) {
344  err = vaapi_encode_make_misc_param_buffer(avctx, pic,
345  ctx->global_params_type[i],
346  ctx->global_params[i],
347  ctx->global_params_size[i]);
348  if (err < 0)
349  goto fail;
350  }
351  }
352 
353  if (ctx->codec->init_picture_params) {
354  err = ctx->codec->init_picture_params(avctx, pic);
355  if (err < 0) {
356  av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture "
357  "parameters: %d.\n", err);
358  goto fail;
359  }
360  err = vaapi_encode_make_param_buffer(avctx, pic,
361  VAEncPictureParameterBufferType,
363  ctx->codec->picture_params_size);
364  if (err < 0)
365  goto fail;
366  }
367 
368 #if VA_CHECK_VERSION(1, 5, 0)
369  if (ctx->max_frame_size) {
370  err = vaapi_encode_make_misc_param_buffer(avctx, pic,
371  VAEncMiscParameterTypeMaxFrameSize,
372  &ctx->mfs_params,
373  sizeof(ctx->mfs_params));
374  if (err < 0)
375  goto fail;
376  }
377 #endif
378 
379  if (pic->type == PICTURE_TYPE_IDR) {
380  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
381  ctx->codec->write_sequence_header) {
382  bit_len = 8 * sizeof(data);
383  err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
384  if (err < 0) {
385  av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence "
386  "header: %d.\n", err);
387  goto fail;
388  }
389  err = vaapi_encode_make_packed_header(avctx, pic,
390  ctx->codec->sequence_header_type,
391  data, bit_len);
392  if (err < 0)
393  goto fail;
394  }
395  }
396 
397  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_PICTURE &&
398  ctx->codec->write_picture_header) {
399  bit_len = 8 * sizeof(data);
400  err = ctx->codec->write_picture_header(avctx, pic, data, &bit_len);
401  if (err < 0) {
402  av_log(avctx, AV_LOG_ERROR, "Failed to write per-picture "
403  "header: %d.\n", err);
404  goto fail;
405  }
406  err = vaapi_encode_make_packed_header(avctx, pic,
407  ctx->codec->picture_header_type,
408  data, bit_len);
409  if (err < 0)
410  goto fail;
411  }
412 
413  if (ctx->codec->write_extra_buffer) {
414  for (i = 0;; i++) {
415  size_t len = sizeof(data);
416  int type;
417  err = ctx->codec->write_extra_buffer(avctx, pic, i, &type,
418  data, &len);
419  if (err == AVERROR_EOF)
420  break;
421  if (err < 0) {
422  av_log(avctx, AV_LOG_ERROR, "Failed to write extra "
423  "buffer %d: %d.\n", i, err);
424  goto fail;
425  }
426 
427  err = vaapi_encode_make_param_buffer(avctx, pic, type,
428  data, len);
429  if (err < 0)
430  goto fail;
431  }
432  }
433 
434  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_MISC &&
435  ctx->codec->write_extra_header) {
436  for (i = 0;; i++) {
437  int type;
438  bit_len = 8 * sizeof(data);
439  err = ctx->codec->write_extra_header(avctx, pic, i, &type,
440  data, &bit_len);
441  if (err == AVERROR_EOF)
442  break;
443  if (err < 0) {
444  av_log(avctx, AV_LOG_ERROR, "Failed to write extra "
445  "header %d: %d.\n", i, err);
446  goto fail;
447  }
448 
449  err = vaapi_encode_make_packed_header(avctx, pic, type,
450  data, bit_len);
451  if (err < 0)
452  goto fail;
453  }
454  }
455 
456  if (pic->nb_slices == 0)
457  pic->nb_slices = ctx->nb_slices;
458  if (pic->nb_slices > 0) {
459  pic->slices = av_calloc(pic->nb_slices, sizeof(*pic->slices));
460  if (!pic->slices) {
461  err = AVERROR(ENOMEM);
462  goto fail;
463  }
464 
465  if (ctx->tile_rows && ctx->tile_cols)
466  vaapi_encode_make_tile_slice(avctx, pic);
467  else
468  vaapi_encode_make_row_slice(avctx, pic);
469  }
470 
471  for (i = 0; i < pic->nb_slices; i++) {
472  slice = &pic->slices[i];
473 
474  if (ctx->codec->slice_params_size > 0) {
475  slice->codec_slice_params = av_mallocz(ctx->codec->slice_params_size);
476  if (!slice->codec_slice_params) {
477  err = AVERROR(ENOMEM);
478  goto fail;
479  }
480  }
481 
482  if (ctx->codec->init_slice_params) {
483  err = ctx->codec->init_slice_params(avctx, pic, slice);
484  if (err < 0) {
485  av_log(avctx, AV_LOG_ERROR, "Failed to initialise slice "
486  "parameters: %d.\n", err);
487  goto fail;
488  }
489  }
490 
491  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SLICE &&
492  ctx->codec->write_slice_header) {
493  bit_len = 8 * sizeof(data);
494  err = ctx->codec->write_slice_header(avctx, pic, slice,
495  data, &bit_len);
496  if (err < 0) {
497  av_log(avctx, AV_LOG_ERROR, "Failed to write per-slice "
498  "header: %d.\n", err);
499  goto fail;
500  }
501  err = vaapi_encode_make_packed_header(avctx, pic,
502  ctx->codec->slice_header_type,
503  data, bit_len);
504  if (err < 0)
505  goto fail;
506  }
507 
508  if (ctx->codec->init_slice_params) {
509  err = vaapi_encode_make_param_buffer(avctx, pic,
510  VAEncSliceParameterBufferType,
511  slice->codec_slice_params,
512  ctx->codec->slice_params_size);
513  if (err < 0)
514  goto fail;
515  }
516  }
517 
518 #if VA_CHECK_VERSION(1, 0, 0)
521  if (sd && ctx->roi_allowed) {
522  const AVRegionOfInterest *roi;
523  uint32_t roi_size;
524  VAEncMiscParameterBufferROI param_roi;
525  int nb_roi, i, v;
526 
527  roi = (const AVRegionOfInterest*)sd->data;
528  roi_size = roi->self_size;
529  av_assert0(roi_size && sd->size % roi_size == 0);
530  nb_roi = sd->size / roi_size;
531  if (nb_roi > ctx->roi_max_regions) {
532  if (!ctx->roi_warned) {
533  av_log(avctx, AV_LOG_WARNING, "More ROIs set than "
534  "supported by driver (%d > %d).\n",
535  nb_roi, ctx->roi_max_regions);
536  ctx->roi_warned = 1;
537  }
538  nb_roi = ctx->roi_max_regions;
539  }
540 
541  pic->roi = av_calloc(nb_roi, sizeof(*pic->roi));
542  if (!pic->roi) {
543  err = AVERROR(ENOMEM);
544  goto fail;
545  }
546  // For overlapping regions, the first in the array takes priority.
547  for (i = 0; i < nb_roi; i++) {
548  roi = (const AVRegionOfInterest*)(sd->data + roi_size * i);
549 
550  av_assert0(roi->qoffset.den != 0);
551  v = roi->qoffset.num * ctx->roi_quant_range / roi->qoffset.den;
552  av_log(avctx, AV_LOG_DEBUG, "ROI: (%d,%d)-(%d,%d) -> %+d.\n",
553  roi->top, roi->left, roi->bottom, roi->right, v);
554 
555  pic->roi[i] = (VAEncROI) {
556  .roi_rectangle = {
557  .x = roi->left,
558  .y = roi->top,
559  .width = roi->right - roi->left,
560  .height = roi->bottom - roi->top,
561  },
562  .roi_value = av_clip_int8(v),
563  };
564  }
565 
566  param_roi = (VAEncMiscParameterBufferROI) {
567  .num_roi = nb_roi,
568  .max_delta_qp = INT8_MAX,
569  .min_delta_qp = INT8_MIN,
570  .roi = pic->roi,
571  .roi_flags.bits.roi_value_is_qp_delta = 1,
572  };
573 
574  err = vaapi_encode_make_misc_param_buffer(avctx, pic,
575  VAEncMiscParameterTypeROI,
576  &param_roi,
577  sizeof(param_roi));
578  if (err < 0)
579  goto fail;
580  }
581 #endif
582 
583  vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
584  pic->input_surface);
585  if (vas != VA_STATUS_SUCCESS) {
586  av_log(avctx, AV_LOG_ERROR, "Failed to begin picture encode issue: "
587  "%d (%s).\n", vas, vaErrorStr(vas));
588  err = AVERROR(EIO);
589  goto fail_with_picture;
590  }
591 
592  vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
593  pic->param_buffers, pic->nb_param_buffers);
594  if (vas != VA_STATUS_SUCCESS) {
595  av_log(avctx, AV_LOG_ERROR, "Failed to upload encode parameters: "
596  "%d (%s).\n", vas, vaErrorStr(vas));
597  err = AVERROR(EIO);
598  goto fail_with_picture;
599  }
600 
601  vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
602  if (vas != VA_STATUS_SUCCESS) {
603  av_log(avctx, AV_LOG_ERROR, "Failed to end picture encode issue: "
604  "%d (%s).\n", vas, vaErrorStr(vas));
605  err = AVERROR(EIO);
606  // vaRenderPicture() has been called here, so we should not destroy
607  // the parameter buffers unless separate destruction is required.
608  if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
610  goto fail;
611  else
612  goto fail_at_end;
613  }
614 
615  if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
617  for (i = 0; i < pic->nb_param_buffers; i++) {
618  vas = vaDestroyBuffer(ctx->hwctx->display,
619  pic->param_buffers[i]);
620  if (vas != VA_STATUS_SUCCESS) {
621  av_log(avctx, AV_LOG_ERROR, "Failed to destroy "
622  "param buffer %#x: %d (%s).\n",
623  pic->param_buffers[i], vas, vaErrorStr(vas));
624  // And ignore.
625  }
626  }
627  }
628 
629  pic->encode_issued = 1;
630 
631  return 0;
632 
633 fail_with_picture:
634  vaEndPicture(ctx->hwctx->display, ctx->va_context);
635 fail:
636  for(i = 0; i < pic->nb_param_buffers; i++)
637  vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]);
638  if (pic->slices) {
639  for (i = 0; i < pic->nb_slices; i++)
641  }
642 fail_at_end:
644  av_freep(&pic->param_buffers);
645  av_freep(&pic->slices);
646  av_freep(&pic->roi);
647  av_frame_free(&pic->recon_image);
649  pic->output_buffer = VA_INVALID_ID;
650  return err;
651 }
652 
655 {
656  VAAPIEncodeContext *ctx = avctx->priv_data;
657  VACodedBufferSegment *buf_list, *buf;
658  VAStatus vas;
659  int total_size = 0;
660  uint8_t *ptr;
661  int err;
662 
663  err = vaapi_encode_wait(avctx, pic);
664  if (err < 0)
665  return err;
666 
667  buf_list = NULL;
668  vas = vaMapBuffer(ctx->hwctx->display, pic->output_buffer,
669  (void**)&buf_list);
670  if (vas != VA_STATUS_SUCCESS) {
671  av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "
672  "%d (%s).\n", vas, vaErrorStr(vas));
673  err = AVERROR(EIO);
674  goto fail;
675  }
676 
677  for (buf = buf_list; buf; buf = buf->next)
678  total_size += buf->size;
679 
680  err = ff_get_encode_buffer(avctx, pkt, total_size, 0);
681  ptr = pkt->data;
682 
683  if (err < 0)
684  goto fail_mapped;
685 
686  for (buf = buf_list; buf; buf = buf->next) {
687  av_log(avctx, AV_LOG_DEBUG, "Output buffer: %u bytes "
688  "(status %08x).\n", buf->size, buf->status);
689 
690  memcpy(ptr, buf->buf, buf->size);
691  ptr += buf->size;
692  }
693 
694  if (pic->type == PICTURE_TYPE_IDR)
696 
697  pkt->pts = pic->pts;
698  pkt->duration = pic->duration;
699 
700  vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
701  if (vas != VA_STATUS_SUCCESS) {
702  av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
703  "%d (%s).\n", vas, vaErrorStr(vas));
704  err = AVERROR(EIO);
705  goto fail;
706  }
707 
708  // for no-delay encoders this is handled in generic codec
709  if (avctx->codec->capabilities & AV_CODEC_CAP_DELAY &&
710  avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
711  pkt->opaque = pic->opaque;
712  pkt->opaque_ref = pic->opaque_ref;
713  pic->opaque_ref = NULL;
714  }
715 
717  pic->output_buffer = VA_INVALID_ID;
718 
719  av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
720  pic->display_order, pic->encode_order);
721  return 0;
722 
723 fail_mapped:
724  vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
725 fail:
727  pic->output_buffer = VA_INVALID_ID;
728  return err;
729 }
730 
732  VAAPIEncodePicture *pic)
733 {
734  vaapi_encode_wait(avctx, pic);
735 
736  if (pic->output_buffer_ref) {
737  av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
738  "%"PRId64"/%"PRId64".\n",
739  pic->display_order, pic->encode_order);
740 
742  pic->output_buffer = VA_INVALID_ID;
743  }
744 
745  return 0;
746 }
747 
749 {
750  VAAPIEncodeContext *ctx = avctx->priv_data;
751  VAAPIEncodePicture *pic;
752 
753  pic = av_mallocz(sizeof(*pic));
754  if (!pic)
755  return NULL;
756 
757  if (ctx->codec->picture_priv_data_size > 0) {
758  pic->priv_data = av_mallocz(ctx->codec->picture_priv_data_size);
759  if (!pic->priv_data) {
760  av_freep(&pic);
761  return NULL;
762  }
763  }
764 
765  pic->input_surface = VA_INVALID_ID;
766  pic->recon_surface = VA_INVALID_ID;
767  pic->output_buffer = VA_INVALID_ID;
768 
769  return pic;
770 }
771 
773  VAAPIEncodePicture *pic)
774 {
775  int i;
776 
777  if (pic->encode_issued)
778  vaapi_encode_discard(avctx, pic);
779 
780  if (pic->slices) {
781  for (i = 0; i < pic->nb_slices; i++)
783  }
785 
786  av_frame_free(&pic->input_image);
787  av_frame_free(&pic->recon_image);
788 
790 
791  av_freep(&pic->param_buffers);
792  av_freep(&pic->slices);
793  // Output buffer should already be destroyed.
794  av_assert0(pic->output_buffer == VA_INVALID_ID);
795 
796  av_freep(&pic->priv_data);
798  av_freep(&pic->roi);
799 
800  av_free(pic);
801 
802  return 0;
803 }
804 
806  VAAPIEncodePicture *pic,
807  VAAPIEncodePicture *target,
808  int is_ref, int in_dpb, int prev)
809 {
810  int refs = 0;
811 
812  if (is_ref) {
813  av_assert0(pic != target);
815  pic->refs[pic->nb_refs++] = target;
816  ++refs;
817  }
818 
819  if (in_dpb) {
821  pic->dpb[pic->nb_dpb_pics++] = target;
822  ++refs;
823  }
824 
825  if (prev) {
826  av_assert0(!pic->prev);
827  pic->prev = target;
828  ++refs;
829  }
830 
831  target->ref_count[0] += refs;
832  target->ref_count[1] += refs;
833 }
834 
836  VAAPIEncodePicture *pic,
837  int level)
838 {
839  int i;
840 
841  if (pic->ref_removed[level])
842  return;
843 
844  for (i = 0; i < pic->nb_refs; i++) {
845  av_assert0(pic->refs[i]);
846  --pic->refs[i]->ref_count[level];
847  av_assert0(pic->refs[i]->ref_count[level] >= 0);
848  }
849 
850  for (i = 0; i < pic->nb_dpb_pics; i++) {
851  av_assert0(pic->dpb[i]);
852  --pic->dpb[i]->ref_count[level];
853  av_assert0(pic->dpb[i]->ref_count[level] >= 0);
854  }
855 
856  av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR);
857  if (pic->prev) {
858  --pic->prev->ref_count[level];
859  av_assert0(pic->prev->ref_count[level] >= 0);
860  }
861 
862  pic->ref_removed[level] = 1;
863 }
864 
866  VAAPIEncodePicture *start,
867  VAAPIEncodePicture *end,
868  VAAPIEncodePicture *prev,
869  int current_depth,
870  VAAPIEncodePicture **last)
871 {
872  VAAPIEncodeContext *ctx = avctx->priv_data;
873  VAAPIEncodePicture *pic, *next, *ref;
874  int i, len;
875 
876  av_assert0(start && end && start != end && start->next != end);
877 
878  // If we are at the maximum depth then encode all pictures as
879  // non-referenced B-pictures. Also do this if there is exactly one
880  // picture left, since there will be nothing to reference it.
881  if (current_depth == ctx->max_b_depth || start->next->next == end) {
882  for (pic = start->next; pic; pic = pic->next) {
883  if (pic == end)
884  break;
885  pic->type = PICTURE_TYPE_B;
886  pic->b_depth = current_depth;
887 
888  vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0);
889  vaapi_encode_add_ref(avctx, pic, end, 1, 1, 0);
890  vaapi_encode_add_ref(avctx, pic, prev, 0, 0, 1);
891 
892  for (ref = end->refs[1]; ref; ref = ref->refs[1])
893  vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0);
894  }
895  *last = prev;
896 
897  } else {
898  // Split the current list at the midpoint with a referenced
899  // B-picture, then descend into each side separately.
900  len = 0;
901  for (pic = start->next; pic != end; pic = pic->next)
902  ++len;
903  for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++);
904 
905  pic->type = PICTURE_TYPE_B;
906  pic->b_depth = current_depth;
907 
908  pic->is_reference = 1;
909 
910  vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0);
911  vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0);
912  vaapi_encode_add_ref(avctx, pic, end, 1, 1, 0);
913  vaapi_encode_add_ref(avctx, pic, prev, 0, 0, 1);
914 
915  for (ref = end->refs[1]; ref; ref = ref->refs[1])
916  vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0);
917 
918  if (i > 1)
919  vaapi_encode_set_b_pictures(avctx, start, pic, pic,
920  current_depth + 1, &next);
921  else
922  next = pic;
923 
924  vaapi_encode_set_b_pictures(avctx, pic, end, next,
925  current_depth + 1, last);
926  }
927 }
928 
930  VAAPIEncodePicture **pic_out)
931 {
932  VAAPIEncodeContext *ctx = avctx->priv_data;
933  VAAPIEncodePicture *pic = NULL, *next, *start;
934  int i, b_counter, closed_gop_end;
935 
936  // If there are any B-frames already queued, the next one to encode
937  // is the earliest not-yet-issued frame for which all references are
938  // available.
939  for (pic = ctx->pic_start; pic; pic = pic->next) {
940  if (pic->encode_issued)
941  continue;
942  if (pic->type != PICTURE_TYPE_B)
943  continue;
944  for (i = 0; i < pic->nb_refs; i++) {
945  if (!pic->refs[i]->encode_issued)
946  break;
947  }
948  if (i == pic->nb_refs)
949  break;
950  }
951 
952  if (pic) {
953  av_log(avctx, AV_LOG_DEBUG, "Pick B-picture at depth %d to "
954  "encode next.\n", pic->b_depth);
955  *pic_out = pic;
956  return 0;
957  }
958 
959  // Find the B-per-Pth available picture to become the next picture
960  // on the top layer.
961  start = NULL;
962  b_counter = 0;
963  closed_gop_end = ctx->closed_gop ||
964  ctx->idr_counter == ctx->gop_per_idr;
965  for (pic = ctx->pic_start; pic; pic = next) {
966  next = pic->next;
967  if (pic->encode_issued) {
968  start = pic;
969  continue;
970  }
971  // If the next available picture is force-IDR, encode it to start
972  // a new GOP immediately.
973  if (pic->force_idr)
974  break;
975  if (b_counter == ctx->b_per_p)
976  break;
977  // If this picture ends a closed GOP or starts a new GOP then it
978  // needs to be in the top layer.
979  if (ctx->gop_counter + b_counter + closed_gop_end >= ctx->gop_size)
980  break;
981  // If the picture after this one is force-IDR, we need to encode
982  // this one in the top layer.
983  if (next && next->force_idr)
984  break;
985  ++b_counter;
986  }
987 
988  // At the end of the stream the last picture must be in the top layer.
989  if (!pic && ctx->end_of_stream) {
990  --b_counter;
991  pic = ctx->pic_end;
992  if (pic->encode_complete)
993  return AVERROR_EOF;
994  else if (pic->encode_issued)
995  return AVERROR(EAGAIN);
996  }
997 
998  if (!pic) {
999  av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
1000  "need more input for reference pictures.\n");
1001  return AVERROR(EAGAIN);
1002  }
1003  if (ctx->input_order <= ctx->decode_delay && !ctx->end_of_stream) {
1004  av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
1005  "need more input for timestamps.\n");
1006  return AVERROR(EAGAIN);
1007  }
1008 
1009  if (pic->force_idr) {
1010  av_log(avctx, AV_LOG_DEBUG, "Pick forced IDR-picture to "
1011  "encode next.\n");
1012  pic->type = PICTURE_TYPE_IDR;
1013  ctx->idr_counter = 1;
1014  ctx->gop_counter = 1;
1015 
1016  } else if (ctx->gop_counter + b_counter >= ctx->gop_size) {
1017  if (ctx->idr_counter == ctx->gop_per_idr) {
1018  av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP IDR-picture to "
1019  "encode next.\n");
1020  pic->type = PICTURE_TYPE_IDR;
1021  ctx->idr_counter = 1;
1022  } else {
1023  av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP I-picture to "
1024  "encode next.\n");
1025  pic->type = PICTURE_TYPE_I;
1026  ++ctx->idr_counter;
1027  }
1028  ctx->gop_counter = 1;
1029 
1030  } else {
1031  if (ctx->gop_counter + b_counter + closed_gop_end == ctx->gop_size) {
1032  av_log(avctx, AV_LOG_DEBUG, "Pick group-end P-picture to "
1033  "encode next.\n");
1034  } else {
1035  av_log(avctx, AV_LOG_DEBUG, "Pick normal P-picture to "
1036  "encode next.\n");
1037  }
1038  pic->type = PICTURE_TYPE_P;
1039  av_assert0(start);
1040  ctx->gop_counter += 1 + b_counter;
1041  }
1042  pic->is_reference = 1;
1043  *pic_out = pic;
1044 
1045  vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0);
1046  if (pic->type != PICTURE_TYPE_IDR) {
1047  vaapi_encode_add_ref(avctx, pic, start,
1048  pic->type == PICTURE_TYPE_P,
1049  b_counter > 0, 0);
1050  vaapi_encode_add_ref(avctx, pic, ctx->next_prev, 0, 0, 1);
1051  }
1052  if (ctx->next_prev)
1053  --ctx->next_prev->ref_count[0];
1054 
1055  if (b_counter > 0) {
1056  vaapi_encode_set_b_pictures(avctx, start, pic, pic, 1,
1057  &ctx->next_prev);
1058  } else {
1059  ctx->next_prev = pic;
1060  }
1061  ++ctx->next_prev->ref_count[0];
1062  return 0;
1063 }
1064 
1066 {
1067  VAAPIEncodeContext *ctx = avctx->priv_data;
1068  VAAPIEncodePicture *pic, *prev, *next;
1069 
1070  av_assert0(ctx->pic_start);
1071 
1072  // Remove direct references once each picture is complete.
1073  for (pic = ctx->pic_start; pic; pic = pic->next) {
1074  if (pic->encode_complete && pic->next)
1075  vaapi_encode_remove_refs(avctx, pic, 0);
1076  }
1077 
1078  // Remove indirect references once a picture has no direct references.
1079  for (pic = ctx->pic_start; pic; pic = pic->next) {
1080  if (pic->encode_complete && pic->ref_count[0] == 0)
1081  vaapi_encode_remove_refs(avctx, pic, 1);
1082  }
1083 
1084  // Clear out all complete pictures with no remaining references.
1085  prev = NULL;
1086  for (pic = ctx->pic_start; pic; pic = next) {
1087  next = pic->next;
1088  if (pic->encode_complete && pic->ref_count[1] == 0) {
1089  av_assert0(pic->ref_removed[0] && pic->ref_removed[1]);
1090  if (prev)
1091  prev->next = next;
1092  else
1093  ctx->pic_start = next;
1094  vaapi_encode_free(avctx, pic);
1095  } else {
1096  prev = pic;
1097  }
1098  }
1099 
1100  return 0;
1101 }
1102 
1104  const AVFrame *frame)
1105 {
1106  VAAPIEncodeContext *ctx = avctx->priv_data;
1107 
1108  if ((frame->crop_top || frame->crop_bottom ||
1109  frame->crop_left || frame->crop_right) && !ctx->crop_warned) {
1110  av_log(avctx, AV_LOG_WARNING, "Cropping information on input "
1111  "frames ignored due to lack of API support.\n");
1112  ctx->crop_warned = 1;
1113  }
1114 
1115  if (!ctx->roi_allowed) {
1116  AVFrameSideData *sd =
1118 
1119  if (sd && !ctx->roi_warned) {
1120  av_log(avctx, AV_LOG_WARNING, "ROI side data on input "
1121  "frames ignored due to lack of driver support.\n");
1122  ctx->roi_warned = 1;
1123  }
1124  }
1125 
1126  return 0;
1127 }
1128 
1130 {
1131  VAAPIEncodeContext *ctx = avctx->priv_data;
1132  VAAPIEncodePicture *pic;
1133  int err;
1134 
1135  if (frame) {
1136  av_log(avctx, AV_LOG_DEBUG, "Input frame: %ux%u (%"PRId64").\n",
1137  frame->width, frame->height, frame->pts);
1138 
1139  err = vaapi_encode_check_frame(avctx, frame);
1140  if (err < 0)
1141  return err;
1142 
1143  pic = vaapi_encode_alloc(avctx);
1144  if (!pic)
1145  return AVERROR(ENOMEM);
1146 
1147  pic->input_image = av_frame_alloc();
1148  if (!pic->input_image) {
1149  err = AVERROR(ENOMEM);
1150  goto fail;
1151  }
1152 
1153  if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I)
1154  pic->force_idr = 1;
1155 
1156  pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3];
1157  pic->pts = frame->pts;
1158  pic->duration = frame->duration;
1159 
1160  if (avctx->flags & AV_CODEC_FLAG_COPY_OPAQUE) {
1161  err = av_buffer_replace(&pic->opaque_ref, frame->opaque_ref);
1162  if (err < 0)
1163  goto fail;
1164 
1165  pic->opaque = frame->opaque;
1166  }
1167 
1169 
1170  if (ctx->input_order == 0)
1171  ctx->first_pts = pic->pts;
1172  if (ctx->input_order == ctx->decode_delay)
1173  ctx->dts_pts_diff = pic->pts - ctx->first_pts;
1174  if (ctx->output_delay > 0)
1175  ctx->ts_ring[ctx->input_order %
1176  (3 * ctx->output_delay + ctx->async_depth)] = pic->pts;
1177 
1178  pic->display_order = ctx->input_order;
1179  ++ctx->input_order;
1180 
1181  if (ctx->pic_start) {
1182  ctx->pic_end->next = pic;
1183  ctx->pic_end = pic;
1184  } else {
1185  ctx->pic_start = pic;
1186  ctx->pic_end = pic;
1187  }
1188 
1189  } else {
1190  ctx->end_of_stream = 1;
1191 
1192  // Fix timestamps if we hit end-of-stream before the initial decode
1193  // delay has elapsed.
1194  if (ctx->input_order < ctx->decode_delay)
1195  ctx->dts_pts_diff = ctx->pic_end->pts - ctx->first_pts;
1196  }
1197 
1198  return 0;
1199 
1200 fail:
1201  vaapi_encode_free(avctx, pic);
1202  return err;
1203 }
1204 
1206 {
1207  VAAPIEncodeContext *ctx = avctx->priv_data;
1208  VAAPIEncodePicture *pic;
1209  AVFrame *frame = ctx->frame;
1210  int err;
1211 
1212  err = ff_encode_get_frame(avctx, frame);
1213  if (err < 0 && err != AVERROR_EOF)
1214  return err;
1215 
1216  if (err == AVERROR_EOF)
1217  frame = NULL;
1218 
1219  err = vaapi_encode_send_frame(avctx, frame);
1220  if (err < 0)
1221  return err;
1222 
1223  if (!ctx->pic_start) {
1224  if (ctx->end_of_stream)
1225  return AVERROR_EOF;
1226  else
1227  return AVERROR(EAGAIN);
1228  }
1229 
1230  if (ctx->has_sync_buffer_func) {
1231  pic = NULL;
1232 
1233  if (av_fifo_can_write(ctx->encode_fifo)) {
1234  err = vaapi_encode_pick_next(avctx, &pic);
1235  if (!err) {
1236  av_assert0(pic);
1237  pic->encode_order = ctx->encode_order +
1238  av_fifo_can_read(ctx->encode_fifo);
1239  err = vaapi_encode_issue(avctx, pic);
1240  if (err < 0) {
1241  av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
1242  return err;
1243  }
1244  av_fifo_write(ctx->encode_fifo, &pic, 1);
1245  }
1246  }
1247 
1248  if (!av_fifo_can_read(ctx->encode_fifo))
1249  return err;
1250 
1251  // More frames can be buffered
1252  if (av_fifo_can_write(ctx->encode_fifo) && !ctx->end_of_stream)
1253  return AVERROR(EAGAIN);
1254 
1255  av_fifo_read(ctx->encode_fifo, &pic, 1);
1256  ctx->encode_order = pic->encode_order + 1;
1257  } else {
1258  pic = NULL;
1259  err = vaapi_encode_pick_next(avctx, &pic);
1260  if (err < 0)
1261  return err;
1262  av_assert0(pic);
1263 
1264  pic->encode_order = ctx->encode_order++;
1265 
1266  err = vaapi_encode_issue(avctx, pic);
1267  if (err < 0) {
1268  av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
1269  return err;
1270  }
1271  }
1272 
1273  err = vaapi_encode_output(avctx, pic, pkt);
1274  if (err < 0) {
1275  av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
1276  return err;
1277  }
1278 
1279  if (ctx->output_delay == 0) {
1280  pkt->dts = pkt->pts;
1281  } else if (pic->encode_order < ctx->decode_delay) {
1282  if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff)
1283  pkt->dts = INT64_MIN;
1284  else
1285  pkt->dts = ctx->ts_ring[pic->encode_order] - ctx->dts_pts_diff;
1286  } else {
1287  pkt->dts = ctx->ts_ring[(pic->encode_order - ctx->decode_delay) %
1288  (3 * ctx->output_delay + ctx->async_depth)];
1289  }
1290  av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64" dts %"PRId64".\n",
1291  pkt->pts, pkt->dts);
1292 
1293  ctx->output_order = pic->encode_order;
1294  vaapi_encode_clear_old(avctx);
1295 
1296  return 0;
1297 }
1298 
1299 
1301  void *buffer, size_t size)
1302 {
1303  VAAPIEncodeContext *ctx = avctx->priv_data;
1304 
1305  av_assert0(ctx->nb_global_params < MAX_GLOBAL_PARAMS);
1306 
1307  ctx->global_params_type[ctx->nb_global_params] = type;
1308  ctx->global_params [ctx->nb_global_params] = buffer;
1309  ctx->global_params_size[ctx->nb_global_params] = size;
1310 
1311  ++ctx->nb_global_params;
1312 }
1313 
1314 typedef struct VAAPIEncodeRTFormat {
1315  const char *name;
1316  unsigned int value;
1317  int depth;
1322 
1324  { "YUV400", VA_RT_FORMAT_YUV400, 8, 1, },
1325  { "YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 },
1326  { "YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 },
1327 #if VA_CHECK_VERSION(1, 2, 0)
1328  { "YUV420_12", VA_RT_FORMAT_YUV420_12, 12, 3, 1, 1 },
1329  { "YUV422_10", VA_RT_FORMAT_YUV422_10, 10, 3, 1, 0 },
1330  { "YUV422_12", VA_RT_FORMAT_YUV422_12, 12, 3, 1, 0 },
1331  { "YUV444_10", VA_RT_FORMAT_YUV444_10, 10, 3, 0, 0 },
1332  { "YUV444_12", VA_RT_FORMAT_YUV444_12, 12, 3, 0, 0 },
1333 #endif
1334  { "YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
1335  { "XYUV", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
1336  { "YUV411", VA_RT_FORMAT_YUV411, 8, 3, 2, 0 },
1337 #if VA_CHECK_VERSION(0, 38, 1)
1338  { "YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
1339 #endif
1340 };
1341 
1342 static const VAEntrypoint vaapi_encode_entrypoints_normal[] = {
1343  VAEntrypointEncSlice,
1344  VAEntrypointEncPicture,
1345 #if VA_CHECK_VERSION(0, 39, 2)
1346  VAEntrypointEncSliceLP,
1347 #endif
1348  0
1349 };
1350 #if VA_CHECK_VERSION(0, 39, 2)
1351 static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
1352  VAEntrypointEncSliceLP,
1353  0
1354 };
1355 #endif
1356 
1358 {
1359  VAAPIEncodeContext *ctx = avctx->priv_data;
1360  VAProfile *va_profiles = NULL;
1361  VAEntrypoint *va_entrypoints = NULL;
1362  VAStatus vas;
1363  const VAEntrypoint *usable_entrypoints;
1364  const VAAPIEncodeProfile *profile;
1365  const AVPixFmtDescriptor *desc;
1366  VAConfigAttrib rt_format_attr;
1367  const VAAPIEncodeRTFormat *rt_format;
1368  const char *profile_string, *entrypoint_string;
1369  int i, j, n, depth, err;
1370 
1371 
1372  if (ctx->low_power) {
1373 #if VA_CHECK_VERSION(0, 39, 2)
1374  usable_entrypoints = vaapi_encode_entrypoints_low_power;
1375 #else
1376  av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
1377  "supported with this VAAPI version.\n");
1378  return AVERROR(EINVAL);
1379 #endif
1380  } else {
1381  usable_entrypoints = vaapi_encode_entrypoints_normal;
1382  }
1383 
1384  desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format);
1385  if (!desc) {
1386  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
1387  ctx->input_frames->sw_format);
1388  return AVERROR(EINVAL);
1389  }
1390  depth = desc->comp[0].depth;
1391  for (i = 1; i < desc->nb_components; i++) {
1392  if (desc->comp[i].depth != depth) {
1393  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
1394  desc->name);
1395  return AVERROR(EINVAL);
1396  }
1397  }
1398  av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
1399  desc->name);
1400 
1401  n = vaMaxNumProfiles(ctx->hwctx->display);
1402  va_profiles = av_malloc_array(n, sizeof(VAProfile));
1403  if (!va_profiles) {
1404  err = AVERROR(ENOMEM);
1405  goto fail;
1406  }
1407  vas = vaQueryConfigProfiles(ctx->hwctx->display, va_profiles, &n);
1408  if (vas != VA_STATUS_SUCCESS) {
1409  av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n",
1410  vas, vaErrorStr(vas));
1411  err = AVERROR_EXTERNAL;
1412  goto fail;
1413  }
1414 
1415  av_assert0(ctx->codec->profiles);
1416  for (i = 0; (ctx->codec->profiles[i].av_profile !=
1417  FF_PROFILE_UNKNOWN); i++) {
1418  profile = &ctx->codec->profiles[i];
1419  if (depth != profile->depth ||
1420  desc->nb_components != profile->nb_components)
1421  continue;
1422  if (desc->nb_components > 1 &&
1423  (desc->log2_chroma_w != profile->log2_chroma_w ||
1424  desc->log2_chroma_h != profile->log2_chroma_h))
1425  continue;
1426  if (avctx->profile != profile->av_profile &&
1427  avctx->profile != FF_PROFILE_UNKNOWN)
1428  continue;
1429 
1430 #if VA_CHECK_VERSION(1, 0, 0)
1431  profile_string = vaProfileStr(profile->va_profile);
1432 #else
1433  profile_string = "(no profile names)";
1434 #endif
1435 
1436  for (j = 0; j < n; j++) {
1437  if (va_profiles[j] == profile->va_profile)
1438  break;
1439  }
1440  if (j >= n) {
1441  av_log(avctx, AV_LOG_VERBOSE, "Compatible profile %s (%d) "
1442  "is not supported by driver.\n", profile_string,
1443  profile->va_profile);
1444  continue;
1445  }
1446 
1447  ctx->profile = profile;
1448  break;
1449  }
1450  if (!ctx->profile) {
1451  av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n");
1452  err = AVERROR(ENOSYS);
1453  goto fail;
1454  }
1455 
1456  avctx->profile = profile->av_profile;
1457  ctx->va_profile = profile->va_profile;
1458  av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI profile %s (%d).\n",
1459  profile_string, ctx->va_profile);
1460 
1461  n = vaMaxNumEntrypoints(ctx->hwctx->display);
1462  va_entrypoints = av_malloc_array(n, sizeof(VAEntrypoint));
1463  if (!va_entrypoints) {
1464  err = AVERROR(ENOMEM);
1465  goto fail;
1466  }
1467  vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile,
1468  va_entrypoints, &n);
1469  if (vas != VA_STATUS_SUCCESS) {
1470  av_log(avctx, AV_LOG_ERROR, "Failed to query entrypoints for "
1471  "profile %s (%d): %d (%s).\n", profile_string,
1472  ctx->va_profile, vas, vaErrorStr(vas));
1473  err = AVERROR_EXTERNAL;
1474  goto fail;
1475  }
1476 
1477  for (i = 0; i < n; i++) {
1478  for (j = 0; usable_entrypoints[j]; j++) {
1479  if (va_entrypoints[i] == usable_entrypoints[j])
1480  break;
1481  }
1482  if (usable_entrypoints[j])
1483  break;
1484  }
1485  if (i >= n) {
1486  av_log(avctx, AV_LOG_ERROR, "No usable encoding entrypoint found "
1487  "for profile %s (%d).\n", profile_string, ctx->va_profile);
1488  err = AVERROR(ENOSYS);
1489  goto fail;
1490  }
1491 
1492  ctx->va_entrypoint = va_entrypoints[i];
1493 #if VA_CHECK_VERSION(1, 0, 0)
1494  entrypoint_string = vaEntrypointStr(ctx->va_entrypoint);
1495 #else
1496  entrypoint_string = "(no entrypoint names)";
1497 #endif
1498  av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI entrypoint %s (%d).\n",
1499  entrypoint_string, ctx->va_entrypoint);
1500 
1501  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_encode_rt_formats); i++) {
1502  rt_format = &vaapi_encode_rt_formats[i];
1503  if (rt_format->depth == depth &&
1504  rt_format->nb_components == profile->nb_components &&
1505  rt_format->log2_chroma_w == profile->log2_chroma_w &&
1506  rt_format->log2_chroma_h == profile->log2_chroma_h)
1507  break;
1508  }
1510  av_log(avctx, AV_LOG_ERROR, "No usable render target format "
1511  "found for profile %s (%d) entrypoint %s (%d).\n",
1512  profile_string, ctx->va_profile,
1513  entrypoint_string, ctx->va_entrypoint);
1514  err = AVERROR(ENOSYS);
1515  goto fail;
1516  }
1517 
1518  rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
1519  vas = vaGetConfigAttributes(ctx->hwctx->display,
1520  ctx->va_profile, ctx->va_entrypoint,
1521  &rt_format_attr, 1);
1522  if (vas != VA_STATUS_SUCCESS) {
1523  av_log(avctx, AV_LOG_ERROR, "Failed to query RT format "
1524  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1525  err = AVERROR_EXTERNAL;
1526  goto fail;
1527  }
1528 
1529  if (rt_format_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1530  av_log(avctx, AV_LOG_VERBOSE, "RT format config attribute not "
1531  "supported by driver: assuming surface RT format %s "
1532  "is valid.\n", rt_format->name);
1533  } else if (!(rt_format_attr.value & rt_format->value)) {
1534  av_log(avctx, AV_LOG_ERROR, "Surface RT format %s not supported "
1535  "by driver for encoding profile %s (%d) entrypoint %s (%d).\n",
1536  rt_format->name, profile_string, ctx->va_profile,
1537  entrypoint_string, ctx->va_entrypoint);
1538  err = AVERROR(ENOSYS);
1539  goto fail;
1540  } else {
1541  av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI render target "
1542  "format %s (%#x).\n", rt_format->name, rt_format->value);
1543  ctx->config_attributes[ctx->nb_config_attributes++] =
1544  (VAConfigAttrib) {
1545  .type = VAConfigAttribRTFormat,
1546  .value = rt_format->value,
1547  };
1548  }
1549 
1550  err = 0;
1551 fail:
1552  av_freep(&va_profiles);
1553  av_freep(&va_entrypoints);
1554  return err;
1555 }
1556 
1558  // Bitrate Quality
1559  // | Maxrate | HRD/VBV
1560  { 0 }, // | | | |
1561  { RC_MODE_CQP, "CQP", 1, VA_RC_CQP, 0, 0, 1, 0 },
1562  { RC_MODE_CBR, "CBR", 1, VA_RC_CBR, 1, 0, 0, 1 },
1563  { RC_MODE_VBR, "VBR", 1, VA_RC_VBR, 1, 1, 0, 1 },
1564 #if VA_CHECK_VERSION(1, 1, 0)
1565  { RC_MODE_ICQ, "ICQ", 1, VA_RC_ICQ, 0, 0, 1, 0 },
1566 #else
1567  { RC_MODE_ICQ, "ICQ", 0 },
1568 #endif
1569 #if VA_CHECK_VERSION(1, 3, 0)
1570  { RC_MODE_QVBR, "QVBR", 1, VA_RC_QVBR, 1, 1, 1, 1 },
1571  { RC_MODE_AVBR, "AVBR", 0, VA_RC_AVBR, 1, 0, 0, 0 },
1572 #else
1573  { RC_MODE_QVBR, "QVBR", 0 },
1574  { RC_MODE_AVBR, "AVBR", 0 },
1575 #endif
1576 };
1577 
1579 {
1580  VAAPIEncodeContext *ctx = avctx->priv_data;
1581  uint32_t supported_va_rc_modes;
1582  const VAAPIEncodeRCMode *rc_mode;
1583  int64_t rc_bits_per_second;
1584  int rc_target_percentage;
1585  int rc_window_size;
1586  int rc_quality;
1587  int64_t hrd_buffer_size;
1588  int64_t hrd_initial_buffer_fullness;
1589  int fr_num, fr_den;
1590  VAConfigAttrib rc_attr = { VAConfigAttribRateControl };
1591  VAStatus vas;
1592  char supported_rc_modes_string[64];
1593 
1594  vas = vaGetConfigAttributes(ctx->hwctx->display,
1595  ctx->va_profile, ctx->va_entrypoint,
1596  &rc_attr, 1);
1597  if (vas != VA_STATUS_SUCCESS) {
1598  av_log(avctx, AV_LOG_ERROR, "Failed to query rate control "
1599  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1600  return AVERROR_EXTERNAL;
1601  }
1602  if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1603  av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any "
1604  "supported rate control modes: assuming CQP only.\n");
1605  supported_va_rc_modes = VA_RC_CQP;
1606  strcpy(supported_rc_modes_string, "unknown");
1607  } else {
1608  char *str = supported_rc_modes_string;
1609  size_t len = sizeof(supported_rc_modes_string);
1610  int i, first = 1, res;
1611 
1612  supported_va_rc_modes = rc_attr.value;
1613  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_encode_rc_modes); i++) {
1615  if (supported_va_rc_modes & rc_mode->va_mode) {
1616  res = snprintf(str, len, "%s%s",
1617  first ? "" : ", ", rc_mode->name);
1618  first = 0;
1619  if (res < 0) {
1620  *str = 0;
1621  break;
1622  }
1623  len -= res;
1624  str += res;
1625  if (len == 0)
1626  break;
1627  }
1628  }
1629 
1630  av_log(avctx, AV_LOG_DEBUG, "Driver supports RC modes %s.\n",
1631  supported_rc_modes_string);
1632  }
1633 
1634  // Rate control mode selection:
1635  // * If the user has set a mode explicitly with the rc_mode option,
1636  // use it and fail if it is not available.
1637  // * If an explicit QP option has been set, use CQP.
1638  // * If the codec is CQ-only, use CQP.
1639  // * If the QSCALE avcodec option is set, use CQP.
1640  // * If bitrate and quality are both set, try QVBR.
1641  // * If quality is set, try ICQ, then CQP.
1642  // * If bitrate and maxrate are set and have the same value, try CBR.
1643  // * If a bitrate is set, try AVBR, then VBR, then CBR.
1644  // * If no bitrate is set, try ICQ, then CQP.
1645 
1646 #define TRY_RC_MODE(mode, fail) do { \
1647  rc_mode = &vaapi_encode_rc_modes[mode]; \
1648  if (!(rc_mode->va_mode & supported_va_rc_modes)) { \
1649  if (fail) { \
1650  av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
1651  "RC mode (supported modes: %s).\n", rc_mode->name, \
1652  supported_rc_modes_string); \
1653  return AVERROR(EINVAL); \
1654  } \
1655  av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
1656  "RC mode.\n", rc_mode->name); \
1657  rc_mode = NULL; \
1658  } else { \
1659  goto rc_mode_found; \
1660  } \
1661  } while (0)
1662 
1663  if (ctx->explicit_rc_mode)
1664  TRY_RC_MODE(ctx->explicit_rc_mode, 1);
1665 
1666  if (ctx->explicit_qp)
1668 
1669  if (ctx->codec->flags & FLAG_CONSTANT_QUALITY_ONLY)
1671 
1672  if (avctx->flags & AV_CODEC_FLAG_QSCALE)
1674 
1675  if (avctx->bit_rate > 0 && avctx->global_quality > 0)
1677 
1678  if (avctx->global_quality > 0) {
1681  }
1682 
1683  if (avctx->bit_rate > 0 && avctx->rc_max_rate == avctx->bit_rate)
1685 
1686  if (avctx->bit_rate > 0) {
1690  } else {
1693  }
1694 
1695  av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
1696  "RC mode compatible with selected options "
1697  "(supported modes: %s).\n", supported_rc_modes_string);
1698  return AVERROR(EINVAL);
1699 
1700 rc_mode_found:
1701  if (rc_mode->bitrate) {
1702  if (avctx->bit_rate <= 0) {
1703  av_log(avctx, AV_LOG_ERROR, "Bitrate must be set for %s "
1704  "RC mode.\n", rc_mode->name);
1705  return AVERROR(EINVAL);
1706  }
1707 
1708  if (rc_mode->mode == RC_MODE_AVBR) {
1709  // For maximum confusion AVBR is hacked into the existing API
1710  // by overloading some of the fields with completely different
1711  // meanings.
1712 
1713  // Target percentage does not apply in AVBR mode.
1714  rc_bits_per_second = avctx->bit_rate;
1715 
1716  // Accuracy tolerance range for meeting the specified target
1717  // bitrate. It's very unclear how this is actually intended
1718  // to work - since we do want to get the specified bitrate,
1719  // set the accuracy to 100% for now.
1720  rc_target_percentage = 100;
1721 
1722  // Convergence period in frames. The GOP size reflects the
1723  // user's intended block size for cutting, so reusing that
1724  // as the convergence period seems a reasonable default.
1725  rc_window_size = avctx->gop_size > 0 ? avctx->gop_size : 60;
1726 
1727  } else if (rc_mode->maxrate) {
1728  if (avctx->rc_max_rate > 0) {
1729  if (avctx->rc_max_rate < avctx->bit_rate) {
1730  av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: "
1731  "bitrate (%"PRId64") must not be greater than "
1732  "maxrate (%"PRId64").\n", avctx->bit_rate,
1733  avctx->rc_max_rate);
1734  return AVERROR(EINVAL);
1735  }
1736  rc_bits_per_second = avctx->rc_max_rate;
1737  rc_target_percentage = (avctx->bit_rate * 100) /
1738  avctx->rc_max_rate;
1739  } else {
1740  // We only have a target bitrate, but this mode requires
1741  // that a maximum rate be supplied as well. Since the
1742  // user does not want this to be a constraint, arbitrarily
1743  // pick a maximum rate of double the target rate.
1744  rc_bits_per_second = 2 * avctx->bit_rate;
1745  rc_target_percentage = 50;
1746  }
1747  } else {
1748  if (avctx->rc_max_rate > avctx->bit_rate) {
1749  av_log(avctx, AV_LOG_WARNING, "Max bitrate is ignored "
1750  "in %s RC mode.\n", rc_mode->name);
1751  }
1752  rc_bits_per_second = avctx->bit_rate;
1753  rc_target_percentage = 100;
1754  }
1755  } else {
1756  rc_bits_per_second = 0;
1757  rc_target_percentage = 100;
1758  }
1759 
1760  if (rc_mode->quality) {
1761  if (ctx->explicit_qp) {
1762  rc_quality = ctx->explicit_qp;
1763  } else if (avctx->global_quality > 0) {
1764  rc_quality = avctx->global_quality;
1765  } else {
1766  rc_quality = ctx->codec->default_quality;
1767  av_log(avctx, AV_LOG_WARNING, "No quality level set; "
1768  "using default (%d).\n", rc_quality);
1769  }
1770  } else {
1771  rc_quality = 0;
1772  }
1773 
1774  if (rc_mode->hrd) {
1775  if (avctx->rc_buffer_size)
1776  hrd_buffer_size = avctx->rc_buffer_size;
1777  else if (avctx->rc_max_rate > 0)
1778  hrd_buffer_size = avctx->rc_max_rate;
1779  else
1780  hrd_buffer_size = avctx->bit_rate;
1781  if (avctx->rc_initial_buffer_occupancy) {
1782  if (avctx->rc_initial_buffer_occupancy > hrd_buffer_size) {
1783  av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
1784  "must have initial buffer size (%d) <= "
1785  "buffer size (%"PRId64").\n",
1786  avctx->rc_initial_buffer_occupancy, hrd_buffer_size);
1787  return AVERROR(EINVAL);
1788  }
1789  hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
1790  } else {
1791  hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1792  }
1793 
1794  rc_window_size = (hrd_buffer_size * 1000) / rc_bits_per_second;
1795  } else {
1796  if (avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
1797  av_log(avctx, AV_LOG_WARNING, "Buffering settings are ignored "
1798  "in %s RC mode.\n", rc_mode->name);
1799  }
1800 
1801  hrd_buffer_size = 0;
1802  hrd_initial_buffer_fullness = 0;
1803 
1804  if (rc_mode->mode != RC_MODE_AVBR) {
1805  // Already set (with completely different meaning) for AVBR.
1806  rc_window_size = 1000;
1807  }
1808  }
1809 
1810  if (rc_bits_per_second > UINT32_MAX ||
1811  hrd_buffer_size > UINT32_MAX ||
1812  hrd_initial_buffer_fullness > UINT32_MAX) {
1813  av_log(avctx, AV_LOG_ERROR, "RC parameters of 2^32 or "
1814  "greater are not supported by VAAPI.\n");
1815  return AVERROR(EINVAL);
1816  }
1817 
1818  ctx->rc_mode = rc_mode;
1819  ctx->rc_quality = rc_quality;
1820  ctx->va_rc_mode = rc_mode->va_mode;
1821  ctx->va_bit_rate = rc_bits_per_second;
1822 
1823  av_log(avctx, AV_LOG_VERBOSE, "RC mode: %s.\n", rc_mode->name);
1824  if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1825  // This driver does not want the RC mode attribute to be set.
1826  } else {
1827  ctx->config_attributes[ctx->nb_config_attributes++] =
1828  (VAConfigAttrib) {
1829  .type = VAConfigAttribRateControl,
1830  .value = ctx->va_rc_mode,
1831  };
1832  }
1833 
1834  if (rc_mode->quality)
1835  av_log(avctx, AV_LOG_VERBOSE, "RC quality: %d.\n", rc_quality);
1836 
1837  if (rc_mode->va_mode != VA_RC_CQP) {
1838  if (rc_mode->mode == RC_MODE_AVBR) {
1839  av_log(avctx, AV_LOG_VERBOSE, "RC target: %"PRId64" bps "
1840  "converging in %d frames with %d%% accuracy.\n",
1841  rc_bits_per_second, rc_window_size,
1842  rc_target_percentage);
1843  } else if (rc_mode->bitrate) {
1844  av_log(avctx, AV_LOG_VERBOSE, "RC target: %d%% of "
1845  "%"PRId64" bps over %d ms.\n", rc_target_percentage,
1846  rc_bits_per_second, rc_window_size);
1847  }
1848 
1849  ctx->rc_params = (VAEncMiscParameterRateControl) {
1850  .bits_per_second = rc_bits_per_second,
1851  .target_percentage = rc_target_percentage,
1852  .window_size = rc_window_size,
1853  .initial_qp = 0,
1854  .min_qp = (avctx->qmin > 0 ? avctx->qmin : 0),
1855  .basic_unit_size = 0,
1856 #if VA_CHECK_VERSION(1, 1, 0)
1857  .ICQ_quality_factor = av_clip(rc_quality, 1, 51),
1858  .max_qp = (avctx->qmax > 0 ? avctx->qmax : 0),
1859 #endif
1860 #if VA_CHECK_VERSION(1, 3, 0)
1861  .quality_factor = rc_quality,
1862 #endif
1863  };
1865  VAEncMiscParameterTypeRateControl,
1866  &ctx->rc_params,
1867  sizeof(ctx->rc_params));
1868  }
1869 
1870  if (rc_mode->hrd) {
1871  av_log(avctx, AV_LOG_VERBOSE, "RC buffer: %"PRId64" bits, "
1872  "initial fullness %"PRId64" bits.\n",
1873  hrd_buffer_size, hrd_initial_buffer_fullness);
1874 
1875  ctx->hrd_params = (VAEncMiscParameterHRD) {
1876  .initial_buffer_fullness = hrd_initial_buffer_fullness,
1877  .buffer_size = hrd_buffer_size,
1878  };
1880  VAEncMiscParameterTypeHRD,
1881  &ctx->hrd_params,
1882  sizeof(ctx->hrd_params));
1883  }
1884 
1885  if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
1886  av_reduce(&fr_num, &fr_den,
1887  avctx->framerate.num, avctx->framerate.den, 65535);
1888  else
1889  av_reduce(&fr_num, &fr_den,
1890  avctx->time_base.den, avctx->time_base.num, 65535);
1891 
1892  av_log(avctx, AV_LOG_VERBOSE, "RC framerate: %d/%d (%.2f fps).\n",
1893  fr_num, fr_den, (double)fr_num / fr_den);
1894 
1895  ctx->fr_params = (VAEncMiscParameterFrameRate) {
1896  .framerate = (unsigned int)fr_den << 16 | fr_num,
1897  };
1898 #if VA_CHECK_VERSION(0, 40, 0)
1900  VAEncMiscParameterTypeFrameRate,
1901  &ctx->fr_params,
1902  sizeof(ctx->fr_params));
1903 #endif
1904 
1905  return 0;
1906 }
1907 
1909 {
1910 #if VA_CHECK_VERSION(1, 5, 0)
1911  VAAPIEncodeContext *ctx = avctx->priv_data;
1912  VAConfigAttrib attr = { VAConfigAttribMaxFrameSize };
1913  VAStatus vas;
1914 
1915  if (ctx->va_rc_mode == VA_RC_CQP) {
1916  ctx->max_frame_size = 0;
1917  av_log(avctx, AV_LOG_ERROR, "Max frame size is invalid in CQP rate "
1918  "control mode.\n");
1919  return AVERROR(EINVAL);
1920  }
1921 
1922  vas = vaGetConfigAttributes(ctx->hwctx->display,
1923  ctx->va_profile,
1924  ctx->va_entrypoint,
1925  &attr, 1);
1926  if (vas != VA_STATUS_SUCCESS) {
1927  ctx->max_frame_size = 0;
1928  av_log(avctx, AV_LOG_ERROR, "Failed to query max frame size "
1929  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1930  return AVERROR_EXTERNAL;
1931  }
1932 
1933  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1934  ctx->max_frame_size = 0;
1935  av_log(avctx, AV_LOG_ERROR, "Max frame size attribute "
1936  "is not supported.\n");
1937  return AVERROR(EINVAL);
1938  } else {
1939  VAConfigAttribValMaxFrameSize attr_mfs;
1940  attr_mfs.value = attr.value;
1941  // Prefer to use VAEncMiscParameterTypeMaxFrameSize for max frame size.
1942  if (!attr_mfs.bits.max_frame_size && attr_mfs.bits.multiple_pass) {
1943  ctx->max_frame_size = 0;
1944  av_log(avctx, AV_LOG_ERROR, "Driver only supports multiple pass "
1945  "max frame size which has not been implemented in FFmpeg.\n");
1946  return AVERROR(EINVAL);
1947  }
1948 
1949  ctx->mfs_params = (VAEncMiscParameterBufferMaxFrameSize){
1950  .max_frame_size = ctx->max_frame_size * 8,
1951  };
1952 
1953  av_log(avctx, AV_LOG_VERBOSE, "Set max frame size: %d bytes.\n",
1954  ctx->max_frame_size);
1955  }
1956 #else
1957  av_log(avctx, AV_LOG_ERROR, "The max frame size option is not supported with "
1958  "this VAAPI version.\n");
1959  return AVERROR(EINVAL);
1960 #endif
1961 
1962  return 0;
1963 }
1964 
1966 {
1967  VAAPIEncodeContext *ctx = avctx->priv_data;
1968  VAStatus vas;
1969  VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
1970  uint32_t ref_l0, ref_l1;
1971  int prediction_pre_only;
1972 
1973  vas = vaGetConfigAttributes(ctx->hwctx->display,
1974  ctx->va_profile,
1975  ctx->va_entrypoint,
1976  &attr, 1);
1977  if (vas != VA_STATUS_SUCCESS) {
1978  av_log(avctx, AV_LOG_ERROR, "Failed to query reference frames "
1979  "attribute: %d (%s).\n", vas, vaErrorStr(vas));
1980  return AVERROR_EXTERNAL;
1981  }
1982 
1983  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1984  ref_l0 = ref_l1 = 0;
1985  } else {
1986  ref_l0 = attr.value & 0xffff;
1987  ref_l1 = attr.value >> 16 & 0xffff;
1988  }
1989 
1990  ctx->p_to_gpb = 0;
1991  prediction_pre_only = 0;
1992 
1993 #if VA_CHECK_VERSION(1, 9, 0)
1994  if (!(ctx->codec->flags & FLAG_INTRA_ONLY ||
1995  avctx->gop_size <= 1)) {
1996  attr = (VAConfigAttrib) { VAConfigAttribPredictionDirection };
1997  vas = vaGetConfigAttributes(ctx->hwctx->display,
1998  ctx->va_profile,
1999  ctx->va_entrypoint,
2000  &attr, 1);
2001  if (vas != VA_STATUS_SUCCESS) {
2002  av_log(avctx, AV_LOG_WARNING, "Failed to query prediction direction "
2003  "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2004  return AVERROR_EXTERNAL;
2005  } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2006  av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any additional "
2007  "prediction constraints.\n");
2008  } else {
2009  if (((ref_l0 > 0 || ref_l1 > 0) && !(attr.value & VA_PREDICTION_DIRECTION_PREVIOUS)) ||
2010  ((ref_l1 == 0) && (attr.value & (VA_PREDICTION_DIRECTION_FUTURE | VA_PREDICTION_DIRECTION_BI_NOT_EMPTY)))) {
2011  av_log(avctx, AV_LOG_ERROR, "Driver report incorrect prediction "
2012  "direction attribute.\n");
2013  return AVERROR_EXTERNAL;
2014  }
2015 
2016  if (!(attr.value & VA_PREDICTION_DIRECTION_FUTURE)) {
2017  if (ref_l0 > 0 && ref_l1 > 0) {
2018  prediction_pre_only = 1;
2019  av_log(avctx, AV_LOG_VERBOSE, "Driver only support same reference "
2020  "lists for B-frames.\n");
2021  }
2022  }
2023 
2024  if (attr.value & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) {
2025  if (ref_l0 > 0 && ref_l1 > 0) {
2026  ctx->p_to_gpb = 1;
2027  av_log(avctx, AV_LOG_VERBOSE, "Driver does not support P-frames, "
2028  "replacing them with B-frames.\n");
2029  }
2030  }
2031  }
2032  }
2033 #endif
2034 
2035  if (ctx->codec->flags & FLAG_INTRA_ONLY ||
2036  avctx->gop_size <= 1) {
2037  av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n");
2038  ctx->gop_size = 1;
2039  } else if (ref_l0 < 1) {
2040  av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
2041  "reference frames.\n");
2042  return AVERROR(EINVAL);
2043  } else if (!(ctx->codec->flags & FLAG_B_PICTURES) ||
2044  ref_l1 < 1 || avctx->max_b_frames < 1 ||
2045  prediction_pre_only) {
2046  if (ctx->p_to_gpb)
2047  av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames "
2048  "(supported references: %d / %d).\n",
2049  ref_l0, ref_l1);
2050  else
2051  av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames "
2052  "(supported references: %d / %d).\n", ref_l0, ref_l1);
2053  ctx->gop_size = avctx->gop_size;
2054  ctx->p_per_i = INT_MAX;
2055  ctx->b_per_p = 0;
2056  } else {
2057  if (ctx->p_to_gpb)
2058  av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames "
2059  "(supported references: %d / %d).\n",
2060  ref_l0, ref_l1);
2061  else
2062  av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames "
2063  "(supported references: %d / %d).\n", ref_l0, ref_l1);
2064  ctx->gop_size = avctx->gop_size;
2065  ctx->p_per_i = INT_MAX;
2066  ctx->b_per_p = avctx->max_b_frames;
2067  if (ctx->codec->flags & FLAG_B_PICTURE_REFERENCES) {
2068  ctx->max_b_depth = FFMIN(ctx->desired_b_depth,
2069  av_log2(ctx->b_per_p) + 1);
2070  } else {
2071  ctx->max_b_depth = 1;
2072  }
2073  }
2074 
2075  if (ctx->codec->flags & FLAG_NON_IDR_KEY_PICTURES) {
2076  ctx->closed_gop = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP);
2077  ctx->gop_per_idr = ctx->idr_interval + 1;
2078  } else {
2079  ctx->closed_gop = 1;
2080  ctx->gop_per_idr = 1;
2081  }
2082 
2083  return 0;
2084 }
2085 
2087  uint32_t slice_structure)
2088 {
2089  VAAPIEncodeContext *ctx = avctx->priv_data;
2090  int req_slices;
2091 
2092  // For fixed-size slices currently we only support whole rows, making
2093  // rectangular slices. This could be extended to arbitrary runs of
2094  // blocks, but since slices tend to be a conformance requirement and
2095  // most cases (such as broadcast or bluray) want rectangular slices
2096  // only it would need to be gated behind another option.
2097  if (avctx->slices > ctx->slice_block_rows) {
2098  av_log(avctx, AV_LOG_WARNING, "Not enough rows to use "
2099  "configured number of slices (%d < %d); using "
2100  "maximum.\n", ctx->slice_block_rows, avctx->slices);
2101  req_slices = ctx->slice_block_rows;
2102  } else {
2103  req_slices = avctx->slices;
2104  }
2105  if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS ||
2106  slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) {
2107  ctx->nb_slices = req_slices;
2108  ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices;
2109  } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) {
2110  int k;
2111  for (k = 1;; k *= 2) {
2112  if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows)
2113  break;
2114  }
2115  ctx->nb_slices = (ctx->slice_block_rows + k - 1) / k;
2116  ctx->slice_size = k;
2117 #if VA_CHECK_VERSION(1, 0, 0)
2118  } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) {
2119  ctx->nb_slices = ctx->slice_block_rows;
2120  ctx->slice_size = 1;
2121 #endif
2122  } else {
2123  av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable "
2124  "slice structure modes (%#x).\n", slice_structure);
2125  return AVERROR(EINVAL);
2126  }
2127 
2128  return 0;
2129 }
2130 
2132  uint32_t slice_structure)
2133 {
2134  VAAPIEncodeContext *ctx = avctx->priv_data;
2135  int i, req_tiles;
2136 
2137  if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS ||
2138  (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS &&
2139  ctx->tile_cols == 1))) {
2140  av_log(avctx, AV_LOG_ERROR, "Supported slice structure (%#x) doesn't work for "
2141  "current tile requirement.\n", slice_structure);
2142  return AVERROR(EINVAL);
2143  }
2144 
2145  if (ctx->tile_rows > ctx->slice_block_rows ||
2146  ctx->tile_cols > ctx->slice_block_cols) {
2147  av_log(avctx, AV_LOG_WARNING, "Not enough block rows/cols (%d x %d) "
2148  "for configured number of tile (%d x %d); ",
2149  ctx->slice_block_rows, ctx->slice_block_cols,
2150  ctx->tile_rows, ctx->tile_cols);
2151  ctx->tile_rows = ctx->tile_rows > ctx->slice_block_rows ?
2152  ctx->slice_block_rows : ctx->tile_rows;
2153  ctx->tile_cols = ctx->tile_cols > ctx->slice_block_cols ?
2154  ctx->slice_block_cols : ctx->tile_cols;
2155  av_log(avctx, AV_LOG_WARNING, "using allowed maximum (%d x %d).\n",
2156  ctx->tile_rows, ctx->tile_cols);
2157  }
2158 
2159  req_tiles = ctx->tile_rows * ctx->tile_cols;
2160 
2161  // Tile slice is not allowed to cross the boundary of a tile due to
2162  // the constraints of media-driver. Currently we support one slice
2163  // per tile. This could be extended to multiple slices per tile.
2164  if (avctx->slices != req_tiles)
2165  av_log(avctx, AV_LOG_WARNING, "The number of requested slices "
2166  "mismatches with configured number of tile (%d != %d); "
2167  "using requested tile number for slice.\n",
2168  avctx->slices, req_tiles);
2169 
2170  ctx->nb_slices = req_tiles;
2171 
2172  // Default in uniform spacing
2173  // 6-3, 6-5
2174  for (i = 0; i < ctx->tile_cols; i++) {
2175  ctx->col_width[i] = ( i + 1 ) * ctx->slice_block_cols / ctx->tile_cols -
2176  i * ctx->slice_block_cols / ctx->tile_cols;
2177  ctx->col_bd[i + 1] = ctx->col_bd[i] + ctx->col_width[i];
2178  }
2179  // 6-4, 6-6
2180  for (i = 0; i < ctx->tile_rows; i++) {
2181  ctx->row_height[i] = ( i + 1 ) * ctx->slice_block_rows / ctx->tile_rows -
2182  i * ctx->slice_block_rows / ctx->tile_rows;
2183  ctx->row_bd[i + 1] = ctx->row_bd[i] + ctx->row_height[i];
2184  }
2185 
2186  av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d x %d tile.\n",
2187  ctx->tile_rows, ctx->tile_cols);
2188 
2189  return 0;
2190 }
2191 
2193 {
2194  VAAPIEncodeContext *ctx = avctx->priv_data;
2195  VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices },
2196  { VAConfigAttribEncSliceStructure },
2197 #if VA_CHECK_VERSION(1, 1, 0)
2198  { VAConfigAttribEncTileSupport },
2199 #endif
2200  };
2201  VAStatus vas;
2202  uint32_t max_slices, slice_structure;
2203  int ret;
2204 
2205  if (!(ctx->codec->flags & FLAG_SLICE_CONTROL)) {
2206  if (avctx->slices > 0) {
2207  av_log(avctx, AV_LOG_WARNING, "Multiple slices were requested "
2208  "but this codec does not support controlling slices.\n");
2209  }
2210  return 0;
2211  }
2212 
2213  av_assert0(ctx->slice_block_height > 0 && ctx->slice_block_width > 0);
2214 
2215  ctx->slice_block_rows = (avctx->height + ctx->slice_block_height - 1) /
2216  ctx->slice_block_height;
2217  ctx->slice_block_cols = (avctx->width + ctx->slice_block_width - 1) /
2218  ctx->slice_block_width;
2219 
2220  if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) {
2221  ctx->nb_slices = 1;
2222  ctx->slice_size = ctx->slice_block_rows;
2223  return 0;
2224  }
2225 
2226  vas = vaGetConfigAttributes(ctx->hwctx->display,
2227  ctx->va_profile,
2228  ctx->va_entrypoint,
2229  attr, FF_ARRAY_ELEMS(attr));
2230  if (vas != VA_STATUS_SUCCESS) {
2231  av_log(avctx, AV_LOG_ERROR, "Failed to query slice "
2232  "attributes: %d (%s).\n", vas, vaErrorStr(vas));
2233  return AVERROR_EXTERNAL;
2234  }
2235  max_slices = attr[0].value;
2236  slice_structure = attr[1].value;
2237  if (max_slices == VA_ATTRIB_NOT_SUPPORTED ||
2238  slice_structure == VA_ATTRIB_NOT_SUPPORTED) {
2239  av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding "
2240  "pictures as multiple slices.\n.");
2241  return AVERROR(EINVAL);
2242  }
2243 
2244  if (ctx->tile_rows && ctx->tile_cols) {
2245 #if VA_CHECK_VERSION(1, 1, 0)
2246  uint32_t tile_support = attr[2].value;
2247  if (tile_support == VA_ATTRIB_NOT_SUPPORTED) {
2248  av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding "
2249  "pictures as multiple tiles.\n.");
2250  return AVERROR(EINVAL);
2251  }
2252 #else
2253  av_log(avctx, AV_LOG_ERROR, "Tile encoding option is "
2254  "not supported with this VAAPI version.\n");
2255  return AVERROR(EINVAL);
2256 #endif
2257  }
2258 
2259  if (ctx->tile_rows && ctx->tile_cols)
2260  ret = vaapi_encode_init_tile_slice_structure(avctx, slice_structure);
2261  else
2262  ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure);
2263  if (ret < 0)
2264  return ret;
2265 
2266  if (ctx->nb_slices > avctx->slices) {
2267  av_log(avctx, AV_LOG_WARNING, "Slice count rounded up to "
2268  "%d (from %d) due to driver constraints on slice "
2269  "structure.\n", ctx->nb_slices, avctx->slices);
2270  }
2271  if (ctx->nb_slices > max_slices) {
2272  av_log(avctx, AV_LOG_ERROR, "Driver does not support "
2273  "encoding with %d slices (max %"PRIu32").\n",
2274  ctx->nb_slices, max_slices);
2275  return AVERROR(EINVAL);
2276  }
2277 
2278  av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n",
2279  ctx->nb_slices);
2280  return 0;
2281 }
2282 
2284 {
2285  VAAPIEncodeContext *ctx = avctx->priv_data;
2286  VAStatus vas;
2287  VAConfigAttrib attr = { VAConfigAttribEncPackedHeaders };
2288 
2289  vas = vaGetConfigAttributes(ctx->hwctx->display,
2290  ctx->va_profile,
2291  ctx->va_entrypoint,
2292  &attr, 1);
2293  if (vas != VA_STATUS_SUCCESS) {
2294  av_log(avctx, AV_LOG_ERROR, "Failed to query packed headers "
2295  "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2296  return AVERROR_EXTERNAL;
2297  }
2298 
2299  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2300  if (ctx->desired_packed_headers) {
2301  av_log(avctx, AV_LOG_WARNING, "Driver does not support any "
2302  "packed headers (wanted %#x).\n",
2303  ctx->desired_packed_headers);
2304  } else {
2305  av_log(avctx, AV_LOG_VERBOSE, "Driver does not support any "
2306  "packed headers (none wanted).\n");
2307  }
2308  ctx->va_packed_headers = 0;
2309  } else {
2310  if (ctx->desired_packed_headers & ~attr.value) {
2311  av_log(avctx, AV_LOG_WARNING, "Driver does not support some "
2312  "wanted packed headers (wanted %#x, found %#x).\n",
2313  ctx->desired_packed_headers, attr.value);
2314  } else {
2315  av_log(avctx, AV_LOG_VERBOSE, "All wanted packed headers "
2316  "available (wanted %#x, found %#x).\n",
2317  ctx->desired_packed_headers, attr.value);
2318  }
2319  ctx->va_packed_headers = ctx->desired_packed_headers & attr.value;
2320  }
2321 
2322  if (ctx->va_packed_headers) {
2323  ctx->config_attributes[ctx->nb_config_attributes++] =
2324  (VAConfigAttrib) {
2325  .type = VAConfigAttribEncPackedHeaders,
2326  .value = ctx->va_packed_headers,
2327  };
2328  }
2329 
2330  if ( (ctx->desired_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2331  !(ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2332  (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
2333  av_log(avctx, AV_LOG_WARNING, "Driver does not support packed "
2334  "sequence headers, but a global header is requested.\n");
2335  av_log(avctx, AV_LOG_WARNING, "No global header will be written: "
2336  "this may result in a stream which is not usable for some "
2337  "purposes (e.g. not muxable to some containers).\n");
2338  }
2339 
2340  return 0;
2341 }
2342 
2344 {
2345 #if VA_CHECK_VERSION(0, 36, 0)
2346  VAAPIEncodeContext *ctx = avctx->priv_data;
2347  VAStatus vas;
2348  VAConfigAttrib attr = { VAConfigAttribEncQualityRange };
2349  int quality = avctx->compression_level;
2350 
2351  vas = vaGetConfigAttributes(ctx->hwctx->display,
2352  ctx->va_profile,
2353  ctx->va_entrypoint,
2354  &attr, 1);
2355  if (vas != VA_STATUS_SUCCESS) {
2356  av_log(avctx, AV_LOG_ERROR, "Failed to query quality "
2357  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2358  return AVERROR_EXTERNAL;
2359  }
2360 
2361  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2362  if (quality != 0) {
2363  av_log(avctx, AV_LOG_WARNING, "Quality attribute is not "
2364  "supported: will use default quality level.\n");
2365  }
2366  } else {
2367  if (quality > attr.value) {
2368  av_log(avctx, AV_LOG_WARNING, "Invalid quality level: "
2369  "valid range is 0-%d, using %d.\n",
2370  attr.value, attr.value);
2371  quality = attr.value;
2372  }
2373 
2374  ctx->quality_params = (VAEncMiscParameterBufferQualityLevel) {
2375  .quality_level = quality,
2376  };
2378  VAEncMiscParameterTypeQualityLevel,
2379  &ctx->quality_params,
2380  sizeof(ctx->quality_params));
2381  }
2382 #else
2383  av_log(avctx, AV_LOG_WARNING, "The encode quality option is "
2384  "not supported with this VAAPI version.\n");
2385 #endif
2386 
2387  return 0;
2388 }
2389 
2391 {
2392 #if VA_CHECK_VERSION(1, 0, 0)
2393  VAAPIEncodeContext *ctx = avctx->priv_data;
2394  VAStatus vas;
2395  VAConfigAttrib attr = { VAConfigAttribEncROI };
2396 
2397  vas = vaGetConfigAttributes(ctx->hwctx->display,
2398  ctx->va_profile,
2399  ctx->va_entrypoint,
2400  &attr, 1);
2401  if (vas != VA_STATUS_SUCCESS) {
2402  av_log(avctx, AV_LOG_ERROR, "Failed to query ROI "
2403  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2404  return AVERROR_EXTERNAL;
2405  }
2406 
2407  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2408  ctx->roi_allowed = 0;
2409  } else {
2410  VAConfigAttribValEncROI roi = {
2411  .value = attr.value,
2412  };
2413 
2414  ctx->roi_max_regions = roi.bits.num_roi_regions;
2415  ctx->roi_allowed = ctx->roi_max_regions > 0 &&
2416  (ctx->va_rc_mode == VA_RC_CQP ||
2417  roi.bits.roi_rc_qp_delta_support);
2418  }
2419 #endif
2420  return 0;
2421 }
2422 
2423 static void vaapi_encode_free_output_buffer(void *opaque,
2424  uint8_t *data)
2425 {
2426  AVCodecContext *avctx = opaque;
2427  VAAPIEncodeContext *ctx = avctx->priv_data;
2428  VABufferID buffer_id;
2429 
2430  buffer_id = (VABufferID)(uintptr_t)data;
2431 
2432  vaDestroyBuffer(ctx->hwctx->display, buffer_id);
2433 
2434  av_log(avctx, AV_LOG_DEBUG, "Freed output buffer %#x\n", buffer_id);
2435 }
2436 
2438  size_t size)
2439 {
2440  AVCodecContext *avctx = opaque;
2441  VAAPIEncodeContext *ctx = avctx->priv_data;
2442  VABufferID buffer_id;
2443  VAStatus vas;
2444  AVBufferRef *ref;
2445 
2446  // The output buffer size is fixed, so it needs to be large enough
2447  // to hold the largest possible compressed frame. We assume here
2448  // that the uncompressed frame plus some header data is an upper
2449  // bound on that.
2450  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
2451  VAEncCodedBufferType,
2452  3 * ctx->surface_width * ctx->surface_height +
2453  (1 << 16), 1, 0, &buffer_id);
2454  if (vas != VA_STATUS_SUCCESS) {
2455  av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream "
2456  "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
2457  return NULL;
2458  }
2459 
2460  av_log(avctx, AV_LOG_DEBUG, "Allocated output buffer %#x\n", buffer_id);
2461 
2462  ref = av_buffer_create((uint8_t*)(uintptr_t)buffer_id,
2463  sizeof(buffer_id),
2465  avctx, AV_BUFFER_FLAG_READONLY);
2466  if (!ref) {
2467  vaDestroyBuffer(ctx->hwctx->display, buffer_id);
2468  return NULL;
2469  }
2470 
2471  return ref;
2472 }
2473 
2475 {
2476  VAAPIEncodeContext *ctx = avctx->priv_data;
2477  AVVAAPIHWConfig *hwconfig = NULL;
2478  AVHWFramesConstraints *constraints = NULL;
2479  enum AVPixelFormat recon_format;
2480  int err, i;
2481 
2482  hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
2483  if (!hwconfig) {
2484  err = AVERROR(ENOMEM);
2485  goto fail;
2486  }
2487  hwconfig->config_id = ctx->va_config;
2488 
2489  constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref,
2490  hwconfig);
2491  if (!constraints) {
2492  err = AVERROR(ENOMEM);
2493  goto fail;
2494  }
2495 
2496  // Probably we can use the input surface format as the surface format
2497  // of the reconstructed frames. If not, we just pick the first (only?)
2498  // format in the valid list and hope that it all works.
2499  recon_format = AV_PIX_FMT_NONE;
2500  if (constraints->valid_sw_formats) {
2501  for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
2502  if (ctx->input_frames->sw_format ==
2503  constraints->valid_sw_formats[i]) {
2504  recon_format = ctx->input_frames->sw_format;
2505  break;
2506  }
2507  }
2508  if (recon_format == AV_PIX_FMT_NONE) {
2509  // No match. Just use the first in the supported list and
2510  // hope for the best.
2511  recon_format = constraints->valid_sw_formats[0];
2512  }
2513  } else {
2514  // No idea what to use; copy input format.
2515  recon_format = ctx->input_frames->sw_format;
2516  }
2517  av_log(avctx, AV_LOG_DEBUG, "Using %s as format of "
2518  "reconstructed frames.\n", av_get_pix_fmt_name(recon_format));
2519 
2520  if (ctx->surface_width < constraints->min_width ||
2521  ctx->surface_height < constraints->min_height ||
2522  ctx->surface_width > constraints->max_width ||
2523  ctx->surface_height > constraints->max_height) {
2524  av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at "
2525  "size %dx%d (constraints: width %d-%d height %d-%d).\n",
2526  ctx->surface_width, ctx->surface_height,
2527  constraints->min_width, constraints->max_width,
2528  constraints->min_height, constraints->max_height);
2529  err = AVERROR(EINVAL);
2530  goto fail;
2531  }
2532 
2533  av_freep(&hwconfig);
2534  av_hwframe_constraints_free(&constraints);
2535 
2536  ctx->recon_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
2537  if (!ctx->recon_frames_ref) {
2538  err = AVERROR(ENOMEM);
2539  goto fail;
2540  }
2541  ctx->recon_frames = (AVHWFramesContext*)ctx->recon_frames_ref->data;
2542 
2543  ctx->recon_frames->format = AV_PIX_FMT_VAAPI;
2544  ctx->recon_frames->sw_format = recon_format;
2545  ctx->recon_frames->width = ctx->surface_width;
2546  ctx->recon_frames->height = ctx->surface_height;
2547 
2548  err = av_hwframe_ctx_init(ctx->recon_frames_ref);
2549  if (err < 0) {
2550  av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
2551  "frame context: %d.\n", err);
2552  goto fail;
2553  }
2554 
2555  err = 0;
2556  fail:
2557  av_freep(&hwconfig);
2558  av_hwframe_constraints_free(&constraints);
2559  return err;
2560 }
2561 
2563 {
2564  VAAPIEncodeContext *ctx = avctx->priv_data;
2565  AVVAAPIFramesContext *recon_hwctx = NULL;
2566  VAStatus vas;
2567  int err;
2568 
2569  ctx->va_config = VA_INVALID_ID;
2570  ctx->va_context = VA_INVALID_ID;
2571 
2572  /* If you add something that can fail above this av_frame_alloc(),
2573  * modify ff_vaapi_encode_close() accordingly. */
2574  ctx->frame = av_frame_alloc();
2575  if (!ctx->frame) {
2576  return AVERROR(ENOMEM);
2577  }
2578 
2579  if (!avctx->hw_frames_ctx) {
2580  av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
2581  "required to associate the encoding device.\n");
2582  return AVERROR(EINVAL);
2583  }
2584 
2585  ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
2586  if (!ctx->input_frames_ref) {
2587  err = AVERROR(ENOMEM);
2588  goto fail;
2589  }
2590  ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
2591 
2592  ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
2593  if (!ctx->device_ref) {
2594  err = AVERROR(ENOMEM);
2595  goto fail;
2596  }
2597  ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
2598  ctx->hwctx = ctx->device->hwctx;
2599 
2600  err = vaapi_encode_profile_entrypoint(avctx);
2601  if (err < 0)
2602  goto fail;
2603 
2604  if (ctx->codec->get_encoder_caps) {
2605  err = ctx->codec->get_encoder_caps(avctx);
2606  if (err < 0)
2607  goto fail;
2608  } else {
2609  // Assume 16x16 blocks.
2610  ctx->surface_width = FFALIGN(avctx->width, 16);
2611  ctx->surface_height = FFALIGN(avctx->height, 16);
2612  if (ctx->codec->flags & FLAG_SLICE_CONTROL) {
2613  ctx->slice_block_width = 16;
2614  ctx->slice_block_height = 16;
2615  }
2616  }
2617 
2618  err = vaapi_encode_init_rate_control(avctx);
2619  if (err < 0)
2620  goto fail;
2621 
2622  err = vaapi_encode_init_gop_structure(avctx);
2623  if (err < 0)
2624  goto fail;
2625 
2626  err = vaapi_encode_init_slice_structure(avctx);
2627  if (err < 0)
2628  goto fail;
2629 
2630  err = vaapi_encode_init_packed_headers(avctx);
2631  if (err < 0)
2632  goto fail;
2633 
2634  err = vaapi_encode_init_roi(avctx);
2635  if (err < 0)
2636  goto fail;
2637 
2638  if (avctx->compression_level >= 0) {
2639  err = vaapi_encode_init_quality(avctx);
2640  if (err < 0)
2641  goto fail;
2642  }
2643 
2644  if (ctx->max_frame_size) {
2645  err = vaapi_encode_init_max_frame_size(avctx);
2646  if (err < 0)
2647  goto fail;
2648  }
2649 
2650  vas = vaCreateConfig(ctx->hwctx->display,
2651  ctx->va_profile, ctx->va_entrypoint,
2652  ctx->config_attributes, ctx->nb_config_attributes,
2653  &ctx->va_config);
2654  if (vas != VA_STATUS_SUCCESS) {
2655  av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
2656  "configuration: %d (%s).\n", vas, vaErrorStr(vas));
2657  err = AVERROR(EIO);
2658  goto fail;
2659  }
2660 
2661  err = vaapi_encode_create_recon_frames(avctx);
2662  if (err < 0)
2663  goto fail;
2664 
2665  recon_hwctx = ctx->recon_frames->hwctx;
2666  vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
2667  ctx->surface_width, ctx->surface_height,
2668  VA_PROGRESSIVE,
2669  recon_hwctx->surface_ids,
2670  recon_hwctx->nb_surfaces,
2671  &ctx->va_context);
2672  if (vas != VA_STATUS_SUCCESS) {
2673  av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
2674  "context: %d (%s).\n", vas, vaErrorStr(vas));
2675  err = AVERROR(EIO);
2676  goto fail;
2677  }
2678 
2679  ctx->output_buffer_pool =
2680  av_buffer_pool_init2(sizeof(VABufferID), avctx,
2682  if (!ctx->output_buffer_pool) {
2683  err = AVERROR(ENOMEM);
2684  goto fail;
2685  }
2686 
2687  if (ctx->codec->configure) {
2688  err = ctx->codec->configure(avctx);
2689  if (err < 0)
2690  goto fail;
2691  }
2692 
2693  ctx->output_delay = ctx->b_per_p;
2694  ctx->decode_delay = ctx->max_b_depth;
2695 
2696  if (ctx->codec->sequence_params_size > 0) {
2697  ctx->codec_sequence_params =
2698  av_mallocz(ctx->codec->sequence_params_size);
2699  if (!ctx->codec_sequence_params) {
2700  err = AVERROR(ENOMEM);
2701  goto fail;
2702  }
2703  }
2704  if (ctx->codec->picture_params_size > 0) {
2705  ctx->codec_picture_params =
2706  av_mallocz(ctx->codec->picture_params_size);
2707  if (!ctx->codec_picture_params) {
2708  err = AVERROR(ENOMEM);
2709  goto fail;
2710  }
2711  }
2712 
2713  if (ctx->codec->init_sequence_params) {
2714  err = ctx->codec->init_sequence_params(avctx);
2715  if (err < 0) {
2716  av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
2717  "failed: %d.\n", err);
2718  goto fail;
2719  }
2720  }
2721 
2722  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
2723  ctx->codec->write_sequence_header &&
2726  size_t bit_len = 8 * sizeof(data);
2727 
2728  err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
2729  if (err < 0) {
2730  av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
2731  "for extradata: %d.\n", err);
2732  goto fail;
2733  } else {
2734  avctx->extradata_size = (bit_len + 7) / 8;
2735  avctx->extradata = av_mallocz(avctx->extradata_size +
2737  if (!avctx->extradata) {
2738  err = AVERROR(ENOMEM);
2739  goto fail;
2740  }
2741  memcpy(avctx->extradata, data, avctx->extradata_size);
2742  }
2743  }
2744 
2745 #if VA_CHECK_VERSION(1, 9, 0)
2746  // check vaSyncBuffer function
2747  vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0);
2748  if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) {
2749  ctx->has_sync_buffer_func = 1;
2750  ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth,
2751  sizeof(VAAPIEncodePicture *),
2752  0);
2753  if (!ctx->encode_fifo)
2754  return AVERROR(ENOMEM);
2755  }
2756 #endif
2757 
2758  return 0;
2759 
2760 fail:
2761  return err;
2762 }
2763 
2765 {
2766  VAAPIEncodeContext *ctx = avctx->priv_data;
2767  VAAPIEncodePicture *pic, *next;
2768 
2769  /* We check ctx->frame to know whether ff_vaapi_encode_init()
2770  * has been called and va_config/va_context initialized. */
2771  if (!ctx->frame)
2772  return 0;
2773 
2774  for (pic = ctx->pic_start; pic; pic = next) {
2775  next = pic->next;
2776  vaapi_encode_free(avctx, pic);
2777  }
2778 
2779  av_buffer_pool_uninit(&ctx->output_buffer_pool);
2780 
2781  if (ctx->va_context != VA_INVALID_ID) {
2782  vaDestroyContext(ctx->hwctx->display, ctx->va_context);
2783  ctx->va_context = VA_INVALID_ID;
2784  }
2785 
2786  if (ctx->va_config != VA_INVALID_ID) {
2787  vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
2788  ctx->va_config = VA_INVALID_ID;
2789  }
2790 
2791  av_frame_free(&ctx->frame);
2792 
2793  av_freep(&ctx->codec_sequence_params);
2794  av_freep(&ctx->codec_picture_params);
2795  av_fifo_freep2(&ctx->encode_fifo);
2796 
2797  av_buffer_unref(&ctx->recon_frames_ref);
2798  av_buffer_unref(&ctx->input_frames_ref);
2799  av_buffer_unref(&ctx->device_ref);
2800 
2801  return 0;
2802 }
AV_LOG_WARNING
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:186
VAAPIEncodeSlice::codec_slice_params
void * codec_slice_params
Definition: vaapi_encode.h:69
AVPixelFormat
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
av_fifo_can_write
size_t av_fifo_can_write(const AVFifo *f)
Definition: fifo.c:94
level
uint8_t level
Definition: svq3.c:204
av_clip
#define av_clip
Definition: common.h:95
vaapi_encode_init_roi
static av_cold int vaapi_encode_init_roi(AVCodecContext *avctx)
Definition: vaapi_encode.c:2390
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
AVVAAPIHWConfig
VAAPI hardware pipeline configuration details.
Definition: hwcontext_vaapi.h:110
PICTURE_TYPE_IDR
@ PICTURE_TYPE_IDR
Definition: vaapi_encode.h:57
av_frame_get_side_data
AVFrameSideData * av_frame_get_side_data(const AVFrame *frame, enum AVFrameSideDataType type)
Definition: frame.c:691
av_clip_int8
#define av_clip_int8
Definition: common.h:104
av_hwdevice_hwconfig_alloc
void * av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
Allocate a HW-specific configuration structure for a given HW device.
Definition: hwcontext.c:570
av_pix_fmt_desc_get
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2888
AVERROR_EOF
#define AVERROR_EOF
End of file.
Definition: error.h:57
vaapi_encode_make_row_slice
static int vaapi_encode_make_row_slice(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:183
AVBufferRef::data
uint8_t * data
The data buffer.
Definition: buffer.h:90
AV_CODEC_FLAG_QSCALE
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition: avcodec.h:216
vaapi_encode_entrypoints_normal
static const VAEntrypoint vaapi_encode_entrypoints_normal[]
Definition: vaapi_encode.c:1342
av_unused
#define av_unused
Definition: attributes.h:131
av_frame_free
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:116
vaapi_encode_init_slice_structure
static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
Definition: vaapi_encode.c:2192
av_hwframe_ctx_init
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:334
AVFrame
This structure describes decoded (raw) audio or video data.
Definition: frame.h:330
tmp
static uint8_t tmp[11]
Definition: aes_ctr.c:28
pixdesc.h
AVCodec::capabilities
int capabilities
Codec capabilities.
Definition: codec.h:223
av_hwframe_ctx_alloc
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:248
AVPacket::data
uint8_t * data
Definition: packet.h:374
VAAPIEncodeSlice
Definition: vaapi_encode.h:63
VAAPIEncodePicture::refs
struct VAAPIEncodePicture * refs[MAX_PICTURE_REFERENCES]
Definition: vaapi_encode.h:122
encode.h
data
const char data[16]
Definition: mxf.c:146
VAAPIEncodePicture::force_idr
int force_idr
Definition: vaapi_encode.h:79
MAX_PICTURE_REFERENCES
@ MAX_PICTURE_REFERENCES
Definition: vaapi_encode.h:44
AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS
@ AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
Definition: hwcontext_vaapi.h:47
VAAPIEncodeSlice::block_start
int block_start
Definition: vaapi_encode.h:67
AV_LOG_VERBOSE
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:196
VAAPIEncodePicture::ref_count
int ref_count[2]
Definition: vaapi_encode.h:129
ff_vaapi_encode_close
av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
Definition: vaapi_encode.c:2764
AVPacket::duration
int64_t duration
Duration of this packet in AVStream->time_base units, 0 if unknown.
Definition: packet.h:392
vaapi_encode_init_rate_control
static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)
Definition: vaapi_encode.c:1578
VAAPIEncodeSlice::index
int index
Definition: vaapi_encode.h:64
VAAPIEncodePicture::nb_refs
int nb_refs
Definition: vaapi_encode.h:121
av_buffer_ref
AVBufferRef * av_buffer_ref(const AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:103
AVCodecContext::qmax
int qmax
maximum quantizer
Definition: avcodec.h:1227
av_hwdevice_get_hwframe_constraints
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:581
AV_PKT_FLAG_KEY
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: packet.h:429
FLAG_CONSTANT_QUALITY_ONLY
@ FLAG_CONSTANT_QUALITY_ONLY
Definition: vaapi_encode.h:373
VAAPIEncodeRTFormat::value
unsigned int value
Definition: vaapi_encode.c:1316
quality
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But a word about quality
Definition: rate_distortion.txt:12
AVFrame::data
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:351
av_malloc
#define av_malloc(s)
Definition: tableprint_vlc.h:30
AV_CODEC_FLAG_GLOBAL_HEADER
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition: avcodec.h:317
AVHWFramesConstraints
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:453
AVCodecContext::framerate
AVRational framerate
Definition: avcodec.h:1768
AVVAAPIHWConfig::config_id
VAConfigID config_id
ID of a VAAPI pipeline configuration.
Definition: hwcontext_vaapi.h:114
AVVAAPIFramesContext::surface_ids
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
Definition: hwcontext_vaapi.h:101
AV_CODEC_FLAG_COPY_OPAQUE
#define AV_CODEC_FLAG_COPY_OPAQUE
Request the encoder to propagate each frame's AVFrame.opaque and AVFrame.opaque_ref values to its cor...
Definition: avcodec.h:269
FLAG_NON_IDR_KEY_PICTURES
@ FLAG_NON_IDR_KEY_PICTURES
Definition: vaapi_encode.h:382
AVCodecContext::codec
const struct AVCodec * codec
Definition: avcodec.h:440
AVPacket::opaque_ref
AVBufferRef * opaque_ref
AVBufferRef for free use by the API user.
Definition: packet.h:410
VAAPIEncodeSlice::row_start
int row_start
Definition: vaapi_encode.h:65
vaapi_encode.h
vaapi_encode_init_gop_structure
static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
Definition: vaapi_encode.c:1965
vaapi_encode_make_tile_slice
static int vaapi_encode_make_tile_slice(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:238
fail
#define fail()
Definition: checkasm.h:134
av_fifo_write
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
Definition: fifo.c:188
VAAPIEncodePicture
Definition: vaapi_encode.h:72
av_buffer_pool_init2
AVBufferPool * av_buffer_pool_init2(size_t size, void *opaque, AVBufferRef *(*alloc)(void *opaque, size_t size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:259
AVHWFramesConstraints::min_width
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:471
vaapi_encode_pick_next
static int vaapi_encode_pick_next(AVCodecContext *avctx, VAAPIEncodePicture **pic_out)
Definition: vaapi_encode.c:929
AVCodecContext::flags
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:511
VAAPIEncodeRTFormat
Definition: vaapi_encode.c:1314
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
TRY_RC_MODE
#define TRY_RC_MODE(mode, fail)
av_reduce
int av_reduce(int *dst_num, int *dst_den, int64_t num, int64_t den, int64_t max)
Reduce a fraction.
Definition: rational.c:35
AVRational::num
int num
Numerator.
Definition: rational.h:59
FLAG_B_PICTURES
@ FLAG_B_PICTURES
Definition: vaapi_encode.h:377
PICTURE_TYPE_I
@ PICTURE_TYPE_I
Definition: vaapi_encode.h:58
MAX_GLOBAL_PARAMS
@ MAX_GLOBAL_PARAMS
Definition: vaapi_encode.h:42
AVHWDeviceContext
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:61
av_frame_alloc
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:104
vaapi_encode_rt_formats
static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[]
Definition: vaapi_encode.c:1323
picture_type_name
static const char *const picture_type_name[]
Definition: vaapi_encode.c:39
first
trying all byte sequences megabyte in length and selecting the best looking sequence will yield cases to try But first
Definition: rate_distortion.txt:12
avassert.h
VAAPIEncodeRTFormat::log2_chroma_w
int log2_chroma_w
Definition: vaapi_encode.c:1319
pkt
AVPacket * pkt
Definition: movenc.c:59
AV_LOG_ERROR
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:180
FF_ARRAY_ELEMS
#define FF_ARRAY_ELEMS(a)
Definition: sinewin_tablegen.c:29
av_cold
#define av_cold
Definition: attributes.h:90
AVRegionOfInterest
Structure describing a single Region Of Interest.
Definition: frame.h:255
av_fifo_read
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
Definition: fifo.c:240
AVCodecContext::rc_initial_buffer_occupancy
int rc_initial_buffer_occupancy
Number of bits which should be loaded into the rc buffer before decoding starts.
Definition: avcodec.h:1284
AVHWFramesConstraints::valid_sw_formats
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:465
VAAPIEncodeSlice::row_size
int row_size
Definition: vaapi_encode.h:66
av_buffer_pool_get
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:384
av_hwframe_constraints_free
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition: hwcontext.c:606
VAAPIEncodePicture::codec_picture_params
void * codec_picture_params
Definition: vaapi_encode.h:109
AVCodecContext::extradata_size
int extradata_size
Definition: avcodec.h:533
AVCodecContext::global_quality
int global_quality
Global quality for codecs which cannot change it per frame.
Definition: avcodec.h:497
AVRegionOfInterest::bottom
int bottom
Definition: frame.h:271
av_realloc_array
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:225
AV_BUFFER_FLAG_READONLY
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:114
RC_MODE_CQP
@ RC_MODE_CQP
Definition: vaapi_encode.h:153
AVFormatContext::flags
int flags
Flags modifying the (de)muxer behaviour.
Definition: avformat.h:1334
VAAPIEncodePicture::encode_complete
int encode_complete
Definition: vaapi_encode.h:94
vaapi_encode_make_param_buffer
static int vaapi_encode_make_param_buffer(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t len)
Definition: vaapi_encode.c:87
FLAG_INTRA_ONLY
@ FLAG_INTRA_ONLY
Definition: vaapi_encode.h:375
FF_PROFILE_UNKNOWN
#define FF_PROFILE_UNKNOWN
Definition: avcodec.h:1584
av_assert0
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
VAAPIEncodePicture::pts
int64_t pts
Definition: vaapi_encode.h:77
AV_LOG_DEBUG
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:201
ctx
AVFormatContext * ctx
Definition: movenc.c:48
RC_MODE_CBR
@ RC_MODE_CBR
Definition: vaapi_encode.h:154
ff_vaapi_encode_receive_packet
int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
Definition: vaapi_encode.c:1205
vaapi_encode_alloc
static VAAPIEncodePicture * vaapi_encode_alloc(AVCodecContext *avctx)
Definition: vaapi_encode.c:748
vaapi_encode_set_b_pictures
static void vaapi_encode_set_b_pictures(AVCodecContext *avctx, VAAPIEncodePicture *start, VAAPIEncodePicture *end, VAAPIEncodePicture *prev, int current_depth, VAAPIEncodePicture **last)
Definition: vaapi_encode.c:865
AVCodecContext::rc_max_rate
int64_t rc_max_rate
maximum bitrate
Definition: avcodec.h:1256
VAAPIEncodePicture::opaque
void * opaque
Definition: vaapi_encode.h:81
AVPacket::opaque
void * opaque
for some private data of the user
Definition: packet.h:399
RC_MODE_QVBR
@ RC_MODE_QVBR
Definition: vaapi_encode.h:157
vaapi_encode_discard
static int vaapi_encode_discard(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:731
VAAPIEncodeContext
Definition: vaapi_encode.h:181
VAAPIEncodePicture::prev
struct VAAPIEncodePicture * prev
Definition: vaapi_encode.h:125
if
if(ret)
Definition: filter_design.txt:179
vaapi_encode_add_ref
static void vaapi_encode_add_ref(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodePicture *target, int is_ref, int in_dpb, int prev)
Definition: vaapi_encode.c:805
AVCodecContext::rc_buffer_size
int rc_buffer_size
decoder bitstream buffer size
Definition: avcodec.h:1241
vaapi_encode_issue
static int vaapi_encode_issue(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:265
NULL
#define NULL
Definition: coverity.c:32
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:139
VAAPIEncodePicture::dpb
struct VAAPIEncodePicture * dpb[MAX_DPB_SIZE]
Definition: vaapi_encode.h:118
AVCodecContext::bit_rate
int64_t bit_rate
the average bitrate
Definition: avcodec.h:481
AVRegionOfInterest::self_size
uint32_t self_size
Must be set to the size of this data structure (that is, sizeof(AVRegionOfInterest)).
Definition: frame.h:260
AV_PICTURE_TYPE_I
@ AV_PICTURE_TYPE_I
Intra.
Definition: avutil.h:274
av_buffer_pool_uninit
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:322
PICTURE_TYPE_P
@ PICTURE_TYPE_P
Definition: vaapi_encode.h:59
av_fifo_can_read
size_t av_fifo_can_read(const AVFifo *f)
Definition: fifo.c:87
vaapi_encode_remove_refs
static void vaapi_encode_remove_refs(AVCodecContext *avctx, VAAPIEncodePicture *pic, int level)
Definition: vaapi_encode.c:835
VAAPIEncodePicture::opaque_ref
AVBufferRef * opaque_ref
Definition: vaapi_encode.h:82
VAAPIEncodePicture::duration
int64_t duration
Definition: vaapi_encode.h:78
index
int index
Definition: gxfenc.c:89
VAAPIEncodeRTFormat::name
const char * name
Definition: vaapi_encode.c:1315
VAAPIEncodePicture::encode_issued
int encode_issued
Definition: vaapi_encode.h:93
av_buffer_create
AVBufferRef * av_buffer_create(uint8_t *data, size_t size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:55
AVCodecContext::time_base
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented.
Definition: avcodec.h:554
VAAPIEncodePicture::slices
VAAPIEncodeSlice * slices
Definition: vaapi_encode.h:133
VAAPIEncodePicture::input_surface
VASurfaceID input_surface
Definition: vaapi_encode.h:97
VAAPIEncodePicture::type
int type
Definition: vaapi_encode.h:91
AVCodecContext::gop_size
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:626
vaapi_encode_init_quality
static av_cold int vaapi_encode_init_quality(AVCodecContext *avctx)
Definition: vaapi_encode.c:2343
for
for(k=2;k<=8;++k)
Definition: h264pred_template.c:425
vaapi_encode_make_misc_param_buffer
static int vaapi_encode_make_misc_param_buffer(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, const void *data, size_t len)
Definition: vaapi_encode.c:115
vaapi_encode_rc_modes
static const VAAPIEncodeRCMode vaapi_encode_rc_modes[]
Definition: vaapi_encode.c:1557
size
int size
Definition: twinvq_data.h:10344
VAAPIEncodeRTFormat::nb_components
int nb_components
Definition: vaapi_encode.c:1318
AVCodecHWConfigInternal
Definition: hwconfig.h:29
RC_MODE_AVBR
@ RC_MODE_AVBR
Definition: vaapi_encode.h:158
header
static const uint8_t header[24]
Definition: sdr2.c:67
VAAPIEncodeRTFormat::log2_chroma_h
int log2_chroma_h
Definition: vaapi_encode.c:1320
AVPacket::dts
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed.
Definition: packet.h:373
VAAPIEncodePicture::recon_surface
VASurfaceID recon_surface
Definition: vaapi_encode.h:100
vaapi_encode_init_packed_headers
static av_cold int vaapi_encode_init_packed_headers(AVCodecContext *avctx)
Definition: vaapi_encode.c:2283
AVERROR_EXTERNAL
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:59
VAAPIEncodePicture::output_buffer
VABufferID output_buffer
Definition: vaapi_encode.h:106
AVHWFramesConstraints::max_width
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:478
vaapi_encode_create_recon_frames
static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx)
Definition: vaapi_encode.c:2474
VAAPIEncodePicture::priv_data
void * priv_data
Definition: vaapi_encode.h:108
AVPacket::flags
int flags
A combination of AV_PKT_FLAG values.
Definition: packet.h:380
AVRegionOfInterest::right
int right
Definition: frame.h:273
VAAPIEncodePicture::display_order
int64_t display_order
Definition: vaapi_encode.h:75
AV_PIX_FMT_VAAPI
@ AV_PIX_FMT_VAAPI
Hardware acceleration through VA-API, data[3] contains a VASurfaceID.
Definition: pixfmt.h:119
VAAPIEncodePicture::nb_dpb_pics
int nb_dpb_pics
Definition: vaapi_encode.h:117
VAAPIEncodePicture::b_depth
int b_depth
Definition: vaapi_encode.h:92
vaapi_encode_free
static int vaapi_encode_free(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:772
VAAPIEncodePicture::ref_removed
int ref_removed[2]
Definition: vaapi_encode.h:130
HW_CONFIG_ENCODER_FRAMES
#define HW_CONFIG_ENCODER_FRAMES(format, device_type_)
Definition: hwconfig.h:97
AVRegionOfInterest::left
int left
Definition: frame.h:272
vaapi_encode_free_output_buffer
static void vaapi_encode_free_output_buffer(void *opaque, uint8_t *data)
Definition: vaapi_encode.c:2423
vaapi_encode_check_frame
static int vaapi_encode_check_frame(AVCodecContext *avctx, const AVFrame *frame)
Definition: vaapi_encode.c:1103
log.h
i
#define i(width, name, range_min, range_max)
Definition: cbs_h2645.c:269
AVPacket::pts
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: packet.h:367
AVCodecContext::extradata
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:532
AVRegionOfInterest::top
int top
Distance in pixels from the top edge of the frame to the top and bottom edges and from the left edge ...
Definition: frame.h:270
internal.h
av_malloc_array
#define av_malloc_array(a, b)
Definition: tableprint_vlc.h:31
VAAPIEncodePicture::roi
void * roi
Definition: vaapi_encode.h:88
FLAG_SLICE_CONTROL
@ FLAG_SLICE_CONTROL
Definition: vaapi_encode.h:371
common.h
MAX_PARAM_BUFFER_SIZE
@ MAX_PARAM_BUFFER_SIZE
Definition: vaapi_encode.h:46
FFMIN
#define FFMIN(a, b)
Definition: macros.h:49
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:516
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:264
av_buffer_replace
int av_buffer_replace(AVBufferRef **pdst, const AVBufferRef *src)
Ensure dst refers to the same data as src.
Definition: buffer.c:233
len
int len
Definition: vorbis_enc_data.h:426
profile
int profile
Definition: mxfenc.c:2006
AVCodecContext::height
int height
Definition: avcodec.h:604
av_calloc
void * av_calloc(size_t nmemb, size_t size)
Definition: mem.c:272
AVCodecContext::hw_frames_ctx
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames.
Definition: avcodec.h:1916
avcodec.h
AVHWFramesContext
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:124
ff_vaapi_encode_hw_configs
const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[]
Definition: vaapi_encode.c:34
VAAPIEncodePicture::output_buffer_ref
AVBufferRef * output_buffer_ref
Definition: vaapi_encode.h:105
AV_CODEC_FLAG_CLOSED_GOP
#define AV_CODEC_FLAG_CLOSED_GOP
Definition: avcodec.h:331
ff_vaapi_encode_init
av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
Definition: vaapi_encode.c:2562
ret
ret
Definition: filter_design.txt:187
VAAPIEncodeRTFormat::depth
int depth
Definition: vaapi_encode.c:1317
vaapi_encode_add_global_param
static av_cold void vaapi_encode_add_global_param(AVCodecContext *avctx, int type, void *buffer, size_t size)
Definition: vaapi_encode.c:1300
vaapi_encode_output
static int vaapi_encode_output(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt)
Definition: vaapi_encode.c:653
frame
these buffered frames must be flushed immediately if a new input produces new the filter must not call request_frame to get more It must just process the frame or queue it The task of requesting more frames is left to the filter s request_frame method or the application If a filter has several the filter must be ready for frames arriving randomly on any input any filter with several inputs will most likely require some kind of queuing mechanism It is perfectly acceptable to have a limited queue and to drop frames when the inputs are too unbalanced request_frame For filters that do not use the this method is called when a frame is wanted on an output For a it should directly call filter_frame on the corresponding output For a if there are queued frames already one of these frames should be pushed If the filter should request a frame on one of its repeatedly until at least one frame has been pushed Return or at least make progress towards producing a frame
Definition: filter_design.txt:264
av_fifo_alloc2
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
Definition: fifo.c:47
AVHWFramesConstraints::max_height
int max_height
Definition: hwcontext.h:479
AV_INPUT_BUFFER_PADDING_SIZE
#define AV_INPUT_BUFFER_PADDING_SIZE
Definition: defs.h:40
VAAPIEncodePicture::param_buffers
VABufferID * param_buffers
Definition: vaapi_encode.h:103
AVCodecContext
main external API structure.
Definition: avcodec.h:431
RC_MODE_VBR
@ RC_MODE_VBR
Definition: vaapi_encode.h:155
AVHWFramesConstraints::min_height
int min_height
Definition: hwcontext.h:472
AVVAAPIFramesContext::nb_surfaces
int nb_surfaces
Definition: hwcontext_vaapi.h:102
buffer
the frame and frame reference mechanism is intended to as much as expensive copies of that data while still allowing the filters to produce correct results The data is stored in buffers represented by AVFrame structures Several references can point to the same frame buffer
Definition: filter_design.txt:49
ff_get_encode_buffer
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
Definition: encode.c:79
AVCodecContext::qmin
int qmin
minimum quantizer
Definition: avcodec.h:1220
AVRational::den
int den
Denominator.
Definition: rational.h:60
VAAPIEncodePicture::is_reference
int is_reference
Definition: vaapi_encode.h:112
AV_PIX_FMT_NONE
@ AV_PIX_FMT_NONE
Definition: pixfmt.h:65
VAAPIEncodePicture::recon_image
AVFrame * recon_image
Definition: vaapi_encode.h:99
AVCodecContext::profile
int profile
profile
Definition: avcodec.h:1583
ref
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:112
RC_MODE_ICQ
@ RC_MODE_ICQ
Definition: vaapi_encode.h:156
AV_CODEC_CAP_DELAY
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
Definition: codec.h:82
PICTURE_TYPE_B
@ PICTURE_TYPE_B
Definition: vaapi_encode.h:60
FLAG_B_PICTURE_REFERENCES
@ FLAG_B_PICTURE_REFERENCES
Definition: vaapi_encode.h:379
vaapi_encode_init_tile_slice_structure
static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx, uint32_t slice_structure)
Definition: vaapi_encode.c:2131
VAAPIEncodePicture::next
struct VAAPIEncodePicture * next
Definition: vaapi_encode.h:73
desc
const char * desc
Definition: libsvtav1.c:83
AVCodecContext::max_b_frames
int max_b_frames
maximum number of B-frames between non-B-frames Note: The output will be delayed by max_b_frames+1 re...
Definition: avcodec.h:703
ff_encode_get_frame
int ff_encode_get_frame(AVCodecContext *avctx, AVFrame *frame)
Called by encoders to get the next frame for encoding.
Definition: encode.c:178
AVBufferRef
A reference to a data buffer.
Definition: buffer.h:82
VAAPIEncodePicture::input_image
AVFrame * input_image
Definition: vaapi_encode.h:96
MAX_DPB_SIZE
@ MAX_DPB_SIZE
Definition: vaapi_encode.h:43
VAAPIEncodeSlice::block_size
int block_size
Definition: vaapi_encode.h:68
AVFrameSideData
Structure to hold side data for an AVFrame.
Definition: frame.h:236
VAAPIEncodeRCMode
Definition: vaapi_encode.h:162
AVPixFmtDescriptor
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:69
vaapi_encode_alloc_output_buffer
static AVBufferRef * vaapi_encode_alloc_output_buffer(void *opaque, size_t size)
Definition: vaapi_encode.c:2437
AVVAAPIFramesContext
VAAPI-specific data associated with a frame pool.
Definition: hwcontext_vaapi.h:88
vaapi_encode_send_frame
static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame)
Definition: vaapi_encode.c:1129
av_free
#define av_free(p)
Definition: tableprint_vlc.h:33
vaapi_encode_profile_entrypoint
static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
Definition: vaapi_encode.c:1357
FFALIGN
#define FFALIGN(x, a)
Definition: macros.h:78
AVCodecContext::slices
int slices
Number of slices.
Definition: avcodec.h:1031
AVPacket
This structure stores compressed data.
Definition: packet.h:351
AVCodecContext::priv_data
void * priv_data
Definition: avcodec.h:458
VAAPIEncodePicture::encode_order
int64_t encode_order
Definition: vaapi_encode.h:76
av_freep
#define av_freep(p)
Definition: tableprint_vlc.h:34
AVCodecContext::width
int width
picture width / height.
Definition: avcodec.h:604
convert_header.str
string str
Definition: convert_header.py:20
AV_FRAME_DATA_REGIONS_OF_INTEREST
@ AV_FRAME_DATA_REGIONS_OF_INTEREST
Regions Of Interest, the data is an array of AVRegionOfInterest type, the number of array element is ...
Definition: frame.h:165
vaapi_encode_init_max_frame_size
static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx)
Definition: vaapi_encode.c:1908
av_log
#define av_log(a,...)
Definition: tableprint_vlc.h:27
av_fifo_freep2
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
Definition: fifo.c:286
VAAPIEncodePicture::nb_param_buffers
int nb_param_buffers
Definition: vaapi_encode.h:102
vaapi_encode_clear_old
static int vaapi_encode_clear_old(AVCodecContext *avctx)
Definition: vaapi_encode.c:1065
rc_mode
mfxU16 rc_mode
Definition: qsvenc.c:142
vaapi_encode_make_packed_header
static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len)
Definition: vaapi_encode.c:41
vaapi_encode_wait
static int vaapi_encode_wait(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:138
int
int
Definition: ffmpeg_filter.c:156
av_hwframe_get_buffer
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:507
AVRegionOfInterest::qoffset
AVRational qoffset
Quantisation offset.
Definition: frame.h:297
snprintf
#define snprintf
Definition: snprintf.h:34
av_log2
int av_log2(unsigned v)
Definition: intmath.c:26
vaapi_encode_init_row_slice_structure
static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx, uint32_t slice_structure)
Definition: vaapi_encode.c:2086
VAAPIEncodeProfile
Definition: vaapi_encode.h:136
av_get_pix_fmt_name
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:2808
AVCodecContext::compression_level
int compression_level
Definition: avcodec.h:503
VAAPIEncodePicture::nb_slices
int nb_slices
Definition: vaapi_encode.h:132