From cd575ff72b81c453fa3a6863fba3c2c8accd62ca Mon Sep 17 00:00:00 2001 From: Sil Vilerino Date: Thu, 23 Mar 2023 10:56:14 -0400 Subject: [PATCH] d3d12: Encode H264/HEVC - Do not write PPS unless different from active Part-of: --- src/gallium/drivers/d3d12/d3d12_video_enc.h | 1 + .../drivers/d3d12/d3d12_video_enc_h264.cpp | 15 +++++++++++++-- .../drivers/d3d12/d3d12_video_enc_hevc.cpp | 17 ++++++++++++++--- ...d3d12_video_encoder_bitstream_builder_h264.h | 11 ++++++++--- ...d3d12_video_encoder_bitstream_builder_hevc.h | 17 +++++++++++------ 5 files changed, 47 insertions(+), 14 deletions(-) diff --git a/src/gallium/drivers/d3d12/d3d12_video_enc.h b/src/gallium/drivers/d3d12/d3d12_video_enc.h index 9a9c40bbddd..7c5b23afa8b 100644 --- a/src/gallium/drivers/d3d12/d3d12_video_enc.h +++ b/src/gallium/drivers/d3d12/d3d12_video_enc.h @@ -259,6 +259,7 @@ struct d3d12_video_encoder }; std::vector m_BitstreamHeadersBuffer; + std::vector m_StagingHeadersBuffer; std::vector m_spEncodedFrameMetadata; struct D3D12EncodeCapabilities m_currentEncodeCapabilities = {}; diff --git a/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp b/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp index 9b5ee0e67a8..37b7eab3277 100644 --- a/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp +++ b/src/gallium/drivers/d3d12/d3d12_video_enc_h264.cpp @@ -860,10 +860,21 @@ d3d12_video_encoder_build_codec_headers_h264(struct d3d12_video_encoder *pD3D12E *currentPicParams.pH264PicData, currentPicParams.pH264PicData->pic_parameter_set_id, active_seq_parameter_set_id, - pD3D12Enc->m_BitstreamHeadersBuffer, - pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenSPSBytesCount, + pD3D12Enc->m_StagingHeadersBuffer, + pD3D12Enc->m_StagingHeadersBuffer.begin(), writtenPPSBytesCount); + std::vector& active_pps = pH264BitstreamBuilder->get_active_pps(); + if ( (writtenPPSBytesCount != active_pps.size()) || + memcmp(pD3D12Enc->m_StagingHeadersBuffer.data(), active_pps.data(), writtenPPSBytesCount)) { + active_pps = pD3D12Enc->m_StagingHeadersBuffer; + pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenSPSBytesCount + writtenPPSBytesCount); + memcpy(&pD3D12Enc->m_BitstreamHeadersBuffer.data()[writtenSPSBytesCount], pD3D12Enc->m_StagingHeadersBuffer.data(), writtenPPSBytesCount); + } else { + writtenPPSBytesCount = 0; + debug_printf("Skipping PPS (same as active PPS) for fenceValue: %" PRIu64 "\n", pD3D12Enc->m_fenceValue); + } + // Shrink buffer to fit the headers if (pD3D12Enc->m_BitstreamHeadersBuffer.size() > (writtenPPSBytesCount + writtenSPSBytesCount)) { pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenPPSBytesCount + writtenSPSBytesCount); diff --git a/src/gallium/drivers/d3d12/d3d12_video_enc_hevc.cpp b/src/gallium/drivers/d3d12/d3d12_video_enc_hevc.cpp index 5865a46ac4a..004d39a1edf 100644 --- a/src/gallium/drivers/d3d12/d3d12_video_enc_hevc.cpp +++ b/src/gallium/drivers/d3d12/d3d12_video_enc_hevc.cpp @@ -792,15 +792,26 @@ d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12E } size_t writtenPPSBytesCount = 0; - + pHEVCBitstreamBuilder->build_pps(pHEVCBitstreamBuilder->get_latest_sps(), currentPicParams.pHEVCPicData->slice_pic_parameter_set_id, *codecConfigDesc.pHEVCConfig, *currentPicParams.pHEVCPicData, - pD3D12Enc->m_BitstreamHeadersBuffer, - pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenSPSBytesCount + writtenVPSBytesCount, + pD3D12Enc->m_StagingHeadersBuffer, + pD3D12Enc->m_StagingHeadersBuffer.begin(), writtenPPSBytesCount); + std::vector& active_pps = pHEVCBitstreamBuilder->get_active_pps(); + if ( (writtenPPSBytesCount != active_pps.size()) || + memcmp(pD3D12Enc->m_StagingHeadersBuffer.data(), active_pps.data(), writtenPPSBytesCount)) { + active_pps = pD3D12Enc->m_StagingHeadersBuffer; + pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenSPSBytesCount + writtenVPSBytesCount + writtenPPSBytesCount); + memcpy(&pD3D12Enc->m_BitstreamHeadersBuffer.data()[(writtenSPSBytesCount + writtenVPSBytesCount)], pD3D12Enc->m_StagingHeadersBuffer.data(), writtenPPSBytesCount); + } else { + writtenPPSBytesCount = 0; + debug_printf("Skipping PPS (same as active PPS) for fenceValue: %" PRIu64 "\n", pD3D12Enc->m_fenceValue); + } + // Shrink buffer to fit the headers if (pD3D12Enc->m_BitstreamHeadersBuffer.size() > (writtenPPSBytesCount + writtenSPSBytesCount + writtenVPSBytesCount)) { pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenPPSBytesCount + writtenSPSBytesCount + writtenVPSBytesCount); 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 ca569a2da4f..c44eb1898b5 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 @@ -66,9 +66,6 @@ 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 m_activeSPSIndex = 0; - uint32_t m_activePPSIndex = 0; - uint32_t get_active_sps_id() { return m_activeSPSIndex; @@ -78,6 +75,11 @@ class d3d12_video_bitstream_builder_h264 : public d3d12_video_bitstream_builder_ return m_activePPSIndex; }; + std::vector& get_active_pps() + { + return m_activePPS; + }; + void set_active_sps_id(uint32_t active_sps_id) { m_activeSPSIndex = active_sps_id; @@ -91,6 +93,9 @@ class d3d12_video_bitstream_builder_h264 : public d3d12_video_bitstream_builder_ private: d3d12_video_nalu_writer_h264 m_h264Encoder; + std::vector m_activePPS; + uint32_t m_activeSPSIndex = 0; + uint32_t m_activePPSIndex = 0; }; #endif diff --git a/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_hevc.h b/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_hevc.h index 6eb80c13c28..e2487c132a4 100644 --- a/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_hevc.h +++ b/src/gallium/drivers/d3d12/d3d12_video_encoder_bitstream_builder_hevc.h @@ -79,12 +79,10 @@ class d3d12_video_bitstream_builder_hevc : public d3d12_video_bitstream_builder_ void print_pps(const HevcPicParameterSet& pps); void print_rps(const HevcSeqParameterSet* sps, UINT stRpsIdx); - uint32_t m_activeVPSIndex = 0; - uint32_t m_activeSPSIndex = 0; - uint32_t m_activePPSIndex = 0; - HevcVideoParameterSet m_latest_vps = {}; - HevcSeqParameterSet m_latest_sps = {}; - HevcPicParameterSet m_latest_pps = {}; + std::vector& get_active_pps() + { + return m_activePPS; + }; HevcVideoParameterSet get_latest_vps() { @@ -133,6 +131,13 @@ class d3d12_video_bitstream_builder_hevc : public d3d12_video_bitstream_builder_ private: d3d12_video_nalu_writer_hevc m_hevcEncoder; + uint32_t m_activeVPSIndex = 0; + uint32_t m_activeSPSIndex = 0; + uint32_t m_activePPSIndex = 0; + HevcVideoParameterSet m_latest_vps = {}; + HevcSeqParameterSet m_latest_sps = {}; + HevcPicParameterSet m_latest_pps = {}; + std::vector m_activePPS; void init_profile_tier_level(HEVCProfileTierLevel *ptl, uint8_t HEVCProfileIdc, uint8_t HEVCLevelIdc, bool isHighTier); };