2 * This file is part of FFmpeg.
4 * FFmpeg is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * FFmpeg is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with FFmpeg; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
20 #include <va/va_enc_h264.h>
22 #include "libavutil/avassert.h"
23 #include "libavutil/internal.h"
24 #include "libavutil/opt.h"
25 #include "libavutil/pixfmt.h"
30 #include "vaapi_encode.h"
31 #include "vaapi_encode_h26x.h"
41 // This structure contains all possibly-useful per-sequence syntax elements
42 // which are not already contained in the various VAAPI structures.
43 typedef 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;
52 char separate_colour_plane_flag;
53 char qpprime_y_zero_transform_bypass_flag;
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;
59 unsigned int num_slice_groups_minus1;
60 unsigned int slice_group_map_type;
62 int pic_init_qs_minus26;
64 char vui_parameters_present_flag;
65 } VAAPIEncodeH264MiscSequenceParams;
67 // This structure contains all possibly-useful per-slice syntax elements
68 // which are not already contained in the various VAAPI structures.
69 typedef struct VAAPIEncodeH264MiscSliceParams {
70 unsigned int nal_unit_type;
71 unsigned int nal_ref_idc;
73 unsigned int colour_plane_id;
75 char bottom_field_flag;
77 unsigned int redundant_pic_cnt;
79 char sp_for_switch_flag;
82 char ref_pic_list_modification_flag_l0;
83 char ref_pic_list_modification_flag_l1;
85 char no_output_of_prior_pics_flag;
86 char long_term_reference_flag;
87 char adaptive_ref_pic_marking_mode_flag;
88 } VAAPIEncodeH264MiscSliceParams;
90 typedef struct VAAPIEncodeH264Slice {
91 VAAPIEncodeH264MiscSliceParams misc_slice_params;
92 } VAAPIEncodeH264Slice;
94 typedef struct VAAPIEncodeH264Context {
95 VAAPIEncodeH264MiscSequenceParams misc_sequence_params;
105 int64_t idr_pic_count;
107 // Rate control configuration.
109 VAEncMiscParameterBuffer misc;
110 VAEncMiscParameterRateControl rc;
113 VAEncMiscParameterBuffer misc;
114 VAEncMiscParameterHRD hrd;
117 #if VA_CHECK_VERSION(0, 36, 0)
118 // Speed-quality tradeoff setting.
120 VAEncMiscParameterBuffer misc;
121 VAEncMiscParameterBufferQualityLevel quality;
124 } VAAPIEncodeH264Context;
126 typedef struct VAAPIEncodeH264Options {
130 } VAAPIEncodeH264Options;
133 #define vseq_var(name) vseq->name, name
134 #define vseq_field(name) vseq->seq_fields.bits.name, name
135 #define vpic_var(name) vpic->name, name
136 #define vpic_field(name) vpic->pic_fields.bits.name, name
137 #define vslice_var(name) vslice->name, name
138 #define vslice_field(name) vslice->slice_fields.bits.name, name
139 #define mseq_var(name) mseq->name, name
140 #define mslice_var(name) mslice->name, name
142 static void vaapi_encode_h264_write_nal_header(PutBitContext *pbc,
143 int nal_unit_type, int nal_ref_idc)
145 u(1, 0, forbidden_zero_bit);
146 u(2, nal_ref_idc, nal_ref_idc);
147 u(5, nal_unit_type, nal_unit_type);
150 static void vaapi_encode_h264_write_trailing_rbsp(PutBitContext *pbc)
152 u(1, 1, rbsp_stop_one_bit);
153 while (put_bits_count(pbc) & 7)
154 u(1, 0, rbsp_alignment_zero_bit);
157 static void vaapi_encode_h264_write_sps(PutBitContext *pbc,
158 VAAPIEncodeContext *ctx)
160 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
161 VAAPIEncodeH264Context *priv = ctx->priv_data;
162 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
165 vaapi_encode_h264_write_nal_header(pbc, NAL_SPS, 3);
167 u(8, mseq_var(profile_idc));
168 u(1, mseq_var(constraint_set0_flag));
169 u(1, mseq_var(constraint_set1_flag));
170 u(1, mseq_var(constraint_set2_flag));
171 u(1, mseq_var(constraint_set3_flag));
172 u(1, mseq_var(constraint_set4_flag));
173 u(1, mseq_var(constraint_set5_flag));
174 u(2, 0, reserved_zero_2bits);
176 u(8, vseq_var(level_idc));
178 ue(vseq_var(seq_parameter_set_id));
180 if (mseq->profile_idc == 100 || mseq->profile_idc == 110 ||
181 mseq->profile_idc == 122 || mseq->profile_idc == 244 ||
182 mseq->profile_idc == 44 || mseq->profile_idc == 83 ||
183 mseq->profile_idc == 86 || mseq->profile_idc == 118 ||
184 mseq->profile_idc == 128 || mseq->profile_idc == 138) {
185 ue(vseq_field(chroma_format_idc));
187 if (vseq->seq_fields.bits.chroma_format_idc == 3)
188 u(1, mseq_var(separate_colour_plane_flag));
190 ue(vseq_var(bit_depth_luma_minus8));
191 ue(vseq_var(bit_depth_chroma_minus8));
193 u(1, mseq_var(qpprime_y_zero_transform_bypass_flag));
195 u(1, vseq_field(seq_scaling_matrix_present_flag));
196 if (vseq->seq_fields.bits.seq_scaling_matrix_present_flag) {
197 av_assert0(0 && "scaling matrices not supported");
201 ue(vseq_field(log2_max_frame_num_minus4));
202 ue(vseq_field(pic_order_cnt_type));
204 if (vseq->seq_fields.bits.pic_order_cnt_type == 0) {
205 ue(vseq_field(log2_max_pic_order_cnt_lsb_minus4));
206 } else if (vseq->seq_fields.bits.pic_order_cnt_type == 1) {
207 u(1, mseq_var(delta_pic_order_always_zero_flag));
208 se(vseq_var(offset_for_non_ref_pic));
209 se(vseq_var(offset_for_top_to_bottom_field));
210 ue(vseq_var(num_ref_frames_in_pic_order_cnt_cycle));
212 for (i = 0; i < vseq->num_ref_frames_in_pic_order_cnt_cycle; i++)
213 se(vseq_var(offset_for_ref_frame[i]));
216 ue(vseq_var(max_num_ref_frames));
217 u(1, mseq_var(gaps_in_frame_num_allowed_flag));
219 ue(vseq->picture_width_in_mbs - 1, pic_width_in_mbs_minus1);
220 ue(vseq->picture_height_in_mbs - 1, pic_height_in_mbs_minus1);
222 u(1, vseq_field(frame_mbs_only_flag));
223 if (!vseq->seq_fields.bits.frame_mbs_only_flag)
224 u(1, vseq_field(mb_adaptive_frame_field_flag));
226 u(1, vseq_field(direct_8x8_inference_flag));
228 u(1, vseq_var(frame_cropping_flag));
229 if (vseq->frame_cropping_flag) {
230 ue(vseq_var(frame_crop_left_offset));
231 ue(vseq_var(frame_crop_right_offset));
232 ue(vseq_var(frame_crop_top_offset));
233 ue(vseq_var(frame_crop_bottom_offset));
236 u(1, mseq_var(vui_parameters_present_flag));
238 vaapi_encode_h264_write_trailing_rbsp(pbc);
241 static void vaapi_encode_h264_write_pps(PutBitContext *pbc,
242 VAAPIEncodeContext *ctx)
244 VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params;
245 VAAPIEncodeH264Context *priv = ctx->priv_data;
246 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
248 vaapi_encode_h264_write_nal_header(pbc, NAL_PPS, 3);
250 ue(vpic_var(pic_parameter_set_id));
251 ue(vpic_var(seq_parameter_set_id));
253 u(1, vpic_field(entropy_coding_mode_flag));
254 u(1, mseq_var(bottom_field_pic_order_in_frame_present_flag));
256 ue(mseq_var(num_slice_groups_minus1));
257 if (mseq->num_slice_groups_minus1 > 0) {
258 ue(mseq_var(slice_group_map_type));
259 av_assert0(0 && "slice groups not supported");
262 ue(vpic_var(num_ref_idx_l0_active_minus1));
263 ue(vpic_var(num_ref_idx_l1_active_minus1));
265 u(1, vpic_field(weighted_pred_flag));
266 u(2, vpic_field(weighted_bipred_idc));
268 se(vpic->pic_init_qp - 26, pic_init_qp_minus26);
269 se(mseq_var(pic_init_qs_minus26));
270 se(vpic_var(chroma_qp_index_offset));
272 u(1, vpic_field(deblocking_filter_control_present_flag));
273 u(1, vpic_field(constrained_intra_pred_flag));
274 u(1, vpic_field(redundant_pic_cnt_present_flag));
275 u(1, vpic_field(transform_8x8_mode_flag));
277 u(1, vpic_field(pic_scaling_matrix_present_flag));
278 if (vpic->pic_fields.bits.pic_scaling_matrix_present_flag) {
279 av_assert0(0 && "scaling matrices not supported");
282 se(vpic_var(second_chroma_qp_index_offset));
284 vaapi_encode_h264_write_trailing_rbsp(pbc);
287 static void vaapi_encode_h264_write_slice_header2(PutBitContext *pbc,
288 VAAPIEncodeContext *ctx,
289 VAAPIEncodePicture *pic,
290 VAAPIEncodeSlice *slice)
292 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
293 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
294 VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params;
295 VAAPIEncodeH264Context *priv = ctx->priv_data;
296 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
297 VAAPIEncodeH264Slice *pslice = slice->priv_data;
298 VAAPIEncodeH264MiscSliceParams *mslice = &pslice->misc_slice_params;
300 vaapi_encode_h264_write_nal_header(pbc, mslice->nal_unit_type,
301 mslice->nal_ref_idc);
303 ue(vslice->macroblock_address, first_mb_in_slice);
304 ue(vslice_var(slice_type));
305 ue(vpic_var(pic_parameter_set_id));
307 if (mseq->separate_colour_plane_flag) {
308 u(2, mslice_var(colour_plane_id));
311 u(4 + vseq->seq_fields.bits.log2_max_frame_num_minus4,
313 ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1)),
316 if (!vseq->seq_fields.bits.frame_mbs_only_flag) {
317 u(1, mslice_var(field_pic_flag));
318 if (mslice->field_pic_flag)
319 u(1, mslice_var(bottom_field_flag));
322 if (vpic->pic_fields.bits.idr_pic_flag) {
323 ue(vslice_var(idr_pic_id));
326 if (vseq->seq_fields.bits.pic_order_cnt_type == 0) {
327 u(4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4,
328 vslice_var(pic_order_cnt_lsb));
329 if (mseq->bottom_field_pic_order_in_frame_present_flag &&
330 !mslice->field_pic_flag) {
331 se(vslice_var(delta_pic_order_cnt_bottom));
335 if (vseq->seq_fields.bits.pic_order_cnt_type == 1 &&
336 !vseq->seq_fields.bits.delta_pic_order_always_zero_flag) {
337 se(vslice_var(delta_pic_order_cnt[0]));
338 if (mseq->bottom_field_pic_order_in_frame_present_flag &&
339 !mslice->field_pic_flag) {
340 se(vslice_var(delta_pic_order_cnt[1]));
344 if (vpic->pic_fields.bits.redundant_pic_cnt_present_flag) {
345 ue(mslice_var(redundant_pic_cnt));
348 if (vslice->slice_type == SLICE_TYPE_B) {
349 u(1, vslice_var(direct_spatial_mv_pred_flag));
352 if (vslice->slice_type == SLICE_TYPE_P ||
353 vslice->slice_type == SLICE_TYPE_SP ||
354 vslice->slice_type == SLICE_TYPE_B) {
355 u(1, vslice_var(num_ref_idx_active_override_flag));
356 if (vslice->num_ref_idx_active_override_flag) {
357 ue(vslice_var(num_ref_idx_l0_active_minus1));
358 if (vslice->slice_type == SLICE_TYPE_B)
359 ue(vslice_var(num_ref_idx_l1_active_minus1));
363 if (mslice->nal_unit_type == 20 || mslice->nal_unit_type == 21) {
364 av_assert0(0 && "no MVC support");
366 if (vslice->slice_type % 5 != 2 && vslice->slice_type % 5 != 4) {
367 u(1, mslice_var(ref_pic_list_modification_flag_l0));
368 if (mslice->ref_pic_list_modification_flag_l0) {
369 av_assert0(0 && "ref pic list modification");
372 if (vslice->slice_type % 5 == 1) {
373 u(1, mslice_var(ref_pic_list_modification_flag_l1));
374 if (mslice->ref_pic_list_modification_flag_l1) {
375 av_assert0(0 && "ref pic list modification");
380 if ((vpic->pic_fields.bits.weighted_pred_flag &&
381 (vslice->slice_type == SLICE_TYPE_P ||
382 vslice->slice_type == SLICE_TYPE_SP)) ||
383 (vpic->pic_fields.bits.weighted_bipred_idc == 1 &&
384 vslice->slice_type == SLICE_TYPE_B)) {
385 av_assert0(0 && "prediction weights not supported");
388 av_assert0(mslice->nal_ref_idc > 0 ==
389 vpic->pic_fields.bits.reference_pic_flag);
390 if (mslice->nal_ref_idc != 0) {
391 if (vpic->pic_fields.bits.idr_pic_flag) {
392 u(1, mslice_var(no_output_of_prior_pics_flag));
393 u(1, mslice_var(long_term_reference_flag));
395 u(1, mslice_var(adaptive_ref_pic_marking_mode_flag));
396 if (mslice->adaptive_ref_pic_marking_mode_flag) {
397 av_assert0(0 && "MMCOs not supported");
402 if (vpic->pic_fields.bits.entropy_coding_mode_flag &&
403 vslice->slice_type != SLICE_TYPE_I &&
404 vslice->slice_type != SLICE_TYPE_SI) {
405 ue(vslice_var(cabac_init_idc));
408 se(vslice_var(slice_qp_delta));
409 if (vslice->slice_type == SLICE_TYPE_SP ||
410 vslice->slice_type == SLICE_TYPE_SI) {
411 if (vslice->slice_type == SLICE_TYPE_SP)
412 u(1, mslice_var(sp_for_switch_flag));
413 se(mslice_var(slice_qs_delta));
416 if (vpic->pic_fields.bits.deblocking_filter_control_present_flag) {
417 ue(vslice_var(disable_deblocking_filter_idc));
418 if (vslice->disable_deblocking_filter_idc != 1) {
419 se(vslice_var(slice_alpha_c0_offset_div2));
420 se(vslice_var(slice_beta_offset_div2));
424 if (mseq->num_slice_groups_minus1 > 0 &&
425 mseq->slice_group_map_type >= 3 && mseq->slice_group_map_type <= 5) {
426 av_assert0(0 && "slice groups not supported");
429 // No alignment - this need not be a byte boundary.
432 static int vaapi_encode_h264_write_sequence_header(AVCodecContext *avctx,
433 char *data, size_t *data_len)
435 VAAPIEncodeContext *ctx = avctx->priv_data;
439 size_t nal_len, bit_len, bit_pos, next_len;
444 init_put_bits(&pbc, tmp, sizeof(tmp));
445 vaapi_encode_h264_write_sps(&pbc, ctx);
446 nal_len = put_bits_count(&pbc);
447 flush_put_bits(&pbc);
449 next_len = bit_len - bit_pos;
450 err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
457 init_put_bits(&pbc, tmp, sizeof(tmp));
458 vaapi_encode_h264_write_pps(&pbc, ctx);
459 nal_len = put_bits_count(&pbc);
460 flush_put_bits(&pbc);
462 next_len = bit_len - bit_pos;
463 err = ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data + bit_pos / 8,
474 static int vaapi_encode_h264_write_slice_header(AVCodecContext *avctx,
475 VAAPIEncodePicture *pic,
476 VAAPIEncodeSlice *slice,
477 char *data, size_t *data_len)
479 VAAPIEncodeContext *ctx = avctx->priv_data;
484 init_put_bits(&pbc, tmp, sizeof(tmp));
485 vaapi_encode_h264_write_slice_header2(&pbc, ctx, pic, slice);
486 header_len = put_bits_count(&pbc);
487 flush_put_bits(&pbc);
489 return ff_vaapi_encode_h26x_nal_unit_to_byte_stream(data, data_len,
493 static int vaapi_encode_h264_init_sequence_params(AVCodecContext *avctx)
495 VAAPIEncodeContext *ctx = avctx->priv_data;
496 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
497 VAEncPictureParameterBufferH264 *vpic = ctx->codec_picture_params;
498 VAAPIEncodeH264Context *priv = ctx->priv_data;
499 VAAPIEncodeH264MiscSequenceParams *mseq = &priv->misc_sequence_params;
503 vseq->seq_parameter_set_id = 0;
505 vseq->level_idc = avctx->level;
507 vseq->max_num_ref_frames = 2;
509 vseq->picture_width_in_mbs = priv->mb_width;
510 vseq->picture_height_in_mbs = priv->mb_height;
512 vseq->seq_fields.bits.chroma_format_idc = 1;
513 vseq->seq_fields.bits.frame_mbs_only_flag = 1;
514 vseq->seq_fields.bits.direct_8x8_inference_flag = 1;
515 vseq->seq_fields.bits.log2_max_frame_num_minus4 = 4;
516 vseq->seq_fields.bits.pic_order_cnt_type = 0;
518 if (ctx->input_width != ctx->aligned_width ||
519 ctx->input_height != ctx->aligned_height) {
520 vseq->frame_cropping_flag = 1;
522 vseq->frame_crop_left_offset = 0;
523 vseq->frame_crop_right_offset =
524 (ctx->aligned_width - ctx->input_width) / 2;
525 vseq->frame_crop_top_offset = 0;
526 vseq->frame_crop_bottom_offset =
527 (ctx->aligned_height - ctx->input_height) / 2;
529 vseq->frame_cropping_flag = 0;
532 vseq->bits_per_second = avctx->bit_rate;
533 if (avctx->framerate.num > 0 && avctx->framerate.den > 0) {
534 vseq->num_units_in_tick = avctx->framerate.num;
535 vseq->time_scale = 2 * avctx->framerate.den;
537 vseq->num_units_in_tick = avctx->time_base.num;
538 vseq->time_scale = 2 * avctx->time_base.den;
541 vseq->intra_period = ctx->p_per_i * (ctx->b_per_p + 1);
542 vseq->intra_idr_period = vseq->intra_period;
543 vseq->ip_period = ctx->b_per_p + 1;
547 vpic->CurrPic.picture_id = VA_INVALID_ID;
548 vpic->CurrPic.flags = VA_PICTURE_H264_INVALID;
550 for (i = 0; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
551 vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID;
552 vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
555 vpic->coded_buf = VA_INVALID_ID;
557 vpic->pic_parameter_set_id = 0;
558 vpic->seq_parameter_set_id = 0;
560 vpic->num_ref_idx_l0_active_minus1 = 0;
561 vpic->num_ref_idx_l1_active_minus1 = 0;
563 vpic->pic_fields.bits.entropy_coding_mode_flag =
564 ((avctx->profile & 0xff) != 66);
565 vpic->pic_fields.bits.weighted_pred_flag = 0;
566 vpic->pic_fields.bits.weighted_bipred_idc = 0;
567 vpic->pic_fields.bits.transform_8x8_mode_flag =
568 ((avctx->profile & 0xff) >= 100);
570 vpic->pic_init_qp = priv->fixed_qp_idr;
574 mseq->profile_idc = avctx->profile & 0xff;
576 if (avctx->profile & FF_PROFILE_H264_CONSTRAINED)
577 mseq->constraint_set1_flag = 1;
578 if (avctx->profile & FF_PROFILE_H264_INTRA)
579 mseq->constraint_set3_flag = 1;
585 static int vaapi_encode_h264_init_picture_params(AVCodecContext *avctx,
586 VAAPIEncodePicture *pic)
588 VAAPIEncodeContext *ctx = avctx->priv_data;
589 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
590 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
591 VAAPIEncodeH264Context *priv = ctx->priv_data;
594 if (pic->type == PICTURE_TYPE_IDR) {
595 av_assert0(pic->display_order == pic->encode_order);
597 priv->next_frame_num = 1;
599 vpic->frame_num = priv->next_frame_num;
600 if (pic->type != PICTURE_TYPE_B) {
602 ++priv->next_frame_num;
606 vpic->frame_num = vpic->frame_num &
607 ((1 << (4 + vseq->seq_fields.bits.log2_max_frame_num_minus4)) - 1);
609 vpic->CurrPic.picture_id = pic->recon_surface;
610 vpic->CurrPic.frame_idx = vpic->frame_num;
611 vpic->CurrPic.flags = 0;
612 vpic->CurrPic.TopFieldOrderCnt = pic->display_order;
613 vpic->CurrPic.BottomFieldOrderCnt = pic->display_order;
615 for (i = 0; i < pic->nb_refs; i++) {
616 VAAPIEncodePicture *ref = pic->refs[i];
617 av_assert0(ref && ref->encode_order < pic->encode_order);
618 vpic->ReferenceFrames[i].picture_id = ref->recon_surface;
619 vpic->ReferenceFrames[i].frame_idx = ref->encode_order;
620 vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE;
621 vpic->ReferenceFrames[i].TopFieldOrderCnt = ref->display_order;
622 vpic->ReferenceFrames[i].BottomFieldOrderCnt = ref->display_order;
624 for (; i < FF_ARRAY_ELEMS(vpic->ReferenceFrames); i++) {
625 vpic->ReferenceFrames[i].picture_id = VA_INVALID_ID;
626 vpic->ReferenceFrames[i].flags = VA_PICTURE_H264_INVALID;
629 vpic->coded_buf = pic->output_buffer;
631 vpic->pic_fields.bits.idr_pic_flag = (pic->type == PICTURE_TYPE_IDR);
632 vpic->pic_fields.bits.reference_pic_flag = (pic->type != PICTURE_TYPE_B);
639 static int vaapi_encode_h264_init_slice_params(AVCodecContext *avctx,
640 VAAPIEncodePicture *pic,
641 VAAPIEncodeSlice *slice)
643 VAAPIEncodeContext *ctx = avctx->priv_data;
644 VAEncSequenceParameterBufferH264 *vseq = ctx->codec_sequence_params;
645 VAEncPictureParameterBufferH264 *vpic = pic->codec_picture_params;
646 VAEncSliceParameterBufferH264 *vslice = slice->codec_slice_params;
647 VAAPIEncodeH264Context *priv = ctx->priv_data;
648 VAAPIEncodeH264Slice *pslice;
649 VAAPIEncodeH264MiscSliceParams *mslice;
652 slice->priv_data = av_mallocz(sizeof(*pslice));
653 if (!slice->priv_data)
654 return AVERROR(ENOMEM);
655 pslice = slice->priv_data;
656 mslice = &pslice->misc_slice_params;
658 if (pic->type == PICTURE_TYPE_IDR)
659 mslice->nal_unit_type = NAL_IDR_SLICE;
661 mslice->nal_unit_type = NAL_SLICE;
664 case PICTURE_TYPE_IDR:
665 vslice->slice_type = SLICE_TYPE_I;
666 mslice->nal_ref_idc = 3;
669 vslice->slice_type = SLICE_TYPE_I;
670 mslice->nal_ref_idc = 2;
673 vslice->slice_type = SLICE_TYPE_P;
674 mslice->nal_ref_idc = 1;
677 vslice->slice_type = SLICE_TYPE_B;
678 mslice->nal_ref_idc = 0;
681 av_assert0(0 && "invalid picture type");
684 // Only one slice per frame.
685 vslice->macroblock_address = 0;
686 vslice->num_macroblocks = priv->mb_width * priv->mb_height;
688 vslice->macroblock_info = VA_INVALID_ID;
690 vslice->pic_parameter_set_id = vpic->pic_parameter_set_id;
691 vslice->idr_pic_id = priv->idr_pic_count++;
693 vslice->pic_order_cnt_lsb = pic->display_order &
694 ((1 << (4 + vseq->seq_fields.bits.log2_max_pic_order_cnt_lsb_minus4)) - 1);
696 for (i = 0; i < FF_ARRAY_ELEMS(vslice->RefPicList0); i++) {
697 vslice->RefPicList0[i].picture_id = VA_INVALID_ID;
698 vslice->RefPicList0[i].flags = VA_PICTURE_H264_INVALID;
699 vslice->RefPicList1[i].picture_id = VA_INVALID_ID;
700 vslice->RefPicList1[i].flags = VA_PICTURE_H264_INVALID;
703 av_assert0(pic->nb_refs <= 2);
704 if (pic->nb_refs >= 1) {
705 // Backward reference for P- or B-frame.
706 av_assert0(pic->type == PICTURE_TYPE_P ||
707 pic->type == PICTURE_TYPE_B);
709 vslice->num_ref_idx_l0_active_minus1 = 0;
710 vslice->RefPicList0[0] = vpic->ReferenceFrames[0];
712 if (pic->nb_refs >= 2) {
713 // Forward reference for B-frame.
714 av_assert0(pic->type == PICTURE_TYPE_B);
716 vslice->num_ref_idx_l1_active_minus1 = 0;
717 vslice->RefPicList1[0] = vpic->ReferenceFrames[1];
720 if (pic->type == PICTURE_TYPE_B)
721 vslice->slice_qp_delta = priv->fixed_qp_b - vpic->pic_init_qp;
722 else if (pic->type == PICTURE_TYPE_P)
723 vslice->slice_qp_delta = priv->fixed_qp_p - vpic->pic_init_qp;
725 vslice->slice_qp_delta = priv->fixed_qp_idr - vpic->pic_init_qp;
727 vslice->direct_spatial_mv_pred_flag = 1;
732 static av_cold int vaapi_encode_h264_init_constant_bitrate(AVCodecContext *avctx)
734 VAAPIEncodeContext *ctx = avctx->priv_data;
735 VAAPIEncodeH264Context *priv = ctx->priv_data;
737 int hrd_initial_buffer_fullness;
739 if (avctx->bit_rate > INT32_MAX) {
740 av_log(avctx, AV_LOG_ERROR, "Target bitrate of 2^31 bps or "
741 "higher is not supported.\n");
742 return AVERROR(EINVAL);
745 if (avctx->rc_buffer_size)
746 hrd_buffer_size = avctx->rc_buffer_size;
748 hrd_buffer_size = avctx->bit_rate;
749 if (avctx->rc_initial_buffer_occupancy)
750 hrd_initial_buffer_fullness = avctx->rc_initial_buffer_occupancy;
752 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
754 priv->rc_params.misc.type = VAEncMiscParameterTypeRateControl;
755 priv->rc_params.rc = (VAEncMiscParameterRateControl) {
756 .bits_per_second = avctx->bit_rate,
757 .target_percentage = 66,
759 .initial_qp = (avctx->qmax >= 0 ? avctx->qmax : 40),
760 .min_qp = (avctx->qmin >= 0 ? avctx->qmin : 18),
761 .basic_unit_size = 0,
763 ctx->global_params[ctx->nb_global_params] =
764 &priv->rc_params.misc;
765 ctx->global_params_size[ctx->nb_global_params++] =
766 sizeof(priv->rc_params);
768 priv->hrd_params.misc.type = VAEncMiscParameterTypeHRD;
769 priv->hrd_params.hrd = (VAEncMiscParameterHRD) {
770 .initial_buffer_fullness = hrd_initial_buffer_fullness,
771 .buffer_size = hrd_buffer_size,
773 ctx->global_params[ctx->nb_global_params] =
774 &priv->hrd_params.misc;
775 ctx->global_params_size[ctx->nb_global_params++] =
776 sizeof(priv->hrd_params);
778 // These still need to be set for pic_init_qp/slice_qp_delta.
779 priv->fixed_qp_idr = 26;
780 priv->fixed_qp_p = 26;
781 priv->fixed_qp_b = 26;
783 av_log(avctx, AV_LOG_DEBUG, "Using constant-bitrate = %"PRId64" bps.\n",
788 static av_cold int vaapi_encode_h264_init_fixed_qp(AVCodecContext *avctx)
790 VAAPIEncodeContext *ctx = avctx->priv_data;
791 VAAPIEncodeH264Context *priv = ctx->priv_data;
792 VAAPIEncodeH264Options *opt = ctx->codec_options;
794 priv->fixed_qp_p = opt->qp;
795 if (avctx->i_quant_factor > 0.0)
796 priv->fixed_qp_idr = (int)((priv->fixed_qp_p * avctx->i_quant_factor +
797 avctx->i_quant_offset) + 0.5);
799 priv->fixed_qp_idr = priv->fixed_qp_p;
800 if (avctx->b_quant_factor > 0.0)
801 priv->fixed_qp_b = (int)((priv->fixed_qp_p * avctx->b_quant_factor +
802 avctx->b_quant_offset) + 0.5);
804 priv->fixed_qp_b = priv->fixed_qp_p;
806 av_log(avctx, AV_LOG_DEBUG, "Using fixed QP = "
807 "%d / %d / %d for IDR- / P- / B-frames.\n",
808 priv->fixed_qp_idr, priv->fixed_qp_p, priv->fixed_qp_b);
812 static av_cold int vaapi_encode_h264_init_internal(AVCodecContext *avctx)
814 static const VAConfigAttrib default_config_attributes[] = {
815 { .type = VAConfigAttribRTFormat,
816 .value = VA_RT_FORMAT_YUV420 },
817 { .type = VAConfigAttribEncPackedHeaders,
818 .value = (VA_ENC_PACKED_HEADER_SEQUENCE |
819 VA_ENC_PACKED_HEADER_SLICE) },
822 VAAPIEncodeContext *ctx = avctx->priv_data;
823 VAAPIEncodeH264Context *priv = ctx->priv_data;
824 VAAPIEncodeH264Options *opt = ctx->codec_options;
827 switch (avctx->profile) {
828 case FF_PROFILE_H264_CONSTRAINED_BASELINE:
829 ctx->va_profile = VAProfileH264ConstrainedBaseline;
831 case FF_PROFILE_H264_BASELINE:
832 ctx->va_profile = VAProfileH264Baseline;
834 case FF_PROFILE_H264_MAIN:
835 ctx->va_profile = VAProfileH264Main;
837 case FF_PROFILE_H264_EXTENDED:
838 av_log(avctx, AV_LOG_ERROR, "H.264 extended profile "
839 "is not supported.\n");
840 return AVERROR_PATCHWELCOME;
841 case FF_PROFILE_UNKNOWN:
842 case FF_PROFILE_H264_HIGH:
843 ctx->va_profile = VAProfileH264High;
845 case FF_PROFILE_H264_HIGH_10:
846 case FF_PROFILE_H264_HIGH_10_INTRA:
847 av_log(avctx, AV_LOG_ERROR, "H.264 10-bit profiles "
848 "are not supported.\n");
849 return AVERROR_PATCHWELCOME;
850 case FF_PROFILE_H264_HIGH_422:
851 case FF_PROFILE_H264_HIGH_422_INTRA:
852 case FF_PROFILE_H264_HIGH_444:
853 case FF_PROFILE_H264_HIGH_444_PREDICTIVE:
854 case FF_PROFILE_H264_HIGH_444_INTRA:
855 case FF_PROFILE_H264_CAVLC_444:
856 av_log(avctx, AV_LOG_ERROR, "H.264 non-4:2:0 profiles "
857 "are not supported.\n");
858 return AVERROR_PATCHWELCOME;
860 av_log(avctx, AV_LOG_ERROR, "Unknown H.264 profile %d.\n",
862 return AVERROR(EINVAL);
864 if (opt->low_power) {
865 #if VA_CHECK_VERSION(0, 39, 1)
866 ctx->va_entrypoint = VAEntrypointEncSliceLP;
868 av_log(avctx, AV_LOG_ERROR, "Low-power encoding is not "
869 "supported with this VAAPI version.\n");
870 return AVERROR(EINVAL);
873 ctx->va_entrypoint = VAEntrypointEncSlice;
876 ctx->input_width = avctx->width;
877 ctx->input_height = avctx->height;
878 ctx->aligned_width = FFALIGN(ctx->input_width, 16);
879 ctx->aligned_height = FFALIGN(ctx->input_height, 16);
880 priv->mb_width = ctx->aligned_width / 16;
881 priv->mb_height = ctx->aligned_height / 16;
883 for (i = 0; i < FF_ARRAY_ELEMS(default_config_attributes); i++) {
884 ctx->config_attributes[ctx->nb_config_attributes++] =
885 default_config_attributes[i];
888 if (avctx->bit_rate > 0) {
889 ctx->va_rc_mode = VA_RC_CBR;
890 err = vaapi_encode_h264_init_constant_bitrate(avctx);
892 ctx->va_rc_mode = VA_RC_CQP;
893 err = vaapi_encode_h264_init_fixed_qp(avctx);
898 ctx->config_attributes[ctx->nb_config_attributes++] = (VAConfigAttrib) {
899 .type = VAConfigAttribRateControl,
900 .value = ctx->va_rc_mode,
903 if (opt->quality > 0) {
904 #if VA_CHECK_VERSION(0, 36, 0)
905 priv->quality_params.misc.type =
906 VAEncMiscParameterTypeQualityLevel;
907 priv->quality_params.quality.quality_level = opt->quality;
909 ctx->global_params[ctx->nb_global_params] =
910 &priv->quality_params.misc;
911 ctx->global_params_size[ctx->nb_global_params++] =
912 sizeof(priv->quality_params);
914 av_log(avctx, AV_LOG_WARNING, "The encode quality option is not "
915 "supported with this VAAPI version.\n");
919 ctx->nb_recon_frames = 20;
924 static VAAPIEncodeType vaapi_encode_type_h264 = {
925 .priv_data_size = sizeof(VAAPIEncodeH264Context),
927 .init = &vaapi_encode_h264_init_internal,
929 .sequence_params_size = sizeof(VAEncSequenceParameterBufferH264),
930 .init_sequence_params = &vaapi_encode_h264_init_sequence_params,
932 .picture_params_size = sizeof(VAEncPictureParameterBufferH264),
933 .init_picture_params = &vaapi_encode_h264_init_picture_params,
935 .slice_params_size = sizeof(VAEncSliceParameterBufferH264),
936 .init_slice_params = &vaapi_encode_h264_init_slice_params,
938 .sequence_header_type = VAEncPackedHeaderSequence,
939 .write_sequence_header = &vaapi_encode_h264_write_sequence_header,
941 .slice_header_type = VAEncPackedHeaderH264_Slice,
942 .write_slice_header = &vaapi_encode_h264_write_slice_header,
945 static av_cold int vaapi_encode_h264_init(AVCodecContext *avctx)
947 return ff_vaapi_encode_init(avctx, &vaapi_encode_type_h264);
950 #define OFFSET(x) (offsetof(VAAPIEncodeContext, codec_options_data) + \
951 offsetof(VAAPIEncodeH264Options, x))
952 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
953 static const AVOption vaapi_encode_h264_options[] = {
954 { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
955 OFFSET(qp), AV_OPT_TYPE_INT, { .i64 = 20 }, 0, 52, FLAGS },
956 { "quality", "Set encode quality (trades off against speed, higher is faster)",
957 OFFSET(quality), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 8, FLAGS },
958 { "low_power", "Use low-power encoding mode (experimental: only supported "
959 "on some platforms, does not support all features)",
960 OFFSET(low_power), AV_OPT_TYPE_INT, { .i64 = 0 }, 0, 1, FLAGS },
964 static const AVCodecDefault vaapi_encode_h264_defaults[] = {
965 { "profile", "100" },
970 { "i_qfactor", "1.0" },
971 { "i_qoffset", "0.0" },
972 { "b_qfactor", "1.2" },
973 { "b_qoffset", "0.0" },
977 static const AVClass vaapi_encode_h264_class = {
978 .class_name = "h264_vaapi",
979 .item_name = av_default_item_name,
980 .option = vaapi_encode_h264_options,
981 .version = LIBAVUTIL_VERSION_INT,
984 AVCodec ff_h264_vaapi_encoder = {
985 .name = "h264_vaapi",
986 .long_name = NULL_IF_CONFIG_SMALL("H.264/AVC (VAAPI)"),
987 .type = AVMEDIA_TYPE_VIDEO,
988 .id = AV_CODEC_ID_H264,
989 .priv_data_size = (sizeof(VAAPIEncodeContext) +
990 sizeof(VAAPIEncodeH264Options)),
991 .init = &vaapi_encode_h264_init,
992 .encode2 = &ff_vaapi_encode2,
993 .close = &ff_vaapi_encode_close,
994 .priv_class = &vaapi_encode_h264_class,
995 .capabilities = AV_CODEC_CAP_DELAY,
996 .defaults = vaapi_encode_h264_defaults,
997 .pix_fmts = (const enum AVPixelFormat[]) {