FFmpeg
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
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 <inttypes.h>
20 #include <string.h>
21 
22 #include "libavutil/avassert.h"
23 #include "libavutil/common.h"
24 #include "libavutil/log.h"
25 #include "libavutil/pixdesc.h"
26 
27 #include "vaapi_encode.h"
28 #include "avcodec.h"
29 
30 static const char * const picture_type_name[] = { "IDR", "I", "P", "B" };
31 
33  VAAPIEncodePicture *pic,
34  int type, char *data, size_t bit_len)
35 {
37  VAStatus vas;
38  VABufferID param_buffer, data_buffer;
39  VABufferID *tmp;
40  VAEncPackedHeaderParameterBuffer params = {
41  .type = type,
42  .bit_length = bit_len,
43  .has_emulation_bytes = 1,
44  };
45 
46  tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), pic->nb_param_buffers + 2);
47  if (!tmp)
48  return AVERROR(ENOMEM);
49  pic->param_buffers = tmp;
50 
51  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
52  VAEncPackedHeaderParameterBufferType,
53  sizeof(params), 1, &params, &param_buffer);
54  if (vas != VA_STATUS_SUCCESS) {
55  av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
56  "for packed header (type %d): %d (%s).\n",
57  type, vas, vaErrorStr(vas));
58  return AVERROR(EIO);
59  }
60  pic->param_buffers[pic->nb_param_buffers++] = param_buffer;
61 
62  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
63  VAEncPackedHeaderDataBufferType,
64  (bit_len + 7) / 8, 1, data, &data_buffer);
65  if (vas != VA_STATUS_SUCCESS) {
66  av_log(avctx, AV_LOG_ERROR, "Failed to create data buffer "
67  "for packed header (type %d): %d (%s).\n",
68  type, vas, vaErrorStr(vas));
69  return AVERROR(EIO);
70  }
71  pic->param_buffers[pic->nb_param_buffers++] = data_buffer;
72 
73  av_log(avctx, AV_LOG_DEBUG, "Packed header buffer (%d) is %#x/%#x "
74  "(%zu bits).\n", type, param_buffer, data_buffer, bit_len);
75  return 0;
76 }
77 
79  VAAPIEncodePicture *pic,
80  int type, char *data, size_t len)
81 {
83  VAStatus vas;
84  VABufferID *tmp;
85  VABufferID buffer;
86 
87  tmp = av_realloc_array(pic->param_buffers, sizeof(*tmp), pic->nb_param_buffers + 1);
88  if (!tmp)
89  return AVERROR(ENOMEM);
90  pic->param_buffers = tmp;
91 
92  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
93  type, len, 1, data, &buffer);
94  if (vas != VA_STATUS_SUCCESS) {
95  av_log(avctx, AV_LOG_ERROR, "Failed to create parameter buffer "
96  "(type %d): %d (%s).\n", type, vas, vaErrorStr(vas));
97  return AVERROR(EIO);
98  }
99  pic->param_buffers[pic->nb_param_buffers++] = buffer;
100 
101  av_log(avctx, AV_LOG_DEBUG, "Param buffer (%d) is %#x.\n",
102  type, buffer);
103  return 0;
104 }
105 
107  VAAPIEncodePicture *pic)
108 {
109  VAAPIEncodeContext *ctx = avctx->priv_data;
110  VAStatus vas;
111 
113 
114  if (pic->encode_complete) {
115  // Already waited for this picture.
116  return 0;
117  }
118 
119  av_log(avctx, AV_LOG_DEBUG, "Sync to pic %"PRId64"/%"PRId64" "
120  "(input surface %#x).\n", pic->display_order,
121  pic->encode_order, pic->input_surface);
122 
123  vas = vaSyncSurface(ctx->hwctx->display, pic->input_surface);
124  if (vas != VA_STATUS_SUCCESS) {
125  av_log(avctx, AV_LOG_ERROR, "Failed to sync to picture completion: "
126  "%d (%s).\n", vas, vaErrorStr(vas));
127  return AVERROR(EIO);
128  }
129 
130  // Input is definitely finished with now.
131  av_frame_free(&pic->input_image);
132 
133  pic->encode_complete = 1;
134  return 0;
135 }
136 
138  VAAPIEncodePicture *pic)
139 {
140  VAAPIEncodeContext *ctx = avctx->priv_data;
141  VAAPIEncodeSlice *slice;
142  VAStatus vas;
143  int err, i;
145  size_t bit_len;
146 
147  av_log(avctx, AV_LOG_DEBUG, "Issuing encode for pic %"PRId64"/%"PRId64" "
148  "as type %s.\n", pic->display_order, pic->encode_order,
149  picture_type_name[pic->type]);
150  if (pic->nb_refs == 0) {
151  av_log(avctx, AV_LOG_DEBUG, "No reference pictures.\n");
152  } else {
153  av_log(avctx, AV_LOG_DEBUG, "Refers to:");
154  for (i = 0; i < pic->nb_refs; i++) {
155  av_log(avctx, AV_LOG_DEBUG, " %"PRId64"/%"PRId64,
156  pic->refs[i]->display_order, pic->refs[i]->encode_order);
157  }
158  av_log(avctx, AV_LOG_DEBUG, ".\n");
159  }
160 
162  for (i = 0; i < pic->nb_refs; i++) {
163  av_assert0(pic->refs[i]);
164  // If we are serialised then the references must have already
165  // completed. If not, they must have been issued but need not
166  // have completed yet.
167  if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)
168  av_assert0(pic->refs[i]->encode_complete);
169  else
170  av_assert0(pic->refs[i]->encode_issued);
171  }
172 
173  av_log(avctx, AV_LOG_DEBUG, "Input surface is %#x.\n", pic->input_surface);
174 
175  pic->recon_image = av_frame_alloc();
176  if (!pic->recon_image) {
177  err = AVERROR(ENOMEM);
178  goto fail;
179  }
180 
182  if (err < 0) {
183  err = AVERROR(ENOMEM);
184  goto fail;
185  }
186  pic->recon_surface = (VASurfaceID)(uintptr_t)pic->recon_image->data[3];
187  av_log(avctx, AV_LOG_DEBUG, "Recon surface is %#x.\n", pic->recon_surface);
188 
190  if (!pic->output_buffer_ref) {
191  err = AVERROR(ENOMEM);
192  goto fail;
193  }
194  pic->output_buffer = (VABufferID)(uintptr_t)pic->output_buffer_ref->data;
195  av_log(avctx, AV_LOG_DEBUG, "Output buffer is %#x.\n",
196  pic->output_buffer);
197 
198  if (ctx->codec->picture_params_size > 0) {
200  if (!pic->codec_picture_params)
201  goto fail;
202  memcpy(pic->codec_picture_params, ctx->codec_picture_params,
203  ctx->codec->picture_params_size);
204  } else {
206  }
207 
208  pic->nb_param_buffers = 0;
209 
210  if (pic->type == PICTURE_TYPE_IDR && ctx->codec->init_sequence_params) {
211  err = vaapi_encode_make_param_buffer(avctx, pic,
212  VAEncSequenceParameterBufferType,
215  if (err < 0)
216  goto fail;
217  }
218 
219  if (pic->type == PICTURE_TYPE_IDR) {
220  for (i = 0; i < ctx->nb_global_params; i++) {
221  err = vaapi_encode_make_param_buffer(avctx, pic,
222  VAEncMiscParameterBufferType,
223  (char*)ctx->global_params[i],
224  ctx->global_params_size[i]);
225  if (err < 0)
226  goto fail;
227  }
228  }
229 
230  if (ctx->codec->init_picture_params) {
231  err = ctx->codec->init_picture_params(avctx, pic);
232  if (err < 0) {
233  av_log(avctx, AV_LOG_ERROR, "Failed to initialise picture "
234  "parameters: %d.\n", err);
235  goto fail;
236  }
237  err = vaapi_encode_make_param_buffer(avctx, pic,
238  VAEncPictureParameterBufferType,
240  ctx->codec->picture_params_size);
241  if (err < 0)
242  goto fail;
243  }
244 
245  if (pic->type == PICTURE_TYPE_IDR) {
246  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
248  bit_len = 8 * sizeof(data);
249  err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
250  if (err < 0) {
251  av_log(avctx, AV_LOG_ERROR, "Failed to write per-sequence "
252  "header: %d.\n", err);
253  goto fail;
254  }
255  err = vaapi_encode_make_packed_header(avctx, pic,
257  data, bit_len);
258  if (err < 0)
259  goto fail;
260  }
261  }
262 
263  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_PICTURE &&
264  ctx->codec->write_picture_header) {
265  bit_len = 8 * sizeof(data);
266  err = ctx->codec->write_picture_header(avctx, pic, data, &bit_len);
267  if (err < 0) {
268  av_log(avctx, AV_LOG_ERROR, "Failed to write per-picture "
269  "header: %d.\n", err);
270  goto fail;
271  }
272  err = vaapi_encode_make_packed_header(avctx, pic,
274  data, bit_len);
275  if (err < 0)
276  goto fail;
277  }
278 
279  if (ctx->codec->write_extra_buffer) {
280  for (i = 0;; i++) {
281  size_t len = sizeof(data);
282  int type;
283  err = ctx->codec->write_extra_buffer(avctx, pic, i, &type,
284  data, &len);
285  if (err == AVERROR_EOF)
286  break;
287  if (err < 0) {
288  av_log(avctx, AV_LOG_ERROR, "Failed to write extra "
289  "buffer %d: %d.\n", i, err);
290  goto fail;
291  }
292 
293  err = vaapi_encode_make_param_buffer(avctx, pic, type,
294  data, len);
295  if (err < 0)
296  goto fail;
297  }
298  }
299 
300  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_MISC &&
301  ctx->codec->write_extra_header) {
302  for (i = 0;; i++) {
303  int type;
304  bit_len = 8 * sizeof(data);
305  err = ctx->codec->write_extra_header(avctx, pic, i, &type,
306  data, &bit_len);
307  if (err == AVERROR_EOF)
308  break;
309  if (err < 0) {
310  av_log(avctx, AV_LOG_ERROR, "Failed to write extra "
311  "header %d: %d.\n", i, err);
312  goto fail;
313  }
314 
315  err = vaapi_encode_make_packed_header(avctx, pic, type,
316  data, bit_len);
317  if (err < 0)
318  goto fail;
319  }
320  }
321 
322  if (pic->nb_slices > 0) {
323  pic->slices = av_mallocz_array(pic->nb_slices, sizeof(*pic->slices));
324  if (!pic->slices) {
325  err = AVERROR(ENOMEM);
326  goto fail;
327  }
328  }
329  for (i = 0; i < pic->nb_slices; i++) {
330  slice = &pic->slices[i];
331  slice->index = i;
332 
333  if (ctx->codec->slice_params_size > 0) {
335  if (!slice->codec_slice_params) {
336  err = AVERROR(ENOMEM);
337  goto fail;
338  }
339  }
340 
341  if (ctx->codec->init_slice_params) {
342  err = ctx->codec->init_slice_params(avctx, pic, slice);
343  if (err < 0) {
344  av_log(avctx, AV_LOG_ERROR, "Failed to initialise slice "
345  "parameters: %d.\n", err);
346  goto fail;
347  }
348  }
349 
350  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SLICE &&
351  ctx->codec->write_slice_header) {
352  bit_len = 8 * sizeof(data);
353  err = ctx->codec->write_slice_header(avctx, pic, slice,
354  data, &bit_len);
355  if (err < 0) {
356  av_log(avctx, AV_LOG_ERROR, "Failed to write per-slice "
357  "header: %d.\n", err);
358  goto fail;
359  }
360  err = vaapi_encode_make_packed_header(avctx, pic,
361  ctx->codec->slice_header_type,
362  data, bit_len);
363  if (err < 0)
364  goto fail;
365  }
366 
367  if (ctx->codec->init_slice_params) {
368  err = vaapi_encode_make_param_buffer(avctx, pic,
369  VAEncSliceParameterBufferType,
370  slice->codec_slice_params,
371  ctx->codec->slice_params_size);
372  if (err < 0)
373  goto fail;
374  }
375  }
376 
377  vas = vaBeginPicture(ctx->hwctx->display, ctx->va_context,
378  pic->input_surface);
379  if (vas != VA_STATUS_SUCCESS) {
380  av_log(avctx, AV_LOG_ERROR, "Failed to begin picture encode issue: "
381  "%d (%s).\n", vas, vaErrorStr(vas));
382  err = AVERROR(EIO);
383  goto fail_with_picture;
384  }
385 
386  vas = vaRenderPicture(ctx->hwctx->display, ctx->va_context,
387  pic->param_buffers, pic->nb_param_buffers);
388  if (vas != VA_STATUS_SUCCESS) {
389  av_log(avctx, AV_LOG_ERROR, "Failed to upload encode parameters: "
390  "%d (%s).\n", vas, vaErrorStr(vas));
391  err = AVERROR(EIO);
392  goto fail_with_picture;
393  }
394 
395  vas = vaEndPicture(ctx->hwctx->display, ctx->va_context);
396  if (vas != VA_STATUS_SUCCESS) {
397  av_log(avctx, AV_LOG_ERROR, "Failed to end picture encode issue: "
398  "%d (%s).\n", vas, vaErrorStr(vas));
399  err = AVERROR(EIO);
400  // vaRenderPicture() has been called here, so we should not destroy
401  // the parameter buffers unless separate destruction is required.
402  if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
404  goto fail;
405  else
406  goto fail_at_end;
407  }
408 
409  if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
411  for (i = 0; i < pic->nb_param_buffers; i++) {
412  vas = vaDestroyBuffer(ctx->hwctx->display,
413  pic->param_buffers[i]);
414  if (vas != VA_STATUS_SUCCESS) {
415  av_log(avctx, AV_LOG_ERROR, "Failed to destroy "
416  "param buffer %#x: %d (%s).\n",
417  pic->param_buffers[i], vas, vaErrorStr(vas));
418  // And ignore.
419  }
420  }
421  }
422 
423  pic->encode_issued = 1;
424 
425  if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING)
426  return vaapi_encode_wait(avctx, pic);
427  else
428  return 0;
429 
430 fail_with_picture:
431  vaEndPicture(ctx->hwctx->display, ctx->va_context);
432 fail:
433  for(i = 0; i < pic->nb_param_buffers; i++)
434  vaDestroyBuffer(ctx->hwctx->display, pic->param_buffers[i]);
435  for (i = 0; i < pic->nb_slices; i++) {
436  if (pic->slices) {
437  av_freep(&pic->slices[i].priv_data);
439  }
440  }
441 fail_at_end:
443  av_freep(&pic->param_buffers);
444  av_freep(&pic->slices);
445  av_frame_free(&pic->recon_image);
447  pic->output_buffer = VA_INVALID_ID;
448  return err;
449 }
450 
453 {
454  VAAPIEncodeContext *ctx = avctx->priv_data;
455  VACodedBufferSegment *buf_list, *buf;
456  VAStatus vas;
457  int err;
458 
459  err = vaapi_encode_wait(avctx, pic);
460  if (err < 0)
461  return err;
462 
463  buf_list = NULL;
464  vas = vaMapBuffer(ctx->hwctx->display, pic->output_buffer,
465  (void**)&buf_list);
466  if (vas != VA_STATUS_SUCCESS) {
467  av_log(avctx, AV_LOG_ERROR, "Failed to map output buffers: "
468  "%d (%s).\n", vas, vaErrorStr(vas));
469  err = AVERROR(EIO);
470  goto fail;
471  }
472 
473  for (buf = buf_list; buf; buf = buf->next) {
474  av_log(avctx, AV_LOG_DEBUG, "Output buffer: %u bytes "
475  "(status %08x).\n", buf->size, buf->status);
476 
477  err = av_new_packet(pkt, buf->size);
478  if (err < 0)
479  goto fail_mapped;
480 
481  memcpy(pkt->data, buf->buf, buf->size);
482  }
483 
484  if (pic->type == PICTURE_TYPE_IDR)
485  pkt->flags |= AV_PKT_FLAG_KEY;
486 
487  pkt->pts = pic->pts;
488 
489  vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
490  if (vas != VA_STATUS_SUCCESS) {
491  av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
492  "%d (%s).\n", vas, vaErrorStr(vas));
493  err = AVERROR(EIO);
494  goto fail;
495  }
496 
498  pic->output_buffer = VA_INVALID_ID;
499 
500  av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
501  pic->display_order, pic->encode_order);
502  return 0;
503 
504 fail_mapped:
505  vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
506 fail:
508  pic->output_buffer = VA_INVALID_ID;
509  return err;
510 }
511 
513  VAAPIEncodePicture *pic)
514 {
515  vaapi_encode_wait(avctx, pic);
516 
517  if (pic->output_buffer_ref) {
518  av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
519  "%"PRId64"/%"PRId64".\n",
520  pic->display_order, pic->encode_order);
521 
523  pic->output_buffer = VA_INVALID_ID;
524  }
525 
526  return 0;
527 }
528 
530 {
531  VAAPIEncodePicture *pic;
532 
533  pic = av_mallocz(sizeof(*pic));
534  if (!pic)
535  return NULL;
536 
537  pic->input_surface = VA_INVALID_ID;
538  pic->recon_surface = VA_INVALID_ID;
539  pic->output_buffer = VA_INVALID_ID;
540 
541  return pic;
542 }
543 
545  VAAPIEncodePicture *pic)
546 {
547  int i;
548 
549  if (pic->encode_issued)
550  vaapi_encode_discard(avctx, pic);
551 
552  for (i = 0; i < pic->nb_slices; i++) {
553  if (pic->slices) {
554  av_freep(&pic->slices[i].priv_data);
556  }
557  }
559 
560  av_frame_free(&pic->input_image);
561  av_frame_free(&pic->recon_image);
562 
563  av_freep(&pic->param_buffers);
564  av_freep(&pic->slices);
565  // Output buffer should already be destroyed.
566  av_assert0(pic->output_buffer == VA_INVALID_ID);
567 
568  av_freep(&pic->priv_data);
570 
571  av_free(pic);
572 
573  return 0;
574 }
575 
577  VAAPIEncodePicture *target)
578 {
579  VAAPIEncodeContext *ctx = avctx->priv_data;
580  VAAPIEncodePicture *pic;
581  int i, err;
582 
583  if (ctx->issue_mode == ISSUE_MODE_SERIALISE_EVERYTHING ||
584  ctx->issue_mode == ISSUE_MODE_MINIMISE_LATENCY) {
585  // These two modes are equivalent, except that we wait for
586  // immediate completion on each operation if serialised.
587 
588  if (!target) {
589  // No target, nothing to do yet.
590  return 0;
591  }
592 
593  if (target->encode_complete) {
594  // Already done.
595  return 0;
596  }
597 
598  pic = target;
599  for (i = 0; i < pic->nb_refs; i++) {
600  if (!pic->refs[i]->encode_complete) {
601  err = vaapi_encode_step(avctx, pic->refs[i]);
602  if (err < 0)
603  return err;
604  }
605  }
606 
607  err = vaapi_encode_issue(avctx, pic);
608  if (err < 0)
609  return err;
610 
611  } else if (ctx->issue_mode == ISSUE_MODE_MAXIMISE_THROUGHPUT) {
612  int activity;
613 
614  // Run through the list of all available pictures repeatedly
615  // and issue the first one found which has all dependencies
616  // available (including previously-issued but not necessarily
617  // completed pictures).
618  do {
619  activity = 0;
620  for (pic = ctx->pic_start; pic; pic = pic->next) {
621  if (!pic->input_available || pic->encode_issued)
622  continue;
623  for (i = 0; i < pic->nb_refs; i++) {
624  if (!pic->refs[i]->encode_issued)
625  break;
626  }
627  if (i < pic->nb_refs)
628  continue;
629  err = vaapi_encode_issue(avctx, pic);
630  if (err < 0)
631  return err;
632  activity = 1;
633  // Start again from the beginning of the list,
634  // because issuing this picture may have satisfied
635  // forward dependencies of earlier ones.
636  break;
637  }
638  } while(activity);
639 
640  // If we had a defined target for this step then it will
641  // always have been issued by now.
642  if (target) {
643  av_assert0(target->encode_issued && "broken dependencies?");
644  }
645 
646  } else {
647  av_assert0(0);
648  }
649 
650  return 0;
651 }
652 
654  VAAPIEncodePicture **pic_out)
655 {
656  VAAPIEncodeContext *ctx = avctx->priv_data;
657  VAAPIEncodePicture *start, *end, *pic;
658  int i;
659 
660  for (pic = ctx->pic_start; pic; pic = pic->next) {
661  if (pic->next)
662  av_assert0(pic->display_order + 1 == pic->next->display_order);
663  if (pic->display_order == ctx->input_order) {
664  *pic_out = pic;
665  return 0;
666  }
667  }
668 
669  pic = vaapi_encode_alloc();
670  if (!pic)
671  return AVERROR(ENOMEM);
672 
673  if (ctx->input_order == 0 || ctx->force_idr ||
674  ctx->gop_counter >= ctx->gop_size) {
675  pic->type = PICTURE_TYPE_IDR;
676  ctx->force_idr = 0;
677  ctx->gop_counter = 1;
678  ctx->p_counter = 0;
679  } else if (ctx->p_counter >= ctx->p_per_i) {
680  pic->type = PICTURE_TYPE_I;
681  ++ctx->gop_counter;
682  ctx->p_counter = 0;
683  } else {
684  pic->type = PICTURE_TYPE_P;
685  pic->refs[0] = ctx->pic_end;
686  pic->nb_refs = 1;
687  ++ctx->gop_counter;
688  ++ctx->p_counter;
689  }
690  start = end = pic;
691 
692  if (pic->type != PICTURE_TYPE_IDR) {
693  // If that was not an IDR frame, add B-frames display-before and
694  // encode-after it, but not exceeding the GOP size.
695 
696  for (i = 0; i < ctx->b_per_p &&
697  ctx->gop_counter < ctx->gop_size; i++) {
698  pic = vaapi_encode_alloc();
699  if (!pic)
700  goto fail;
701 
702  pic->type = PICTURE_TYPE_B;
703  pic->refs[0] = ctx->pic_end;
704  pic->refs[1] = end;
705  pic->nb_refs = 2;
706 
707  pic->next = start;
708  pic->display_order = ctx->input_order + ctx->b_per_p - i - 1;
709  pic->encode_order = pic->display_order + 1;
710  start = pic;
711 
712  ++ctx->gop_counter;
713  }
714  }
715 
716  if (ctx->input_order == 0) {
717  pic->display_order = 0;
718  pic->encode_order = 0;
719 
720  ctx->pic_start = ctx->pic_end = pic;
721 
722  } else {
723  for (i = 0, pic = start; pic; i++, pic = pic->next) {
724  pic->display_order = ctx->input_order + i;
725  if (end->type == PICTURE_TYPE_IDR)
726  pic->encode_order = ctx->input_order + i;
727  else if (pic == end)
728  pic->encode_order = ctx->input_order;
729  else
730  pic->encode_order = ctx->input_order + i + 1;
731  }
732 
733  av_assert0(ctx->pic_end);
734  ctx->pic_end->next = start;
735  ctx->pic_end = end;
736  }
737  *pic_out = start;
738 
739  av_log(avctx, AV_LOG_DEBUG, "Pictures:");
740  for (pic = ctx->pic_start; pic; pic = pic->next) {
741  av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")",
742  picture_type_name[pic->type],
743  pic->display_order, pic->encode_order);
744  }
745  av_log(avctx, AV_LOG_DEBUG, "\n");
746 
747  return 0;
748 
749 fail:
750  while (start) {
751  pic = start->next;
752  vaapi_encode_free(avctx, start);
753  start = pic;
754  }
755  return AVERROR(ENOMEM);
756 }
757 
759 {
760  VAAPIEncodeContext *ctx = avctx->priv_data;
761  VAAPIEncodePicture *pic, *last_pic, *next;
762 
764 
765  // Find the last picture we actually have input for.
766  for (pic = ctx->pic_start; pic; pic = pic->next) {
767  if (!pic->input_available)
768  break;
769  last_pic = pic;
770  }
771 
772  if (pic) {
773  if (last_pic->type == PICTURE_TYPE_B) {
774  // Some fixing up is required. Change the type of this
775  // picture to P, then modify preceding B references which
776  // point beyond it to point at it instead.
777 
778  last_pic->type = PICTURE_TYPE_P;
779  last_pic->encode_order = last_pic->refs[1]->encode_order;
780 
781  for (pic = ctx->pic_start; pic != last_pic; pic = pic->next) {
782  if (pic->type == PICTURE_TYPE_B &&
783  pic->refs[1] == last_pic->refs[1])
784  pic->refs[1] = last_pic;
785  }
786 
787  last_pic->nb_refs = 1;
788  last_pic->refs[1] = NULL;
789  } else {
790  // We can use the current structure (no references point
791  // beyond the end), but there are unused pics to discard.
792  }
793 
794  // Discard all following pics, they will never be used.
795  for (pic = last_pic->next; pic; pic = next) {
796  next = pic->next;
797  vaapi_encode_free(avctx, pic);
798  }
799 
800  last_pic->next = NULL;
801  ctx->pic_end = last_pic;
802 
803  } else {
804  // Input is available for all pictures, so we don't need to
805  // mangle anything.
806  }
807 
808  av_log(avctx, AV_LOG_DEBUG, "Pictures ending truncated GOP:");
809  for (pic = ctx->pic_start; pic; pic = pic->next) {
810  av_log(avctx, AV_LOG_DEBUG, " %s (%"PRId64"/%"PRId64")",
811  picture_type_name[pic->type],
812  pic->display_order, pic->encode_order);
813  }
814  av_log(avctx, AV_LOG_DEBUG, "\n");
815 
816  return 0;
817 }
818 
820 {
821  VAAPIEncodeContext *ctx = avctx->priv_data;
822  VAAPIEncodePicture *pic, *old;
823  int i;
824 
825  while (ctx->pic_start != ctx->pic_end) {
826  old = ctx->pic_start;
827  if (old->encode_order > ctx->output_order)
828  break;
829 
830  for (pic = old->next; pic; pic = pic->next) {
831  if (pic->encode_complete)
832  continue;
833  for (i = 0; i < pic->nb_refs; i++) {
834  if (pic->refs[i] == old) {
835  // We still need this picture because it's referred to
836  // directly by a later one, so it and all following
837  // pictures have to stay.
838  return 0;
839  }
840  }
841  }
842 
843  pic = ctx->pic_start;
844  ctx->pic_start = pic->next;
845  vaapi_encode_free(avctx, pic);
846  }
847 
848  return 0;
849 }
850 
852  const AVFrame *input_image, int *got_packet)
853 {
854  VAAPIEncodeContext *ctx = avctx->priv_data;
855  VAAPIEncodePicture *pic;
856  int err;
857 
858  if (input_image) {
859  av_log(avctx, AV_LOG_DEBUG, "Encode frame: %ux%u (%"PRId64").\n",
860  input_image->width, input_image->height, input_image->pts);
861 
862  if (input_image->pict_type == AV_PICTURE_TYPE_I) {
863  err = vaapi_encode_truncate_gop(avctx);
864  if (err < 0)
865  goto fail;
866  ctx->force_idr = 1;
867  }
868 
869  err = vaapi_encode_get_next(avctx, &pic);
870  if (err) {
871  av_log(avctx, AV_LOG_ERROR, "Input setup failed: %d.\n", err);
872  return err;
873  }
874 
875  pic->input_image = av_frame_alloc();
876  if (!pic->input_image) {
877  err = AVERROR(ENOMEM);
878  goto fail;
879  }
880  err = av_frame_ref(pic->input_image, input_image);
881  if (err < 0)
882  goto fail;
883  pic->input_surface = (VASurfaceID)(uintptr_t)input_image->data[3];
884  pic->pts = input_image->pts;
885 
886  if (ctx->input_order == 0)
887  ctx->first_pts = pic->pts;
888  if (ctx->input_order == ctx->decode_delay)
889  ctx->dts_pts_diff = pic->pts - ctx->first_pts;
890  if (ctx->output_delay > 0)
891  ctx->ts_ring[ctx->input_order % (3 * ctx->output_delay)] = pic->pts;
892 
893  pic->input_available = 1;
894 
895  } else {
896  if (!ctx->end_of_stream) {
897  err = vaapi_encode_truncate_gop(avctx);
898  if (err < 0)
899  goto fail;
900  ctx->end_of_stream = 1;
901  }
902  }
903 
904  ++ctx->input_order;
905  ++ctx->output_order;
906  av_assert0(ctx->output_order + ctx->output_delay + 1 == ctx->input_order);
907 
908  for (pic = ctx->pic_start; pic; pic = pic->next)
909  if (pic->encode_order == ctx->output_order)
910  break;
911 
912  // pic can be null here if we don't have a specific target in this
913  // iteration. We might still issue encodes if things can be overlapped,
914  // even though we don't intend to output anything.
915 
916  err = vaapi_encode_step(avctx, pic);
917  if (err < 0) {
918  av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
919  goto fail;
920  }
921 
922  if (!pic) {
923  *got_packet = 0;
924  } else {
925  err = vaapi_encode_output(avctx, pic, pkt);
926  if (err < 0) {
927  av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
928  goto fail;
929  }
930 
931  if (ctx->output_delay == 0) {
932  pkt->dts = pkt->pts;
933  } else if (ctx->output_order < ctx->decode_delay) {
934  if (ctx->ts_ring[ctx->output_order] < INT64_MIN + ctx->dts_pts_diff)
935  pkt->dts = INT64_MIN;
936  else
937  pkt->dts = ctx->ts_ring[ctx->output_order] - ctx->dts_pts_diff;
938  } else {
939  pkt->dts = ctx->ts_ring[(ctx->output_order - ctx->decode_delay) %
940  (3 * ctx->output_delay)];
941  }
942 
943  *got_packet = 1;
944  }
945 
946  err = vaapi_encode_clear_old(avctx);
947  if (err < 0) {
948  av_log(avctx, AV_LOG_ERROR, "List clearing failed: %d.\n", err);
949  goto fail;
950  }
951 
952  return 0;
953 
954 fail:
955  // Unclear what to clean up on failure. There are probably some things we
956  // could do usefully clean up here, but for now just leave them for uninit()
957  // to do instead.
958  return err;
959 }
960 
962  VAEncMiscParameterBuffer *buffer,
963  size_t size)
964 {
965  VAAPIEncodeContext *ctx = avctx->priv_data;
966 
968 
969  ctx->global_params [ctx->nb_global_params] = buffer;
971 
972  ++ctx->nb_global_params;
973 }
974 
975 typedef struct VAAPIEncodeRTFormat {
976  const char *name;
977  unsigned int value;
978  int depth;
983 
985  { "YUV400", VA_RT_FORMAT_YUV400, 8, 1, },
986  { "YUV420", VA_RT_FORMAT_YUV420, 8, 3, 1, 1 },
987  { "YUV422", VA_RT_FORMAT_YUV422, 8, 3, 1, 0 },
988  { "YUV444", VA_RT_FORMAT_YUV444, 8, 3, 0, 0 },
989  { "YUV411", VA_RT_FORMAT_YUV411, 8, 3, 2, 0 },
990 #if VA_CHECK_VERSION(0, 38, 1)
991  { "YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
992 #endif
993 };
994 
995 static const VAEntrypoint vaapi_encode_entrypoints_normal[] = {
996  VAEntrypointEncSlice,
997  VAEntrypointEncPicture,
998 #if VA_CHECK_VERSION(0, 39, 2)
999  VAEntrypointEncSliceLP,
1000 #endif
1001  0
1002 };
1003 #if VA_CHECK_VERSION(0, 39, 2)
1004 static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
1005  VAEntrypointEncSliceLP,
1006  0
1007 };
1008 #endif
1009 
1011 {
1012  VAAPIEncodeContext *ctx = avctx->priv_data;
1013  VAProfile *va_profiles = NULL;
1014  VAEntrypoint *va_entrypoints = NULL;
1015  VAStatus vas;
1016  const VAEntrypoint *usable_entrypoints;
1017  const VAAPIEncodeProfile *profile;
1018  const AVPixFmtDescriptor *desc;
1019  VAConfigAttrib rt_format_attr;
1020  const VAAPIEncodeRTFormat *rt_format;
1021  const char *profile_string, *entrypoint_string;
1022  int i, j, n, depth, err;
1023 
1024 
1025  if (ctx->low_power) {
1026 #if VA_CHECK_VERSION(0, 39, 2)
1027  usable_entrypoints = vaapi_encode_entrypoints_low_power;
1028 #else
1029  av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
1030  "supported with this VAAPI version.\n");
1031  return AVERROR(EINVAL);
1032 #endif
1033  } else {
1034  usable_entrypoints = vaapi_encode_entrypoints_normal;
1035  }
1036 
1038  if (!desc) {
1039  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
1040  ctx->input_frames->sw_format);
1041  return AVERROR(EINVAL);
1042  }
1043  depth = desc->comp[0].depth;
1044  for (i = 1; i < desc->nb_components; i++) {
1045  if (desc->comp[i].depth != depth) {
1046  av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
1047  desc->name);
1048  return AVERROR(EINVAL);
1049  }
1050  }
1051  av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
1052  desc->name);
1053 
1054  n = vaMaxNumProfiles(ctx->hwctx->display);
1055  va_profiles = av_malloc_array(n, sizeof(VAProfile));
1056  if (!va_profiles) {
1057  err = AVERROR(ENOMEM);
1058  goto fail;
1059  }
1060  vas = vaQueryConfigProfiles(ctx->hwctx->display, va_profiles, &n);
1061  if (vas != VA_STATUS_SUCCESS) {
1062  av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n",
1063  vas, vaErrorStr(vas));
1064  err = AVERROR_EXTERNAL;
1065  goto fail;
1066  }
1067 
1068  av_assert0(ctx->codec->profiles);
1069  for (i = 0; (ctx->codec->profiles[i].av_profile !=
1070  FF_PROFILE_UNKNOWN); i++) {
1071  profile = &ctx->codec->profiles[i];
1072  if (depth != profile->depth ||
1073  desc->nb_components != profile->nb_components)
1074  continue;
1075  if (desc->nb_components > 1 &&
1076  (desc->log2_chroma_w != profile->log2_chroma_w ||
1077  desc->log2_chroma_h != profile->log2_chroma_h))
1078  continue;
1079  if (avctx->profile != profile->av_profile &&
1080  avctx->profile != FF_PROFILE_UNKNOWN)
1081  continue;
1082 
1083 #if VA_CHECK_VERSION(1, 0, 0)
1084  profile_string = vaProfileStr(profile->va_profile);
1085 #else
1086  profile_string = "(no profile names)";
1087 #endif
1088 
1089  for (j = 0; j < n; j++) {
1090  if (va_profiles[j] == profile->va_profile)
1091  break;
1092  }
1093  if (j >= n) {
1094  av_log(avctx, AV_LOG_VERBOSE, "Matching profile %d is "
1095  "not supported by driver.\n", profile->va_profile);
1096  continue;
1097  }
1098 
1099  ctx->profile = profile;
1100  break;
1101  }
1102  if (!ctx->profile) {
1103  av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n");
1104  err = AVERROR(ENOSYS);
1105  goto fail;
1106  }
1107 
1108  avctx->profile = profile->av_profile;
1109  ctx->va_profile = profile->va_profile;
1110  av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI profile %s (%d).\n",
1111  profile_string, ctx->va_profile);
1112 
1113  n = vaMaxNumEntrypoints(ctx->hwctx->display);
1114  va_entrypoints = av_malloc_array(n, sizeof(VAEntrypoint));
1115  if (!va_entrypoints) {
1116  err = AVERROR(ENOMEM);
1117  goto fail;
1118  }
1119  vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile,
1120  va_entrypoints, &n);
1121  if (vas != VA_STATUS_SUCCESS) {
1122  av_log(avctx, AV_LOG_ERROR, "Failed to query entrypoints for "
1123  "profile %s (%d): %d (%s).\n", profile_string,
1124  ctx->va_profile, vas, vaErrorStr(vas));
1125  err = AVERROR_EXTERNAL;
1126  goto fail;
1127  }
1128 
1129  for (i = 0; i < n; i++) {
1130  for (j = 0; usable_entrypoints[j]; j++) {
1131  if (va_entrypoints[i] == usable_entrypoints[j])
1132  break;
1133  }
1134  if (usable_entrypoints[j])
1135  break;
1136  }
1137  if (i >= n) {
1138  av_log(avctx, AV_LOG_ERROR, "No usable encoding entrypoint found "
1139  "for profile %s (%d).\n", profile_string, ctx->va_profile);
1140  err = AVERROR(ENOSYS);
1141  goto fail;
1142  }
1143 
1144  ctx->va_entrypoint = va_entrypoints[i];
1145 #if VA_CHECK_VERSION(1, 0, 0)
1146  entrypoint_string = vaEntrypointStr(ctx->va_entrypoint);
1147 #else
1148  entrypoint_string = "(no entrypoint names)";
1149 #endif
1150  av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI entrypoint %s (%d).\n",
1151  entrypoint_string, ctx->va_entrypoint);
1152 
1153  for (i = 0; i < FF_ARRAY_ELEMS(vaapi_encode_rt_formats); i++) {
1154  rt_format = &vaapi_encode_rt_formats[i];
1155  if (rt_format->depth == depth &&
1156  rt_format->nb_components == profile->nb_components &&
1157  rt_format->log2_chroma_w == profile->log2_chroma_w &&
1158  rt_format->log2_chroma_h == profile->log2_chroma_h)
1159  break;
1160  }
1161  if (i >= FF_ARRAY_ELEMS(vaapi_encode_rt_formats)) {
1162  av_log(avctx, AV_LOG_ERROR, "No usable render target format "
1163  "found for profile %s (%d) entrypoint %s (%d).\n",
1164  profile_string, ctx->va_profile,
1165  entrypoint_string, ctx->va_entrypoint);
1166  err = AVERROR(ENOSYS);
1167  goto fail;
1168  }
1169 
1170  rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
1171  vas = vaGetConfigAttributes(ctx->hwctx->display,
1172  ctx->va_profile, ctx->va_entrypoint,
1173  &rt_format_attr, 1);
1174  if (vas != VA_STATUS_SUCCESS) {
1175  av_log(avctx, AV_LOG_ERROR, "Failed to query RT format "
1176  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1177  err = AVERROR_EXTERNAL;
1178  goto fail;
1179  }
1180 
1181  if (rt_format_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1182  av_log(avctx, AV_LOG_VERBOSE, "RT format config attribute not "
1183  "supported by driver: assuming surface RT format %s "
1184  "is valid.\n", rt_format->name);
1185  } else if (!(rt_format_attr.value & rt_format->value)) {
1186  av_log(avctx, AV_LOG_ERROR, "Surface RT format %s not supported "
1187  "by driver for encoding profile %s (%d) entrypoint %s (%d).\n",
1188  rt_format->name, profile_string, ctx->va_profile,
1189  entrypoint_string, ctx->va_entrypoint);
1190  err = AVERROR(ENOSYS);
1191  goto fail;
1192  } else {
1193  av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI render target "
1194  "format %s (%#x).\n", rt_format->name, rt_format->value);
1196  (VAConfigAttrib) {
1197  .type = VAConfigAttribRTFormat,
1198  .value = rt_format->value,
1199  };
1200  }
1201 
1202  err = 0;
1203 fail:
1204  av_freep(&va_profiles);
1205  av_freep(&va_entrypoints);
1206  return err;
1207 }
1208 
1210 {
1211  VAAPIEncodeContext *ctx = avctx->priv_data;
1212  int64_t rc_bits_per_second;
1213  int rc_target_percentage;
1214  int rc_window_size;
1215  int64_t hrd_buffer_size;
1216  int64_t hrd_initial_buffer_fullness;
1217  int fr_num, fr_den;
1218  VAConfigAttrib rc_attr = { VAConfigAttribRateControl };
1219  VAStatus vas;
1220 
1221  vas = vaGetConfigAttributes(ctx->hwctx->display,
1222  ctx->va_profile, ctx->va_entrypoint,
1223  &rc_attr, 1);
1224  if (vas != VA_STATUS_SUCCESS) {
1225  av_log(avctx, AV_LOG_ERROR, "Failed to query rate control "
1226  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1227  return AVERROR_EXTERNAL;
1228  }
1229 
1230  if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1231  av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any "
1232  "supported rate control modes: assuming constant-quality.\n");
1233  ctx->va_rc_mode = VA_RC_CQP;
1234  return 0;
1235  }
1236  if (avctx->flags & AV_CODEC_FLAG_QSCALE ||
1237  avctx->bit_rate <= 0) {
1238  if (rc_attr.value & VA_RC_CQP) {
1239  av_log(avctx, AV_LOG_VERBOSE, "Using constant-quality mode.\n");
1240  ctx->va_rc_mode = VA_RC_CQP;
1241  if (avctx->bit_rate > 0 || avctx->rc_max_rate > 0) {
1242  av_log(avctx, AV_LOG_WARNING, "Bitrate target parameters "
1243  "ignored in constant-quality mode.\n");
1244  }
1245  return 0;
1246  } else {
1247  av_log(avctx, AV_LOG_ERROR, "Driver does not support "
1248  "constant-quality mode (%#x).\n", rc_attr.value);
1249  return AVERROR(EINVAL);
1250  }
1251  }
1252 
1253  if (!(rc_attr.value & (VA_RC_CBR | VA_RC_VBR))) {
1254  av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
1255  "bitrate-targetted rate control modes.\n");
1256  return AVERROR(EINVAL);
1257  }
1258 
1259  if (avctx->rc_buffer_size)
1260  hrd_buffer_size = avctx->rc_buffer_size;
1261  else if (avctx->rc_max_rate > 0)
1262  hrd_buffer_size = avctx->rc_max_rate;
1263  else
1264  hrd_buffer_size = avctx->bit_rate;
1265  if (avctx->rc_initial_buffer_occupancy) {
1266  if (avctx->rc_initial_buffer_occupancy > hrd_buffer_size) {
1267  av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
1268  "must have initial buffer size (%d) < "
1269  "buffer size (%"PRId64").\n",
1270  avctx->rc_initial_buffer_occupancy, hrd_buffer_size);
1271  return AVERROR(EINVAL);
1272  }
1273  hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
1274  } else {
1275  hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1276  }
1277 
1278  if (avctx->rc_max_rate && avctx->rc_max_rate < avctx->bit_rate) {
1279  av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: must have "
1280  "bitrate (%"PRId64") <= maxrate (%"PRId64").\n",
1281  avctx->bit_rate, avctx->rc_max_rate);
1282  return AVERROR(EINVAL);
1283  }
1284 
1285  if (avctx->rc_max_rate > avctx->bit_rate) {
1286  if (!(rc_attr.value & VA_RC_VBR)) {
1287  av_log(avctx, AV_LOG_WARNING, "Driver does not support "
1288  "VBR mode (%#x), using CBR mode instead.\n",
1289  rc_attr.value);
1290  ctx->va_rc_mode = VA_RC_CBR;
1291 
1292  rc_bits_per_second = avctx->bit_rate;
1293  rc_target_percentage = 100;
1294  } else {
1295  ctx->va_rc_mode = VA_RC_VBR;
1296 
1297  rc_bits_per_second = avctx->rc_max_rate;
1298  rc_target_percentage = (avctx->bit_rate * 100) /
1299  avctx->rc_max_rate;
1300  }
1301 
1302  } else if (avctx->rc_max_rate == avctx->bit_rate) {
1303  if (!(rc_attr.value & VA_RC_CBR)) {
1304  av_log(avctx, AV_LOG_WARNING, "Driver does not support "
1305  "CBR mode (%#x), using VBR mode instead.\n",
1306  rc_attr.value);
1307  ctx->va_rc_mode = VA_RC_VBR;
1308  } else {
1309  ctx->va_rc_mode = VA_RC_CBR;
1310  }
1311 
1312  rc_bits_per_second = avctx->bit_rate;
1313  rc_target_percentage = 100;
1314 
1315  } else {
1316  if (rc_attr.value & VA_RC_VBR) {
1317  ctx->va_rc_mode = VA_RC_VBR;
1318 
1319  // We only have a target bitrate, but VAAPI requires that a
1320  // maximum rate be supplied as well. Since the user has
1321  // offered no particular constraint, arbitrarily pick a
1322  // maximum rate of double the target rate.
1323  rc_bits_per_second = 2 * avctx->bit_rate;
1324  rc_target_percentage = 50;
1325  } else {
1326  ctx->va_rc_mode = VA_RC_CBR;
1327 
1328  rc_bits_per_second = avctx->bit_rate;
1329  rc_target_percentage = 100;
1330  }
1331  }
1332 
1333  rc_window_size = (hrd_buffer_size * 1000) / rc_bits_per_second;
1334 
1335  av_log(avctx, AV_LOG_VERBOSE, "RC mode: %s, %d%% of %"PRId64" bps "
1336  "over %d ms.\n", ctx->va_rc_mode == VA_RC_VBR ? "VBR" : "CBR",
1337  rc_target_percentage, rc_bits_per_second, rc_window_size);
1338  av_log(avctx, AV_LOG_VERBOSE, "RC buffer: %"PRId64" bits, "
1339  "initial fullness %"PRId64" bits.\n",
1340  hrd_buffer_size, hrd_initial_buffer_fullness);
1341 
1342  if (rc_bits_per_second > UINT32_MAX ||
1343  hrd_buffer_size > UINT32_MAX ||
1344  hrd_initial_buffer_fullness > UINT32_MAX) {
1345  av_log(avctx, AV_LOG_ERROR, "RC parameters of 2^32 or "
1346  "greater are not supported by VAAPI.\n");
1347  return AVERROR(EINVAL);
1348  }
1349 
1350  ctx->va_bit_rate = rc_bits_per_second;
1351 
1353  (VAConfigAttrib) {
1354  .type = VAConfigAttribRateControl,
1355  .value = ctx->va_rc_mode,
1356  };
1357 
1358  ctx->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
1359  ctx->rc_params.rc = (VAEncMiscParameterRateControl) {
1360  .bits_per_second = rc_bits_per_second,
1361  .target_percentage = rc_target_percentage,
1362  .window_size = rc_window_size,
1363  .initial_qp = 0,
1364  .min_qp = (avctx->qmin > 0 ? avctx->qmin : 0),
1365  .basic_unit_size = 0,
1366 #if VA_CHECK_VERSION(1, 1, 0)
1367  .max_qp = (avctx->qmax > 0 ? avctx->qmax : 0),
1368 #endif
1369  };
1371  sizeof(ctx->rc_params));
1372 
1373  ctx->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
1374  ctx->hrd_params.hrd = (VAEncMiscParameterHRD) {
1375  .initial_buffer_fullness = hrd_initial_buffer_fullness,
1376  .buffer_size = hrd_buffer_size,
1377  };
1379  sizeof(ctx->hrd_params));
1380 
1381  if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
1382  av_reduce(&fr_num, &fr_den,
1383  avctx->framerate.num, avctx->framerate.den, 65535);
1384  else
1385  av_reduce(&fr_num, &fr_den,
1386  avctx->time_base.den, avctx->time_base.num, 65535);
1387 
1388  ctx->fr_params.misc.type = VAEncMiscParameterTypeFrameRate;
1389  ctx->fr_params.fr.framerate = (unsigned int)fr_den << 16 | fr_num;
1390 
1391 #if VA_CHECK_VERSION(0, 40, 0)
1393  sizeof(ctx->fr_params));
1394 #endif
1395 
1396  return 0;
1397 }
1398 
1400 {
1401  VAAPIEncodeContext *ctx = avctx->priv_data;
1402  VAStatus vas;
1403  VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
1404  uint32_t ref_l0, ref_l1;
1405 
1406  vas = vaGetConfigAttributes(ctx->hwctx->display,
1407  ctx->va_profile,
1408  ctx->va_entrypoint,
1409  &attr, 1);
1410  if (vas != VA_STATUS_SUCCESS) {
1411  av_log(avctx, AV_LOG_ERROR, "Failed to query reference frames "
1412  "attribute: %d (%s).\n", vas, vaErrorStr(vas));
1413  return AVERROR_EXTERNAL;
1414  }
1415 
1416  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1417  ref_l0 = ref_l1 = 0;
1418  } else {
1419  ref_l0 = attr.value & 0xffff;
1420  ref_l1 = attr.value >> 16 & 0xffff;
1421  }
1422 
1423  if (avctx->gop_size <= 1) {
1424  av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n");
1425  ctx->gop_size = 1;
1426  } else if (ref_l0 < 1) {
1427  av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
1428  "reference frames.\n");
1429  return AVERROR(EINVAL);
1430  } else if (ref_l1 < 1 || avctx->max_b_frames < 1) {
1431  av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames "
1432  "(supported references: %d / %d).\n", ref_l0, ref_l1);
1433  ctx->gop_size = avctx->gop_size;
1434  ctx->p_per_i = INT_MAX;
1435  ctx->b_per_p = 0;
1436  } else {
1437  av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames "
1438  "(supported references: %d / %d).\n", ref_l0, ref_l1);
1439  ctx->gop_size = avctx->gop_size;
1440  ctx->p_per_i = INT_MAX;
1441  ctx->b_per_p = avctx->max_b_frames;
1442  }
1443 
1444  return 0;
1445 }
1446 
1448 {
1449  VAAPIEncodeContext *ctx = avctx->priv_data;
1450  VAStatus vas;
1451  VAConfigAttrib attr = { VAConfigAttribEncPackedHeaders };
1452 
1453  vas = vaGetConfigAttributes(ctx->hwctx->display,
1454  ctx->va_profile,
1455  ctx->va_entrypoint,
1456  &attr, 1);
1457  if (vas != VA_STATUS_SUCCESS) {
1458  av_log(avctx, AV_LOG_ERROR, "Failed to query packed headers "
1459  "attribute: %d (%s).\n", vas, vaErrorStr(vas));
1460  return AVERROR_EXTERNAL;
1461  }
1462 
1463  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1464  if (ctx->desired_packed_headers) {
1465  av_log(avctx, AV_LOG_WARNING, "Driver does not support any "
1466  "packed headers (wanted %#x).\n",
1467  ctx->desired_packed_headers);
1468  } else {
1469  av_log(avctx, AV_LOG_VERBOSE, "Driver does not support any "
1470  "packed headers (none wanted).\n");
1471  }
1472  ctx->va_packed_headers = 0;
1473  } else {
1474  if (ctx->desired_packed_headers & ~attr.value) {
1475  av_log(avctx, AV_LOG_WARNING, "Driver does not support some "
1476  "wanted packed headers (wanted %#x, found %#x).\n",
1477  ctx->desired_packed_headers, attr.value);
1478  } else {
1479  av_log(avctx, AV_LOG_VERBOSE, "All wanted packed headers "
1480  "available (wanted %#x, found %#x).\n",
1481  ctx->desired_packed_headers, attr.value);
1482  }
1483  ctx->va_packed_headers = ctx->desired_packed_headers & attr.value;
1484  }
1485 
1486  if (ctx->va_packed_headers) {
1488  (VAConfigAttrib) {
1489  .type = VAConfigAttribEncPackedHeaders,
1490  .value = ctx->va_packed_headers,
1491  };
1492  }
1493 
1494  if ( (ctx->desired_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
1495  !(ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
1496  (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
1497  av_log(avctx, AV_LOG_WARNING, "Driver does not support packed "
1498  "sequence headers, but a global header is requested.\n");
1499  av_log(avctx, AV_LOG_WARNING, "No global header will be written: "
1500  "this may result in a stream which is not usable for some "
1501  "purposes (e.g. not muxable to some containers).\n");
1502  }
1503 
1504  return 0;
1505 }
1506 
1508 {
1509 #if VA_CHECK_VERSION(0, 36, 0)
1510  VAAPIEncodeContext *ctx = avctx->priv_data;
1511  VAStatus vas;
1512  VAConfigAttrib attr = { VAConfigAttribEncQualityRange };
1513  int quality = avctx->compression_level;
1514 
1515  vas = vaGetConfigAttributes(ctx->hwctx->display,
1516  ctx->va_profile,
1517  ctx->va_entrypoint,
1518  &attr, 1);
1519  if (vas != VA_STATUS_SUCCESS) {
1520  av_log(avctx, AV_LOG_ERROR, "Failed to query quality "
1521  "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1522  return AVERROR_EXTERNAL;
1523  }
1524 
1525  if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1526  if (quality != 0) {
1527  av_log(avctx, AV_LOG_WARNING, "Quality attribute is not "
1528  "supported: will use default quality level.\n");
1529  }
1530  } else {
1531  if (quality > attr.value) {
1532  av_log(avctx, AV_LOG_WARNING, "Invalid quality level: "
1533  "valid range is 0-%d, using %d.\n",
1534  attr.value, attr.value);
1535  quality = attr.value;
1536  }
1537 
1538  ctx->quality_params.misc.type = VAEncMiscParameterTypeQualityLevel;
1539  ctx->quality_params.quality.quality_level = quality;
1540 
1541  vaapi_encode_add_global_param(avctx, &ctx->quality_params.misc,
1542  sizeof(ctx->quality_params));
1543  }
1544 #else
1545  av_log(avctx, AV_LOG_WARNING, "The encode quality option is "
1546  "not supported with this VAAPI version.\n");
1547 #endif
1548 
1549  return 0;
1550 }
1551 
1552 static void vaapi_encode_free_output_buffer(void *opaque,
1553  uint8_t *data)
1554 {
1555  AVCodecContext *avctx = opaque;
1556  VAAPIEncodeContext *ctx = avctx->priv_data;
1557  VABufferID buffer_id;
1558 
1559  buffer_id = (VABufferID)(uintptr_t)data;
1560 
1561  vaDestroyBuffer(ctx->hwctx->display, buffer_id);
1562 
1563  av_log(avctx, AV_LOG_DEBUG, "Freed output buffer %#x\n", buffer_id);
1564 }
1565 
1567  int size)
1568 {
1569  AVCodecContext *avctx = opaque;
1570  VAAPIEncodeContext *ctx = avctx->priv_data;
1571  VABufferID buffer_id;
1572  VAStatus vas;
1573  AVBufferRef *ref;
1574 
1575  // The output buffer size is fixed, so it needs to be large enough
1576  // to hold the largest possible compressed frame. We assume here
1577  // that the uncompressed frame plus some header data is an upper
1578  // bound on that.
1579  vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
1580  VAEncCodedBufferType,
1581  3 * ctx->surface_width * ctx->surface_height +
1582  (1 << 16), 1, 0, &buffer_id);
1583  if (vas != VA_STATUS_SUCCESS) {
1584  av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream "
1585  "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
1586  return NULL;
1587  }
1588 
1589  av_log(avctx, AV_LOG_DEBUG, "Allocated output buffer %#x\n", buffer_id);
1590 
1591  ref = av_buffer_create((uint8_t*)(uintptr_t)buffer_id,
1592  sizeof(buffer_id),
1594  avctx, AV_BUFFER_FLAG_READONLY);
1595  if (!ref) {
1596  vaDestroyBuffer(ctx->hwctx->display, buffer_id);
1597  return NULL;
1598  }
1599 
1600  return ref;
1601 }
1602 
1604 {
1605  VAAPIEncodeContext *ctx = avctx->priv_data;
1606  AVVAAPIHWConfig *hwconfig = NULL;
1607  AVHWFramesConstraints *constraints = NULL;
1608  enum AVPixelFormat recon_format;
1609  int err, i;
1610 
1611  hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
1612  if (!hwconfig) {
1613  err = AVERROR(ENOMEM);
1614  goto fail;
1615  }
1616  hwconfig->config_id = ctx->va_config;
1617 
1619  hwconfig);
1620  if (!constraints) {
1621  err = AVERROR(ENOMEM);
1622  goto fail;
1623  }
1624 
1625  // Probably we can use the input surface format as the surface format
1626  // of the reconstructed frames. If not, we just pick the first (only?)
1627  // format in the valid list and hope that it all works.
1628  recon_format = AV_PIX_FMT_NONE;
1629  if (constraints->valid_sw_formats) {
1630  for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
1631  if (ctx->input_frames->sw_format ==
1632  constraints->valid_sw_formats[i]) {
1633  recon_format = ctx->input_frames->sw_format;
1634  break;
1635  }
1636  }
1637  if (recon_format == AV_PIX_FMT_NONE) {
1638  // No match. Just use the first in the supported list and
1639  // hope for the best.
1640  recon_format = constraints->valid_sw_formats[0];
1641  }
1642  } else {
1643  // No idea what to use; copy input format.
1644  recon_format = ctx->input_frames->sw_format;
1645  }
1646  av_log(avctx, AV_LOG_DEBUG, "Using %s as format of "
1647  "reconstructed frames.\n", av_get_pix_fmt_name(recon_format));
1648 
1649  if (ctx->surface_width < constraints->min_width ||
1650  ctx->surface_height < constraints->min_height ||
1651  ctx->surface_width > constraints->max_width ||
1652  ctx->surface_height > constraints->max_height) {
1653  av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at "
1654  "size %dx%d (constraints: width %d-%d height %d-%d).\n",
1655  ctx->surface_width, ctx->surface_height,
1656  constraints->min_width, constraints->max_width,
1657  constraints->min_height, constraints->max_height);
1658  err = AVERROR(EINVAL);
1659  goto fail;
1660  }
1661 
1662  av_freep(&hwconfig);
1663  av_hwframe_constraints_free(&constraints);
1664 
1666  if (!ctx->recon_frames_ref) {
1667  err = AVERROR(ENOMEM);
1668  goto fail;
1669  }
1671 
1673  ctx->recon_frames->sw_format = recon_format;
1674  ctx->recon_frames->width = ctx->surface_width;
1675  ctx->recon_frames->height = ctx->surface_height;
1676  // At most three IDR/I/P frames and two runs of B frames can be in
1677  // flight at any one time.
1678  ctx->recon_frames->initial_pool_size = 3 + 2 * ctx->b_per_p;
1679 
1681  if (err < 0) {
1682  av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
1683  "frame context: %d.\n", err);
1684  goto fail;
1685  }
1686 
1687  err = 0;
1688  fail:
1689  av_freep(&hwconfig);
1690  av_hwframe_constraints_free(&constraints);
1691  return err;
1692 }
1693 
1695 {
1696  VAAPIEncodeContext *ctx = avctx->priv_data;
1697  AVVAAPIFramesContext *recon_hwctx = NULL;
1698  VAStatus vas;
1699  int err;
1700 
1701  if (!avctx->hw_frames_ctx) {
1702  av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
1703  "required to associate the encoding device.\n");
1704  return AVERROR(EINVAL);
1705  }
1706 
1707  ctx->va_config = VA_INVALID_ID;
1708  ctx->va_context = VA_INVALID_ID;
1709 
1711  if (!ctx->input_frames_ref) {
1712  err = AVERROR(ENOMEM);
1713  goto fail;
1714  }
1716 
1718  if (!ctx->device_ref) {
1719  err = AVERROR(ENOMEM);
1720  goto fail;
1721  }
1722  ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
1723  ctx->hwctx = ctx->device->hwctx;
1724 
1725  err = vaapi_encode_profile_entrypoint(avctx);
1726  if (err < 0)
1727  goto fail;
1728 
1729  err = vaapi_encode_init_rate_control(avctx);
1730  if (err < 0)
1731  goto fail;
1732 
1733  err = vaapi_encode_init_gop_structure(avctx);
1734  if (err < 0)
1735  goto fail;
1736 
1737  err = vaapi_encode_init_packed_headers(avctx);
1738  if (err < 0)
1739  goto fail;
1740 
1741  if (avctx->compression_level >= 0) {
1742  err = vaapi_encode_init_quality(avctx);
1743  if (err < 0)
1744  goto fail;
1745  }
1746 
1747  vas = vaCreateConfig(ctx->hwctx->display,
1748  ctx->va_profile, ctx->va_entrypoint,
1750  &ctx->va_config);
1751  if (vas != VA_STATUS_SUCCESS) {
1752  av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
1753  "configuration: %d (%s).\n", vas, vaErrorStr(vas));
1754  err = AVERROR(EIO);
1755  goto fail;
1756  }
1757 
1758  err = vaapi_encode_create_recon_frames(avctx);
1759  if (err < 0)
1760  goto fail;
1761 
1762  recon_hwctx = ctx->recon_frames->hwctx;
1763  vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
1764  ctx->surface_width, ctx->surface_height,
1765  VA_PROGRESSIVE,
1766  recon_hwctx->surface_ids,
1767  recon_hwctx->nb_surfaces,
1768  &ctx->va_context);
1769  if (vas != VA_STATUS_SUCCESS) {
1770  av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
1771  "context: %d (%s).\n", vas, vaErrorStr(vas));
1772  err = AVERROR(EIO);
1773  goto fail;
1774  }
1775 
1776  ctx->output_buffer_pool =
1777  av_buffer_pool_init2(sizeof(VABufferID), avctx,
1779  if (!ctx->output_buffer_pool) {
1780  err = AVERROR(ENOMEM);
1781  goto fail;
1782  }
1783 
1784  if (ctx->codec->configure) {
1785  err = ctx->codec->configure(avctx);
1786  if (err < 0)
1787  goto fail;
1788  }
1789 
1790  ctx->input_order = 0;
1791  ctx->output_delay = ctx->b_per_p;
1792  ctx->decode_delay = 1;
1793  ctx->output_order = - ctx->output_delay - 1;
1794 
1795  if (ctx->codec->sequence_params_size > 0) {
1796  ctx->codec_sequence_params =
1798  if (!ctx->codec_sequence_params) {
1799  err = AVERROR(ENOMEM);
1800  goto fail;
1801  }
1802  }
1803  if (ctx->codec->picture_params_size > 0) {
1804  ctx->codec_picture_params =
1806  if (!ctx->codec_picture_params) {
1807  err = AVERROR(ENOMEM);
1808  goto fail;
1809  }
1810  }
1811 
1812  if (ctx->codec->init_sequence_params) {
1813  err = ctx->codec->init_sequence_params(avctx);
1814  if (err < 0) {
1815  av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
1816  "failed: %d.\n", err);
1817  goto fail;
1818  }
1819  }
1820 
1821  // This should be configurable somehow. (Needs testing on a machine
1822  // where it actually overlaps properly, though.)
1823  ctx->issue_mode = ISSUE_MODE_MAXIMISE_THROUGHPUT;
1824 
1825  if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
1826  ctx->codec->write_sequence_header &&
1829  size_t bit_len = 8 * sizeof(data);
1830 
1831  err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
1832  if (err < 0) {
1833  av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
1834  "for extradata: %d.\n", err);
1835  goto fail;
1836  } else {
1837  avctx->extradata_size = (bit_len + 7) / 8;
1838  avctx->extradata = av_mallocz(avctx->extradata_size +
1840  if (!avctx->extradata) {
1841  err = AVERROR(ENOMEM);
1842  goto fail;
1843  }
1844  memcpy(avctx->extradata, data, avctx->extradata_size);
1845  }
1846  }
1847 
1848  return 0;
1849 
1850 fail:
1851  ff_vaapi_encode_close(avctx);
1852  return err;
1853 }
1854 
1856 {
1857  VAAPIEncodeContext *ctx = avctx->priv_data;
1858  VAAPIEncodePicture *pic, *next;
1859 
1860  for (pic = ctx->pic_start; pic; pic = next) {
1861  next = pic->next;
1862  vaapi_encode_free(avctx, pic);
1863  }
1864 
1866 
1867  if (ctx->va_context != VA_INVALID_ID) {
1868  vaDestroyContext(ctx->hwctx->display, ctx->va_context);
1869  ctx->va_context = VA_INVALID_ID;
1870  }
1871 
1872  if (ctx->va_config != VA_INVALID_ID) {
1873  vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
1874  ctx->va_config = VA_INVALID_ID;
1875  }
1876 
1879 
1882  av_buffer_unref(&ctx->device_ref);
1883 
1884  return 0;
1885 }
This struct aggregates all the (hardware/vendor-specific) "high-level" state, i.e.
Definition: hwcontext.h:60
#define NULL
Definition: coverity.c:32
AVRational framerate
Definition: avcodec.h:3055
VASurfaceID input_surface
Definition: vaapi_encode.h:72
VAProfile va_profile
Definition: vaapi_encode.h:135
VAEncMiscParameterBuffer misc
Definition: vaapi_encode.h:175
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it...
Definition: buffer.c:125
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
Definition: pixdesc.c:2406
VAAPI-specific data associated with a frame pool.
This structure describes decoded (raw) audio or video data.
Definition: frame.h:218
VAEntrypoint va_entrypoint
Definition: vaapi_encode.h:137
ptrdiff_t const GLvoid * data
Definition: opengl_enc.c:101
static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[]
Definition: vaapi_encode.c:984
#define AV_LOG_WARNING
Something somehow does not look correct.
Definition: log.h:182
int64_t bit_rate
the average bitrate
Definition: avcodec.h:1582
const char * desc
Definition: nvenc.c:65
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:1792
int rc_initial_buffer_occupancy
Number of bits which should be loaded into the rc buffer before decoding starts.
Definition: avcodec.h:2434
int num
Numerator.
Definition: rational.h:59
int size
Definition: avcodec.h:1445
struct VAAPIEncodeContext::@161 hrd_params
static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
int width
The allocated dimensions of the frames in this pool.
Definition: hwcontext.h:228
static int vaapi_encode_make_packed_header(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t bit_len)
Definition: vaapi_encode.c:32
static const char *const picture_type_name[]
Definition: vaapi_encode.c:30
void * av_hwdevice_hwconfig_alloc(AVBufferRef *ref)
Allocate a HW-specific configuration structure for a given HW device.
Definition: hwcontext.c:526
enum AVPixelFormat format
The pixel format identifying the underlying HW surface type.
Definition: hwcontext.h:208
int(* write_slice_header)(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodeSlice *slice, char *data, size_t *data_len)
Definition: vaapi_encode.h:275
void * av_mallocz(size_t size)
Allocate a memory block with alignment suitable for all memory accesses (including vectors if availab...
Definition: mem.c:236
void * codec_sequence_params
Definition: vaapi_encode.h:194
AVBufferRef * input_frames_ref
Definition: vaapi_encode.h:157
static AVPacket pkt
VAEncMiscParameterHRD hrd
Definition: vaapi_encode.h:180
size_t picture_params_size
Definition: vaapi_encode.h:250
AVHWDeviceContext * device
Definition: vaapi_encode.h:153
static int vaapi_encode_clear_old(AVCodecContext *avctx)
Definition: vaapi_encode.c:819
int profile
profile
Definition: avcodec.h:2858
uint8_t log2_chroma_w
Amount to shift the luma width right to find the chroma width.
Definition: pixdesc.h:92
static int vaapi_encode_wait(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:106
int max_width
The maximum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:457
static int vaapi_encode_discard(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:512
static int vaapi_encode_make_param_buffer(AVCodecContext *avctx, VAAPIEncodePicture *pic, int type, char *data, size_t len)
Definition: vaapi_encode.c:78
AVRational time_base
This is the fundamental unit of time (in seconds) in terms of which frame timestamps are represented...
Definition: avcodec.h:1655
void av_hwframe_constraints_free(AVHWFramesConstraints **constraints)
Free an AVHWFrameConstraints structure.
Definition: hwcontext.c:562
unsigned int va_packed_headers
Definition: vaapi_encode.h:143
#define av_assert0(cond)
assert() equivalent, that is always enabled.
Definition: avassert.h:37
VAEncMiscParameterFrameRate fr
Definition: vaapi_encode.h:184
static VAAPIEncodePicture * vaapi_encode_alloc(void)
Definition: vaapi_encode.c:529
AVComponentDescriptor comp[4]
Parameters that describe how pixels are packed.
Definition: pixdesc.h:117
uint8_t
#define av_cold
Definition: attributes.h:82
#define av_malloc(s)
AVFrame * av_frame_alloc(void)
Allocate an AVFrame and set its fields to default values.
Definition: frame.c:189
static int vaapi_encode_issue(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:137
static av_cold int end(AVCodecContext *avctx)
Definition: avrndec.c:90
int(* write_picture_header)(AVCodecContext *avctx, VAAPIEncodePicture *pic, char *data, size_t *data_len)
Definition: vaapi_encode.h:272
int av_frame_ref(AVFrame *dst, const AVFrame *src)
Set up a new reference to the data described by the source frame.
Definition: frame.c:441
static AVBufferRef * vaapi_encode_alloc_output_buffer(void *opaque, int size)
int64_t pts
Presentation timestamp in time_base units (time when frame should be shown to user).
Definition: frame.h:311
uint8_t * extradata
some codecs need / can use extradata like Huffman tables.
Definition: avcodec.h:1633
AVBufferRef * output_buffer_ref
Definition: vaapi_encode.h:80
void * hwctx
The format-specific data, allocated and freed by libavutil along with this context.
Definition: hwcontext.h:91
VABufferID * param_buffers
Definition: vaapi_encode.h:78
uint8_t * data
Definition: avcodec.h:1444
VAContextID va_context
Definition: vaapi_encode.h:150
#define AVERROR_EOF
End of file.
Definition: error.h:55
#define AV_LOG_VERBOSE
Detailed information.
Definition: log.h:192
VASurfaceID recon_surface
Definition: vaapi_encode.h:75
#define AV_BUFFER_FLAG_READONLY
Always treat the buffer as read-only, even when it has only one reference.
Definition: buffer.h:113
ptrdiff_t size
Definition: opengl_enc.c:101
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
void * av_realloc_array(void *ptr, size_t nmemb, size_t size)
Definition: mem.c:198
#define av_log(a,...)
const char * name
Definition: pixdesc.h:82
#define AV_PKT_FLAG_KEY
The packet contains a keyframe.
Definition: avcodec.h:1476
const char * name
Definition: vaapi_encode.c:976
int av_new_packet(AVPacket *pkt, int size)
Allocate the payload of a packet and initialize its fields with default values.
Definition: avpacket.c:86
unsigned int va_rc_mode
Definition: vaapi_encode.h:139
VAConfigAttrib config_attributes[MAX_CONFIG_ATTRIBUTES]
Definition: vaapi_encode.h:146
AVHWFramesContext * input_frames
Definition: vaapi_encode.h:158
int width
Definition: frame.h:276
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
Definition: log.h:176
VAAPI hardware pipeline configuration details.
uint8_t log2_chroma_h
Amount to shift the luma height right to find the chroma height.
Definition: pixdesc.h:101
#define AVERROR(e)
Definition: error.h:43
void av_frame_free(AVFrame **frame)
Free the frame and any dynamically allocated objects in it, e.g.
Definition: frame.c:202
static av_cold int vaapi_encode_init_packed_headers(AVCodecContext *avctx)
int qmax
maximum quantizer
Definition: avcodec.h:2377
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
Definition: log.h:197
VAEncMiscParameterBuffer * global_params[MAX_GLOBAL_PARAMS]
Definition: vaapi_encode.h:169
int(* configure)(AVCodecContext *avctx)
Definition: vaapi_encode.h:245
int flags
AV_CODEC_FLAG_*.
Definition: avcodec.h:1612
GLenum GLint * params
Definition: opengl_enc.c:114
simple assert() macros that are a bit more flexible than ISO C assert().
AVBufferRef * av_buffer_create(uint8_t *data, int size, void(*free)(void *opaque, uint8_t *data), void *opaque, int flags)
Create an AVBuffer from an existing array.
Definition: buffer.c:28
unsigned int va_bit_rate
Definition: vaapi_encode.h:141
int av_hwframe_ctx_init(AVBufferRef *ref)
Finalize the context before use.
Definition: hwcontext.c:329
int(* init_picture_params)(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.h:255
void * codec_picture_params
Definition: vaapi_encode.h:84
int av_hwframe_get_buffer(AVBufferRef *hwframe_ref, AVFrame *frame, int flags)
Allocate a new frame attached to the given AVHWFramesContext.
Definition: hwcontext.c:465
#define fail()
Definition: checkasm.h:117
int(* write_extra_header)(AVCodecContext *avctx, VAAPIEncodePicture *pic, int index, int *type, char *data, size_t *data_len)
Definition: vaapi_encode.h:292
VAConfigID va_config
Definition: vaapi_encode.h:149
AVHWFramesContext * recon_frames
Definition: vaapi_encode.h:162
int flags
A combination of AV_PKT_FLAG values.
Definition: avcodec.h:1450
int rc_buffer_size
decoder bitstream buffer size
Definition: avcodec.h:2391
static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
VAAPIEncodeSlice * slices
Definition: vaapi_encode.h:90
int initial_pool_size
Initial size of the frame pool.
Definition: hwcontext.h:198
uint8_t nb_components
The number of components each pixel has, (1-4)
Definition: pixdesc.h:83
enum AVPictureType pict_type
Picture type of the frame.
Definition: frame.h:301
#define AV_CODEC_FLAG_QSCALE
Use fixed qscale.
Definition: avcodec.h:841
unsigned int value
Definition: vaapi_encode.c:977
AVBufferRef * hw_frames_ctx
A reference to the AVHWFramesContext describing the input (for encoding) or output (decoding) frames...
Definition: avcodec.h:3212
const VAAPIEncodeProfile * profile
Definition: vaapi_encode.h:132
#define FF_PROFILE_UNKNOWN
Definition: avcodec.h:2859
const VAAPIEncodeProfile * profiles
Definition: vaapi_encode.h:240
av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
AVFormatContext * ctx
Definition: movenc.c:48
struct VAAPIEncodePicture * next
Definition: vaapi_encode.h:60
AVFrame * input_image
Definition: vaapi_encode.h:71
void * codec_picture_params
Definition: vaapi_encode.h:198
int n
Definition: avisynth_c.h:684
int64_t ts_ring[MAX_REORDER_DELAY *3]
Definition: vaapi_encode.h:225
AVBufferPool * output_buffer_pool
Definition: vaapi_encode.h:165
AVBufferPool * av_buffer_pool_init2(int size, void *opaque, AVBufferRef *(*alloc)(void *opaque, int size), void(*pool_free)(void *opaque))
Allocate and initialize a buffer pool with a more complex allocator.
Definition: buffer.c:218
#define FF_ARRAY_ELEMS(a)
VADisplay display
The VADisplay handle, to be filled by the user.
int(* write_sequence_header)(AVCodecContext *avctx, char *data, size_t *data_len)
Definition: vaapi_encode.h:270
struct VAAPIEncodePicture * refs[MAX_PICTURE_REFERENCES]
Definition: vaapi_encode.h:87
struct VAAPIEncodeContext::@160 rc_params
int min_width
The minimum size of frames in this hw_frames_ctx.
Definition: hwcontext.h:450
const struct VAAPIEncodeType * codec
Definition: vaapi_encode.h:112
Libavcodec external API header.
This struct describes the constraints on hardware frames attached to a given device with a hardware-s...
Definition: hwcontext.h:432
int compression_level
Definition: avcodec.h:1604
VAAPIEncodePicture * pic_start
Definition: vaapi_encode.h:201
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
Definition: pixdesc.h:81
main external API structure.
Definition: avcodec.h:1532
AVHWFramesConstraints * av_hwdevice_get_hwframe_constraints(AVBufferRef *ref, const void *hwconfig)
Get the constraints on HW frames given a device and the HW-specific configuration to be used with tha...
Definition: hwcontext.c:537
uint8_t * data
The data buffer.
Definition: buffer.h:89
int(* write_extra_buffer)(AVCodecContext *avctx, VAAPIEncodePicture *pic, int index, int *type, char *data, size_t *data_len)
Definition: vaapi_encode.h:284
int qmin
minimum quantizer
Definition: avcodec.h:2370
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
Definition: hwcontext.h:161
size_t slice_params_size
Definition: vaapi_encode.h:251
unsigned int driver_quirks
Driver quirks to apply - this is filled by av_hwdevice_ctx_init(), with reference to a table of known...
void * buf
Definition: avisynth_c.h:690
GLint GLenum type
Definition: opengl_enc.c:105
int extradata_size
Definition: avcodec.h:1634
void av_buffer_pool_uninit(AVBufferPool **ppool)
Mark the pool as being available for freeing.
Definition: buffer.c:275
This struct describes a set or pool of "hardware" frames (i.e.
Definition: hwcontext.h:123
static int vaapi_encode_step(AVCodecContext *avctx, VAAPIEncodePicture *target)
Definition: vaapi_encode.c:576
AVBufferRef * recon_frames_ref
Definition: vaapi_encode.h:161
static av_cold void vaapi_encode_add_global_param(AVCodecContext *avctx, VAEncMiscParameterBuffer *buffer, size_t size)
Definition: vaapi_encode.c:961
static int vaapi_encode_truncate_gop(AVCodecContext *avctx)
Definition: vaapi_encode.c:758
static av_cold int vaapi_encode_init_quality(AVCodecContext *avctx)
mfxU16 profile
Definition: qsvenc.c:44
AVBufferRef * device_ref
Definition: vaapi_encode.h:152
VAAPIEncodePicture * pic_end
Definition: vaapi_encode.h:201
struct VAAPIEncodeContext::@162 fr_params
uint8_t * data[AV_NUM_DATA_POINTERS]
pointer to the picture/channel planes.
Definition: frame.h:232
AVBufferRef * device_ref
A reference to the parent AVHWDeviceContext.
Definition: hwcontext.h:140
#define AV_CODEC_FLAG_GLOBAL_HEADER
Place global headers in extradata instead of every keyframe.
Definition: avcodec.h:890
size_t global_params_size[MAX_GLOBAL_PARAMS]
Definition: vaapi_encode.h:170
int gop_size
the number of pictures in a group of pictures, or 0 for intra_only
Definition: avcodec.h:1727
VAEncMiscParameterRateControl rc
Definition: vaapi_encode.h:176
A reference to a data buffer.
Definition: buffer.h:81
size_t sequence_params_size
Definition: vaapi_encode.h:249
VAProfile va_profile
Definition: vaapi_encode.h:105
int
common internal and external API header
static int ref[MAX_W *MAX_W]
Definition: jpeg2000dwt.c:107
AVBufferRef * av_hwframe_ctx_alloc(AVBufferRef *device_ref_in)
Allocate an AVHWFramesContext tied to a given device context.
Definition: hwcontext.c:243
static int vaapi_encode_get_next(AVCodecContext *avctx, VAAPIEncodePicture **pic_out)
Definition: vaapi_encode.c:653
AVBufferRef * av_buffer_ref(AVBufferRef *buf)
Create a new reference to an AVBuffer.
Definition: buffer.c:93
int ff_vaapi_encode2(AVCodecContext *avctx, AVPacket *pkt, const AVFrame *input_image, int *got_packet)
Definition: vaapi_encode.c:851
int den
Denominator.
Definition: rational.h:60
#define AV_INPUT_BUFFER_PADDING_SIZE
Required number of additionally allocated bytes at the end of the input bitstream for decoding...
Definition: avcodec.h:781
void * priv_data
Definition: avcodec.h:1559
The driver does not destroy parameter buffers when they are used by vaRenderPicture().
static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx)
#define av_free(p)
static const VAEntrypoint vaapi_encode_entrypoints_normal[]
Definition: vaapi_encode.c:995
int len
enum AVPixelFormat * valid_sw_formats
A list of possible values for sw_format in the hw_frames_ctx, terminated by AV_PIX_FMT_NONE.
Definition: hwcontext.h:444
void * codec_slice_params
Definition: vaapi_encode.h:56
AVFrame * recon_image
Definition: vaapi_encode.h:74
static int vaapi_encode_free(AVCodecContext *avctx, VAAPIEncodePicture *pic)
Definition: vaapi_encode.c:544
int(* init_slice_params)(AVCodecContext *avctx, VAAPIEncodePicture *pic, VAAPIEncodeSlice *slice)
Definition: vaapi_encode.h:257
VAConfigID config_id
ID of a VAAPI pipeline configuration.
int(* init_sequence_params)(AVCodecContext *avctx)
Definition: vaapi_encode.h:254
static void vaapi_encode_free_output_buffer(void *opaque, uint8_t *data)
int64_t dts
Decompression timestamp in AVStream->time_base units; the time at which the packet is decompressed...
Definition: avcodec.h:1443
unsigned int desired_packed_headers
Definition: vaapi_encode.h:120
int height
Definition: frame.h:276
#define av_freep(p)
VASurfaceID * surface_ids
The surfaces IDs of all surfaces in the pool after creation.
void INT64 start
Definition: avisynth_c.h:690
AVBufferRef * av_buffer_pool_get(AVBufferPool *pool)
Allocate a new AVBuffer, reusing an old buffer from the pool when available.
Definition: buffer.c:334
#define av_malloc_array(a, b)
static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)
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:2322
int depth
Number of bits in the component.
Definition: pixdesc.h:58
VABufferID output_buffer
Definition: vaapi_encode.h:81
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
Definition: hwcontext.h:221
#define AVERROR_EXTERNAL
Generic error in an external library.
Definition: error.h:57
AVPixelFormat
Pixel format.
Definition: pixfmt.h:64
This structure stores compressed data.
Definition: avcodec.h:1421
int64_t pts
Presentation timestamp in AVStream->time_base units; the time at which the decompressed packet will b...
Definition: avcodec.h:1437
av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
enum VAAPIEncodeContext::@163 issue_mode
GLuint buffer
Definition: opengl_enc.c:102
int64_t rc_max_rate
maximum bitrate
Definition: avcodec.h:2406
void * av_mallocz_array(size_t nmemb, size_t size)
Definition: mem.c:191
static int vaapi_encode_output(AVCodecContext *avctx, VAAPIEncodePicture *pic, AVPacket *pkt)
Definition: vaapi_encode.c:451
AVVAAPIDeviceContext * hwctx
Definition: vaapi_encode.h:154
static uint8_t tmp[11]
Definition: aes_ctr.c:26