H264解码之解析从Live555接收到的数据

Live555接收数据:数据解析、SEI解析: 


void RtspVideo::process(RtspCliSession::Type type, const std::string& codec, char* data, int size, void* pdatauser)
{
	unsigned char const start_code[4] = { 0x00, 0x00, 0x00, 0x01 };

	if (RtspCliSession::VIDEO == type)
	{   // ps video data
		if("MP2P" == codec)
		{
			m_st->m_len = size;
			memcpy(m_st->m_st_data, data, size);
			mPsParser->parse(m_st);
		}
		else if("H264" == codec)//H264 video data
		{
			{
				unsigned char* data_buf = NULL;
				if ((data[0] & 0x1F) == 6)
				{
					int nCount = 0;

					unsigned char buf[1602] = { 0 };
					int nType = 0;
					unsigned char * sei = (unsigned char *)(data + 1);
					nCount = size;
					int nsize = get_sei_buffer(sei, ((unsigned char*)data + size - sei), buf, &nCount, &nType);
					if (5 == nType)
					{
						int nSd_Type = buf[0];

						if (1 == nSd_Type)
						{
							unsigned int nSd_Num = buf[1];
							m_nNumSize = nSd_Num;

							//max 100
							if (m_nNumSize > 100)
							{
								m_nNumSize = 100;
							}

							if (nSd_Num > 0)
							{
								for (int i = 0; i < m_nNumSize; i++)
								{
									BYTE buffer[8];
									//解析人脸框坐标
									buffer[0] = buf[i * 16 + 2];
									buffer[1] = buf[i * 16 + 3];
									unsigned short number = (buffer[0] << 8) + buffer[1];
									m_pFaceInfo[i].face_x = number;

									buffer[2] = buf[i * 16 + 4];
									buffer[3] = buf[i * 16 + 5];
									number = (buffer[2] << 8) + buffer[3];
									m_pFaceInfo[i].face_y = number;

									buffer[4] = buf[i * 16 + 6];
									buffer[5] = buf[i * 16 + 7];
									number = (buffer[4] << 8) + buffer[5];
									m_pFaceInfo[i].face_w = number;

									buffer[6] = buf[i * 16 + 8];
									buffer[7] = buf[i * 16 + 9];
									number = (buffer[6] << 8) + buffer[7];
									m_pFaceInfo[i].face_h = number;

									//解析人员信息
									//buffer[8] = *buf++;
									m_pFaceInfo[i].usrSex = buf[i * 16 + 10];
									m_pFaceInfo[i].userAge = buf[i * 16 + 11];
									m_pFaceInfo[i].userHairstyle = buf[i * 16 + 12];
									m_pFaceInfo[i].userHat = buf[i * 16 + 13];
									m_pFaceInfo[i].userBrow = buf[i * 16 + 16];
									m_pFaceInfo[i].userGlasses = buf[i * 16 + 14];
									m_pFaceInfo[i].userMask = buf[i * 16 + 17];
									m_pFaceInfo[i].userRace = buf[i * 16 + 18];
								}	
							}
						}
					}
					
					return;
				}
				
				//m_nNumSize = 1;
				if (PassFrame(data[0]))
				{
					unsigned char type = data[0] & 0x1F;
					switch (type)
					{
					case 0x07:
					{
						memcpy(m_spsBuf, start_code, 4);
						m_spsSize = 4;

						memcpy(m_spsBuf + m_spsSize, data, size);

						m_spsSize += size;
					}
					break;
					case 0x08:
					{
						memcpy(m_spsBuf + m_spsSize, start_code, 4);

						m_spsSize += 4;

						memcpy(m_spsBuf + m_spsSize, data, size);

						m_spsSize += size;
					}
					break;
					default:
					{

						break;
					}
					}

					if (size >= SPS_BUF_SIZE)
					{
						data_buf = new unsigned char[size + sizeof(start_code) + 1];
						m_frameType = 0;
						memcpy(data_buf, start_code, sizeof(start_code));
						memcpy(data_buf + sizeof(start_code), data, size);
						m_VideoDecoder.decode_videostream(data_buf, size + sizeof(start_code), 1, 0, 0, 0, m_pFaceInfo, m_nNumSize);	

						m_nNumSize = 0;
						return;
					}
					return;
				}

				if (size < 4)
				{
					return;
				}
				bool bIsIFrame = IsIFrame(data[0]);

				//unsigned char const start_code[4] = { 0x00, 0x00, 0x00, 0x01 };

				if (bIsIFrame)
				{
					data_buf = new unsigned char[size + sizeof(start_code) + m_spsSize + 1];

					memcpy(data_buf, m_spsBuf, m_spsSize);
			
					memcpy((data_buf + m_spsSize), start_code, sizeof(start_code));
					memcpy((data_buf + sizeof(start_code) + m_spsSize), data, size);

					m_spsSize = 0;

					m_frameType = 1;
					m_VideoDecoder.decode_videostream(data_buf, (size + sizeof(start_code) + m_spsSize), 1, 0, 0, 0, m_pFaceInfo, m_nNumSize);
					{
						memset(m_spsBuf, 0, sizeof(SPS_BUF_SIZE));
					}

					m_nNumSize = 0;
				}
				else
				{
					data_buf = new unsigned char[size + sizeof(start_code) + 1];
					m_frameType = 0;
					memcpy(data_buf, start_code, sizeof(start_code));
					memcpy(data_buf + sizeof(start_code), data, size);
					m_VideoDecoder.decode_videostream(data_buf, size + sizeof(start_code), 1, 0, 0, 0, m_pFaceInfo, m_nNumSize);

					m_nNumSize = 0;
				}

				delete[]data_buf;
			}
		}
	}
	return ;
}

 SEI解析:

int get_sei_buffer(unsigned char * data, uint32_t size, unsigned char * buffer, int *count, int *nType)
{
	unsigned char * sei = data;
	int sei_type = 0;
	unsigned sei_size = 0;
	//payload type  
	do {
		sei_type += *sei;
		*nType = sei_type;
	} while (*sei++ == 255);
	//数据长度  
	do {
		sei_size += *sei;
	} while (*sei++ == 255);

	//检查UUID  
	static unsigned char uuid[] = { 0x73, 0x74, 0x64, 0x74, 0x73, 0x74, 0x64, 0x74, 0x73, 0x74, 0x64, 0x74, 0x73, 0x74, 0x64, 0x74 };

	if (sei_size >= UUID_SIZE && sei_size <= (data + size - sei) &&
		sei_type == 5 /*&& memcmp(sei, uuid, UUID_SIZE) == 0*/)
	{
		sei += UUID_SIZE;
		sei_size -= UUID_SIZE;

		if (buffer != NULL && count != NULL)
		{
			if (*count > (int)sei_size)
			{
				memcpy(buffer, sei, sei_size);
			}
		}

		*count = sei_size;

		return sei_size;
	}
	return -1;
}

关键帧解析:

bool RtspVideo::PassFrame(unsigned char c)
{
	int nal_type = c & 0x1F; 

	if (/*nal_type == 6 || */nal_type == 7 || nal_type == 8)
	{
		return true;
	}

	return false;
}

关键帧解析:

bool RtspVideo::IsIFrame(unsigned char c)
{
	int nal_type = c & 0x1F; 

	if (nal_type == 5)
	{
		return true;
	}

	return false;
}
原文地址:https://www.cnblogs.com/SunkingYang/p/11049142.html