The previous SDP did not parse the "A = fmtp" field for the h264 encoded video. Today, it is added to parse the width and height of the video.
In section 8.2 of rfc3984, field is introduced. Here we only decode the sprop-parameter-sets field, because my main purpose is to parse the video width and height information.
This field is encoded with base-64. Therefore, the base-64 is decoded first. The decoding method is provided here:
long CBase64::Decode(const char *pSrc, long srcLen, unsigned char *pDest, long destLen){int i = 0;int iCnt = 0;unsigned char * p = pDest;for (i=0; i<srcLen; i++){if (pSrc[i] > 127){continue;}if (pSrc[i] == '='){return p-pDest+1;}unsigned char a = Base64IdxTab[pSrc[i]];if (a == 255){continue;}switch (iCnt){case 0:{*p = a << 2;iCnt++;}break;case 1:{*p++ |= a >> 4;*p = a << 4;iCnt++;}break;case 2:{*p++ |= a >> 2;*p = a << 6;iCnt++;}break;case 3:{*p++ |= a;iCnt = 0;}break;} }*p = 0x00;return p-pDest;}
The return value is the length of the target string.
Then, for the contact string, its first byte is a NUL header. We want its nal_type to be 7, that is, the sequential parameter set (SPS)
For this parameter set, we want to solve the pic_width_in_mbs_minus1 field and pic_height_in_map_units_minus1 field in accordance with the 7.3.2.1 Syntax of H.264.
Here we have encountered a problem because it is an exponential Columbus code and therefore needs to be decoded:
Int golombdecode (bool * pbinaryarray, Int & des) {If (pbinaryarray = NULL) {return-1;} int iter = 0; int numofzero = 0; int m_bit = 0; int info = 0; double result; // find the first 1 while (pbinaryarray [iter ++] = 0) {numofzero ++;} For (INT I = NumOfZero-1; i> = 0; I --) {info + = pbinaryarray [iter ++] <I;} result = POW (double) 2, (double) numofzero) + Info-1; des = result; return ITER ;}
The return value is the offset address of the binary string.
Because of the Variable Length of the exponential Columbus code, we need to work out the entire SPS (based on ITU-T h264 7.3.2.1.1 ):
int ParseSPS(unsigned char *pSrc, unsigned long SrcLen, unsigned long &VideoWidth, unsigned long &VideoHeight){int ret = 0;unsigned long offset = 0;bool *pBinaryArray = new bool[SrcLen*8];unsigned long iter = 0;unsigned char mask = 0x80;for (int i=0; i<SrcLen; i++){mask = 0x80;for (int j=0; j<8; j++){if (pSrc[i] & (mask >> j)){pBinaryArray[iter] = 1;}else{pBinaryArray[iter] = 0;}iter++;}}iter = 0;unsigned char profile_idc = *pSrc;int seq_parameter_set_id;offset = 24;ret = GolombDecode(pBinaryArray+offset, seq_parameter_set_id);offset += ret;if (profile_idc == 100 || profile_idc == 110 || profile_idc == 122 || profile_idc == 144){int chroma_format_idc;ret = GolombDecode(pBinaryArray+offset, chroma_format_idc);offset += ret;if(chroma_format_idc == 3){offset += 1;}int bit_depth_luma_minus8, bit_depth_chroma_minus8;ret = GolombDecode(pBinaryArray+offset, bit_depth_luma_minus8);offset += ret;ret = GolombDecode(pBinaryArray+offset, bit_depth_chroma_minus8);offset += ret;offset += 2;bool seq_scaling_matrix_present_flag = pBinaryArray[offset];if (seq_scaling_matrix_present_flag){offset += 1;}}int log2_max_frame_num_minus4, pic_order_cnt_type;ret = GolombDecode(pBinaryArray+offset, log2_max_frame_num_minus4);offset += ret;ret = GolombDecode(pBinaryArray+offset, pic_order_cnt_type);offset += ret;if (pic_order_cnt_type == 0){int log2_max_pic_order_cnt_lsb_minus4;ret = GolombDecode(pBinaryArray+offset, pic_order_cnt_type);offset += ret;}else if (pic_order_cnt_type == 1){offset += 1;int offset_for_non_ref_pic, offset_for_top_to_bottom_field, num_ref_frames_in_pic_order_cnt_cycle, offset_for_ref_frame;ret = GolombDecode(pBinaryArray+offset, offset_for_non_ref_pic);offset += ret;ret = GolombDecode(pBinaryArray+offset, offset_for_top_to_bottom_field);offset += ret;ret = GolombDecode(pBinaryArray+offset, num_ref_frames_in_pic_order_cnt_cycle);offset += ret;for (int i=0; i<num_ref_frames_in_pic_order_cnt_cycle ;i++){ret = GolombDecode(pBinaryArray+offset, offset_for_ref_frame);offset += ret;}}int num_ref_frames;ret = GolombDecode(pBinaryArray+offset, num_ref_frames);offset += ret;offset += 1;int pic_width_in_mbs_minus1, pic_height_in_map_units_minus1;ret = GolombDecode(pBinaryArray+offset, pic_width_in_mbs_minus1);offset += ret;ret = GolombDecode(pBinaryArray+offset, pic_height_in_map_units_minus1);offset += ret;VideoWidth = (pic_width_in_mbs_minus1 + 1) * 16;VideoHeight = (pic_height_in_map_units_minus1 + 1) * 16;delete []pBinaryArray;pBinaryArray = NULL;return 0;}
In this way, the target is achieved, and the length and width of the video information are obtained.