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