//// classCH264_RTP_UNPACK
classCH264_RTP_UNPACK
{
#defineRTP_VERSION2
#defineBUF_SIZE(1024*500)
typedefstruct
{
//LITTLE_ENDIAN
unsignedshortcc:4;/*CSRCcount*/
unsignedshortx:1;/*headerextensionflag*/
unsignedshortp:1;/*paddingflag*/
unsignedshortv:2;/*packettype*/
unsignedshortpt:7;/*payloadtype*/
unsignedshortm:1;/*markerbit*/
unsignedshortseq;/*sequencenumber*/
unsignedlongts;/*timestamp*/
unsignedlongssrc;/*synchronizationsource*/
}rtp_hdr_t;
public:
CH264_RTP_UNPACK(HRESULT&hr,unsignedcharH264PAYLOADTYPE=96)
:m_bSPSFound(false)
,m_bWaitKeyFrame(true)
,m_bPrevFrameEnd(false)
,m_bAssemblingFrame(false)
,m_wSeq(1234)
,m_ssrc(0)
{
m_pBuf=newBYTE[BUF_SIZE];
if(m_pBuf==NULL)
{
hr=E_OUTOFMEMORY;
return;
}
m_H264PAYLOADTYPE=H264PAYLOADTYPE;
m_pEnd=m_pBuf+BUF_SIZE;
m_pStart=m_pBuf;
m_dwSize=0;
hr=S_OK;
}
~CH264_RTP_UNPACK(void)
{
delete[]m_pBuf;
}
//pBuf为H264RTP视频数据包,nSize为RTP视频数据包字节长度,outSize为输出视频数据帧字节长度。
//返回值为指向视频数据帧的指针。输入数据可能被破坏。
BYTE*Parse_RTP_Packet(BYTE*pBuf,unsignedshortnSize,int*outSize)
{
if(nSize<=12)
{
returnNULL;
}
BYTE*cp=(BYTE*)&m_RTP_Header;
cp[0]=pBuf[0];
cp[1]=pBuf[1];
m_RTP_Header.seq=pBuf[2];
m_RTP_Header.seq<<=8;
m_RTP_Header.seq|=pBuf[3];
m_RTP_Header.ts=pBuf[4];
m_RTP_Header.ts<<=8;
m_RTP_Header.ts|=pBuf[5];
m_RTP_Header.ts<<=8;
m_RTP_Header.ts|=pBuf[6];
m_RTP_Header.ts<<=8;
m_RTP_Header.ts|=pBuf[7];
m_RTP_Header.ssrc=pBuf[8];
m_RTP_Header.ssrc<<=8;
m_RTP_Header.ssrc|=pBuf[9];
m_RTP_Header.ssrc<<=8;
m_RTP_Header.ssrc|=pBuf[10];
m_RTP_Header.ssrc<<=8;
m_RTP_Header.ssrc|=pBuf[11];
BYTE*pPayload=pBuf+12;
DWORDPayloadSize=nSize-12;
//ChecktheRTPversionnumber(itshouldbe2):
if(m_RTP_Header.v!=RTP_VERSION)
{
returnNULL;
}
/*
//SkipoveranyCSRCidentifiersintheheader:
if(m_RTP_Header.cc)
{
longcc=m_RTP_Header.cc*4;
if(Size<cc)
{
returnNULL;
}
Size-=cc;
p+=cc;
}
//Checkfor(&ignore)anyRTPheaderextension
if(m_RTP_Header.x)
{
if(Size<4)
{
returnNULL;
}
Size-=4;
p+=2;
longl=p[0];
l<<=8;
l|=p[1];
p+=2;
l*=4;
if(Size<l);
{
returnNULL;
}
Size-=l;
p+=l;
}
//Discardanypaddingbytes:
if(m_RTP_Header.p)
{
if(Size==0)
{
returnNULL;
}
longPadding=p[Size-1];
if(Size<Padding)
{
returnNULL;
}
Size-=Padding;
}*/
//CheckthePayloadType.
if(m_RTP_Header.pt!=m_H264PAYLOADTYPE)
{
returnNULL;
}
intPayloadType=pPayload[0]&0x1f;
intNALType=PayloadType;
if(NALType==28)//FU_A
{
if(PayloadSize<2)
{
returnNULL;
}
NALType=pPayload[1]&0x1f;
}
if(m_ssrc!=m_RTP_Header.ssrc)
{
m_ssrc=m_RTP_Header.ssrc;
SetLostPacket();
}
if(NALType==0x07)//SPS
{
m_bSPSFound=true;
}
if(!m_bSPSFound)
{
returnNULL;
}
if(NALType==0x07||NALType==0x08)//SPSPPS
{
m_wSeq=m_RTP_Header.seq;
m_bPrevFrameEnd=true;
pPayload-=4;
*((DWORD*)(pPayload))=0x01000000;
*outSize=PayloadSize+4;
returnpPayload;
}
if(m_bWaitKeyFrame)
{
if(m_RTP_Header.m)//frameend
{
m_bPrevFrameEnd=true;
if(!m_bAssemblingFrame)
{
m_wSeq=m_RTP_Header.seq;
returnNULL;
}
}
if(!m_bPrevFrameEnd)
{
m_wSeq=m_RTP_Header.seq;
returnNULL;
}
else
{
if(NALType!=0x05)//KEYFRAME
{
m_wSeq=m_RTP_Header.seq;
m_bPrevFrameEnd=false;
returnNULL;
}
}
}
if(m_RTP_Header.seq!=(WORD)(m_wSeq+1))//lostpacket
{
m_wSeq=m_RTP_Header.seq;
SetLostPacket();
returnNULL;
}
else
{
//码流正常
m_wSeq=m_RTP_Header.seq;
m_bAssemblingFrame=true;
if(PayloadType!=28)//wholeNAL
{
*((DWORD*)(m_pStart))=0x01000000;
m_pStart+=4;
m_dwSize+=4;
}
else//FU_A
{
if(pPayload[1]&0x80)//FU_Astart
{
*((DWORD*)(m_pStart))=0x01000000;
m_pStart+=4;
m_dwSize+=4;
pPayload[1]=(pPayload[0]&0xE0)|NALType;
pPayload+=1;
PayloadSize-=1;
}
else
{
pPayload+=2;
PayloadSize-=2;
}
}
if(m_pStart+PayloadSize<m_pEnd)
{
CopyMemory(m_pStart,pPayload,PayloadSize);
m_dwSize+=PayloadSize;
m_pStart+=PayloadSize;
}
else//memoryoverflow
{
SetLostPacket();
returnNULL;
}
if(m_RTP_Header.m)//frameend
{
*outSize=m_dwSize;
m_pStart=m_pBuf;
m_dwSize=0;
if(NALType==0x05)//KEYFRAME
{
m_bWaitKeyFrame=false;
}
returnm_pBuf;
}
else
{
returnNULL;
}
}
}
voidSetLostPacket()
{
m_bSPSFound=false;
m_bWaitKeyFrame=true;
m_bPrevFrameEnd=false;
m_bAssemblingFrame=false;
m_pStart=m_pBuf;
m_dwSize=0;
}
private:
rtp_hdr_tm_RTP_Header;
BYTE*m_pBuf;
boolm_bSPSFound;
boolm_bWaitKeyFrame;
boolm_bAssemblingFrame;
boolm_bPrevFrameEnd;
BYTE*m_pStart;
BYTE*m_pEnd;
DWORDm_dwSize;
WORDm_wSeq;
BYTEm_H264PAYLOADTYPE;
DWORDm_ssrc;
};
//classCH264_RTP_UNPACKend
//使用范例
HRESULThr;
CH264_RTP_UNPACKunpack(hr);
BYTE*pRtpData;
WORDinSize;
intoutSize;
BYTE*pFrame=unpack.Parse_RTP_Packet(pRtpData,inSize,&outSize);
if(pFrame!=NULL)
{
//frameprocess
//...
}