d3d12: Add HEVC support for on demand AUD NALUS

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/31114>
This commit is contained in:
Sil Vilerino
2024-08-19 11:38:01 -04:00
committed by Marge Bot
parent 1c490a79f2
commit 26a02b7df7
5 changed files with 104 additions and 6 deletions
@@ -1071,6 +1071,17 @@ d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12E
static_cast<d3d12_video_bitstream_builder_hevc *>(pD3D12Enc->m_upBitstreamBuilder.get());
assert(pHEVCBitstreamBuilder);
size_t writtenAUDBytesCount = 0;
bool forceWriteAUD = (pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags & d3d12_video_encoder_config_dirty_flag_aud_header);
if (forceWriteAUD)
{
pHEVCBitstreamBuilder->write_aud(pD3D12Enc->m_BitstreamHeadersBuffer,
pD3D12Enc->m_BitstreamHeadersBuffer.begin(),
currentPicParams.pHEVCPicData->FrameType,
writtenAUDBytesCount);
pWrittenCodecUnitsSizes.push_back(writtenAUDBytesCount);
}
uint32_t active_seq_parameter_set_id = pHEVCBitstreamBuilder->get_active_sps().sps_seq_parameter_set_id;
uint32_t active_video_parameter_set_id = pHEVCBitstreamBuilder->get_active_vps().vps_video_parameter_set_id;
@@ -1086,7 +1097,7 @@ d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12E
gopHasBFrames,
active_video_parameter_set_id,
pD3D12Enc->m_BitstreamHeadersBuffer,
pD3D12Enc->m_BitstreamHeadersBuffer.begin(),
pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenAUDBytesCount,
writtenVPSBytesCount);
pHEVCBitstreamBuilder->set_active_vps(vps);
pWrittenCodecUnitsSizes.push_back(writtenVPSBytesCount);
@@ -1110,7 +1121,7 @@ d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12E
*codecConfigDesc.pHEVCConfig,
pD3D12Enc->m_currentEncodeConfig.m_encoderGOPConfigDesc.m_HEVCGroupOfPictures,
pD3D12Enc->m_BitstreamHeadersBuffer,
pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenVPSBytesCount,
pD3D12Enc->m_BitstreamHeadersBuffer.begin() + writtenAUDBytesCount + writtenVPSBytesCount,
writtenSPSBytesCount);
pHEVCBitstreamBuilder->set_active_sps(sps);
pWrittenCodecUnitsSizes.push_back(writtenSPSBytesCount);
@@ -1129,8 +1140,8 @@ d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12E
bool forceWritePPS = (pD3D12Enc->m_currentEncodeConfig.m_ConfigDirtyFlags & d3d12_video_encoder_config_dirty_flag_picture_header);
if (forceWritePPS || d3d12_video_encoder_needs_new_pps_hevc(pD3D12Enc, writeNewSPS, tentative_pps, active_pps)) {
pHEVCBitstreamBuilder->set_active_pps(tentative_pps);
pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenSPSBytesCount + writtenVPSBytesCount + writtenPPSBytesCount);
memcpy(&pD3D12Enc->m_BitstreamHeadersBuffer.data()[(writtenSPSBytesCount + writtenVPSBytesCount)], pD3D12Enc->m_StagingHeadersBuffer.data(), writtenPPSBytesCount);
pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenAUDBytesCount + writtenVPSBytesCount + writtenSPSBytesCount + writtenPPSBytesCount);
memcpy(&pD3D12Enc->m_BitstreamHeadersBuffer.data()[(writtenAUDBytesCount + writtenVPSBytesCount + writtenSPSBytesCount)], pD3D12Enc->m_StagingHeadersBuffer.data(), writtenPPSBytesCount);
pWrittenCodecUnitsSizes.push_back(writtenPPSBytesCount);
} else {
writtenPPSBytesCount = 0;
@@ -1138,8 +1149,8 @@ d3d12_video_encoder_build_codec_headers_hevc(struct d3d12_video_encoder *pD3D12E
}
// Shrink buffer to fit the headers
if (pD3D12Enc->m_BitstreamHeadersBuffer.size() > (writtenPPSBytesCount + writtenSPSBytesCount + writtenVPSBytesCount)) {
pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenPPSBytesCount + writtenSPSBytesCount + writtenVPSBytesCount);
if (pD3D12Enc->m_BitstreamHeadersBuffer.size() > (writtenAUDBytesCount + writtenVPSBytesCount + writtenSPSBytesCount + writtenPPSBytesCount)) {
pD3D12Enc->m_BitstreamHeadersBuffer.resize(writtenAUDBytesCount + writtenVPSBytesCount + writtenSPSBytesCount + writtenPPSBytesCount);
}
assert(std::accumulate(pWrittenCodecUnitsSizes.begin(), pWrittenCodecUnitsSizes.end(), 0u) ==
@@ -552,6 +552,15 @@ d3d12_video_bitstream_builder_hevc::write_end_of_sequence_nalu(std::vector<uint8
m_hevcEncoder.write_end_of_sequence_nalu(headerBitstream, placingPositionStart, writtenBytes);
}
void
d3d12_video_bitstream_builder_hevc::write_aud(std::vector<uint8_t> & headerBitstream,
std::vector<uint8_t>::iterator placingPositionStart,
D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType,
size_t & writtenBytes)
{
m_hevcEncoder.write_aud(headerBitstream, placingPositionStart, frameType, writtenBytes);
}
void
d3d12_video_bitstream_builder_hevc::print_vps(const HevcVideoParameterSet& VPS)
{
@@ -72,6 +72,11 @@ class d3d12_video_bitstream_builder_hevc : public d3d12_video_bitstream_builder_
std::vector<uint8_t>::iterator placingPositionStart,
size_t & writtenBytes);
void write_aud(std::vector<uint8_t> & headerBitstream,
std::vector<uint8_t>::iterator placingPositionStart,
D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType,
size_t & writtenBytes);
void print_vps(const HevcVideoParameterSet& vps);
void print_sps(const HevcSeqParameterSet& sps);
void print_pps(const HevcPicParameterSet& pps);
@@ -90,6 +90,51 @@ d3d12_video_nalu_writer_hevc::write_end_of_sequence_nalu(std::vector<BYTE> &head
generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, &endOfSeqNALU);
}
void
d3d12_video_nalu_writer_hevc::write_aud(std::vector<BYTE> &headerBitstream,
std::vector<BYTE>::iterator placingPositionStart,
D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType,
size_t &writtenBytes) {
HevcAccessUnitDelimiter AUD = {};
AUD.nalu =
{
// uint8_t forbidden_zero_bit;
static_cast<uint8_t>(0u),
// uint8_t nal_unit_type
static_cast<uint8_t>(HEVC_NALU_AUD_NUT),
// uint8_t nuh_layer_id
static_cast<uint8_t>(0u),
// uint8_t nuh_temporal_id_plus1
static_cast<uint8_t>(1u)
};
// pic_type slice_type values that may be present in the coded picture
switch (frameType)
{
case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_IDR_FRAME:
case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_I_FRAME:
{
AUD.pic_type = 0u; // 0 I
} break;
case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_P_FRAME:
{
AUD.pic_type = 1u; // 1 P, I
} break;
case D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC_B_FRAME:
{
AUD.pic_type = 2u; // 2 B, P, I
} break;
default:
{
debug_printf("d3d12_video_nalu_writer_hevc::write_aud failed: Invalid D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType argument \n");
assert(false);
} break;
}
generic_write_bytes(headerBitstream, placingPositionStart, writtenBytes, &AUD);
}
void
d3d12_video_nalu_writer_hevc::generic_write_bytes( std::vector<BYTE> &headerBitstream,
std::vector<BYTE>::iterator placingPositionStart,
@@ -161,6 +206,10 @@ d3d12_video_nalu_writer_hevc::write_bytes_from_struct(d3d12_video_encoder_bitstr
// Do nothing for these two, just the header suffices
return 1;
} break;
case HEVC_NALU_AUD_NUT:
{
return write_aud_bytes(pBitstream, (HevcAccessUnitDelimiter *) pData);
} break;
default:
{
unreachable("Unsupported NALU value");
@@ -168,6 +217,20 @@ d3d12_video_nalu_writer_hevc::write_bytes_from_struct(d3d12_video_encoder_bitstr
}
}
uint32_t
d3d12_video_nalu_writer_hevc::write_aud_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcAccessUnitDelimiter *pAUD)
{
int32_t iBytesWritten = pBitstream->get_byte_count();
pBitstream->put_bits(3, pAUD->pic_type);
rbsp_trailing(pBitstream);
pBitstream->flush();
iBytesWritten = pBitstream->get_byte_count() - iBytesWritten;
return (uint32_t) iBytesWritten;
}
uint32_t
d3d12_video_nalu_writer_hevc::write_vps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcVideoParameterSet *vps)
{
@@ -318,6 +318,11 @@ struct HevcVideoParameterSet {
uint8_t vps_extension_data_flag;
};
struct HevcAccessUnitDelimiter {
HEVCNaluHeader nalu;
uint8_t pic_type;
};
class d3d12_video_nalu_writer_hevc
{
public:
@@ -362,12 +367,17 @@ public:
placingPositionStart,
size_t &writtenBytes);
void write_aud(std::vector<uint8_t> & headerBitstream,
std::vector<uint8_t>::iterator placingPositionStart,
D3D12_VIDEO_ENCODER_FRAME_TYPE_HEVC frameType,
size_t & writtenBytes);
private:
// Writes from structure into bitstream with RBSP trailing but WITHOUT NAL unit wrap (eg. nal_idc_type, etc)
uint32_t write_vps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcVideoParameterSet *pSPS);
uint32_t write_sps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcSeqParameterSet *pSPS);
uint32_t write_pps_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcPicParameterSet *pPPS);
uint32_t write_aud_bytes(d3d12_video_encoder_bitstream *pBitstream, HevcAccessUnitDelimiter *pAUD);
// Adds NALU wrapping into structures and ending NALU control bits
uint32_t wrap_rbsp_into_nalu(d3d12_video_encoder_bitstream *pNALU, d3d12_video_encoder_bitstream *pRBSP, HEVCNaluHeader *pHeader);