www.pudn.com > avs-m3.rar > sei.c
/*! ************************************************************************ * \file sei.c * \brief * Functions to implement SEI messages in decoder * \by liuhui 2005/03/20 liuhui@mail.ustc.edu.cn ************************************************************************ */ #include#include #include #include "global.h" #include "memalloc.h" #include "sei.h" #include "vlc.h" #include "header.h" #include "parset.h" #include "HRD.h" extern unsigned int seq_parameter_set_id; extern unsigned int cpb_dpb_cnt_minus1; extern unsigned int *cpb_underflow_allowable_flag; extern unsigned int *bit_rate_value_minus1_lsb; extern unsigned int *bit_rate_value_minus1_msb; extern unsigned int *cpb_size_value_minus1_lsb; extern unsigned int *cpb_size_value_minus1_msb; extern unsigned int *dpb_size_value_minus1_lsb; extern unsigned int *dpb_size_value_minus1_msb; extern unsigned int *initial_cpb_removal_delay_lsb; extern unsigned int *initial_cpb_removal_delay_msb; extern unsigned int *initial_cpb_removal_delay; extern unsigned int *initial_dpb_output_delay_lsb; extern unsigned int *initial_dpb_output_delay_msb; extern unsigned int *initial_dpb_output_delay; extern unsigned int *Bit_Buffer; extern unsigned int *ROT; extern struct DecodedPictureBuffer dpb; extern struct FrameBuffer outframe; extern struct FrameBuffer decframe; extern unsigned int outputtimer; extern int pre_picture_distance; /*! ************************************************************************ * \brief * Interpret the SEI rbsp * \param msg * a pointer that point to the sei message. * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void InterpretSEIMessage(byte* msg, int size, Image *img) { int payload_type = 0; int payload_size = 0; int offset = 1; //skip first NAL header byte #if TRACE fprintf(p_trace,"\n"); tracebits2("start_code_prefix",24,0x01); fprintf(p_trace,"ANNEX B NALU, len %d, forbidden_bit %d, nal_reference_idc %d, nal_unit_type %d,\n", nalu->len,nalu->forbidden_bit,nalu->nal_reference_idc,nalu->nal_unit_type); #endif #if TRACE tracebits2("SEI: NALU Header",8,nalu->buf[0]); #endif do { // sei_message(); payload_type = 0; while ( msg[offset++] == 0xFF) payload_type += 255; payload_type += msg[offset-1]; // this is the last byte payload_size = 0; while ( msg[offset++] == 0xFF) payload_size += 255; payload_size += msg[offset-1]; // this is the last byte switch ( payload_type ) // sei_payload( type, size ); { case SEI_USER_DATA: #if TRACE //liuhui 0601 tracebits2("SEI: UserData:PayloadType",8,payload_type); tracebits2("SEI: UserData:PayloadSize",8,payload_size); #endif interpret_user_data(msg+offset, payload_size, img ); break; case SEI_FULL_FRAME_FREEZE: #if TRACE //liuhui 0601 tracebits2("SEI: FullFrameFreeze:PayloadType",8,payload_type); tracebits2("SEI: FullFrameFreeze:PayloadSize",8,payload_size); #endif interpret_full_frame_freeze( msg+offset, payload_size, img ); break; case SEI_FULL_FRAME_FREEZE_RELEASE: #if TRACE //liuhui 0601 tracebits2("SEI: FullFrameFreezeRelease:PayloadType",8,payload_type); tracebits2("SEI: FullFrameFreezeRelease:PayloadSize",8,payload_size); #endif interpret_full_frame_freeze_release( msg+offset, payload_size, img ); break; case SEI_SCALABLE_LAYER_PROFILE_LEVEL: #if TRACE //liuhui 0601 tracebits2("SEI: ScalaLayerProfileLevel:PayloadType",8,payload_type); tracebits2("SEI: ScalaLayerProfileLevel:PayloadSize",8,payload_size); #endif interpret_scalable_layer_profile_level(msg+offset, payload_size, img ); break; #ifdef _HRD_ case SEI_HRD_BUFFERING_PARAMETERS: #if TRACE //liuhui 0601 tracebits2("SEI: HRDBufferParam:PayloadType",8,payload_type); tracebits2("SEI: HRDBufferParam:PayloadSize",8,payload_size); #endif interpret_hrd_buffering_parameters(msg+offset, payload_size, img ); break; #endif case SEI_GRADUAL_RANDOM_ACCESS: #if TRACE //liuhui 0601 tracebits2("SEI: GradualRandomAccess:PayloadType",8,payload_type); tracebits2("SEI: GradualRandomAccess:PayloadSize",8,payload_size); #endif interpret_gradual_random_access(msg+offset, payload_size, img ); break; default: #if TRACE //liuhui 0601 tracebits2("SEI: Reserved:PayloadType",8,payload_type); tracebits2("SEI: Reserved:PayloadSize",8,payload_size); #endif interpret_reserved( msg+offset, payload_size, img ); break; } offset += payload_size; }while( 0 ); } /*! ************************************************************************ * \brief * Interpret the User data SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer ************************************************************************ */ void interpret_user_data( byte* payload, int size, Image *img ) { byte uiUserData; int i; Bitstream *bitstream = AllocBitstream(); for(i = 0; i < size; i++) bitstream->streamBuffer[i] = payload[i]; bitstream->frame_bitoffset = 0; bitstream->bitstream_length = size; #ifdef PRINT_USER_DATA printf("----- USER_DATA SEI -----\n"); #endif for( i = 0; i < size*8/17; i++) { uiUserData = SEI_u_v(8, "UserData", bitstream); putchar(uiUserData); uiUserData = SEI_u_v(8, "UserData", bitstream); putchar(uiUserData); uiUserData = SEI_u_v(1, "market_bit", bitstream); } if(((size*8)%17) > 8) /*Zhan Ma*/ { uiUserData = SEI_u_v(8, "UserData", bitstream); putchar(uiUserData); } printf("\n"); #if TRACE //liuhui 0601 if( (size*8 - bitstream->frame_bitoffset) != 0 ) //read trailing_bits { i = size*8 - bitstream->frame_bitoffset; SEI_u_v(i, "SEI: trailing_bits", bitstream); } #endif } /*! ************************************************************************ * \brief * Interpret the Full-frame freeze SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_full_frame_freeze( byte* payload, int size, Image *img ) { //when this function executes, full frame freeze valids assert(size == 1); assert( *payload == 0x80 ); #if TRACE //liuhui 0601 tracebits2("SEI: trailing_bits",8,*payload); #endif #ifdef PRINT_FULL_FRAME_FREEZE printf("----- FULL_FRAME_FREEZE SEI -----\n"); #endif } /*! ************************************************************************ * \brief * Interpret the Full-frame freeze release SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_full_frame_freeze_release( byte* payload, int size, Image *img ) { assert(size == 1); assert(*payload == 0x80); #if TRACE //liuhui 0601 tracebits2("SEI: trailing_bits",8,*payload); #endif #ifdef PRINT_FULL_FRAME_FREEZE_RELEASE printf("----- FULL_FRAME_FREEZE_RELEASE SEI -----\n"); #endif } /*! ************************************************************************ * \brief * Interpret the Scalable layer profile level SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer ************************************************************************ */ void interpret_scalable_layer_profile_level(byte* payload, int size, Image *img ) { unsigned int ref_pic_profile_idc, ref_pic_level_idc; assert(size == 3); ref_pic_profile_idc = payload[0]; ref_pic_level_idc = payload[1]; #if TRACE //liuhui 0601 tracebits2("SEI: Profile_Idc",8,ref_pic_profile_idc); tracebits2("SEI: Level_Idc",8,ref_pic_level_idc); tracebits2("SEI: trailing_bits",8,payload[2]); #endif #ifdef PRINT_SCALABLE_LAYER_PROFILE_LEVEL printf("----- SCALABLE_LAYER_PROFILE_LEVEL SEI -----\n"); printf("Ref_pic_profile_idc: %d\n", ref_pic_profile_idc ); printf("Ref_pic_level_idc : %d\n", ref_pic_level_idc ); #endif } #ifdef _HRD_ //BUG_FIX liuhui 0512 /*! ************************************************************************ * \brief * Interpret the HRD buffering parameters SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer ************************************************************************ */ void interpret_hrd_buffering_parameters(byte* payload, int size, Image *img ) { // unsigned int bit_rate,cpb_size,dpb_size,initCpbDelay,initDpbDelay;//guoyi BUG_FIX 01/06 unsigned int HrdIdx; int i; Bitstream *bitstream = AllocBitstream(); for(i = 0; i < size; i++) bitstream->streamBuffer[i] = payload[i]; bitstream->frame_bitoffset = 0; bitstream->bitstream_length = size; //#define _PRINT_ seq_parameter_set_id = SEI_ue_v("seq_parameter_set_id", bitstream); cpb_dpb_cnt_minus1 = SEI_ue_v("cpb_dpb_cnt_minus1", bitstream); init_hrd(cpb_dpb_cnt_minus1 + 1); #ifdef _PRINT_ printf("\n\n----------HRD SEI informations----------\n"); printf("seq_parameter_set_id :%d\n",seq_parameter_set_id); printf("cpb_dpb_cnt_minus1 :%d\n", cpb_dpb_cnt_minus1 ); #endif for(HrdIdx = 0; HrdIdx < cpb_dpb_cnt_minus1 + 1; HrdIdx++) { cpb_underflow_allowable_flag[HrdIdx] = SEI_u_1("cpb_underflow_allowable_flag[HrdIdx]", bitstream); bit_rate_value_minus1_lsb[HrdIdx] = SEI_ue_v("bit_rate_value_minus1_lsb[HrdIdx]", bitstream); SEI_u_v(1, "marker_bit", bitstream ); bit_rate_value_minus1_msb[HrdIdx] = SEI_ue_v("bit_rate_value_minus1_msb[HrdIdx]", bitstream); SEI_u_v(1, "marker_bit", bitstream ); cpb_size_value_minus1_lsb[HrdIdx] = SEI_ue_v("cpb_size_value_minus1_lsb[HrdIdx]", bitstream); SEI_u_v(1, "marker_bit", bitstream ); cpb_size_value_minus1_msb[HrdIdx] = SEI_ue_v("cpb_size_value_minus1_msb[HrdIdx]", bitstream); SEI_u_v(1, "marker_bit", bitstream ); dpb_size_value_minus1_lsb[HrdIdx] = SEI_ue_v("dpb_size_value_minus1_lsb[HrdIdx]", bitstream); SEI_u_v(1, "marker_bit", bitstream ); dpb_size_value_minus1_msb[HrdIdx] = SEI_ue_v("dpb_size_value_minus1_msb[HrdIdx]", bitstream); SEI_u_v(1, "marker_bit", bitstream ); if( sps->initial_cpb_removal_delay_length > 16 ) { initial_cpb_removal_delay_lsb[HrdIdx] = SEI_u_v(16, "initial_cpb_removal_delay_lsb[HrdIdx]", bitstream); SEI_u_v( 1, "marker_bit", bitstream ); initial_cpb_removal_delay_msb[HrdIdx] = SEI_u_v(sps->initial_cpb_removal_delay_length-16, "initial_cpb_removal_delay_msb[HrdIdx]", bitstream); } else initial_cpb_removal_delay[HrdIdx] = SEI_u_v(sps->initial_cpb_removal_delay_length, "initial_cpb_removal_delay [HrdIdx]", bitstream); SEI_u_v( 1, "marker_bit", bitstream ); if( sps->initial_dpb_output_delay_length > 16 ) { initial_dpb_output_delay_lsb [HrdIdx] = SEI_u_v(16, "initial_dpb_output_delay_lsb[HrdIdx]", bitstream); SEI_u_v( 1, "marker_bit", bitstream ); initial_dpb_output_delay_msb [HrdIdx] = SEI_u_v(sps->initial_dpb_output_delay_length-16, "initial_dpb_output_delay_msb[HrdIdx]", bitstream); } else initial_dpb_output_delay [HrdIdx] = SEI_u_v(sps->initial_dpb_output_delay_length, "initial_dpb_output_delay [HrdIdx]", bitstream); SEI_u_v( 1, "marker_bit", bitstream ); #if TRACE //liuhui 0601 if( HrdIdx == cpb_dpb_cnt_minus1 ) //read trailing_bits { i = size*8-bitstream->frame_bitoffset; assert(i); SEI_u_v( i, "SEI: trailing_bits", bitstream); } #endif #ifdef PRINT_HRD printf("\nHrdIdx = %d :\n",HrdIdx); printf("cpb_underflow_allowable_flag[HrdIdx] :%d\n",cpb_underflow_allowable_flag[HrdIdx]); printf("bit_rate_value_minus1_lsb[HrdIdx] :%d\n",bit_rate_value_minus1_lsb[HrdIdx]); printf("bit_rate_value_minus1_msb[HrdIdx] :%d\n",bit_rate_value_minus1_msb[HrdIdx]); printf("cpb_size_value_minus1_lsb[HrdIdx] :%d\n",cpb_size_value_minus1_lsb[HrdIdx]); printf("cpb_size_value_minus1_msb[HrdIdx] :%d\n",cpb_size_value_minus1_msb[HrdIdx]); printf("dpb_size_value_minus1_lsb[HrdIdx] :%d\n",dpb_size_value_minus1_lsb[HrdIdx]); printf("dpb_size_value_minus1_msb[HrdIdx] :%d\n",dpb_size_value_minus1_msb[HrdIdx]); if(sps->initial_cpb_removal_delay_length>16) { printf("initial_cpb_removal_delay_lsb[HrdIdx] :%d\n",initial_cpb_removal_delay_lsb[HrdIdx]); printf("initial_cpb_removal_delay_msb[HrdIdx] :%d\n",initial_cpb_removal_delay_msb[HrdIdx]); } else printf("initial_cpb_removal_delay[HrdIdx] :%d\n",initial_cpb_removal_delay[HrdIdx]); if(sps->initial_dpb_output_delay_length>16) { printf("initial_dpb_output_delay_lsb[HrdIdx] :%d\n",initial_dpb_output_delay_lsb[HrdIdx]); printf("initial_dpb_output_delay_msb[HrdIdx] :%d\n",initial_dpb_output_delay_msb[HrdIdx]); } else printf("initial_dpb_output_delay[HrdIdx] :%d\n",initial_dpb_output_delay[HrdIdx]); bit_rate=(bit_rate_value_minus1_lsb[HrdIdx]+1+(bit_rate_value_minus1_msb[HrdIdx]<<16))<<(6+sps->bit_rate_scale); cpb_size=(cpb_size_value_minus1_lsb[HrdIdx]+1+(cpb_size_value_minus1_msb[HrdIdx]<<16))<<(4+sps->cpb_size_scale); dpb_size=(dpb_size_value_minus1_lsb[HrdIdx]+1+(dpb_size_value_minus1_msb[HrdIdx]<<16))<<(4+sps->dpb_size_scale); if( sps->initial_cpb_removal_delay_length > 16 ) { initCpbDelay=initial_cpb_removal_delay_lsb[HrdIdx]+(initial_cpb_removal_delay_msb[HrdIdx]<<16); } else { initCpbDelay=initial_cpb_removal_delay_lsb[HrdIdx]; } if( sps->initial_dpb_output_delay_length > 16 ) { initDpbDelay=initial_dpb_output_delay_lsb[HrdIdx]+(initial_dpb_output_delay_msb[HrdIdx]<<16); } else { initDpbDelay=initial_dpb_output_delay_lsb[HrdIdx]; } fprintf(p_trace,"\nHrdIdx=%d :\n",HrdIdx); fprintf(p_trace,"bit_rate :%d\n",bit_rate); fprintf(p_trace,"cpb_size :%d\n",cpb_size); fprintf(p_trace,"dpb_size :%d\n",dpb_size); fprintf(p_trace,"initCpbDelay(1/90000 s) :%d\n",initCpbDelay); #endif #ifdef _PRINT_ printf("\nHrdIdx = %d :\n",HrdIdx); printf("cpb_underflow_allowable_flag[HrdIdx] :%d\n",cpb_underflow_allowable_flag[HrdIdx]); printf("bit_rate_value_minus1[HrdIdx] :%d\n",bit_rate_value_minus1[HrdIdx]); printf("cpb_size_value_minus1[HrdIdx] :%d\n",cpb_size_value_minus1[HrdIdx]); printf("dpb_size_value_minus1[HrdIdx] :%d\n",dpb_size_value_minus1[HrdIdx]); printf("initial_cpb_removal_delay[HrdIdx] :%d\n",initial_cpb_removal_delay[HrdIdx]); printf("initial_dpb_output_delay[HrdIdx] :%d\n\n",initial_dpb_output_delay[HrdIdx]); #endif } free(bitstream->streamBuffer); free(bitstream); } #endif //_HRD_ /*! ************************************************************************ * \brief * Interpret the gradual random access SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_gradual_random_access( byte* payload, int size, Image *img ) { int i, recovery_frame_cnt; Bitstream *bitstream = AllocBitstream(); for(i = 0; i < size; i++) bitstream->streamBuffer[i] = payload[i]; bitstream->frame_bitoffset = 0; bitstream->bitstream_length = size; recovery_frame_cnt = SEI_ue_v("recovery_frame_cnt", bitstream ); assert( recovery_frame_cnt <= 31 && recovery_frame_cnt >= 0 ); #if TRACE //liuhui 0601 { i = size*8 - bitstream->frame_bitoffset; assert(i); SEI_u_v(i, "SEI: trailing_bits", bitstream); } #endif printf("----- GRADUAL_RANDOM_ACCESS SEI -----\n"); printf("recovery_frame_cnt = %d\n", recovery_frame_cnt); printf("\n"); } /*! ************************************************************************ * \brief * Interpret the Reserved SEI message * \param payload * a pointer that point to the sei payload * \param size * the size of the sei message * \param img * the image pointer * ************************************************************************ */ void interpret_reserved( byte* payload, int size, Image *img ) { byte uiReserved; int i; Bitstream *bitstream = AllocBitstream(); for(i = 0; i < size; i++) bitstream->streamBuffer[i] = payload[i]; bitstream->frame_bitoffset = 0; bitstream->bitstream_length = size; #ifdef PRINT_RESERVED printf("----- RESERVED SEI -----\n"); #endif for( i = 0; i < size*8/17; i++) { uiReserved = SEI_u_v(8, "Reserved byte", bitstream); putchar(uiReserved); uiReserved = SEI_u_v(8, "Reserved byte", bitstream); putchar(uiReserved); uiReserved = SEI_u_v(1, "market_bit", bitstream); } if(((size*8)%17) > 8) { uiReserved = SEI_u_v(8, "Reserved byte", bitstream); putchar(uiReserved); } printf("\n"); #if TRACE { i = 8*size - bitstream->frame_bitoffset; assert(i); SEI_u_v(i, "SEI: trailing_bits", bitstream); } #endif } /*! ************************************************************************ * \brief * SEI coding function like GetVLCSymbol(),different only at writing bitstream * \param info * refer to param in GetVLCSymbol() * \param bitstream * store the coded bit-stream of SEI ************************************************************************ */ int SEI_GetVLCSymbol (int *info, Bitstream *bitstream) { register int inf; long byteoffset; // byte from start of buffer int bitoffset; // bit from start of byte int ctr_bit=0; // control bit for current bit posision int bitcounter=1; int len; int info_bit; byte *buffer = bitstream->streamBuffer; int bytecount = bitstream->bitstream_length; int totbitoffset = bitstream->frame_bitoffset; byteoffset= totbitoffset/8; bitoffset= 7-(totbitoffset%8); ctr_bit = (buffer[byteoffset] & (0x01< bytecount) { error("parse error", -1); return -1; } inf=(inf<<1); if(buffer[byteoffset] & (0x01<<(bitoffset))) inf |=1; } *info = inf; bitstream->frame_bitoffset += bitcounter; return bitcounter; // return absolute offset in bit from start of frame } /*! ************************************************************************ * \brief * SEI coding function like read_VLC(),different only at writing bitstream * \param info * refer to param in read_VLC() * \param bitstream * store the coded bit-stream of SEI ************************************************************************ */ int SEI_read_VLC(SyntaxElement *sym, Bitstream *bitstream) { int frame_bitoffset = bitstream->frame_bitoffset; byte *buf = bitstream->streamBuffer; int BitstreamLengthInBytes = bitstream->bitstream_length; sym->len = SEI_GetVLCSymbol (&(sym->inf), bitstream); if (sym->len == -1) return -1; sym->mapping(sym->len,sym->inf,&(sym->value1)); #if TRACE //liuhui 0601 tracebits(sym->tracestring, sym->len, sym->inf, sym->value1); #endif return 1; } /*! ************************************************************************ * \brief * SEI coding function like read_FLC(),different only at writing bitstream * \param info * refer to param in read_FLC() * \param bitstream * store the coded bit-stream of SEI ************************************************************************ */ int SEI_read_FLC(SyntaxElement *sym, Bitstream *bitstream) { int frame_bitoffset = bitstream->frame_bitoffset; byte *buf = bitstream->streamBuffer; int BitstreamLengthInBytes = bitstream->bitstream_length; if ((GetBits(buf, frame_bitoffset, &(sym->inf), BitstreamLengthInBytes, sym->len)) < 0) return -1; bitstream->frame_bitoffset += sym->len; // move bitstream pointer sym->value1 = sym->inf; #if TRACE //liuhui 0601 tracebits2(sym->tracestring, sym->len, sym->inf); #endif return 1; } /*! ************************************************************************ * \brief * SEI coding function like ue_v(),different only at writing bitstream * \param info * refer to param in ue_v() * \param bitstream * store the coded bit-stream of SEI ************************************************************************ */ int SEI_ue_v(char *tracestring, Bitstream *bitstream) { SyntaxElement symbol, *sym=&symbol; assert (bitstream->streamBuffer != NULL); sym->mapping = mapping_ue; // Mapping rule #if TRACE strncpy(sym->tracestring,tracestring,TRACESTRING_SIZE); #endif SEI_read_VLC (sym, bitstream); return sym->value1; } /*! ************************************************************************ * \brief * SEI coding function like u_v(),different only at writing bitstream * \param info * refer to param in u_v() * \param bitstream * store the coded bit-stream of SEI ************************************************************************ */ int SEI_u_v(int LenInBits, char* tracestring, Bitstream *bitstream) { SyntaxElement symbol, *sym=&symbol; assert (bitstream->streamBuffer != NULL); //sym->type = SE_HEADER; sym->mapping = mapping_ue; // Mapping rule sym->len = LenInBits; #if TRACE strncpy(sym->tracestring, tracestring, TRACESTRING_SIZE); #endif SEI_read_FLC (sym, bitstream); return sym->inf; } /*! ************************************************************************ * \brief * SEI coding function like u_1(),different only at writing bitstream * \param info * refer to param in u_1() * \param bitstream * store the coded bit-stream of SEI ************************************************************************ */ int SEI_u_1 (char *tracestring, Bitstream *bitstream) { return SEI_u_v (1, tracestring, bitstream); }