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);
350 D3D12_VIDEO_ENCODER_OUTPUT_METADATA *meta =
NULL;
351 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *subregion_meta =
NULL;
362 subregion_meta = (D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA*)(
data +
sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA));
363 if (subregion_meta->bSize == 0) {
368 *
size = subregion_meta->bSize;
380 uint8_t *mapped_data =
NULL;
381 size_t total_size = 0;
383 size_t av1_pic_hd_size = 0;
384 int tile_group_extra_size = 0;
395 memset(pic_hd_data, 0,
sizeof(pic_hd_data));
401 av1_pic_hd_size /= 8;
402 av_log(avctx,
AV_LOG_DEBUG,
"AV1 picture header size: %zu bytes.\n", av1_pic_hd_size);
405 tile_group_extra_size = (
av_log2(total_size) + 7) / 7 + 1;
406 av_log(avctx,
AV_LOG_DEBUG,
"Tile group extra size: %d bytes.\n", tile_group_extra_size);
408 total_size += (pic->
header_size + tile_group_extra_size + av1_pic_hd_size);
428 memcpy(ptr, pic_hd_data, av1_pic_hd_size);
429 ptr += av1_pic_hd_size;
430 total_size -= av1_pic_hd_size;
431 av_log(avctx,
AV_LOG_DEBUG,
"AV1 total_size after write picture header: %d.\n", total_size);
433 total_size -= tile_group_extra_size;
439 assert((total_size + tile_group_extra_size) * 8 == bit_len);
467 .transfer_characteristics = avctx->
color_trc,
473 .subsampling_x =
desc->log2_chroma_w,
474 .subsampling_y =
desc->log2_chroma_h,
512 "any normal level, using maximum parameters level by default.\n");
552 D3D12_VIDEO_ENCODER_AV1_PROFILE
profile = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
553 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS
level = { 0 };
557 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 support = {
559 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
560 .InputFormat = hwctx->
format,
561 .RateControl =
ctx->rc,
562 .IntraRefresh = D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE,
563 .SubregionFrameEncoding = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
564 .ResolutionsListCount = 1,
565 .pResolutionList = &
ctx->resolution,
566 .CodecGopSequence =
ctx->gop,
568 .CodecConfiguration =
ctx->codec_conf,
569 .SuggestedProfile.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE),
570 .SuggestedProfile.pAV1Profile = &
profile,
571 .SuggestedLevel.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS),
572 .SuggestedLevel.pAV1LevelSetting = &
level,
573 .pResolutionDependentSupport = &
ctx->res_limits,
574 .SubregionFrameEncodingData.pTilesPartition_AV1 =
ctx->subregions_layout.pTilesPartition_AV1,
577 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_SUPPORT1,
578 &support,
sizeof(support));
585 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
586 av_log(avctx,
AV_LOG_ERROR,
"Driver does not support some request D3D12VA AV1 features. %#x\n",
587 support.ValidationFlags);
591 if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS) {
592 ctx->is_texture_array = 1;
593 av_log(avctx,
AV_LOG_DEBUG,
"D3D12 video encode on this device uses texture array mode.\n");
596 memset(seqheader_obu, 0,
sizeof(*seqheader_obu));
626 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION *
config;
627 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT av1_caps;
629 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codec_caps = {
631 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
632 .Profile =
ctx->profile->d3d12_profile,
633 .CodecSupportLimits.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT),
636 codec_caps.CodecSupportLimits.pAV1Support = &av1_caps;
638 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT,
639 &codec_caps,
sizeof(codec_caps));
640 if (!(SUCCEEDED(hr) && codec_caps.IsSupported))
643 ctx->codec_conf.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION);
645 if (!
ctx->codec_conf.pAV1Config)
651 config->FeatureFlags = D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_NONE;
652 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK) {
653 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK;
660 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER) {
661 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER;
665 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING) {
666 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING;
670 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY) {
671 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY;
675 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS) {
677 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS;
681 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING) {
683 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING;
687 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER) {
689 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER;
693 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP) {
695 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP;
699 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS) {
701 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS;
705 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION) {
707 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION;
711 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION) {
713 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION;
717 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND) {
719 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND;
732 int fixed_qp_key, fixed_qp_inter;
738 if (
ctx->rc.Mode == D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP) {
739 D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP *cqp_ctl;
746 fixed_qp_key = fixed_qp_inter;
749 "%d / %d for Key / Inter frames.\n",
750 fixed_qp_key, fixed_qp_inter);
752 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP);
757 cqp_ctl->ConstantQP_FullIntracodedFrame = fixed_qp_key;
758 cqp_ctl->ConstantQP_InterPredictedFrame_PrevRefOnly = fixed_qp_inter;
759 cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef = fixed_qp_inter;
761 ctx->rc.ConfigParams.pConfiguration_CQP = cqp_ctl;
764 priv->
q_idx_p = fixed_qp_inter;
769 ctx->gop.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_SEQUENCE_STRUCTURE);
771 if (!
ctx->gop.pAV1SequenceStructure)
774 ctx->gop.pAV1SequenceStructure->IntraDistance = base_ctx->
gop_size;
775 ctx->gop.pAV1SequenceStructure->InterFramePeriod = base_ctx->
b_per_p + 1;
786 ctx->level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
788 if (!
ctx->level.pAV1LevelSetting)
804 ctx->level.pAV1LevelSetting->Level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
805 avctx->
level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
810 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
813 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_MAIN;
817 if (priv->
tier >= 0) {
818 ctx->level.pAV1LevelSetting->Tier = priv->
tier == 0 ?
819 D3D12_VIDEO_ENCODER_AV1_TIER_MAIN :
820 D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
824 ctx->level.pAV1LevelSetting->Level,
825 ctx->level.pAV1LevelSetting->Tier == D3D12_VIDEO_ENCODER_AV1_TIER_MAIN ?
"Main" :
"High");
834 ctx->subregions_layout.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES);
835 D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *tiles_layout =
av_mallocz(
ctx->subregions_layout.DataSize);
836 ctx->subregions_layout.pTilesPartition_AV1 = tiles_layout;
839 tiles_layout->RowCount = 1;
840 tiles_layout->ColCount = 1;
870 { 1, 0, 0, 0, -1, 0, -1, -1 };
872 memset(frameheader_obu, 0,
sizeof(*frameheader_obu));
876 d3d12va_pic->
pic_ctl.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_CODEC_DATA);
878 if (!d3d12va_pic->
pic_ctl.pAV1PicData)
898 href =
ref->codec_priv;
907 if (base_ctx->
ref_l0 > 1) {
925 href =
ref->codec_priv;
929 }
else if (base_ctx->
ref_l0 == 1) {
935 av_log(avctx,
AV_LOG_ERROR,
"D3D12 AV1 video encode on this device requires B-frame support, "
936 "but it's not implemented.\n");
973 d3d12va_pic->
pic_ctl.pAV1PicData->InterpolationFilter = D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_SWITCHABLE;
976 d3d12va_pic->
pic_ctl.pAV1PicData->Flags |= D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_FLAG_ENABLE_ERROR_RESILIENT_MODE;
981 d3d12va_pic->
pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[
i].ReconstructedPictureResourceIndex =
987 d3d12va_pic->
pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[
i].ReconstructedPictureResourceIndex =
1007 .d3d12_codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
1013 .default_quality = 25,
1033 #ifdef CONFIG_AV1_D3D12VA_ENCODER
1052 "in 8-bit unsigned integer.\n", avctx->
level);
1057 ctx->explicit_qp = priv->
qp;
1069 ff_cbs_close(&priv->
cbc);
1081 #define OFFSET(x) offsetof(D3D12VAEncodeAV1Context, x)
1082 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1087 {
"qp",
"Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
1090 {
"profile",
"Set profile (general_profile_idc)",
1094 #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1095 { .i64 = value }, 0, 0, FLAGS, "profile"
1101 {
"tier",
"Set tier (general_tier_flag)",
1103 { .i64 = 0 }, 0, 1,
FLAGS,
"tier" },
1105 { .i64 = 0 }, 0, 0,
FLAGS,
"tier" },
1107 { .i64 = 1 }, 0, 0,
FLAGS,
"tier" },
1109 {
"level",
"Set level (general_level_idc)",
1113 #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1114 { .i64 = value }, 0, 0, FLAGS, "level"
1115 {
LEVEL(
"2.0", 0) },
1116 {
LEVEL(
"2.1", 1) },
1117 {
LEVEL(
"2.2", 2) },
1118 {
LEVEL(
"2.3", 3) },
1119 {
LEVEL(
"3.0", 4) },
1120 {
LEVEL(
"3.1", 5) },
1121 {
LEVEL(
"3.2", 6) },
1122 {
LEVEL(
"3.3", 7) },
1123 {
LEVEL(
"4.0", 8) },
1124 {
LEVEL(
"4.1", 9) },
1125 {
LEVEL(
"4.2", 10) },
1126 {
LEVEL(
"4.3", 11) },
1127 {
LEVEL(
"5.0", 12) },
1128 {
LEVEL(
"5.1", 13) },
1129 {
LEVEL(
"5.2", 14) },
1130 {
LEVEL(
"5.3", 15) },
1131 {
LEVEL(
"6.0", 16) },
1132 {
LEVEL(
"6.1", 17) },
1133 {
LEVEL(
"6.2", 18) },
1134 {
LEVEL(
"6.3", 19) },
1135 {
LEVEL(
"7.0", 20) },
1136 {
LEVEL(
"7.1", 21) },
1137 {
LEVEL(
"7.2", 22) },
1138 {
LEVEL(
"7.3", 23) },
1147 {
"i_qfactor",
"1" },
1148 {
"i_qoffset",
"0" },
1149 {
"b_qfactor",
"1" },
1150 {
"b_qoffset",
"0" },
1165 .
p.
name =
"av1_d3d12va",
1181 .p.wrapper_name =
"d3d12va",