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