1 /*
2 * This file is part of FFmpeg.
3 *
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.
8 *
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.
13 *
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
17 */
18
19 #include <string.h>
20
21 #include <va/va.h>
22 #include <va/va_enc_h264.h>
23
29
41
42 enum {
47 };
48
49 // Random (version 4) ISO 11578 UUID.
51 0x59, 0x94, 0x8b, 0x28, 0x11, 0xec, 0x45, 0xaf,
52 0x96, 0x75, 0x19, 0xd4, 0x1f, 0xea, 0xa9, 0x4d,
53 };
54
58
61
64
68
72
73 // User options.
81
82 // Derived settings.
85
89
90 // Writer structures.
93
96
103
108
109
111 char *
data,
size_t *data_len,
113 {
115 int err;
116
118 if (err < 0) {
120 return err;
121 }
122
125 "%zu < %zu.\n", *data_len,
128 }
129
132
133 return 0;
134 }
135
138 void *nal_unit)
139 {
141 int err;
142
145 if (err < 0) {
147 "type = %d.\n",
header->nal_unit_type);
148 return err;
149 }
150
151 return 0;
152 }
153
155 char *
data,
size_t *data_len)
156 {
159 int err;
160
163 if (err < 0)
166 }
167
169 if (err < 0)
171
173 if (err < 0)
175
179 return err;
180 }
181
185 char *
data,
size_t *data_len)
186 {
189 int err;
190
193 if (err < 0)
196 }
197
199 if (err < 0)
201
205 return err;
206 }
207
211 char *
data,
size_t *data_len)
212 {
215 int err;
216
220 if (err < 0)
223 }
224
229 if (err < 0)
231 }
237 if (err < 0)
239 }
243 if (err < 0)
245 }
250 if (err < 0)
252 }
257 if (err < 0)
259 }
260
262
264 if (err < 0)
266
268
269 *
type = VAEncPackedHeaderRawData;
270 return 0;
271
272 #if !CONFIG_VAAPI_1
274 // Insert a zero-length header using the old SEI type. This is
275 // required to avoid triggering broken behaviour on Intel platforms
276 // in CBR mode where an invalid SEI message is generated by the
277 // driver and inserted into the stream.
278 *data_len = 0;
279 *
type = VAEncPackedHeaderH264_SEI;
281 return 0;
282 #endif
283
284 } else {
286 }
287
290 return err;
291 }
292
294 {
300 VAEncSequenceParameterBufferH264 *vseq =
ctx->codec_sequence_params;
301 VAEncPictureParameterBufferH264 *vpic =
ctx->codec_picture_params;
302
307 .cabac = priv->
coder,
308 .hrd_buffer_size =
ctx->hrd_params.buffer_size,
310 .initial_buffer_fullness =
ctx->hrd_params.initial_buffer_fullness,
312 };
313
315 &priv->
units, &unit_opts);
316 if (err < 0)
317 return err;
318
319 *vseq = (VAEncSequenceParameterBufferH264) {
320 .seq_parameter_set_id =
sps->seq_parameter_set_id,
321 .level_idc =
sps->level_idc,
323 .intra_idr_period = base_ctx->
gop_size,
324 .ip_period = base_ctx->
b_per_p + 1,
325
326 .bits_per_second =
ctx->va_bit_rate,
327 .max_num_ref_frames =
sps->max_num_ref_frames,
328 .picture_width_in_mbs =
sps->pic_width_in_mbs_minus1 + 1,
329 .picture_height_in_mbs =
sps->pic_height_in_map_units_minus1 + 1,
330
331 .seq_fields.bits = {
332 .chroma_format_idc =
sps->chroma_format_idc,
333 .frame_mbs_only_flag =
sps->frame_mbs_only_flag,
334 .mb_adaptive_frame_field_flag =
sps->mb_adaptive_frame_field_flag,
335 .seq_scaling_matrix_present_flag =
sps->seq_scaling_matrix_present_flag,
336 .direct_8x8_inference_flag =
sps->direct_8x8_inference_flag,
337 .log2_max_frame_num_minus4 =
sps->log2_max_frame_num_minus4,
338 .pic_order_cnt_type =
sps->pic_order_cnt_type,
339 .log2_max_pic_order_cnt_lsb_minus4 =
sps->log2_max_pic_order_cnt_lsb_minus4,
340 .delta_pic_order_always_zero_flag =
sps->delta_pic_order_always_zero_flag,
341 },
342
343 .bit_depth_luma_minus8 =
sps->bit_depth_luma_minus8,
344 .bit_depth_chroma_minus8 =
sps->bit_depth_chroma_minus8,
345
346 .frame_cropping_flag =
sps->frame_cropping_flag,
347 .frame_crop_left_offset =
sps->frame_crop_left_offset,
348 .frame_crop_right_offset =
sps->frame_crop_right_offset,
349 .frame_crop_top_offset =
sps->frame_crop_top_offset,
350 .frame_crop_bottom_offset =
sps->frame_crop_bottom_offset,
351
352 .vui_parameters_present_flag =
sps->vui_parameters_present_flag,
353
354 .vui_fields.bits = {
355 .aspect_ratio_info_present_flag =
sps->vui.aspect_ratio_info_present_flag,
356 .timing_info_present_flag =
sps->vui.timing_info_present_flag,
357 .bitstream_restriction_flag =
sps->vui.bitstream_restriction_flag,
358 .log2_max_mv_length_horizontal =
sps->vui.log2_max_mv_length_horizontal,
359 .log2_max_mv_length_vertical =
sps->vui.log2_max_mv_length_vertical,
360 },
361
362 .aspect_ratio_idc =
sps->vui.aspect_ratio_idc,
363 .sar_width =
sps->vui.sar_width,
364 .sar_height =
sps->vui.sar_height,
365 .num_units_in_tick =
sps->vui.num_units_in_tick,
366 .time_scale =
sps->vui.time_scale,
367 };
368
369 *vpic = (VAEncPictureParameterBufferH264) {
370 .CurrPic = {
371 .picture_id = VA_INVALID_ID,
372 .flags = VA_PICTURE_H264_INVALID,
373 },
374
375 .coded_buf = VA_INVALID_ID,
376
377 .pic_parameter_set_id =
pps->pic_parameter_set_id,
378 .seq_parameter_set_id =
pps->seq_parameter_set_id,
379
380 .pic_init_qp =
pps->pic_init_qp_minus26 + 26,
381 .num_ref_idx_l0_active_minus1 =
pps->num_ref_idx_l0_default_active_minus1,
382 .num_ref_idx_l1_active_minus1 =
pps->num_ref_idx_l1_default_active_minus1,
383
384 .chroma_qp_index_offset =
pps->chroma_qp_index_offset,
385 .second_chroma_qp_index_offset =
pps->second_chroma_qp_index_offset,
386
387 .pic_fields.bits = {
388 .entropy_coding_mode_flag =
pps->entropy_coding_mode_flag,
389 .weighted_pred_flag =
pps->weighted_pred_flag,
390 .weighted_bipred_idc =
pps->weighted_bipred_idc,
391 .constrained_intra_pred_flag =
pps->constrained_intra_pred_flag,
392 .transform_8x8_mode_flag =
pps->transform_8x8_mode_flag,
393 .deblocking_filter_control_present_flag =
394 pps->deblocking_filter_control_present_flag,
395 .redundant_pic_cnt_present_flag =
pps->redundant_pic_cnt_present_flag,
396 .pic_order_present_flag =
397 pps->bottom_field_pic_order_in_frame_present_flag,
398 .pic_scaling_matrix_present_flag =
pps->pic_scaling_matrix_present_flag,
399 },
400 };
401
402 return 0;
403 }
404
407 {
409 #if !CONFIG_VAAPI_1
411 #endif
419
422
426
429 } else {
431
433
436
443 } else {
446 }
447 }
451 }
452
455
461 },
463 };
464 } else {
466 }
467
469
472 #if !CONFIG_VAAPI_1
473 if (
ctx->va_rc_mode == VA_RC_CBR)
475 #endif
476
481 };
482
484 }
485
489 .exact_match_flag = 1,
490 .broken_link_flag = base_ctx->
b_per_p > 0,
491 };
492
494 }
495
497 int err;
498 size_t sei_a53cc_len;
501 if (err < 0)
502 return err;
507
509 }
510 }
511
512 vpic->CurrPic = (VAPictureH264) {
515 .flags = 0,
518 };
523
525 href =
ref->codec_priv;
526
527 vpic->ReferenceFrames[j++] = (VAPictureH264) {
530 .flags = VA_PICTURE_H264_SHORT_TERM_REFERENCE,
533 };
534 }
535 }
536
538 vpic->ReferenceFrames[j] = (VAPictureH264) {
539 .picture_id = VA_INVALID_ID,
540 .flags = VA_PICTURE_H264_INVALID,
541 };
542 }
543
545
547
549 vpic->pic_fields.bits.reference_pic_flag = pic->
is_reference;
550
551 return 0;
552 }
553
558 int *rpl_size)
559 {
563
567
571
573 for (j = n; j > 0; j--) {
577 break;
578 rpl0[j] = rpl0[j - 1];
579 }
580 rpl0[j] = prev->
dpb[
i];
581
583 for (j = n; j > 0; j--) {
589 break;
590 } else {
592 break;
593 }
594 rpl0[j] = rpl0[j - 1];
595 }
596 rpl0[j] = prev->
dpb[
i];
597
598 for (j = n; j > 0; j--) {
604 break;
605 } else {
607 break;
608 }
609 rpl1[j] = rpl1[j - 1];
610 }
611 rpl1[j] = prev->
dpb[
i];
612 }
613
614 ++n;
615 }
616
618 for (
i = 0;
i < n;
i++) {
619 if (rpl0[
i] != rpl1[
i])
620 break;
621 }
624 }
625
630 for (
i = 0;
i < n;
i++) {
633 hn->frame_num,
hn->pic_order_cnt);
634 }
636 }
640 for (
i = 0;
i < n;
i++) {
643 hn->frame_num,
hn->pic_order_cnt);
644 }
646 }
647
648 *rpl_size = n;
649 }
650
654 {
665
669 } else {
672 }
673
676
678
680 ((1 << (4 +
sps->log2_max_frame_num_minus4)) - 1);
683 ((1 << (4 +
sps->log2_max_pic_order_cnt_lsb_minus4)) - 1);
684
686
691 else
693
696 int discard = 0, keep = 0;
697
698 // Discard everything which is in the DPB of the previous frame but
699 // not in the DPB of this one.
702 if (prev->
dpb[
i] == pic->
dpb[j])
703 break;
704 }
706 discard_list[discard] = prev->
dpb[
i];
707 ++discard;
708 } else {
709 ++keep;
710 }
711 }
713
714 if (discard == 0) {
716 } else {
718 for (
i = 0;
i < discard;
i++) {
724 }
726 }
727 }
728
729 // If the intended references are not the first entries of RefPicListN
730 // by default, use ref-pic-list-modification to move them there.
734 int n;
735
737 def_l0, def_l1, &n);
738
740 int need_rplm = 0;
744 need_rplm = 1;
745 }
746
748 if (need_rplm) {
757 } else {
761 }
763 }
765 }
766
767 } else {
768 int need_rplm_l0 = 0, need_rplm_l1 = 0;
769 int n0 = 0, n1 = 0;
775 need_rplm_l0 = 1;
776 ++n0;
777 }
778
784 need_rplm_l1 = 1;
785 ++n1;
786 }
787
789 if (need_rplm_l0) {
798 } else {
802 }
804 ++j;
805 }
808 }
809
811 if (need_rplm_l1) {
820 } else {
824 }
826 ++j;
827 }
830 }
831 }
832 }
833
836
837 vslice->macroblock_info = VA_INVALID_ID;
838
842
844
846
848 vslice->RefPicList0[
i].picture_id = VA_INVALID_ID;
849 vslice->RefPicList0[
i].flags = VA_PICTURE_H264_INVALID;
850 vslice->RefPicList1[
i].picture_id = VA_INVALID_ID;
851 vslice->RefPicList1[
i].flags = VA_PICTURE_H264_INVALID;
852 }
853
855 // Backward reference for P- or B-frame.
858 vslice->RefPicList0[0] = vpic->ReferenceFrames[0];
859 }
861 // Forward reference for B-frame.
863 vslice->RefPicList1[0] = vpic->ReferenceFrames[1];
864 }
865
867
868 return 0;
869 }
870
872 {
875 int err;
876
878 if (err < 0)
879 return err;
880
883
884 if (
ctx->va_rc_mode == VA_RC_CQP) {
890 else
896 else
898
900 "%d / %d / %d for IDR- / P- / B-frames.\n",
902
903 } else {
904 // These still need to be set for pic_init_qp/slice_qp_delta.
908 }
909
910 if (!
ctx->rc_mode->hrd) {
911 // Timing SEI requires a mode respecting HRD parameters.
913 }
914
917 const char *vaapi = VA_VERSION_S;
918 const char *driver;
920
924
925 driver = vaQueryVendorString(
ctx->hwctx->display);
926 if (!driver)
927 driver = "unknown driver";
928
934
936 "%s / VAAPI %s / %s", lavc, vaapi, driver);
937
940 }
941 }
942
943 ctx->roi_quant_range = 51 + 6 * (
ctx->profile->depth - 8);
944
945 return 0;
946 }
947
949 #if VA_CHECK_VERSION(1, 18, 0)
951 #endif
955 8, 3, 1, 1, VAProfileH264ConstrainedBaseline },
957 };
958
961
966
967 .default_quality = 20,
968
970
972
973 .sequence_params_size = sizeof(VAEncSequenceParameterBufferH264),
975
976 .picture_params_size = sizeof(VAEncPictureParameterBufferH264),
978
979 .slice_params_size = sizeof(VAEncSliceParameterBufferH264),
981
982 .sequence_header_type = VAEncPackedHeaderSequence,
984
985 .slice_header_type = VAEncPackedHeaderH264_Slice,
987
989 };
990
992 {
996
998
1005
1006 // Reject unsupported profiles.
1010 "supported, using constrained baseline profile instead.\n");
1012 break;
1015 "is not supported.\n");
1019 "is not supported.\n");
1028 "are not supported.\n");
1030 }
1031
1034 "in 8-bit unsigned integer.\n", avctx->
level);
1036 }
1037
1038 ctx->desired_packed_headers =
1039 VA_ENC_PACKED_HEADER_SEQUENCE | // SPS and PPS.
1040 VA_ENC_PACKED_HEADER_SLICE | // Slice headers.
1041 VA_ENC_PACKED_HEADER_MISC; // SEI.
1042
1045
1047
1049 ctx->explicit_qp = priv->
qp;
1050
1052 }
1053
1055 {
1057
1062
1064 }
1065
1066 #define OFFSET(x) offsetof(VAAPIEncodeH264Context, x)
1067 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1072
1073 { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
1075 { "quality", "Set encode quality (trades off against speed, higher is faster)",
1077 { "coder", "Entropy coder type",
1083
1084 { "aud", "Include AUD",
1086
1087 { "sei", "Set SEI to include",
1090 0, INT_MAX,
FLAGS, .unit =
"sei" },
1091 { "identifier", "Include encoder version identifier",
1093 INT_MIN, INT_MAX,
FLAGS, .unit =
"sei" },
1094 { "timing", "Include timing parameters (buffering_period and pic_timing)",
1096 INT_MIN, INT_MAX,
FLAGS, .unit =
"sei" },
1097 { "recovery_point", "Include recovery points where appropriate",
1099 INT_MIN, INT_MAX,
FLAGS, .unit =
"sei" },
1100 { "a53_cc", "Include A/53 caption data",
1102 INT_MIN, INT_MAX,
FLAGS, .unit =
"sei" },
1103
1104 { "profile", "Set profile (profile_idc and constraint_set*_flag)",
1107
1108 #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1109 { .i64 = value }, 0, 0, FLAGS, .unit = "profile"
1114 #undef PROFILE
1115
1116 { "level", "Set level (level_idc)",
1119
1120 #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1121 { .i64 = value }, 0, 0, FLAGS, .unit = "level"
1123 {
LEVEL(
"1.1", 11) },
1124 {
LEVEL(
"1.2", 12) },
1125 {
LEVEL(
"1.3", 13) },
1127 {
LEVEL(
"2.1", 21) },
1128 {
LEVEL(
"2.2", 22) },
1130 {
LEVEL(
"3.1", 31) },
1131 {
LEVEL(
"3.2", 32) },
1133 {
LEVEL(
"4.1", 41) },
1134 {
LEVEL(
"4.2", 42) },
1136 {
LEVEL(
"5.1", 51) },
1137 {
LEVEL(
"5.2", 52) },
1139 {
LEVEL(
"6.1", 61) },
1140 {
LEVEL(
"6.2", 62) },
1141 #undef LEVEL
1142
1144 };
1145
1147 { "b", "0" },
1148 { "bf", "2" },
1149 { "g", "120" },
1150 { "i_qfactor", "1" },
1151 { "i_qoffset", "0" },
1152 { "b_qfactor", "6/5" },
1153 { "b_qoffset", "0" },
1154 { "qmin", "-1" },
1155 { "qmax", "-1" },
1157 };
1158
1164 };
1165
1167 .
p.
name =
"h264_vaapi",
1184 },
1187 .p.wrapper_name = "vaapi",
1188 };