[Libva] [PATCH][AVCENC] Add the SEI segment for CBR mode to pass HRD test

Xiang, Haihao haihao.xiang at intel.com
Thu Sep 27 00:01:44 PDT 2012


Applied

Thanks
Haihao

> 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[])




More information about the Libva mailing list