32 #include "config_components.h"
44 uint64_t completion = ID3D12Fence_GetCompletedValue(psync_ctx->
fence);
45 if (completion < psync_ctx->fence_value) {
46 if (FAILED(ID3D12Fence_SetEventOnCompletion(psync_ctx->
fence, psync_ctx->
fence_value, psync_ctx->
event)))
49 WaitForSingleObjectEx(psync_ctx->
event, INFINITE, FALSE);
59 DX_CHECK(ID3D12CommandQueue_Signal(
ctx->command_queue,
ctx->sync_ctx.fence, ++
ctx->sync_ctx.fence_value));
78 uint64_t completion = ID3D12Fence_GetCompletedValue(
ctx->sync_ctx.fence);
86 hr = ID3D12Device_CreateCommandAllocator(
ctx->hwctx->device, D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
87 &IID_ID3D12CommandAllocator, (
void **)ppAllocator);
102 .fence_value = fence_value,
124 completion = ID3D12Fence_GetCompletedValue(
ctx->sync_ctx.fence);
125 if (completion < pic->fence_value) {
126 if (FAILED(ID3D12Fence_SetEventOnCompletion(
ctx->sync_ctx.fence, pic->
fence_value,
127 ctx->sync_ctx.event)))
130 WaitForSingleObjectEx(
ctx->sync_ctx.event, INFINITE, FALSE);
147 int width =
sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA);
148 #if CONFIG_AV1_D3D12VA_ENCODER
149 if (
ctx->codec->d3d12_codec == D3D12_VIDEO_ENCODER_CODEC_AV1) {
150 width +=
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES)
151 +
sizeof(D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES);
154 D3D12_HEAP_PROPERTIES encoded_meta_props = { .Type = D3D12_HEAP_TYPE_DEFAULT }, resolved_meta_props;
155 D3D12_HEAP_TYPE resolved_heap_type = D3D12_HEAP_TYPE_READBACK;
158 D3D12_RESOURCE_DESC meta_desc = {
159 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
161 .Width =
ctx->req.MaxEncoderOutputMetadataBufferSize,
163 .DepthOrArraySize = 1,
165 .Format = DXGI_FORMAT_UNKNOWN,
166 .SampleDesc = { .Count = 1, .Quality = 0 },
167 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
168 .Flags = D3D12_RESOURCE_FLAG_NONE,
171 hr = ID3D12Device_CreateCommittedResource(
ctx->hwctx->device, &encoded_meta_props, D3D12_HEAP_FLAG_NONE,
172 &meta_desc, D3D12_RESOURCE_STATE_COMMON,
NULL,
179 ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(
ctx->hwctx->device, &resolved_meta_props, 0, resolved_heap_type);
181 meta_desc.Width =
width;
183 hr = ID3D12Device_CreateCommittedResource(
ctx->hwctx->device, &resolved_meta_props, D3D12_HEAP_FLAG_NONE,
184 &meta_desc, D3D12_RESOURCE_STATE_COMMON,
NULL,
207 ID3D12CommandAllocator *command_allocator =
NULL;
208 ID3D12VideoEncodeCommandList2 *cmd_list =
ctx->command_list;
209 D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
210 D3D12_VIDEO_ENCODE_REFERENCE_FRAMES d3d12_refs = { 0 };
211 int barriers_ref_index = 0;
212 D3D12_RESOURCE_BARRIER *barriers_ref =
NULL;
214 D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAGS seq_flags = D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_NONE;
217 if (
ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
218 seq_flags |= D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_REQUEST_INTRA_REFRESH;
221 D3D12_VIDEO_ENCODER_ENCODEFRAME_INPUT_ARGUMENTS input_args = {
222 .SequenceControlDesc = {
224 .IntraRefreshConfig =
ctx->intra_refresh,
225 .RateControl =
ctx->rc,
226 .PictureTargetResolution =
ctx->resolution,
227 .SelectedLayoutMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
228 .FrameSubregionsLayoutData =
ctx->subregions_layout,
229 .CodecGopSequence =
ctx->gop,
232 .InputFrameSubresource = 0,
235 D3D12_VIDEO_ENCODER_ENCODEFRAME_OUTPUT_ARGUMENTS output_args = { 0 };
237 D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS input_metadata = {
238 .EncoderCodec =
ctx->codec->d3d12_codec,
239 .EncoderProfile =
ctx->profile->d3d12_profile,
240 .EncoderInputFormat = frames_hwctx->
format,
241 .EncodedPictureEffectiveResolution =
ctx->resolution,
244 D3D12_VIDEO_ENCODER_RESOLVE_METADATA_OUTPUT_ARGUMENTS output_metadata = { 0 };
302 if (
ctx->codec->init_picture_params) {
303 err =
ctx->codec->init_picture_params(avctx, base_pic);
306 "parameters: %d.\n", err);
312 if (
ctx->codec->write_sequence_header) {
313 bit_len = 8 *
sizeof(
data);
314 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
317 "header: %d.\n", err);
336 d3d12_refs.NumTexture2Ds = base_pic->
nb_refs[0] + base_pic->
nb_refs[1];
337 if (d3d12_refs.NumTexture2Ds) {
338 d3d12_refs.ppTexture2Ds =
av_calloc(d3d12_refs.NumTexture2Ds,
339 sizeof(*d3d12_refs.ppTexture2Ds));
340 if (!d3d12_refs.ppTexture2Ds) {
345 if (
ctx->is_texture_array) {
346 d3d12_refs.pSubresources =
av_calloc(d3d12_refs.NumTexture2Ds,
347 sizeof(*d3d12_refs.pSubresources));
348 if (!d3d12_refs.pSubresources) {
355 for (j = 0; j < base_pic->
nb_refs[0]; j++) {
357 if (
ctx->is_texture_array)
361 for (j = 0; j < base_pic->
nb_refs[1]; j++) {
363 if (
ctx->is_texture_array)
369 input_args.PictureControlDesc.IntraRefreshFrameIndex =
ctx->intra_refresh_frame_index;
371 input_args.PictureControlDesc.Flags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_FLAG_USED_AS_REFERENCE_PICTURE;
373 input_args.PictureControlDesc.PictureControlCodecData = pic->
pic_ctl;
374 input_args.PictureControlDesc.ReferenceFrames = d3d12_refs;
380 output_args.ReconstructedPicture.ReconstructedPictureSubresource =
ctx->is_texture_array ? pic->
subresource_index : 0;
382 output_args.EncoderOutputMetadata.Offset = 0;
385 input_metadata.HWLayoutMetadata.Offset = 0;
388 output_metadata.ResolvedLayoutMetadata.Offset = 0;
394 hr = ID3D12CommandAllocator_Reset(command_allocator);
400 hr = ID3D12VideoEncodeCommandList2_Reset(cmd_list, command_allocator);
406 #define TRANSITION_BARRIER(res, subres, before, after) \
407 (D3D12_RESOURCE_BARRIER) { \
408 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, \
409 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, \
412 .Subresource = subres, \
413 .StateBefore = before, \
414 .StateAfter = after, \
419 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
420 D3D12_RESOURCE_STATE_COMMON,
421 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
423 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
424 D3D12_RESOURCE_STATE_COMMON,
425 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
427 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
428 D3D12_RESOURCE_STATE_COMMON,
429 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
431 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
432 D3D12_RESOURCE_STATE_COMMON,
433 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
435 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
437 if (
ctx->is_texture_array)
439 sizeof(D3D12_RESOURCE_BARRIER));
443 if (
ctx->is_texture_array) {
444 D3D12_RESOURCE_DESC references_tex_array_desc = { 0 };
447 for (uint32_t reference_subresource = 0; reference_subresource < references_tex_array_desc.DepthOrArraySize;
448 reference_subresource++) {
450 uint32_t array_size = references_tex_array_desc.DepthOrArraySize;
451 uint32_t mip_slice = reference_subresource % references_tex_array_desc.MipLevels;
452 uint32_t array_slice = (reference_subresource / references_tex_array_desc.MipLevels) % array_size;
454 for (uint32_t plane_slice = 0; plane_slice <
ctx->plane_count; plane_slice++) {
455 uint32_t outputSubresource = mip_slice + array_slice * references_tex_array_desc.MipLevels +
456 plane_slice * references_tex_array_desc.MipLevels * array_size;
459 D3D12_RESOURCE_STATE_COMMON,
460 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
463 D3D12_RESOURCE_STATE_COMMON,
464 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
470 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
471 D3D12_RESOURCE_STATE_COMMON,
472 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
474 if (d3d12_refs.NumTexture2Ds) {
475 for (
i = 0;
i < d3d12_refs.NumTexture2Ds;
i++)
477 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
478 D3D12_RESOURCE_STATE_COMMON,
479 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
482 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index, barriers_ref);
484 ID3D12VideoEncodeCommandList2_EncodeFrame(cmd_list,
ctx->encoder,
ctx->encoder_heap,
485 &input_args, &output_args);
488 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
489 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
490 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
492 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 1, &barriers[3]);
494 ID3D12VideoEncodeCommandList2_ResolveEncoderOutputMetadata(cmd_list, &input_metadata, &output_metadata);
496 if (barriers_ref_index > 0) {
497 for (
i = 0;
i < barriers_ref_index;
i++)
498 FFSWAP(D3D12_RESOURCE_STATES, barriers_ref[
i].Transition.StateBefore, barriers_ref[
i].Transition.StateAfter);
500 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index,
505 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
506 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
507 D3D12_RESOURCE_STATE_COMMON);
509 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
510 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
511 D3D12_RESOURCE_STATE_COMMON);
513 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
514 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
515 D3D12_RESOURCE_STATE_COMMON);
517 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
518 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
519 D3D12_RESOURCE_STATE_COMMON);
521 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
523 hr = ID3D12VideoEncodeCommandList2_Close(cmd_list);
536 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
545 hr = ID3D12CommandQueue_Signal(
ctx->command_queue,
ctx->sync_ctx.fence, ++
ctx->sync_ctx.fence_value);
558 if (
ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
559 ctx->intra_refresh_frame_index =
560 (
ctx->intra_refresh_frame_index + 1) %
ctx->intra_refresh.IntraRefreshDuration;
563 if (d3d12_refs.ppTexture2Ds)
566 if (
ctx->is_texture_array && d3d12_refs.pSubresources)
567 av_freep(&d3d12_refs.pSubresources);
575 if (command_allocator)
578 if (d3d12_refs.ppTexture2Ds)
581 if (
ctx->is_texture_array && d3d12_refs.pSubresources)
582 av_freep(&d3d12_refs.pSubresources);
587 if (
ctx->codec->free_picture_params)
588 ctx->codec->free_picture_params(pic);
606 "%"PRId64
"/%"PRId64
".\n",
623 switch (
ctx->rc.Mode)
625 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP:
626 av_freep(&
ctx->rc.ConfigParams.pConfiguration_CQP);
628 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR:
629 av_freep(&
ctx->rc.ConfigParams.pConfiguration_CBR);
631 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR:
632 av_freep(&
ctx->rc.ConfigParams.pConfiguration_VBR);
634 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR:
635 av_freep(&
ctx->rc.ConfigParams.pConfiguration_QVBR);
650 if (
ctx->codec->picture_priv_data_size > 0) {
669 if (
ctx->codec->free_picture_params)
670 ctx->codec->free_picture_params(priv);
678 D3D12_VIDEO_ENCODER_OUTPUT_METADATA *meta =
NULL;
689 meta = (D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)
data;
691 if (meta->EncodeErrorFlags != D3D12_VIDEO_ENCODER_ENCODE_ERROR_FLAG_NO_ERROR) {
697 if (meta->EncodedBitstreamWrittenBytesCount == 0) {
703 *
size = meta->EncodedBitstreamWrittenBytesCount;
714 uint8_t *ptr, *mapped_data;
715 size_t total_size = 0;
742 memcpy(ptr, mapped_data, total_size);
765 if (
ctx->codec->get_coded_data)
766 err =
ctx->codec->get_coded_data(avctx, pic,
pkt);
797 depth =
desc->comp[0].depth;
798 for (
i = 1;
i <
desc->nb_components;
i++) {
799 if (
desc->comp[
i].depth != depth) {
809 for (
i = 0; (
ctx->codec->profiles[
i].av_profile !=
815 if (
desc->nb_components > 1 &&
839 {
RC_MODE_CQP,
"CQP", 0, 0, 1, 0, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP },
840 {
RC_MODE_CBR,
"CBR", 1, 0, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR },
841 {
RC_MODE_VBR,
"VBR", 1, 1, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR },
842 {
RC_MODE_QVBR,
"QVBR", 1, 1, 1, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR },
849 D3D12_FEATURE_DATA_VIDEO_ENCODER_RATE_CONTROL_MODE d3d12_rc_mode = {
850 .Codec =
ctx->codec->d3d12_codec,
856 d3d12_rc_mode.IsSupported = 0;
857 d3d12_rc_mode.RateControlMode =
rc_mode->d3d12_mode;
859 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3,
860 D3D12_FEATURE_VIDEO_ENCODER_RATE_CONTROL_MODE,
861 &d3d12_rc_mode,
sizeof(d3d12_rc_mode));
867 return d3d12_rc_mode.IsSupported;
877 int64_t hrd_initial_buffer_fullness;
881 #define SET_QP_RANGE(ctl) do { \
882 if (avctx->qmin > 0 || avctx->qmax > 0) { \
883 ctl->MinQP = avctx->qmin; \
884 ctl->MaxQP = avctx->qmax; \
885 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_QP_RANGE; \
889 #define SET_MAX_FRAME_SIZE(ctl) do { \
890 if (ctx->max_frame_size > 0) { \
891 ctl->MaxFrameBitSize = ctx->max_frame_size * 8; \
892 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_MAX_FRAME_SIZE; \
908 #define TRY_RC_MODE(mode, fail) do { \
909 rc_mode = &d3d12va_encode_rc_modes[mode]; \
910 if (!(rc_mode->d3d12_mode && check_rate_control_support(avctx, rc_mode))) { \
912 av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
913 "RC mode.\n", rc_mode->name); \
914 return AVERROR(EINVAL); \
916 av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
917 "RC mode.\n", rc_mode->name); \
920 goto rc_mode_found; \
924 if (
ctx->explicit_rc_mode)
927 if (
ctx->explicit_qp)
954 "RC mode compatible with selected options.\n");
969 "bitrate (%"PRId64
") must not be greater than "
970 "maxrate (%"PRId64
").\n", avctx->
bit_rate,
974 rc_target_bitrate = avctx->
bit_rate;
981 rc_target_bitrate = avctx->
bit_rate;
982 rc_peak_bitrate = 2 * avctx->
bit_rate;
987 "in %s RC mode.\n",
rc_mode->name);
989 rc_target_bitrate = avctx->
bit_rate;
993 rc_target_bitrate = 0;
998 if (
ctx->explicit_qp) {
999 rc_quality =
ctx->explicit_qp;
1006 rc_quality =
ctx->codec->default_quality;
1008 "using default (%d).\n", rc_quality);
1024 "must have initial buffer size (%d) <= "
1025 "buffer size (%"PRId64
").\n",
1031 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1036 "in %s RC mode.\n",
rc_mode->name);
1039 hrd_buffer_size = 0;
1040 hrd_initial_buffer_fullness = 0;
1043 if (rc_target_bitrate > UINT32_MAX ||
1044 hrd_buffer_size > UINT32_MAX ||
1045 hrd_initial_buffer_fullness > UINT32_MAX) {
1047 "greater are not supported by D3D12.\n");
1051 ctx->rc_quality = rc_quality;
1060 "initial fullness %"PRId64
" bits.\n",
1061 hrd_buffer_size, hrd_initial_buffer_fullness);
1072 fr_num, fr_den, (
double)fr_num / fr_den);
1074 ctx->rc.Flags = D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_NONE;
1075 ctx->rc.TargetFrameRate.Numerator = fr_num;
1076 ctx->rc.TargetFrameRate.Denominator = fr_den;
1084 D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR *cbr_ctl;
1086 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR);
1091 cbr_ctl->TargetBitRate = rc_target_bitrate;
1092 cbr_ctl->VBVCapacity = hrd_buffer_size;
1093 cbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1094 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1099 ctx->rc.ConfigParams.pConfiguration_CBR = cbr_ctl;
1103 D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR *vbr_ctl;
1105 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR);
1110 vbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1111 vbr_ctl->PeakBitRate = rc_peak_bitrate;
1112 vbr_ctl->VBVCapacity = hrd_buffer_size;
1113 vbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1114 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1119 ctx->rc.ConfigParams.pConfiguration_VBR = vbr_ctl;
1123 D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR *qvbr_ctl;
1125 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR);
1130 qvbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1131 qvbr_ctl->PeakBitRate = rc_peak_bitrate;
1132 qvbr_ctl->ConstantQualityTarget = rc_quality;
1137 ctx->rc.ConfigParams.pConfiguration_QVBR = qvbr_ctl;
1150 uint32_t ref_l0, ref_l1;
1153 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT support;
1155 D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264;
1156 D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevc;
1157 #if CONFIG_AV1_D3D12VA_ENCODER
1158 D3D12_VIDEO_ENCODER_CODEC_AV1_PICTURE_CONTROL_SUPPORT av1;
1162 support.NodeIndex = 0;
1163 support.Codec =
ctx->codec->d3d12_codec;
1164 support.Profile =
ctx->profile->d3d12_profile;
1166 switch (
ctx->codec->d3d12_codec) {
1167 case D3D12_VIDEO_ENCODER_CODEC_H264:
1168 support.PictureSupport.DataSize =
sizeof(codec_support.h264);
1169 support.PictureSupport.pH264Support = &codec_support.h264;
1172 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1173 support.PictureSupport.DataSize =
sizeof(codec_support.hevc);
1174 support.PictureSupport.pHEVCSupport = &codec_support.hevc;
1177 #if CONFIG_AV1_D3D12VA_ENCODER
1178 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1179 memset(&codec_support.av1, 0,
sizeof(codec_support.av1));
1180 support.PictureSupport.DataSize =
sizeof(codec_support.av1);
1181 support.PictureSupport.pAV1Support = &codec_support.av1;
1188 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
1189 &support,
sizeof(support));
1193 if (support.IsSupported) {
1194 switch (
ctx->codec->d3d12_codec) {
1195 case D3D12_VIDEO_ENCODER_CODEC_H264:
1196 ref_l0 =
FFMIN(support.PictureSupport.pH264Support->MaxL0ReferencesForP,
1197 support.PictureSupport.pH264Support->MaxL1ReferencesForB ?
1198 support.PictureSupport.pH264Support->MaxL1ReferencesForB : UINT_MAX);
1199 ref_l1 = support.PictureSupport.pH264Support->MaxL1ReferencesForB;
1202 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1203 ref_l0 =
FFMIN(support.PictureSupport.pHEVCSupport->MaxL0ReferencesForP,
1204 support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB ?
1205 support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB : UINT_MAX);
1206 ref_l1 = support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
1209 #if CONFIG_AV1_D3D12VA_ENCODER
1210 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1211 ref_l0 = support.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
1220 ref_l0 = ref_l1 = 0;
1223 if (ref_l0 > 0 && ref_l1 > 0 &&
ctx->bi_not_empty) {
1226 "replacing them with B-frames.\n");
1241 if (
ctx->intra_refresh.Mode == D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE)
1245 #if CONFIG_D3D12_INTRA_REFRESH
1247 D3D12_VIDEO_ENCODER_LEVEL_SETTING
level = { 0 };
1248 D3D12_VIDEO_ENCODER_LEVELS_H264 h264_level = { 0 };
1249 D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC hevc_level = { 0 };
1250 #if CONFIG_AV1_D3D12VA_ENCODER
1251 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS av1_level = { 0 };
1254 switch (
ctx->codec->d3d12_codec) {
1255 case D3D12_VIDEO_ENCODER_CODEC_H264:
1256 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_LEVELS_H264);
1257 level.pH264LevelSetting = &h264_level;
1259 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1260 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC);
1261 level.pHEVCLevelSetting = &hevc_level;
1263 #if CONFIG_AV1_D3D12VA_ENCODER
1264 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1265 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
1266 level.pAV1LevelSetting = &av1_level;
1273 D3D12_FEATURE_DATA_VIDEO_ENCODER_INTRA_REFRESH_MODE intra_refresh_support = {
1275 .Codec =
ctx->codec->d3d12_codec,
1276 .Profile =
ctx->profile->d3d12_profile,
1278 .IntraRefreshMode =
ctx->intra_refresh.Mode,
1281 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3,
1282 D3D12_FEATURE_VIDEO_ENCODER_INTRA_REFRESH_MODE,
1283 &intra_refresh_support,
sizeof(intra_refresh_support));
1285 if (FAILED(hr) || !intra_refresh_support.IsSupported) {
1286 av_log(avctx,
AV_LOG_ERROR,
"Requested intra refresh mode not supported by driver.\n");
1292 "Support will be validated during encoder initialization.\n");
1296 if (
ctx->intra_refresh.IntraRefreshDuration == 0) {
1297 ctx->intra_refresh.IntraRefreshDuration = base_ctx->
gop_size;
1299 ctx->intra_refresh.IntraRefreshDuration);
1303 ctx->intra_refresh_frame_index = 0;
1306 ctx->intra_refresh.Mode,
ctx->intra_refresh.IntraRefreshDuration);
1318 D3D12_VIDEO_ENCODER_DESC
desc = {
1320 .Flags = D3D12_VIDEO_ENCODER_FLAG_NONE,
1321 .EncodeCodec =
ctx->codec->d3d12_codec,
1322 .EncodeProfile =
ctx->profile->d3d12_profile,
1323 .InputFormat = frames_hwctx->
format,
1324 .CodecConfiguration =
ctx->codec_conf,
1325 .MaxMotionEstimationPrecision = D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE_MAXIMUM,
1328 hr = ID3D12VideoDevice3_CreateVideoEncoder(
ctx->video_device3, &
desc, &IID_ID3D12VideoEncoder,
1329 (
void **)&
ctx->encoder);
1343 D3D12_VIDEO_ENCODER_HEAP_DESC
desc = {
1345 .Flags = D3D12_VIDEO_ENCODER_HEAP_FLAG_NONE,
1346 .EncodeCodec =
ctx->codec->d3d12_codec,
1347 .EncodeProfile =
ctx->profile->d3d12_profile,
1348 .EncodeLevel =
ctx->level,
1349 .ResolutionsListCount = 1,
1350 .pResolutionList = &
ctx->resolution,
1353 hr = ID3D12VideoDevice3_CreateVideoEncoderHeap(
ctx->video_device3, &
desc,
1354 &IID_ID3D12VideoEncoderHeap, (
void **)&
ctx->encoder_heap);
1365 ID3D12Resource *pResource;
1367 pResource = (ID3D12Resource *)
data;
1376 ID3D12Resource *pResource =
NULL;
1379 D3D12_HEAP_PROPERTIES heap_props;
1380 D3D12_HEAP_TYPE heap_type = D3D12_HEAP_TYPE_READBACK;
1382 D3D12_RESOURCE_DESC
desc = {
1383 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1386 D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT),
1388 .DepthOrArraySize = 1,
1390 .Format = DXGI_FORMAT_UNKNOWN,
1391 .SampleDesc = { .Count = 1, .Quality = 0 },
1392 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1393 .Flags = D3D12_RESOURCE_FLAG_NONE,
1396 ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(
ctx->hwctx->device, &heap_props, 0, heap_type);
1398 hr = ID3D12Device_CreateCommittedResource(
ctx->hwctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
1399 &
desc, D3D12_RESOURCE_STATE_COMMON,
NULL, &IID_ID3D12Resource,
1400 (
void **)&pResource);
1426 ctx->req.NodeIndex = 0;
1427 ctx->req.Codec =
ctx->codec->d3d12_codec;
1428 ctx->req.Profile =
ctx->profile->d3d12_profile;
1429 ctx->req.InputFormat = frames_ctx->
format;
1430 ctx->req.PictureTargetResolution =
ctx->resolution;
1432 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3,
1433 D3D12_FEATURE_VIDEO_ENCODER_RESOURCE_REQUIREMENTS,
1434 &
ctx->req,
sizeof(
ctx->req));
1436 av_log(avctx,
AV_LOG_ERROR,
"Failed to check encoder resource requirements support.\n");
1440 if (!
ctx->req.IsSupported) {
1447 if (!
ctx->output_buffer_pool)
1456 ID3D12CommandAllocator *command_allocator =
NULL;
1460 D3D12_COMMAND_QUEUE_DESC queue_desc = {
1461 .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
1463 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
1469 if (!
ctx->allocator_queue)
1472 hr = ID3D12Device_CreateFence(
ctx->hwctx->device, 0, D3D12_FENCE_FLAG_NONE,
1473 &IID_ID3D12Fence, (
void **)&
ctx->sync_ctx.fence);
1480 ctx->sync_ctx.event = CreateEvent(
NULL, FALSE, FALSE,
NULL);
1481 if (!
ctx->sync_ctx.event)
1488 hr = ID3D12Device_CreateCommandQueue(
ctx->hwctx->device, &queue_desc,
1489 &IID_ID3D12CommandQueue, (
void **)&
ctx->command_queue);
1496 hr = ID3D12Device_CreateCommandList(
ctx->hwctx->device, 0, queue_desc.Type,
1497 command_allocator,
NULL, &IID_ID3D12CommandList,
1498 (
void **)&
ctx->command_list);
1505 hr = ID3D12VideoEncodeCommandList2_Close(
ctx->command_list);
1512 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
1553 hwctx->
resource_flags = D3D12_RESOURCE_FLAG_VIDEO_ENCODE_REFERENCE_ONLY |
1554 D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
1555 if (
ctx->is_texture_array) {
1563 "frame context: %d.\n", err);
1591 D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT support = { 0 };
1592 D3D12_FEATURE_DATA_FORMAT_INFO format_info = { 0 };
1607 hr = ID3D12Device_QueryInterface(
ctx->hwctx->device, &IID_ID3D12Device3, (
void **)&
ctx->device3);
1614 hr = ID3D12Device3_QueryInterface(
ctx->device3, &IID_ID3D12VideoDevice3, (
void **)&
ctx->video_device3);
1621 if (FAILED(ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
1622 &support,
sizeof(support))) && !support.VideoEncodeSupport) {
1629 if (FAILED(ID3D12VideoDevice_CheckFeatureSupport(
ctx->hwctx->device, D3D12_FEATURE_FORMAT_INFO,
1630 &format_info,
sizeof(format_info)))) {
1635 ctx->plane_count = format_info.PlaneCount;
1641 if (
ctx->codec->set_tile) {
1642 err =
ctx->codec->set_tile(avctx);
1651 if (
ctx->codec->get_encoder_caps) {
1652 err =
ctx->codec->get_encoder_caps(avctx);
1667 "but this codec does not support controlling slices.\n");
1678 if (
ctx->codec->configure) {
1679 err =
ctx->codec->configure(avctx);
1684 if (
ctx->codec->init_sequence_params) {
1685 err =
ctx->codec->init_sequence_params(avctx);
1688 "failed: %d.\n", err);
1693 if (
ctx->codec->set_level) {
1694 err =
ctx->codec->set_level(avctx);
1728 int num_allocator = 0;
1734 if (!base_ctx->
frame)
1737 for (pic = base_ctx->
pic_start; pic; pic = next) {
1749 if (
ctx->allocator_queue) {
1755 av_log(avctx,
AV_LOG_VERBOSE,
"Total number of command allocators reused: %d\n", num_allocator);
1761 if (
ctx->sync_ctx.event)
1762 CloseHandle(
ctx->sync_ctx.event);