FFmpeg coverage


Directory: ../../../ffmpeg/
File: src/libavcodec/vaapi_encode_av1.c
Date: 2024-05-04 02:01:39
Exec Total Coverage
Lines: 0 461 0.0%
Functions: 0 14 0.0%
Branches: 0 203 0.0%

Line Branch Exec Source
1 /*
2 * Copyright (c) 2023 Intel Corporation
3 *
4 * This file is part of FFmpeg.
5 *
6 * FFmpeg is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
10 *
11 * FFmpeg is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 *
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with FFmpeg; if not, write to the Free Software
18 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 */
20
21 #include <va/va.h>
22 #include <va/va_enc_av1.h>
23
24 #include "libavutil/pixdesc.h"
25 #include "libavutil/opt.h"
26
27 #include "cbs_av1.h"
28 #include "put_bits.h"
29 #include "codec_internal.h"
30 #include "av1_levels.h"
31 #include "vaapi_encode.h"
32
33 #define AV1_MAX_QUANT 255
34
35 typedef struct VAAPIEncodeAV1Picture {
36 int64_t last_idr_frame;
37 int slot;
38 } VAAPIEncodeAV1Picture;
39
40 typedef struct VAAPIEncodeAV1Context {
41 VAAPIEncodeContext common;
42 AV1RawOBU sh; /**< sequence header.*/
43 AV1RawOBU fh; /**< frame header.*/
44 CodedBitstreamContext *cbc;
45 CodedBitstreamFragment current_obu;
46 VAConfigAttribValEncAV1 attr;
47 VAConfigAttribValEncAV1Ext1 attr_ext1;
48 VAConfigAttribValEncAV1Ext2 attr_ext2;
49
50 char sh_data[MAX_PARAM_BUFFER_SIZE]; /**< coded sequence header data. */
51 size_t sh_data_len; /**< bit length of sh_data. */
52 char fh_data[MAX_PARAM_BUFFER_SIZE]; /**< coded frame header data. */
53 size_t fh_data_len; /**< bit length of fh_data. */
54
55 uint8_t uniform_tile;
56 uint8_t use_128x128_superblock;
57 int sb_cols;
58 int sb_rows;
59 int tile_cols_log2;
60 int tile_rows_log2;
61 int max_tile_width_sb;
62 int max_tile_height_sb;
63 uint8_t width_in_sbs_minus_1[AV1_MAX_TILE_COLS];
64 uint8_t height_in_sbs_minus_1[AV1_MAX_TILE_ROWS];
65
66 int min_log2_tile_cols;
67 int max_log2_tile_cols;
68 int min_log2_tile_rows;
69 int max_log2_tile_rows;
70
71 int q_idx_idr;
72 int q_idx_p;
73 int q_idx_b;
74
75 /** bit positions in current frame header */
76 int qindex_offset;
77 int loopfilter_offset;
78 int cdef_start_offset;
79 int cdef_param_size;
80
81 /** user options */
82 int profile;
83 int level;
84 int tier;
85 int tile_cols, tile_rows;
86 int tile_groups;
87 } VAAPIEncodeAV1Context;
88
89 static void vaapi_encode_av1_trace_write_log(void *ctx,
90 PutBitContext *pbc, int length,
91 const char *str, const int *subscripts,
92 int64_t value)
93 {
94 VAAPIEncodeAV1Context *priv = ctx;
95 int position;
96
97 position = put_bits_count(pbc);
98 av_assert0(position >= length);
99
100 if (!strcmp(str, "base_q_idx"))
101 priv->qindex_offset = position - length;
102 else if (!strcmp(str, "loop_filter_level[0]"))
103 priv->loopfilter_offset = position - length;
104 else if (!strcmp(str, "cdef_damping_minus_3"))
105 priv->cdef_start_offset = position - length;
106 else if (!strcmp(str, "cdef_uv_sec_strength[i]"))
107 priv->cdef_param_size = position - priv->cdef_start_offset;
108 }
109
110 static av_cold int vaapi_encode_av1_get_encoder_caps(AVCodecContext *avctx)
111 {
112 VAAPIEncodeContext *ctx = avctx->priv_data;
113 VAAPIEncodeAV1Context *priv = avctx->priv_data;
114
115 // Surfaces must be aligned to superblock boundaries.
116 ctx->surface_width = FFALIGN(avctx->width, priv->use_128x128_superblock ? 128 : 64);
117 ctx->surface_height = FFALIGN(avctx->height, priv->use_128x128_superblock ? 128 : 64);
118
119 return 0;
120 }
121
122 static av_cold int vaapi_encode_av1_configure(AVCodecContext *avctx)
123 {
124 VAAPIEncodeContext *ctx = avctx->priv_data;
125 VAAPIEncodeAV1Context *priv = avctx->priv_data;
126 int ret;
127
128 ret = ff_cbs_init(&priv->cbc, AV_CODEC_ID_AV1, avctx);
129 if (ret < 0)
130 return ret;
131 priv->cbc->trace_enable = 1;
132 priv->cbc->trace_level = AV_LOG_DEBUG;
133 priv->cbc->trace_context = ctx;
134 priv->cbc->trace_write_callback = vaapi_encode_av1_trace_write_log;
135
136 if (ctx->rc_mode->quality) {
137 priv->q_idx_p = av_clip(ctx->rc_quality, 0, AV1_MAX_QUANT);
138 if (fabs(avctx->i_quant_factor) > 0.0)
139 priv->q_idx_idr =
140 av_clip((fabs(avctx->i_quant_factor) * priv->q_idx_p +
141 avctx->i_quant_offset) + 0.5,
142 0, AV1_MAX_QUANT);
143 else
144 priv->q_idx_idr = priv->q_idx_p;
145
146 if (fabs(avctx->b_quant_factor) > 0.0)
147 priv->q_idx_b =
148 av_clip((fabs(avctx->b_quant_factor) * priv->q_idx_p +
149 avctx->b_quant_offset) + 0.5,
150 0, AV1_MAX_QUANT);
151 else
152 priv->q_idx_b = priv->q_idx_p;
153 } else {
154 /** Arbitrary value */
155 priv->q_idx_idr = priv->q_idx_p = priv->q_idx_b = 128;
156 }
157
158 ctx->roi_quant_range = AV1_MAX_QUANT;
159
160 return 0;
161 }
162
163 static int vaapi_encode_av1_add_obu(AVCodecContext *avctx,
164 CodedBitstreamFragment *au,
165 uint8_t type,
166 void *obu_unit)
167 {
168 int ret;
169
170 ret = ff_cbs_insert_unit_content(au, -1,
171 type, obu_unit, NULL);
172 if (ret < 0) {
173 av_log(avctx, AV_LOG_ERROR, "Failed to add OBU unit: "
174 "type = %d.\n", type);
175 return ret;
176 }
177
178 return 0;
179 }
180
181 static int vaapi_encode_av1_write_obu(AVCodecContext *avctx,
182 char *data, size_t *data_len,
183 CodedBitstreamFragment *bs)
184 {
185 VAAPIEncodeAV1Context *priv = avctx->priv_data;
186 int ret;
187
188 ret = ff_cbs_write_fragment_data(priv->cbc, bs);
189 if (ret < 0) {
190 av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
191 return ret;
192 }
193
194 if ((size_t)8 * MAX_PARAM_BUFFER_SIZE < 8 * bs->data_size - bs->data_bit_padding) {
195 av_log(avctx, AV_LOG_ERROR, "Access unit too large: "
196 "%zu < %zu.\n", (size_t)8 * MAX_PARAM_BUFFER_SIZE,
197 8 * bs->data_size - bs->data_bit_padding);
198 return AVERROR(ENOSPC);
199 }
200
201 memcpy(data, bs->data, bs->data_size);
202 *data_len = 8 * bs->data_size - bs->data_bit_padding;
203
204 return 0;
205 }
206
207 static int tile_log2(int blkSize, int target) {
208 int k;
209 for (k = 0; (blkSize << k) < target; k++);
210 return k;
211 }
212
213 static int vaapi_encode_av1_set_tile(AVCodecContext *avctx)
214 {
215 VAAPIEncodeAV1Context *priv = avctx->priv_data;
216 int mi_cols, mi_rows, sb_shift, sb_size;
217 int max_tile_area_sb, max_tile_area_sb_varied;
218 int tile_width_sb, tile_height_sb, widest_tile_sb;
219 int tile_cols, tile_rows;
220 int min_log2_tiles;
221 int i;
222
223 if (priv->tile_cols > AV1_MAX_TILE_COLS ||
224 priv->tile_rows > AV1_MAX_TILE_ROWS) {
225 av_log(avctx, AV_LOG_ERROR, "Invalid tile number %dx%d, should less than %dx%d.\n",
226 priv->tile_cols, priv->tile_rows, AV1_MAX_TILE_COLS, AV1_MAX_TILE_ROWS);
227 return AVERROR(EINVAL);
228 }
229
230 mi_cols = 2 * ((avctx->width + 7) >> 3);
231 mi_rows = 2 * ((avctx->height + 7) >> 3);
232 priv->sb_cols = priv->use_128x128_superblock ?
233 ((mi_cols + 31) >> 5) : ((mi_cols + 15) >> 4);
234 priv->sb_rows = priv->use_128x128_superblock ?
235 ((mi_rows + 31) >> 5) : ((mi_rows + 15) >> 4);
236 sb_shift = priv->use_128x128_superblock ? 5 : 4;
237 sb_size = sb_shift + 2;
238 priv->max_tile_width_sb = AV1_MAX_TILE_WIDTH >> sb_size;
239 max_tile_area_sb = AV1_MAX_TILE_AREA >> (2 * sb_size);
240
241 priv->min_log2_tile_cols = tile_log2(priv->max_tile_width_sb, priv->sb_cols);
242 priv->max_log2_tile_cols = tile_log2(1, FFMIN(priv->sb_cols, AV1_MAX_TILE_COLS));
243 priv->max_log2_tile_rows = tile_log2(1, FFMIN(priv->sb_rows, AV1_MAX_TILE_ROWS));
244 min_log2_tiles = FFMAX(priv->min_log2_tile_cols,
245 tile_log2(max_tile_area_sb, priv->sb_rows * priv->sb_cols));
246
247 tile_cols = av_clip(priv->tile_cols, (priv->sb_cols + priv->max_tile_width_sb - 1) / priv->max_tile_width_sb, priv->sb_cols);
248
249 if (!priv->tile_cols)
250 priv->tile_cols = tile_cols;
251 else if (priv->tile_cols != tile_cols){
252 av_log(avctx, AV_LOG_ERROR, "Invalid tile cols %d, should be in range of %d~%d\n",
253 priv->tile_cols,
254 (priv->sb_cols + priv->max_tile_width_sb - 1) / priv->max_tile_width_sb,
255 priv->sb_cols);
256 return AVERROR(EINVAL);
257 }
258
259 priv->tile_cols_log2 = tile_log2(1, priv->tile_cols);
260 tile_width_sb = (priv->sb_cols + (1 << priv->tile_cols_log2) - 1) >>
261 priv->tile_cols_log2;
262
263 if (priv->tile_rows > priv->sb_rows) {
264 av_log(avctx, AV_LOG_ERROR, "Invalid tile rows %d, should be less than %d.\n",
265 priv->tile_rows, priv->sb_rows);
266 return AVERROR(EINVAL);
267 }
268
269 /** Try user setting tile rows number first. */
270 tile_rows = priv->tile_rows ? priv->tile_rows : 1;
271 for (; tile_rows <= priv->sb_rows && tile_rows <= AV1_MAX_TILE_ROWS; tile_rows++) {
272 /** try uniformed tile. */
273 priv->tile_rows_log2 = tile_log2(1, tile_rows);
274 if ((priv->sb_cols + tile_width_sb - 1) / tile_width_sb == priv->tile_cols) {
275 for (i = 0; i < priv->tile_cols - 1; i++)
276 priv->width_in_sbs_minus_1[i] = tile_width_sb - 1;
277 priv->width_in_sbs_minus_1[i] = priv->sb_cols - (priv->tile_cols - 1) * tile_width_sb - 1;
278
279 tile_height_sb = (priv->sb_rows + (1 << priv->tile_rows_log2) - 1) >>
280 priv->tile_rows_log2;
281
282 if ((priv->sb_rows + tile_height_sb - 1) / tile_height_sb == tile_rows &&
283 tile_height_sb <= max_tile_area_sb / tile_width_sb) {
284 for (i = 0; i < tile_rows - 1; i++)
285 priv->height_in_sbs_minus_1[i] = tile_height_sb - 1;
286 priv->height_in_sbs_minus_1[i] = priv->sb_rows - (tile_rows - 1) * tile_height_sb - 1;
287
288 priv->uniform_tile = 1;
289 priv->min_log2_tile_rows = FFMAX(min_log2_tiles - priv->tile_cols_log2, 0);
290
291 break;
292 }
293 }
294
295 /** try non-uniformed tile. */
296 widest_tile_sb = 0;
297 for (i = 0; i < priv->tile_cols; i++) {
298 priv->width_in_sbs_minus_1[i] = (i + 1) * priv->sb_cols / priv->tile_cols - i * priv->sb_cols / priv->tile_cols - 1;
299 widest_tile_sb = FFMAX(widest_tile_sb, priv->width_in_sbs_minus_1[i] + 1);
300 }
301
302 if (min_log2_tiles)
303 max_tile_area_sb_varied = (priv->sb_rows * priv->sb_cols) >> (min_log2_tiles + 1);
304 else
305 max_tile_area_sb_varied = priv->sb_rows * priv->sb_cols;
306 priv->max_tile_height_sb = FFMAX(1, max_tile_area_sb_varied / widest_tile_sb);
307
308 if (tile_rows == av_clip(tile_rows, (priv->sb_rows + priv->max_tile_height_sb - 1) / priv->max_tile_height_sb, priv->sb_rows)) {
309 for (i = 0; i < tile_rows; i++)
310 priv->height_in_sbs_minus_1[i] = (i + 1) * priv->sb_rows / tile_rows - i * priv->sb_rows / tile_rows - 1;
311
312 break;
313 }
314
315 /** Return invalid parameter if explicit tile rows is set. */
316 if (priv->tile_rows) {
317 av_log(avctx, AV_LOG_ERROR, "Invalid tile rows %d.\n", priv->tile_rows);
318 return AVERROR(EINVAL);
319 }
320 }
321
322 priv->tile_rows = tile_rows;
323 av_log(avctx, AV_LOG_DEBUG, "Setting tile cols/rows to %d/%d.\n",
324 priv->tile_cols, priv->tile_rows);
325
326 /** check if tile cols/rows is supported by driver. */
327 if (priv->attr_ext2.bits.max_tile_num_minus1) {
328 if ((priv->tile_cols * priv->tile_rows - 1) > priv->attr_ext2.bits.max_tile_num_minus1) {
329 av_log(avctx, AV_LOG_ERROR, "Unsupported tile num %d * %d = %d by driver, "
330 "should be at most %d.\n", priv->tile_cols, priv->tile_rows,
331 priv->tile_cols * priv->tile_rows,
332 priv->attr_ext2.bits.max_tile_num_minus1 + 1);
333 return AVERROR(EINVAL);
334 }
335 }
336
337 /** check if tile group numbers is valid. */
338 if (priv->tile_groups > priv->tile_cols * priv->tile_rows) {
339 av_log(avctx, AV_LOG_WARNING, "Invalid tile groups number %d, "
340 "correct to %d.\n", priv->tile_groups, priv->tile_cols * priv->tile_rows);
341 priv->tile_groups = priv->tile_cols * priv->tile_rows;
342 }
343
344 return 0;
345 }
346
347 static int vaapi_encode_av1_write_sequence_header(AVCodecContext *avctx,
348 char *data, size_t *data_len)
349 {
350 VAAPIEncodeAV1Context *priv = avctx->priv_data;
351
352 memcpy(data, &priv->sh_data, MAX_PARAM_BUFFER_SIZE * sizeof(char));
353 *data_len = priv->sh_data_len;
354
355 return 0;
356 }
357
358 static int vaapi_encode_av1_init_sequence_params(AVCodecContext *avctx)
359 {
360 VAAPIEncodeContext *ctx = avctx->priv_data;
361 VAAPIEncodeAV1Context *priv = avctx->priv_data;
362 AV1RawOBU *sh_obu = &priv->sh;
363 AV1RawSequenceHeader *sh = &sh_obu->obu.sequence_header;
364 VAEncSequenceParameterBufferAV1 *vseq = ctx->codec_sequence_params;
365 CodedBitstreamFragment *obu = &priv->current_obu;
366 const AVPixFmtDescriptor *desc;
367 int ret;
368
369 memset(sh_obu, 0, sizeof(*sh_obu));
370 sh_obu->header.obu_type = AV1_OBU_SEQUENCE_HEADER;
371
372 desc = av_pix_fmt_desc_get(priv->common.input_frames->sw_format);
373 av_assert0(desc);
374
375 sh->seq_profile = avctx->profile;
376 if (!sh->seq_force_screen_content_tools)
377 sh->seq_force_integer_mv = AV1_SELECT_INTEGER_MV;
378 sh->frame_width_bits_minus_1 = av_log2(avctx->width);
379 sh->frame_height_bits_minus_1 = av_log2(avctx->height);
380 sh->max_frame_width_minus_1 = avctx->width - 1;
381 sh->max_frame_height_minus_1 = avctx->height - 1;
382 sh->seq_tier[0] = priv->tier;
383 /** enable order hint and reserve maximum 8 bits for it by default. */
384 sh->enable_order_hint = 1;
385 sh->order_hint_bits_minus_1 = 7;
386
387 sh->color_config = (AV1RawColorConfig) {
388 .high_bitdepth = desc->comp[0].depth == 8 ? 0 : 1,
389 .color_primaries = avctx->color_primaries,
390 .transfer_characteristics = avctx->color_trc,
391 .matrix_coefficients = avctx->colorspace,
392 .color_description_present_flag = (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
393 avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
394 avctx->colorspace != AVCOL_SPC_UNSPECIFIED),
395 .color_range = avctx->color_range == AVCOL_RANGE_JPEG,
396 .subsampling_x = desc->log2_chroma_w,
397 .subsampling_y = desc->log2_chroma_h,
398 };
399
400 switch (avctx->chroma_sample_location) {
401 case AVCHROMA_LOC_LEFT:
402 sh->color_config.chroma_sample_position = AV1_CSP_VERTICAL;
403 break;
404 case AVCHROMA_LOC_TOPLEFT:
405 sh->color_config.chroma_sample_position = AV1_CSP_COLOCATED;
406 break;
407 default:
408 sh->color_config.chroma_sample_position = AV1_CSP_UNKNOWN;
409 break;
410 }
411
412 if (avctx->level != AV_LEVEL_UNKNOWN) {
413 sh->seq_level_idx[0] = avctx->level;
414 } else {
415 const AV1LevelDescriptor *level;
416 float framerate;
417
418 if (avctx->framerate.num > 0 && avctx->framerate.den > 0)
419 framerate = avctx->framerate.num / avctx->framerate.den;
420 else
421 framerate = 0;
422
423 level = ff_av1_guess_level(avctx->bit_rate, priv->tier,
424 ctx->surface_width, ctx->surface_height,
425 priv->tile_rows * priv->tile_cols,
426 priv->tile_cols, framerate);
427 if (level) {
428 av_log(avctx, AV_LOG_VERBOSE, "Using level %s.\n", level->name);
429 sh->seq_level_idx[0] = level->level_idx;
430 } else {
431 av_log(avctx, AV_LOG_VERBOSE, "Stream will not conform to "
432 "any normal level, using maximum parameters level by default.\n");
433 sh->seq_level_idx[0] = 31;
434 sh->seq_tier[0] = 1;
435 }
436 }
437 vseq->seq_profile = sh->seq_profile;
438 vseq->seq_level_idx = sh->seq_level_idx[0];
439 vseq->seq_tier = sh->seq_tier[0];
440 vseq->order_hint_bits_minus_1 = sh->order_hint_bits_minus_1;
441 vseq->intra_period = ctx->gop_size;
442 vseq->ip_period = ctx->b_per_p + 1;
443
444 vseq->seq_fields.bits.enable_order_hint = sh->enable_order_hint;
445
446 if (!(ctx->va_rc_mode & VA_RC_CQP)) {
447 vseq->bits_per_second = ctx->va_bit_rate;
448 vseq->seq_fields.bits.enable_cdef = sh->enable_cdef = 1;
449 }
450
451 ret = vaapi_encode_av1_add_obu(avctx, obu, AV1_OBU_SEQUENCE_HEADER, &priv->sh);
452 if (ret < 0)
453 goto end;
454
455 ret = vaapi_encode_av1_write_obu(avctx, priv->sh_data, &priv->sh_data_len, obu);
456 if (ret < 0)
457 goto end;
458
459 end:
460 ff_cbs_fragment_reset(obu);
461 return ret;
462 }
463
464 static int vaapi_encode_av1_init_picture_params(AVCodecContext *avctx,
465 VAAPIEncodePicture *pic)
466 {
467 VAAPIEncodeContext *ctx = avctx->priv_data;
468 VAAPIEncodeAV1Context *priv = avctx->priv_data;
469 VAAPIEncodeAV1Picture *hpic = pic->priv_data;
470 AV1RawOBU *fh_obu = &priv->fh;
471 AV1RawFrameHeader *fh = &fh_obu->obu.frame.header;
472 VAEncPictureParameterBufferAV1 *vpic = pic->codec_picture_params;
473 CodedBitstreamFragment *obu = &priv->current_obu;
474 VAAPIEncodePicture *ref;
475 VAAPIEncodeAV1Picture *href;
476 int slot, i;
477 int ret;
478 static const int8_t default_loop_filter_ref_deltas[AV1_TOTAL_REFS_PER_FRAME] =
479 { 1, 0, 0, 0, -1, 0, -1, -1 };
480
481 memset(fh_obu, 0, sizeof(*fh_obu));
482 pic->nb_slices = priv->tile_groups;
483 pic->non_independent_frame = pic->encode_order < pic->display_order;
484 fh_obu->header.obu_type = AV1_OBU_FRAME_HEADER;
485 fh_obu->header.obu_has_size_field = 1;
486
487 switch (pic->type) {
488 case PICTURE_TYPE_IDR:
489 av_assert0(pic->nb_refs[0] == 0 || pic->nb_refs[1]);
490 fh->frame_type = AV1_FRAME_KEY;
491 fh->refresh_frame_flags = 0xFF;
492 fh->base_q_idx = priv->q_idx_idr;
493 hpic->slot = 0;
494 hpic->last_idr_frame = pic->display_order;
495 break;
496 case PICTURE_TYPE_P:
497 av_assert0(pic->nb_refs[0]);
498 fh->frame_type = AV1_FRAME_INTER;
499 fh->base_q_idx = priv->q_idx_p;
500 ref = pic->refs[0][pic->nb_refs[0] - 1];
501 href = ref->priv_data;
502 hpic->slot = !href->slot;
503 hpic->last_idr_frame = href->last_idr_frame;
504 fh->refresh_frame_flags = 1 << hpic->slot;
505
506 /** set the nearest frame in L0 as all reference frame. */
507 for (i = 0; i < AV1_REFS_PER_FRAME; i++) {
508 fh->ref_frame_idx[i] = href->slot;
509 }
510 fh->primary_ref_frame = href->slot;
511 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
512 vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
513
514 /** set the 2nd nearest frame in L0 as Golden frame. */
515 if (pic->nb_refs[0] > 1) {
516 ref = pic->refs[0][pic->nb_refs[0] - 2];
517 href = ref->priv_data;
518 fh->ref_frame_idx[3] = href->slot;
519 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
520 vpic->ref_frame_ctrl_l0.fields.search_idx1 = AV1_REF_FRAME_GOLDEN;
521 }
522 break;
523 case PICTURE_TYPE_B:
524 av_assert0(pic->nb_refs[0] && pic->nb_refs[1]);
525 fh->frame_type = AV1_FRAME_INTER;
526 fh->base_q_idx = priv->q_idx_b;
527 fh->refresh_frame_flags = 0x0;
528 fh->reference_select = 1;
529
530 /** B frame will not be referenced, disable its recon frame. */
531 vpic->picture_flags.bits.disable_frame_recon = 1;
532
533 /** Use LAST_FRAME and BWDREF_FRAME for reference. */
534 vpic->ref_frame_ctrl_l0.fields.search_idx0 = AV1_REF_FRAME_LAST;
535 vpic->ref_frame_ctrl_l1.fields.search_idx0 = AV1_REF_FRAME_BWDREF;
536
537 ref = pic->refs[0][pic->nb_refs[0] - 1];
538 href = ref->priv_data;
539 hpic->last_idr_frame = href->last_idr_frame;
540 fh->primary_ref_frame = href->slot;
541 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
542 for (i = 0; i < AV1_REF_FRAME_GOLDEN; i++) {
543 fh->ref_frame_idx[i] = href->slot;
544 }
545
546 ref = pic->refs[1][pic->nb_refs[1] - 1];
547 href = ref->priv_data;
548 fh->ref_order_hint[href->slot] = ref->display_order - href->last_idr_frame;
549 for (i = AV1_REF_FRAME_GOLDEN; i < AV1_REFS_PER_FRAME; i++) {
550 fh->ref_frame_idx[i] = href->slot;
551 }
552 break;
553 default:
554 av_assert0(0 && "invalid picture type");
555 }
556
557 fh->show_frame = pic->display_order <= pic->encode_order;
558 fh->showable_frame = fh->frame_type != AV1_FRAME_KEY;
559 fh->frame_width_minus_1 = avctx->width - 1;
560 fh->frame_height_minus_1 = avctx->height - 1;
561 fh->render_width_minus_1 = fh->frame_width_minus_1;
562 fh->render_height_minus_1 = fh->frame_height_minus_1;
563 fh->order_hint = pic->display_order - hpic->last_idr_frame;
564 fh->tile_cols = priv->tile_cols;
565 fh->tile_rows = priv->tile_rows;
566 fh->tile_cols_log2 = priv->tile_cols_log2;
567 fh->tile_rows_log2 = priv->tile_rows_log2;
568 fh->uniform_tile_spacing_flag = priv->uniform_tile;
569 fh->tile_size_bytes_minus1 = priv->attr_ext2.bits.tile_size_bytes_minus1;
570
571 /** ignore ONLY_4x4 mode for codedlossless is not fully implemented. */
572 if (priv->attr_ext2.bits.tx_mode_support & 0x04)
573 fh->tx_mode = AV1_TX_MODE_SELECT;
574 else if (priv->attr_ext2.bits.tx_mode_support & 0x02)
575 fh->tx_mode = AV1_TX_MODE_LARGEST;
576 else {
577 av_log(avctx, AV_LOG_ERROR, "No available tx mode found.\n");
578 return AVERROR(EINVAL);
579 }
580
581 for (i = 0; i < fh->tile_cols; i++)
582 fh->width_in_sbs_minus_1[i] = vpic->width_in_sbs_minus_1[i] = priv->width_in_sbs_minus_1[i];
583
584 for (i = 0; i < fh->tile_rows; i++)
585 fh->height_in_sbs_minus_1[i] = vpic->height_in_sbs_minus_1[i] = priv->height_in_sbs_minus_1[i];
586
587 memcpy(fh->loop_filter_ref_deltas, default_loop_filter_ref_deltas,
588 AV1_TOTAL_REFS_PER_FRAME * sizeof(int8_t));
589
590 if (fh->frame_type == AV1_FRAME_KEY && fh->show_frame) {
591 fh->error_resilient_mode = 1;
592 }
593
594 if (fh->frame_type == AV1_FRAME_KEY || fh->error_resilient_mode)
595 fh->primary_ref_frame = AV1_PRIMARY_REF_NONE;
596
597 vpic->base_qindex = fh->base_q_idx;
598 vpic->frame_width_minus_1 = fh->frame_width_minus_1;
599 vpic->frame_height_minus_1 = fh->frame_height_minus_1;
600 vpic->primary_ref_frame = fh->primary_ref_frame;
601 vpic->reconstructed_frame = pic->recon_surface;
602 vpic->coded_buf = pic->output_buffer;
603 vpic->tile_cols = fh->tile_cols;
604 vpic->tile_rows = fh->tile_rows;
605 vpic->order_hint = fh->order_hint;
606 #if VA_CHECK_VERSION(1, 15, 0)
607 vpic->refresh_frame_flags = fh->refresh_frame_flags;
608 #endif
609
610 vpic->picture_flags.bits.enable_frame_obu = 0;
611 vpic->picture_flags.bits.frame_type = fh->frame_type;
612 vpic->picture_flags.bits.reduced_tx_set = fh->reduced_tx_set;
613 vpic->picture_flags.bits.error_resilient_mode = fh->error_resilient_mode;
614
615 /** let driver decide to use single or compound reference prediction mode. */
616 vpic->mode_control_flags.bits.reference_mode = fh->reference_select ? 2 : 0;
617 vpic->mode_control_flags.bits.tx_mode = fh->tx_mode;
618
619 vpic->tile_group_obu_hdr_info.bits.obu_has_size_field = 1;
620
621 /** set reference. */
622 for (i = 0; i < AV1_REFS_PER_FRAME; i++)
623 vpic->ref_frame_idx[i] = fh->ref_frame_idx[i];
624
625 for (i = 0; i < FF_ARRAY_ELEMS(vpic->reference_frames); i++)
626 vpic->reference_frames[i] = VA_INVALID_SURFACE;
627
628 for (i = 0; i < MAX_REFERENCE_LIST_NUM; i++) {
629 for (int j = 0; j < pic->nb_refs[i]; j++) {
630 VAAPIEncodePicture *ref_pic = pic->refs[i][j];
631
632 slot = ((VAAPIEncodeAV1Picture*)ref_pic->priv_data)->slot;
633 av_assert0(vpic->reference_frames[slot] == VA_INVALID_SURFACE);
634
635 vpic->reference_frames[slot] = ref_pic->recon_surface;
636 }
637 }
638
639 ret = vaapi_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER, &priv->fh);
640 if (ret < 0)
641 goto end;
642
643 ret = vaapi_encode_av1_write_obu(avctx, priv->fh_data, &priv->fh_data_len, obu);
644 if (ret < 0)
645 goto end;
646
647 if (!(ctx->va_rc_mode & VA_RC_CQP)) {
648 vpic->min_base_qindex = av_clip(avctx->qmin, 1, AV1_MAX_QUANT);
649 vpic->max_base_qindex = av_clip(avctx->qmax, 1, AV1_MAX_QUANT);
650
651 vpic->bit_offset_qindex = priv->qindex_offset;
652 vpic->bit_offset_loopfilter_params = priv->loopfilter_offset;
653 vpic->bit_offset_cdef_params = priv->cdef_start_offset;
654 vpic->size_in_bits_cdef_params = priv->cdef_param_size;
655 vpic->size_in_bits_frame_hdr_obu = priv->fh_data_len;
656 vpic->byte_offset_frame_hdr_obu_size = (((pic->type == PICTURE_TYPE_IDR) ?
657 priv->sh_data_len / 8 : 0) +
658 (fh_obu->header.obu_extension_flag ?
659 2 : 1));
660 }
661
662 end:
663 ff_cbs_fragment_reset(obu);
664 return ret;
665 }
666
667 static int vaapi_encode_av1_init_slice_params(AVCodecContext *avctx,
668 VAAPIEncodePicture *pic,
669 VAAPIEncodeSlice *slice)
670 {
671 VAAPIEncodeAV1Context *priv = avctx->priv_data;
672 VAEncTileGroupBufferAV1 *vslice = slice->codec_slice_params;
673 CodedBitstreamAV1Context *cbctx = priv->cbc->priv_data;
674 int div;
675
676 /** Set tile group info. */
677 div = priv->tile_cols * priv->tile_rows / priv->tile_groups;
678 vslice->tg_start = slice->index * div;
679 if (slice->index == (priv->tile_groups - 1)) {
680 vslice->tg_end = priv->tile_cols * priv->tile_rows - 1;
681 cbctx->seen_frame_header = 0;
682 } else {
683 vslice->tg_end = (slice->index + 1) * div - 1;
684 }
685
686 return 0;
687 }
688
689 static int vaapi_encode_av1_write_picture_header(AVCodecContext *avctx,
690 VAAPIEncodePicture *pic,
691 char *data, size_t *data_len)
692 {
693 VAAPIEncodeAV1Context *priv = avctx->priv_data;
694 CodedBitstreamFragment *obu = &priv->current_obu;
695 CodedBitstreamAV1Context *cbctx = priv->cbc->priv_data;
696 AV1RawOBU *fh_obu = &priv->fh;
697 AV1RawFrameHeader *rep_fh = &fh_obu->obu.frame_header;
698 VAAPIEncodeAV1Picture *href;
699 int ret = 0;
700
701 pic->tail_size = 0;
702 /** Pack repeat frame header. */
703 if (pic->display_order > pic->encode_order) {
704 memset(fh_obu, 0, sizeof(*fh_obu));
705 href = pic->refs[0][pic->nb_refs[0] - 1]->priv_data;
706 fh_obu->header.obu_type = AV1_OBU_FRAME_HEADER;
707 fh_obu->header.obu_has_size_field = 1;
708
709 rep_fh->show_existing_frame = 1;
710 rep_fh->frame_to_show_map_idx = href->slot == 0;
711 rep_fh->frame_type = AV1_FRAME_INTER;
712 rep_fh->frame_width_minus_1 = avctx->width - 1;
713 rep_fh->frame_height_minus_1 = avctx->height - 1;
714 rep_fh->render_width_minus_1 = rep_fh->frame_width_minus_1;
715 rep_fh->render_height_minus_1 = rep_fh->frame_height_minus_1;
716
717 cbctx->seen_frame_header = 0;
718
719 ret = vaapi_encode_av1_add_obu(avctx, obu, AV1_OBU_FRAME_HEADER, &priv->fh);
720 if (ret < 0)
721 goto end;
722
723 ret = vaapi_encode_av1_write_obu(avctx, pic->tail_data, &pic->tail_size, obu);
724 if (ret < 0)
725 goto end;
726
727 pic->tail_size /= 8;
728 }
729
730 memcpy(data, &priv->fh_data, MAX_PARAM_BUFFER_SIZE * sizeof(char));
731 *data_len = priv->fh_data_len;
732
733 end:
734 ff_cbs_fragment_reset(obu);
735 return ret;
736 }
737
738 static const VAAPIEncodeProfile vaapi_encode_av1_profiles[] = {
739 { AV_PROFILE_AV1_MAIN, 8, 3, 1, 1, VAProfileAV1Profile0 },
740 { AV_PROFILE_AV1_MAIN, 10, 3, 1, 1, VAProfileAV1Profile0 },
741 { AV_PROFILE_UNKNOWN }
742 };
743
744 static const VAAPIEncodeType vaapi_encode_type_av1 = {
745 .profiles = vaapi_encode_av1_profiles,
746 .flags = FLAG_B_PICTURES | FLAG_TIMESTAMP_NO_DELAY,
747 .default_quality = 25,
748
749 .get_encoder_caps = &vaapi_encode_av1_get_encoder_caps,
750 .configure = &vaapi_encode_av1_configure,
751
752 .sequence_header_type = VAEncPackedHeaderSequence,
753 .sequence_params_size = sizeof(VAEncSequenceParameterBufferAV1),
754 .init_sequence_params = &vaapi_encode_av1_init_sequence_params,
755 .write_sequence_header = &vaapi_encode_av1_write_sequence_header,
756
757 .picture_priv_data_size = sizeof(VAAPIEncodeAV1Picture),
758 .picture_header_type = VAEncPackedHeaderPicture,
759 .picture_params_size = sizeof(VAEncPictureParameterBufferAV1),
760 .init_picture_params = &vaapi_encode_av1_init_picture_params,
761 .write_picture_header = &vaapi_encode_av1_write_picture_header,
762
763 .slice_params_size = sizeof(VAEncTileGroupBufferAV1),
764 .init_slice_params = &vaapi_encode_av1_init_slice_params,
765 };
766
767 static av_cold int vaapi_encode_av1_init(AVCodecContext *avctx)
768 {
769 VAAPIEncodeContext *ctx = avctx->priv_data;
770 VAAPIEncodeAV1Context *priv = avctx->priv_data;
771 VAConfigAttrib attr;
772 VAStatus vas;
773 int ret;
774
775 ctx->codec = &vaapi_encode_type_av1;
776
777 ctx->desired_packed_headers =
778 VA_ENC_PACKED_HEADER_SEQUENCE |
779 VA_ENC_PACKED_HEADER_PICTURE;
780
781 if (avctx->profile == AV_PROFILE_UNKNOWN)
782 avctx->profile = priv->profile;
783 if (avctx->level == AV_LEVEL_UNKNOWN)
784 avctx->level = priv->level;
785
786 if (avctx->level != AV_LEVEL_UNKNOWN && avctx->level & ~0x1f) {
787 av_log(avctx, AV_LOG_ERROR, "Invalid level %d\n", avctx->level);
788 return AVERROR(EINVAL);
789 }
790
791 ret = ff_vaapi_encode_init(avctx);
792 if (ret < 0)
793 return ret;
794
795 attr.type = VAConfigAttribEncAV1;
796 vas = vaGetConfigAttributes(ctx->hwctx->display,
797 ctx->va_profile,
798 ctx->va_entrypoint,
799 &attr, 1);
800 if (vas != VA_STATUS_SUCCESS) {
801 av_log(avctx, AV_LOG_ERROR, "Failed to query "
802 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
803 return AVERROR_EXTERNAL;
804 } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
805 priv->attr.value = 0;
806 av_log(avctx, AV_LOG_WARNING, "Attribute type:%d is not "
807 "supported.\n", attr.type);
808 } else {
809 priv->attr.value = attr.value;
810 }
811
812 attr.type = VAConfigAttribEncAV1Ext1;
813 vas = vaGetConfigAttributes(ctx->hwctx->display,
814 ctx->va_profile,
815 ctx->va_entrypoint,
816 &attr, 1);
817 if (vas != VA_STATUS_SUCCESS) {
818 av_log(avctx, AV_LOG_ERROR, "Failed to query "
819 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
820 return AVERROR_EXTERNAL;
821 } else if (attr.value == VA_ATTRIB_NOT_SUPPORTED) {
822 priv->attr_ext1.value = 0;
823 av_log(avctx, AV_LOG_WARNING, "Attribute type:%d is not "
824 "supported.\n", attr.type);
825 } else {
826 priv->attr_ext1.value = attr.value;
827 }
828
829 /** This attr provides essential indicators, return error if not support. */
830 attr.type = VAConfigAttribEncAV1Ext2;
831 vas = vaGetConfigAttributes(ctx->hwctx->display,
832 ctx->va_profile,
833 ctx->va_entrypoint,
834 &attr, 1);
835 if (vas != VA_STATUS_SUCCESS || attr.value == VA_ATTRIB_NOT_SUPPORTED) {
836 av_log(avctx, AV_LOG_ERROR, "Failed to query "
837 "config attribute: %d (%s).\n", vas, vaErrorStr(vas));
838 return AVERROR_EXTERNAL;
839 } else {
840 priv->attr_ext2.value = attr.value;
841 }
842
843 av_opt_set_int(priv->cbc->priv_data, "fixed_obu_size_length",
844 priv->attr_ext2.bits.obu_size_bytes_minus1 + 1, 0);
845
846 ret = vaapi_encode_av1_set_tile(avctx);
847 if (ret < 0)
848 return ret;
849
850 return 0;
851 }
852
853 static av_cold int vaapi_encode_av1_close(AVCodecContext *avctx)
854 {
855 VAAPIEncodeAV1Context *priv = avctx->priv_data;
856
857 ff_cbs_fragment_free(&priv->current_obu);
858 ff_cbs_close(&priv->cbc);
859
860 return ff_vaapi_encode_close(avctx);
861 }
862
863 #define OFFSET(x) offsetof(VAAPIEncodeAV1Context, x)
864 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
865
866 static const AVOption vaapi_encode_av1_options[] = {
867 VAAPI_ENCODE_COMMON_OPTIONS,
868 VAAPI_ENCODE_RC_OPTIONS,
869 { "profile", "Set profile (seq_profile)",
870 OFFSET(profile), AV_OPT_TYPE_INT,
871 { .i64 = AV_PROFILE_UNKNOWN }, AV_PROFILE_UNKNOWN, 0xff, FLAGS, .unit = "profile" },
872
873 #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
874 { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
875 { PROFILE("main", AV_PROFILE_AV1_MAIN) },
876 { PROFILE("high", AV_PROFILE_AV1_HIGH) },
877 { PROFILE("professional", AV_PROFILE_AV1_PROFESSIONAL) },
878 #undef PROFILE
879
880 { "tier", "Set tier (seq_tier)",
881 OFFSET(tier), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS, .unit = "tier" },
882 { "main", NULL, 0, AV_OPT_TYPE_CONST,
883 { .i64 = 0 }, 0, 0, FLAGS, .unit = "tier" },
884 { "high", NULL, 0, AV_OPT_TYPE_CONST,
885 { .i64 = 1 }, 0, 0, FLAGS, .unit = "tier" },
886 { "level", "Set level (seq_level_idx)",
887 OFFSET(level), AV_OPT_TYPE_INT,
888 { .i64 = AV_LEVEL_UNKNOWN }, AV_LEVEL_UNKNOWN, 0x1f, FLAGS, .unit = "level" },
889
890 #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
891 { .i64 = value }, 0, 0, FLAGS, .unit = "level"
892 { LEVEL("2.0", 0) },
893 { LEVEL("2.1", 1) },
894 { LEVEL("3.0", 4) },
895 { LEVEL("3.1", 5) },
896 { LEVEL("4.0", 8) },
897 { LEVEL("4.1", 9) },
898 { LEVEL("5.0", 12) },
899 { LEVEL("5.1", 13) },
900 { LEVEL("5.2", 14) },
901 { LEVEL("5.3", 15) },
902 { LEVEL("6.0", 16) },
903 { LEVEL("6.1", 17) },
904 { LEVEL("6.2", 18) },
905 { LEVEL("6.3", 19) },
906 #undef LEVEL
907
908 { "tiles", "Tile columns x rows (Use minimal tile column/row number automatically by default)",
909 OFFSET(tile_cols), AV_OPT_TYPE_IMAGE_SIZE, { .str = NULL }, 0, 0, FLAGS },
910 { "tile_groups", "Number of tile groups for encoding",
911 OFFSET(tile_groups), AV_OPT_TYPE_INT, { .i64 = 1 }, 1, AV1_MAX_TILE_ROWS * AV1_MAX_TILE_COLS, FLAGS },
912
913 { NULL },
914 };
915
916 static const FFCodecDefault vaapi_encode_av1_defaults[] = {
917 { "b", "0" },
918 { "bf", "2" },
919 { "g", "120" },
920 { "qmin", "1" },
921 { "qmax", "255" },
922 { NULL },
923 };
924
925 static const AVClass vaapi_encode_av1_class = {
926 .class_name = "av1_vaapi",
927 .item_name = av_default_item_name,
928 .option = vaapi_encode_av1_options,
929 .version = LIBAVUTIL_VERSION_INT,
930 };
931
932 const FFCodec ff_av1_vaapi_encoder = {
933 .p.name = "av1_vaapi",
934 CODEC_LONG_NAME("AV1 (VAAPI)"),
935 .p.type = AVMEDIA_TYPE_VIDEO,
936 .p.id = AV_CODEC_ID_AV1,
937 .priv_data_size = sizeof(VAAPIEncodeAV1Context),
938 .init = &vaapi_encode_av1_init,
939 FF_CODEC_RECEIVE_PACKET_CB(&ff_vaapi_encode_receive_packet),
940 .close = &vaapi_encode_av1_close,
941 .p.priv_class = &vaapi_encode_av1_class,
942 .p.capabilities = AV_CODEC_CAP_DELAY | AV_CODEC_CAP_HARDWARE |
943 AV_CODEC_CAP_DR1 | AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE,
944 .caps_internal = FF_CODEC_CAP_NOT_INIT_THREADSAFE |
945 FF_CODEC_CAP_INIT_CLEANUP,
946 .defaults = vaapi_encode_av1_defaults,
947 .p.pix_fmts = (const enum AVPixelFormat[]) {
948 AV_PIX_FMT_VAAPI,
949 AV_PIX_FMT_NONE,
950 },
951 .hw_configs = ff_vaapi_encode_hw_configs,
952 .p.wrapper_name = "vaapi",
953 };
954