From: Boyuan Zhang Date: Tue, 7 Nov 2017 21:17:25 +0000 (-0500) Subject: radeon/vcn: add encode header algorithms X-Git-Url: https://git.libre-soc.org/?a=commitdiff_plain;h=d940fdf765b18974b54e21f66d31c45455ad79bc;p=mesa.git radeon/vcn: add encode header algorithms Since bitstream headers, e.g. sps, pps, slice, are encoded in driver side, we need to add corresponding algorithms that required to generate those headers. According to h.264 specs, signed/unsigned interger Exp-Golomb-coded syntax element with left bit first (code_se and code_ue) and unsigned integer using n bits (code_fixed_bits) descriptors function are needed. Therefore, adding those algorithms and related variables and output algorithms here. Signed-off-by: Boyuan Zhang Acked-by: Christian König --- diff --git a/src/gallium/drivers/radeon/radeon_vcn_enc.h b/src/gallium/drivers/radeon/radeon_vcn_enc.h index fe61419e301..c04652ba1fd 100644 --- a/src/gallium/drivers/radeon/radeon_vcn_enc.h +++ b/src/gallium/drivers/radeon/radeon_vcn_enc.h @@ -396,9 +396,15 @@ struct radeon_encoder { struct radeon_enc_h264_enc_pic enc_pic; unsigned alignment; + unsigned shifter; + unsigned bits_in_shifter; + unsigned num_zeros; + unsigned byte_index; + unsigned bits_output; uint32_t total_task_size; uint32_t* p_task_size; + bool emulation_prevention; bool need_feedback; }; diff --git a/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c b/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c index f75f3d63af4..5170c672295 100644 --- a/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c +++ b/src/gallium/drivers/radeon/radeon_vcn_enc_1_2.c @@ -49,6 +49,7 @@ RADEON_ENC_CS(cmd) enc->total_task_size += *begin;} static const unsigned profiles[7] = { 66, 77, 88, 100, 110, 122, 244 }; +static const unsigned index_to_shifts[4] = {24, 16, 8, 0}; static void radeon_enc_add_buffer(struct radeon_encoder *enc, struct pb_buffer *buf, enum radeon_bo_usage usage, enum radeon_bo_domain domain, @@ -63,6 +64,126 @@ static void radeon_enc_add_buffer(struct radeon_encoder *enc, struct pb_buffer * RADEON_ENC_CS(addr); } +static void radeon_enc_set_emulation_prevention(struct radeon_encoder *enc, bool set) +{ + if (set != enc->emulation_prevention) { + enc->emulation_prevention = set; + enc->num_zeros = 0; + } +} + +static void radeon_enc_output_one_byte(struct radeon_encoder *enc, unsigned char byte) +{ + if (enc->byte_index == 0) + enc->cs->current.buf[enc->cs->current.cdw] = 0; + enc->cs->current.buf[enc->cs->current.cdw] |= ((unsigned int)(byte) << index_to_shifts[enc->byte_index]); + enc->byte_index++; + + if (enc->byte_index >= 4) { + enc->byte_index = 0; + enc->cs->current.cdw++; + } +} + +static void radeon_enc_emulation_prevention(struct radeon_encoder *enc, unsigned char byte) +{ + if(enc->emulation_prevention) { + if((enc->num_zeros >= 2) && ((byte == 0x00) || (byte == 0x01) || (byte == 0x03))) { + radeon_enc_output_one_byte(enc, 0x03); + enc->bits_output += 8; + enc->num_zeros = 0; + } + enc->num_zeros = (byte == 0 ? (enc->num_zeros + 1) : 0); + } +} + +static void radeon_enc_code_fixed_bits(struct radeon_encoder *enc, unsigned int value, unsigned int num_bits) +{ + unsigned int bits_to_pack = 0; + + while(num_bits > 0) { + unsigned int value_to_pack = value & (0xffffffff >> (32 - num_bits)); + bits_to_pack = num_bits > (32 - enc->bits_in_shifter) ? (32 - enc->bits_in_shifter) : num_bits; + + if (bits_to_pack < num_bits) + value_to_pack = value_to_pack >> (num_bits - bits_to_pack); + + enc->shifter |= value_to_pack << (32 - enc->bits_in_shifter - bits_to_pack); + num_bits -= bits_to_pack; + enc->bits_in_shifter += bits_to_pack; + + while(enc->bits_in_shifter >= 8) { + unsigned char output_byte = (unsigned char)(enc->shifter >> 24); + enc->shifter <<= 8; + radeon_enc_emulation_prevention(enc, output_byte); + radeon_enc_output_one_byte(enc, output_byte); + enc->bits_in_shifter -= 8; + enc->bits_output += 8; + } + } +} + +static void radeon_enc_reset(struct radeon_encoder *enc) +{ + enc->emulation_prevention = false; + enc->shifter = 0; + enc->bits_in_shifter = 0; + enc->bits_output = 0; + enc->num_zeros = 0; + enc->byte_index = 0; +} + +static void radeon_enc_byte_align(struct radeon_encoder *enc) +{ + unsigned int num_padding_zeros = (32 - enc->bits_in_shifter) % 8; + + if (num_padding_zeros > 0) + radeon_enc_code_fixed_bits(enc, 0, num_padding_zeros); +} + +static void radeon_enc_flush_headers(struct radeon_encoder *enc) +{ + if (enc->bits_in_shifter != 0) { + unsigned char output_byte = (unsigned char)(enc->shifter >> 24); + radeon_enc_emulation_prevention(enc, output_byte); + radeon_enc_output_one_byte(enc, output_byte); + enc->bits_output += enc->bits_in_shifter; + enc->shifter = 0; + enc->bits_in_shifter = 0; + enc->num_zeros = 0; + } + + if (enc->byte_index > 0) { + enc->cs->current.cdw++; + enc->byte_index = 0; + } +} + +static void radeon_enc_code_ue(struct radeon_encoder *enc, unsigned int value) +{ + int x = -1; + unsigned int ue_code = value + 1; + value += 1; + + while (value) { + value = (value >> 1); + x += 1; + } + + unsigned int ue_length = (x << 1) + 1; + radeon_enc_code_fixed_bits(enc, ue_code, ue_length); +} + +static void radeon_enc_code_se(struct radeon_encoder *enc, int value) +{ + unsigned int v = 0; + + if (value != 0) + v = (value < 0 ? ((unsigned int)(0 - value) << 1) : (((unsigned int)(value) << 1) - 1)); + + radeon_enc_code_ue(enc, v); +} + static void radeon_enc_session_info(struct radeon_encoder *enc) { unsigned int interface_version = ((RENCODE_FW_INTERFACE_MAJOR_VERSION << RENCODE_IF_MAJOR_VERSION_SHIFT) |