From 33336a2766d6b176d2a244a96a068769e8f43dc0 Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Tue, 19 Mar 2024 11:39:33 -0400 Subject: [PATCH] d3d12: Support H264 slice L0/L1 active number override Part-of: --- .../drivers/d3d12/d3d12_video_enc_h264.cpp | 86 +++++++++++++------ ...2_video_encoder_bitstream_builder_h264.cpp | 8 +- ...d12_video_encoder_bitstream_builder_h264.h | 70 +++++++-------- 3 files changed, 95 insertions(+), 69 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp b/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp index dc27cc79c2e..6ff2af58574 100644 --- a/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp +++ b/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp @@ -351,7 +351,13 @@ d3d12_video_encoder_update_current_frame_pic_params_info_h264(struct d3d12_video bUsedAsReference = !h264Pic->not_referenced; - picParams.pH264PicData->pic_parameter_set_id = pH264BitstreamBuilder->get_active_pps_id(); + if (pD3D12Enc->m_currentEncodeCapabilities.m_encoderCodecSpecificConfigCaps.m_H264CodecCaps.SupportFlags & + D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_SUPPORT_H264_FLAG_NUM_REF_IDX_ACTIVE_OVERRIDE_FLAG_SLICE_SUPPORT) + { + picParams.pH264PicData->Flags |= D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_FLAG_REQUEST_NUM_REF_IDX_ACTIVE_OVERRIDE_FLAG_SLICE; + } + + picParams.pH264PicData->pic_parameter_set_id = pH264BitstreamBuilder->get_active_pps().pic_parameter_set_id; picParams.pH264PicData->idr_pic_id = h264Pic->idr_pic_id; picParams.pH264PicData->FrameType = d3d12_video_encoder_convert_frame_type_h264(h264Pic->picture_type); picParams.pH264PicData->PictureOrderCountNumber = h264Pic->pic_order_cnt; @@ -1117,6 +1123,31 @@ d3d12_video_encoder_compare_slice_config_h264_hevc( sizeof(D3D12_VIDEO_ENCODER_PICTURE_CONTROL_SUBREGIONS_LAYOUT_DATA_SLICES)) == 0); } +static inline bool +d3d12_video_encoder_needs_new_pps_h264(struct d3d12_video_encoder *pD3D12Enc, + bool writeNewSPS, + H264_PPS &tentative_pps, + const H264_PPS &active_pps) +{ + bool bUseSliceL0L1Override = (pD3D12Enc->m_currentEncodeConfig.m_encoderPicParamsDesc.m_H264PicData.Flags & + D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264_FLAG_REQUEST_NUM_REF_IDX_ACTIVE_OVERRIDE_FLAG_SLICE); + + bool bDifferentL0L1Lists = !bUseSliceL0L1Override && + ((tentative_pps.num_ref_idx_l0_active_minus1 != active_pps.num_ref_idx_l0_active_minus1) || + (tentative_pps.num_ref_idx_l1_active_minus1 != active_pps.num_ref_idx_l1_active_minus1)); + + bool bDidPPSChange = + ((tentative_pps.constrained_intra_pred_flag != active_pps.constrained_intra_pred_flag) || + (tentative_pps.entropy_coding_mode_flag != active_pps.entropy_coding_mode_flag) || + bDifferentL0L1Lists || + (tentative_pps.pic_order_present_flag != active_pps.pic_order_present_flag) || + (tentative_pps.pic_parameter_set_id != active_pps.pic_parameter_set_id) || + (tentative_pps.seq_parameter_set_id != active_pps.seq_parameter_set_id) || + (tentative_pps.transform_8x8_mode_flag != active_pps.transform_8x8_mode_flag)); + + return writeNewSPS || bDidPPSChange; +} + uint32_t d3d12_video_encoder_build_codec_headers_h264(struct d3d12_video_encoder *pD3D12Enc, std::vector &pWrittenCodecUnitsSizes) @@ -1149,41 +1180,40 @@ d3d12_video_encoder_build_codec_headers_h264(struct d3d12_video_encoder *pD3D12E // Also on input format dirty flag for new SPS, VUI etc || (pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags & d3d12_video_encoder_config_dirty_flag_sequence_info); - uint32_t active_seq_parameter_set_id = pH264BitstreamBuilder->get_active_sps_id(); + uint32_t active_seq_parameter_set_id = pH264BitstreamBuilder->get_active_sps().seq_parameter_set_id; size_t writtenSPSBytesCount = 0; if (writeNewSPS) { - pH264BitstreamBuilder->build_sps(pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificSequenceStateDescH264, - pD3D12Enc->base.profile, - *levelDesc.pH264LevelSetting, - pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo.Format, - *codecConfigDesc.pH264Config, - pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_H264GroupOfPictures, - active_seq_parameter_set_id, - MaxDPBCapacity, // max_num_ref_frames - pD3D12Enc->m_currentEncodeConfig.m_currentResolution, - pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig, - pD3D12Enc->m_BitstreamHeadersBuffer, - pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenAUDBytesCount, - writtenSPSBytesCount); + H264_SPS sps = pH264BitstreamBuilder->build_sps(pD3D12Enc->m_currentEncodeConfig.m_encoderCodecSpecificSequenceStateDescH264, + pD3D12Enc->base.profile, + *levelDesc.pH264LevelSetting, + pD3D12Enc->m_currentEncodeConfig.m_encodeFormatInfo.Format, + *codecConfigDesc.pH264Config, + pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_H264GroupOfPictures, + active_seq_parameter_set_id, + MaxDPBCapacity, // max_num_ref_frames + pD3D12Enc->m_currentEncodeConfig.m_currentResolution, + pD3D12Enc->m_currentEncodeConfig.m_FrameCroppingCodecConfig, + pD3D12Enc->m_BitstreamHeadersBuffer, + pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenAUDBytesCount, + writtenSPSBytesCount); + pH264BitstreamBuilder->set_active_sps(sps); pWrittenCodecUnitsSizes.push_back(writtenSPSBytesCount); } size_t writtenPPSBytesCount = 0; - pH264BitstreamBuilder->build_pps(pD3D12Enc->base.profile, - *codecConfigDesc.pH264Config, - *currentPicParams.pH264PicData, - currentPicParams.pH264PicData->pic_parameter_set_id, - active_seq_parameter_set_id, - pD3D12Enc->m_StagingHeadersBuffer, - pD3D12Enc->m_StagingHeadersBuffer.begin(), - writtenPPSBytesCount); + H264_PPS tentative_pps = pH264BitstreamBuilder->build_pps(pD3D12Enc->base.profile, + *codecConfigDesc.pH264Config, + *currentPicParams.pH264PicData, + currentPicParams.pH264PicData->pic_parameter_set_id, + active_seq_parameter_set_id, + pD3D12Enc->m_StagingHeadersBuffer, + pD3D12Enc->m_StagingHeadersBuffer.begin(), + writtenPPSBytesCount); - std::vector& active_pps = pH264BitstreamBuilder->get_active_pps(); - if (writeNewSPS || - (writtenPPSBytesCount != active_pps.size()) || - memcmp(pD3D12Enc->m_StagingHeadersBuffer.data(), active_pps.data(), writtenPPSBytesCount)) { - active_pps = pD3D12Enc->m_StagingHeadersBuffer; + const H264_PPS &active_pps = pH264BitstreamBuilder->get_active_pps(); + if (d3d12_video_encoder_needs_new_pps_h264(pD3D12Enc, writeNewSPS, tentative_pps, active_pps)) { + pH264BitstreamBuilder->set_active_pps(tentative_pps); pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenAUDBytesCount + writtenSPSBytesCount + writtenPPSBytesCount); memcpy(&pD3D12Enc->m_BitstreamHeadersBuffer.data()[writtenAUDBytesCount + writtenSPSBytesCount], pD3D12Enc->m_StagingHeadersBuffer.data(), writtenPPSBytesCount); pWrittenCodecUnitsSizes.push_back(writtenPPSBytesCount); diff --git a/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.cpp b/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.cpp index 9756e822d43..652461e790d 100644 --- a/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.cpp +++ b/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.cpp @@ -53,7 +53,7 @@ Convert12ToSpecH264Profiles(D3D12_VIDEO_ENCODER_PROFILE_H264 profile12) } } -void +H264_SPS d3d12_video_bitstream_builder_h264::build_sps(const struct pipe_h264_enc_seq_param & seqData, const enum pipe_video_profile & profile, const D3D12_VIDEO_ENCODER_LEVELS_H264 & level, @@ -168,6 +168,8 @@ d3d12_video_bitstream_builder_h264::build_sps(const struct pipe_h264_enc_seq_par // Convert the H264 SPS structure into bytes m_h264Encoder.sps_to_nalu_bytes(&spsStructure, headerBitstream, placingPositionStart, writtenBytes); + + return spsStructure; } void @@ -194,7 +196,7 @@ d3d12_video_bitstream_builder_h264::write_aud(std::vector & hea m_h264Encoder.write_access_unit_delimiter_nalu(headerBitstream, placingPositionStart, writtenBytes); } -void +H264_PPS d3d12_video_bitstream_builder_h264::build_pps(const enum pipe_video_profile & profile, const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 & codecConfig, const D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264 &pictureControl, @@ -236,6 +238,8 @@ d3d12_video_bitstream_builder_h264::build_pps(const enum pipe_video_profile & // Convert the H264 SPS structure into bytes m_h264Encoder.pps_to_nalu_bytes(&ppsStructure, headerBitstream, bIsHighProfile, placingPositionStart, writtenBytes); + + return ppsStructure; } void diff --git a/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.h b/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.h index 2bbd7d239ef..a365639337d 100644 --- a/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.h +++ b/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_h264.h @@ -34,28 +34,28 @@ class d3d12_video_bitstream_builder_h264 : public d3d12_video_bitstream_builder_ d3d12_video_bitstream_builder_h264(bool insert_aud_nalu = false); ~d3d12_video_bitstream_builder_h264() {}; - void build_sps(const struct pipe_h264_enc_seq_param & seqData, - const enum pipe_video_profile & profile, - const D3D12_VIDEO_ENCODER_LEVELS_H264 & level, - const DXGI_FORMAT & inputFmt, - const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 & codecConfig, - const D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_H264 &gopConfig, - uint32_t seq_parameter_set_id, - uint32_t max_num_ref_frames, - D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC sequenceTargetResolution, - D3D12_BOX frame_cropping_codec_config, - std::vector & headerBitstream, - std::vector::iterator placingPositionStart, - size_t & writtenBytes); + H264_SPS build_sps(const struct pipe_h264_enc_seq_param & seqData, + const enum pipe_video_profile & profile, + const D3D12_VIDEO_ENCODER_LEVELS_H264 & level, + const DXGI_FORMAT & inputFmt, + const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 & codecConfig, + const D3D12_VIDEO_ENCODER_SEQUENCE_GOP_STRUCTURE_H264 &gopConfig, + uint32_t seq_parameter_set_id, + uint32_t max_num_ref_frames, + D3D12_VIDEO_ENCODER_PICTURE_RESOLUTION_DESC sequenceTargetResolution, + D3D12_BOX frame_cropping_codec_config, + std::vector & headerBitstream, + std::vector::iterator placingPositionStart, + size_t & writtenBytes); - void build_pps(const enum pipe_video_profile & profile, - const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 & codecConfig, - const D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264 &pictureControl, - uint32_t pic_parameter_set_id, - uint32_t seq_parameter_set_id, - std::vector & headerBitstream, - std::vector::iterator placingPositionStart, - size_t & writtenBytes); + H264_PPS build_pps(const enum pipe_video_profile & profile, + const D3D12_VIDEO_ENCODER_CODEC_CONFIGURATION_H264 & codecConfig, + const D3D12_VIDEO_ENCODER_PICTURE_CONTROL_CODEC_DATA_H264 &pictureControl, + uint32_t pic_parameter_set_id, + uint32_t seq_parameter_set_id, + std::vector & headerBitstream, + std::vector::iterator placingPositionStart, + size_t & writtenBytes); void write_end_of_stream_nalu(std::vector & headerBitstream, std::vector::iterator placingPositionStart, @@ -71,38 +71,30 @@ class d3d12_video_bitstream_builder_h264 : public d3d12_video_bitstream_builder_ void print_pps(const H264_PPS &pps); void print_sps(const H264_SPS &sps); - uint32_t get_active_sps_id() + const H264_SPS& get_active_sps() { - return m_activeSPSIndex; + return m_activeSPSStructure; }; - uint32_t get_active_pps_id() + const H264_PPS& get_active_pps() { - return m_activePPSIndex; + return m_activePPSStructure; }; - std::vector& get_active_pps() + void set_active_sps(H264_SPS &active_sps) { - return m_activePPS; + m_activeSPSStructure = active_sps; }; - - void set_active_sps_id(uint32_t active_sps_id) + void set_active_pps(H264_PPS &active_pps) { - m_activeSPSIndex = active_sps_id; - debug_printf("[d3d12_video_bitstream_builder_h264] Setting new active SPS ID: %d ", m_activeSPSIndex); - }; - void set_active_pps_id(uint32_t active_pps_id) - { - m_activePPSIndex = active_pps_id; - debug_printf("[d3d12_video_bitstream_builder_h264] Setting new active PPS ID: %d ", m_activePPSIndex); + m_activePPSStructure = active_pps; }; bool insert_aud_nalu_requested() { return m_insert_aud_nalu; } private: d3d12_video_nalu_writer_h264 m_h264Encoder; - std::vector m_activePPS; - uint32_t m_activeSPSIndex = 0; - uint32_t m_activePPSIndex = 0; + H264_SPS m_activeSPSStructure = {}; + H264_PPS m_activePPSStructure = {}; bool m_insert_aud_nalu = false; };