[Libva] [PATCH][AVCENC] Add the SEI segment for CBR mode to pass HRD test
yakui.zhao at intel.com
yakui.zhao at intel.com
Mon Sep 24 14:17:19 PDT 2012
From: Zhao Yakui <yakui.zhao at intel.com>
Otherwise the encoded h264 video stream can't be parsed by HRD test software.
Signed-off-by: Zhao Yakui <yakui.zhao at intel.com>
---
test/encode/avcenc.c | 155 ++++++++++++++++++++++++++++++++++++++++++++++++++-
1 file changed, 154 insertions(+), 1 deletion(-)
diff --git a/test/encode/avcenc.c b/test/encode/avcenc.c
index a7e0575..2f7f70f 100644
--- a/test/encode/avcenc.c
+++ b/test/encode/avcenc.c
@@ -59,6 +59,7 @@
#define NAL_IDR 5
#define NAL_SPS 7
#define NAL_PPS 8
+#define NAL_SEI 6
#define SLICE_TYPE_P 0
#define SLICE_TYPE_B 1
@@ -98,6 +99,16 @@ build_packed_pic_buffer(unsigned char **header_buffer);
static int
build_packed_seq_buffer(unsigned char **header_buffer);
+static int
+build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,
+ unsigned int init_cpb_removal_delay,
+ unsigned int init_cpb_removal_delay_offset,
+ unsigned int cpb_removal_length,
+ unsigned int cpb_removal_delay,
+ unsigned int dpb_output_length,
+ unsigned int dpb_output_delay,
+ unsigned char **sei_buffer);
+
struct upload_thread_param
{
FILE *yuv_fp;
@@ -123,6 +134,8 @@ static struct {
VABufferID packed_seq_buf_id;
VABufferID packed_pic_header_param_buf_id;
VABufferID packed_pic_buf_id;
+ VABufferID packed_sei_header_param_buf_id; /* the SEI buffer */
+ VABufferID packed_sei_buf_id;
VABufferID misc_parameter_hrd_buf_id;
int num_slices;
@@ -133,6 +146,11 @@ static struct {
struct upload_thread_param upload_thread_param;
pthread_t upload_thread_id;
int upload_thread_value;
+ int i_initial_cpb_removal_delay;
+ int i_initial_cpb_removal_delay_length;
+ int i_cpb_removal_delay;
+ int i_cpb_removal_delay_length;
+ int i_dpb_output_delay_length;
} avcenc_context;
static void create_encode_pipe()
@@ -264,6 +282,45 @@ static void release_encode_resource()
vaDestroySurfaces(va_dpy, &surface_ids[0], SID_NUMBER);
}
+static void avcenc_update_sei_param(int frame_num)
+{
+ VAEncPackedHeaderParameterBuffer packed_header_param_buffer;
+ unsigned int length_in_bits, offset_in_bytes;
+ unsigned char *packed_sei_buffer = NULL;
+ VAStatus va_status;
+
+ length_in_bits = build_packed_sei_buffer_timing(
+ avcenc_context.i_initial_cpb_removal_delay_length,
+ avcenc_context.i_initial_cpb_removal_delay,
+ 0,
+ avcenc_context.i_cpb_removal_delay_length,
+ avcenc_context.i_cpb_removal_delay * frame_num,
+ avcenc_context.i_dpb_output_delay_length,
+ 0,
+ &packed_sei_buffer);
+
+ offset_in_bytes = 0;
+ packed_header_param_buffer.type = VAEncPackedHeaderH264_SEI;
+ packed_header_param_buffer.bit_length = length_in_bits;
+ packed_header_param_buffer.has_emulation_bytes = 0;
+
+ va_status = vaCreateBuffer(va_dpy,
+ avcenc_context.context_id,
+ VAEncPackedHeaderParameterBufferType,
+ sizeof(packed_header_param_buffer), 1, &packed_header_param_buffer,
+ &avcenc_context.packed_sei_header_param_buf_id);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+
+ va_status = vaCreateBuffer(va_dpy,
+ avcenc_context.context_id,
+ VAEncPackedHeaderDataBufferType,
+ (length_in_bits + 7) / 8, 1, packed_sei_buffer,
+ &avcenc_context.packed_sei_buf_id);
+ CHECK_VASTATUS(va_status,"vaCreateBuffer");
+ free(packed_sei_buffer);
+ return;
+}
+
static void avcenc_update_picture_parameter(int slice_type, int frame_num, int display_num, int is_idr)
{
VAEncPictureParameterBufferH264 *pic_param;
@@ -541,7 +598,7 @@ static int begin_picture(FILE *yuv_fp, int frame_num, int display_num, int slice
int avcenc_render_picture()
{
VAStatus va_status;
- VABufferID va_buffers[8];
+ VABufferID va_buffers[10];
unsigned int num_va_buffers = 0;
int i;
@@ -560,6 +617,12 @@ int avcenc_render_picture()
if (avcenc_context.packed_pic_buf_id != VA_INVALID_ID)
va_buffers[num_va_buffers++] = avcenc_context.packed_pic_buf_id;
+ if (avcenc_context.packed_sei_header_param_buf_id != VA_INVALID_ID)
+ va_buffers[num_va_buffers++] = avcenc_context.packed_sei_header_param_buf_id;
+
+ if (avcenc_context.packed_sei_buf_id != VA_INVALID_ID)
+ va_buffers[num_va_buffers++] = avcenc_context.packed_sei_buf_id;
+
if (avcenc_context.misc_parameter_hrd_buf_id != VA_INVALID_ID)
va_buffers[num_va_buffers++] = avcenc_context.misc_parameter_hrd_buf_id;
@@ -633,6 +696,8 @@ static void end_picture(int slice_type, int next_is_bpic)
avcenc_destroy_buffers(&avcenc_context.packed_seq_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.packed_pic_header_param_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.packed_pic_buf_id, 1);
+ avcenc_destroy_buffers(&avcenc_context.packed_sei_header_param_buf_id, 1);
+ avcenc_destroy_buffers(&avcenc_context.packed_sei_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.slice_param_buf_id[0], avcenc_context.num_slices);
avcenc_destroy_buffers(&avcenc_context.codedbuf_buf_id, 1);
avcenc_destroy_buffers(&avcenc_context.misc_parameter_hrd_buf_id, 1);
@@ -990,6 +1055,71 @@ build_packed_seq_buffer(unsigned char **header_buffer)
return bs.bit_offset;
}
+static int
+build_packed_sei_buffer_timing(unsigned int init_cpb_removal_length,
+ unsigned int init_cpb_removal_delay,
+ unsigned int init_cpb_removal_delay_offset,
+ unsigned int cpb_removal_length,
+ unsigned int cpb_removal_delay,
+ unsigned int dpb_output_length,
+ unsigned int dpb_output_delay,
+ unsigned char **sei_buffer)
+{
+ unsigned char *byte_buf;
+ int bp_byte_size, i, pic_byte_size;
+
+ bitstream nal_bs;
+ bitstream sei_bp_bs, sei_pic_bs;
+
+ bitstream_start(&sei_bp_bs);
+ bitstream_put_ue(&sei_bp_bs, 0); /*seq_parameter_set_id*/
+ bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay, cpb_removal_length);
+ bitstream_put_ui(&sei_bp_bs, init_cpb_removal_delay_offset, cpb_removal_length);
+ if ( sei_bp_bs.bit_offset & 0x7) {
+ bitstream_put_ui(&sei_bp_bs, 1, 1);
+ }
+ bitstream_end(&sei_bp_bs);
+ bp_byte_size = (sei_bp_bs.bit_offset + 7) / 8;
+
+ bitstream_start(&sei_pic_bs);
+ bitstream_put_ui(&sei_pic_bs, cpb_removal_delay, cpb_removal_length);
+ bitstream_put_ui(&sei_pic_bs, dpb_output_delay, dpb_output_length);
+ if ( sei_pic_bs.bit_offset & 0x7) {
+ bitstream_put_ui(&sei_pic_bs, 1, 1);
+ }
+ bitstream_end(&sei_pic_bs);
+ pic_byte_size = (sei_pic_bs.bit_offset + 7) / 8;
+
+ bitstream_start(&nal_bs);
+ nal_start_code_prefix(&nal_bs);
+ nal_header(&nal_bs, NAL_REF_IDC_NONE, NAL_SEI);
+
+ /* Write the SEI buffer period data */
+ bitstream_put_ui(&nal_bs, 0, 8);
+ bitstream_put_ui(&nal_bs, bp_byte_size, 8);
+
+ byte_buf = (unsigned char *)sei_bp_bs.buffer;
+ for(i = 0; i < bp_byte_size; i++) {
+ bitstream_put_ui(&nal_bs, byte_buf[i], 8);
+ }
+ free(byte_buf);
+ /* write the SEI timing data */
+ bitstream_put_ui(&nal_bs, 0x01, 8);
+ bitstream_put_ui(&nal_bs, pic_byte_size, 8);
+
+ byte_buf = (unsigned char *)sei_pic_bs.buffer;
+ for(i = 0; i < pic_byte_size; i++) {
+ bitstream_put_ui(&nal_bs, byte_buf[i], 8);
+ }
+ free(byte_buf);
+
+ rbsp_trailing_bits(&nal_bs);
+ bitstream_end(&nal_bs);
+
+ *sei_buffer = (unsigned char *)nal_bs.buffer;
+
+ return nal_bs.bit_offset;
+}
#if 0
static void
@@ -1214,6 +1344,9 @@ encode_picture(FILE *yuv_fp, FILE *avc_fp,
/* picture parameter set */
avcenc_update_picture_parameter(slice_type, frame_num, display_num, is_idr);
+ if (avcenc_context.rate_control_method == VA_RC_CBR)
+ avcenc_update_sei_param(frame_num);
+
avcenc_render_picture();
ret = store_coded_buffer(avc_fp, slice_type);
@@ -1324,6 +1457,22 @@ static void avcenc_context_pic_param_init(VAEncPictureParameterBufferH264 *pic_p
pic_param->pic_fields.bits.deblocking_filter_control_present_flag = 1;
}
+static void avcenc_context_sei_init()
+{
+ int init_cpb_size;
+ int target_bit_rate;
+
+ /* it comes for the bps defined in SPS */
+ target_bit_rate = avcenc_context.seq_param.bits_per_second;
+ init_cpb_size = (target_bit_rate * 8) >> 10;
+ avcenc_context.i_initial_cpb_removal_delay = init_cpb_size * 0.5 * 1024 / target_bit_rate * 90000;
+
+ avcenc_context.i_cpb_removal_delay = 2;
+ avcenc_context.i_initial_cpb_removal_delay_length = 24;
+ avcenc_context.i_cpb_removal_delay_length = 24;
+ avcenc_context.i_dpb_output_delay_length = 24;
+}
+
static void avcenc_context_init(int width, int height)
{
int i;
@@ -1359,6 +1508,8 @@ static void avcenc_context_init(int width, int height)
avcenc_context.codedbuf_pb_size = 0;
avcenc_context.current_input_surface = SID_INPUT_PICTURE_0;
avcenc_context.upload_thread_value = -1;
+ avcenc_context.packed_sei_header_param_buf_id = VA_INVALID_ID;
+ avcenc_context.packed_sei_buf_id = VA_INVALID_ID;
if (qp_value == -1)
avcenc_context.rate_control_method = VA_RC_CBR;
@@ -1375,6 +1526,8 @@ static void avcenc_context_init(int width, int height)
avcenc_context_seq_param_init(&avcenc_context.seq_param, width, height);
avcenc_context_pic_param_init(&avcenc_context.pic_param);
+ if (avcenc_context.rate_control_method == VA_RC_CBR)
+ avcenc_context_sei_init();
}
int main(int argc, char *argv[])
--
1.7.12-rc1
More information about the Libva
mailing list