29 #include "config_components.h"
40 #include <d3d12video.h>
42 #ifndef D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX
43 #define D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX ( 0xff )
115 { 0, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_0 },
116 { 1, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_1 },
117 { 2, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_2 },
118 { 3, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_3 },
119 { 4, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_0 },
120 { 5, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_1 },
121 { 6, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_2 },
122 { 7, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_3 },
123 { 8, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_0 },
124 { 9, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_1 },
125 { 10, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_2 },
126 { 11, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_3 },
127 { 12, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_0 },
128 { 13, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_1 },
129 { 14, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2 },
130 { 15, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_3 },
131 { 16, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_0 },
132 { 17, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_1 },
133 { 18, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_2 },
134 { 19, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_3 },
135 { 20, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_0 },
136 { 21, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_1 },
137 { 22, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_2 },
138 { 23, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_3 },
141 static const D3D12_VIDEO_ENCODER_AV1_PROFILE
profile_main = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
142 static const D3D12_VIDEO_ENCODER_AV1_PROFILE
profile_high = D3D12_VIDEO_ENCODER_AV1_PROFILE_HIGH;
143 static const D3D12_VIDEO_ENCODER_AV1_PROFILE
profile_professional = D3D12_VIDEO_ENCODER_AV1_PROFILE_PROFESSIONAL;
145 #define D3D_PROFILE_DESC(name) \
146 { sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE), { .pAV1Profile = (D3D12_VIDEO_ENCODER_AV1_PROFILE *)&profile_ ## name } }
158 char *
data,
size_t *data_len,
164 err = ff_cbs_write_fragment_data(priv->
cbc, obu);
183 err = ff_cbs_insert_unit_content(au, -1, obu_type, obu_unit,
NULL);
186 "type = %d.\n", obu_type);
193 char *
data,
size_t *data_len)
207 ff_cbs_fragment_reset(obu);
220 D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES *post_encode_values =
NULL;
228 post_encode_values = (D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES*) (
data +
229 sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
230 sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA) +
231 sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES));
234 fh->
base_q_idx = post_encode_values->Quantization.BaseQIndex;
235 fh->
delta_q_y_dc = post_encode_values->Quantization.YDCDeltaQ;
236 fh->
delta_q_u_dc = post_encode_values->Quantization.UDCDeltaQ;
237 fh->
delta_q_u_ac = post_encode_values->Quantization.UACDeltaQ;
238 fh->
delta_q_v_dc = post_encode_values->Quantization.VDCDeltaQ;
239 fh->
delta_q_v_ac = post_encode_values->Quantization.VACDeltaQ;
240 fh->
using_qmatrix = post_encode_values->Quantization.UsingQMatrix;
241 fh->
qm_y = post_encode_values->Quantization.QMY;
242 fh->
qm_u = post_encode_values->Quantization.QMU;
243 fh->
qm_v = post_encode_values->Quantization.QMV;
258 for (
int i = 0;
i < 2;
i++) {
266 fh->
cdef_bits = post_encode_values->CDEF.CdefBits;
267 for (
int i = 0;
i < 8;
i++) {
275 fh->
delta_q_present = post_encode_values->QuantizationDelta.DeltaQPresent;
276 fh->
delta_q_res = post_encode_values->QuantizationDelta.DeltaQRes;
291 char *
data,
size_t *data_len)
301 av_log(avctx,
AV_LOG_ERROR,
"Failed to update current frame picture header: %d.\n", err);
314 ff_cbs_fragment_reset(obu);
321 uint32_t tile_group_size,
322 char *
data,
size_t *data_len)
342 ff_cbs_fragment_reset(obu);
349 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *subregion_meta =
NULL;
360 subregion_meta = (D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA*)(
data +
sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA));
361 if (subregion_meta->bSize == 0) {
366 *
size = subregion_meta->bSize;
378 uint8_t *mapped_data =
NULL;
379 size_t total_size = 0;
381 size_t av1_pic_hd_size = 0;
382 int tile_group_extra_size = 0;
392 memset(pic_hd_data, 0,
sizeof(pic_hd_data));
398 av1_pic_hd_size /= 8;
399 av_log(avctx,
AV_LOG_DEBUG,
"AV1 picture header size: %zu bytes.\n", av1_pic_hd_size);
402 tile_group_extra_size = (
av_log2(total_size) + 7) / 7 + 1;
403 av_log(avctx,
AV_LOG_DEBUG,
"Tile group extra size: %d bytes.\n", tile_group_extra_size);
405 total_size += (pic->
header_size + tile_group_extra_size + av1_pic_hd_size);
425 memcpy(ptr, pic_hd_data, av1_pic_hd_size);
426 ptr += av1_pic_hd_size;
427 total_size -= av1_pic_hd_size;
428 av_log(avctx,
AV_LOG_DEBUG,
"AV1 total_size after write picture header: %zu.\n", total_size);
430 total_size -= tile_group_extra_size;
436 assert((total_size + tile_group_extra_size) * 8 == bit_len);
464 .transfer_characteristics = avctx->
color_trc,
470 .subsampling_x =
desc->log2_chroma_w,
471 .subsampling_y =
desc->log2_chroma_h,
509 "any normal level, using maximum parameters level by default.\n");
549 D3D12_VIDEO_ENCODER_AV1_PROFILE
profile = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
550 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS
level = { 0 };
554 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 support = {
556 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
557 .InputFormat = hwctx->
format,
558 .RateControl =
ctx->rc,
559 .IntraRefresh =
ctx->intra_refresh.Mode,
560 .SubregionFrameEncoding = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
561 .ResolutionsListCount = 1,
562 .pResolutionList = &
ctx->resolution,
563 .CodecGopSequence =
ctx->gop,
565 .CodecConfiguration =
ctx->codec_conf,
566 .SuggestedProfile.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE),
567 .SuggestedProfile.pAV1Profile = &
profile,
568 .SuggestedLevel.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS),
569 .SuggestedLevel.pAV1LevelSetting = &
level,
570 .pResolutionDependentSupport = &
ctx->res_limits,
571 .SubregionFrameEncodingData.pTilesPartition_AV1 =
ctx->subregions_layout.pTilesPartition_AV1,
574 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_SUPPORT1,
575 &support,
sizeof(support));
582 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
583 av_log(avctx,
AV_LOG_ERROR,
"Driver does not support some request D3D12VA AV1 features. %#x\n",
584 support.ValidationFlags);
588 if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS) {
589 ctx->is_texture_array = 1;
590 av_log(avctx,
AV_LOG_DEBUG,
"D3D12 video encode on this device uses texture array mode.\n");
593 memset(seqheader_obu, 0,
sizeof(*seqheader_obu));
623 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION *
config;
624 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT av1_caps;
626 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codec_caps = {
628 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
629 .Profile =
ctx->profile->d3d12_profile,
630 .CodecSupportLimits.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT),
633 codec_caps.CodecSupportLimits.pAV1Support = &av1_caps;
635 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT,
636 &codec_caps,
sizeof(codec_caps));
637 if (!(SUCCEEDED(hr) && codec_caps.IsSupported))
640 ctx->codec_conf.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION);
642 if (!
ctx->codec_conf.pAV1Config)
648 config->FeatureFlags = D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_NONE;
649 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK) {
650 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK;
657 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER) {
658 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER;
662 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING) {
663 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING;
667 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY) {
668 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY;
672 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS) {
674 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS;
678 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING) {
680 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING;
684 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER) {
686 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER;
690 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP) {
692 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP;
696 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS) {
698 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS;
702 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION) {
704 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION;
708 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION) {
710 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION;
714 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND) {
716 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND;
729 int fixed_qp_key, fixed_qp_inter;
735 if (
ctx->rc.Mode == D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP) {
736 D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP *cqp_ctl;
743 fixed_qp_key = fixed_qp_inter;
746 "%d / %d for Key / Inter frames.\n",
747 fixed_qp_key, fixed_qp_inter);
749 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP);
754 cqp_ctl->ConstantQP_FullIntracodedFrame = fixed_qp_key;
755 cqp_ctl->ConstantQP_InterPredictedFrame_PrevRefOnly = fixed_qp_inter;
756 cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef = fixed_qp_inter;
758 ctx->rc.ConfigParams.pConfiguration_CQP = cqp_ctl;
761 priv->
q_idx_p = fixed_qp_inter;
766 ctx->gop.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_SEQUENCE_STRUCTURE);
768 if (!
ctx->gop.pAV1SequenceStructure)
771 ctx->gop.pAV1SequenceStructure->IntraDistance = base_ctx->
gop_size;
772 ctx->gop.pAV1SequenceStructure->InterFramePeriod = base_ctx->
b_per_p + 1;
783 ctx->level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
785 if (!
ctx->level.pAV1LevelSetting)
801 ctx->level.pAV1LevelSetting->Level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
802 avctx->
level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
807 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
810 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_MAIN;
814 if (priv->
tier >= 0) {
815 ctx->level.pAV1LevelSetting->Tier = priv->
tier == 0 ?
816 D3D12_VIDEO_ENCODER_AV1_TIER_MAIN :
817 D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
821 ctx->level.pAV1LevelSetting->Level,
822 ctx->level.pAV1LevelSetting->Tier == D3D12_VIDEO_ENCODER_AV1_TIER_MAIN ?
"Main" :
"High");
831 ctx->subregions_layout.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES);
832 D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *tiles_layout =
av_mallocz(
ctx->subregions_layout.DataSize);
833 ctx->subregions_layout.pTilesPartition_AV1 = tiles_layout;
836 tiles_layout->RowCount = 1;
837 tiles_layout->ColCount = 1;
867 { 1, 0, 0, 0, -1, 0, -1, -1 };
869 memset(frameheader_obu, 0,
sizeof(*frameheader_obu));
873 d3d12va_pic->
pic_ctl.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_CODEC_DATA);
875 if (!d3d12va_pic->
pic_ctl.pAV1PicData)
895 href =
ref->codec_priv;
904 if (base_ctx->
ref_l0 > 1) {
922 href =
ref->codec_priv;
926 }
else if (base_ctx->
ref_l0 == 1) {
932 av_log(avctx,
AV_LOG_ERROR,
"D3D12 AV1 video encode on this device requires B-frame support, "
933 "but it's not implemented.\n");
970 d3d12va_pic->
pic_ctl.pAV1PicData->InterpolationFilter = D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_SWITCHABLE;
973 d3d12va_pic->
pic_ctl.pAV1PicData->Flags |= D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_FLAG_ENABLE_ERROR_RESILIENT_MODE;
978 d3d12va_pic->
pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[
i].ReconstructedPictureResourceIndex =
984 d3d12va_pic->
pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[
i].ReconstructedPictureResourceIndex =
1002 .d3d12_codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
1008 .default_quality = 25,
1028 #ifdef CONFIG_AV1_D3D12VA_ENCODER
1047 "in 8-bit unsigned integer.\n", avctx->
level);
1052 ctx->explicit_qp = priv->
qp;
1064 ff_cbs_close(&priv->
cbc);
1076 #define OFFSET(x) offsetof(D3D12VAEncodeAV1Context, x)
1077 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1083 {
"qp",
"Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
1086 {
"profile",
"Set profile (general_profile_idc)",
1090 #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1091 { .i64 = value }, 0, 0, FLAGS, "profile"
1097 {
"tier",
"Set tier (general_tier_flag)",
1099 { .i64 = 0 }, 0, 1,
FLAGS,
"tier" },
1101 { .i64 = 0 }, 0, 0,
FLAGS,
"tier" },
1103 { .i64 = 1 }, 0, 0,
FLAGS,
"tier" },
1105 {
"level",
"Set level (general_level_idc)",
1109 #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1110 { .i64 = value }, 0, 0, FLAGS, "level"
1111 {
LEVEL(
"2.0", 0) },
1112 {
LEVEL(
"2.1", 1) },
1113 {
LEVEL(
"2.2", 2) },
1114 {
LEVEL(
"2.3", 3) },
1115 {
LEVEL(
"3.0", 4) },
1116 {
LEVEL(
"3.1", 5) },
1117 {
LEVEL(
"3.2", 6) },
1118 {
LEVEL(
"3.3", 7) },
1119 {
LEVEL(
"4.0", 8) },
1120 {
LEVEL(
"4.1", 9) },
1121 {
LEVEL(
"4.2", 10) },
1122 {
LEVEL(
"4.3", 11) },
1123 {
LEVEL(
"5.0", 12) },
1124 {
LEVEL(
"5.1", 13) },
1125 {
LEVEL(
"5.2", 14) },
1126 {
LEVEL(
"5.3", 15) },
1127 {
LEVEL(
"6.0", 16) },
1128 {
LEVEL(
"6.1", 17) },
1129 {
LEVEL(
"6.2", 18) },
1130 {
LEVEL(
"6.3", 19) },
1131 {
LEVEL(
"7.0", 20) },
1132 {
LEVEL(
"7.1", 21) },
1133 {
LEVEL(
"7.2", 22) },
1134 {
LEVEL(
"7.3", 23) },
1143 {
"i_qfactor",
"1" },
1144 {
"i_qoffset",
"0" },
1145 {
"b_qfactor",
"1" },
1146 {
"b_qoffset",
"0" },
1161 .
p.
name =
"av1_d3d12va",
1177 .p.wrapper_name =
"d3d12va",