• 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;
    }
  • 相关阅读:
    Linux.NET学习手记(1)
    初识Entity Framework CodeFirst(3)
    初识Entity Framework CodeFirst(2)
    Linux.NET学习手记(3)
    Linux.NET学习手记(2)
    第四次博客作业结对项目
    [转]制作BlogWriter 博客客户端
    【整理】C# WinFrom 中如何txt内容与dataGridView互动
    将字符串给datetimepicker赋值
    (转)koograExcel文件读取利器的使用
  • 原文地址:https://www.cnblogs.com/SunkingYang/p/11049142.html
Copyright © 2020-2023  润新知