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);
151 int block_width, block_height;
152 int block_size, qp_range;
156 block_size =
ctx->qp_map_region_size;
159 switch (
ctx->codec->d3d12_codec) {
160 case D3D12_VIDEO_ENCODER_CODEC_H264:
161 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
165 #if CONFIG_AV1_D3D12VA_ENCODER
166 case D3D12_VIDEO_ENCODER_CODEC_AV1:
177 block_width = (avctx->
width + block_size - 1) / block_size;
178 block_height = (avctx->
height + block_size - 1) / block_size;
193 nb_roi =
size / roi_size;
196 for (
i = nb_roi - 1;
i >= 0;
i--) {
197 int startx, endx, starty, endy;
204 starty =
FFMIN(block_height, roi->
top / block_size);
205 endy =
FFMIN(block_height, (roi->
bottom + block_size - 1) / block_size);
206 startx =
FFMIN(block_width, roi->
left / block_size);
207 endx =
FFMIN(block_width, (roi->
right + block_size - 1) / block_size);
223 int16_t *qp_map_int16 = (int16_t *)pic->
qp_map;
225 for (y = starty; y < endy; y++)
226 for (x = startx; x < endx; x++)
227 qp_map_int16[x + y * block_width] = delta_qp;
229 int8_t *qp_map_int8 = (int8_t *)pic->
qp_map;
231 for (y = starty; y < endy; y++)
232 for (x = startx; x < endx; x++)
233 qp_map_int8[x + y * block_width] = delta_qp;
246 int width =
sizeof(D3D12_VIDEO_ENCODER_OUTPUT_METADATA) +
sizeof(D3D12_VIDEO_ENCODER_FRAME_SUBREGION_METADATA);
247 #if CONFIG_AV1_D3D12VA_ENCODER
248 if (
ctx->codec->d3d12_codec == D3D12_VIDEO_ENCODER_CODEC_AV1) {
249 width +=
sizeof(D3D12_VIDEO_ENCODER_AV1_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_TILES)
250 +
sizeof(D3D12_VIDEO_ENCODER_AV1_POST_ENCODE_VALUES);
253 D3D12_HEAP_PROPERTIES encoded_meta_props = { .Type = D3D12_HEAP_TYPE_DEFAULT }, resolved_meta_props;
254 D3D12_HEAP_TYPE resolved_heap_type = D3D12_HEAP_TYPE_READBACK;
257 D3D12_RESOURCE_DESC meta_desc = {
258 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
260 .Width =
ctx->req.MaxEncoderOutputMetadataBufferSize,
262 .DepthOrArraySize = 1,
264 .Format = DXGI_FORMAT_UNKNOWN,
265 .SampleDesc = { .Count = 1, .Quality = 0 },
266 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
267 .Flags = D3D12_RESOURCE_FLAG_NONE,
270 hr = ID3D12Device_CreateCommittedResource(
ctx->hwctx->device, &encoded_meta_props, D3D12_HEAP_FLAG_NONE,
271 &meta_desc, D3D12_RESOURCE_STATE_COMMON,
NULL,
278 ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(
ctx->hwctx->device, &resolved_meta_props, 0, resolved_heap_type);
280 meta_desc.Width =
width;
282 hr = ID3D12Device_CreateCommittedResource(
ctx->hwctx->device, &resolved_meta_props, D3D12_HEAP_FLAG_NONE,
283 &meta_desc, D3D12_RESOURCE_STATE_COMMON,
NULL,
306 ID3D12CommandAllocator *command_allocator =
NULL;
307 ID3D12VideoEncodeCommandList2 *cmd_list =
ctx->command_list;
308 D3D12_RESOURCE_BARRIER barriers[32] = { 0 };
309 D3D12_VIDEO_ENCODE_REFERENCE_FRAMES d3d12_refs = { 0 };
310 int barriers_ref_index = 0;
311 D3D12_RESOURCE_BARRIER *barriers_ref =
NULL;
313 D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAGS seq_flags = D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_NONE;
316 if (
ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
317 seq_flags |= D3D12_VIDEO_ENCODER_SEQUENCE_CONTROL_FLAG_REQUEST_INTRA_REFRESH;
320 D3D12_VIDEO_ENCODER_ENCODEFRAME_INPUT_ARGUMENTS input_args = {
321 .SequenceControlDesc = {
323 .IntraRefreshConfig =
ctx->intra_refresh,
324 .RateControl =
ctx->rc,
325 .PictureTargetResolution =
ctx->resolution,
326 .SelectedLayoutMode = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
327 .FrameSubregionsLayoutData =
ctx->subregions_layout,
328 .CodecGopSequence =
ctx->gop,
331 .InputFrameSubresource = 0,
334 D3D12_VIDEO_ENCODER_ENCODEFRAME_OUTPUT_ARGUMENTS output_args = { 0 };
336 D3D12_VIDEO_ENCODER_RESOLVE_METADATA_INPUT_ARGUMENTS input_metadata = {
337 .EncoderCodec =
ctx->codec->d3d12_codec,
338 .EncoderProfile =
ctx->profile->d3d12_profile,
339 .EncoderInputFormat = frames_hwctx->
format,
340 .EncodedPictureEffectiveResolution =
ctx->resolution,
343 D3D12_VIDEO_ENCODER_RESOLVE_METADATA_OUTPUT_ARGUMENTS output_metadata = { 0 };
410 input_args.SequenceControlDesc.RateControl.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_DELTA_QP;
411 av_log(avctx,
AV_LOG_DEBUG,
"ROI delta QP map created with %d blocks (region size: %d pixels).\n",
415 if (
ctx->codec->init_picture_params) {
416 err =
ctx->codec->init_picture_params(avctx, base_pic);
419 "parameters: %d.\n", err);
425 if (
ctx->codec->write_sequence_header) {
426 bit_len = 8 *
sizeof(
data);
427 err =
ctx->codec->write_sequence_header(avctx,
data, &bit_len);
430 "header: %d.\n", err);
449 d3d12_refs.NumTexture2Ds = base_pic->
nb_refs[0] + base_pic->
nb_refs[1];
450 if (d3d12_refs.NumTexture2Ds) {
451 d3d12_refs.ppTexture2Ds =
av_calloc(d3d12_refs.NumTexture2Ds,
452 sizeof(*d3d12_refs.ppTexture2Ds));
453 if (!d3d12_refs.ppTexture2Ds) {
458 if (
ctx->is_texture_array) {
459 d3d12_refs.pSubresources =
av_calloc(d3d12_refs.NumTexture2Ds,
460 sizeof(*d3d12_refs.pSubresources));
461 if (!d3d12_refs.pSubresources) {
468 for (j = 0; j < base_pic->
nb_refs[0]; j++) {
470 if (
ctx->is_texture_array)
474 for (j = 0; j < base_pic->
nb_refs[1]; j++) {
476 if (
ctx->is_texture_array)
482 input_args.PictureControlDesc.IntraRefreshFrameIndex =
ctx->intra_refresh_frame_index;
484 input_args.PictureControlDesc.Flags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_FLAG_USED_AS_REFERENCE_PICTURE;
486 input_args.PictureControlDesc.PictureControlCodecData = pic->
pic_ctl;
487 input_args.PictureControlDesc.ReferenceFrames = d3d12_refs;
493 output_args.ReconstructedPicture.ReconstructedPictureSubresource =
ctx->is_texture_array ? pic->
subresource_index : 0;
495 output_args.EncoderOutputMetadata.Offset = 0;
498 input_metadata.HWLayoutMetadata.Offset = 0;
501 output_metadata.ResolvedLayoutMetadata.Offset = 0;
507 hr = ID3D12CommandAllocator_Reset(command_allocator);
513 hr = ID3D12VideoEncodeCommandList2_Reset(cmd_list, command_allocator);
519 #define TRANSITION_BARRIER(res, subres, before, after) \
520 (D3D12_RESOURCE_BARRIER) { \
521 .Type = D3D12_RESOURCE_BARRIER_TYPE_TRANSITION, \
522 .Flags = D3D12_RESOURCE_BARRIER_FLAG_NONE, \
525 .Subresource = subres, \
526 .StateBefore = before, \
527 .StateAfter = after, \
532 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
533 D3D12_RESOURCE_STATE_COMMON,
534 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
536 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
537 D3D12_RESOURCE_STATE_COMMON,
538 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
540 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
541 D3D12_RESOURCE_STATE_COMMON,
542 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
544 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
545 D3D12_RESOURCE_STATE_COMMON,
546 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
548 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
550 if (
ctx->is_texture_array)
552 sizeof(D3D12_RESOURCE_BARRIER));
556 if (
ctx->is_texture_array) {
557 D3D12_RESOURCE_DESC references_tex_array_desc = { 0 };
560 for (uint32_t reference_subresource = 0; reference_subresource < references_tex_array_desc.DepthOrArraySize;
561 reference_subresource++) {
563 uint32_t array_size = references_tex_array_desc.DepthOrArraySize;
564 uint32_t mip_slice = reference_subresource % references_tex_array_desc.MipLevels;
565 uint32_t array_slice = (reference_subresource / references_tex_array_desc.MipLevels) % array_size;
567 for (uint32_t plane_slice = 0; plane_slice <
ctx->plane_count; plane_slice++) {
568 uint32_t outputSubresource = mip_slice + array_slice * references_tex_array_desc.MipLevels +
569 plane_slice * references_tex_array_desc.MipLevels * array_size;
572 D3D12_RESOURCE_STATE_COMMON,
573 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
576 D3D12_RESOURCE_STATE_COMMON,
577 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
583 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
584 D3D12_RESOURCE_STATE_COMMON,
585 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE);
587 if (d3d12_refs.NumTexture2Ds) {
588 for (
i = 0;
i < d3d12_refs.NumTexture2Ds;
i++)
590 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
591 D3D12_RESOURCE_STATE_COMMON,
592 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
595 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index, barriers_ref);
597 ID3D12VideoEncodeCommandList2_EncodeFrame(cmd_list,
ctx->encoder,
ctx->encoder_heap,
598 &input_args, &output_args);
601 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
602 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
603 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ);
605 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 1, &barriers[3]);
607 ID3D12VideoEncodeCommandList2_ResolveEncoderOutputMetadata(cmd_list, &input_metadata, &output_metadata);
609 if (barriers_ref_index > 0) {
610 for (
i = 0;
i < barriers_ref_index;
i++)
611 FFSWAP(D3D12_RESOURCE_STATES, barriers_ref[
i].Transition.StateBefore, barriers_ref[
i].Transition.StateAfter);
613 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, barriers_ref_index,
618 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
619 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
620 D3D12_RESOURCE_STATE_COMMON);
622 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
623 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
624 D3D12_RESOURCE_STATE_COMMON);
626 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
627 D3D12_RESOURCE_STATE_VIDEO_ENCODE_READ,
628 D3D12_RESOURCE_STATE_COMMON);
630 D3D12_RESOURCE_BARRIER_ALL_SUBRESOURCES,
631 D3D12_RESOURCE_STATE_VIDEO_ENCODE_WRITE,
632 D3D12_RESOURCE_STATE_COMMON);
634 ID3D12VideoEncodeCommandList2_ResourceBarrier(cmd_list, 4, barriers);
636 hr = ID3D12VideoEncodeCommandList2_Close(cmd_list);
649 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
658 hr = ID3D12CommandQueue_Signal(
ctx->command_queue,
ctx->sync_ctx.fence, ++
ctx->sync_ctx.fence_value);
671 if (
ctx->intra_refresh.Mode != D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE) {
672 ctx->intra_refresh_frame_index =
673 (
ctx->intra_refresh_frame_index + 1) %
ctx->intra_refresh.IntraRefreshDuration;
676 if (d3d12_refs.ppTexture2Ds)
679 if (
ctx->is_texture_array && d3d12_refs.pSubresources)
680 av_freep(&d3d12_refs.pSubresources);
688 if (command_allocator)
691 if (d3d12_refs.ppTexture2Ds)
694 if (
ctx->is_texture_array && d3d12_refs.pSubresources)
695 av_freep(&d3d12_refs.pSubresources);
700 if (
ctx->codec->free_picture_params)
701 ctx->codec->free_picture_params(pic);
719 "%"PRId64
"/%"PRId64
".\n",
736 switch (
ctx->rc.Mode)
738 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP:
739 av_freep(&
ctx->rc.ConfigParams.pConfiguration_CQP);
741 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR:
742 av_freep(&
ctx->rc.ConfigParams.pConfiguration_CBR);
744 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR:
745 av_freep(&
ctx->rc.ConfigParams.pConfiguration_VBR);
747 case D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR:
748 av_freep(&
ctx->rc.ConfigParams.pConfiguration_QVBR);
763 if (
ctx->codec->picture_priv_data_size > 0) {
782 if (
ctx->codec->free_picture_params)
783 ctx->codec->free_picture_params(priv);
794 D3D12_VIDEO_ENCODER_OUTPUT_METADATA *meta =
NULL;
805 meta = (D3D12_VIDEO_ENCODER_OUTPUT_METADATA *)
data;
807 if (meta->EncodeErrorFlags != D3D12_VIDEO_ENCODER_ENCODE_ERROR_FLAG_NO_ERROR) {
813 if (meta->EncodedBitstreamWrittenBytesCount == 0) {
819 *
size = meta->EncodedBitstreamWrittenBytesCount;
830 uint8_t *ptr, *mapped_data;
831 size_t total_size = 0;
858 memcpy(ptr, mapped_data, total_size);
881 if (
ctx->codec->get_coded_data)
882 err =
ctx->codec->get_coded_data(avctx, pic,
pkt);
913 depth =
desc->comp[0].depth;
914 for (
i = 1;
i <
desc->nb_components;
i++) {
915 if (
desc->comp[
i].depth != depth) {
925 for (
i = 0; (
ctx->codec->profiles[
i].av_profile !=
931 if (
desc->nb_components > 1 &&
955 {
RC_MODE_CQP,
"CQP", 0, 0, 1, 0, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP },
956 {
RC_MODE_CBR,
"CBR", 1, 0, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CBR },
957 {
RC_MODE_VBR,
"VBR", 1, 1, 0, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_VBR },
958 {
RC_MODE_QVBR,
"QVBR", 1, 1, 1, 1, D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_QVBR },
965 D3D12_FEATURE_DATA_VIDEO_ENCODER_RATE_CONTROL_MODE d3d12_rc_mode = {
966 .Codec =
ctx->codec->d3d12_codec,
972 d3d12_rc_mode.IsSupported = 0;
973 d3d12_rc_mode.RateControlMode =
rc_mode->d3d12_mode;
975 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3,
976 D3D12_FEATURE_VIDEO_ENCODER_RATE_CONTROL_MODE,
977 &d3d12_rc_mode,
sizeof(d3d12_rc_mode));
983 return d3d12_rc_mode.IsSupported;
993 int64_t hrd_initial_buffer_fullness;
997 #define SET_QP_RANGE(ctl) do { \
998 if (avctx->qmin > 0 || avctx->qmax > 0) { \
999 ctl->MinQP = avctx->qmin; \
1000 ctl->MaxQP = avctx->qmax; \
1001 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_QP_RANGE; \
1005 #define SET_MAX_FRAME_SIZE(ctl) do { \
1006 if (ctx->max_frame_size > 0) { \
1007 ctl->MaxFrameBitSize = ctx->max_frame_size * 8; \
1008 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_MAX_FRAME_SIZE; \
1024 #define TRY_RC_MODE(mode, fail) do { \
1025 rc_mode = &d3d12va_encode_rc_modes[mode]; \
1026 if (!(rc_mode->d3d12_mode && check_rate_control_support(avctx, rc_mode))) { \
1028 av_log(avctx, AV_LOG_ERROR, "Driver does not support %s " \
1029 "RC mode.\n", rc_mode->name); \
1030 return AVERROR(EINVAL); \
1032 av_log(avctx, AV_LOG_DEBUG, "Driver does not support %s " \
1033 "RC mode.\n", rc_mode->name); \
1036 goto rc_mode_found; \
1040 if (
ctx->explicit_rc_mode)
1043 if (
ctx->explicit_qp)
1070 "RC mode compatible with selected options.\n");
1085 "bitrate (%"PRId64
") must not be greater than "
1086 "maxrate (%"PRId64
").\n", avctx->
bit_rate,
1090 rc_target_bitrate = avctx->
bit_rate;
1097 rc_target_bitrate = avctx->
bit_rate;
1098 rc_peak_bitrate = 2 * avctx->
bit_rate;
1103 "in %s RC mode.\n",
rc_mode->name);
1105 rc_target_bitrate = avctx->
bit_rate;
1106 rc_peak_bitrate = 0;
1109 rc_target_bitrate = 0;
1110 rc_peak_bitrate = 0;
1114 if (
ctx->explicit_qp) {
1115 rc_quality =
ctx->explicit_qp;
1122 rc_quality =
ctx->codec->default_quality;
1124 "using default (%d).\n", rc_quality);
1140 "must have initial buffer size (%d) <= "
1141 "buffer size (%"PRId64
").\n",
1147 hrd_initial_buffer_fullness = hrd_buffer_size * 3 / 4;
1152 "in %s RC mode.\n",
rc_mode->name);
1155 hrd_buffer_size = 0;
1156 hrd_initial_buffer_fullness = 0;
1159 if (rc_target_bitrate > UINT32_MAX ||
1160 hrd_buffer_size > UINT32_MAX ||
1161 hrd_initial_buffer_fullness > UINT32_MAX) {
1163 "greater are not supported by D3D12.\n");
1167 ctx->rc_quality = rc_quality;
1176 "initial fullness %"PRId64
" bits.\n",
1177 hrd_buffer_size, hrd_initial_buffer_fullness);
1188 fr_num, fr_den, (
double)fr_num / fr_den);
1190 ctx->rc.Flags = D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_NONE;
1191 ctx->rc.TargetFrameRate.Numerator = fr_num;
1192 ctx->rc.TargetFrameRate.Denominator = fr_den;
1200 D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR *cbr_ctl;
1202 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CBR);
1207 cbr_ctl->TargetBitRate = rc_target_bitrate;
1208 cbr_ctl->VBVCapacity = hrd_buffer_size;
1209 cbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1210 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1215 ctx->rc.ConfigParams.pConfiguration_CBR = cbr_ctl;
1219 D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR *vbr_ctl;
1221 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_VBR);
1226 vbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1227 vbr_ctl->PeakBitRate = rc_peak_bitrate;
1228 vbr_ctl->VBVCapacity = hrd_buffer_size;
1229 vbr_ctl->InitialVBVFullness = hrd_initial_buffer_fullness;
1230 ctx->rc.Flags |= D3D12_VIDEO_ENCODER_RATE_CONTROL_FLAG_ENABLE_VBV_SIZES;
1235 ctx->rc.ConfigParams.pConfiguration_VBR = vbr_ctl;
1239 D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR *qvbr_ctl;
1241 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_QVBR);
1246 qvbr_ctl->TargetAvgBitRate = rc_target_bitrate;
1247 qvbr_ctl->PeakBitRate = rc_peak_bitrate;
1248 qvbr_ctl->ConstantQualityTarget = rc_quality;
1253 ctx->rc.ConfigParams.pConfiguration_QVBR = qvbr_ctl;
1269 if (
ctx->me_precision == D3D12_VIDEO_ENCODER_MOTION_ESTIMATION_PRECISION_MODE_MAXIMUM)
1272 D3D12_VIDEO_ENCODER_PROFILE_DESC
profile = { 0 };
1273 D3D12_VIDEO_ENCODER_PROFILE_H264 h264_profile = D3D12_VIDEO_ENCODER_PROFILE_H264_MAIN;
1274 D3D12_VIDEO_ENCODER_PROFILE_HEVC hevc_profile = D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN;
1275 #if CONFIG_AV1_D3D12VA_ENCODER
1276 D3D12_VIDEO_ENCODER_AV1_PROFILE av1_profile = D3D12_VIDEO_ENCODER_AV1_PROFILE_MAIN;
1279 D3D12_VIDEO_ENCODER_LEVEL_SETTING
level = { 0 };
1280 D3D12_VIDEO_ENCODER_LEVELS_H264 h264_level = { 0 };
1281 D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC hevc_level = { 0 };
1282 #if CONFIG_AV1_D3D12VA_ENCODER
1283 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS av1_level = { 0 };
1286 switch (
ctx->codec->d3d12_codec) {
1287 case D3D12_VIDEO_ENCODER_CODEC_H264:
1288 profile.DataSize =
sizeof(D3D12_VIDEO_ENCODER_PROFILE_H264);
1289 profile.pH264Profile = &h264_profile;
1290 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_LEVELS_H264);
1291 level.pH264LevelSetting = &h264_level;
1293 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1294 profile.DataSize =
sizeof(D3D12_VIDEO_ENCODER_PROFILE_HEVC);
1295 profile.pHEVCProfile = &hevc_profile;
1296 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC);
1297 level.pHEVCLevelSetting = &hevc_level;
1299 #if CONFIG_AV1_D3D12VA_ENCODER
1300 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1301 profile.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_PROFILE);
1302 profile.pAV1Profile = &av1_profile;
1303 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
1304 level.pAV1LevelSetting = &av1_level;
1311 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT support = {
1313 .Codec =
ctx->codec->d3d12_codec,
1314 .InputFormat = hwctx->
format,
1315 .RateControl =
ctx->rc,
1316 .IntraRefresh = D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE,
1317 .SubregionFrameEncoding = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
1318 .ResolutionsListCount = 1,
1319 .pResolutionList = &
ctx->resolution,
1320 .CodecGopSequence =
ctx->gop,
1322 .CodecConfiguration =
ctx->codec_conf,
1324 .SuggestedLevel =
level,
1325 .pResolutionDependentSupport = &
ctx->res_limits,
1328 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_SUPPORT,
1329 &support,
sizeof(support));
1331 av_log(avctx,
AV_LOG_ERROR,
"Failed to check encoder support for motion estimation.\n");
1335 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_MOTION_ESTIMATION_PRECISION_MODE_LIMIT_AVAILABLE)) {
1337 "precision mode limits.\n");
1342 "precision mode limits.\n");
1351 uint32_t ref_l0, ref_l1;
1354 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT support;
1356 D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_H264 h264;
1357 D3D12_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT_HEVC hevc;
1358 #if CONFIG_AV1_D3D12VA_ENCODER
1359 D3D12_VIDEO_ENCODER_CODEC_AV1_PICTURE_CONTROL_SUPPORT av1;
1363 support.NodeIndex = 0;
1364 support.Codec =
ctx->codec->d3d12_codec;
1365 support.Profile =
ctx->profile->d3d12_profile;
1367 switch (
ctx->codec->d3d12_codec) {
1368 case D3D12_VIDEO_ENCODER_CODEC_H264:
1369 support.PictureSupport.DataSize =
sizeof(codec_support.h264);
1370 support.PictureSupport.pH264Support = &codec_support.h264;
1373 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1374 support.PictureSupport.DataSize =
sizeof(codec_support.hevc);
1375 support.PictureSupport.pHEVCSupport = &codec_support.hevc;
1378 #if CONFIG_AV1_D3D12VA_ENCODER
1379 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1380 memset(&codec_support.av1, 0,
sizeof(codec_support.av1));
1381 support.PictureSupport.DataSize =
sizeof(codec_support.av1);
1382 support.PictureSupport.pAV1Support = &codec_support.av1;
1389 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_PICTURE_CONTROL_SUPPORT,
1390 &support,
sizeof(support));
1394 if (support.IsSupported) {
1395 switch (
ctx->codec->d3d12_codec) {
1396 case D3D12_VIDEO_ENCODER_CODEC_H264:
1397 ref_l0 =
FFMIN(support.PictureSupport.pH264Support->MaxL0ReferencesForP,
1398 support.PictureSupport.pH264Support->MaxL1ReferencesForB ?
1399 support.PictureSupport.pH264Support->MaxL1ReferencesForB : UINT_MAX);
1400 ref_l1 = support.PictureSupport.pH264Support->MaxL1ReferencesForB;
1403 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1404 ref_l0 =
FFMIN(support.PictureSupport.pHEVCSupport->MaxL0ReferencesForP,
1405 support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB ?
1406 support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB : UINT_MAX);
1407 ref_l1 = support.PictureSupport.pHEVCSupport->MaxL1ReferencesForB;
1410 #if CONFIG_AV1_D3D12VA_ENCODER
1411 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1412 ref_l0 = support.PictureSupport.pAV1Support->MaxUniqueReferencesPerFrame;
1421 ref_l0 = ref_l1 = 0;
1424 if (ref_l0 > 0 && ref_l1 > 0 &&
ctx->bi_not_empty) {
1427 "replacing them with B-frames.\n");
1442 if (
ctx->intra_refresh.Mode == D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE)
1446 #if CONFIG_D3D12_INTRA_REFRESH
1448 D3D12_VIDEO_ENCODER_LEVEL_SETTING
level = { 0 };
1449 D3D12_VIDEO_ENCODER_LEVELS_H264 h264_level = { 0 };
1450 D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC hevc_level = { 0 };
1451 #if CONFIG_AV1_D3D12VA_ENCODER
1452 D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS av1_level = { 0 };
1455 switch (
ctx->codec->d3d12_codec) {
1456 case D3D12_VIDEO_ENCODER_CODEC_H264:
1457 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_LEVELS_H264);
1458 level.pH264LevelSetting = &h264_level;
1460 case D3D12_VIDEO_ENCODER_CODEC_HEVC:
1461 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC);
1462 level.pHEVCLevelSetting = &hevc_level;
1464 #if CONFIG_AV1_D3D12VA_ENCODER
1465 case D3D12_VIDEO_ENCODER_CODEC_AV1:
1466 level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_AV1_LEVEL_TIER_CONSTRAINTS);
1467 level.pAV1LevelSetting = &av1_level;
1474 D3D12_FEATURE_DATA_VIDEO_ENCODER_INTRA_REFRESH_MODE intra_refresh_support = {
1476 .Codec =
ctx->codec->d3d12_codec,
1477 .Profile =
ctx->profile->d3d12_profile,
1479 .IntraRefreshMode =
ctx->intra_refresh.Mode,
1482 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3,
1483 D3D12_FEATURE_VIDEO_ENCODER_INTRA_REFRESH_MODE,
1484 &intra_refresh_support,
sizeof(intra_refresh_support));
1486 if (FAILED(hr) || !intra_refresh_support.IsSupported) {
1487 av_log(avctx,
AV_LOG_ERROR,
"Requested intra refresh mode not supported by driver.\n");
1493 "Support will be validated during encoder initialization.\n");
1497 if (
ctx->intra_refresh.IntraRefreshDuration == 0) {
1498 ctx->intra_refresh.IntraRefreshDuration = base_ctx->
gop_size;
1500 ctx->intra_refresh.IntraRefreshDuration);
1504 ctx->intra_refresh_frame_index = 0;
1507 ctx->intra_refresh.Mode,
ctx->intra_refresh.IntraRefreshDuration);
1519 D3D12_VIDEO_ENCODER_DESC
desc = {
1521 .Flags = D3D12_VIDEO_ENCODER_FLAG_NONE,
1522 .EncodeCodec =
ctx->codec->d3d12_codec,
1523 .EncodeProfile =
ctx->profile->d3d12_profile,
1524 .InputFormat = frames_hwctx->
format,
1525 .CodecConfiguration =
ctx->codec_conf,
1526 .MaxMotionEstimationPrecision =
ctx->me_precision,
1529 hr = ID3D12VideoDevice3_CreateVideoEncoder(
ctx->video_device3, &
desc, &IID_ID3D12VideoEncoder,
1530 (
void **)&
ctx->encoder);
1544 D3D12_VIDEO_ENCODER_HEAP_DESC
desc = {
1546 .Flags = D3D12_VIDEO_ENCODER_HEAP_FLAG_NONE,
1547 .EncodeCodec =
ctx->codec->d3d12_codec,
1548 .EncodeProfile =
ctx->profile->d3d12_profile,
1549 .EncodeLevel =
ctx->level,
1550 .ResolutionsListCount = 1,
1551 .pResolutionList = &
ctx->resolution,
1554 hr = ID3D12VideoDevice3_CreateVideoEncoderHeap(
ctx->video_device3, &
desc,
1555 &IID_ID3D12VideoEncoderHeap, (
void **)&
ctx->encoder_heap);
1566 ID3D12Resource *pResource;
1568 pResource = (ID3D12Resource *)
data;
1577 ID3D12Resource *pResource =
NULL;
1580 D3D12_HEAP_PROPERTIES heap_props;
1581 D3D12_HEAP_TYPE heap_type = D3D12_HEAP_TYPE_READBACK;
1583 D3D12_RESOURCE_DESC
desc = {
1584 .Dimension = D3D12_RESOURCE_DIMENSION_BUFFER,
1587 D3D12_TEXTURE_DATA_PLACEMENT_ALIGNMENT),
1589 .DepthOrArraySize = 1,
1591 .Format = DXGI_FORMAT_UNKNOWN,
1592 .SampleDesc = { .Count = 1, .Quality = 0 },
1593 .Layout = D3D12_TEXTURE_LAYOUT_ROW_MAJOR,
1594 .Flags = D3D12_RESOURCE_FLAG_NONE,
1597 ctx->hwctx->device->lpVtbl->GetCustomHeapProperties(
ctx->hwctx->device, &heap_props, 0, heap_type);
1599 hr = ID3D12Device_CreateCommittedResource(
ctx->hwctx->device, &heap_props, D3D12_HEAP_FLAG_NONE,
1600 &
desc, D3D12_RESOURCE_STATE_COMMON,
NULL, &IID_ID3D12Resource,
1601 (
void **)&pResource);
1627 ctx->req.NodeIndex = 0;
1628 ctx->req.Codec =
ctx->codec->d3d12_codec;
1629 ctx->req.Profile =
ctx->profile->d3d12_profile;
1630 ctx->req.InputFormat = frames_ctx->
format;
1631 ctx->req.PictureTargetResolution =
ctx->resolution;
1633 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3,
1634 D3D12_FEATURE_VIDEO_ENCODER_RESOURCE_REQUIREMENTS,
1635 &
ctx->req,
sizeof(
ctx->req));
1637 av_log(avctx,
AV_LOG_ERROR,
"Failed to check encoder resource requirements support.\n");
1641 if (!
ctx->req.IsSupported) {
1648 if (!
ctx->output_buffer_pool)
1657 ID3D12CommandAllocator *command_allocator =
NULL;
1661 D3D12_COMMAND_QUEUE_DESC queue_desc = {
1662 .Type = D3D12_COMMAND_LIST_TYPE_VIDEO_ENCODE,
1664 .Flags = D3D12_COMMAND_QUEUE_FLAG_NONE,
1670 if (!
ctx->allocator_queue)
1673 hr = ID3D12Device_CreateFence(
ctx->hwctx->device, 0, D3D12_FENCE_FLAG_NONE,
1674 &IID_ID3D12Fence, (
void **)&
ctx->sync_ctx.fence);
1681 ctx->sync_ctx.event = CreateEvent(
NULL, FALSE, FALSE,
NULL);
1682 if (!
ctx->sync_ctx.event)
1689 hr = ID3D12Device_CreateCommandQueue(
ctx->hwctx->device, &queue_desc,
1690 &IID_ID3D12CommandQueue, (
void **)&
ctx->command_queue);
1697 hr = ID3D12Device_CreateCommandList(
ctx->hwctx->device, 0, queue_desc.Type,
1698 command_allocator,
NULL, &IID_ID3D12CommandList,
1699 (
void **)&
ctx->command_list);
1706 hr = ID3D12VideoEncodeCommandList2_Close(
ctx->command_list);
1713 ID3D12CommandQueue_ExecuteCommandLists(
ctx->command_queue, 1, (ID3D12CommandList **)&
ctx->command_list);
1754 hwctx->
resource_flags = D3D12_RESOURCE_FLAG_VIDEO_ENCODE_REFERENCE_ONLY |
1755 D3D12_RESOURCE_FLAG_DENY_SHADER_RESOURCE;
1756 if (
ctx->is_texture_array) {
1764 "frame context: %d.\n", err);
1792 D3D12_FEATURE_DATA_VIDEO_FEATURE_AREA_SUPPORT support = { 0 };
1793 D3D12_FEATURE_DATA_FORMAT_INFO format_info = { 0 };
1808 hr = ID3D12Device_QueryInterface(
ctx->hwctx->device, &IID_ID3D12Device3, (
void **)&
ctx->device3);
1815 hr = ID3D12Device3_QueryInterface(
ctx->device3, &IID_ID3D12VideoDevice3, (
void **)&
ctx->video_device3);
1822 if (FAILED(ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_FEATURE_AREA_SUPPORT,
1823 &support,
sizeof(support))) && !support.VideoEncodeSupport) {
1830 if (FAILED(ID3D12VideoDevice_CheckFeatureSupport(
ctx->hwctx->device, D3D12_FEATURE_FORMAT_INFO,
1831 &format_info,
sizeof(format_info)))) {
1836 ctx->plane_count = format_info.PlaneCount;
1842 if (
ctx->codec->set_tile) {
1843 err =
ctx->codec->set_tile(avctx);
1852 if (
ctx->codec->get_encoder_caps) {
1853 err =
ctx->codec->get_encoder_caps(avctx);
1868 "but this codec does not support controlling slices.\n");
1879 if (
ctx->codec->configure) {
1880 err =
ctx->codec->configure(avctx);
1889 if (
ctx->codec->init_sequence_params) {
1890 err =
ctx->codec->init_sequence_params(avctx);
1893 "failed: %d.\n", err);
1898 if (
ctx->codec->set_level) {
1899 err =
ctx->codec->set_level(avctx);
1933 int num_allocator = 0;
1939 if (!base_ctx->
frame)
1942 for (pic = base_ctx->
pic_start; pic; pic = next) {
1954 if (
ctx->allocator_queue) {
1960 av_log(avctx,
AV_LOG_VERBOSE,
"Total number of command allocators reused: %d\n", num_allocator);
1966 if (
ctx->sync_ctx.event)
1967 CloseHandle(
ctx->sync_ctx.event);