vaapi_h264: Add support for AUD NAL units
[libav.git] / libavcodec / vaapi_encode_h264.c
CommitLineData
2c62fcdf
MT
1/*
2 * This file is part of Libav.
3 *
4 * Libav 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 * Libav 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 Libav; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
7a4fac5e
MT
19#include <string.h>
20
2c62fcdf
MT
21#include <va/va.h>
22#include <va/va_enc_h264.h>
23
24#include "libavutil/avassert.h"
7a4fac5e 25#include "libavutil/common.h"
2c62fcdf
MT
26#include "libavutil/internal.h"
27#include "libavutil/opt.h"
2c62fcdf
MT
28
29#include "avcodec.h"
7a4fac5e
MT
30#include "cbs.h"
31#include "cbs_h264.h"
251cbb44 32#include "h264.h"
48e2967c 33#include "h264_sei.h"
2c62fcdf
MT
34#include "internal.h"
35#include "vaapi_encode.h"
2c62fcdf
MT
36
37enum {
7a4fac5e
MT
38 SEI_TIMING = 0x01,
39 SEI_IDENTIFIER = 0x02,
2c62fcdf
MT
40};
41
7a4fac5e
MT
42// Random (version 4) ISO 11578 UUID.
43static const uint8_t vaapi_encode_h264_sei_identifier_uuid[16] = {
44 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf,
45 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d,
46};
2c62fcdf
MT
47
48typedef struct VAAPIEncodeH264Context {
2c62fcdf
MT
49 int mb_width;
50 int mb_height;
51
52 int fixed_qp_idr;
53 int fixed_qp_p;
54 int fixed_qp_b;
55
820a4483 56 H264RawAUD aud;
7a4fac5e
MT
57 H264RawSPS sps;
58 H264RawPPS pps;
59 H264RawSEI sei;
60 H264RawSlice slice;
61
62 H264RawSEIBufferingPeriod buffering_period;
63 H264RawSEIPicTiming pic_timing;
64 H264RawSEIUserDataUnregistered identifier;
65 char *identifier_string;
66
67 int frame_num;
68 int pic_order_cnt;
b51c7c6b 69 int next_frame_num;
9b1db2d3 70 int64_t last_idr_frame;
2c62fcdf 71 int64_t idr_pic_count;
2c62fcdf 72
7a4fac5e
MT
73 int primary_pic_type;
74 int slice_type;
75
48e2967c
MT
76 int cpb_delay;
77 int dpb_delay;
78
7a4fac5e
MT
79 CodedBitstreamContext cbc;
80 CodedBitstreamFragment current_access_unit;
820a4483 81 int aud_needed;
7a4fac5e 82 int sei_needed;
2c62fcdf
MT
83} VAAPIEncodeH264Context;
84
9629701c
MT
85typedef struct VAAPIEncodeH264Options {
86 int qp;
fcf536b1 87 int quality;
a86aa160 88 int low_power;
820a4483 89 int aud;
7a4fac5e 90 int sei;
9629701c
MT
91} VAAPIEncodeH264Options;
92
2c62fcdf 93
7a4fac5e
MT
94static int vaapi_encode_h264_write_access_unit(AVCodecContext *avctx,
95 char *data, size_t *data_len,
96 CodedBitstreamFragment *au)
2c62fcdf 97{
7a4fac5e
MT
98 VAAPIEncodeContext *ctx = avctx->priv_data;
99 VAAPIEncodeH264Context *priv = ctx->priv_data;
100 int err;
48e2967c 101
7a4fac5e
MT
102 err = ff_cbs_write_fragment_data(&priv->cbc, au);
103 if (err < 0) {
104 av_log(avctx, AV_LOG_ERROR, "Failed to write packed header.\n");
105 return err;
48e2967c 106 }
48e2967c 107
7a4fac5e
MT
108 if (*data_len < 8 * au->data_size - au->data_bit_padding) {
109 av_log(avctx, AV_LOG_ERROR, "Access unit too large: "
110 "%zu < %zu.\n", *data_len,
111 8 * au->data_size - au->data_bit_padding);
112 return AVERROR(ENOSPC);
48e2967c 113 }
48e2967c 114
7a4fac5e
MT
115 memcpy(data, au->data, au->data_size);
116 *data_len = 8 * au->data_size - au->data_bit_padding;
02fa1ad9 117
7a4fac5e 118 return 0;
02fa1ad9
MT
119}
120
7a4fac5e
MT
121static int vaapi_encode_h264_add_nal(AVCodecContext *avctx,
122 CodedBitstreamFragment *au,
123 void *nal_unit)
48e2967c 124{
7a4fac5e 125 VAAPIEncodeContext *ctx = avctx->priv_data;
48e2967c 126 VAAPIEncodeH264Context *priv = ctx->priv_data;
7a4fac5e
MT
127 H264RawNALUnitHeader *header = nal_unit;
128 int err;
48e2967c 129
7a4fac5e
MT
130 err = ff_cbs_insert_unit_content(&priv->cbc, au, -1,
131 header->nal_unit_type, nal_unit);
132 if (err < 0) {
133 av_log(avctx, AV_LOG_ERROR, "Failed to add NAL unit: "
134 "type = %d.\n", header->nal_unit_type);
135 return err;
48e2967c
MT
136 }
137
7a4fac5e 138 return 0;
48e2967c
MT
139}
140
2c62fcdf
MT
141static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx,
142 char *data, size_t *data_len)
143{
7a4fac5e
MT
144 VAAPIEncodeContext *ctx = avctx->priv_data;
145 VAAPIEncodeH264Context *priv = ctx->priv_data;
146 CodedBitstreamFragment *au = &priv->current_access_unit;
2c62fcdf 147 int err;
2c62fcdf 148
820a4483
MT
149 if (priv->aud_needed) {
150 err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud);
151 if (err < 0)
152 goto fail;
153 priv->aud_needed = 0;
154 }
155
7a4fac5e 156 err = vaapi_encode_h264_add_nal(avctx, au, &priv->sps);
2c62fcdf 157 if (err < 0)
7a4fac5e 158 goto fail;
2c62fcdf 159
7a4fac5e 160 err = vaapi_encode_h264_add_nal(avctx, au, &priv->pps);
2c62fcdf 161 if (err < 0)
7a4fac5e 162 goto fail;
2c62fcdf 163
7a4fac5e
MT
164 err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au);
165fail:
166 ff_cbs_fragment_uninit(&priv->cbc, au);
167 return err;
2c62fcdf
MT
168}
169
170static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx,
171 VAAPIEncodePicture *pic,
172 VAAPIEncodeSlice *slice,
173 char *data, size_t *data_len)
174{
7a4fac5e
MT
175 VAAPIEncodeContext *ctx = avctx->priv_data;
176 VAAPIEncodeH264Context *priv = ctx->priv_data;
177 CodedBitstreamFragment *au = &priv->current_access_unit;
178 int err;
2c62fcdf 179
820a4483
MT
180 if (priv->aud_needed) {
181 err = vaapi_encode_h264_add_nal(avctx, au, &priv->aud);
182 if (err < 0)
183 goto fail;
184 priv->aud_needed = 0;
185 }
186
7a4fac5e
MT
187 err = vaapi_encode_h264_add_nal(avctx, au, &priv->slice);
188 if (err < 0)
189 goto fail;
2c62fcdf 190
7a4fac5e
MT
191 err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au);
192fail:
193 ff_cbs_fragment_uninit(&priv->cbc, au);
194 return err;
2c62fcdf
MT
195}
196
48e2967c
MT
197static int vaapi_encode_h264_write_extra_header(AVCodecContext *avctx,
198 VAAPIEncodePicture *pic,
199 int index, int *type,
200 char *data, size_t *data_len)
201{
7a4fac5e
MT
202 VAAPIEncodeContext *ctx = avctx->priv_data;
203 VAAPIEncodeH264Context *priv = ctx->priv_data;
204 VAAPIEncodeH264Options *opt = ctx->codec_options;
205 CodedBitstreamFragment *au = &priv->current_access_unit;
206 int err, i;
207
208 if (priv->sei_needed) {
820a4483
MT
209 if (priv->aud_needed) {
210 vaapi_encode_h264_add_nal(avctx, au, &priv->aud);
211 priv->aud_needed = 0;
212 }
213
7a4fac5e
MT
214 memset(&priv->sei, 0, sizeof(priv->sei));
215 priv->sei.nal_unit_header.nal_unit_type = H264_NAL_SEI;
216
217 i = 0;
218 if (pic->encode_order == 0 && opt->sei & SEI_IDENTIFIER) {
219 priv->sei.payload[i].payload_type = H264_SEI_TYPE_USER_DATA_UNREGISTERED;
220 priv->sei.payload[i].payload.user_data_unregistered = priv->identifier;
221 ++i;
222 }
223 if (opt->sei & SEI_TIMING) {
224 if (pic->type == PICTURE_TYPE_IDR) {
225 priv->sei.payload[i].payload_type = H264_SEI_TYPE_BUFFERING_PERIOD;
226 priv->sei.payload[i].payload.buffering_period = priv->buffering_period;
227 ++i;
228 }
229 priv->sei.payload[i].payload_type = H264_SEI_TYPE_PIC_TIMING;
230 priv->sei.payload[i].payload.pic_timing = priv->pic_timing;
231 ++i;
232 }
48e2967c 233
7a4fac5e
MT
234 priv->sei.payload_count = i;
235 av_assert0(priv->sei.payload_count > 0);
236
237 err = vaapi_encode_h264_add_nal(avctx, au, &priv->sei);
238 if (err < 0)
239 goto fail;
240 priv->sei_needed = 0;
48e2967c 241
7a4fac5e
MT
242 err = vaapi_encode_h264_write_access_unit(avctx, data, data_len, au);
243 if (err < 0)
244 goto fail;
48e2967c 245
7a4fac5e 246 ff_cbs_fragment_uninit(&priv->cbc, au);
48e2967c 247
7a4fac5e
MT
248 *type = VAEncPackedHeaderH264_SEI;
249 return 0;
48e2967c
MT
250 } else {
251 return AVERROR_EOF;
252 }
7a4fac5e
MT
253
254fail:
255 ff_cbs_fragment_uninit(&priv->cbc, au);
256 return err;
48e2967c
MT
257}
258
2c62fcdf
MT
259static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
260{
7a4fac5e
MT
261 VAAPIEncodeContext *ctx = avctx->priv_data;
262 VAAPIEncodeH264Context *priv = ctx->priv_data;
263 VAAPIEncodeH264Options *opt = ctx->codec_options;
264 H264RawSPS *sps = &priv->sps;
265 H264RawPPS *pps = &priv->pps;
266 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
267 VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params;
2c62fcdf 268
7a4fac5e
MT
269 memset(&priv->current_access_unit, 0,
270 sizeof(priv->current_access_unit));
2c62fcdf 271
7a4fac5e
MT
272 memset(sps, 0, sizeof(*sps));
273 memset(pps, 0, sizeof(*pps));
2c62fcdf 274
7a4fac5e
MT
275 sps->nal_unit_header.nal_ref_idc = 3;
276 sps->nal_unit_header.nal_unit_type = H264_NAL_SPS;
2c62fcdf 277
7a4fac5e
MT
278 sps->profile_idc = avctx->profile & 0xff;
279 sps->constraint_set1_flag =
280 !!(avctx->profile & FF_PROFILE_H264_CONSTRAINED);
281 sps->constraint_set3_flag =
282 !!(avctx->profile & FF_PROFILE_H264_INTRA);
2c62fcdf 283
7a4fac5e 284 sps->level_idc = avctx->level;
2c62fcdf 285
7a4fac5e
MT
286 sps->seq_parameter_set_id = 0;
287 sps->chroma_format_idc = 1;
2c62fcdf 288
7a4fac5e
MT
289 sps->log2_max_frame_num_minus4 = 4;
290 sps->pic_order_cnt_type = 0;
291 sps->log2_max_pic_order_cnt_lsb_minus4 =
292 av_clip(av_log2(ctx->b_per_p + 1) - 2, 0, 12);
293
294 sps->max_num_ref_frames =
295 (avctx->profile & FF_PROFILE_H264_INTRA) ? 0 :
296 1 + (ctx->b_per_p > 0);
297
298 sps->pic_width_in_mbs_minus1 = priv->mb_width - 1;
299 sps->pic_height_in_map_units_minus1 = priv->mb_height - 1;
300
301 sps->frame_mbs_only_flag = 1;
302 sps->direct_8x8_inference_flag = 1;
6e8f66fc 303
7a4fac5e
MT
304 if (avctx->width != 16 * priv->mb_width ||
305 avctx->height != 16 * priv->mb_height) {
306 sps->frame_cropping_flag = 1;
307
308 sps->frame_crop_left_offset = 0;
309 sps->frame_crop_right_offset =
310 (16 * priv->mb_width - avctx->width) / 2;
311 sps->frame_crop_top_offset = 0;
312 sps->frame_crop_bottom_offset =
313 (16 * priv->mb_height - avctx->height) / 2;
314 } else {
315 sps->frame_cropping_flag = 0;
316 }
317
318 sps->vui_parameters_present_flag = 1;
319
320 if (avctx->sample_aspect_ratio.num != 0 &&
321 avctx->sample_aspect_ratio.den != 0) {
322 static const AVRational sar_idc[] = {
323 { 0, 0 },
324 { 1, 1 }, { 12, 11 }, { 10, 11 }, { 16, 11 },
325 { 40, 33 }, { 24, 11 }, { 20, 11 }, { 32, 11 },
326 { 80, 33 }, { 18, 11 }, { 15, 11 }, { 64, 33 },
327 { 160, 99 }, { 4, 3 }, { 3, 2 }, { 2, 1 },
328 };
329 int i;
330 for (i = 0; i < FF_ARRAY_ELEMS(sar_idc); i++) {
331 if (avctx->sample_aspect_ratio.num == sar_idc[i].num &&
332 avctx->sample_aspect_ratio.den == sar_idc[i].den) {
333 sps->vui.aspect_ratio_idc = i;
334 break;
081961f8
MT
335 }
336 }
7a4fac5e
MT
337 if (i >= FF_ARRAY_ELEMS(sar_idc)) {
338 sps->vui.aspect_ratio_idc = 255;
339 sps->vui.sar_width = avctx->sample_aspect_ratio.num;
340 sps->vui.sar_height = avctx->sample_aspect_ratio.den;
341 }
342 sps->vui.aspect_ratio_info_present_flag = 1;
343 }
344
345 if (avctx->color_range != AVCOL_RANGE_UNSPECIFIED ||
346 avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
347 avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
348 avctx->colorspace != AVCOL_SPC_UNSPECIFIED) {
349 sps->vui.video_signal_type_present_flag = 1;
350 sps->vui.video_format = 5; // Unspecified.
351 sps->vui.video_full_range_flag =
352 avctx->color_range == AVCOL_RANGE_JPEG;
353
081961f8
MT
354 if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
355 avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
356 avctx->colorspace != AVCOL_SPC_UNSPECIFIED) {
7a4fac5e
MT
357 sps->vui.colour_description_present_flag = 1;
358 sps->vui.colour_primaries = avctx->color_primaries;
359 sps->vui.transfer_characteristics = avctx->color_trc;
360 sps->vui.matrix_coefficients = avctx->colorspace;
081961f8 361 }
7a4fac5e
MT
362 } else {
363 sps->vui.video_format = 5;
364 sps->vui.video_full_range_flag = 0;
365 sps->vui.colour_primaries = avctx->color_primaries;
366 sps->vui.transfer_characteristics = avctx->color_trc;
367 sps->vui.matrix_coefficients = avctx->colorspace;
368 }
081961f8 369
7a4fac5e
MT
370 if (avctx->chroma_sample_location != AVCHROMA_LOC_UNSPECIFIED) {
371 sps->vui.chroma_loc_info_present_flag = 1;
372 sps->vui.chroma_sample_loc_type_top_field =
373 sps->vui.chroma_sample_loc_type_bottom_field =
374 avctx->chroma_sample_location - 1;
375 }
081961f8 376
7a4fac5e
MT
377 sps->vui.timing_info_present_flag = 1;
378 if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
379 sps->vui.num_units_in_tick = avctx->framerate.den;
380 sps->vui.time_scale = 2 * avctx->framerate.num;
381 sps->vui.fixed_frame_rate_flag = 1;
382 } else {
383 sps->vui.num_units_in_tick = avctx->time_base.num;
384 sps->vui.time_scale = 2 * avctx->time_base.den;
385 sps->vui.fixed_frame_rate_flag = 0;
386 }
6e8f66fc 387
7a4fac5e
MT
388 if (opt->sei & SEI_TIMING) {
389 H264RawHRD *hrd = &sps->vui.nal_hrd_parameters;
48e2967c 390
7a4fac5e 391 sps->vui.nal_hrd_parameters_present_flag = 1;
48e2967c 392
7a4fac5e 393 hrd->cpb_cnt_minus1 = 0;
48e2967c 394
7a4fac5e
MT
395 // Try to scale these to a sensible range so that the
396 // golomb encode of the value is not overlong.
397 hrd->bit_rate_scale =
398 av_clip_uintp2(av_log2(avctx->bit_rate) - 15 - 6, 4);
399 hrd->bit_rate_value_minus1[0] =
400 (avctx->bit_rate >> hrd->bit_rate_scale + 6) - 1;
48e2967c 401
7a4fac5e
MT
402 hrd->cpb_size_scale =
403 av_clip_uintp2(av_log2(ctx->hrd_params.hrd.buffer_size) - 15 - 4, 4);
404 hrd->cpb_size_value_minus1[0] =
405 (ctx->hrd_params.hrd.buffer_size >> hrd->cpb_size_scale + 4) - 1;
48e2967c 406
7a4fac5e
MT
407 // CBR mode as defined for the HRD cannot be achieved without filler
408 // data, so this flag cannot be set even with VAAPI CBR modes.
409 hrd->cbr_flag[0] = 0;
48e2967c 410
7a4fac5e
MT
411 hrd->initial_cpb_removal_delay_length_minus1 = 23;
412 hrd->cpb_removal_delay_length_minus1 = 23;
413 hrd->dpb_output_delay_length_minus1 = 7;
414 hrd->time_offset_length = 0;
48e2967c 415
7a4fac5e 416 priv->buffering_period.seq_parameter_set_id = sps->seq_parameter_set_id;
48e2967c 417
7a4fac5e
MT
418 // This calculation can easily overflow 32 bits.
419 priv->buffering_period.nal.initial_cpb_removal_delay[0] = 90000 *
420 (uint64_t)ctx->hrd_params.hrd.initial_buffer_fullness /
421 ctx->hrd_params.hrd.buffer_size;
422 priv->buffering_period.nal.initial_cpb_removal_delay_offset[0] = 0;
423 } else {
424 sps->vui.nal_hrd_parameters_present_flag = 0;
425 sps->vui.low_delay_hrd_flag = 1 - sps->vui.fixed_frame_rate_flag;
2c62fcdf
MT
426 }
427
7a4fac5e
MT
428 sps->vui.bitstream_restriction_flag = 1;
429 sps->vui.motion_vectors_over_pic_boundaries_flag = 1;
430 sps->vui.log2_max_mv_length_horizontal = 16;
431 sps->vui.log2_max_mv_length_vertical = 16;
432 sps->vui.max_num_reorder_frames = (ctx->b_per_p > 0);
433 sps->vui.max_dec_frame_buffering = vseq->max_num_ref_frames;
2c62fcdf 434
7a4fac5e
MT
435 pps->nal_unit_header.nal_ref_idc = 3;
436 pps->nal_unit_header.nal_unit_type = H264_NAL_PPS;
2c62fcdf 437
7a4fac5e
MT
438 pps->pic_parameter_set_id = 0;
439 pps->seq_parameter_set_id = 0;
2c62fcdf 440
7a4fac5e
MT
441 pps->entropy_coding_mode_flag =
442 !(sps->profile_idc == FF_PROFILE_H264_BASELINE ||
443 sps->profile_idc == FF_PROFILE_H264_EXTENDED ||
444 sps->profile_idc == FF_PROFILE_H264_CAVLC_444);
2c62fcdf 445
7a4fac5e
MT
446 pps->num_ref_idx_l0_default_active_minus1 = 0;
447 pps->num_ref_idx_l1_default_active_minus1 = 0;
2c62fcdf 448
7a4fac5e 449 pps->pic_init_qp_minus26 = priv->fixed_qp_idr - 26;
2c62fcdf 450
7a4fac5e
MT
451 if (sps->profile_idc == FF_PROFILE_H264_BASELINE ||
452 sps->profile_idc == FF_PROFILE_H264_EXTENDED ||
453 sps->profile_idc == FF_PROFILE_H264_MAIN) {
454 pps->more_rbsp_data = 0;
455 } else {
456 pps->more_rbsp_data = 1;
457
458 pps->transform_8x8_mode_flag = 1;
459 }
460
461 *vseq = (VAEncSequenceParameterBufferH264) {
462 .seq_parameter_set_id = sps->seq_parameter_set_id,
463 .level_idc = sps->level_idc,
464 .intra_period = avctx->gop_size,
465 .intra_idr_period = avctx->gop_size,
466 .ip_period = ctx->b_per_p + 1,
467
468 .bits_per_second = avctx->bit_rate,
469 .max_num_ref_frames = sps->max_num_ref_frames,
470 .picture_width_in_mbs = sps->pic_width_in_mbs_minus1 + 1,
471 .picture_height_in_mbs = sps->pic_height_in_map_units_minus1 + 1,
472
473 .seq_fields.bits = {
474 .chroma_format_idc = sps->chroma_format_idc,
475 .frame_mbs_only_flag = sps->frame_mbs_only_flag,
476 .mb_adaptive_frame_field_flag = sps->mb_adaptive_frame_field_flag,
477 .seq_scaling_matrix_present_flag = sps->seq_scaling_matrix_present_flag,
478 .direct_8x8_inference_flag = sps->direct_8x8_inference_flag,
479 .log2_max_frame_num_minus4 = sps->log2_max_frame_num_minus4,
480 .pic_order_cnt_type = sps->pic_order_cnt_type,
481 .log2_max_pic_order_cnt_lsb_minus4 = sps->log2_max_pic_order_cnt_lsb_minus4,
482 .delta_pic_order_always_zero_flag = sps->delta_pic_order_always_zero_flag,
483 },
484
485 .bit_depth_luma_minus8 = sps->bit_depth_luma_minus8,
486 .bit_depth_chroma_minus8 = sps->bit_depth_chroma_minus8,
487
488 .frame_cropping_flag = sps->frame_cropping_flag,
489 .frame_crop_left_offset = sps->frame_crop_left_offset,
490 .frame_crop_right_offset = sps->frame_crop_right_offset,
491 .frame_crop_top_offset = sps->frame_crop_top_offset,
492 .frame_crop_bottom_offset = sps->frame_crop_bottom_offset,
493
494 .vui_parameters_present_flag = sps->vui_parameters_present_flag,
495
496 .vui_fields.bits = {
497 .aspect_ratio_info_present_flag = sps->vui.aspect_ratio_info_present_flag,
498 .timing_info_present_flag = sps->vui.timing_info_present_flag,
499 .bitstream_restriction_flag = sps->vui.bitstream_restriction_flag,
500 .log2_max_mv_length_horizontal = sps->vui.log2_max_mv_length_horizontal,
501 .log2_max_mv_length_vertical = sps->vui.log2_max_mv_length_vertical,
502 },
503
504 .aspect_ratio_idc = sps->vui.aspect_ratio_idc,
505 .sar_width = sps->vui.sar_width,
506 .sar_height = sps->vui.sar_height,
507 .num_units_in_tick = sps->vui.num_units_in_tick,
508 .time_scale = sps->vui.time_scale,
509 };
2c62fcdf 510
7a4fac5e
MT
511 *vpic = (VAEncPictureParameterBufferH264) {
512 .CurrPic = {
513 .picture_id = VA_INVALID_ID,
514 .flags = VA_PICTURE_H264_INVALID,
515 },
516
517 .coded_buf = VA_INVALID_ID,
518
519 .pic_parameter_set_id = pps->pic_parameter_set_id,
520 .seq_parameter_set_id = pps->seq_parameter_set_id,
521
522 .pic_init_qp = pps->pic_init_qp_minus26 + 26,
523 .num_ref_idx_l0_active_minus1 = pps->num_ref_idx_l0_default_active_minus1,
524 .num_ref_idx_l1_active_minus1 = pps->num_ref_idx_l1_default_active_minus1,
525
526 .chroma_qp_index_offset = pps->chroma_qp_index_offset,
527 .second_chroma_qp_index_offset = pps->second_chroma_qp_index_offset,
528
529 .pic_fields.bits = {
530 .entropy_coding_mode_flag = pps->entropy_coding_mode_flag,
531 .weighted_pred_flag = pps->weighted_pred_flag,
532 .weighted_bipred_idc = pps->weighted_bipred_idc,
533 .constrained_intra_pred_flag = pps->constrained_intra_pred_flag,
534 .transform_8x8_mode_flag = pps->transform_8x8_mode_flag,
535 .deblocking_filter_control_present_flag =
536 pps->deblocking_filter_control_present_flag,
537 .redundant_pic_cnt_present_flag = pps->redundant_pic_cnt_present_flag,
538 .pic_order_present_flag =
539 pps->bottom_field_pic_order_in_frame_present_flag,
540 .pic_scaling_matrix_present_flag = pps->pic_scaling_matrix_present_flag,
541 },
542 };
2c62fcdf
MT
543
544 return 0;
545}
546
547static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
548 VAAPIEncodePicture *pic)
549{
7a4fac5e
MT
550 VAAPIEncodeContext *ctx = avctx->priv_data;
551 VAAPIEncodeH264Context *priv = ctx->priv_data;
552 VAAPIEncodeH264Options *opt = ctx->codec_options;
553 H264RawSPS *sps = &priv->sps;
554 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
2c62fcdf
MT
555 int i;
556
7a4fac5e
MT
557 memset(&priv->current_access_unit, 0,
558 sizeof(priv->current_access_unit));
559
2c62fcdf
MT
560 if (pic->type == PICTURE_TYPE_IDR) {
561 av_assert0(pic->display_order == pic->encode_order);
7a4fac5e 562 priv->frame_num = 0;
b51c7c6b 563 priv->next_frame_num = 1;
7a4fac5e 564 priv->cpb_delay = 0;
9b1db2d3 565 priv->last_idr_frame = pic->display_order;
7a4fac5e
MT
566 ++priv->idr_pic_count;
567
568 priv->slice_type = 7;
569 priv->primary_pic_type = 0;
2c62fcdf 570 } else {
7a4fac5e
MT
571 priv->frame_num = priv->next_frame_num;
572
b51c7c6b 573 if (pic->type != PICTURE_TYPE_B) {
7a4fac5e
MT
574 // Reference picture, so frame_num advances.
575 priv->next_frame_num = (priv->frame_num + 1) &
576 ((1 << (4 + sps->log2_max_frame_num_minus4)) - 1);
b51c7c6b 577 }
48e2967c 578 ++priv->cpb_delay;
7a4fac5e
MT
579
580 if (pic->type == PICTURE_TYPE_I) {
581 priv->slice_type = 7;
582 priv->primary_pic_type = 0;
583 } else if (pic->type == PICTURE_TYPE_P) {
584 priv->slice_type = 5;
585 priv->primary_pic_type = 1;
586 } else {
587 priv->slice_type = 6;
588 priv->primary_pic_type = 2;
589 }
2c62fcdf 590 }
7a4fac5e
MT
591 priv->pic_order_cnt = pic->display_order - priv->last_idr_frame;
592 priv->dpb_delay = pic->display_order - pic->encode_order + 1;
2c62fcdf 593
820a4483
MT
594 if (opt->aud) {
595 priv->aud_needed = 1;
596 priv->aud.nal_unit_header.nal_unit_type = H264_NAL_AUD;
597 priv->aud.primary_pic_type = priv->primary_pic_type;
598 } else {
599 priv->aud_needed = 0;
600 }
601
7a4fac5e
MT
602 if (opt->sei & SEI_IDENTIFIER && pic->encode_order == 0)
603 priv->sei_needed = 1;
604
605 if (opt->sei & SEI_TIMING) {
606 memset(&priv->pic_timing, 0, sizeof(priv->pic_timing));
607
608 priv->pic_timing.cpb_removal_delay =
609 2 * sps->vui.num_units_in_tick * priv->cpb_delay;
610 priv->pic_timing.dpb_output_delay =
611 2 * sps->vui.num_units_in_tick * priv->dpb_delay;
612
613 priv->sei_needed = 1;
614 }
2c62fcdf 615
7a4fac5e
MT
616 vpic->CurrPic = (VAPictureH264) {
617 .picture_id = pic->recon_surface,
618 .frame_idx = priv->frame_num,
619 .flags = 0,
620 .TopFieldOrderCnt = priv->pic_order_cnt,
621 .BottomFieldOrderCnt = priv->pic_order_cnt,
622 };
2c62fcdf
MT
623
624 for (i = 0; i < pic->nb_refs; i++) {
625 VAAPIEncodePicture *ref = pic->refs[i];
7a4fac5e
MT
626 unsigned int frame_num = (ref->encode_order - priv->last_idr_frame) &
627 ((1 << (4 + sps->log2_max_frame_num_minus4)) - 1);
628 unsigned int pic_order_cnt = ref->display_order - priv->last_idr_frame;
629
b51c7c6b 630 av_assert0(ref && ref->encode_order < pic->encode_order);
7a4fac5e
MT
631 vpic->ReferenceFrames[i] = (VAPictureH264) {
632 .picture_id = ref->recon_surface,
633 .frame_idx = frame_num,
634 .flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE,
635 .TopFieldOrderCnt = pic_order_cnt,
636 .BottomFieldOrderCnt = pic_order_cnt,
637 };
2c62fcdf
MT
638 }
639 for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
7a4fac5e
MT
640 vpic->ReferenceFrames[i] = (VAPictureH264) {
641 .picture_id = VA_INVALID_ID,
642 .flags = VA_PICTURE_H264_INVALID,
643 };
2c62fcdf
MT
644 }
645
646 vpic->coded_buf = pic->output_buffer;
647
7a4fac5e
MT
648 vpic->frame_num = priv->frame_num;
649
650 vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR);
2c62fcdf
MT
651 vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B);
652
653 pic->nb_slices = 1;
654
655 return 0;
656}
657
658static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
659 VAAPIEncodePicture *pic,
660 VAAPIEncodeSlice *slice)
661{
7a4fac5e
MT
662 VAAPIEncodeContext *ctx = avctx->priv_data;
663 VAAPIEncodeH264Context *priv = ctx->priv_data;
664 H264RawSPS *sps = &priv->sps;
665 H264RawPPS *pps = &priv->pps;
666 H264RawSliceHeader *sh = &priv->slice.header;
667 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
668 VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params;
2c62fcdf
MT
669 int i;
670
7a4fac5e
MT
671 if (pic->type == PICTURE_TYPE_IDR) {
672 sh->nal_unit_header.nal_unit_type = H264_NAL_IDR_SLICE;
673 sh->nal_unit_header.nal_ref_idc = 3;
674 } else {
675 sh->nal_unit_header.nal_unit_type = H264_NAL_SLICE;
676 sh->nal_unit_header.nal_ref_idc = pic->type != PICTURE_TYPE_B;
677 }
678
679 // Only one slice per frame.
680 sh->first_mb_in_slice = 0;
681 sh->slice_type = priv->slice_type;
682
683 sh->pic_parameter_set_id = pps->pic_parameter_set_id;
2c62fcdf 684
7a4fac5e
MT
685 sh->frame_num = priv->frame_num;
686 sh->idr_pic_id = priv->idr_pic_count;
687
688 sh->pic_order_cnt_lsb = priv->pic_order_cnt &
689 ((1 << (4 + sps->log2_max_pic_order_cnt_lsb_minus4)) - 1);
690
691 sh->direct_spatial_mv_pred_flag = 1;
692
693 if (pic->type == PICTURE_TYPE_B)
694 sh->slice_qp_delta = priv->fixed_qp_b - (pps->pic_init_qp_minus26 + 26);
695 else if (pic->type == PICTURE_TYPE_P)
696 sh->slice_qp_delta = priv->fixed_qp_p - (pps->pic_init_qp_minus26 + 26);
2c62fcdf 697 else
7a4fac5e 698 sh->slice_qp_delta = priv->fixed_qp_idr - (pps->pic_init_qp_minus26 + 26);
2c62fcdf 699
2c62fcdf 700
7a4fac5e
MT
701 vslice->macroblock_address = sh->first_mb_in_slice;
702 vslice->num_macroblocks = priv->mb_width * priv->mb_height;
2c62fcdf
MT
703
704 vslice->macroblock_info = VA_INVALID_ID;
705
7a4fac5e
MT
706 vslice->slice_type = sh->slice_type % 5;
707 vslice->pic_parameter_set_id = sh->pic_parameter_set_id;
708 vslice->idr_pic_id = sh->idr_pic_id;
709
710 vslice->pic_order_cnt_lsb = sh->pic_order_cnt_lsb;
2c62fcdf 711
7a4fac5e 712 vslice->direct_spatial_mv_pred_flag = sh->direct_spatial_mv_pred_flag;
2c62fcdf
MT
713
714 for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) {
715 vslice->RefPicList0[i].picture_id = VA_INVALID_ID;
716 vslice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
717 vslice->RefPicList1[i].picture_id = VA_INVALID_ID;
718 vslice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
719 }
720
721 av_assert0(pic->nb_refs <= 2);
722 if (pic->nb_refs >= 1) {
41ed7ab4 723 // Backward reference for P- or B-frame.
2c62fcdf
MT
724 av_assert0(pic->type == PICTURE_TYPE_P ||
725 pic->type == PICTURE_TYPE_B);
2c62fcdf
MT
726 vslice->RefPicList0[0] = vpic->ReferenceFrames[0];
727 }
728 if (pic->nb_refs >= 2) {
41ed7ab4 729 // Forward reference for B-frame.
2c62fcdf 730 av_assert0(pic->type == PICTURE_TYPE_B);
2c62fcdf
MT
731 vslice->RefPicList1[0] = vpic->ReferenceFrames[1];
732 }
733
7a4fac5e 734 vslice->slice_qp_delta = sh->slice_qp_delta;
2c62fcdf
MT
735
736 return 0;
737}
738
80a5d051 739static av_cold int vaapi_encode_h264_configure(AVCodecContext *avctx)
6e8f66fc
MT
740{
741 VAAPIEncodeContext *ctx = avctx->priv_data;
742 VAAPIEncodeH264Context *priv = ctx->priv_data;
80a5d051 743 VAAPIEncodeH264Options *opt = ctx->codec_options;
7a4fac5e
MT
744 int err;
745
746 err = ff_cbs_init(&priv->cbc, AV_CODEC_ID_H264, avctx);
747 if (err < 0)
748 return err;
6e8f66fc 749
80a5d051
MT
750 priv->mb_width = FFALIGN(avctx->width, 16) / 16;
751 priv->mb_height = FFALIGN(avctx->height, 16) / 16;
752
753 if (ctx->va_rc_mode == VA_RC_CQP) {
754 priv->fixed_qp_p = opt->qp;
755 if (avctx->i_quant_factor > 0.0)
756 priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
757 avctx->i_quant_offset) + 0.5);
758 else
759 priv->fixed_qp_idr = priv->fixed_qp_p;
760 if (avctx->b_quant_factor > 0.0)
761 priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
762 avctx->b_quant_offset) + 0.5);
763 else
764 priv->fixed_qp_b = priv->fixed_qp_p;
765
7a4fac5e
MT
766 opt->sei &= ~SEI_TIMING;
767
80a5d051
MT
768 av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
769 "%d / %d / %d for IDR- / P- / B-frames.\n",
770 priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
771
eddfb572
MT
772 } else if (ctx->va_rc_mode == VA_RC_CBR ||
773 ctx->va_rc_mode == VA_RC_VBR) {
80a5d051
MT
774 // These still need to be set for pic_init_qp/slice_qp_delta.
775 priv->fixed_qp_idr = 26;
776 priv->fixed_qp_p = 26;
777 priv->fixed_qp_b = 26;
778
eddfb572
MT
779 av_log(avctx, AV_LOG_DEBUG, "Using %s-bitrate = %d bps.\n",
780 ctx->va_rc_mode == VA_RC_CBR ? "constant" : "variable",
80a5d051 781 avctx->bit_rate);
6e8f66fc 782
80a5d051
MT
783 } else {
784 av_assert0(0 && "Invalid RC mode.");
785 }
6e8f66fc 786
19388a72
MT
787 if (avctx->compression_level == FF_COMPRESSION_DEFAULT)
788 avctx->compression_level = opt->quality;
6e8f66fc 789
7a4fac5e
MT
790 if (opt->sei & SEI_IDENTIFIER) {
791 const char *lavc = LIBAVCODEC_IDENT;
792 const char *vaapi = VA_VERSION_S;
793 const char *driver;
794 int len;
795
796 memcpy(priv->identifier.uuid_iso_iec_11578,
797 vaapi_encode_h264_sei_identifier_uuid,
798 sizeof(priv->identifier.uuid_iso_iec_11578));
799
800 driver = vaQueryVendorString(ctx->hwctx->display);
801 if (!driver)
802 driver = "unknown driver";
803
804 len = snprintf(NULL, 0, "%s / VAAPI %s / %s", lavc, vaapi, driver);
805 if (len >= 0) {
806 priv->identifier_string = av_malloc(len + 1);
807 if (!priv->identifier_string)
808 return AVERROR(ENOMEM);
809
810 snprintf(priv->identifier_string, len + 1,
811 "%s / VAAPI %s / %s", lavc, vaapi, driver);
812
813 priv->identifier.data = priv->identifier_string;
814 priv->identifier.data_length = len + 1;
815 }
816 }
817
6e8f66fc
MT
818 return 0;
819}
820
80a5d051
MT
821static const VAAPIEncodeType vaapi_encode_type_h264 = {
822 .priv_data_size = sizeof(VAAPIEncodeH264Context),
823
824 .configure = &vaapi_encode_h264_configure,
825
826 .sequence_params_size = sizeof(VAEncSequenceParameterBufferH264),
827 .init_sequence_params = &vaapi_encode_h264_init_sequence_params,
828
829 .picture_params_size = sizeof(VAEncPictureParameterBufferH264),
830 .init_picture_params = &vaapi_encode_h264_init_picture_params,
831
832 .slice_params_size = sizeof(VAEncSliceParameterBufferH264),
833 .init_slice_params = &vaapi_encode_h264_init_slice_params,
834
835 .sequence_header_type = VAEncPackedHeaderSequence,
836 .write_sequence_header = &vaapi_encode_h264_write_sequence_header,
837
838 .slice_header_type = VAEncPackedHeaderH264_Slice,
839 .write_slice_header = &vaapi_encode_h264_write_slice_header,
840
841 .write_extra_header = &vaapi_encode_h264_write_extra_header,
842};
843
844static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
2c62fcdf 845{
80a5d051
MT
846 VAAPIEncodeContext *ctx = avctx->priv_data;
847 VAAPIEncodeH264Options *opt =
848 (VAAPIEncodeH264Options*)ctx->codec_options_data;
f6b85523 849
80a5d051 850 ctx->codec = &vaapi_encode_type_h264;
2c62fcdf
MT
851
852 switch (avctx->profile) {
853 case FF_PROFILE_H264_CONSTRAINED_BASELINE:
854 ctx->va_profile = VAProfileH264ConstrainedBaseline;
855 break;
856 case FF_PROFILE_H264_BASELINE:
857 ctx->va_profile = VAProfileH264Baseline;
858 break;
859 case FF_PROFILE_H264_MAIN:
860 ctx->va_profile = VAProfileH264Main;
861 break;
862 case FF_PROFILE_H264_EXTENDED:
863 av_log(avctx, AV_LOG_ERROR, "H.264 extended profile "
864 "is not supported.\n");
865 return AVERROR_PATCHWELCOME;
866 case FF_PROFILE_UNKNOWN:
867 case FF_PROFILE_H264_HIGH:
868 ctx->va_profile = VAProfileH264High;
869 break;
870 case FF_PROFILE_H264_HIGH_10:
871 case FF_PROFILE_H264_HIGH_10_INTRA:
872 av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles "
873 "are not supported.\n");
874 return AVERROR_PATCHWELCOME;
875 case FF_PROFILE_H264_HIGH_422:
876 case FF_PROFILE_H264_HIGH_422_INTRA:
877 case FF_PROFILE_H264_HIGH_444:
878 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
879 case FF_PROFILE_H264_HIGH_444_INTRA:
880 case FF_PROFILE_H264_CAVLC_444:
881 av_log(avctx, AV_LOG_ERROR, "H.264 non-4:2:0 profiles "
882 "are not supported.\n");
883 return AVERROR_PATCHWELCOME;
884 default:
885 av_log(avctx, AV_LOG_ERROR, "Unknown H.264 profile %d.\n",
886 avctx->profile);
887 return AVERROR(EINVAL);
888 }
a86aa160 889 if (opt->low_power) {
80a5d051 890#if VA_CHECK_VERSION(0, 39, 2)
a86aa160
MT
891 ctx->va_entrypoint = VAEntrypointEncSliceLP;
892#else
893 av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
894 "supported with this VAAPI version.\n");
895 return AVERROR(EINVAL);
896#endif
897 } else {
898 ctx->va_entrypoint = VAEntrypointEncSlice;
899 }
2c62fcdf 900
80a5d051
MT
901 // Only 8-bit encode is supported.
902 ctx->va_rt_format = VA_RT_FORMAT_YUV420;
f6b85523 903
eddfb572
MT
904 if (avctx->bit_rate > 0) {
905 if (avctx->rc_max_rate == avctx->bit_rate)
906 ctx->va_rc_mode = VA_RC_CBR;
907 else
908 ctx->va_rc_mode = VA_RC_VBR;
909 } else
6e8f66fc 910 ctx->va_rc_mode = VA_RC_CQP;
2c62fcdf 911
892bbbcd
MT
912 ctx->va_packed_headers =
913 VA_ENC_PACKED_HEADER_SEQUENCE | // SPS and PPS.
914 VA_ENC_PACKED_HEADER_SLICE | // Slice headers.
915 VA_ENC_PACKED_HEADER_MISC; // SEI.
fcf536b1 916
80a5d051
MT
917 ctx->surface_width = FFALIGN(avctx->width, 16);
918 ctx->surface_height = FFALIGN(avctx->height, 16);
fcf536b1 919
80a5d051 920 return ff_vaapi_encode_init(avctx);
2c62fcdf
MT
921}
922
7a4fac5e
MT
923static av_cold int vaapi_encode_h264_close(AVCodecContext *avctx)
924{
925 VAAPIEncodeContext *ctx = avctx->priv_data;
926 VAAPIEncodeH264Context *priv = ctx->priv_data;
927
928 if (priv) {
929 ff_cbs_close(&priv->cbc);
930 av_freep(&priv->identifier_string);
931 }
932
933 return ff_vaapi_encode_close(avctx);
934}
935
9629701c
MT
936#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
937 offsetof(VAAPIEncodeH264Options, x))
938#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
939static const AVOption vaapi_encode_h264_options[] = {
41ed7ab4 940 { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
9629701c 941 OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 20 }, 0, 52, FLAGS },
fcf536b1 942 { "quality", "Set encode quality (trades off against speed, higher is faster)",
a86aa160
MT
943 OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8, FLAGS },
944 { "low_power", "Use low-power encoding mode (experimental: only supported "
945 "on some platforms, does not support all features)",
946 OFFSET(low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS },
7a4fac5e 947
820a4483
MT
948 { "aud", "Include AUD",
949 OFFSET(aud), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS },
950
7a4fac5e
MT
951 { "sei", "Set SEI to include",
952 OFFSET(sei), AV_OPT_TYPE_FLAGS,
953 { .i64 = SEI_IDENTIFIER | SEI_TIMING },
954 0, INT_MAX, FLAGS, "sei" },
955 { "identifier", "Include encoder version identifier",
956 0, AV_OPT_TYPE_CONST, { .i64 = SEI_IDENTIFIER },
957 INT_MIN, INT_MAX, FLAGS, "sei" },
958 { "timing", "Include timing parameters (buffering_period and pic_timing)",
959 0, AV_OPT_TYPE_CONST, { .i64 = SEI_TIMING },
960 INT_MIN, INT_MAX, FLAGS, "sei" },
9629701c
MT
961 { NULL },
962};
963
2c62fcdf
MT
964static const AVCodecDefault vaapi_encode_h264_defaults[] = {
965 { "profile", "100" },
966 { "level", "51" },
967 { "b", "0" },
968 { "bf", "2" },
969 { "g", "120" },
2c62fcdf
MT
970 { "i_qfactor", "1.0" },
971 { "i_qoffset", "0.0" },
972 { "b_qfactor", "1.2" },
973 { "b_qoffset", "0.0" },
eddfb572 974 { "qmin", "0" },
2c62fcdf
MT
975 { NULL },
976};
977
978static const AVClass vaapi_encode_h264_class = {
979 .class_name = "h264_vaapi",
980 .item_name = av_default_item_name,
9629701c 981 .option = vaapi_encode_h264_options,
2c62fcdf
MT
982 .version = LIBAVUTIL_VERSION_INT,
983};
984
985AVCodec ff_h264_vaapi_encoder = {
986 .name = "h264_vaapi",
987 .long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
988 .type = AVMEDIA_TYPE_VIDEO,
989 .id = AV_CODEC_ID_H264,
9629701c
MT
990 .priv_data_size = (sizeof(VAAPIEncodeContext) +
991 sizeof(VAAPIEncodeH264Options)),
2c62fcdf
MT
992 .init = &vaapi_encode_h264_init,
993 .encode2 = &ff_vaapi_encode2,
7a4fac5e 994 .close = &vaapi_encode_h264_close,
2c62fcdf
MT
995 .priv_class = &vaapi_encode_h264_class,
996 .capabilities = AV_CODEC_CAP_DELAY,
997 .defaults = vaapi_encode_h264_defaults,
998 .pix_fmts = (const enum AVPixelFormat[]) {
999 AV_PIX_FMT_VAAPI,
1000 AV_PIX_FMT_NONE,
1001 },
1002};