vaapi_encode: Add support for writing arbitrary additional packed headers
[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
19#include <va/va.h>
20#include <va/va_enc_h264.h>
21
22#include "libavutil/avassert.h"
23#include "libavutil/internal.h"
24#include "libavutil/opt.h"
25#include "libavutil/pixfmt.h"
26
27#include "avcodec.h"
28#include "h264.h"
29#include "internal.h"
30#include "vaapi_encode.h"
31#include "vaapi_encode_h26x.h"
32
33enum {
34 SLICE_TYPE_P = 0,
35 SLICE_TYPE_B = 1,
36 SLICE_TYPE_I = 2,
37 SLICE_TYPE_SP = 3,
38 SLICE_TYPE_SI = 4,
39};
40
41// This structure contains all possibly-useful per-sequence syntax elements
42// which are not already contained in the various VAAPI structures.
43typedef struct VAAPIEncodeH264MiscSequenceParams {
44 unsigned int profile_idc;
45 char constraint_set0_flag;
46 char constraint_set1_flag;
47 char constraint_set2_flag;
48 char constraint_set3_flag;
49 char constraint_set4_flag;
50 char constraint_set5_flag;
51
52 char separate_colour_plane_flag;
53 char qpprime_y_zero_transform_bypass_flag;
54
55 char gaps_in_frame_num_allowed_flag;
56 char delta_pic_order_always_zero_flag;
57 char bottom_field_pic_order_in_frame_present_flag;
58
59 unsigned int num_slice_groups_minus1;
60 unsigned int slice_group_map_type;
61
62 int pic_init_qs_minus26;
63
081961f8
MT
64 char overscan_info_present_flag;
65 char overscan_appropriate_flag;
66
67 char video_signal_type_present_flag;
68 unsigned int video_format;
69 char video_full_range_flag;
70 char colour_description_present_flag;
71 unsigned int colour_primaries;
72 unsigned int transfer_characteristics;
73 unsigned int matrix_coefficients;
74
75 char chroma_loc_info_present_flag;
76 unsigned int chroma_sample_loc_type_top_field;
77 unsigned int chroma_sample_loc_type_bottom_field;
78
79 // Some timing elements are in VAEncSequenceParameterBufferH264.
80 char fixed_frame_rate_flag;
81
82 char nal_hrd_parameters_present_flag;
83 char vcl_hrd_parameters_present_flag;
84 char low_delay_hrd_flag;
85 char pic_struct_present_flag;
86 char bitstream_restriction_flag;
2c62fcdf
MT
87} VAAPIEncodeH264MiscSequenceParams;
88
89// This structure contains all possibly-useful per-slice syntax elements
90// which are not already contained in the various VAAPI structures.
91typedef struct VAAPIEncodeH264MiscSliceParams {
92 unsigned int nal_unit_type;
93 unsigned int nal_ref_idc;
94
95 unsigned int colour_plane_id;
96 char field_pic_flag;
97 char bottom_field_flag;
98
99 unsigned int redundant_pic_cnt;
100
101 char sp_for_switch_flag;
102 int slice_qs_delta;
103
104 char ref_pic_list_modification_flag_l0;
105 char ref_pic_list_modification_flag_l1;
106
107 char no_output_of_prior_pics_flag;
108 char long_term_reference_flag;
109 char adaptive_ref_pic_marking_mode_flag;
110} VAAPIEncodeH264MiscSliceParams;
111
112typedef struct VAAPIEncodeH264Slice {
113 VAAPIEncodeH264MiscSliceParams misc_slice_params;
114} VAAPIEncodeH264Slice;
115
116typedef struct VAAPIEncodeH264Context {
117 VAAPIEncodeH264MiscSequenceParams misc_sequence_params;
118
119 int mb_width;
120 int mb_height;
121
122 int fixed_qp_idr;
123 int fixed_qp_p;
124 int fixed_qp_b;
125
b51c7c6b 126 int next_frame_num;
2c62fcdf 127 int64_t idr_pic_count;
2c62fcdf 128
6e8f66fc
MT
129 // Rate control configuration.
130 struct {
131 VAEncMiscParameterBuffer misc;
132 VAEncMiscParameterRateControl rc;
133 } rc_params;
134 struct {
135 VAEncMiscParameterBuffer misc;
136 VAEncMiscParameterHRD hrd;
137 } hrd_params;
fcf536b1
MT
138
139#if VA_CHECK_VERSION(0, 36, 0)
140 // Speed-quality tradeoff setting.
141 struct {
142 VAEncMiscParameterBuffer misc;
143 VAEncMiscParameterBufferQualityLevel quality;
144 } quality_params;
145#endif
2c62fcdf
MT
146} VAAPIEncodeH264Context;
147
9629701c
MT
148typedef struct VAAPIEncodeH264Options {
149 int qp;
fcf536b1 150 int quality;
a86aa160 151 int low_power;
9629701c
MT
152} VAAPIEncodeH264Options;
153
2c62fcdf
MT
154
155#define vseq_var(name) vseq->name, name
156#define vseq_field(name) vseq->seq_fields.bits.name, name
081961f8 157#define vvui_field(name) vseq->vui_fields.bits.name, name
2c62fcdf
MT
158#define vpic_var(name) vpic->name, name
159#define vpic_field(name) vpic->pic_fields.bits.name, name
160#define vslice_var(name) vslice->name, name
161#define vslice_field(name) vslice->slice_fields.bits.name, name
162#define mseq_var(name) mseq->name, name
163#define mslice_var(name) mslice->name, name
164
165static void vaapi_encode_h264_write_nal_header(PutBitContext *pbc,
166 int nal_unit_type, int nal_ref_idc)
167{
168 u(1, 0, forbidden_zero_bit);
169 u(2, nal_ref_idc, nal_ref_idc);
170 u(5, nal_unit_type, nal_unit_type);
171}
172
173static void vaapi_encode_h264_write_trailing_rbsp(PutBitContext *pbc)
174{
175 u(1, 1, rbsp_stop_one_bit);
176 while (put_bits_count(pbc) & 7)
177 u(1, 0, rbsp_alignment_zero_bit);
178}
179
081961f8
MT
180static void vaapi_encode_h264_write_vui(PutBitContext *pbc,
181 VAAPIEncodeContext *ctx)
182{
183 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
184 VAAPIEncodeH264Context *priv = ctx->priv_data;
185 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
186
187 u(1, vvui_field(aspect_ratio_info_present_flag));
188 if (vseq->vui_fields.bits.aspect_ratio_info_present_flag) {
189 u(8, vseq_var(aspect_ratio_idc));
190 if (vseq->aspect_ratio_idc == 255) {
191 u(16, vseq_var(sar_width));
192 u(16, vseq_var(sar_height));
193 }
194 }
195
196 u(1, mseq_var(overscan_info_present_flag));
197 if (mseq->overscan_info_present_flag)
198 u(1, mseq_var(overscan_appropriate_flag));
199
200 u(1, mseq_var(video_signal_type_present_flag));
201 if (mseq->video_signal_type_present_flag) {
202 u(3, mseq_var(video_format));
203 u(1, mseq_var(video_full_range_flag));
204 u(1, mseq_var(colour_description_present_flag));
205 if (mseq->colour_description_present_flag) {
206 u(8, mseq_var(colour_primaries));
207 u(8, mseq_var(transfer_characteristics));
208 u(8, mseq_var(matrix_coefficients));
209 }
210 }
211
212 u(1, mseq_var(chroma_loc_info_present_flag));
213 if (mseq->chroma_loc_info_present_flag) {
214 ue(mseq_var(chroma_sample_loc_type_top_field));
215 ue(mseq_var(chroma_sample_loc_type_bottom_field));
216 }
217
218 u(1, vvui_field(timing_info_present_flag));
219 if (vseq->vui_fields.bits.timing_info_present_flag) {
220 u(32, vseq_var(num_units_in_tick));
221 u(32, vseq_var(time_scale));
222 u(1, mseq_var(fixed_frame_rate_flag));
223 }
224
225 u(1, mseq_var(nal_hrd_parameters_present_flag));
226 if (mseq->nal_hrd_parameters_present_flag) {
227 av_assert0(0 && "nal hrd parameters not supported");
228 }
229 u(1, mseq_var(vcl_hrd_parameters_present_flag));
230 if (mseq->vcl_hrd_parameters_present_flag) {
231 av_assert0(0 && "vcl hrd parameters not supported");
232 }
233
234 if (mseq->nal_hrd_parameters_present_flag ||
235 mseq->vcl_hrd_parameters_present_flag)
236 u(1, mseq_var(low_delay_hrd_flag));
237 u(1, mseq_var(pic_struct_present_flag));
238
239 u(1, vvui_field(bitstream_restriction_flag));
240 if (vseq->vui_fields.bits.bitstream_restriction_flag) {
241 av_assert0(0 && "bitstream restrictions not supported");
242 }
243}
244
2c62fcdf
MT
245static void vaapi_encode_h264_write_sps(PutBitContext *pbc,
246 VAAPIEncodeContext *ctx)
247{
248 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
249 VAAPIEncodeH264Context *priv = ctx->priv_data;
250 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
251 int i;
252
253 vaapi_encode_h264_write_nal_header(pbc, NAL_SPS, 3);
254
255 u(8, mseq_var(profile_idc));
256 u(1, mseq_var(constraint_set0_flag));
257 u(1, mseq_var(constraint_set1_flag));
258 u(1, mseq_var(constraint_set2_flag));
259 u(1, mseq_var(constraint_set3_flag));
260 u(1, mseq_var(constraint_set4_flag));
261 u(1, mseq_var(constraint_set5_flag));
262 u(2, 0, reserved_zero_2bits);
263
264 u(8, vseq_var(level_idc));
265
266 ue(vseq_var(seq_parameter_set_id));
267
268 if (mseq->profile_idc == 100 || mseq->profile_idc == 110 ||
269 mseq->profile_idc == 122 || mseq->profile_idc == 244 ||
270 mseq->profile_idc == 44 || mseq->profile_idc == 83 ||
271 mseq->profile_idc == 86 || mseq->profile_idc == 118 ||
272 mseq->profile_idc == 128 || mseq->profile_idc == 138) {
273 ue(vseq_field(chroma_format_idc));
274
275 if (vseq->seq_fields.bits.chroma_format_idc == 3)
276 u(1, mseq_var(separate_colour_plane_flag));
277
278 ue(vseq_var(bit_depth_luma_minus8));
279 ue(vseq_var(bit_depth_chroma_minus8));
280
281 u(1, mseq_var(qpprime_y_zero_transform_bypass_flag));
282
283 u(1, vseq_field(seq_scaling_matrix_present_flag));
284 if (vseq->seq_fields.bits.seq_scaling_matrix_present_flag) {
285 av_assert0(0 && "scaling matrices not supported");
286 }
287 }
288
289 ue(vseq_field(log2_max_frame_num_minus4));
290 ue(vseq_field(pic_order_cnt_type));
291
292 if (vseq->seq_fields.bits.pic_order_cnt_type == 0) {
293 ue(vseq_field(log2_max_pic_order_cnt_lsb_minus4));
294 } else if (vseq->seq_fields.bits.pic_order_cnt_type == 1) {
295 u(1, mseq_var(delta_pic_order_always_zero_flag));
296 se(vseq_var(offset_for_non_ref_pic));
297 se(vseq_var(offset_for_top_to_bottom_field));
298 ue(vseq_var(num_ref_frames_in_pic_order_cnt_cycle));
299
300 for (i = 0; i < vseq->num_ref_frames_in_pic_order_cnt_cycle; i++)
301 se(vseq_var(offset_for_ref_frame[i]));
302 }
303
304 ue(vseq_var(max_num_ref_frames));
305 u(1, mseq_var(gaps_in_frame_num_allowed_flag));
306
307 ue(vseq->picture_width_in_mbs - 1, pic_width_in_mbs_minus1);
308 ue(vseq->picture_height_in_mbs - 1, pic_height_in_mbs_minus1);
309
310 u(1, vseq_field(frame_mbs_only_flag));
311 if (!vseq->seq_fields.bits.frame_mbs_only_flag)
312 u(1, vseq_field(mb_adaptive_frame_field_flag));
313
314 u(1, vseq_field(direct_8x8_inference_flag));
315
316 u(1, vseq_var(frame_cropping_flag));
317 if (vseq->frame_cropping_flag) {
318 ue(vseq_var(frame_crop_left_offset));
319 ue(vseq_var(frame_crop_right_offset));
320 ue(vseq_var(frame_crop_top_offset));
321 ue(vseq_var(frame_crop_bottom_offset));
322 }
323
081961f8
MT
324 u(1, vseq_var(vui_parameters_present_flag));
325 if (vseq->vui_parameters_present_flag)
326 vaapi_encode_h264_write_vui(pbc, ctx);
2c62fcdf
MT
327
328 vaapi_encode_h264_write_trailing_rbsp(pbc);
329}
330
331static void vaapi_encode_h264_write_pps(PutBitContext *pbc,
332 VAAPIEncodeContext *ctx)
333{
334 VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params;
335 VAAPIEncodeH264Context *priv = ctx->priv_data;
336 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
337
338 vaapi_encode_h264_write_nal_header(pbc, NAL_PPS, 3);
339
340 ue(vpic_var(pic_parameter_set_id));
341 ue(vpic_var(seq_parameter_set_id));
342
343 u(1, vpic_field(entropy_coding_mode_flag));
344 u(1, mseq_var(bottom_field_pic_order_in_frame_present_flag));
345
346 ue(mseq_var(num_slice_groups_minus1));
347 if (mseq->num_slice_groups_minus1 > 0) {
348 ue(mseq_var(slice_group_map_type));
349 av_assert0(0 && "slice groups not supported");
350 }
351
352 ue(vpic_var(num_ref_idx_l0_active_minus1));
353 ue(vpic_var(num_ref_idx_l1_active_minus1));
354
355 u(1, vpic_field(weighted_pred_flag));
356 u(2, vpic_field(weighted_bipred_idc));
357
358 se(vpic->pic_init_qp - 26, pic_init_qp_minus26);
359 se(mseq_var(pic_init_qs_minus26));
360 se(vpic_var(chroma_qp_index_offset));
361
362 u(1, vpic_field(deblocking_filter_control_present_flag));
363 u(1, vpic_field(constrained_intra_pred_flag));
364 u(1, vpic_field(redundant_pic_cnt_present_flag));
365 u(1, vpic_field(transform_8x8_mode_flag));
366
367 u(1, vpic_field(pic_scaling_matrix_present_flag));
368 if (vpic->pic_fields.bits.pic_scaling_matrix_present_flag) {
369 av_assert0(0 && "scaling matrices not supported");
370 }
371
372 se(vpic_var(second_chroma_qp_index_offset));
373
374 vaapi_encode_h264_write_trailing_rbsp(pbc);
375}
376
377static void vaapi_encode_h264_write_slice_header2(PutBitContext *pbc,
378 VAAPIEncodeContext *ctx,
379 VAAPIEncodePicture *pic,
380 VAAPIEncodeSlice *slice)
381{
382 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
383 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
384 VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params;
385 VAAPIEncodeH264Context *priv = ctx->priv_data;
386 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
387 VAAPIEncodeH264Slice *pslice = slice->priv_data;
388 VAAPIEncodeH264MiscSliceParams *mslice = &pslice->misc_slice_params;
389
390 vaapi_encode_h264_write_nal_header(pbc, mslice->nal_unit_type,
391 mslice->nal_ref_idc);
392
393 ue(vslice->macroblock_address, first_mb_in_slice);
394 ue(vslice_var(slice_type));
395 ue(vpic_var(pic_parameter_set_id));
396
397 if (mseq->separate_colour_plane_flag) {
398 u(2, mslice_var(colour_plane_id));
399 }
400
401 u(4 + vseq->seq_fields.bits.log2_max_frame_num_minus4,
402 (vpic->frame_num &
403 ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1)),
404 frame_num);
405
406 if (!vseq->seq_fields.bits.frame_mbs_only_flag) {
407 u(1, mslice_var(field_pic_flag));
408 if (mslice->field_pic_flag)
409 u(1, mslice_var(bottom_field_flag));
410 }
411
412 if (vpic->pic_fields.bits.idr_pic_flag) {
413 ue(vslice_var(idr_pic_id));
414 }
415
416 if (vseq->seq_fields.bits.pic_order_cnt_type == 0) {
417 u(4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4,
418 vslice_var(pic_order_cnt_lsb));
419 if (mseq->bottom_field_pic_order_in_frame_present_flag &&
420 !mslice->field_pic_flag) {
421 se(vslice_var(delta_pic_order_cnt_bottom));
422 }
423 }
424
425 if (vseq->seq_fields.bits.pic_order_cnt_type == 1 &&
426 !vseq->seq_fields.bits.delta_pic_order_always_zero_flag) {
427 se(vslice_var(delta_pic_order_cnt[0]));
428 if (mseq->bottom_field_pic_order_in_frame_present_flag &&
429 !mslice->field_pic_flag) {
430 se(vslice_var(delta_pic_order_cnt[1]));
431 }
432 }
433
434 if (vpic->pic_fields.bits.redundant_pic_cnt_present_flag) {
435 ue(mslice_var(redundant_pic_cnt));
436 }
437
438 if (vslice->slice_type == SLICE_TYPE_B) {
439 u(1, vslice_var(direct_spatial_mv_pred_flag));
440 }
441
442 if (vslice->slice_type == SLICE_TYPE_P ||
443 vslice->slice_type == SLICE_TYPE_SP ||
444 vslice->slice_type == SLICE_TYPE_B) {
445 u(1, vslice_var(num_ref_idx_active_override_flag));
446 if (vslice->num_ref_idx_active_override_flag) {
447 ue(vslice_var(num_ref_idx_l0_active_minus1));
448 if (vslice->slice_type == SLICE_TYPE_B)
449 ue(vslice_var(num_ref_idx_l1_active_minus1));
450 }
451 }
452
453 if (mslice->nal_unit_type == 20 || mslice->nal_unit_type == 21) {
454 av_assert0(0 && "no MVC support");
455 } else {
456 if (vslice->slice_type % 5 != 2 && vslice->slice_type % 5 != 4) {
457 u(1, mslice_var(ref_pic_list_modification_flag_l0));
458 if (mslice->ref_pic_list_modification_flag_l0) {
459 av_assert0(0 && "ref pic list modification");
460 }
461 }
462 if (vslice->slice_type % 5 == 1) {
463 u(1, mslice_var(ref_pic_list_modification_flag_l1));
464 if (mslice->ref_pic_list_modification_flag_l1) {
465 av_assert0(0 && "ref pic list modification");
466 }
467 }
468 }
469
470 if ((vpic->pic_fields.bits.weighted_pred_flag &&
471 (vslice->slice_type == SLICE_TYPE_P ||
472 vslice->slice_type == SLICE_TYPE_SP)) ||
473 (vpic->pic_fields.bits.weighted_bipred_idc == 1 &&
474 vslice->slice_type == SLICE_TYPE_B)) {
475 av_assert0(0 && "prediction weights not supported");
476 }
477
478 av_assert0(mslice->nal_ref_idc > 0 ==
479 vpic->pic_fields.bits.reference_pic_flag);
480 if (mslice->nal_ref_idc != 0) {
481 if (vpic->pic_fields.bits.idr_pic_flag) {
482 u(1, mslice_var(no_output_of_prior_pics_flag));
483 u(1, mslice_var(long_term_reference_flag));
484 } else {
485 u(1, mslice_var(adaptive_ref_pic_marking_mode_flag));
486 if (mslice->adaptive_ref_pic_marking_mode_flag) {
487 av_assert0(0 && "MMCOs not supported");
488 }
489 }
490 }
491
492 if (vpic->pic_fields.bits.entropy_coding_mode_flag &&
493 vslice->slice_type != SLICE_TYPE_I &&
494 vslice->slice_type != SLICE_TYPE_SI) {
495 ue(vslice_var(cabac_init_idc));
496 }
497
498 se(vslice_var(slice_qp_delta));
499 if (vslice->slice_type == SLICE_TYPE_SP ||
500 vslice->slice_type == SLICE_TYPE_SI) {
501 if (vslice->slice_type == SLICE_TYPE_SP)
502 u(1, mslice_var(sp_for_switch_flag));
503 se(mslice_var(slice_qs_delta));
504 }
505
506 if (vpic->pic_fields.bits.deblocking_filter_control_present_flag) {
507 ue(vslice_var(disable_deblocking_filter_idc));
508 if (vslice->disable_deblocking_filter_idc != 1) {
509 se(vslice_var(slice_alpha_c0_offset_div2));
510 se(vslice_var(slice_beta_offset_div2));
511 }
512 }
513
514 if (mseq->num_slice_groups_minus1 > 0 &&
515 mseq->slice_group_map_type >= 3 && mseq->slice_group_map_type <= 5) {
516 av_assert0(0 && "slice groups not supported");
517 }
518
519 // No alignment - this need not be a byte boundary.
520}
521
522static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx,
523 char *data, size_t *data_len)
524{
525 VAAPIEncodeContext *ctx = avctx->priv_data;
526 PutBitContext pbc;
527 char tmp[256];
528 int err;
529 size_t nal_len, bit_len, bit_pos, next_len;
530
531 bit_len = *data_len;
532 bit_pos = 0;
533
534 init_put_bits(&pbc, tmp, sizeof(tmp));
535 vaapi_encode_h264_write_sps(&pbc, ctx);
536 nal_len = put_bits_count(&pbc);
537 flush_put_bits(&pbc);
538
539 next_len = bit_len - bit_pos;
540 err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
541 &next_len,
542 tmp, nal_len);
543 if (err < 0)
544 return err;
545 bit_pos += next_len;
546
547 init_put_bits(&pbc, tmp, sizeof(tmp));
548 vaapi_encode_h264_write_pps(&pbc, ctx);
549 nal_len = put_bits_count(&pbc);
550 flush_put_bits(&pbc);
551
552 next_len = bit_len - bit_pos;
553 err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
554 &next_len,
555 tmp, nal_len);
556 if (err < 0)
557 return err;
558 bit_pos += next_len;
559
560 *data_len = bit_pos;
561 return 0;
562}
563
564static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx,
565 VAAPIEncodePicture *pic,
566 VAAPIEncodeSlice *slice,
567 char *data, size_t *data_len)
568{
569 VAAPIEncodeContext *ctx = avctx->priv_data;
570 PutBitContext pbc;
571 char tmp[256];
572 size_t header_len;
573
574 init_put_bits(&pbc, tmp, sizeof(tmp));
575 vaapi_encode_h264_write_slice_header2(&pbc, ctx, pic, slice);
576 header_len = put_bits_count(&pbc);
577 flush_put_bits(&pbc);
578
579 return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len,
580 tmp, header_len);
581}
582
583static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
584{
585 VAAPIEncodeContext *ctx = avctx->priv_data;
586 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
587 VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params;
588 VAAPIEncodeH264Context *priv = ctx->priv_data;
589 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
590 int i;
591
592 {
593 vseq->seq_parameter_set_id = 0;
594
595 vseq->level_idc = avctx->level;
596
597 vseq->max_num_ref_frames = 2;
598
599 vseq->picture_width_in_mbs = priv->mb_width;
600 vseq->picture_height_in_mbs = priv->mb_height;
601
602 vseq->seq_fields.bits.chroma_format_idc = 1;
603 vseq->seq_fields.bits.frame_mbs_only_flag = 1;
604 vseq->seq_fields.bits.direct_8x8_inference_flag = 1;
605 vseq->seq_fields.bits.log2_max_frame_num_minus4 = 4;
606 vseq->seq_fields.bits.pic_order_cnt_type = 0;
607
608 if (ctx->input_width != ctx->aligned_width ||
609 ctx->input_height != ctx->aligned_height) {
610 vseq->frame_cropping_flag = 1;
611
612 vseq->frame_crop_left_offset = 0;
613 vseq->frame_crop_right_offset =
614 (ctx->aligned_width - ctx->input_width) / 2;
615 vseq->frame_crop_top_offset = 0;
616 vseq->frame_crop_bottom_offset =
617 (ctx->aligned_height - ctx->input_height) / 2;
618 } else {
619 vseq->frame_cropping_flag = 0;
620 }
6e8f66fc 621
081961f8
MT
622 vseq->vui_parameters_present_flag = 1;
623 if (avctx->sample_aspect_ratio.num != 0) {
624 vseq->vui_fields.bits.aspect_ratio_info_present_flag = 1;
625 // There is a large enum of these which we could support
626 // individually rather than using the generic X/Y form?
627 if (avctx->sample_aspect_ratio.num ==
628 avctx->sample_aspect_ratio.den) {
629 vseq->aspect_ratio_idc = 1;
630 } else {
631 vseq->aspect_ratio_idc = 255; // Extended SAR.
632 vseq->sar_width = avctx->sample_aspect_ratio.num;
633 vseq->sar_height = avctx->sample_aspect_ratio.den;
634 }
635 }
636 if (avctx->color_primaries != AVCOL_PRI_UNSPECIFIED ||
637 avctx->color_trc != AVCOL_TRC_UNSPECIFIED ||
638 avctx->colorspace != AVCOL_SPC_UNSPECIFIED) {
639 mseq->video_signal_type_present_flag = 1;
640 mseq->video_format = 5; // Unspecified.
641 mseq->video_full_range_flag = 0;
642 mseq->colour_description_present_flag = 1;
643 // These enums are derived from the standard and hence
644 // we can just use the values directly.
645 mseq->colour_primaries = avctx->color_primaries;
646 mseq->transfer_characteristics = avctx->color_trc;
647 mseq->matrix_coefficients = avctx->colorspace;
648 }
649
6e8f66fc 650 vseq->bits_per_second = avctx->bit_rate;
081961f8
MT
651
652 vseq->vui_fields.bits.timing_info_present_flag = 1;
6e8f66fc
MT
653 if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
654 vseq->num_units_in_tick = avctx->framerate.num;
655 vseq->time_scale = 2 * avctx->framerate.den;
081961f8 656 mseq->fixed_frame_rate_flag = 1;
6e8f66fc
MT
657 } else {
658 vseq->num_units_in_tick = avctx->time_base.num;
659 vseq->time_scale = 2 * avctx->time_base.den;
081961f8 660 mseq->fixed_frame_rate_flag = 0;
6e8f66fc
MT
661 }
662
663 vseq->intra_period = ctx->p_per_i * (ctx->b_per_p + 1);
664 vseq->intra_idr_period = vseq->intra_period;
665 vseq->ip_period = ctx->b_per_p + 1;
2c62fcdf
MT
666 }
667
668 {
669 vpic->CurrPic.picture_id = VA_INVALID_ID;
670 vpic->CurrPic.flags = VA_PICTURE_H264_INVALID;
671
672 for (i = 0; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
673 vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID;
674 vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
675 }
676
677 vpic->coded_buf = VA_INVALID_ID;
678
679 vpic->pic_parameter_set_id = 0;
680 vpic->seq_parameter_set_id = 0;
681
682 vpic->num_ref_idx_l0_active_minus1 = 0;
683 vpic->num_ref_idx_l1_active_minus1 = 0;
684
685 vpic->pic_fields.bits.entropy_coding_mode_flag =
686 ((avctx->profile & 0xff) != 66);
687 vpic->pic_fields.bits.weighted_pred_flag = 0;
688 vpic->pic_fields.bits.weighted_bipred_idc = 0;
689 vpic->pic_fields.bits.transform_8x8_mode_flag =
690 ((avctx->profile & 0xff) >= 100);
691
692 vpic->pic_init_qp = priv->fixed_qp_idr;
693 }
694
695 {
696 mseq->profile_idc = avctx->profile & 0xff;
697
698 if (avctx->profile & FF_PROFILE_H264_CONSTRAINED)
699 mseq->constraint_set1_flag = 1;
700 if (avctx->profile & FF_PROFILE_H264_INTRA)
701 mseq->constraint_set3_flag = 1;
702 }
703
704 return 0;
705}
706
707static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
708 VAAPIEncodePicture *pic)
709{
710 VAAPIEncodeContext *ctx = avctx->priv_data;
711 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
712 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
713 VAAPIEncodeH264Context *priv = ctx->priv_data;
714 int i;
715
716 if (pic->type == PICTURE_TYPE_IDR) {
717 av_assert0(pic->display_order == pic->encode_order);
b51c7c6b
MT
718 vpic->frame_num = 0;
719 priv->next_frame_num = 1;
2c62fcdf 720 } else {
b51c7c6b
MT
721 vpic->frame_num = priv->next_frame_num;
722 if (pic->type != PICTURE_TYPE_B) {
723 // nal_ref_idc != 0
724 ++priv->next_frame_num;
725 }
2c62fcdf
MT
726 }
727
b51c7c6b 728 vpic->frame_num = vpic->frame_num &
2c62fcdf
MT
729 ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1);
730
731 vpic->CurrPic.picture_id = pic->recon_surface;
732 vpic->CurrPic.frame_idx = vpic->frame_num;
733 vpic->CurrPic.flags = 0;
734 vpic->CurrPic.TopFieldOrderCnt = pic->display_order;
735 vpic->CurrPic.BottomFieldOrderCnt = pic->display_order;
736
737 for (i = 0; i < pic->nb_refs; i++) {
738 VAAPIEncodePicture *ref = pic->refs[i];
b51c7c6b 739 av_assert0(ref && ref->encode_order < pic->encode_order);
2c62fcdf 740 vpic->ReferenceFrames[i].picture_id = ref->recon_surface;
b51c7c6b 741 vpic->ReferenceFrames[i].frame_idx = ref->encode_order;
2c62fcdf
MT
742 vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
743 vpic->ReferenceFrames[i].TopFieldOrderCnt = ref->display_order;
744 vpic->ReferenceFrames[i].BottomFieldOrderCnt = ref->display_order;
745 }
746 for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
747 vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID;
748 vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
749 }
750
751 vpic->coded_buf = pic->output_buffer;
752
753 vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR);
754 vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B);
755
756 pic->nb_slices = 1;
757
758 return 0;
759}
760
761static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
762 VAAPIEncodePicture *pic,
763 VAAPIEncodeSlice *slice)
764{
765 VAAPIEncodeContext *ctx = avctx->priv_data;
766 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
767 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
768 VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params;
769 VAAPIEncodeH264Context *priv = ctx->priv_data;
770 VAAPIEncodeH264Slice *pslice;
771 VAAPIEncodeH264MiscSliceParams *mslice;
772 int i;
773
774 slice->priv_data = av_mallocz(sizeof(*pslice));
775 if (!slice->priv_data)
776 return AVERROR(ENOMEM);
777 pslice = slice->priv_data;
778 mslice = &pslice->misc_slice_params;
779
780 if (pic->type == PICTURE_TYPE_IDR)
781 mslice->nal_unit_type = NAL_IDR_SLICE;
782 else
783 mslice->nal_unit_type = NAL_SLICE;
784
785 switch (pic->type) {
786 case PICTURE_TYPE_IDR:
787 vslice->slice_type = SLICE_TYPE_I;
788 mslice->nal_ref_idc = 3;
789 break;
790 case PICTURE_TYPE_I:
791 vslice->slice_type = SLICE_TYPE_I;
792 mslice->nal_ref_idc = 2;
793 break;
794 case PICTURE_TYPE_P:
795 vslice->slice_type = SLICE_TYPE_P;
796 mslice->nal_ref_idc = 1;
797 break;
798 case PICTURE_TYPE_B:
799 vslice->slice_type = SLICE_TYPE_B;
800 mslice->nal_ref_idc = 0;
801 break;
802 default:
803 av_assert0(0 && "invalid picture type");
804 }
805
806 // Only one slice per frame.
807 vslice->macroblock_address = 0;
808 vslice->num_macroblocks = priv->mb_width * priv->mb_height;
809
810 vslice->macroblock_info = VA_INVALID_ID;
811
812 vslice->pic_parameter_set_id = vpic->pic_parameter_set_id;
813 vslice->idr_pic_id = priv->idr_pic_count++;
814
815 vslice->pic_order_cnt_lsb = pic->display_order &
816 ((1 << (4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4)) - 1);
817
818 for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) {
819 vslice->RefPicList0[i].picture_id = VA_INVALID_ID;
820 vslice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
821 vslice->RefPicList1[i].picture_id = VA_INVALID_ID;
822 vslice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
823 }
824
825 av_assert0(pic->nb_refs <= 2);
826 if (pic->nb_refs >= 1) {
41ed7ab4 827 // Backward reference for P- or B-frame.
2c62fcdf
MT
828 av_assert0(pic->type == PICTURE_TYPE_P ||
829 pic->type == PICTURE_TYPE_B);
830
831 vslice->num_ref_idx_l0_active_minus1 = 0;
832 vslice->RefPicList0[0] = vpic->ReferenceFrames[0];
833 }
834 if (pic->nb_refs >= 2) {
41ed7ab4 835 // Forward reference for B-frame.
2c62fcdf
MT
836 av_assert0(pic->type == PICTURE_TYPE_B);
837
838 vslice->num_ref_idx_l1_active_minus1 = 0;
839 vslice->RefPicList1[0] = vpic->ReferenceFrames[1];
840 }
841
842 if (pic->type == PICTURE_TYPE_B)
843 vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp;
844 else if (pic->type == PICTURE_TYPE_P)
845 vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp;
846 else
847 vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp;
848
849 vslice->direct_spatial_mv_pred_flag = 1;
850
851 return 0;
852}
853
6e8f66fc
MT
854static av_cold int vaapi_encode_h264_init_constant_bitrate(AVCodecContext *avctx)
855{
856 VAAPIEncodeContext *ctx = avctx->priv_data;
857 VAAPIEncodeH264Context *priv = ctx->priv_data;
858 int hrd_buffer_size;
859 int hrd_initial_buffer_fullness;
860
861 if (avctx->rc_buffer_size)
862 hrd_buffer_size = avctx->rc_buffer_size;
863 else
864 hrd_buffer_size = avctx->bit_rate;
865 if (avctx->rc_initial_buffer_occupancy)
866 hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
867 else
868 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
869
870 priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
871 priv->rc_params.rc = (VAEncMiscParameterRateControl) {
872 .bits_per_second = avctx->bit_rate,
873 .target_percentage = 66,
874 .window_size = 1000,
875 .initial_qp = (avctx->qmax >= 0 ? avctx->qmax : 40),
876 .min_qp = (avctx->qmin >= 0 ? avctx->qmin : 18),
877 .basic_unit_size = 0,
878 };
879 ctx->global_params[ctx->nb_global_params] =
880 &priv->rc_params.misc;
881 ctx->global_params_size[ctx->nb_global_params++] =
882 sizeof(priv->rc_params);
883
884 priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
885 priv->hrd_params.hrd = (VAEncMiscParameterHRD) {
886 .initial_buffer_fullness = hrd_initial_buffer_fullness,
887 .buffer_size = hrd_buffer_size,
888 };
889 ctx->global_params[ctx->nb_global_params] =
890 &priv->hrd_params.misc;
891 ctx->global_params_size[ctx->nb_global_params++] =
892 sizeof(priv->hrd_params);
893
894 // These still need to be set for pic_init_qp/slice_qp_delta.
895 priv->fixed_qp_idr = 26;
896 priv->fixed_qp_p = 26;
897 priv->fixed_qp_b = 26;
898
899 av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %d bps.\n",
900 avctx->bit_rate);
901 return 0;
902}
903
904static av_cold int vaapi_encode_h264_init_fixed_qp(AVCodecContext *avctx)
905{
906 VAAPIEncodeContext *ctx = avctx->priv_data;
907 VAAPIEncodeH264Context *priv = ctx->priv_data;
9629701c 908 VAAPIEncodeH264Options *opt = ctx->codec_options;
6e8f66fc 909
9629701c 910 priv->fixed_qp_p = opt->qp;
6e8f66fc
MT
911 if (avctx->i_quant_factor > 0.0)
912 priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
913 avctx->i_quant_offset) + 0.5);
914 else
915 priv->fixed_qp_idr = priv->fixed_qp_p;
916 if (avctx->b_quant_factor > 0.0)
917 priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
918 avctx->b_quant_offset) + 0.5);
919 else
920 priv->fixed_qp_b = priv->fixed_qp_p;
921
922 av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
41ed7ab4 923 "%d / %d / %d for IDR- / P- / B-frames.\n",
6e8f66fc
MT
924 priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
925 return 0;
926}
927
2c62fcdf
MT
928static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
929{
f6b85523
MT
930 static const VAConfigAttrib default_config_attributes[] = {
931 { .type = VAConfigAttribRTFormat,
932 .value = VA_RT_FORMAT_YUV420 },
f6b85523
MT
933 { .type = VAConfigAttribEncPackedHeaders,
934 .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
935 VA_ENC_PACKED_HEADER_SLICE) },
936 };
937
2c62fcdf
MT
938 VAAPIEncodeContext *ctx = avctx->priv_data;
939 VAAPIEncodeH264Context *priv = ctx->priv_data;
fcf536b1 940 VAAPIEncodeH264Options *opt = ctx->codec_options;
6e8f66fc 941 int i, err;
2c62fcdf
MT
942
943 switch (avctx->profile) {
944 case FF_PROFILE_H264_CONSTRAINED_BASELINE:
945 ctx->va_profile = VAProfileH264ConstrainedBaseline;
946 break;
947 case FF_PROFILE_H264_BASELINE:
948 ctx->va_profile = VAProfileH264Baseline;
949 break;
950 case FF_PROFILE_H264_MAIN:
951 ctx->va_profile = VAProfileH264Main;
952 break;
953 case FF_PROFILE_H264_EXTENDED:
954 av_log(avctx, AV_LOG_ERROR, "H.264 extended profile "
955 "is not supported.\n");
956 return AVERROR_PATCHWELCOME;
957 case FF_PROFILE_UNKNOWN:
958 case FF_PROFILE_H264_HIGH:
959 ctx->va_profile = VAProfileH264High;
960 break;
961 case FF_PROFILE_H264_HIGH_10:
962 case FF_PROFILE_H264_HIGH_10_INTRA:
963 av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles "
964 "are not supported.\n");
965 return AVERROR_PATCHWELCOME;
966 case FF_PROFILE_H264_HIGH_422:
967 case FF_PROFILE_H264_HIGH_422_INTRA:
968 case FF_PROFILE_H264_HIGH_444:
969 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
970 case FF_PROFILE_H264_HIGH_444_INTRA:
971 case FF_PROFILE_H264_CAVLC_444:
972 av_log(avctx, AV_LOG_ERROR, "H.264 non-4:2:0 profiles "
973 "are not supported.\n");
974 return AVERROR_PATCHWELCOME;
975 default:
976 av_log(avctx, AV_LOG_ERROR, "Unknown H.264 profile %d.\n",
977 avctx->profile);
978 return AVERROR(EINVAL);
979 }
a86aa160
MT
980 if (opt->low_power) {
981#if VA_CHECK_VERSION(0, 39, 1)
982 ctx->va_entrypoint = VAEntrypointEncSliceLP;
983#else
984 av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
985 "supported with this VAAPI version.\n");
986 return AVERROR(EINVAL);
987#endif
988 } else {
989 ctx->va_entrypoint = VAEntrypointEncSlice;
990 }
2c62fcdf 991
2c62fcdf
MT
992 ctx->input_width = avctx->width;
993 ctx->input_height = avctx->height;
994 ctx->aligned_width = FFALIGN(ctx->input_width, 16);
995 ctx->aligned_height = FFALIGN(ctx->input_height, 16);
996 priv->mb_width = ctx->aligned_width / 16;
997 priv->mb_height = ctx->aligned_height / 16;
998
f6b85523
MT
999 for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
1000 ctx->config_attributes[ctx->nb_config_attributes++] =
1001 default_config_attributes[i];
1002 }
1003
6e8f66fc
MT
1004 if (avctx->bit_rate > 0) {
1005 ctx->va_rc_mode = VA_RC_CBR;
1006 err = vaapi_encode_h264_init_constant_bitrate(avctx);
1007 } else {
1008 ctx->va_rc_mode = VA_RC_CQP;
1009 err = vaapi_encode_h264_init_fixed_qp(avctx);
1010 }
1011 if (err < 0)
1012 return err;
1013
1014 ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
1015 .type = VAConfigAttribRateControl,
1016 .value = ctx->va_rc_mode,
1017 };
2c62fcdf 1018
fcf536b1
MT
1019 if (opt->quality > 0) {
1020#if VA_CHECK_VERSION(0, 36, 0)
1021 priv->quality_params.misc.type =
1022 VAEncMiscParameterTypeQualityLevel;
1023 priv->quality_params.quality.quality_level = opt->quality;
1024
1025 ctx->global_params[ctx->nb_global_params] =
1026 &priv->quality_params.misc;
1027 ctx->global_params_size[ctx->nb_global_params++] =
1028 sizeof(priv->quality_params);
1029#else
1030 av_log(avctx, AV_LOG_WARNING, "The encode quality option is not "
1031 "supported with this VAAPI version.\n");
1032#endif
1033 }
1034
2c62fcdf
MT
1035 ctx->nb_recon_frames = 20;
1036
1037 return 0;
1038}
1039
1040static VAAPIEncodeType vaapi_encode_type_h264 = {
1041 .priv_data_size = sizeof(VAAPIEncodeH264Context),
1042
1043 .init = &vaapi_encode_h264_init_internal,
1044
1045 .sequence_params_size = sizeof(VAEncSequenceParameterBufferH264),
1046 .init_sequence_params = &vaapi_encode_h264_init_sequence_params,
1047
1048 .picture_params_size = sizeof(VAEncPictureParameterBufferH264),
1049 .init_picture_params = &vaapi_encode_h264_init_picture_params,
1050
1051 .slice_params_size = sizeof(VAEncSliceParameterBufferH264),
1052 .init_slice_params = &vaapi_encode_h264_init_slice_params,
1053
1054 .sequence_header_type = VAEncPackedHeaderSequence,
1055 .write_sequence_header = &vaapi_encode_h264_write_sequence_header,
1056
1057 .slice_header_type = VAEncPackedHeaderH264_Slice,
1058 .write_slice_header = &vaapi_encode_h264_write_slice_header,
1059};
1060
1061static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
1062{
1063 return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h264);
1064}
1065
9629701c
MT
1066#define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
1067 offsetof(VAAPIEncodeH264Options, x))
1068#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1069static const AVOption vaapi_encode_h264_options[] = {
41ed7ab4 1070 { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
9629701c 1071 OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 20 }, 0, 52, FLAGS },
fcf536b1 1072 { "quality", "Set encode quality (trades off against speed, higher is faster)",
a86aa160
MT
1073 OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8, FLAGS },
1074 { "low_power", "Use low-power encoding mode (experimental: only supported "
1075 "on some platforms, does not support all features)",
1076 OFFSET(low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS },
9629701c
MT
1077 { NULL },
1078};
1079
2c62fcdf
MT
1080static const AVCodecDefault vaapi_encode_h264_defaults[] = {
1081 { "profile", "100" },
1082 { "level", "51" },
1083 { "b", "0" },
1084 { "bf", "2" },
1085 { "g", "120" },
2c62fcdf
MT
1086 { "i_qfactor", "1.0" },
1087 { "i_qoffset", "0.0" },
1088 { "b_qfactor", "1.2" },
1089 { "b_qoffset", "0.0" },
1090 { NULL },
1091};
1092
1093static const AVClass vaapi_encode_h264_class = {
1094 .class_name = "h264_vaapi",
1095 .item_name = av_default_item_name,
9629701c 1096 .option = vaapi_encode_h264_options,
2c62fcdf
MT
1097 .version = LIBAVUTIL_VERSION_INT,
1098};
1099
1100AVCodec ff_h264_vaapi_encoder = {
1101 .name = "h264_vaapi",
1102 .long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
1103 .type = AVMEDIA_TYPE_VIDEO,
1104 .id = AV_CODEC_ID_H264,
9629701c
MT
1105 .priv_data_size = (sizeof(VAAPIEncodeContext) +
1106 sizeof(VAAPIEncodeH264Options)),
2c62fcdf
MT
1107 .init = &vaapi_encode_h264_init,
1108 .encode2 = &ff_vaapi_encode2,
1109 .close = &ff_vaapi_encode_close,
1110 .priv_class = &vaapi_encode_h264_class,
1111 .capabilities = AV_CODEC_CAP_DELAY,
1112 .defaults = vaapi_encode_h264_defaults,
1113 .pix_fmts = (const enum AVPixelFormat[]) {
1114 AV_PIX_FMT_VAAPI,
1115 AV_PIX_FMT_NONE,
1116 },
1117};