1 /*
2 * Direct3D 12 HW acceleration video encoder
3 *
4 * Copyright (c) 2024 Intel Corporation
5 *
6 * This file is part of FFmpeg.
7 *
8 * FFmpeg is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
12 *
13 * FFmpeg is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
17 *
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with FFmpeg; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
21 */
27
35
40
43
44 // User options.
49
50 // Writer structures.
54
58
63
65 {
66 {
67 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
68 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
69 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
70 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
71 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
72 3,
73 3,
74 },
75 {
76 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
77 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
78 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
79 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
80 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
81 0,
82 0,
83 },
84 {
85 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
86 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
87 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32,
88 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
89 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
90 2,
91 2,
92 },
93 {
94 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
95 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
96 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64,
97 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
98 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
99 2,
100 2,
101 },
102 {
103 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_NONE,
104 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8,
105 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64,
106 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4,
107 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32,
108 4,
109 4,
110 },
111 };
112
114 { 30, D3D12_VIDEO_ENCODER_LEVELS_HEVC_1 },
115 { 60, D3D12_VIDEO_ENCODER_LEVELS_HEVC_2 },
116 { 63, D3D12_VIDEO_ENCODER_LEVELS_HEVC_21 },
117 { 90, D3D12_VIDEO_ENCODER_LEVELS_HEVC_3 },
118 { 93, D3D12_VIDEO_ENCODER_LEVELS_HEVC_31 },
119 { 120, D3D12_VIDEO_ENCODER_LEVELS_HEVC_4 },
120 { 123, D3D12_VIDEO_ENCODER_LEVELS_HEVC_41 },
121 { 150, D3D12_VIDEO_ENCODER_LEVELS_HEVC_5 },
122 { 153, D3D12_VIDEO_ENCODER_LEVELS_HEVC_51 },
123 { 156, D3D12_VIDEO_ENCODER_LEVELS_HEVC_52 },
124 { 180, D3D12_VIDEO_ENCODER_LEVELS_HEVC_6 },
125 { 183, D3D12_VIDEO_ENCODER_LEVELS_HEVC_61 },
126 { 186, D3D12_VIDEO_ENCODER_LEVELS_HEVC_62 },
127 };
128
129 static const D3D12_VIDEO_ENCODER_PROFILE_HEVC
profile_main = D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN;
130 static const D3D12_VIDEO_ENCODER_PROFILE_HEVC
profile_main10 = D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN10;
131
132 #define D3D_PROFILE_DESC(name) \
133 { sizeof(D3D12_VIDEO_ENCODER_PROFILE_HEVC), { .pHEVCProfile = (D3D12_VIDEO_ENCODER_PROFILE_HEVC *)&profile_ ## name } }
138 };
139
141 {
142 switch (cusize) {
143 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_8x8: return 8;
144 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_16x16: return 16;
145 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_32x32: return 32;
146 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_CUSIZE_64x64: return 64;
148 }
149 return 0;
150 }
151
153 {
154 switch (tusize) {
155 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_4x4: return 4;
156 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_8x8: return 8;
157 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_16x16: return 16;
158 case D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_TUSIZE_32x32: return 32;
160 }
161 return 0;
162 }
163
165 char *
data,
size_t *data_len,
167 {
169 int err;
170
172 if (err < 0) {
174 return err;
175 }
176
179 "%zu < %zu.\n", *data_len,
182 }
183
186
187 return 0;
188 }
189
192 void *nal_unit)
193 {
195 int err;
196
199 if (err < 0) {
201 "type = %d.\n",
header->nal_unit_type);
202 return err;
203 }
204
205 return 0;
206 }
207
209 char *
data,
size_t *data_len)
210 {
213 int err;
214
216 if (err < 0)
218
220 if (err < 0)
222
224 if (err < 0)
226
230 return err;
231
232 }
233
235 {
245 D3D12_VIDEO_ENCODER_PROFILE_HEVC
profile = D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN;
246 D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC
level = { 0 };
248 uint8_t min_cu_size, max_cu_size, min_tu_size, max_tu_size;
250 HRESULT hr;
252
253 D3D12_FEATURE_DATA_VIDEO_ENCODER_SUPPORT support = {
254 .NodeIndex = 0,
255 .Codec = D3D12_VIDEO_ENCODER_CODEC_HEVC,
256 .InputFormat = hwctx->
format,
257 .RateControl =
ctx->rc,
258 .IntraRefresh = D3D12_VIDEO_ENCODER_INTRA_REFRESH_MODE_NONE,
259 .SubregionFrameEncoding = D3D12_VIDEO_ENCODER_FRAME_SUBREGION_LAYOUT_MODE_FULL_FRAME,
260 .ResolutionsListCount = 1,
261 .pResolutionList = &
ctx->resolution,
262 .CodecGopSequence =
ctx->gop,
264 .CodecConfiguration =
ctx->codec_conf,
265 .SuggestedProfile.DataSize = sizeof(D3D12_VIDEO_ENCODER_PROFILE_HEVC),
266 .SuggestedProfile.pHEVCProfile = &
profile,
267 .SuggestedLevel.DataSize = sizeof(D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC),
268 .SuggestedLevel.pHEVCLevelSetting = &
level,
269 .pResolutionDependentSupport = &
ctx->res_limits,
270 };
271
272 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_SUPPORT,
273 &support, sizeof(support));
274
275 if (FAILED(hr)) {
278 }
279
280 if (!(support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_GENERAL_SUPPORT_OK)) {
282 support.ValidationFlags);
284 }
285
286 if (support.SupportFlags & D3D12_VIDEO_ENCODER_SUPPORT_FLAG_RECONSTRUCTED_FRAMES_REQUIRE_TEXTURE_ARRAYS) {
287 av_log(avctx,
AV_LOG_ERROR,
"D3D12 video encode on this device requires texture array support, "
288 "but it's not implemented.\n");
290 }
291
292 memset(
vps, 0,
sizeof(*
vps));
293 memset(
sps, 0,
sizeof(*
sps));
294 memset(
pps, 0,
sizeof(*
pps));
295
298 if (
desc->nb_components == 1) {
299 chroma_format = 0;
300 } else {
301 if (
desc->log2_chroma_w == 1 &&
desc->log2_chroma_h == 1) {
302 chroma_format = 1;
303 }
else if (
desc->log2_chroma_w == 1 &&
desc->log2_chroma_h == 0) {
304 chroma_format = 2;
305 }
else if (
desc->log2_chroma_w == 0 &&
desc->log2_chroma_h == 0) {
306 chroma_format = 3;
307 } else {
309 "%s is not supported.\n",
desc->name);
311 }
312 }
314
319
320 // VPS
321
324 .nuh_layer_id = 0,
325 .nuh_temporal_id_plus1 = 1,
326 };
327
328 vps->vps_video_parameter_set_id = 0;
329
330 vps->vps_base_layer_internal_flag = 1;
331 vps->vps_base_layer_available_flag = 1;
332 vps->vps_max_layers_minus1 = 0;
333 vps->vps_max_sub_layers_minus1 = 0;
334 vps->vps_temporal_id_nesting_flag = 1;
335
339
341
346
351
355
358
360
363 } else {
365
368 1, 1, 1, (base_ctx->
b_per_p > 0) + 1);
372 } else {
374 "any normal level; using level 8.5.\n");
376 // The tier flag must be set in level 8.5.
378 }
380 }
381
382 vps->vps_sub_layer_ordering_info_present_flag = 0;
383 vps->vps_max_dec_pic_buffering_minus1[0] = base_ctx->
max_b_depth + 1;
385 vps->vps_max_latency_increase_plus1[0] = 0;
386
387 vps->vps_max_layer_id = 0;
388 vps->vps_num_layer_sets_minus1 = 0;
389 vps->layer_id_included_flag[0][0] = 1;
390
391 vps->vps_timing_info_present_flag = 1;
395 vps->vps_poc_proportional_to_timing_flag = 1;
396 vps->vps_num_ticks_poc_diff_one_minus1 = 0;
397 } else {
400 vps->vps_poc_proportional_to_timing_flag = 0;
401 }
402 vps->vps_num_hrd_parameters = 0;
403
404 // SPS
405
408 .nuh_layer_id = 0,
409 .nuh_temporal_id_plus1 = 1,
410 };
411
412 sps->sps_video_parameter_set_id =
vps->vps_video_parameter_set_id;
413
414 sps->sps_max_sub_layers_minus1 =
vps->vps_max_sub_layers_minus1;
415 sps->sps_temporal_id_nesting_flag =
vps->vps_temporal_id_nesting_flag;
416
417 sps->profile_tier_level =
vps->profile_tier_level;
418
419 sps->sps_seq_parameter_set_id = 0;
420
421 sps->chroma_format_idc = chroma_format;
422 sps->separate_colour_plane_flag = 0;
423
424 av_assert0(
ctx->res_limits.SubregionBlockPixelsSize % min_cu_size == 0);
425
427 ctx->res_limits.SubregionBlockPixelsSize);
429 ctx->res_limits.SubregionBlockPixelsSize);
430
431 if (avctx->
width !=
sps->pic_width_in_luma_samples ||
432 avctx->
height !=
sps->pic_height_in_luma_samples) {
433 sps->conformance_window_flag = 1;
434 sps->conf_win_left_offset = 0;
435 sps->conf_win_right_offset =
436 (
sps->pic_width_in_luma_samples - avctx->
width) >>
desc->log2_chroma_w;
437 sps->conf_win_top_offset = 0;
438 sps->conf_win_bottom_offset =
439 (
sps->pic_height_in_luma_samples - avctx->
height) >>
desc->log2_chroma_h;
440 } else {
441 sps->conformance_window_flag = 0;
442 }
443
446
447 sps->log2_max_pic_order_cnt_lsb_minus4 =
ctx->gop.pHEVCGroupOfPictures->log2_max_pic_order_cnt_lsb_minus4;
448
449 sps->sps_sub_layer_ordering_info_present_flag =
450 vps->vps_sub_layer_ordering_info_present_flag;
451 for (
i = 0;
i <=
sps->sps_max_sub_layers_minus1;
i++) {
452 sps->sps_max_dec_pic_buffering_minus1[
i] =
453 vps->vps_max_dec_pic_buffering_minus1[
i];
454 sps->sps_max_num_reorder_pics[
i] =
455 vps->vps_max_num_reorder_pics[
i];
456 sps->sps_max_latency_increase_plus1[
i] =
457 vps->vps_max_latency_increase_plus1[
i];
458 }
459
460 sps->log2_min_luma_coding_block_size_minus3 = (uint8_t)(
av_log2(min_cu_size) - 3);
461 sps->log2_diff_max_min_luma_coding_block_size = (uint8_t)(
av_log2(max_cu_size) -
av_log2(min_cu_size));
462 sps->log2_min_luma_transform_block_size_minus2 = (uint8_t)(
av_log2(min_tu_size) - 2);
463 sps->log2_diff_max_min_luma_transform_block_size = (uint8_t)(
av_log2(max_tu_size) -
av_log2(min_tu_size));
464
465 sps->max_transform_hierarchy_depth_inter =
ctx->codec_conf.pHEVCConfig->max_transform_hierarchy_depth_inter;
466 sps->max_transform_hierarchy_depth_intra =
ctx->codec_conf.pHEVCConfig->max_transform_hierarchy_depth_intra;
467
468 sps->amp_enabled_flag = !!(
ctx->codec_conf.pHEVCConfig->ConfigurationFlags &
469 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION);
470 sps->sample_adaptive_offset_enabled_flag = !!(
ctx->codec_conf.pHEVCConfig->ConfigurationFlags &
471 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_SAO_FILTER);
472 sps->sps_temporal_mvp_enabled_flag = 0;
473 sps->pcm_enabled_flag = 0;
474
475 sps->vui_parameters_present_flag = 1;
476
486 break;
487 }
488 }
493 }
495 }
496
497 // Unspecified video format, from table E-2.
511
517 }
518
525
533
534 // PPS
535
538 .nuh_layer_id = 0,
539 .nuh_temporal_id_plus1 = 1,
540 };
541
542 pps->pps_pic_parameter_set_id = 0;
543 pps->pps_seq_parameter_set_id =
sps->sps_seq_parameter_set_id;
544
545 pps->cabac_init_present_flag = 1;
546
547 pps->num_ref_idx_l0_default_active_minus1 = 0;
548 pps->num_ref_idx_l1_default_active_minus1 = 0;
549
550 pps->init_qp_minus26 = 0;
551
552 pps->transform_skip_enabled_flag = !!(
ctx->codec_conf.pHEVCConfig->ConfigurationFlags &
553 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_TRANSFORM_SKIPPING);
554
555 // cu_qp_delta always required to be 1 in https://github.com/microsoft/DirectX-Specs/blob/master/d3d/D3D12VideoEncoding.md
556 pps->cu_qp_delta_enabled_flag = 1;
557
558 pps->diff_cu_qp_delta_depth = 0;
559
560 pps->pps_slice_chroma_qp_offsets_present_flag = 1;
561
562 pps->tiles_enabled_flag = 0;
// no tiling in D3D12
563
564 pps->pps_loop_filter_across_slices_enabled_flag = !(
ctx->codec_conf.pHEVCConfig->ConfigurationFlags &
565 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_DISABLE_LOOP_FILTER_ACROSS_SLICES);
566 pps->deblocking_filter_control_present_flag = 1;
567
568 return 0;
569 }
570
572 {
574 HRESULT hr;
575 uint8_t min_cu_size, max_cu_size;
578 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC *
config;
579 D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC hevc_caps;
580
581 D3D12_FEATURE_DATA_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT codec_caps = {
582 .NodeIndex = 0,
583 .Codec = D3D12_VIDEO_ENCODER_CODEC_HEVC,
584 .Profile =
ctx->profile->d3d12_profile,
585 .CodecSupportLimits.DataSize = sizeof(D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC),
586 };
587
590 codec_caps.CodecSupportLimits.pHEVCSupport = &hevc_caps;
591 hr = ID3D12VideoDevice3_CheckFeatureSupport(
ctx->video_device3, D3D12_FEATURE_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT,
592 &codec_caps, sizeof(codec_caps));
593 if (SUCCEEDED(hr) && codec_caps.IsSupported)
594 break;
595 }
596
600 }
601
602 ctx->codec_conf.DataSize =
sizeof(D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC);
604 if (!
ctx->codec_conf.pHEVCConfig)
606
608
609 config->ConfigurationFlags = D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_NONE;
610 config->MinLumaCodingUnitSize = hevc_caps.MinLumaCodingUnitSize;
611 config->MaxLumaCodingUnitSize = hevc_caps.MaxLumaCodingUnitSize;
612 config->MinLumaTransformUnitSize = hevc_caps.MinLumaTransformUnitSize;
613 config->MaxLumaTransformUnitSize = hevc_caps.MaxLumaTransformUnitSize;
614 config->max_transform_hierarchy_depth_inter = hevc_caps.max_transform_hierarchy_depth_inter;
615 config->max_transform_hierarchy_depth_intra = hevc_caps.max_transform_hierarchy_depth_intra;
616
617 if (hevc_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_SUPPORT ||
618 hevc_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_ASYMETRIC_MOTION_PARTITION_REQUIRED)
619 config->ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_USE_ASYMETRIC_MOTION_PARTITION;
620
621 if (hevc_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_SAO_FILTER_SUPPORT)
622 config->ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_SAO_FILTER;
623
624 if (hevc_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_DISABLING_LOOP_FILTER_ACROSS_SLICES_SUPPORT)
625 config->ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_DISABLE_LOOP_FILTER_ACROSS_SLICES;
626
627 if (hevc_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_TRANSFORM_SKIP_SUPPORT)
628 config->ConfigurationFlags |= D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC_FLAG_ENABLE_TRANSFORM_SKIPPING;
629
630 if (hevc_caps.SupportFlags & D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_HEVC_FLAG_P_FRAMES_IMPLEMENTED_AS_LOW_DELAY_B_FRAMES)
631 ctx->bi_not_empty = 1;
632
633 // block sizes
636
638 "min CB size %dx%d.\n", max_cu_size, max_cu_size,
639 min_cu_size, min_cu_size);
640
643
644 return 0;
645 }
646
648 {
652 int fixed_qp_idr, fixed_qp_p, fixed_qp_b;
653 int err;
654
656 if (err < 0)
657 return err;
658
659 // Rate control
660 if (
ctx->rc.Mode == D3D12_VIDEO_ENCODER_RATE_CONTROL_MODE_CQP) {
661 D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP *cqp_ctl;
666 else
667 fixed_qp_idr = fixed_qp_p;
671 else
672 fixed_qp_b = fixed_qp_p;
673
675 "%d / %d / %d for IDR- / P- / B-frames.\n",
676 fixed_qp_idr, fixed_qp_p, fixed_qp_b);
677
678 ctx->rc.ConfigParams.DataSize =
sizeof(D3D12_VIDEO_ENCODER_RATE_CONTROL_CQP);
680 if (!cqp_ctl)
682
683 cqp_ctl->ConstantQP_FullIntracodedFrame = fixed_qp_idr;
684 cqp_ctl->ConstantQP_InterPredictedFrame_PrevRefOnly = fixed_qp_p;
685 cqp_ctl->ConstantQP_InterPredictedFrame_BiDirectionalRef = fixed_qp_b;
686
687 ctx->rc.ConfigParams.pConfiguration_CQP = cqp_ctl;
688 }
689
690 // GOP
691 ctx->gop.DataSize =
sizeof(D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_HEVC);
693 if (!
ctx->gop.pHEVCGroupOfPictures)
695
696 ctx->gop.pHEVCGroupOfPictures->GOPLength = base_ctx->
gop_size;
697 ctx->gop.pHEVCGroupOfPictures->PPicturePeriod = base_ctx->
b_per_p + 1;
698 // Power of 2
700 ctx->gop.pHEVCGroupOfPictures->log2_max_pic_order_cnt_lsb_minus4 =
702 else
703 ctx->gop.pHEVCGroupOfPictures->log2_max_pic_order_cnt_lsb_minus4 =
705
706 return 0;
707 }
708
710 {
714
715 ctx->level.DataSize =
sizeof(D3D12_VIDEO_ENCODER_LEVEL_TIER_CONSTRAINTS_HEVC);
717 if (!
ctx->level.pHEVCLevelSetting)
719
723 break;
724 }
725 }
726
730 }
731
733 D3D12_VIDEO_ENCODER_TIER_HEVC_MAIN :
734 D3D12_VIDEO_ENCODER_TIER_HEVC_HIGH;
735
736 return 0;
737 }
738
740 {
741 if (!pic->
pic_ctl.pHEVCPicData)
742 return;
743
746 av_freep(&pic->
pic_ctl.pHEVCPicData->pReferenceFramesReconPictureDescriptors);
748 }
749
752 {
757 D3D12_VIDEO_ENCODER_REFERENCE_PICTURE_DESCRIPTOR_HEVC *pd =
NULL;
758 UINT *ref_list0 =
NULL, *ref_list1 =
NULL;
760
761 pic->
pic_ctl.DataSize =
sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC);
763 if (!pic->
pic_ctl.pHEVCPicData)
765
769 } else {
772 }
774
775 switch(base_pic->
type) {
777 pic->
pic_ctl.pHEVCPicData->FrameType = D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_IDR_FRAME;
778 break;
780 pic->
pic_ctl.pHEVCPicData->FrameType = D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_I_FRAME;
781 break;
783 pic->
pic_ctl.pHEVCPicData->FrameType = D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_P_FRAME;
784 break;
786 pic->
pic_ctl.pHEVCPicData->FrameType = D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME;
787 break;
788 default:
790 }
791
792 pic->
pic_ctl.pHEVCPicData->slice_pic_parameter_set_id = 0;
794
797 if (!pd)
799
801 if (!ref_list0)
803
804 pic->
pic_ctl.pHEVCPicData->List0ReferenceFramesCount = base_pic->
nb_refs[0];
808
810 href =
ref->codec_priv;
811
813 pd[idx].ReconstructedPictureResourceIndex = idx;
814 pd[idx].IsRefUsedByCurrentPic = TRUE;
816 idx++;
817 }
818 }
819
822 if (!ref_list1)
824
825 pic->
pic_ctl.pHEVCPicData->List1ReferenceFramesCount = base_pic->
nb_refs[1];
829
831 href =
ref->codec_priv;
832
834 pd[idx].ReconstructedPictureResourceIndex = idx;
835 pd[idx].IsRefUsedByCurrentPic = TRUE;
837 idx++;
838 }
839 }
840
841 pic->
pic_ctl.pHEVCPicData->pList0ReferenceFrames = ref_list0;
842 pic->
pic_ctl.pHEVCPicData->pList1ReferenceFrames = ref_list1;
843 pic->
pic_ctl.pHEVCPicData->ReferenceFramesReconPictureDescriptorsCount = idx;
844 pic->
pic_ctl.pHEVCPicData->pReferenceFramesReconPictureDescriptors = pd;
845
846 return 0;
847 }
848
851
852 .d3d12_codec = D3D12_VIDEO_ENCODER_CODEC_HEVC,
853
857
858 .default_quality = 25,
859
861
863
865
867
869
871
873
875 };
876
878 {
881
883
888
891 "in 8-bit unsigned integer.\n", avctx->
level);
893 }
894
896 ctx->explicit_qp = priv->
qp;
897
899 }
900
902 {
904
907
911
913 }
914
915 #define OFFSET(x) offsetof(D3D12VAEncodeHEVCContext, x)
916 #define FLAGS (AV_OPT_FLAG_VIDEO_PARAM | AV_OPT_FLAG_ENCODING_PARAM)
920
921 { "qp", "Constant QP (for P-frames; scaled by qfactor/qoffset for I/B)",
923
924 { "profile", "Set profile (general_profile_idc)",
927
928 #define PROFILE(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
929 { .i64 = value }, 0, 0, FLAGS, "profile"
932 #undef PROFILE
933
934 { "tier", "Set tier (general_tier_flag)",
936 { .i64 = 0 }, 0, 1,
FLAGS,
"tier" },
938 { .i64 = 0 }, 0, 0,
FLAGS,
"tier" },
940 { .i64 = 1 }, 0, 0,
FLAGS,
"tier" },
941
942 { "level", "Set level (general_level_idc)",
945
946 #define LEVEL(name, value) name, NULL, 0, AV_OPT_TYPE_CONST, \
947 { .i64 = value }, 0, 0, FLAGS, "level"
950 {
LEVEL(
"2.1", 63) },
952 {
LEVEL(
"3.1", 93) },
954 {
LEVEL(
"4.1", 123) },
956 {
LEVEL(
"5.1", 153) },
957 {
LEVEL(
"5.2", 156) },
959 {
LEVEL(
"6.1", 183) },
960 {
LEVEL(
"6.2", 186) },
961 #undef LEVEL
962
964 };
965
967 { "b", "0" },
968 { "bf", "2" },
969 { "g", "120" },
970 { "i_qfactor", "1" },
971 { "i_qoffset", "0" },
972 { "b_qfactor", "1" },
973 { "b_qoffset", "0" },
974 { "qmin", "-1" },
975 { "qmax", "-1" },
977 };
978
984 };
985
987 .
p.
name =
"hevc_d3d12va",
1004 },
1006 .p.wrapper_name = "d3d12va",
1007 };