mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-09 08:58:02 +02:00
radeonsi/uvd_enc: Support raw packed headers
Reviewed-by: Ruijing Dong <ruijing.dong@amd.com> Acked-by: Leo Liu <leo.liu@amd.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/32829>
This commit is contained in:
parent
da9de889aa
commit
73657d4246
3 changed files with 134 additions and 46 deletions
|
|
@ -23,8 +23,6 @@ static void radeon_uvd_enc_get_param(struct radeon_uvd_encoder *enc,
|
|||
enc->enc_pic.desc = pic;
|
||||
enc->enc_pic.picture_type = pic->picture_type;
|
||||
enc->enc_pic.nal_unit_type = pic->pic.nal_unit_type;
|
||||
enc->enc_pic.is_iframe = (pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_IDR) ||
|
||||
(pic->picture_type == PIPE_H2645_ENC_PICTURE_TYPE_I);
|
||||
enc->enc_pic.enc_params.reference_picture_index =
|
||||
pic->ref_list0[0] == PIPE_H2645_LIST_REF_INVALID_ENTRY ? 0xffffffff : pic->ref_list0[0];
|
||||
enc->enc_pic.enc_params.reconstructed_picture_index = pic->dpb_curr_pic;
|
||||
|
|
@ -187,6 +185,79 @@ static void radeon_uvd_enc_begin_frame(struct pipe_video_codec *encoder,
|
|||
}
|
||||
}
|
||||
|
||||
static void *radeon_uvd_enc_encode_headers(struct radeon_uvd_encoder *enc)
|
||||
{
|
||||
unsigned num_slices = 0, num_headers = 0;
|
||||
|
||||
util_dynarray_foreach(&enc->enc_pic.desc->raw_headers, struct pipe_enc_raw_header, header) {
|
||||
if (header->is_slice)
|
||||
num_slices++;
|
||||
num_headers++;
|
||||
}
|
||||
|
||||
if (!num_headers || !num_slices || num_headers == num_slices)
|
||||
return NULL;
|
||||
|
||||
size_t segments_size =
|
||||
sizeof(struct ruvd_enc_output_unit_segment) * (num_headers - num_slices + 1);
|
||||
struct ruvd_enc_feedback_data *data =
|
||||
CALLOC_VARIANT_LENGTH_STRUCT(ruvd_enc_feedback_data, segments_size);
|
||||
if (!data)
|
||||
return NULL;
|
||||
|
||||
uint8_t *ptr = enc->ws->buffer_map(enc->ws, enc->bs_handle, &enc->cs,
|
||||
PIPE_MAP_WRITE | RADEON_MAP_TEMPORARY);
|
||||
if (!ptr) {
|
||||
RVID_ERR("Can't map bs buffer.\n");
|
||||
FREE(data);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
unsigned offset = 0;
|
||||
struct ruvd_enc_output_unit_segment *slice_segment = NULL;
|
||||
|
||||
util_dynarray_foreach(&enc->enc_pic.desc->raw_headers, struct pipe_enc_raw_header, header) {
|
||||
if (header->is_slice) {
|
||||
if (slice_segment)
|
||||
continue;
|
||||
slice_segment = &data->segments[data->num_segments];
|
||||
slice_segment->is_slice = true;
|
||||
} else {
|
||||
unsigned size;
|
||||
switch (header->type) {
|
||||
case PIPE_H265_NAL_VPS:
|
||||
size = radeon_uvd_enc_write_vps(enc, ptr + offset);
|
||||
break;
|
||||
case PIPE_H265_NAL_SPS:
|
||||
size = radeon_uvd_enc_write_sps(enc, ptr + offset);
|
||||
break;
|
||||
case PIPE_H265_NAL_PPS:
|
||||
size = radeon_uvd_enc_write_pps(enc, ptr + offset);
|
||||
break;
|
||||
default:
|
||||
assert(header->buffer);
|
||||
memcpy(ptr + offset, header->buffer, header->size);
|
||||
size = header->size;
|
||||
break;
|
||||
}
|
||||
data->segments[data->num_segments].size = size;
|
||||
data->segments[data->num_segments].offset = offset;
|
||||
offset += size;
|
||||
}
|
||||
data->num_segments++;
|
||||
}
|
||||
|
||||
enc->bs_offset = align(offset, 16);
|
||||
assert(enc->bs_offset < enc->bs_size);
|
||||
|
||||
assert(slice_segment);
|
||||
slice_segment->offset = enc->bs_offset;
|
||||
|
||||
enc->ws->buffer_unmap(enc->ws, enc->bs_handle);
|
||||
|
||||
return data;
|
||||
}
|
||||
|
||||
static void radeon_uvd_enc_encode_bitstream(struct pipe_video_codec *encoder,
|
||||
struct pipe_video_buffer *source,
|
||||
struct pipe_resource *destination, void **fb)
|
||||
|
|
@ -194,6 +265,7 @@ static void radeon_uvd_enc_encode_bitstream(struct pipe_video_codec *encoder,
|
|||
struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder;
|
||||
enc->get_buffer(destination, &enc->bs_handle, NULL);
|
||||
enc->bs_size = destination->width0;
|
||||
enc->bs_offset = 0;
|
||||
|
||||
*fb = enc->fb = CALLOC_STRUCT(rvid_buffer);
|
||||
|
||||
|
|
@ -202,6 +274,8 @@ static void radeon_uvd_enc_encode_bitstream(struct pipe_video_codec *encoder,
|
|||
return;
|
||||
}
|
||||
|
||||
enc->fb->user_data = radeon_uvd_enc_encode_headers(enc);
|
||||
|
||||
enc->need_feedback = true;
|
||||
enc->encode(enc);
|
||||
}
|
||||
|
|
@ -244,15 +318,38 @@ static void radeon_uvd_enc_get_feedback(struct pipe_video_codec *encoder, void *
|
|||
struct radeon_uvd_encoder *enc = (struct radeon_uvd_encoder *)encoder;
|
||||
struct rvid_buffer *fb = feedback;
|
||||
|
||||
if (NULL != size) {
|
||||
radeon_uvd_enc_feedback_t *fb_data = (radeon_uvd_enc_feedback_t *)enc->ws->buffer_map(
|
||||
enc->ws, fb->res->buf, &enc->cs, PIPE_MAP_READ_WRITE | RADEON_MAP_TEMPORARY);
|
||||
radeon_uvd_enc_feedback_t *fb_data = (radeon_uvd_enc_feedback_t *)enc->ws->buffer_map(
|
||||
enc->ws, fb->res->buf, &enc->cs, PIPE_MAP_READ_WRITE | RADEON_MAP_TEMPORARY);
|
||||
|
||||
if (!fb_data->status)
|
||||
*size = fb_data->bitstream_size;
|
||||
else
|
||||
*size = 0;
|
||||
enc->ws->buffer_unmap(enc->ws, fb->res->buf);
|
||||
if (!fb_data->status)
|
||||
*size = fb_data->bitstream_size;
|
||||
else
|
||||
*size = 0;
|
||||
|
||||
enc->ws->buffer_unmap(enc->ws, fb->res->buf);
|
||||
|
||||
metadata->present_metadata = PIPE_VIDEO_FEEDBACK_METADATA_TYPE_CODEC_UNIT_LOCATION;
|
||||
|
||||
if (fb->user_data) {
|
||||
struct ruvd_enc_feedback_data *data = fb->user_data;
|
||||
metadata->codec_unit_metadata_count = data->num_segments;
|
||||
for (unsigned i = 0; i < data->num_segments; i++) {
|
||||
metadata->codec_unit_metadata[i].offset = data->segments[i].offset;
|
||||
if (data->segments[i].is_slice) {
|
||||
metadata->codec_unit_metadata[i].size = *size;
|
||||
metadata->codec_unit_metadata[i].flags = 0;
|
||||
} else {
|
||||
metadata->codec_unit_metadata[i].size = data->segments[i].size;
|
||||
metadata->codec_unit_metadata[i].flags = PIPE_VIDEO_CODEC_UNIT_LOCATION_FLAG_SINGLE_NALU;
|
||||
}
|
||||
}
|
||||
FREE(fb->user_data);
|
||||
fb->user_data = NULL;
|
||||
} else {
|
||||
metadata->codec_unit_metadata_count = 1;
|
||||
metadata->codec_unit_metadata[0].offset = 0;
|
||||
metadata->codec_unit_metadata[0].size = *size;
|
||||
metadata->codec_unit_metadata[0].flags = 0;
|
||||
}
|
||||
|
||||
si_vid_destroy_buffer(fb);
|
||||
|
|
|
|||
|
|
@ -317,8 +317,6 @@ struct radeon_uvd_enc_pic {
|
|||
unsigned nal_unit_type;
|
||||
unsigned temporal_id;
|
||||
|
||||
bool is_iframe;
|
||||
|
||||
ruvd_enc_task_info_t task_info;
|
||||
ruvd_enc_session_init_t session_init;
|
||||
ruvd_enc_layer_control_t layer_ctrl;
|
||||
|
|
@ -359,6 +357,7 @@ struct radeon_uvd_encoder {
|
|||
|
||||
struct pb_buffer_lean *bs_handle;
|
||||
unsigned bs_size;
|
||||
unsigned bs_offset;
|
||||
|
||||
unsigned dpb_slots;
|
||||
|
||||
|
|
@ -375,9 +374,24 @@ struct radeon_uvd_encoder {
|
|||
bool need_rc_per_pic;
|
||||
};
|
||||
|
||||
struct ruvd_enc_output_unit_segment {
|
||||
bool is_slice;
|
||||
unsigned size;
|
||||
unsigned offset;
|
||||
};
|
||||
|
||||
struct ruvd_enc_feedback_data {
|
||||
unsigned num_segments;
|
||||
struct ruvd_enc_output_unit_segment segments[];
|
||||
};
|
||||
|
||||
struct si_screen;
|
||||
|
||||
void radeon_uvd_enc_1_1_init(struct radeon_uvd_encoder *enc);
|
||||
bool si_radeon_uvd_enc_supported(struct si_screen *sscreen);
|
||||
|
||||
unsigned int radeon_uvd_enc_write_vps(struct radeon_uvd_encoder *enc, uint8_t *out);
|
||||
unsigned int radeon_uvd_enc_write_sps(struct radeon_uvd_encoder *enc, uint8_t *out);
|
||||
unsigned int radeon_uvd_enc_write_pps(struct radeon_uvd_encoder *enc, uint8_t *out);
|
||||
|
||||
#endif // _RADEON_UVD_ENC_H
|
||||
|
|
|
|||
|
|
@ -277,17 +277,13 @@ static void radeon_uvd_enc_quality_params(struct radeon_uvd_encoder *enc)
|
|||
RADEON_ENC_END();
|
||||
}
|
||||
|
||||
static void radeon_uvd_enc_nalu_sps_hevc(struct radeon_uvd_encoder *enc)
|
||||
unsigned int radeon_uvd_enc_write_sps(struct radeon_uvd_encoder *enc, uint8_t *out)
|
||||
{
|
||||
struct radeon_bitstream bs;
|
||||
struct pipe_h265_enc_seq_param *sps = &enc->enc_pic.desc->seq;
|
||||
int i;
|
||||
|
||||
RADEON_ENC_BEGIN(RENC_UVD_IB_PARAM_INSERT_NALU_BUFFER);
|
||||
RADEON_ENC_CS(RENC_UVD_NALU_TYPE_SPS);
|
||||
uint32_t *size_in_bytes = &enc->cs.current.buf[enc->cs.current.cdw++];
|
||||
|
||||
radeon_bs_reset(&bs, NULL, &enc->cs);
|
||||
radeon_bs_reset(&bs, out, NULL);
|
||||
radeon_bs_set_emulation_prevention(&bs, false);
|
||||
radeon_bs_code_fixed_bits(&bs, 0x00000001, 32);
|
||||
radeon_bs_code_fixed_bits(&bs, 0x4201, 16);
|
||||
|
|
@ -412,21 +408,15 @@ static void radeon_uvd_enc_nalu_sps_hevc(struct radeon_uvd_encoder *enc)
|
|||
radeon_bs_code_fixed_bits(&bs, 0x1, 1);
|
||||
radeon_bs_byte_align(&bs);
|
||||
|
||||
radeon_bs_flush_headers(&bs);
|
||||
*size_in_bytes = bs.bits_output / 8;
|
||||
RADEON_ENC_END();
|
||||
return bs.bits_output / 8;
|
||||
}
|
||||
|
||||
static void radeon_uvd_enc_nalu_pps_hevc(struct radeon_uvd_encoder *enc)
|
||||
unsigned int radeon_uvd_enc_write_pps(struct radeon_uvd_encoder *enc, uint8_t *out)
|
||||
{
|
||||
struct radeon_bitstream bs;
|
||||
struct pipe_h265_enc_pic_param *pps = &enc->enc_pic.desc->pic;
|
||||
|
||||
RADEON_ENC_BEGIN(RENC_UVD_IB_PARAM_INSERT_NALU_BUFFER);
|
||||
RADEON_ENC_CS(RENC_UVD_NALU_TYPE_PPS);
|
||||
uint32_t *size_in_bytes = &enc->cs.current.buf[enc->cs.current.cdw++];
|
||||
|
||||
radeon_bs_reset(&bs, NULL, &enc->cs);
|
||||
radeon_bs_reset(&bs, out, NULL);
|
||||
radeon_bs_set_emulation_prevention(&bs, false);
|
||||
radeon_bs_code_fixed_bits(&bs, 0x00000001, 32);
|
||||
radeon_bs_code_fixed_bits(&bs, 0x4401, 16);
|
||||
|
|
@ -473,22 +463,16 @@ static void radeon_uvd_enc_nalu_pps_hevc(struct radeon_uvd_encoder *enc)
|
|||
radeon_bs_code_fixed_bits(&bs, 0x1, 1);
|
||||
radeon_bs_byte_align(&bs);
|
||||
|
||||
radeon_bs_flush_headers(&bs);
|
||||
*size_in_bytes = bs.bits_output / 8;
|
||||
RADEON_ENC_END();
|
||||
return bs.bits_output / 8;
|
||||
}
|
||||
|
||||
static void radeon_uvd_enc_nalu_vps_hevc(struct radeon_uvd_encoder *enc)
|
||||
unsigned int radeon_uvd_enc_write_vps(struct radeon_uvd_encoder *enc, uint8_t *out)
|
||||
{
|
||||
struct radeon_bitstream bs;
|
||||
struct pipe_h265_enc_vid_param *vps = &enc->enc_pic.desc->vid;
|
||||
int i;
|
||||
|
||||
RADEON_ENC_BEGIN(RENC_UVD_IB_PARAM_INSERT_NALU_BUFFER);
|
||||
RADEON_ENC_CS(RENC_UVD_NALU_TYPE_VPS);
|
||||
uint32_t *size_in_bytes = &enc->cs.current.buf[enc->cs.current.cdw++];
|
||||
|
||||
radeon_bs_reset(&bs, NULL, &enc->cs);
|
||||
radeon_bs_reset(&bs, out, NULL);
|
||||
radeon_bs_set_emulation_prevention(&bs, false);
|
||||
radeon_bs_code_fixed_bits(&bs, 0x00000001, 32);
|
||||
radeon_bs_code_fixed_bits(&bs, 0x4001, 16);
|
||||
|
|
@ -524,9 +508,7 @@ static void radeon_uvd_enc_nalu_vps_hevc(struct radeon_uvd_encoder *enc)
|
|||
radeon_bs_code_fixed_bits(&bs, 0x1, 1);
|
||||
radeon_bs_byte_align(&bs);
|
||||
|
||||
radeon_bs_flush_headers(&bs);
|
||||
*size_in_bytes = bs.bits_output / 8;
|
||||
RADEON_ENC_END();
|
||||
return bs.bits_output / 8;
|
||||
}
|
||||
|
||||
static void radeon_uvd_enc_slice_header_hevc(struct radeon_uvd_encoder *enc)
|
||||
|
|
@ -715,7 +697,7 @@ static void radeon_uvd_enc_bitstream(struct radeon_uvd_encoder *enc)
|
|||
{
|
||||
enc->enc_pic.bit_buf.mode = RENC_UVD_SWIZZLE_MODE_LINEAR;
|
||||
enc->enc_pic.bit_buf.video_bitstream_buffer_size = enc->bs_size;
|
||||
enc->enc_pic.bit_buf.video_bitstream_data_offset = 0;
|
||||
enc->enc_pic.bit_buf.video_bitstream_data_offset = enc->bs_offset;
|
||||
|
||||
RADEON_ENC_BEGIN(RENC_UVD_IB_PARAM_VIDEO_BITSTREAM_BUFFER);
|
||||
RADEON_ENC_CS(enc->enc_pic.bit_buf.mode);
|
||||
|
|
@ -800,7 +782,7 @@ static void radeon_uvd_enc_encode_params_hevc(struct radeon_uvd_encoder *enc)
|
|||
enc->enc_pic.enc_params.pic_type = RENC_UVD_PICTURE_TYPE_I;
|
||||
}
|
||||
|
||||
enc->enc_pic.enc_params.allowed_max_bitstream_size = enc->bs_size;
|
||||
enc->enc_pic.enc_params.allowed_max_bitstream_size = enc->bs_size - enc->bs_offset;
|
||||
if (sscreen->info.gfx_level < GFX9) {
|
||||
enc->enc_pic.enc_params.input_pic_luma_pitch =
|
||||
(enc->luma->u.legacy.level[0].nblk_x * enc->luma->bpe);
|
||||
|
|
@ -933,11 +915,6 @@ static void encode(struct radeon_uvd_encoder *enc)
|
|||
enc->enc_pic.layer_sel.temporal_layer_index = enc->enc_pic.temporal_id;
|
||||
radeon_uvd_enc_layer_select(enc);
|
||||
|
||||
if (enc->enc_pic.is_iframe) {
|
||||
radeon_uvd_enc_nalu_vps_hevc(enc);
|
||||
radeon_uvd_enc_nalu_pps_hevc(enc);
|
||||
radeon_uvd_enc_nalu_sps_hevc(enc);
|
||||
}
|
||||
radeon_uvd_enc_slice_header_hevc(enc);
|
||||
radeon_uvd_enc_encode_params_hevc(enc);
|
||||
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue