SDP的fmtp部分

之前做的SDP对于h264编码的视频没有做"a=fmtp"字段的解析,今天加上,主要是为了解析出视频的宽高信息。


RFC3984的8.2节对field做了介绍,这里只介绍sprop-parameter-sets字段的解码方法,因为我的主要目的是解析出视频宽高信息


该字段用BASE-64编码,因此,首先解码BASE-64,这里给出解码方法:


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 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;
}

其中返回值为解出的目标串的长度



然后,针对接触的字符串,它的第一个字节是个NUL头,我们希望它的NAL_TYPE为7,也就是序列参数集(sps)

针对该参数集,对照h.264文档的7.3.2.1对语法,我们希望解出pic_width_in_mbs_minus1字段和pic_height_in_map_units_minus1字段


这里遇到了一个问题,因为它是指数哥伦布编码,因此又需要解码:

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;

	//找到第一个1
	while(pBinaryArray[iter++] == 0)
	{
		NumOfZero++;
	}
	for (int i=NumOfZero-1; i>=0; i--)
	{
		INFO += pBinaryArray[iter++]<
其中,返回值是二进制字符串的偏移地址


因为指数哥伦布编码不定长的特性,我们需要解出整个SPS(依据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> 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

这样,就完成了目标,得到了视频信息的长和宽


你可能感兴趣的:(SDP,H264)