29#include "config_components.h"
40#include <d3d12video.h>
43#ifndef D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION
44#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION \
45 ((D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE)5)
47#ifndef D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION
48#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION \
49 ((D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE)6)
52#ifndef D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX
53#define D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX ( 0xff )
134 { 0, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_0 },
135 { 1, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_1 },
136 { 2, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_2 },
137 { 3, D3D12_VIDEO_ENCODER_AV1_LEVELS_2_3 },
138 { 4, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_0 },
139 { 5, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_1 },
140 { 6, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_2 },
141 { 7, D3D12_VIDEO_ENCODER_AV1_LEVELS_3_3 },
142 { 8, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_0 },
143 { 9, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_1 },
144 { 10, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_2 },
145 { 11, D3D12_VIDEO_ENCODER_AV1_LEVELS_4_3 },
146 { 12, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_0 },
147 { 13, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_1 },
148 { 14, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2 },
149 { 15, D3D12_VIDEO_ENCODER_AV1_LEVELS_5_3 },
150 { 16, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_0 },
151 { 17, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_1 },
152 { 18, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_2 },
153 { 19, D3D12_VIDEO_ENCODER_AV1_LEVELS_6_3 },
154 { 20, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_0 },
155 { 21, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_1 },
156 { 22, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_2 },
157 { 23, D3D12_VIDEO_ENCODER_AV1_LEVELS_7_3 },
166static const D3D12_VIDEO_ENCODER_AV1_PROFILE
profile_main = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
167static const D3D12_VIDEO_ENCODER_AV1_PROFILE
profile_high = D3D12_VIDEO_ENCODER_AV1_PROFILE_HIGH;
168static const D3D12_VIDEO_ENCODER_AV1_PROFILE
profile_professional = D3D12_VIDEO_ENCODER_AV1_PROFILE_PROFESSIONAL;
170#define D3D_PROFILE_DESC(name) \
171 { sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE), { .pAV1Profile = (D3D12_VIDEO_ENCODER_AV1_PROFILE *)&profile_ ## name } }
183 char *
data,
size_t *data_len,
189 err = ff_cbs_write_fragment_data(priv->
cbc, obu);
208 err = ff_cbs_insert_unit_content(au, -1, obu_type, obu_unit,
NULL);
211 "type = %d.\n", obu_type);
218 char *
data,
size_t *data_len)
232 ff_cbs_fragment_reset(obu);
245 D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES *post_encode_values =
NULL;
253 uint64_t nb_subregions =
FFMAX(((D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)
data)->WrittenSubregionsCount, 1);
254 D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *tile_partition =
255 (D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *) (
data +
256 sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
257 sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA) * nb_subregions);
259 post_encode_values = (D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES *) (
data +
260 sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
261 sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA) * nb_subregions +
262 sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES));
264 if (nb_subregions > 1)
268 fh->
base_q_idx = post_encode_values->Quantization.BaseQIndex;
269 fh->
delta_q_y_dc = post_encode_values->Quantization.YDCDeltaQ;
270 fh->
delta_q_u_dc = post_encode_values->Quantization.UDCDeltaQ;
271 fh->
delta_q_u_ac = post_encode_values->Quantization.UACDeltaQ;
272 fh->
delta_q_v_dc = post_encode_values->Quantization.VDCDeltaQ;
273 fh->
delta_q_v_ac = post_encode_values->Quantization.VACDeltaQ;
274 fh->
using_qmatrix = post_encode_values->Quantization.UsingQMatrix;
275 fh->
qm_y = post_encode_values->Quantization.QMY;
276 fh->
qm_u = post_encode_values->Quantization.QMU;
277 fh->
qm_v = post_encode_values->Quantization.QMV;
292 for (
int i = 0;
i < 2;
i++) {
300 fh->
cdef_bits = post_encode_values->CDEF.CdefBits;
301 for (
int i = 0;
i < 8;
i++) {
309 fh->
delta_q_present = post_encode_values->QuantizationDelta.DeltaQPresent;
310 fh->
delta_q_res = post_encode_values->QuantizationDelta.DeltaQRes;
325 char *
data,
size_t *data_len)
335 av_log(avctx,
AV_LOG_ERROR,
"Failed to update current frame picture header: %d.\n", err);
348 ff_cbs_fragment_reset(obu);
355 uint32_t tile_group_size,
356 char *
data,
size_t *data_len)
380 ff_cbs_fragment_reset(obu);
386 uint64_t tile_size_bytes,
387 uint64_t *nb_subregions_out,
389 size_t *tile_payload_size_out)
391 uint8_t *meta_data =
NULL;
395 D3D12_VIDEO_ENCODER_OUTPUT_METADATA *
out;
396 D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *subregions;
398 uint64_t nb_subregions;
399 size_t tile_payload_size = 0;
405 out = (D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)meta_data;
406 subregions = (D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA *) (meta_data +
407 sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA));
409 if (
out->EncodeErrorFlags != D3D12_VIDEO_ENCODER_ENCODE_ERROR_FLAG_NO_ERROR) {
411 (uint64_t)
out->EncodeErrorFlags);
416 nb_subregions =
out->WrittenSubregionsCount;
417 if (nb_subregions == 0 || subregions[0].bSize == 0) {
429 for (uint64_t
i = 0;
i < nb_subregions;
i++) {
430 tiles[
i].full = subregions[
i].bSize;
431 tiles[
i].prefix = subregions[
i].bStartOffset;
432 tiles[
i].data = subregions[
i].bSize - subregions[
i].bStartOffset;
433 tile_payload_size +=
tiles[
i].data;
436 if (nb_subregions > 1)
437 tile_payload_size += (nb_subregions - 1) * tile_size_bytes;
439 *nb_subregions_out = nb_subregions;
441 *tile_payload_size_out = tile_payload_size;
454 uint8_t *mapped_data =
NULL;
455 uint8_t *tile_group_buf =
NULL;
456 char *obu_buf =
NULL;
458 size_t av1_pic_hd_size = 0;
461 size_t tile_payload_size = 0;
462 size_t total_size = 0;
463 uint64_t nb_subregions = 0;
464 int output_buffer_mapped = 0;
470 &nb_subregions, &
tiles,
480 output_buffer_mapped = 1;
482 tile_group_buf =
av_malloc(tile_payload_size);
483 if (!tile_group_buf) {
488 uint8_t *
dst = tile_group_buf;
490 uint64_t src_off = 0;
491 for (uint64_t
i = 0;
i < nb_subregions;
i++) {
494 uint64_t src_pos = src_off +
tiles[
i].prefix;
497 if (
i != nb_subregions - 1) {
499 uint64_t v =
tiles[
i].data - 1;
501 *
dst++ = (v >> (8 *
b)) & 0xff;
512 av1_pic_hd_size = bit_len / 8;
520 tile_payload_size, obu_buf, &bit_len);
525 obu_size = bit_len / 8;
527 total_size = pic->
header_size + av1_pic_hd_size + obu_size;
536 memcpy(ptr, pic_hd_data, av1_pic_hd_size);
537 ptr += av1_pic_hd_size;
539 memcpy(ptr, obu_buf, obu_size);
542 "pic header %zu, tile group %zu, total %zu bytes.\n",
543 nb_subregions, pic->
header_size, av1_pic_hd_size, obu_size, total_size);
546 if (output_buffer_mapped)
572 .high_bitdepth =
desc->comp[0].depth == 8 ? 0 : 1,
574 .transfer_characteristics = avctx->
color_trc,
580 .subsampling_x =
desc->log2_chroma_w,
581 .subsampling_y =
desc->log2_chroma_h,
621 "any normal level, using maximum parameters level by default.\n");
662 D3D12_VIDEO_ENCODER_AV1_PROFILE
profile = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
663 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS
level = { 0 };
667 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT1 support = {
669 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
670 .InputFormat = hwctx->
format,
671 .RateControl =
ctx->rc,
672 .IntraRefresh =
ctx->intra_refresh.Mode,
673 .SubregionFrameEncoding =
ctx->subregion_mode,
674 .ResolutionsListCount = 1,
675 .pResolutionList = &
ctx->resolution,
676 .CodecGopSequence =
ctx->gop,
678 .CodecConfiguration =
ctx->codec_conf,
679 .SuggestedProfile.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE),
680 .SuggestedProfile.pAV1Profile = &
profile,
681 .SuggestedLevel.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS),
682 .SuggestedLevel.pAV1LevelSetting = &
level,
683 .pResolutionDependentSupport = &
ctx->res_limits,
684 .SubregionFrameEncodingData.pTilesPartition_AV1 =
ctx->subregions_layout.pTilesPartition_AV1,
687 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_SUPPORT1,
688 &support,
sizeof(support));
695 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
696 av_log(avctx,
AV_LOG_ERROR,
"Driver does not support requested features. ValidationFlags: %#x\n",
697 support.ValidationFlags);
702 if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS) {
703 ctx->is_texture_array = 1;
704 av_log(avctx,
AV_LOG_DEBUG,
"D3D12 video encode on this device uses texture array mode.\n");
708 if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RATE_CONTROL_DELTA_QP_AVAILABLE) {
711 ctx->qp_map_region_size =
ctx->res_limits.QPMapRegionPixelsSize;
713 "(QP map region size: %d pixels).\n",
ctx->qp_map_region_size);
716 av_log(avctx,
AV_LOG_DEBUG,
"ROI encoding not supported by hardware for current rate control mode \n");
720 if (
ctx->me_precision != D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE_MAXIMUM) {
721 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_MOTION_ESTIMATION_PRECISION_MODE_LIMIT_AVAILABLE)) {
723 "precision mode limits.\n");
727 "precision mode limits.\n");
730 memset(seqheader_obu, 0,
sizeof(*seqheader_obu));
756 for (k = 0; (blksize << k) < target; k++);
764 D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES *tiles_layout;
766 ctx->subregions_layout.DataSize =
767 sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES);
771 ctx->subregions_layout.pTilesPartition_AV1 = tiles_layout;
777 int mi_cols = 2 * ((
width + 7) >> 3);
778 int mi_rows = 2 * ((
height + 7) >> 3);
779 int sb_cols = use_128 ? ((mi_cols + 31) >> 5) : ((mi_cols + 15) >> 4);
780 int sb_rows = use_128 ? ((mi_rows + 31) >> 5) : ((mi_rows + 15) >> 4);
781 int sb_shift = use_128 ? 5 : 4;
782 int sb_size = sb_shift + 2;
788 int min_log2_tiles =
FFMAX(min_log2_tile_cols,
790 int max_tile_area_sb_varied;
791 int tile_width_sb, tile_height_sb, widest_tile_sb;
793 int min_tile_cols = (sb_cols + max_tile_width_sb - 1) / max_tile_width_sb;
811 "of %d~%d.\n", priv->
tile_cols, min_tile_cols, sb_cols);
829 if ((sb_cols + tile_width_sb - 1) / tile_width_sb == priv->
tile_cols) {
837 if ((sb_rows + tile_height_sb - 1) / tile_height_sb ==
tile_rows &&
838 tile_height_sb <= max_tile_area_sb / tile_width_sb) {
857 max_tile_area_sb_varied = (sb_rows * sb_cols) >> (min_log2_tiles + 1);
859 max_tile_area_sb_varied = sb_rows * sb_cols;
860 tile_height_sb =
FFMAX(1, max_tile_area_sb_varied / widest_tile_sb);
863 (sb_rows + tile_height_sb - 1) / tile_height_sb,
885 "exceeds the AV1 maximum of %dx%d.\n",
width,
height,
893 tiles_layout->RowCount = priv->
tile_rows;
894 tiles_layout->ColCount = priv->
tile_cols;
903 if (
ctx->num_subregions <= 1)
904 ctx->subregion_mode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME;
912 use_128 ?
"128x128" :
"64x64",
913 ctx->num_subregions <= 1 ?
"full frame" :
926 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION *config;
927 D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT av1_caps;
929 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codec_caps = {
931 .Codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
932 .Profile =
ctx->profile->d3d12_profile,
933 .CodecSupportLimits.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION_SUPPORT),
936 codec_caps.CodecSupportLimits.pAV1Support = &av1_caps;
938 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT,
939 &codec_caps,
sizeof(codec_caps));
940 if (!(SUCCEEDED(hr) && codec_caps.IsSupported))
943 ctx->codec_conf.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_CODEC_CONFIGURATION);
945 if (!
ctx->codec_conf.pAV1Config)
949 config =
ctx->codec_conf.pAV1Config;
951 config->FeatureFlags = D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_NONE;
952 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK) {
953 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_128x128_SUPERBLOCK;
960 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER) {
961 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_RESTORATION_FILTER;
965 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING) {
966 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_PALETTE_ENCODING;
970 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY) {
971 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTRA_BLOCK_COPY;
975 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS) {
977 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_LOOP_FILTER_DELTAS;
981 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING) {
983 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_CDEF_FILTERING;
987 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER) {
989 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_DUAL_FILTER;
993 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP) {
995 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_JNT_COMP;
999 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS) {
1001 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_FRAME_REFERENCE_MOTION_VECTORS;
1005 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION) {
1007 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_SUPER_RESOLUTION;
1011 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION) {
1013 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_WARPED_MOTION;
1017 if (av1_caps.SupportedFeatureFlags & D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND) {
1019 config->FeatureFlags |= D3D12_VIDEO_ENCODER_AV1_FEATURE_FLAG_INTERINTRA_COMPOUND;
1032 int fixed_qp_key, fixed_qp_inter;
1038 if (
ctx->rc.Mode == D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP) {
1039 D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP *cqp_ctl;
1046 fixed_qp_key = fixed_qp_inter;
1049 "%d / %d for Key / Inter frames.\n",
1050 fixed_qp_key, fixed_qp_inter);
1052 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP);
1057 cqp_ctl->ConstantQP_FullIntracodedFrame = fixed_qp_key;
1058 cqp_ctl->ConstantQP_InterPredictedFrame_PrevRefOnly = fixed_qp_inter;
1059 cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef = fixed_qp_inter;
1061 ctx->rc.ConfigParams.pConfiguration_CQP = cqp_ctl;
1064 priv->
q_idx_p = fixed_qp_inter;
1069 ctx->gop.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_SEQUENCE_STRUCTURE);
1071 if (!
ctx->gop.pAV1SequenceStructure)
1074 ctx->gop.pAV1SequenceStructure->IntraDistance = base_ctx->
gop_size;
1075 ctx->gop.pAV1SequenceStructure->InterFramePeriod = base_ctx->
b_per_p + 1;
1086 ctx->level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
1088 if (!
ctx->level.pAV1LevelSetting)
1104 ctx->level.pAV1LevelSetting->Level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
1105 avctx->
level = D3D12_VIDEO_ENCODER_AV1_LEVELS_5_2;
1110 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
1113 ctx->level.pAV1LevelSetting->Tier = D3D12_VIDEO_ENCODER_AV1_TIER_MAIN;
1117 if (priv->
tier >= 0) {
1118 ctx->level.pAV1LevelSetting->Tier = priv->
tier == 0 ?
1119 D3D12_VIDEO_ENCODER_AV1_TIER_MAIN :
1120 D3D12_VIDEO_ENCODER_AV1_TIER_HIGH;
1124 ctx->level.pAV1LevelSetting->Level,
1125 ctx->level.pAV1LevelSetting->Tier == D3D12_VIDEO_ENCODER_AV1_TIER_MAIN ?
"Main" :
"High");
1132 if (!pic->
pic_ctl.pAV1PicData)
1155 { 1, 0, 0, 0, -1, 0, -1, -1 };
1157 memset(frameheader_obu, 0,
sizeof(*frameheader_obu));
1161 d3d12va_pic->
pic_ctl.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_CODEC_DATA);
1163 if (!d3d12va_pic->
pic_ctl.pAV1PicData)
1183 href =
ref->codec_priv;
1192 if (base_ctx->
ref_l0 > 1) {
1210 href =
ref->codec_priv;
1214 }
else if (base_ctx->
ref_l0 == 1) {
1220 av_log(avctx,
AV_LOG_ERROR,
"D3D12 AV1 video encode on this device requires B-frame support, "
1221 "but it's not implemented.\n");
1265 d3d12va_pic->
pic_ctl.pAV1PicData->SpatialLayerIndexPlus1 = hpic->
spatial_id + 1;
1267 d3d12va_pic->
pic_ctl.pAV1PicData->InterpolationFilter = D3D12_VIDEO_ENCODER_AV1_INTERPOLATION_FILTERS_SWITCHABLE;
1270 d3d12va_pic->
pic_ctl.pAV1PicData->Flags |= D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_FLAG_ENABLE_ERROR_RESILIENT_MODE;
1275 d3d12va_pic->
pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[
i].ReconstructedPictureResourceIndex =
1281 d3d12va_pic->
pic_ctl.pAV1PicData->ReferenceFramesReconPictureDescriptors[
i].ReconstructedPictureResourceIndex =
1295 d3d12va_pic->
pic_ctl.pAV1PicData->pRateControlQPMap = (INT16 *)d3d12va_pic->
qp_map;
1305 .d3d12_codec = D3D12_VIDEO_ENCODER_CODEC_AV1,
1311 .default_quality = 25,
1331#ifdef CONFIG_AV1_D3D12VA_ENCODER
1350 "in 8-bit unsigned integer.\n", avctx->
level);
1355 ctx->explicit_qp = priv->
qp;
1367 ff_cbs_close(&priv->
cbc);
1379#define OFFSET(x) offsetof(D3D12VAEncodeAV1Context, x)
1380#define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
1386 {
"qp",
"Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
1389 {
"profile",
"Set profile (general_profile_idc)",
1393#define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1394 { .i64 = value }, 0, 0, FLAGS, "profile"
1400 {
"tier",
"Set tier (general_tier_flag)",
1402 { .i64 = 0 }, 0, 1,
FLAGS,
"tier" },
1404 { .i64 = 0 }, 0, 0,
FLAGS,
"tier" },
1406 { .i64 = 1 }, 0, 0,
FLAGS,
"tier" },
1408 {
"level",
"Set level (general_level_idc)",
1412#define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
1413 { .i64 = value }, 0, 0, FLAGS, "level"
1414 {
LEVEL(
"2.0", 0) },
1415 {
LEVEL(
"2.1", 1) },
1416 {
LEVEL(
"2.2", 2) },
1417 {
LEVEL(
"2.3", 3) },
1418 {
LEVEL(
"3.0", 4) },
1419 {
LEVEL(
"3.1", 5) },
1420 {
LEVEL(
"3.2", 6) },
1421 {
LEVEL(
"3.3", 7) },
1422 {
LEVEL(
"4.0", 8) },
1423 {
LEVEL(
"4.1", 9) },
1424 {
LEVEL(
"4.2", 10) },
1425 {
LEVEL(
"4.3", 11) },
1426 {
LEVEL(
"5.0", 12) },
1427 {
LEVEL(
"5.1", 13) },
1428 {
LEVEL(
"5.2", 14) },
1429 {
LEVEL(
"5.3", 15) },
1430 {
LEVEL(
"6.0", 16) },
1431 {
LEVEL(
"6.1", 17) },
1432 {
LEVEL(
"6.2", 18) },
1433 {
LEVEL(
"6.3", 19) },
1434 {
LEVEL(
"7.0", 20) },
1435 {
LEVEL(
"7.1", 21) },
1436 {
LEVEL(
"7.2", 22) },
1437 {
LEVEL(
"7.3", 23) },
1440 {
"tiles",
"Tile columns x rows (Use minimal tile column/row number "
1441 "automatically by default)",
1451 {
"i_qfactor",
"1" },
1452 {
"i_qoffset",
"0" },
1453 {
"b_qfactor",
"1" },
1454 {
"b_qoffset",
"0" },
1462 .class_name =
"av1_d3d12va",
1469 .p.name =
"av1_d3d12va",
1485 .p.wrapper_name =
"d3d12va",
uint8_t ptrdiff_t const uint8_t ptrdiff_t int intptr_t intptr_t int int16_t * dst
const FFCodec ff_av1_d3d12va_encoder
static AVFormatContext * ctx
static AVDictionary * opts
const AV1LevelDescriptor * ff_av1_guess_level(int64_t bitrate, int tier, int width, int height, int tiles, int tile_cols, float fps)
Guess the level of a stream from some parameters.
static const AV1LevelDescriptor av1_levels[]
ignore entries which named in spec but no details.
Libavcodec external API header.
static int FUNC tile_group_obu(CodedBitstreamContext *ctx, RWContext *rw, AV1RawTileGroup *current)
#define i(width, name, range_min, range_max)
#define CODEC_PIXFMTS(...)
#define FF_CODEC_CAP_NOT_INIT_THREADSAFE
The codec is not known to be init-threadsafe (i.e.
#define FF_CODEC_RECEIVE_PACKET_CB(func)
#define CODEC_LONG_NAME(str)
#define FF_CODEC_CAP_INIT_CLEANUP
The codec allows calling the close function for deallocation even if the init function returned a fai...
common internal and external API header
int ff_d3d12va_encode_receive_packet(AVCodecContext *avctx, AVPacket *pkt)
void ff_d3d12va_encode_check_encoder_feature_flags(void *log_ctx, D3D12_VIDEO_ENCODER_VALIDATION_FLAGS flags)
const AVCodecHWConfigInternal *const ff_d3d12va_encode_hw_configs[]
int ff_d3d12va_encode_init(AVCodecContext *avctx)
int ff_d3d12va_encode_close(AVCodecContext *avctx)
#define D3D12VA_ENCODE_RC_OPTIONS
#define D3D12VA_ENCODE_COMMON_OPTIONS
#define MAX_PARAM_BUFFER_SIZE
#define D3D_PROFILE_DESC(name)
static int d3d12va_encode_av1_get_coded_data(AVCodecContext *avctx, D3D12VAEncodePicture *pic, AVPacket *pkt)
static int d3d12va_encode_av1_set_level(AVCodecContext *avctx)
static const AVOption d3d12va_encode_av1_options[]
static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_professional
static av_always_inline int d3d12va_encode_av1_tile_log2(int blksize, int target)
static int d3d12va_encode_av1_get_encoder_caps(AVCodecContext *avctx)
static int d3d12va_encode_av1_get_buffer_size(AVCodecContext *avctx, D3D12VAEncodePicture *pic, uint64_t tile_size_bytes, uint64_t *nb_subregions_out, D3D12VAEncodeAV1TileInfo **tiles_out, size_t *tile_payload_size_out)
#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_UNIFORM_GRID_PARTITION
static int d3d12va_encode_av1_init(AVCodecContext *avctx)
static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_main
#define D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_CONFIGURABLE_GRID_PARTITION
static int d3d12va_encode_av1_init_picture_params(AVCodecContext *avctx, FFHWBaseEncodePicture *pic)
static const D3D12VAEncodeType d3d12va_encode_type_av1
static int d3d12va_encode_av1_write_sequence_header(AVCodecContext *avctx, char *data, size_t *data_len)
#define LEVEL(name, value)
static int d3d12va_encode_av1_write_picture_header(AVCodecContext *avctx, D3D12VAEncodePicture *pic, char *data, size_t *data_len)
static int d3d12va_encode_av1_set_tile(AVCodecContext *avctx)
static int d3d12va_hw_base_encode_init_params_av1(FFHWBaseEncodeContext *base_ctx, AVCodecContext *avctx, D3D12VAHWBaseEncodeAV1 *common, D3D12VAHWBaseEncodeAV1Opts *opts)
static const D3D12_VIDEO_ENCODER_AV1_PROFILE profile_high
static const FFCodecDefault d3d12va_encode_av1_defaults[]
static int d3d12va_encode_av1_add_obu(AVCodecContext *avctx, CodedBitstreamFragment *au, CodedBitstreamUnitType obu_type, void *obu_unit)
static int d3d12va_encode_av1_write_tile_group(AVCodecContext *avctx, uint8_t *tile_group, uint32_t tile_group_size, char *data, size_t *data_len)
static int d3d12va_encode_av1_close(AVCodecContext *avctx)
static const AVClass d3d12va_encode_av1_class
#define PROFILE(name, value)
static int d3d12va_encode_av1_configure(AVCodecContext *avctx)
#define D3D12_VIDEO_ENCODER_AV1_INVALID_DPB_RESOURCE_INDEX
static int d3d12va_encode_av1_write_obu(AVCodecContext *avctx, char *data, size_t *data_len, CodedBitstreamFragment *obu)
static const D3D12VAEncodeProfile d3d12va_encode_av1_profiles[]
static int d3d12va_encode_av1_init_sequence_params(AVCodecContext *avctx)
static void d3d12va_encode_av1_free_picture_params(D3D12VAEncodePicture *pic)
static int d3d12va_encode_av1_update_current_frame_picture_header(AVCodecContext *avctx, D3D12VAEncodePicture *pic, AV1RawOBU *frameheader_obu)
#define AV_PROFILE_AV1_HIGH
#define AV_PROFILE_UNKNOWN
#define AV_PROFILE_AV1_MAIN
#define AV_PROFILE_AV1_PROFESSIONAL
int(* init)(AVBSFContext *ctx)
int ff_get_encode_buffer(AVCodecContext *avctx, AVPacket *avpkt, int64_t size, int flags)
Get a buffer for a packet.
@ AV_OPT_TYPE_IMAGE_SIZE
Underlying C type is two consecutive integers.
@ AV_OPT_TYPE_CONST
Special option type for declaring named constants.
@ AV_OPT_TYPE_INT
Underlying C type is int.
#define AV_CODEC_CAP_ENCODER_REORDERED_OPAQUE
This encoder can reorder user opaque values from input AVFrames and return them with corresponding ou...
#define AV_CODEC_CAP_DELAY
Encoder or decoder requires flushing with NULL input at the end in order to give the complete and cor...
#define AV_CODEC_CAP_DR1
Codec uses get_buffer() or get_encode_buffer() for allocating buffers and supports custom allocators.
#define AV_CODEC_CAP_HARDWARE
Codec is backed by a hardware implementation.
void av_buffer_unref(AVBufferRef **buf)
Free a given reference and automatically free the buffer if there are no more references to it.
#define AVERROR_UNKNOWN
Unknown error, typically from an external library.
#define AVERROR_PATCHWELCOME
Not yet implemented in FFmpeg, patches welcome.
#define AVERROR_EXTERNAL
Generic error in an external library.
AVFifo * av_fifo_alloc2(size_t nb_elems, size_t elem_size, unsigned int flags)
Allocate and initialize an AVFifo with a given element size.
void av_fifo_freep2(AVFifo **f)
Free an AVFifo and reset pointer to NULL.
#define AV_FIFO_FLAG_AUTO_GROW
Automatically resize the FIFO on writes, so that the data fits.
int av_fifo_write(AVFifo *f, const void *buf, size_t nb_elems)
Write data into a FIFO.
int av_fifo_read(AVFifo *f, void *buf, size_t nb_elems)
Read data from a FIFO.
#define AV_LOG_DEBUG
Stuff which is only useful for libav* developers.
#define AV_LOG_VERBOSE
Detailed information.
#define AV_LOG_ERROR
Something went wrong and cannot losslessly be recovered.
const char * av_default_item_name(void *ptr)
Return the context name.
#define LIBAVUTIL_VERSION_INT
#define HW_BASE_ENCODE_COMMON_OPTIONS
@ FF_HW_FLAG_NON_IDR_KEY_PICTURES
@ FF_HW_FLAG_B_PICTURE_REFERENCES
@ AV1_OBU_SEQUENCE_HEADER
@ AV1_INTERPOLATION_FILTER_SWITCHABLE
@ AV1_TOTAL_REFS_PER_FRAME
uint32_t CodedBitstreamUnitType
The codec-specific type of a bitstream unit.
Memory handling functions.
const AVPixFmtDescriptor * av_pix_fmt_desc_get(enum AVPixelFormat pix_fmt)
@ AVCHROMA_LOC_TOPLEFT
ITU-R 601, SMPTE 274M 296M S314M(DV 4:1:1), mpeg2 4:2:2.
@ AVCHROMA_LOC_LEFT
MPEG-2/4 4:2:0, H.264 default for 4:2:0.
@ AVCOL_RANGE_JPEG
Full range content.
@ AV_PIX_FMT_D3D12
Hardware surfaces for Direct3D 12.
#define FF_ARRAY_ELEMS(a)
uint8_t chroma_sample_position
AV1RawFrameHeader frame_header
AV1RawSequenceHeader sequence_header
union AV1RawOBU::@016362317061177152367125047142162076164261250366 obu
uint8_t tile_start_and_end_present_flag
Describe the class of an AVClass context structure.
main external API structure.
int width
picture width / height.
enum AVColorRange color_range
MPEG vs JPEG YUV range.
enum AVColorPrimaries color_primaries
Chromaticity coordinates of the source primaries.
int level
Encoding level descriptor.
int64_t bit_rate
the average bitrate
enum AVColorSpace colorspace
YUV colorspace type.
enum AVColorTransferCharacteristic color_trc
Color Transfer Characteristic.
enum AVChromaLocation chroma_sample_location
This defines the location of chroma samples.
float i_quant_factor
qscale factor between P- and I-frames If > 0 then the last P-frame quantizer will be used (q = lastp_...
float i_quant_offset
qscale offset between P and I-frames
This struct is allocated as AVHWFramesContext.hwctx.
DXGI_FORMAT format
DXGI_FORMAT format.
void * hwctx
The format-specific data, allocated and freed automatically along with this context.
enum AVPixelFormat sw_format
The pixel format identifying the actual data layout of the hardware frames.
This structure stores compressed data.
Descriptor that unambiguously describes how the bits of a pixel are stored in the up to 4 data planes...
AV1ReferenceFrameState ref[AV1_NUM_REF_FRAMES]
Context structure for coded bitstream operations.
void * priv_data
Internal codec-specific data.
Coded bitstream fragment structure, combining one or more units.
size_t data_bit_padding
The number of bits which should be ignored in the final byte.
size_t data_size
The number of bytes in the bitstream.
uint8_t * data
Pointer to the bitstream form of this fragment.
D3D12VAHWBaseEncodeAV1Opts unit_opts
CodedBitstreamFragment current_obu
D3D12VAHWBaseEncodeAV1 units
uint8_t height_in_sbs_minus_1[AV1_MAX_TILE_ROWS]
CodedBitstreamContext * cbc
D3D12VAEncodeContext common
uint16_t context_update_tile_id
D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES_FLAGS post_encode_values_flag
uint8_t width_in_sbs_minus_1[AV1_MAX_TILE_COLS]
AVFifo * picture_header_list
D3D12_VIDEO_ENCODER_AV1_LEVELS d3d12_level
D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION codec_conf
D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE gop
D3D12_VIDEO_ENCODER_LEVEL_SETTING level
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA subregions_layout
AVBufferRef * output_buffer_ref
D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA pic_ctl
ID3D12Resource * resolved_metadata
ID3D12Resource * output_buffer
int enable_masked_compound
int enable_intra_block_copy
int enable_intra_edge_filter
int enable_loop_filter_delta
int enable_128x128_superblock
int enable_interintra_compound
AV1RawOBU raw_frame_header
AV1RawOBU raw_sequence_header
AVHWFramesContext * input_frames
int nb_refs[MAX_REFERENCE_LIST_NUM]
struct FFHWBaseEncodePicture * refs[MAX_REFERENCE_LIST_NUM][MAX_PICTURE_REFERENCES]
#define av_malloc_array(a, b)
static int ref[MAX_W *MAX_W]
static int write_sequence_header(AVCodecContext *avctx, FFHWBaseEncodePicture *base_pic, uint8_t *data, size_t *data_len)