d3d12: Add support for HEVC range extension header parameters

Reviewed-By: Jesse Natalie <jenatali@microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31117>
This commit is contained in:
Sil Vilerino 2024-09-06 12:43:50 -04:00 committed by Marge Bot
parent 92d6989fdc
commit 6f82b1ea18
6 changed files with 224 additions and 16 deletions

View file

@ -285,6 +285,7 @@ struct D3D12EncodeConfiguration
struct pipe_h264_enc_seq_param m_encoderCodecSpecificSequenceStateDescH264;
struct pipe_h265_enc_seq_param m_encoderCodecSpecificSequenceStateDescH265;
struct pipe_h265_enc_vid_param m_encoderCodecSpecificVideoStateDescH265;
struct pipe_h265_enc_pic_param m_encoderCodecSpecificPictureStateDescH265;
};
struct EncodedBitstreamResolvedMetadata

View file

@ -1136,6 +1136,7 @@ d3d12_video_encoder_update_current_encoder_config_state_hevc(struct d3d12_video_
pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags |= d3d12_video_encoder_config_dirty_flag_sequence_header;
}
pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificSequenceStateDescH265 = hevcPic->seq;
pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificPictureStateDescH265 = hevcPic->pic;
// Iterate over the headers the app requested and set flags to emit those for this frame
util_dynarray_foreach(&hevcPic->raw_headers, struct pipe_enc_raw_header, header) {
@ -1458,7 +1459,8 @@ d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12E
}
size_t writtenPPSBytesCount = 0;
HevcPicParameterSet tentative_pps = pHEVCBitstreamBuilder->build_pps(pHEVCBitstreamBuilder->get_active_sps(),
HevcPicParameterSet tentative_pps = pHEVCBitstreamBuilder->build_pps(pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificPictureStateDescH265,
pHEVCBitstreamBuilder->get_active_sps(),
currentPicParams.pHEVCPicData->slice_pic_parameter_set_id,
*codecConfigDesc.pHEVCConfig,
*currentPicParams.pHEVCPicData1,

View file

@ -27,8 +27,25 @@
static uint8_t
convert_profile12_to_stdprofile(D3D12_VIDEO_ENCODER_PROFILE_HEVC profile)
{
// Main is 1, Main10 is 2, one more than the D3D12 enum definition
return static_cast<uint8_t>(profile) + 1u;
switch (profile)
{
case D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN:
{
return 1;
} break;
case D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN10:
{
return 2;
} break;
case D3D12_VIDEO_ENCODER_PROFILE_HEVC_MAIN_444:
{
return 4;
} break;
default:
{
unreachable("Unsupported D3D12_VIDEO_ENCODER_PROFILE_HEVC value");
} break;
}
}
void
@ -51,6 +68,14 @@ d3d12_video_bitstream_builder_hevc::init_profile_tier_level(HEVCProfileTierLevel
ptl->general_non_packed_constraint_flag = 1; // no frame packing arrangement SEI messages
ptl->general_frame_only_constraint_flag = 1;
ptl->general_level_idc = HEVCLevelIdc;
if (ptl->general_profile_idc == 4 /*MAIN444*/)
{
ptl->general_intra_constraint_flag = 1;
ptl->general_max_12bit_constraint_flag = 1;
ptl->general_max_10bit_constraint_flag = 1;
ptl->general_max_8bit_constraint_flag = 1;
}
}
void
@ -474,7 +499,20 @@ d3d12_video_bitstream_builder_hevc::build_sps(const HevcVideoParameterSet& paren
m_latest_sps.vui.motion_vectors_over_pic_boundaries_flag = seqData.vui_flags.motion_vectors_over_pic_boundaries_flag;
m_latest_sps.vui.restricted_ref_pic_lists_flag = seqData.vui_flags.restricted_ref_pic_lists_flag;
m_latest_sps.sps_extension_flag = 0;
m_latest_sps.sps_extension_present_flag = seqData.sps_range_extension.sps_range_extension_flag; // Set sps_extension_present_flag if sps_range_extension_flag present
if (m_latest_sps.sps_extension_present_flag)
{
m_latest_sps.sps_range_extension.sps_range_extension_flag = seqData.sps_range_extension.sps_range_extension_flag;
m_latest_sps.sps_range_extension.transform_skip_rotation_enabled_flag = seqData.sps_range_extension.transform_skip_rotation_enabled_flag;
m_latest_sps.sps_range_extension.transform_skip_context_enabled_flag = seqData.sps_range_extension.transform_skip_context_enabled_flag;
m_latest_sps.sps_range_extension.implicit_rdpcm_enabled_flag = seqData.sps_range_extension.implicit_rdpcm_enabled_flag;
m_latest_sps.sps_range_extension.explicit_rdpcm_enabled_flag = seqData.sps_range_extension.explicit_rdpcm_enabled_flag;
m_latest_sps.sps_range_extension.extended_precision_processing_flag = seqData.sps_range_extension.extended_precision_processing_flag;
m_latest_sps.sps_range_extension.intra_smoothing_disabled_flag = seqData.sps_range_extension.intra_smoothing_disabled_flag;
m_latest_sps.sps_range_extension.high_precision_offsets_enabled_flag = seqData.sps_range_extension.high_precision_offsets_enabled_flag;
m_latest_sps.sps_range_extension.persistent_rice_adaptation_enabled_flag = seqData.sps_range_extension.persistent_rice_adaptation_enabled_flag;
m_latest_sps.sps_range_extension.cabac_bypass_alignment_enabled_flag = seqData.sps_range_extension.cabac_bypass_alignment_enabled_flag;
}
// Print built SPS structure
debug_printf("[HEVCBitstreamBuilder] HevcSeqParameterSet Structure generated before writing to bitstream:\n");
@ -486,7 +524,8 @@ d3d12_video_bitstream_builder_hevc::build_sps(const HevcVideoParameterSet& paren
}
HevcPicParameterSet
d3d12_video_bitstream_builder_hevc::build_pps(const HevcSeqParameterSet& parentSPS,
d3d12_video_bitstream_builder_hevc::build_pps(const struct pipe_h265_enc_pic_param & picData,
const HevcSeqParameterSet& parentSPS,
uint8_t pic_parameter_set_id,
const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC& codecConfig,
const D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC1& pictureControl,
@ -528,6 +567,24 @@ d3d12_video_bitstream_builder_hevc::build_pps(const HevcSeqParameterSet& parentS
m_latest_pps.pps_slice_chroma_qp_offsets_present_flag = 1;
m_latest_pps.cu_qp_delta_enabled_flag = 1;
m_latest_pps.pps_extension_present_flag = picData.pps_range_extension.pps_range_extension_flag; // Set pps_extension_present_flag if pps_range_extension_flag present
if (m_latest_pps.pps_extension_present_flag)
{
m_latest_pps.pps_range_extension.pps_range_extension_flag = picData.pps_range_extension.pps_range_extension_flag;
m_latest_pps.pps_range_extension.log2_max_transform_skip_block_size_minus2 = picData.pps_range_extension.log2_max_transform_skip_block_size_minus2;
m_latest_pps.pps_range_extension.cross_component_prediction_enabled_flag = picData.pps_range_extension.cross_component_prediction_enabled_flag;
m_latest_pps.pps_range_extension.chroma_qp_offset_list_enabled_flag = picData.pps_range_extension.chroma_qp_offset_list_enabled_flag;
m_latest_pps.pps_range_extension.diff_cu_chroma_qp_offset_depth = picData.pps_range_extension.diff_cu_chroma_qp_offset_depth;
m_latest_pps.pps_range_extension.chroma_qp_offset_list_len_minus1 = picData.pps_range_extension.chroma_qp_offset_list_len_minus1;
m_latest_pps.pps_range_extension.log2_sao_offset_scale_luma = picData.pps_range_extension.log2_sao_offset_scale_luma;
m_latest_pps.pps_range_extension.log2_sao_offset_scale_chroma = picData.pps_range_extension.log2_sao_offset_scale_chroma;
for (unsigned i = 0; i < ARRAY_SIZE(picData.pps_range_extension.cb_qp_offset_list); i++)
m_latest_pps.pps_range_extension.cb_qp_offset_list[i] = picData.pps_range_extension.cb_qp_offset_list[i];
for (unsigned i = 0; i < ARRAY_SIZE(picData.pps_range_extension.cr_qp_offset_list); i++)
m_latest_pps.pps_range_extension.cr_qp_offset_list[i] = picData.pps_range_extension.cr_qp_offset_list[i];
}
// Print built PPS structure
debug_printf("[HEVCBitstreamBuilder] HevcPicParameterSet Structure generated before writing to bitstream:\n");
print_pps(m_latest_pps);
@ -710,7 +767,7 @@ d3d12_video_bitstream_builder_hevc::print_sps(const HevcSeqParameterSet& SPS)
debug_printf("max_bits_per_min_cu_denom: %d\n", SPS.vui.max_bits_per_min_cu_denom);
debug_printf("log2_max_mv_length_horizontal: %d\n", SPS.vui.log2_max_mv_length_horizontal);
debug_printf("log2_max_mv_length_vertical: %d\n", SPS.vui.log2_max_mv_length_vertical);
debug_printf("sps_extension_flag: %d\n", SPS.sps_extension_flag);
debug_printf("sps_extension_present_flag: %d\n", SPS.sps_extension_present_flag);
debug_printf("sps_extension_data_flag: %d\n", SPS.sps_extension_data_flag);
debug_printf("HevcSeqParameterSet values end\n--------------------------------------\n");
@ -757,7 +814,7 @@ d3d12_video_bitstream_builder_hevc::print_pps(const HevcPicParameterSet& PPS)
debug_printf("lists_modification_present_flag: %d\n", PPS.lists_modification_present_flag);
debug_printf("log2_parallel_merge_level_minus2: %d\n", PPS.log2_parallel_merge_level_minus2);
debug_printf("slice_segment_header_extension_present_flag: %d\n", PPS.slice_segment_header_extension_present_flag);
debug_printf("pps_extension_flag: %d\n", PPS.pps_extension_flag);
debug_printf("pps_extension_present_flag: %d\n", PPS.pps_extension_present_flag);
debug_printf("pps_extension_data_flag: %d\n", PPS.pps_extension_data_flag);
debug_printf("HevcPicParameterSet values end\n--------------------------------------\n");
}

View file

@ -57,7 +57,8 @@ class d3d12_video_bitstream_builder_hevc : public d3d12_video_bitstream_builder_
std::vector<BYTE>::iterator placingPositionStart,
size_t &writtenBytes);
HevcPicParameterSet build_pps(const HevcSeqParameterSet& parentSPS,
HevcPicParameterSet build_pps(const struct pipe_h265_enc_pic_param & picData,
const HevcSeqParameterSet& parentSPS,
uint8_t pic_parameter_set_id,
const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_HEVC& codecConfig,
const D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_HEVC1& pictureControl,

View file

@ -416,8 +416,32 @@ d3d12_video_nalu_writer_hevc::write_sps_bytes(d3d12_video_encoder_bitstream *pBi
pBitstream->exp_Golomb_ue(pSPS->vui.log2_max_mv_length_vertical);
}
// pSps_extension_flag
pBitstream->put_bits(1, 0);
// Set sps_extension_present_flag if sps_range_extension_flag present
pSPS->sps_extension_present_flag = pSPS->sps_range_extension.sps_range_extension_flag ? 1u : 0u;
pBitstream->put_bits(1, pSPS->sps_extension_present_flag);
if (pSPS->sps_extension_present_flag)
{
pBitstream->put_bits(1, pSPS->sps_range_extension.sps_range_extension_flag);
pBitstream->put_bits(1, 0);// sps_multilayer_extension_flag u(1)
pBitstream->put_bits(1, 0);// sps_3d_extension_flag u(1)
pBitstream->put_bits(1, 0);// sps_scc_extension_flag u(1)
pBitstream->put_bits(4, 0);// sps_extension_4bits u(4)
}
if (pSPS->sps_range_extension.sps_range_extension_flag)
{
// sps_range_extension( )
pBitstream->put_bits(1, pSPS->sps_range_extension.transform_skip_rotation_enabled_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.transform_skip_context_enabled_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.implicit_rdpcm_enabled_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.explicit_rdpcm_enabled_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.extended_precision_processing_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.intra_smoothing_disabled_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.high_precision_offsets_enabled_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.persistent_rice_adaptation_enabled_flag);
pBitstream->put_bits(1, pSPS->sps_range_extension.cabac_bypass_alignment_enabled_flag);
}
rbsp_trailing(pBitstream);
pBitstream->flush();
@ -503,8 +527,37 @@ d3d12_video_nalu_writer_hevc::write_pps_bytes(d3d12_video_encoder_bitstream *pBi
pBitstream->exp_Golomb_ue(pPPS->log2_parallel_merge_level_minus2);
pBitstream->put_bits(1, pPPS->slice_segment_header_extension_present_flag);
//pps_extension_flag
pBitstream->put_bits(1, 0);
// Set pps_extension_present_flag if sps_range_extension_flag present
pPPS->pps_extension_present_flag = pPPS->pps_range_extension.pps_range_extension_flag ? 1u : 0u;
pBitstream->put_bits(1, pPPS->pps_extension_present_flag);
if (pPPS->pps_extension_present_flag)
{
pBitstream->put_bits(1, pPPS->pps_range_extension.pps_range_extension_flag);
pBitstream->put_bits(1, 0);// pps_multilayer_extension_flag u(1)
pBitstream->put_bits(1, 0);// pps_3d_extension_flag u(1)
pBitstream->put_bits(1, 0);// pps_scc_extension_flag u(1)
pBitstream->put_bits(4, 0);// pps_extension_4bits u(4)
}
if (pPPS->pps_range_extension.pps_range_extension_flag)
{
// pps_range_extension( )
if( pPPS->transform_skip_enabled_flag )
pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_max_transform_skip_block_size_minus2);
pBitstream->put_bits(1, pPPS->pps_range_extension.cross_component_prediction_enabled_flag);
pBitstream->put_bits(1, pPPS->pps_range_extension.chroma_qp_offset_list_enabled_flag);
if(pPPS->pps_range_extension.chroma_qp_offset_list_enabled_flag) {
pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.diff_cu_chroma_qp_offset_depth);
pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.chroma_qp_offset_list_len_minus1);
for( unsigned i = 0; i <= pPPS->pps_range_extension.chroma_qp_offset_list_len_minus1; i++ ) {
pBitstream->exp_Golomb_se(pPPS->pps_range_extension.cb_qp_offset_list[i]);
pBitstream->exp_Golomb_se(pPPS->pps_range_extension.cr_qp_offset_list[i]);
}
}
pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_sao_offset_scale_luma);
pBitstream->exp_Golomb_ue(pPPS->pps_range_extension.log2_sao_offset_scale_chroma);
}
rbsp_trailing(pBitstream);
pBitstream->flush();
@ -605,8 +658,67 @@ d3d12_video_nalu_writer_hevc::write_profile_tier_level(d3d12_video_encoder_bitst
rbsp->put_bits(1, ptl->general_interlaced_source_flag);
rbsp->put_bits(1, ptl->general_non_packed_constraint_flag);
rbsp->put_bits(1, ptl->general_frame_only_constraint_flag);
rbsp->put_bits(31, 0); //first 31 bits of general_reserved_zero_44bits
rbsp->put_bits(13, 0); //last 13 bits of general_reserved_zero_44bits
if( (ptl->general_profile_idc == 4) || ptl->general_profile_compatibility_flag[4] ||
(ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[5] ||
(ptl->general_profile_idc == 6) || ptl->general_profile_compatibility_flag[6] ||
(ptl->general_profile_idc == 7) || ptl->general_profile_compatibility_flag[7] ||
(ptl->general_profile_idc == 8) || ptl->general_profile_compatibility_flag[8] ||
(ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[9] ||
(ptl->general_profile_idc == 10) || ptl->general_profile_compatibility_flag[10] ||
(ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[11])
{
rbsp->put_bits(1, ptl->general_max_12bit_constraint_flag);
rbsp->put_bits(1, ptl->general_max_10bit_constraint_flag);
rbsp->put_bits(1, ptl->general_max_8bit_constraint_flag);
rbsp->put_bits(1, ptl->general_max_422chroma_constraint_flag);
rbsp->put_bits(1, ptl->general_max_420chroma_constraint_flag);
rbsp->put_bits(1, ptl->general_max_monochrome_constraint_flag);
rbsp->put_bits(1, ptl->general_intra_constraint_flag);
rbsp->put_bits(1, ptl->general_one_picture_only_constraint_flag);
rbsp->put_bits(1, ptl->general_lower_bit_rate_constraint_flag);
if( (ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[5] ||
(ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[9] ||
(ptl->general_profile_idc == 10) || ptl->general_profile_compatibility_flag[10] ||
(ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[11])
{
rbsp->put_bits(1, ptl->general_max_14bit_constraint_flag);
rbsp->put_bits(33, 0); // general_reserved_zero_33bits u(33)
}
else
{
rbsp->put_bits(32, 0); // general_reserved_zero_34bits u(34)
rbsp->put_bits(2, 0); // general_reserved_zero_34bits u(34)
}
}
else if( (ptl->general_profile_idc == 2) || ptl->general_profile_compatibility_flag[2])
{
rbsp->put_bits(7, 0); // general_reserved_zero_7bits
rbsp->put_bits(1, ptl->general_one_picture_only_constraint_flag);
rbsp->put_bits(32, 0); // general_reserved_zero_35bits u(35)
rbsp->put_bits(3, 0); // general_reserved_zero_35bits u(35)
}
else
{
rbsp->put_bits(32, 0); // general_reserved_zero_43bits u(43)
rbsp->put_bits(11, 0); // general_reserved_zero_43bits u(43)
}
if( (ptl->general_profile_idc == 1) || ptl->general_profile_compatibility_flag[ 1 ] ||
(ptl->general_profile_idc == 2) || ptl->general_profile_compatibility_flag[ 2 ] ||
(ptl->general_profile_idc == 3) || ptl->general_profile_compatibility_flag[ 3 ] ||
(ptl->general_profile_idc == 4) || ptl->general_profile_compatibility_flag[ 4 ] ||
(ptl->general_profile_idc == 5) || ptl->general_profile_compatibility_flag[ 5 ] ||
(ptl->general_profile_idc == 9) || ptl->general_profile_compatibility_flag[ 9 ] ||
(ptl->general_profile_idc == 11) || ptl->general_profile_compatibility_flag[ 11 ] )
{
rbsp->put_bits(1, ptl->general_inbld_flag);
}
else
{
rbsp->put_bits(1, 0); // general_reserved_zero_bit u(1)
}
rbsp->put_bits(8, ptl->general_level_idc);
}

View file

@ -92,6 +92,17 @@ struct HEVCProfileTierLevel {
uint8_t general_interlaced_source_flag;
uint8_t general_non_packed_constraint_flag;
uint8_t general_frame_only_constraint_flag;
uint8_t general_max_12bit_constraint_flag;
uint8_t general_max_10bit_constraint_flag;
uint8_t general_max_8bit_constraint_flag;
uint8_t general_max_422chroma_constraint_flag;
uint8_t general_max_420chroma_constraint_flag;
uint8_t general_max_monochrome_constraint_flag;
uint8_t general_intra_constraint_flag;
uint8_t general_one_picture_only_constraint_flag;
uint8_t general_lower_bit_rate_constraint_flag;
uint8_t general_max_14bit_constraint_flag;
uint8_t general_inbld_flag;
uint8_t general_level_idc;
uint8_t sub_layer_profile_present_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
uint8_t sub_layer_level_present_flag[HEVC_MAX_SUB_LAYERS_NUM - 1];
@ -243,8 +254,20 @@ struct HevcSeqParameterSet {
uint8_t strong_intra_smoothing_enabled_flag;
uint8_t vui_parameters_present_flag;
HEVCVideoUsabilityInfo vui;
uint8_t sps_extension_flag;
uint8_t sps_extension_present_flag;
uint8_t sps_extension_data_flag;
struct {
uint32_t sps_range_extension_flag;
uint32_t transform_skip_rotation_enabled_flag: 1;
uint32_t transform_skip_context_enabled_flag: 1;
uint32_t implicit_rdpcm_enabled_flag: 1;
uint32_t explicit_rdpcm_enabled_flag: 1;
uint32_t extended_precision_processing_flag: 1;
uint32_t intra_smoothing_disabled_flag: 1;
uint32_t high_precision_offsets_enabled_flag: 1;
uint32_t persistent_rice_adaptation_enabled_flag: 1;
uint32_t cabac_bypass_alignment_enabled_flag: 1;
} sps_range_extension;
};
struct HevcPicParameterSet {
@ -286,8 +309,20 @@ struct HevcPicParameterSet {
uint8_t lists_modification_present_flag;
uint8_t log2_parallel_merge_level_minus2;
uint8_t slice_segment_header_extension_present_flag;
uint8_t pps_extension_flag;
uint8_t pps_extension_present_flag;
uint8_t pps_extension_data_flag;
struct {
uint8_t pps_range_extension_flag;
uint32_t log2_max_transform_skip_block_size_minus2;
uint32_t cross_component_prediction_enabled_flag: 1;
uint32_t chroma_qp_offset_list_enabled_flag: 1;
uint32_t diff_cu_chroma_qp_offset_depth;
uint32_t chroma_qp_offset_list_len_minus1;
int32_t cb_qp_offset_list[6];
int32_t cr_qp_offset_list[6];
uint32_t log2_sao_offset_scale_luma;
uint32_t log2_sao_offset_scale_chroma;
} pps_range_extension;
};
struct HevcVideoParameterSet {