• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
34 const AVCodecHWConfigInternal *const ff_vaapi_encode_hw_configs[] = {
35     HW_CONFIG_ENCODER_FRAMES(VAAPI, VAAPI),
36     NULL,
37 };
38 
39 static const char * const picture_type_name[] = { "IDR", "I", "P", "B" };
40 
vaapi_encode_make_packed_header(AVCodecContext * avctx,VAAPIEncodePicture * pic,int type,char * data,size_t bit_len)41 static int vaapi_encode_make_packed_header(AVCodecContext *avctx,
42                                            VAAPIEncodePicture *pic,
43                                            int type, char *data, size_t bit_len)
44 {
45     VAAPIEncodeContext *ctx = avctx->priv_data;
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 
vaapi_encode_make_param_buffer(AVCodecContext * avctx,VAAPIEncodePicture * pic,int type,char * data,size_t len)87 static int vaapi_encode_make_param_buffer(AVCodecContext *avctx,
88                                           VAAPIEncodePicture *pic,
89                                           int type, char *data, size_t len)
90 {
91     VAAPIEncodeContext *ctx = avctx->priv_data;
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 
vaapi_encode_make_misc_param_buffer(AVCodecContext * avctx,VAAPIEncodePicture * pic,int type,const void * data,size_t len)115 static int vaapi_encode_make_misc_param_buffer(AVCodecContext *avctx,
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 
vaapi_encode_wait(AVCodecContext * avctx,VAAPIEncodePicture * pic)138 static int vaapi_encode_wait(AVCodecContext *avctx,
139                              VAAPIEncodePicture *pic)
140 {
141     VAAPIEncodeContext *ctx = avctx->priv_data;
142     VAStatus vas;
143 
144     av_assert0(pic->encode_issued);
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 
vaapi_encode_make_row_slice(AVCodecContext * avctx,VAAPIEncodePicture * pic)183 static int vaapi_encode_make_row_slice(AVCodecContext *avctx,
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 
vaapi_encode_make_tile_slice(AVCodecContext * avctx,VAAPIEncodePicture * pic)238 static int vaapi_encode_make_tile_slice(AVCodecContext *avctx,
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 
vaapi_encode_issue(AVCodecContext * avctx,VAAPIEncodePicture * pic)265 static int vaapi_encode_issue(AVCodecContext *avctx,
266                               VAAPIEncodePicture *pic)
267 {
268     VAAPIEncodeContext *ctx = avctx->priv_data;
269     VAAPIEncodeSlice *slice;
270     VAStatus vas;
271     int err, i;
272     char data[MAX_PARAM_BUFFER_SIZE];
273     size_t bit_len;
274     av_unused AVFrameSideData *sd;
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,
362                                              pic->codec_picture_params,
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)
519     sd = av_frame_get_side_data(pic->input_image,
520                                 AV_FRAME_DATA_REGIONS_OF_INTEREST);
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 &
609             AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS)
610             goto fail;
611         else
612             goto fail_at_end;
613     }
614 
615     if (CONFIG_VAAPI_1 || ctx->hwctx->driver_quirks &
616         AV_VAAPI_DRIVER_QUIRK_RENDER_PARAM_BUFFERS) {
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++)
640             av_freep(&pic->slices[i].codec_slice_params);
641     }
642 fail_at_end:
643     av_freep(&pic->codec_picture_params);
644     av_freep(&pic->param_buffers);
645     av_freep(&pic->slices);
646     av_freep(&pic->roi);
647     av_frame_free(&pic->recon_image);
648     av_buffer_unref(&pic->output_buffer_ref);
649     pic->output_buffer = VA_INVALID_ID;
650     return err;
651 }
652 
vaapi_encode_output(AVCodecContext * avctx,VAAPIEncodePicture * pic,AVPacket * pkt)653 static int vaapi_encode_output(AVCodecContext *avctx,
654                                VAAPIEncodePicture *pic, AVPacket *pkt)
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)
695         pkt->flags |= AV_PKT_FLAG_KEY;
696 
697     pkt->pts = pic->pts;
698 
699     vas = vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
700     if (vas != VA_STATUS_SUCCESS) {
701         av_log(avctx, AV_LOG_ERROR, "Failed to unmap output buffers: "
702                "%d (%s).\n", vas, vaErrorStr(vas));
703         err = AVERROR(EIO);
704         goto fail;
705     }
706 
707     av_buffer_unref(&pic->output_buffer_ref);
708     pic->output_buffer = VA_INVALID_ID;
709 
710     av_log(avctx, AV_LOG_DEBUG, "Output read for pic %"PRId64"/%"PRId64".\n",
711            pic->display_order, pic->encode_order);
712     return 0;
713 
714 fail_mapped:
715     vaUnmapBuffer(ctx->hwctx->display, pic->output_buffer);
716 fail:
717     av_buffer_unref(&pic->output_buffer_ref);
718     pic->output_buffer = VA_INVALID_ID;
719     return err;
720 }
721 
vaapi_encode_discard(AVCodecContext * avctx,VAAPIEncodePicture * pic)722 static int vaapi_encode_discard(AVCodecContext *avctx,
723                                 VAAPIEncodePicture *pic)
724 {
725     vaapi_encode_wait(avctx, pic);
726 
727     if (pic->output_buffer_ref) {
728         av_log(avctx, AV_LOG_DEBUG, "Discard output for pic "
729                "%"PRId64"/%"PRId64".\n",
730                pic->display_order, pic->encode_order);
731 
732         av_buffer_unref(&pic->output_buffer_ref);
733         pic->output_buffer = VA_INVALID_ID;
734     }
735 
736     return 0;
737 }
738 
vaapi_encode_alloc(AVCodecContext * avctx)739 static VAAPIEncodePicture *vaapi_encode_alloc(AVCodecContext *avctx)
740 {
741     VAAPIEncodeContext *ctx = avctx->priv_data;
742     VAAPIEncodePicture *pic;
743 
744     pic = av_mallocz(sizeof(*pic));
745     if (!pic)
746         return NULL;
747 
748     if (ctx->codec->picture_priv_data_size > 0) {
749         pic->priv_data = av_mallocz(ctx->codec->picture_priv_data_size);
750         if (!pic->priv_data) {
751             av_freep(&pic);
752             return NULL;
753         }
754     }
755 
756     pic->input_surface = VA_INVALID_ID;
757     pic->recon_surface = VA_INVALID_ID;
758     pic->output_buffer = VA_INVALID_ID;
759 
760     return pic;
761 }
762 
vaapi_encode_free(AVCodecContext * avctx,VAAPIEncodePicture * pic)763 static int vaapi_encode_free(AVCodecContext *avctx,
764                              VAAPIEncodePicture *pic)
765 {
766     int i;
767 
768     if (pic->encode_issued)
769         vaapi_encode_discard(avctx, pic);
770 
771     if (pic->slices) {
772         for (i = 0; i < pic->nb_slices; i++)
773             av_freep(&pic->slices[i].codec_slice_params);
774     }
775     av_freep(&pic->codec_picture_params);
776 
777     av_frame_free(&pic->input_image);
778     av_frame_free(&pic->recon_image);
779 
780     av_freep(&pic->param_buffers);
781     av_freep(&pic->slices);
782     // Output buffer should already be destroyed.
783     av_assert0(pic->output_buffer == VA_INVALID_ID);
784 
785     av_freep(&pic->priv_data);
786     av_freep(&pic->codec_picture_params);
787     av_freep(&pic->roi);
788 
789     av_free(pic);
790 
791     return 0;
792 }
793 
vaapi_encode_add_ref(AVCodecContext * avctx,VAAPIEncodePicture * pic,VAAPIEncodePicture * target,int is_ref,int in_dpb,int prev)794 static void vaapi_encode_add_ref(AVCodecContext *avctx,
795                                  VAAPIEncodePicture *pic,
796                                  VAAPIEncodePicture *target,
797                                  int is_ref, int in_dpb, int prev)
798 {
799     int refs = 0;
800 
801     if (is_ref) {
802         av_assert0(pic != target);
803         av_assert0(pic->nb_refs < MAX_PICTURE_REFERENCES);
804         pic->refs[pic->nb_refs++] = target;
805         ++refs;
806     }
807 
808     if (in_dpb) {
809         av_assert0(pic->nb_dpb_pics < MAX_DPB_SIZE);
810         pic->dpb[pic->nb_dpb_pics++] = target;
811         ++refs;
812     }
813 
814     if (prev) {
815         av_assert0(!pic->prev);
816         pic->prev = target;
817         ++refs;
818     }
819 
820     target->ref_count[0] += refs;
821     target->ref_count[1] += refs;
822 }
823 
vaapi_encode_remove_refs(AVCodecContext * avctx,VAAPIEncodePicture * pic,int level)824 static void vaapi_encode_remove_refs(AVCodecContext *avctx,
825                                      VAAPIEncodePicture *pic,
826                                      int level)
827 {
828     int i;
829 
830     if (pic->ref_removed[level])
831         return;
832 
833     for (i = 0; i < pic->nb_refs; i++) {
834         av_assert0(pic->refs[i]);
835         --pic->refs[i]->ref_count[level];
836         av_assert0(pic->refs[i]->ref_count[level] >= 0);
837     }
838 
839     for (i = 0; i < pic->nb_dpb_pics; i++) {
840         av_assert0(pic->dpb[i]);
841         --pic->dpb[i]->ref_count[level];
842         av_assert0(pic->dpb[i]->ref_count[level] >= 0);
843     }
844 
845     av_assert0(pic->prev || pic->type == PICTURE_TYPE_IDR);
846     if (pic->prev) {
847         --pic->prev->ref_count[level];
848         av_assert0(pic->prev->ref_count[level] >= 0);
849     }
850 
851     pic->ref_removed[level] = 1;
852 }
853 
vaapi_encode_set_b_pictures(AVCodecContext * avctx,VAAPIEncodePicture * start,VAAPIEncodePicture * end,VAAPIEncodePicture * prev,int current_depth,VAAPIEncodePicture ** last)854 static void vaapi_encode_set_b_pictures(AVCodecContext *avctx,
855                                         VAAPIEncodePicture *start,
856                                         VAAPIEncodePicture *end,
857                                         VAAPIEncodePicture *prev,
858                                         int current_depth,
859                                         VAAPIEncodePicture **last)
860 {
861     VAAPIEncodeContext *ctx = avctx->priv_data;
862     VAAPIEncodePicture *pic, *next, *ref;
863     int i, len;
864 
865     av_assert0(start && end && start != end && start->next != end);
866 
867     // If we are at the maximum depth then encode all pictures as
868     // non-referenced B-pictures.  Also do this if there is exactly one
869     // picture left, since there will be nothing to reference it.
870     if (current_depth == ctx->max_b_depth || start->next->next == end) {
871         for (pic = start->next; pic; pic = pic->next) {
872             if (pic == end)
873                 break;
874             pic->type    = PICTURE_TYPE_B;
875             pic->b_depth = current_depth;
876 
877             vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0);
878             vaapi_encode_add_ref(avctx, pic, end,   1, 1, 0);
879             vaapi_encode_add_ref(avctx, pic, prev,  0, 0, 1);
880 
881             for (ref = end->refs[1]; ref; ref = ref->refs[1])
882                 vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0);
883         }
884         *last = prev;
885 
886     } else {
887         // Split the current list at the midpoint with a referenced
888         // B-picture, then descend into each side separately.
889         len = 0;
890         for (pic = start->next; pic != end; pic = pic->next)
891             ++len;
892         for (pic = start->next, i = 1; 2 * i < len; pic = pic->next, i++);
893 
894         pic->type    = PICTURE_TYPE_B;
895         pic->b_depth = current_depth;
896 
897         pic->is_reference = 1;
898 
899         vaapi_encode_add_ref(avctx, pic, pic,   0, 1, 0);
900         vaapi_encode_add_ref(avctx, pic, start, 1, 1, 0);
901         vaapi_encode_add_ref(avctx, pic, end,   1, 1, 0);
902         vaapi_encode_add_ref(avctx, pic, prev,  0, 0, 1);
903 
904         for (ref = end->refs[1]; ref; ref = ref->refs[1])
905             vaapi_encode_add_ref(avctx, pic, ref, 0, 1, 0);
906 
907         if (i > 1)
908             vaapi_encode_set_b_pictures(avctx, start, pic, pic,
909                                         current_depth + 1, &next);
910         else
911             next = pic;
912 
913         vaapi_encode_set_b_pictures(avctx, pic, end, next,
914                                     current_depth + 1, last);
915     }
916 }
917 
vaapi_encode_pick_next(AVCodecContext * avctx,VAAPIEncodePicture ** pic_out)918 static int vaapi_encode_pick_next(AVCodecContext *avctx,
919                                   VAAPIEncodePicture **pic_out)
920 {
921     VAAPIEncodeContext *ctx = avctx->priv_data;
922     VAAPIEncodePicture *pic = NULL, *next, *start;
923     int i, b_counter, closed_gop_end;
924 
925     // If there are any B-frames already queued, the next one to encode
926     // is the earliest not-yet-issued frame for which all references are
927     // available.
928     for (pic = ctx->pic_start; pic; pic = pic->next) {
929         if (pic->encode_issued)
930             continue;
931         if (pic->type != PICTURE_TYPE_B)
932             continue;
933         for (i = 0; i < pic->nb_refs; i++) {
934             if (!pic->refs[i]->encode_issued)
935                 break;
936         }
937         if (i == pic->nb_refs)
938             break;
939     }
940 
941     if (pic) {
942         av_log(avctx, AV_LOG_DEBUG, "Pick B-picture at depth %d to "
943                "encode next.\n", pic->b_depth);
944         *pic_out = pic;
945         return 0;
946     }
947 
948     // Find the B-per-Pth available picture to become the next picture
949     // on the top layer.
950     start = NULL;
951     b_counter = 0;
952     closed_gop_end = ctx->closed_gop ||
953                      ctx->idr_counter == ctx->gop_per_idr;
954     for (pic = ctx->pic_start; pic; pic = next) {
955         next = pic->next;
956         if (pic->encode_issued) {
957             start = pic;
958             continue;
959         }
960         // If the next available picture is force-IDR, encode it to start
961         // a new GOP immediately.
962         if (pic->force_idr)
963             break;
964         if (b_counter == ctx->b_per_p)
965             break;
966         // If this picture ends a closed GOP or starts a new GOP then it
967         // needs to be in the top layer.
968         if (ctx->gop_counter + b_counter + closed_gop_end >= ctx->gop_size)
969             break;
970         // If the picture after this one is force-IDR, we need to encode
971         // this one in the top layer.
972         if (next && next->force_idr)
973             break;
974         ++b_counter;
975     }
976 
977     // At the end of the stream the last picture must be in the top layer.
978     if (!pic && ctx->end_of_stream) {
979         --b_counter;
980         pic = ctx->pic_end;
981         if (pic->encode_complete)
982             return AVERROR_EOF;
983         else if (pic->encode_issued)
984             return AVERROR(EAGAIN);
985     }
986 
987     if (!pic) {
988         av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
989                "need more input for reference pictures.\n");
990         return AVERROR(EAGAIN);
991     }
992     if (ctx->input_order <= ctx->decode_delay && !ctx->end_of_stream) {
993         av_log(avctx, AV_LOG_DEBUG, "Pick nothing to encode next - "
994                "need more input for timestamps.\n");
995         return AVERROR(EAGAIN);
996     }
997 
998     if (pic->force_idr) {
999         av_log(avctx, AV_LOG_DEBUG, "Pick forced IDR-picture to "
1000                "encode next.\n");
1001         pic->type = PICTURE_TYPE_IDR;
1002         ctx->idr_counter = 1;
1003         ctx->gop_counter = 1;
1004 
1005     } else if (ctx->gop_counter + b_counter >= ctx->gop_size) {
1006         if (ctx->idr_counter == ctx->gop_per_idr) {
1007             av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP IDR-picture to "
1008                    "encode next.\n");
1009             pic->type = PICTURE_TYPE_IDR;
1010             ctx->idr_counter = 1;
1011         } else {
1012             av_log(avctx, AV_LOG_DEBUG, "Pick new-GOP I-picture to "
1013                    "encode next.\n");
1014             pic->type = PICTURE_TYPE_I;
1015             ++ctx->idr_counter;
1016         }
1017         ctx->gop_counter = 1;
1018 
1019     } else {
1020         if (ctx->gop_counter + b_counter + closed_gop_end == ctx->gop_size) {
1021             av_log(avctx, AV_LOG_DEBUG, "Pick group-end P-picture to "
1022                    "encode next.\n");
1023         } else {
1024             av_log(avctx, AV_LOG_DEBUG, "Pick normal P-picture to "
1025                    "encode next.\n");
1026         }
1027         pic->type = PICTURE_TYPE_P;
1028         av_assert0(start);
1029         ctx->gop_counter += 1 + b_counter;
1030     }
1031     pic->is_reference = 1;
1032     *pic_out = pic;
1033 
1034     vaapi_encode_add_ref(avctx, pic, pic, 0, 1, 0);
1035     if (pic->type != PICTURE_TYPE_IDR) {
1036         vaapi_encode_add_ref(avctx, pic, start,
1037                              pic->type == PICTURE_TYPE_P,
1038                              b_counter > 0, 0);
1039         vaapi_encode_add_ref(avctx, pic, ctx->next_prev, 0, 0, 1);
1040     }
1041     if (ctx->next_prev)
1042         --ctx->next_prev->ref_count[0];
1043 
1044     if (b_counter > 0) {
1045         vaapi_encode_set_b_pictures(avctx, start, pic, pic, 1,
1046                                     &ctx->next_prev);
1047     } else {
1048         ctx->next_prev = pic;
1049     }
1050     ++ctx->next_prev->ref_count[0];
1051     return 0;
1052 }
1053 
vaapi_encode_clear_old(AVCodecContext * avctx)1054 static int vaapi_encode_clear_old(AVCodecContext *avctx)
1055 {
1056     VAAPIEncodeContext *ctx = avctx->priv_data;
1057     VAAPIEncodePicture *pic, *prev, *next;
1058 
1059     av_assert0(ctx->pic_start);
1060 
1061     // Remove direct references once each picture is complete.
1062     for (pic = ctx->pic_start; pic; pic = pic->next) {
1063         if (pic->encode_complete && pic->next)
1064             vaapi_encode_remove_refs(avctx, pic, 0);
1065     }
1066 
1067     // Remove indirect references once a picture has no direct references.
1068     for (pic = ctx->pic_start; pic; pic = pic->next) {
1069         if (pic->encode_complete && pic->ref_count[0] == 0)
1070             vaapi_encode_remove_refs(avctx, pic, 1);
1071     }
1072 
1073     // Clear out all complete pictures with no remaining references.
1074     prev = NULL;
1075     for (pic = ctx->pic_start; pic; pic = next) {
1076         next = pic->next;
1077         if (pic->encode_complete && pic->ref_count[1] == 0) {
1078             av_assert0(pic->ref_removed[0] && pic->ref_removed[1]);
1079             if (prev)
1080                 prev->next = next;
1081             else
1082                 ctx->pic_start = next;
1083             vaapi_encode_free(avctx, pic);
1084         } else {
1085             prev = pic;
1086         }
1087     }
1088 
1089     return 0;
1090 }
1091 
vaapi_encode_check_frame(AVCodecContext * avctx,const AVFrame * frame)1092 static int vaapi_encode_check_frame(AVCodecContext *avctx,
1093                                     const AVFrame *frame)
1094 {
1095     VAAPIEncodeContext *ctx = avctx->priv_data;
1096 
1097     if ((frame->crop_top  || frame->crop_bottom ||
1098          frame->crop_left || frame->crop_right) && !ctx->crop_warned) {
1099         av_log(avctx, AV_LOG_WARNING, "Cropping information on input "
1100                "frames ignored due to lack of API support.\n");
1101         ctx->crop_warned = 1;
1102     }
1103 
1104     if (!ctx->roi_allowed) {
1105         AVFrameSideData *sd =
1106             av_frame_get_side_data(frame, AV_FRAME_DATA_REGIONS_OF_INTEREST);
1107 
1108         if (sd && !ctx->roi_warned) {
1109             av_log(avctx, AV_LOG_WARNING, "ROI side data on input "
1110                    "frames ignored due to lack of driver support.\n");
1111             ctx->roi_warned = 1;
1112         }
1113     }
1114 
1115     return 0;
1116 }
1117 
vaapi_encode_send_frame(AVCodecContext * avctx,AVFrame * frame)1118 static int vaapi_encode_send_frame(AVCodecContext *avctx, AVFrame *frame)
1119 {
1120     VAAPIEncodeContext *ctx = avctx->priv_data;
1121     VAAPIEncodePicture *pic;
1122     int err;
1123 
1124     if (frame) {
1125         av_log(avctx, AV_LOG_DEBUG, "Input frame: %ux%u (%"PRId64").\n",
1126                frame->width, frame->height, frame->pts);
1127 
1128         err = vaapi_encode_check_frame(avctx, frame);
1129         if (err < 0)
1130             return err;
1131 
1132         pic = vaapi_encode_alloc(avctx);
1133         if (!pic)
1134             return AVERROR(ENOMEM);
1135 
1136         pic->input_image = av_frame_alloc();
1137         if (!pic->input_image) {
1138             err = AVERROR(ENOMEM);
1139             goto fail;
1140         }
1141 
1142         if (ctx->input_order == 0 || frame->pict_type == AV_PICTURE_TYPE_I)
1143             pic->force_idr = 1;
1144 
1145         pic->input_surface = (VASurfaceID)(uintptr_t)frame->data[3];
1146         pic->pts = frame->pts;
1147 
1148         av_frame_move_ref(pic->input_image, frame);
1149 
1150         if (ctx->input_order == 0)
1151             ctx->first_pts = pic->pts;
1152         if (ctx->input_order == ctx->decode_delay)
1153             ctx->dts_pts_diff = pic->pts - ctx->first_pts;
1154         if (ctx->output_delay > 0)
1155             ctx->ts_ring[ctx->input_order %
1156                         (3 * ctx->output_delay + ctx->async_depth)] = pic->pts;
1157 
1158         pic->display_order = ctx->input_order;
1159         ++ctx->input_order;
1160 
1161         if (ctx->pic_start) {
1162             ctx->pic_end->next = pic;
1163             ctx->pic_end       = pic;
1164         } else {
1165             ctx->pic_start     = pic;
1166             ctx->pic_end       = pic;
1167         }
1168 
1169     } else {
1170         ctx->end_of_stream = 1;
1171 
1172         // Fix timestamps if we hit end-of-stream before the initial decode
1173         // delay has elapsed.
1174         if (ctx->input_order < ctx->decode_delay)
1175             ctx->dts_pts_diff = ctx->pic_end->pts - ctx->first_pts;
1176     }
1177 
1178     return 0;
1179 
1180 fail:
1181     vaapi_encode_free(avctx, pic);
1182     return err;
1183 }
1184 
ff_vaapi_encode_receive_packet(AVCodecContext * avctx,AVPacket * pkt)1185 int ff_vaapi_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
1186 {
1187     VAAPIEncodeContext *ctx = avctx->priv_data;
1188     VAAPIEncodePicture *pic;
1189     AVFrame *frame = ctx->frame;
1190     int err;
1191 
1192     err = ff_encode_get_frame(avctx, frame);
1193     if (err < 0 && err != AVERROR_EOF)
1194         return err;
1195 
1196     if (err == AVERROR_EOF)
1197         frame = NULL;
1198 
1199     err = vaapi_encode_send_frame(avctx, frame);
1200     if (err < 0)
1201         return err;
1202 
1203     if (!ctx->pic_start) {
1204         if (ctx->end_of_stream)
1205             return AVERROR_EOF;
1206         else
1207             return AVERROR(EAGAIN);
1208     }
1209 
1210     if (ctx->has_sync_buffer_func) {
1211         pic = NULL;
1212 
1213         if (av_fifo_can_write(ctx->encode_fifo)) {
1214             err = vaapi_encode_pick_next(avctx, &pic);
1215             if (!err) {
1216                 av_assert0(pic);
1217                 pic->encode_order = ctx->encode_order +
1218                     av_fifo_can_read(ctx->encode_fifo);
1219                 err = vaapi_encode_issue(avctx, pic);
1220                 if (err < 0) {
1221                     av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
1222                     return err;
1223                 }
1224                 av_fifo_write(ctx->encode_fifo, &pic, 1);
1225             }
1226         }
1227 
1228         if (!av_fifo_can_read(ctx->encode_fifo))
1229             return err;
1230 
1231         // More frames can be buffered
1232         if (av_fifo_can_write(ctx->encode_fifo) && !ctx->end_of_stream)
1233             return AVERROR(EAGAIN);
1234 
1235         av_fifo_read(ctx->encode_fifo, &pic, 1);
1236         ctx->encode_order = pic->encode_order + 1;
1237     } else {
1238         pic = NULL;
1239         err = vaapi_encode_pick_next(avctx, &pic);
1240         if (err < 0)
1241             return err;
1242         av_assert0(pic);
1243 
1244         pic->encode_order = ctx->encode_order++;
1245 
1246         err = vaapi_encode_issue(avctx, pic);
1247         if (err < 0) {
1248             av_log(avctx, AV_LOG_ERROR, "Encode failed: %d.\n", err);
1249             return err;
1250         }
1251     }
1252 
1253     err = vaapi_encode_output(avctx, pic, pkt);
1254     if (err < 0) {
1255         av_log(avctx, AV_LOG_ERROR, "Output failed: %d.\n", err);
1256         return err;
1257     }
1258 
1259     if (ctx->output_delay == 0) {
1260         pkt->dts = pkt->pts;
1261     } else if (pic->encode_order < ctx->decode_delay) {
1262         if (ctx->ts_ring[pic->encode_order] < INT64_MIN + ctx->dts_pts_diff)
1263             pkt->dts = INT64_MIN;
1264         else
1265             pkt->dts = ctx->ts_ring[pic->encode_order] - ctx->dts_pts_diff;
1266     } else {
1267         pkt->dts = ctx->ts_ring[(pic->encode_order - ctx->decode_delay) %
1268                                 (3 * ctx->output_delay + ctx->async_depth)];
1269     }
1270     av_log(avctx, AV_LOG_DEBUG, "Output packet: pts %"PRId64" dts %"PRId64".\n",
1271            pkt->pts, pkt->dts);
1272 
1273     ctx->output_order = pic->encode_order;
1274     vaapi_encode_clear_old(avctx);
1275 
1276     return 0;
1277 }
1278 
1279 
vaapi_encode_add_global_param(AVCodecContext * avctx,int type,void * buffer,size_t size)1280 static av_cold void vaapi_encode_add_global_param(AVCodecContext *avctx, int type,
1281                                                   void *buffer, size_t size)
1282 {
1283     VAAPIEncodeContext *ctx = avctx->priv_data;
1284 
1285     av_assert0(ctx->nb_global_params < MAX_GLOBAL_PARAMS);
1286 
1287     ctx->global_params_type[ctx->nb_global_params] = type;
1288     ctx->global_params     [ctx->nb_global_params] = buffer;
1289     ctx->global_params_size[ctx->nb_global_params] = size;
1290 
1291     ++ctx->nb_global_params;
1292 }
1293 
1294 typedef struct VAAPIEncodeRTFormat {
1295     const char *name;
1296     unsigned int value;
1297     int depth;
1298     int nb_components;
1299     int log2_chroma_w;
1300     int log2_chroma_h;
1301 } VAAPIEncodeRTFormat;
1302 
1303 static const VAAPIEncodeRTFormat vaapi_encode_rt_formats[] = {
1304     { "YUV400",    VA_RT_FORMAT_YUV400,        8, 1,      },
1305     { "YUV420",    VA_RT_FORMAT_YUV420,        8, 3, 1, 1 },
1306     { "YUV422",    VA_RT_FORMAT_YUV422,        8, 3, 1, 0 },
1307 #if VA_CHECK_VERSION(1, 2, 0)
1308     { "YUV422_10", VA_RT_FORMAT_YUV422_10,    10, 3, 1, 0 },
1309 #endif
1310     { "YUV444",    VA_RT_FORMAT_YUV444,        8, 3, 0, 0 },
1311     { "YUV411",    VA_RT_FORMAT_YUV411,        8, 3, 2, 0 },
1312 #if VA_CHECK_VERSION(0, 38, 1)
1313     { "YUV420_10", VA_RT_FORMAT_YUV420_10BPP, 10, 3, 1, 1 },
1314 #endif
1315 };
1316 
1317 static const VAEntrypoint vaapi_encode_entrypoints_normal[] = {
1318     VAEntrypointEncSlice,
1319     VAEntrypointEncPicture,
1320 #if VA_CHECK_VERSION(0, 39, 2)
1321     VAEntrypointEncSliceLP,
1322 #endif
1323     0
1324 };
1325 #if VA_CHECK_VERSION(0, 39, 2)
1326 static const VAEntrypoint vaapi_encode_entrypoints_low_power[] = {
1327     VAEntrypointEncSliceLP,
1328     0
1329 };
1330 #endif
1331 
vaapi_encode_profile_entrypoint(AVCodecContext * avctx)1332 static av_cold int vaapi_encode_profile_entrypoint(AVCodecContext *avctx)
1333 {
1334     VAAPIEncodeContext      *ctx = avctx->priv_data;
1335     VAProfile    *va_profiles    = NULL;
1336     VAEntrypoint *va_entrypoints = NULL;
1337     VAStatus vas;
1338     const VAEntrypoint *usable_entrypoints;
1339     const VAAPIEncodeProfile *profile;
1340     const AVPixFmtDescriptor *desc;
1341     VAConfigAttrib rt_format_attr;
1342     const VAAPIEncodeRTFormat *rt_format;
1343     const char *profile_string, *entrypoint_string;
1344     int i, j, n, depth, err;
1345 
1346 
1347     if (ctx->low_power) {
1348 #if VA_CHECK_VERSION(0, 39, 2)
1349         usable_entrypoints = vaapi_encode_entrypoints_low_power;
1350 #else
1351         av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
1352                "supported with this VAAPI version.\n");
1353         return AVERROR(EINVAL);
1354 #endif
1355     } else {
1356         usable_entrypoints = vaapi_encode_entrypoints_normal;
1357     }
1358 
1359     desc = av_pix_fmt_desc_get(ctx->input_frames->sw_format);
1360     if (!desc) {
1361         av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%d).\n",
1362                ctx->input_frames->sw_format);
1363         return AVERROR(EINVAL);
1364     }
1365     depth = desc->comp[0].depth;
1366     for (i = 1; i < desc->nb_components; i++) {
1367         if (desc->comp[i].depth != depth) {
1368             av_log(avctx, AV_LOG_ERROR, "Invalid input pixfmt (%s).\n",
1369                    desc->name);
1370             return AVERROR(EINVAL);
1371         }
1372     }
1373     av_log(avctx, AV_LOG_VERBOSE, "Input surface format is %s.\n",
1374            desc->name);
1375 
1376     n = vaMaxNumProfiles(ctx->hwctx->display);
1377     va_profiles = av_malloc_array(n, sizeof(VAProfile));
1378     if (!va_profiles) {
1379         err = AVERROR(ENOMEM);
1380         goto fail;
1381     }
1382     vas = vaQueryConfigProfiles(ctx->hwctx->display, va_profiles, &n);
1383     if (vas != VA_STATUS_SUCCESS) {
1384         av_log(avctx, AV_LOG_ERROR, "Failed to query profiles: %d (%s).\n",
1385                vas, vaErrorStr(vas));
1386         err = AVERROR_EXTERNAL;
1387         goto fail;
1388     }
1389 
1390     av_assert0(ctx->codec->profiles);
1391     for (i = 0; (ctx->codec->profiles[i].av_profile !=
1392                  FF_PROFILE_UNKNOWN); i++) {
1393         profile = &ctx->codec->profiles[i];
1394         if (depth               != profile->depth ||
1395             desc->nb_components != profile->nb_components)
1396             continue;
1397         if (desc->nb_components > 1 &&
1398             (desc->log2_chroma_w != profile->log2_chroma_w ||
1399              desc->log2_chroma_h != profile->log2_chroma_h))
1400             continue;
1401         if (avctx->profile != profile->av_profile &&
1402             avctx->profile != FF_PROFILE_UNKNOWN)
1403             continue;
1404 
1405 #if VA_CHECK_VERSION(1, 0, 0)
1406         profile_string = vaProfileStr(profile->va_profile);
1407 #else
1408         profile_string = "(no profile names)";
1409 #endif
1410 
1411         for (j = 0; j < n; j++) {
1412             if (va_profiles[j] == profile->va_profile)
1413                 break;
1414         }
1415         if (j >= n) {
1416             av_log(avctx, AV_LOG_VERBOSE, "Compatible profile %s (%d) "
1417                    "is not supported by driver.\n", profile_string,
1418                    profile->va_profile);
1419             continue;
1420         }
1421 
1422         ctx->profile = profile;
1423         break;
1424     }
1425     if (!ctx->profile) {
1426         av_log(avctx, AV_LOG_ERROR, "No usable encoding profile found.\n");
1427         err = AVERROR(ENOSYS);
1428         goto fail;
1429     }
1430 
1431     avctx->profile  = profile->av_profile;
1432     ctx->va_profile = profile->va_profile;
1433     av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI profile %s (%d).\n",
1434            profile_string, ctx->va_profile);
1435 
1436     n = vaMaxNumEntrypoints(ctx->hwctx->display);
1437     va_entrypoints = av_malloc_array(n, sizeof(VAEntrypoint));
1438     if (!va_entrypoints) {
1439         err = AVERROR(ENOMEM);
1440         goto fail;
1441     }
1442     vas = vaQueryConfigEntrypoints(ctx->hwctx->display, ctx->va_profile,
1443                                    va_entrypoints, &n);
1444     if (vas != VA_STATUS_SUCCESS) {
1445         av_log(avctx, AV_LOG_ERROR, "Failed to query entrypoints for "
1446                "profile %s (%d): %d (%s).\n", profile_string,
1447                ctx->va_profile, vas, vaErrorStr(vas));
1448         err = AVERROR_EXTERNAL;
1449         goto fail;
1450     }
1451 
1452     for (i = 0; i < n; i++) {
1453         for (j = 0; usable_entrypoints[j]; j++) {
1454             if (va_entrypoints[i] == usable_entrypoints[j])
1455                 break;
1456         }
1457         if (usable_entrypoints[j])
1458             break;
1459     }
1460     if (i >= n) {
1461         av_log(avctx, AV_LOG_ERROR, "No usable encoding entrypoint found "
1462                "for profile %s (%d).\n", profile_string, ctx->va_profile);
1463         err = AVERROR(ENOSYS);
1464         goto fail;
1465     }
1466 
1467     ctx->va_entrypoint = va_entrypoints[i];
1468 #if VA_CHECK_VERSION(1, 0, 0)
1469     entrypoint_string = vaEntrypointStr(ctx->va_entrypoint);
1470 #else
1471     entrypoint_string = "(no entrypoint names)";
1472 #endif
1473     av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI entrypoint %s (%d).\n",
1474            entrypoint_string, ctx->va_entrypoint);
1475 
1476     for (i = 0; i < FF_ARRAY_ELEMS(vaapi_encode_rt_formats); i++) {
1477         rt_format = &vaapi_encode_rt_formats[i];
1478         if (rt_format->depth         == depth &&
1479             rt_format->nb_components == profile->nb_components &&
1480             rt_format->log2_chroma_w == profile->log2_chroma_w &&
1481             rt_format->log2_chroma_h == profile->log2_chroma_h)
1482             break;
1483     }
1484     if (i >= FF_ARRAY_ELEMS(vaapi_encode_rt_formats)) {
1485         av_log(avctx, AV_LOG_ERROR, "No usable render target format "
1486                "found for profile %s (%d) entrypoint %s (%d).\n",
1487                profile_string, ctx->va_profile,
1488                entrypoint_string, ctx->va_entrypoint);
1489         err = AVERROR(ENOSYS);
1490         goto fail;
1491     }
1492 
1493     rt_format_attr = (VAConfigAttrib) { VAConfigAttribRTFormat };
1494     vas = vaGetConfigAttributes(ctx->hwctx->display,
1495                                 ctx->va_profile, ctx->va_entrypoint,
1496                                 &rt_format_attr, 1);
1497     if (vas != VA_STATUS_SUCCESS) {
1498         av_log(avctx, AV_LOG_ERROR, "Failed to query RT format "
1499                "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1500         err = AVERROR_EXTERNAL;
1501         goto fail;
1502     }
1503 
1504     if (rt_format_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1505         av_log(avctx, AV_LOG_VERBOSE, "RT format config attribute not "
1506                "supported by driver: assuming surface RT format %s "
1507                "is valid.\n", rt_format->name);
1508     } else if (!(rt_format_attr.value & rt_format->value)) {
1509         av_log(avctx, AV_LOG_ERROR, "Surface RT format %s not supported "
1510                "by driver for encoding profile %s (%d) entrypoint %s (%d).\n",
1511                rt_format->name, profile_string, ctx->va_profile,
1512                entrypoint_string, ctx->va_entrypoint);
1513         err = AVERROR(ENOSYS);
1514         goto fail;
1515     } else {
1516         av_log(avctx, AV_LOG_VERBOSE, "Using VAAPI render target "
1517                "format %s (%#x).\n", rt_format->name, rt_format->value);
1518         ctx->config_attributes[ctx->nb_config_attributes++] =
1519             (VAConfigAttrib) {
1520             .type  = VAConfigAttribRTFormat,
1521             .value = rt_format->value,
1522         };
1523     }
1524 
1525     err = 0;
1526 fail:
1527     av_freep(&va_profiles);
1528     av_freep(&va_entrypoints);
1529     return err;
1530 }
1531 
1532 static const VAAPIEncodeRCMode vaapi_encode_rc_modes[] = {
1533     //                                  Bitrate   Quality
1534     //                                     | Maxrate | HRD/VBV
1535     { 0 }, //                              |    |    |    |
1536     { RC_MODE_CQP,  "CQP",  1, VA_RC_CQP,  0,   0,   1,   0 },
1537     { RC_MODE_CBR,  "CBR",  1, VA_RC_CBR,  1,   0,   0,   1 },
1538     { RC_MODE_VBR,  "VBR",  1, VA_RC_VBR,  1,   1,   0,   1 },
1539 #if VA_CHECK_VERSION(1, 1, 0)
1540     { RC_MODE_ICQ,  "ICQ",  1, VA_RC_ICQ,  0,   0,   1,   0 },
1541 #else
1542     { RC_MODE_ICQ,  "ICQ",  0 },
1543 #endif
1544 #if VA_CHECK_VERSION(1, 3, 0)
1545     { RC_MODE_QVBR, "QVBR", 1, VA_RC_QVBR, 1,   1,   1,   1 },
1546     { RC_MODE_AVBR, "AVBR", 0, VA_RC_AVBR, 1,   0,   0,   0 },
1547 #else
1548     { RC_MODE_QVBR, "QVBR", 0 },
1549     { RC_MODE_AVBR, "AVBR", 0 },
1550 #endif
1551 };
1552 
vaapi_encode_init_rate_control(AVCodecContext * avctx)1553 static av_cold int vaapi_encode_init_rate_control(AVCodecContext *avctx)
1554 {
1555     VAAPIEncodeContext *ctx = avctx->priv_data;
1556     uint32_t supported_va_rc_modes;
1557     const VAAPIEncodeRCMode *rc_mode;
1558     int64_t rc_bits_per_second;
1559     int     rc_target_percentage;
1560     int     rc_window_size;
1561     int     rc_quality;
1562     int64_t hrd_buffer_size;
1563     int64_t hrd_initial_buffer_fullness;
1564     int fr_num, fr_den;
1565     VAConfigAttrib rc_attr = { VAConfigAttribRateControl };
1566     VAStatus vas;
1567     char supported_rc_modes_string[64];
1568 
1569     vas = vaGetConfigAttributes(ctx->hwctx->display,
1570                                 ctx->va_profile, ctx->va_entrypoint,
1571                                 &rc_attr, 1);
1572     if (vas != VA_STATUS_SUCCESS) {
1573         av_log(avctx, AV_LOG_ERROR, "Failed to query rate control "
1574                "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1575         return AVERROR_EXTERNAL;
1576     }
1577     if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1578         av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any "
1579                "supported rate control modes: assuming CQP only.\n");
1580         supported_va_rc_modes = VA_RC_CQP;
1581         strcpy(supported_rc_modes_string, "unknown");
1582     } else {
1583         char *str = supported_rc_modes_string;
1584         size_t len = sizeof(supported_rc_modes_string);
1585         int i, first = 1, res;
1586 
1587         supported_va_rc_modes = rc_attr.value;
1588         for (i = 0; i < FF_ARRAY_ELEMS(vaapi_encode_rc_modes); i++) {
1589             rc_mode = &vaapi_encode_rc_modes[i];
1590             if (supported_va_rc_modes & rc_mode->va_mode) {
1591                 res = snprintf(str, len, "%s%s",
1592                                first ? "" : ", ", rc_mode->name);
1593                 first = 0;
1594                 if (res < 0) {
1595                     *str = 0;
1596                     break;
1597                 }
1598                 len -= res;
1599                 str += res;
1600                 if (len == 0)
1601                     break;
1602             }
1603         }
1604 
1605         av_log(avctx, AV_LOG_DEBUG, "Driver supports RC modes %s.\n",
1606                supported_rc_modes_string);
1607     }
1608 
1609     // Rate control mode selection:
1610     // * If the user has set a mode explicitly with the rc_mode option,
1611     //   use it and fail if it is not available.
1612     // * If an explicit QP option has been set, use CQP.
1613     // * If the codec is CQ-only, use CQP.
1614     // * If the QSCALE avcodec option is set, use CQP.
1615     // * If bitrate and quality are both set, try QVBR.
1616     // * If quality is set, try ICQ, then CQP.
1617     // * If bitrate and maxrate are set and have the same value, try CBR.
1618     // * If a bitrate is set, try AVBR, then VBR, then CBR.
1619     // * If no bitrate is set, try ICQ, then CQP.
1620 
1621 #define TRY_RC_MODE(mode, fail) do { \
1622         rc_mode = &vaapi_encode_rc_modes[mode]; \
1623         if (!(rc_mode->va_mode & supported_va_rc_modes)) { \
1624             if (fail) { \
1625                 av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
1626                        "RC mode (supported modes: %s).\n", rc_mode->name, \
1627                        supported_rc_modes_string); \
1628                 return AVERROR(EINVAL); \
1629             } \
1630             av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
1631                    "RC mode.\n", rc_mode->name); \
1632             rc_mode = NULL; \
1633         } else { \
1634             goto rc_mode_found; \
1635         } \
1636     } while (0)
1637 
1638     if (ctx->explicit_rc_mode)
1639         TRY_RC_MODE(ctx->explicit_rc_mode, 1);
1640 
1641     if (ctx->explicit_qp)
1642         TRY_RC_MODE(RC_MODE_CQP, 1);
1643 
1644     if (ctx->codec->flags & FLAG_CONSTANT_QUALITY_ONLY)
1645         TRY_RC_MODE(RC_MODE_CQP, 1);
1646 
1647     if (avctx->flags & AV_CODEC_FLAG_QSCALE)
1648         TRY_RC_MODE(RC_MODE_CQP, 1);
1649 
1650     if (avctx->bit_rate > 0 && avctx->global_quality > 0)
1651         TRY_RC_MODE(RC_MODE_QVBR, 0);
1652 
1653     if (avctx->global_quality > 0) {
1654         TRY_RC_MODE(RC_MODE_ICQ, 0);
1655         TRY_RC_MODE(RC_MODE_CQP, 0);
1656     }
1657 
1658     if (avctx->bit_rate > 0 && avctx->rc_max_rate == avctx->bit_rate)
1659         TRY_RC_MODE(RC_MODE_CBR, 0);
1660 
1661     if (avctx->bit_rate > 0) {
1662         TRY_RC_MODE(RC_MODE_AVBR, 0);
1663         TRY_RC_MODE(RC_MODE_VBR, 0);
1664         TRY_RC_MODE(RC_MODE_CBR, 0);
1665     } else {
1666         TRY_RC_MODE(RC_MODE_ICQ, 0);
1667         TRY_RC_MODE(RC_MODE_CQP, 0);
1668     }
1669 
1670     av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
1671            "RC mode compatible with selected options "
1672            "(supported modes: %s).\n", supported_rc_modes_string);
1673     return AVERROR(EINVAL);
1674 
1675 rc_mode_found:
1676     if (rc_mode->bitrate) {
1677         if (avctx->bit_rate <= 0) {
1678             av_log(avctx, AV_LOG_ERROR, "Bitrate must be set for %s "
1679                    "RC mode.\n", rc_mode->name);
1680             return AVERROR(EINVAL);
1681         }
1682 
1683         if (rc_mode->mode == RC_MODE_AVBR) {
1684             // For maximum confusion AVBR is hacked into the existing API
1685             // by overloading some of the fields with completely different
1686             // meanings.
1687 
1688             // Target percentage does not apply in AVBR mode.
1689             rc_bits_per_second = avctx->bit_rate;
1690 
1691             // Accuracy tolerance range for meeting the specified target
1692             // bitrate.  It's very unclear how this is actually intended
1693             // to work - since we do want to get the specified bitrate,
1694             // set the accuracy to 100% for now.
1695             rc_target_percentage = 100;
1696 
1697             // Convergence period in frames.  The GOP size reflects the
1698             // user's intended block size for cutting, so reusing that
1699             // as the convergence period seems a reasonable default.
1700             rc_window_size = avctx->gop_size > 0 ? avctx->gop_size : 60;
1701 
1702         } else if (rc_mode->maxrate) {
1703             if (avctx->rc_max_rate > 0) {
1704                 if (avctx->rc_max_rate < avctx->bit_rate) {
1705                     av_log(avctx, AV_LOG_ERROR, "Invalid bitrate settings: "
1706                            "bitrate (%"PRId64") must not be greater than "
1707                            "maxrate (%"PRId64").\n", avctx->bit_rate,
1708                            avctx->rc_max_rate);
1709                     return AVERROR(EINVAL);
1710                 }
1711                 rc_bits_per_second   = avctx->rc_max_rate;
1712                 rc_target_percentage = (avctx->bit_rate * 100) /
1713                                        avctx->rc_max_rate;
1714             } else {
1715                 // We only have a target bitrate, but this mode requires
1716                 // that a maximum rate be supplied as well.  Since the
1717                 // user does not want this to be a constraint, arbitrarily
1718                 // pick a maximum rate of double the target rate.
1719                 rc_bits_per_second   = 2 * avctx->bit_rate;
1720                 rc_target_percentage = 50;
1721             }
1722         } else {
1723             if (avctx->rc_max_rate > avctx->bit_rate) {
1724                 av_log(avctx, AV_LOG_WARNING, "Max bitrate is ignored "
1725                        "in %s RC mode.\n", rc_mode->name);
1726             }
1727             rc_bits_per_second   = avctx->bit_rate;
1728             rc_target_percentage = 100;
1729         }
1730     } else {
1731         rc_bits_per_second   = 0;
1732         rc_target_percentage = 100;
1733     }
1734 
1735     if (rc_mode->quality) {
1736         if (ctx->explicit_qp) {
1737             rc_quality = ctx->explicit_qp;
1738         } else if (avctx->global_quality > 0) {
1739             rc_quality = avctx->global_quality;
1740         } else {
1741             rc_quality = ctx->codec->default_quality;
1742             av_log(avctx, AV_LOG_WARNING, "No quality level set; "
1743                    "using default (%d).\n", rc_quality);
1744         }
1745     } else {
1746         rc_quality = 0;
1747     }
1748 
1749     if (rc_mode->hrd) {
1750         if (avctx->rc_buffer_size)
1751             hrd_buffer_size = avctx->rc_buffer_size;
1752         else if (avctx->rc_max_rate > 0)
1753             hrd_buffer_size = avctx->rc_max_rate;
1754         else
1755             hrd_buffer_size = avctx->bit_rate;
1756         if (avctx->rc_initial_buffer_occupancy) {
1757             if (avctx->rc_initial_buffer_occupancy > hrd_buffer_size) {
1758                 av_log(avctx, AV_LOG_ERROR, "Invalid RC buffer settings: "
1759                        "must have initial buffer size (%d) <= "
1760                        "buffer size (%"PRId64").\n",
1761                        avctx->rc_initial_buffer_occupancy, hrd_buffer_size);
1762                 return AVERROR(EINVAL);
1763             }
1764             hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
1765         } else {
1766             hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1767         }
1768 
1769         rc_window_size = (hrd_buffer_size * 1000) / rc_bits_per_second;
1770     } else {
1771         if (avctx->rc_buffer_size || avctx->rc_initial_buffer_occupancy) {
1772             av_log(avctx, AV_LOG_WARNING, "Buffering settings are ignored "
1773                    "in %s RC mode.\n", rc_mode->name);
1774         }
1775 
1776         hrd_buffer_size             = 0;
1777         hrd_initial_buffer_fullness = 0;
1778 
1779         if (rc_mode->mode != RC_MODE_AVBR) {
1780             // Already set (with completely different meaning) for AVBR.
1781             rc_window_size = 1000;
1782         }
1783     }
1784 
1785     if (rc_bits_per_second          > UINT32_MAX ||
1786         hrd_buffer_size             > UINT32_MAX ||
1787         hrd_initial_buffer_fullness > UINT32_MAX) {
1788         av_log(avctx, AV_LOG_ERROR, "RC parameters of 2^32 or "
1789                "greater are not supported by VAAPI.\n");
1790         return AVERROR(EINVAL);
1791     }
1792 
1793     ctx->rc_mode     = rc_mode;
1794     ctx->rc_quality  = rc_quality;
1795     ctx->va_rc_mode  = rc_mode->va_mode;
1796     ctx->va_bit_rate = rc_bits_per_second;
1797 
1798     av_log(avctx, AV_LOG_VERBOSE, "RC mode: %s.\n", rc_mode->name);
1799     if (rc_attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1800         // This driver does not want the RC mode attribute to be set.
1801     } else {
1802         ctx->config_attributes[ctx->nb_config_attributes++] =
1803             (VAConfigAttrib) {
1804             .type  = VAConfigAttribRateControl,
1805             .value = ctx->va_rc_mode,
1806         };
1807     }
1808 
1809     if (rc_mode->quality)
1810         av_log(avctx, AV_LOG_VERBOSE, "RC quality: %d.\n", rc_quality);
1811 
1812     if (rc_mode->va_mode != VA_RC_CQP) {
1813         if (rc_mode->mode == RC_MODE_AVBR) {
1814             av_log(avctx, AV_LOG_VERBOSE, "RC target: %"PRId64" bps "
1815                    "converging in %d frames with %d%% accuracy.\n",
1816                    rc_bits_per_second, rc_window_size,
1817                    rc_target_percentage);
1818         } else if (rc_mode->bitrate) {
1819             av_log(avctx, AV_LOG_VERBOSE, "RC target: %d%% of "
1820                    "%"PRId64" bps over %d ms.\n", rc_target_percentage,
1821                    rc_bits_per_second, rc_window_size);
1822         }
1823 
1824         ctx->rc_params = (VAEncMiscParameterRateControl) {
1825             .bits_per_second    = rc_bits_per_second,
1826             .target_percentage  = rc_target_percentage,
1827             .window_size        = rc_window_size,
1828             .initial_qp         = 0,
1829             .min_qp             = (avctx->qmin > 0 ? avctx->qmin : 0),
1830             .basic_unit_size    = 0,
1831 #if VA_CHECK_VERSION(1, 1, 0)
1832             .ICQ_quality_factor = av_clip(rc_quality, 1, 51),
1833             .max_qp             = (avctx->qmax > 0 ? avctx->qmax : 0),
1834 #endif
1835 #if VA_CHECK_VERSION(1, 3, 0)
1836             .quality_factor     = rc_quality,
1837 #endif
1838         };
1839         vaapi_encode_add_global_param(avctx,
1840                                       VAEncMiscParameterTypeRateControl,
1841                                       &ctx->rc_params,
1842                                       sizeof(ctx->rc_params));
1843     }
1844 
1845     if (rc_mode->hrd) {
1846         av_log(avctx, AV_LOG_VERBOSE, "RC buffer: %"PRId64" bits, "
1847                "initial fullness %"PRId64" bits.\n",
1848                hrd_buffer_size, hrd_initial_buffer_fullness);
1849 
1850         ctx->hrd_params = (VAEncMiscParameterHRD) {
1851             .initial_buffer_fullness = hrd_initial_buffer_fullness,
1852             .buffer_size             = hrd_buffer_size,
1853         };
1854         vaapi_encode_add_global_param(avctx,
1855                                       VAEncMiscParameterTypeHRD,
1856                                       &ctx->hrd_params,
1857                                       sizeof(ctx->hrd_params));
1858     }
1859 
1860     if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
1861         av_reduce(&fr_num, &fr_den,
1862                   avctx->framerate.num, avctx->framerate.den, 65535);
1863     else
1864         av_reduce(&fr_num, &fr_den,
1865                   avctx->time_base.den, avctx->time_base.num, 65535);
1866 
1867     av_log(avctx, AV_LOG_VERBOSE, "RC framerate: %d/%d (%.2f fps).\n",
1868            fr_num, fr_den, (double)fr_num / fr_den);
1869 
1870     ctx->fr_params = (VAEncMiscParameterFrameRate) {
1871         .framerate = (unsigned int)fr_den << 16 | fr_num,
1872     };
1873 #if VA_CHECK_VERSION(0, 40, 0)
1874     vaapi_encode_add_global_param(avctx,
1875                                   VAEncMiscParameterTypeFrameRate,
1876                                   &ctx->fr_params,
1877                                   sizeof(ctx->fr_params));
1878 #endif
1879 
1880     return 0;
1881 }
1882 
vaapi_encode_init_max_frame_size(AVCodecContext * avctx)1883 static av_cold int vaapi_encode_init_max_frame_size(AVCodecContext *avctx)
1884 {
1885 #if VA_CHECK_VERSION(1, 5, 0)
1886     VAAPIEncodeContext  *ctx = avctx->priv_data;
1887     VAConfigAttrib      attr = { VAConfigAttribMaxFrameSize };
1888     VAStatus vas;
1889 
1890     if (ctx->va_rc_mode == VA_RC_CQP) {
1891         ctx->max_frame_size = 0;
1892         av_log(avctx, AV_LOG_ERROR, "Max frame size is invalid in CQP rate "
1893                "control mode.\n");
1894         return AVERROR(EINVAL);
1895     }
1896 
1897     vas = vaGetConfigAttributes(ctx->hwctx->display,
1898                                 ctx->va_profile,
1899                                 ctx->va_entrypoint,
1900                                 &attr, 1);
1901     if (vas != VA_STATUS_SUCCESS) {
1902         ctx->max_frame_size = 0;
1903         av_log(avctx, AV_LOG_ERROR, "Failed to query max frame size "
1904                "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
1905         return AVERROR_EXTERNAL;
1906     }
1907 
1908     if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1909         ctx->max_frame_size = 0;
1910         av_log(avctx, AV_LOG_ERROR, "Max frame size attribute "
1911                "is not supported.\n");
1912         return AVERROR(EINVAL);
1913     } else {
1914         VAConfigAttribValMaxFrameSize attr_mfs;
1915         attr_mfs.value = attr.value;
1916         // Prefer to use VAEncMiscParameterTypeMaxFrameSize for max frame size.
1917         if (!attr_mfs.bits.max_frame_size && attr_mfs.bits.multiple_pass) {
1918             ctx->max_frame_size = 0;
1919             av_log(avctx, AV_LOG_ERROR, "Driver only supports multiple pass "
1920                    "max frame size which has not been implemented in FFmpeg.\n");
1921             return AVERROR(EINVAL);
1922         }
1923 
1924         ctx->mfs_params = (VAEncMiscParameterBufferMaxFrameSize){
1925             .max_frame_size = ctx->max_frame_size * 8,
1926         };
1927 
1928         av_log(avctx, AV_LOG_VERBOSE, "Set max frame size: %d bytes.\n",
1929                ctx->max_frame_size);
1930     }
1931 #else
1932     av_log(avctx, AV_LOG_ERROR, "The max frame size option is not supported with "
1933            "this VAAPI version.\n");
1934     return AVERROR(EINVAL);
1935 #endif
1936 
1937     return 0;
1938 }
1939 
vaapi_encode_init_gop_structure(AVCodecContext * avctx)1940 static av_cold int vaapi_encode_init_gop_structure(AVCodecContext *avctx)
1941 {
1942     VAAPIEncodeContext *ctx = avctx->priv_data;
1943     VAStatus vas;
1944     VAConfigAttrib attr = { VAConfigAttribEncMaxRefFrames };
1945     uint32_t ref_l0, ref_l1;
1946     int prediction_pre_only;
1947 
1948     vas = vaGetConfigAttributes(ctx->hwctx->display,
1949                                 ctx->va_profile,
1950                                 ctx->va_entrypoint,
1951                                 &attr, 1);
1952     if (vas != VA_STATUS_SUCCESS) {
1953         av_log(avctx, AV_LOG_ERROR, "Failed to query reference frames "
1954                "attribute: %d (%s).\n", vas, vaErrorStr(vas));
1955         return AVERROR_EXTERNAL;
1956     }
1957 
1958     if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1959         ref_l0 = ref_l1 = 0;
1960     } else {
1961         ref_l0 = attr.value       & 0xffff;
1962         ref_l1 = attr.value >> 16 & 0xffff;
1963     }
1964 
1965     ctx->p_to_gpb = 0;
1966     prediction_pre_only = 0;
1967 
1968 #if VA_CHECK_VERSION(1, 9, 0)
1969     if (!(ctx->codec->flags & FLAG_INTRA_ONLY ||
1970         avctx->gop_size <= 1)) {
1971         attr = (VAConfigAttrib) { VAConfigAttribPredictionDirection };
1972         vas = vaGetConfigAttributes(ctx->hwctx->display,
1973                                     ctx->va_profile,
1974                                     ctx->va_entrypoint,
1975                                     &attr, 1);
1976         if (vas != VA_STATUS_SUCCESS) {
1977             av_log(avctx, AV_LOG_WARNING, "Failed to query prediction direction "
1978                    "attribute: %d (%s).\n", vas, vaErrorStr(vas));
1979             return AVERROR_EXTERNAL;
1980         } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
1981             av_log(avctx, AV_LOG_VERBOSE, "Driver does not report any additional "
1982                    "prediction constraints.\n");
1983         } else {
1984             if (((ref_l0 > 0 || ref_l1 > 0) && !(attr.value & VA_PREDICTION_DIRECTION_PREVIOUS)) ||
1985                 ((ref_l1 == 0) && (attr.value & (VA_PREDICTION_DIRECTION_FUTURE | VA_PREDICTION_DIRECTION_BI_NOT_EMPTY)))) {
1986                 av_log(avctx, AV_LOG_ERROR, "Driver report incorrect prediction "
1987                        "direction attribute.\n");
1988                 return AVERROR_EXTERNAL;
1989             }
1990 
1991             if (!(attr.value & VA_PREDICTION_DIRECTION_FUTURE)) {
1992                 if (ref_l0 > 0 && ref_l1 > 0) {
1993                     prediction_pre_only = 1;
1994                     av_log(avctx, AV_LOG_VERBOSE, "Driver only support same reference "
1995                            "lists for B-frames.\n");
1996                 }
1997             }
1998 
1999             if (attr.value & VA_PREDICTION_DIRECTION_BI_NOT_EMPTY) {
2000                 if (ref_l0 > 0 && ref_l1 > 0) {
2001                     ctx->p_to_gpb = 1;
2002                     av_log(avctx, AV_LOG_VERBOSE, "Driver does not support P-frames, "
2003                            "replacing them with B-frames.\n");
2004                 }
2005             }
2006         }
2007     }
2008 #endif
2009 
2010     if (ctx->codec->flags & FLAG_INTRA_ONLY ||
2011         avctx->gop_size <= 1) {
2012         av_log(avctx, AV_LOG_VERBOSE, "Using intra frames only.\n");
2013         ctx->gop_size = 1;
2014     } else if (ref_l0 < 1) {
2015         av_log(avctx, AV_LOG_ERROR, "Driver does not support any "
2016                "reference frames.\n");
2017         return AVERROR(EINVAL);
2018     } else if (!(ctx->codec->flags & FLAG_B_PICTURES) ||
2019                ref_l1 < 1 || avctx->max_b_frames < 1 ||
2020                prediction_pre_only) {
2021         if (ctx->p_to_gpb)
2022            av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames "
2023                   "(supported references: %d / %d).\n",
2024                   ref_l0, ref_l1);
2025         else
2026             av_log(avctx, AV_LOG_VERBOSE, "Using intra and P-frames "
2027                    "(supported references: %d / %d).\n", ref_l0, ref_l1);
2028         ctx->gop_size = avctx->gop_size;
2029         ctx->p_per_i  = INT_MAX;
2030         ctx->b_per_p  = 0;
2031     } else {
2032        if (ctx->p_to_gpb)
2033            av_log(avctx, AV_LOG_VERBOSE, "Using intra and B-frames "
2034                   "(supported references: %d / %d).\n",
2035                   ref_l0, ref_l1);
2036        else
2037            av_log(avctx, AV_LOG_VERBOSE, "Using intra, P- and B-frames "
2038                   "(supported references: %d / %d).\n", ref_l0, ref_l1);
2039         ctx->gop_size = avctx->gop_size;
2040         ctx->p_per_i  = INT_MAX;
2041         ctx->b_per_p  = avctx->max_b_frames;
2042         if (ctx->codec->flags & FLAG_B_PICTURE_REFERENCES) {
2043             ctx->max_b_depth = FFMIN(ctx->desired_b_depth,
2044                                      av_log2(ctx->b_per_p) + 1);
2045         } else {
2046             ctx->max_b_depth = 1;
2047         }
2048     }
2049 
2050     if (ctx->codec->flags & FLAG_NON_IDR_KEY_PICTURES) {
2051         ctx->closed_gop  = !!(avctx->flags & AV_CODEC_FLAG_CLOSED_GOP);
2052         ctx->gop_per_idr = ctx->idr_interval + 1;
2053     } else {
2054         ctx->closed_gop  = 1;
2055         ctx->gop_per_idr = 1;
2056     }
2057 
2058     return 0;
2059 }
2060 
vaapi_encode_init_row_slice_structure(AVCodecContext * avctx,uint32_t slice_structure)2061 static av_cold int vaapi_encode_init_row_slice_structure(AVCodecContext *avctx,
2062                                                          uint32_t slice_structure)
2063 {
2064     VAAPIEncodeContext *ctx = avctx->priv_data;
2065     int req_slices;
2066 
2067     // For fixed-size slices currently we only support whole rows, making
2068     // rectangular slices.  This could be extended to arbitrary runs of
2069     // blocks, but since slices tend to be a conformance requirement and
2070     // most cases (such as broadcast or bluray) want rectangular slices
2071     // only it would need to be gated behind another option.
2072     if (avctx->slices > ctx->slice_block_rows) {
2073         av_log(avctx, AV_LOG_WARNING, "Not enough rows to use "
2074                "configured number of slices (%d < %d); using "
2075                "maximum.\n", ctx->slice_block_rows, avctx->slices);
2076         req_slices = ctx->slice_block_rows;
2077     } else {
2078         req_slices = avctx->slices;
2079     }
2080     if (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS ||
2081         slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS) {
2082         ctx->nb_slices  = req_slices;
2083         ctx->slice_size = ctx->slice_block_rows / ctx->nb_slices;
2084     } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_POWER_OF_TWO_ROWS) {
2085         int k;
2086         for (k = 1;; k *= 2) {
2087             if (2 * k * (req_slices - 1) + 1 >= ctx->slice_block_rows)
2088                 break;
2089         }
2090         ctx->nb_slices  = (ctx->slice_block_rows + k - 1) / k;
2091         ctx->slice_size = k;
2092 #if VA_CHECK_VERSION(1, 0, 0)
2093     } else if (slice_structure & VA_ENC_SLICE_STRUCTURE_EQUAL_ROWS) {
2094         ctx->nb_slices  = ctx->slice_block_rows;
2095         ctx->slice_size = 1;
2096 #endif
2097     } else {
2098         av_log(avctx, AV_LOG_ERROR, "Driver does not support any usable "
2099                "slice structure modes (%#x).\n", slice_structure);
2100         return AVERROR(EINVAL);
2101     }
2102 
2103     return 0;
2104 }
2105 
vaapi_encode_init_tile_slice_structure(AVCodecContext * avctx,uint32_t slice_structure)2106 static av_cold int vaapi_encode_init_tile_slice_structure(AVCodecContext *avctx,
2107                                                           uint32_t slice_structure)
2108 {
2109     VAAPIEncodeContext *ctx = avctx->priv_data;
2110     int i, req_tiles;
2111 
2112     if (!(slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_MACROBLOCKS ||
2113          (slice_structure & VA_ENC_SLICE_STRUCTURE_ARBITRARY_ROWS &&
2114           ctx->tile_cols == 1))) {
2115         av_log(avctx, AV_LOG_ERROR, "Supported slice structure (%#x) doesn't work for "
2116                "current tile requirement.\n", slice_structure);
2117         return AVERROR(EINVAL);
2118     }
2119 
2120     if (ctx->tile_rows > ctx->slice_block_rows ||
2121         ctx->tile_cols > ctx->slice_block_cols) {
2122         av_log(avctx, AV_LOG_WARNING, "Not enough block rows/cols (%d x %d) "
2123                "for configured number of tile (%d x %d); ",
2124                ctx->slice_block_rows, ctx->slice_block_cols,
2125                ctx->tile_rows, ctx->tile_cols);
2126         ctx->tile_rows = ctx->tile_rows > ctx->slice_block_rows ?
2127                                           ctx->slice_block_rows : ctx->tile_rows;
2128         ctx->tile_cols = ctx->tile_cols > ctx->slice_block_cols ?
2129                                           ctx->slice_block_cols : ctx->tile_cols;
2130         av_log(avctx, AV_LOG_WARNING, "using allowed maximum (%d x %d).\n",
2131                ctx->tile_rows, ctx->tile_cols);
2132     }
2133 
2134     req_tiles = ctx->tile_rows * ctx->tile_cols;
2135 
2136     // Tile slice is not allowed to cross the boundary of a tile due to
2137     // the constraints of media-driver. Currently we support one slice
2138     // per tile. This could be extended to multiple slices per tile.
2139     if (avctx->slices != req_tiles)
2140         av_log(avctx, AV_LOG_WARNING, "The number of requested slices "
2141                "mismatches with configured number of tile (%d != %d); "
2142                "using requested tile number for slice.\n",
2143                avctx->slices, req_tiles);
2144 
2145     ctx->nb_slices = req_tiles;
2146 
2147     // Default in uniform spacing
2148     // 6-3, 6-5
2149     for (i = 0; i < ctx->tile_cols; i++) {
2150         ctx->col_width[i] = ( i + 1 ) * ctx->slice_block_cols / ctx->tile_cols -
2151                                     i * ctx->slice_block_cols / ctx->tile_cols;
2152         ctx->col_bd[i + 1]  = ctx->col_bd[i] + ctx->col_width[i];
2153     }
2154     // 6-4, 6-6
2155     for (i = 0; i < ctx->tile_rows; i++) {
2156         ctx->row_height[i] = ( i + 1 ) * ctx->slice_block_rows / ctx->tile_rows -
2157                                      i * ctx->slice_block_rows / ctx->tile_rows;
2158         ctx->row_bd[i + 1] = ctx->row_bd[i] + ctx->row_height[i];
2159     }
2160 
2161     av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d x %d tile.\n",
2162            ctx->tile_rows, ctx->tile_cols);
2163 
2164     return 0;
2165 }
2166 
vaapi_encode_init_slice_structure(AVCodecContext * avctx)2167 static av_cold int vaapi_encode_init_slice_structure(AVCodecContext *avctx)
2168 {
2169     VAAPIEncodeContext *ctx = avctx->priv_data;
2170     VAConfigAttrib attr[3] = { { VAConfigAttribEncMaxSlices },
2171                                { VAConfigAttribEncSliceStructure },
2172 #if VA_CHECK_VERSION(1, 1, 0)
2173                                { VAConfigAttribEncTileSupport },
2174 #endif
2175                              };
2176     VAStatus vas;
2177     uint32_t max_slices, slice_structure;
2178     int ret;
2179 
2180     if (!(ctx->codec->flags & FLAG_SLICE_CONTROL)) {
2181         if (avctx->slices > 0) {
2182             av_log(avctx, AV_LOG_WARNING, "Multiple slices were requested "
2183                    "but this codec does not support controlling slices.\n");
2184         }
2185         return 0;
2186     }
2187 
2188     av_assert0(ctx->slice_block_height > 0 && ctx->slice_block_width > 0);
2189 
2190     ctx->slice_block_rows = (avctx->height + ctx->slice_block_height - 1) /
2191                              ctx->slice_block_height;
2192     ctx->slice_block_cols = (avctx->width  + ctx->slice_block_width  - 1) /
2193                              ctx->slice_block_width;
2194 
2195     if (avctx->slices <= 1 && !ctx->tile_rows && !ctx->tile_cols) {
2196         ctx->nb_slices  = 1;
2197         ctx->slice_size = ctx->slice_block_rows;
2198         return 0;
2199     }
2200 
2201     vas = vaGetConfigAttributes(ctx->hwctx->display,
2202                                 ctx->va_profile,
2203                                 ctx->va_entrypoint,
2204                                 attr, FF_ARRAY_ELEMS(attr));
2205     if (vas != VA_STATUS_SUCCESS) {
2206         av_log(avctx, AV_LOG_ERROR, "Failed to query slice "
2207                "attributes: %d (%s).\n", vas, vaErrorStr(vas));
2208         return AVERROR_EXTERNAL;
2209     }
2210     max_slices      = attr[0].value;
2211     slice_structure = attr[1].value;
2212     if (max_slices      == VA_ATTRIB_NOT_SUPPORTED ||
2213         slice_structure == VA_ATTRIB_NOT_SUPPORTED) {
2214         av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding "
2215                "pictures as multiple slices.\n.");
2216         return AVERROR(EINVAL);
2217     }
2218 
2219     if (ctx->tile_rows && ctx->tile_cols) {
2220 #if VA_CHECK_VERSION(1, 1, 0)
2221         uint32_t tile_support = attr[2].value;
2222         if (tile_support == VA_ATTRIB_NOT_SUPPORTED) {
2223             av_log(avctx, AV_LOG_ERROR, "Driver does not support encoding "
2224                    "pictures as multiple tiles.\n.");
2225             return AVERROR(EINVAL);
2226         }
2227 #else
2228         av_log(avctx, AV_LOG_ERROR, "Tile encoding option is "
2229             "not supported with this VAAPI version.\n");
2230         return AVERROR(EINVAL);
2231 #endif
2232     }
2233 
2234     if (ctx->tile_rows && ctx->tile_cols)
2235         ret = vaapi_encode_init_tile_slice_structure(avctx, slice_structure);
2236     else
2237         ret = vaapi_encode_init_row_slice_structure(avctx, slice_structure);
2238     if (ret < 0)
2239         return ret;
2240 
2241     if (ctx->nb_slices > avctx->slices) {
2242         av_log(avctx, AV_LOG_WARNING, "Slice count rounded up to "
2243                "%d (from %d) due to driver constraints on slice "
2244                "structure.\n", ctx->nb_slices, avctx->slices);
2245     }
2246     if (ctx->nb_slices > max_slices) {
2247         av_log(avctx, AV_LOG_ERROR, "Driver does not support "
2248                "encoding with %d slices (max %"PRIu32").\n",
2249                ctx->nb_slices, max_slices);
2250         return AVERROR(EINVAL);
2251     }
2252 
2253     av_log(avctx, AV_LOG_VERBOSE, "Encoding pictures with %d slices.\n",
2254            ctx->nb_slices);
2255     return 0;
2256 }
2257 
vaapi_encode_init_packed_headers(AVCodecContext * avctx)2258 static av_cold int vaapi_encode_init_packed_headers(AVCodecContext *avctx)
2259 {
2260     VAAPIEncodeContext *ctx = avctx->priv_data;
2261     VAStatus vas;
2262     VAConfigAttrib attr = { VAConfigAttribEncPackedHeaders };
2263 
2264     vas = vaGetConfigAttributes(ctx->hwctx->display,
2265                                 ctx->va_profile,
2266                                 ctx->va_entrypoint,
2267                                 &attr, 1);
2268     if (vas != VA_STATUS_SUCCESS) {
2269         av_log(avctx, AV_LOG_ERROR, "Failed to query packed headers "
2270                "attribute: %d (%s).\n", vas, vaErrorStr(vas));
2271         return AVERROR_EXTERNAL;
2272     }
2273 
2274     if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2275         if (ctx->desired_packed_headers) {
2276             av_log(avctx, AV_LOG_WARNING, "Driver does not support any "
2277                    "packed headers (wanted %#x).\n",
2278                    ctx->desired_packed_headers);
2279         } else {
2280             av_log(avctx, AV_LOG_VERBOSE, "Driver does not support any "
2281                    "packed headers (none wanted).\n");
2282         }
2283         ctx->va_packed_headers = 0;
2284     } else {
2285         if (ctx->desired_packed_headers & ~attr.value) {
2286             av_log(avctx, AV_LOG_WARNING, "Driver does not support some "
2287                    "wanted packed headers (wanted %#x, found %#x).\n",
2288                    ctx->desired_packed_headers, attr.value);
2289         } else {
2290             av_log(avctx, AV_LOG_VERBOSE, "All wanted packed headers "
2291                    "available (wanted %#x, found %#x).\n",
2292                    ctx->desired_packed_headers, attr.value);
2293         }
2294         ctx->va_packed_headers = ctx->desired_packed_headers & attr.value;
2295     }
2296 
2297     if (ctx->va_packed_headers) {
2298         ctx->config_attributes[ctx->nb_config_attributes++] =
2299             (VAConfigAttrib) {
2300             .type  = VAConfigAttribEncPackedHeaders,
2301             .value = ctx->va_packed_headers,
2302         };
2303     }
2304 
2305     if ( (ctx->desired_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2306         !(ctx->va_packed_headers      & VA_ENC_PACKED_HEADER_SEQUENCE) &&
2307          (avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER)) {
2308         av_log(avctx, AV_LOG_WARNING, "Driver does not support packed "
2309                "sequence headers, but a global header is requested.\n");
2310         av_log(avctx, AV_LOG_WARNING, "No global header will be written: "
2311                "this may result in a stream which is not usable for some "
2312                "purposes (e.g. not muxable to some containers).\n");
2313     }
2314 
2315     return 0;
2316 }
2317 
vaapi_encode_init_quality(AVCodecContext * avctx)2318 static av_cold int vaapi_encode_init_quality(AVCodecContext *avctx)
2319 {
2320 #if VA_CHECK_VERSION(0, 36, 0)
2321     VAAPIEncodeContext *ctx = avctx->priv_data;
2322     VAStatus vas;
2323     VAConfigAttrib attr = { VAConfigAttribEncQualityRange };
2324     int quality = avctx->compression_level;
2325 
2326     vas = vaGetConfigAttributes(ctx->hwctx->display,
2327                                 ctx->va_profile,
2328                                 ctx->va_entrypoint,
2329                                 &attr, 1);
2330     if (vas != VA_STATUS_SUCCESS) {
2331         av_log(avctx, AV_LOG_ERROR, "Failed to query quality "
2332                "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2333         return AVERROR_EXTERNAL;
2334     }
2335 
2336     if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2337         if (quality != 0) {
2338             av_log(avctx, AV_LOG_WARNING, "Quality attribute is not "
2339                    "supported: will use default quality level.\n");
2340         }
2341     } else {
2342         if (quality > attr.value) {
2343             av_log(avctx, AV_LOG_WARNING, "Invalid quality level: "
2344                    "valid range is 0-%d, using %d.\n",
2345                    attr.value, attr.value);
2346             quality = attr.value;
2347         }
2348 
2349         ctx->quality_params = (VAEncMiscParameterBufferQualityLevel) {
2350             .quality_level = quality,
2351         };
2352         vaapi_encode_add_global_param(avctx,
2353                                       VAEncMiscParameterTypeQualityLevel,
2354                                       &ctx->quality_params,
2355                                       sizeof(ctx->quality_params));
2356     }
2357 #else
2358     av_log(avctx, AV_LOG_WARNING, "The encode quality option is "
2359            "not supported with this VAAPI version.\n");
2360 #endif
2361 
2362     return 0;
2363 }
2364 
vaapi_encode_init_roi(AVCodecContext * avctx)2365 static av_cold int vaapi_encode_init_roi(AVCodecContext *avctx)
2366 {
2367 #if VA_CHECK_VERSION(1, 0, 0)
2368     VAAPIEncodeContext *ctx = avctx->priv_data;
2369     VAStatus vas;
2370     VAConfigAttrib attr = { VAConfigAttribEncROI };
2371 
2372     vas = vaGetConfigAttributes(ctx->hwctx->display,
2373                                 ctx->va_profile,
2374                                 ctx->va_entrypoint,
2375                                 &attr, 1);
2376     if (vas != VA_STATUS_SUCCESS) {
2377         av_log(avctx, AV_LOG_ERROR, "Failed to query ROI "
2378                "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
2379         return AVERROR_EXTERNAL;
2380     }
2381 
2382     if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
2383         ctx->roi_allowed = 0;
2384     } else {
2385         VAConfigAttribValEncROI roi = {
2386             .value = attr.value,
2387         };
2388 
2389         ctx->roi_max_regions = roi.bits.num_roi_regions;
2390         ctx->roi_allowed = ctx->roi_max_regions > 0 &&
2391             (ctx->va_rc_mode == VA_RC_CQP ||
2392              roi.bits.roi_rc_qp_delta_support);
2393     }
2394 #endif
2395     return 0;
2396 }
2397 
vaapi_encode_free_output_buffer(void * opaque,uint8_t * data)2398 static void vaapi_encode_free_output_buffer(void *opaque,
2399                                             uint8_t *data)
2400 {
2401     AVCodecContext   *avctx = opaque;
2402     VAAPIEncodeContext *ctx = avctx->priv_data;
2403     VABufferID buffer_id;
2404 
2405     buffer_id = (VABufferID)(uintptr_t)data;
2406 
2407     vaDestroyBuffer(ctx->hwctx->display, buffer_id);
2408 
2409     av_log(avctx, AV_LOG_DEBUG, "Freed output buffer %#x\n", buffer_id);
2410 }
2411 
vaapi_encode_alloc_output_buffer(void * opaque,size_t size)2412 static AVBufferRef *vaapi_encode_alloc_output_buffer(void *opaque,
2413                                                      size_t size)
2414 {
2415     AVCodecContext   *avctx = opaque;
2416     VAAPIEncodeContext *ctx = avctx->priv_data;
2417     VABufferID buffer_id;
2418     VAStatus vas;
2419     AVBufferRef *ref;
2420 
2421     // The output buffer size is fixed, so it needs to be large enough
2422     // to hold the largest possible compressed frame.  We assume here
2423     // that the uncompressed frame plus some header data is an upper
2424     // bound on that.
2425     vas = vaCreateBuffer(ctx->hwctx->display, ctx->va_context,
2426                          VAEncCodedBufferType,
2427                          3 * ctx->surface_width * ctx->surface_height +
2428                          (1 << 16), 1, 0, &buffer_id);
2429     if (vas != VA_STATUS_SUCCESS) {
2430         av_log(avctx, AV_LOG_ERROR, "Failed to create bitstream "
2431                "output buffer: %d (%s).\n", vas, vaErrorStr(vas));
2432         return NULL;
2433     }
2434 
2435     av_log(avctx, AV_LOG_DEBUG, "Allocated output buffer %#x\n", buffer_id);
2436 
2437     ref = av_buffer_create((uint8_t*)(uintptr_t)buffer_id,
2438                            sizeof(buffer_id),
2439                            &vaapi_encode_free_output_buffer,
2440                            avctx, AV_BUFFER_FLAG_READONLY);
2441     if (!ref) {
2442         vaDestroyBuffer(ctx->hwctx->display, buffer_id);
2443         return NULL;
2444     }
2445 
2446     return ref;
2447 }
2448 
vaapi_encode_create_recon_frames(AVCodecContext * avctx)2449 static av_cold int vaapi_encode_create_recon_frames(AVCodecContext *avctx)
2450 {
2451     VAAPIEncodeContext *ctx = avctx->priv_data;
2452     AVVAAPIHWConfig *hwconfig = NULL;
2453     AVHWFramesConstraints *constraints = NULL;
2454     enum AVPixelFormat recon_format;
2455     int err, i;
2456 
2457     hwconfig = av_hwdevice_hwconfig_alloc(ctx->device_ref);
2458     if (!hwconfig) {
2459         err = AVERROR(ENOMEM);
2460         goto fail;
2461     }
2462     hwconfig->config_id = ctx->va_config;
2463 
2464     constraints = av_hwdevice_get_hwframe_constraints(ctx->device_ref,
2465                                                       hwconfig);
2466     if (!constraints) {
2467         err = AVERROR(ENOMEM);
2468         goto fail;
2469     }
2470 
2471     // Probably we can use the input surface format as the surface format
2472     // of the reconstructed frames.  If not, we just pick the first (only?)
2473     // format in the valid list and hope that it all works.
2474     recon_format = AV_PIX_FMT_NONE;
2475     if (constraints->valid_sw_formats) {
2476         for (i = 0; constraints->valid_sw_formats[i] != AV_PIX_FMT_NONE; i++) {
2477             if (ctx->input_frames->sw_format ==
2478                 constraints->valid_sw_formats[i]) {
2479                 recon_format = ctx->input_frames->sw_format;
2480                 break;
2481             }
2482         }
2483         if (recon_format == AV_PIX_FMT_NONE) {
2484             // No match.  Just use the first in the supported list and
2485             // hope for the best.
2486             recon_format = constraints->valid_sw_formats[0];
2487         }
2488     } else {
2489         // No idea what to use; copy input format.
2490         recon_format = ctx->input_frames->sw_format;
2491     }
2492     av_log(avctx, AV_LOG_DEBUG, "Using %s as format of "
2493            "reconstructed frames.\n", av_get_pix_fmt_name(recon_format));
2494 
2495     if (ctx->surface_width  < constraints->min_width  ||
2496         ctx->surface_height < constraints->min_height ||
2497         ctx->surface_width  > constraints->max_width ||
2498         ctx->surface_height > constraints->max_height) {
2499         av_log(avctx, AV_LOG_ERROR, "Hardware does not support encoding at "
2500                "size %dx%d (constraints: width %d-%d height %d-%d).\n",
2501                ctx->surface_width, ctx->surface_height,
2502                constraints->min_width,  constraints->max_width,
2503                constraints->min_height, constraints->max_height);
2504         err = AVERROR(EINVAL);
2505         goto fail;
2506     }
2507 
2508     av_freep(&hwconfig);
2509     av_hwframe_constraints_free(&constraints);
2510 
2511     ctx->recon_frames_ref = av_hwframe_ctx_alloc(ctx->device_ref);
2512     if (!ctx->recon_frames_ref) {
2513         err = AVERROR(ENOMEM);
2514         goto fail;
2515     }
2516     ctx->recon_frames = (AVHWFramesContext*)ctx->recon_frames_ref->data;
2517 
2518     ctx->recon_frames->format    = AV_PIX_FMT_VAAPI;
2519     ctx->recon_frames->sw_format = recon_format;
2520     ctx->recon_frames->width     = ctx->surface_width;
2521     ctx->recon_frames->height    = ctx->surface_height;
2522 
2523     err = av_hwframe_ctx_init(ctx->recon_frames_ref);
2524     if (err < 0) {
2525         av_log(avctx, AV_LOG_ERROR, "Failed to initialise reconstructed "
2526                "frame context: %d.\n", err);
2527         goto fail;
2528     }
2529 
2530     err = 0;
2531   fail:
2532     av_freep(&hwconfig);
2533     av_hwframe_constraints_free(&constraints);
2534     return err;
2535 }
2536 
ff_vaapi_encode_init(AVCodecContext * avctx)2537 av_cold int ff_vaapi_encode_init(AVCodecContext *avctx)
2538 {
2539     VAAPIEncodeContext *ctx = avctx->priv_data;
2540     AVVAAPIFramesContext *recon_hwctx = NULL;
2541     VAStatus vas;
2542     int err;
2543 
2544     ctx->va_config  = VA_INVALID_ID;
2545     ctx->va_context = VA_INVALID_ID;
2546 
2547     /* If you add something that can fail above this av_frame_alloc(),
2548      * modify ff_vaapi_encode_close() accordingly. */
2549     ctx->frame = av_frame_alloc();
2550     if (!ctx->frame) {
2551         return AVERROR(ENOMEM);
2552     }
2553 
2554     if (!avctx->hw_frames_ctx) {
2555         av_log(avctx, AV_LOG_ERROR, "A hardware frames reference is "
2556                "required to associate the encoding device.\n");
2557         return AVERROR(EINVAL);
2558     }
2559 
2560     ctx->input_frames_ref = av_buffer_ref(avctx->hw_frames_ctx);
2561     if (!ctx->input_frames_ref) {
2562         err = AVERROR(ENOMEM);
2563         goto fail;
2564     }
2565     ctx->input_frames = (AVHWFramesContext*)ctx->input_frames_ref->data;
2566 
2567     ctx->device_ref = av_buffer_ref(ctx->input_frames->device_ref);
2568     if (!ctx->device_ref) {
2569         err = AVERROR(ENOMEM);
2570         goto fail;
2571     }
2572     ctx->device = (AVHWDeviceContext*)ctx->device_ref->data;
2573     ctx->hwctx = ctx->device->hwctx;
2574 
2575     err = vaapi_encode_profile_entrypoint(avctx);
2576     if (err < 0)
2577         goto fail;
2578 
2579     if (ctx->codec->get_encoder_caps) {
2580         err = ctx->codec->get_encoder_caps(avctx);
2581         if (err < 0)
2582             goto fail;
2583     } else {
2584         // Assume 16x16 blocks.
2585         ctx->surface_width  = FFALIGN(avctx->width,  16);
2586         ctx->surface_height = FFALIGN(avctx->height, 16);
2587         if (ctx->codec->flags & FLAG_SLICE_CONTROL) {
2588             ctx->slice_block_width  = 16;
2589             ctx->slice_block_height = 16;
2590         }
2591     }
2592 
2593     err = vaapi_encode_init_rate_control(avctx);
2594     if (err < 0)
2595         goto fail;
2596 
2597     err = vaapi_encode_init_gop_structure(avctx);
2598     if (err < 0)
2599         goto fail;
2600 
2601     err = vaapi_encode_init_slice_structure(avctx);
2602     if (err < 0)
2603         goto fail;
2604 
2605     err = vaapi_encode_init_packed_headers(avctx);
2606     if (err < 0)
2607         goto fail;
2608 
2609     err = vaapi_encode_init_roi(avctx);
2610     if (err < 0)
2611         goto fail;
2612 
2613     if (avctx->compression_level >= 0) {
2614         err = vaapi_encode_init_quality(avctx);
2615         if (err < 0)
2616             goto fail;
2617     }
2618 
2619     if (ctx->max_frame_size) {
2620         err = vaapi_encode_init_max_frame_size(avctx);
2621         if (err < 0)
2622             goto fail;
2623     }
2624 
2625     vas = vaCreateConfig(ctx->hwctx->display,
2626                          ctx->va_profile, ctx->va_entrypoint,
2627                          ctx->config_attributes, ctx->nb_config_attributes,
2628                          &ctx->va_config);
2629     if (vas != VA_STATUS_SUCCESS) {
2630         av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
2631                "configuration: %d (%s).\n", vas, vaErrorStr(vas));
2632         err = AVERROR(EIO);
2633         goto fail;
2634     }
2635 
2636     err = vaapi_encode_create_recon_frames(avctx);
2637     if (err < 0)
2638         goto fail;
2639 
2640     recon_hwctx = ctx->recon_frames->hwctx;
2641     vas = vaCreateContext(ctx->hwctx->display, ctx->va_config,
2642                           ctx->surface_width, ctx->surface_height,
2643                           VA_PROGRESSIVE,
2644                           recon_hwctx->surface_ids,
2645                           recon_hwctx->nb_surfaces,
2646                           &ctx->va_context);
2647     if (vas != VA_STATUS_SUCCESS) {
2648         av_log(avctx, AV_LOG_ERROR, "Failed to create encode pipeline "
2649                "context: %d (%s).\n", vas, vaErrorStr(vas));
2650         err = AVERROR(EIO);
2651         goto fail;
2652     }
2653 
2654     ctx->output_buffer_pool =
2655         av_buffer_pool_init2(sizeof(VABufferID), avctx,
2656                              &vaapi_encode_alloc_output_buffer, NULL);
2657     if (!ctx->output_buffer_pool) {
2658         err = AVERROR(ENOMEM);
2659         goto fail;
2660     }
2661 
2662     if (ctx->codec->configure) {
2663         err = ctx->codec->configure(avctx);
2664         if (err < 0)
2665             goto fail;
2666     }
2667 
2668     ctx->output_delay = ctx->b_per_p;
2669     ctx->decode_delay = ctx->max_b_depth;
2670 
2671     if (ctx->codec->sequence_params_size > 0) {
2672         ctx->codec_sequence_params =
2673             av_mallocz(ctx->codec->sequence_params_size);
2674         if (!ctx->codec_sequence_params) {
2675             err = AVERROR(ENOMEM);
2676             goto fail;
2677         }
2678     }
2679     if (ctx->codec->picture_params_size > 0) {
2680         ctx->codec_picture_params =
2681             av_mallocz(ctx->codec->picture_params_size);
2682         if (!ctx->codec_picture_params) {
2683             err = AVERROR(ENOMEM);
2684             goto fail;
2685         }
2686     }
2687 
2688     if (ctx->codec->init_sequence_params) {
2689         err = ctx->codec->init_sequence_params(avctx);
2690         if (err < 0) {
2691             av_log(avctx, AV_LOG_ERROR, "Codec sequence initialisation "
2692                    "failed: %d.\n", err);
2693             goto fail;
2694         }
2695     }
2696 
2697     if (ctx->va_packed_headers & VA_ENC_PACKED_HEADER_SEQUENCE &&
2698         ctx->codec->write_sequence_header &&
2699         avctx->flags & AV_CODEC_FLAG_GLOBAL_HEADER) {
2700         char data[MAX_PARAM_BUFFER_SIZE];
2701         size_t bit_len = 8 * sizeof(data);
2702 
2703         err = ctx->codec->write_sequence_header(avctx, data, &bit_len);
2704         if (err < 0) {
2705             av_log(avctx, AV_LOG_ERROR, "Failed to write sequence header "
2706                    "for extradata: %d.\n", err);
2707             goto fail;
2708         } else {
2709             avctx->extradata_size = (bit_len + 7) / 8;
2710             avctx->extradata = av_mallocz(avctx->extradata_size +
2711                                           AV_INPUT_BUFFER_PADDING_SIZE);
2712             if (!avctx->extradata) {
2713                 err = AVERROR(ENOMEM);
2714                 goto fail;
2715             }
2716             memcpy(avctx->extradata, data, avctx->extradata_size);
2717         }
2718     }
2719 
2720 #if VA_CHECK_VERSION(1, 9, 0)
2721     // check vaSyncBuffer function
2722     vas = vaSyncBuffer(ctx->hwctx->display, VA_INVALID_ID, 0);
2723     if (vas != VA_STATUS_ERROR_UNIMPLEMENTED) {
2724         ctx->has_sync_buffer_func = 1;
2725         ctx->encode_fifo = av_fifo_alloc2(ctx->async_depth,
2726                                           sizeof(VAAPIEncodePicture *),
2727                                           0);
2728         if (!ctx->encode_fifo)
2729             return AVERROR(ENOMEM);
2730     }
2731 #endif
2732 
2733     return 0;
2734 
2735 fail:
2736     return err;
2737 }
2738 
ff_vaapi_encode_close(AVCodecContext * avctx)2739 av_cold int ff_vaapi_encode_close(AVCodecContext *avctx)
2740 {
2741     VAAPIEncodeContext *ctx = avctx->priv_data;
2742     VAAPIEncodePicture *pic, *next;
2743 
2744     /* We check ctx->frame to know whether ff_vaapi_encode_init()
2745      * has been called and va_config/va_context initialized. */
2746     if (!ctx->frame)
2747         return 0;
2748 
2749     for (pic = ctx->pic_start; pic; pic = next) {
2750         next = pic->next;
2751         vaapi_encode_free(avctx, pic);
2752     }
2753 
2754     av_buffer_pool_uninit(&ctx->output_buffer_pool);
2755 
2756     if (ctx->va_context != VA_INVALID_ID) {
2757         if (ctx->hwctx)
2758             vaDestroyContext(ctx->hwctx->display, ctx->va_context);
2759         ctx->va_context = VA_INVALID_ID;
2760     }
2761 
2762     if (ctx->va_config != VA_INVALID_ID) {
2763         if (ctx->hwctx)
2764             vaDestroyConfig(ctx->hwctx->display, ctx->va_config);
2765         ctx->va_config = VA_INVALID_ID;
2766     }
2767 
2768     av_frame_free(&ctx->frame);
2769 
2770     av_freep(&ctx->codec_sequence_params);
2771     av_freep(&ctx->codec_picture_params);
2772     av_fifo_freep2(&ctx->encode_fifo);
2773 
2774     av_buffer_unref(&ctx->recon_frames_ref);
2775     av_buffer_unref(&ctx->input_frames_ref);
2776     av_buffer_unref(&ctx->device_ref);
2777 
2778     return 0;
2779 }
2780