RTP_h264解包源码

class CH264_RTP_UNPACK 

class CH264_RTP_UNPACK 

 

#define RTP_VERSION 2 

#define BUF_SIZE (1024 * 500) 

 

    typedef struct 

    { 

        //LITTLE_ENDIAN 

        unsigned short   cc:4;/* CSRC count                 */ 

        unsigned short   x:1;/* header extension flag      */ 

        unsigned short   p:1;/* padding flag               */ 

        unsigned short   v:2;/* packet type                */ 

        unsigned short   pt:7;/* payload type               */ 

        unsigned short   m:1;/* marker bit                 */ 

 

        unsigned short    seq;/* sequence number            */ 

        unsigned long     ts;/* timestamp                  */ 

        unsigned long     ssrc;/*synchronization source     */ 

    } rtp_hdr_t; 

public: 

 

    CH264_RTP_UNPACK ( HRESULT &hr, unsigned char H264PAYLOADTYPE = 96 ) 

        : m_bSPSFound(false) 

        , m_bWaitKeyFrame(true) 

        , m_bPrevFrameEnd(false) 

        , m_bAssemblingFrame(false) 

        , m_wSeq(1234) 

        , m_ssrc(0) 

    { 

        m_pBuf = new BYTE[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为H264 RTP视频数据包,nSize为RTP视频数据包字节长度,outSize为输出视频数据帧字节长度。 

//返回值为指向视频数据帧的指针。输入数据可能被破坏。 

    BYTE* Parse_RTP_Packet ( BYTE *pBuf, unsigned short nSize, int *outSize ) 

    { 

        if ( nSize <= 12 ) 

        { 

            return NULL ; 

        } 

        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 ; 

        DWORD PayloadSize = nSize - 12 ; 

 

        // Check the RTP version number (it should be 2): 

        if ( m_RTP_Header.v != RTP_VERSION ) 

        { 

            return NULL ; 

        } 

 

        /* 

        // Skip over any CSRC identifiers in the header: 

        if ( m_RTP_Header.cc ) 

        { 

            long cc = m_RTP_Header.cc * 4 ; 

            if ( Size < cc ) 

            { 

                return NULL ; 

            } 

 

            Size -= cc ; 

            p += cc ; 

        }

 

        // Check for (& ignore) any RTP header extension 

        if ( m_RTP_Header.x ) 

        { 

            if ( Size < 4 ) 

            { 

                return NULL ; 

            } 

 

            Size -= 4 ; 

            p += 2 ; 

            long l = p[0] ; 

            l <<= 8 ; 

            l |= p[1] ; 

            p += 2 ; 

            l *= 4 ; 

            if ( Size < l ) ; 

            { 

                return NULL ; 

            } 

            Size -= l ; 

            p += l ; 

        } 

        

        // Discard any padding bytes: 

        if ( m_RTP_Header.p ) 

        { 

            if ( Size == 0 ) 

            { 

                return NULL ; 

            } 

            long Padding = p[Size-1] ; 

            if ( Size < Padding ) 

            { 

                return NULL ; 

            } 

            Size -= Padding ; 

        }*/ 

 

        // Check the Payload Type. 

        if ( m_RTP_Header.pt != m_H264PAYLOADTYPE ) 

        { 

            return NULL ; 

        } 

 

        int PayloadType = pPayload[0] & 0x1f ; 

        int NALType = PayloadType ; 

        if ( NALType == 28 ) // FU_A 

        { 

            if ( PayloadSize < 2 ) 

            { 

                return NULL ; 

            } 

 

            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 ) 

        { 

            return NULL ; 

        } 

 

        if ( NALType == 0x07 || NALType == 0x08 ) // SPS PPS 

        { 

            m_wSeq = m_RTP_Header.seq ; 

            m_bPrevFrameEnd = true ; 

 

            pPayload -= 4 ; 

            *((DWORD*)(pPayload)) = 0x01000000 ; 

            *outSize = PayloadSize + 4 ; 

            return pPayload ; 

        } 

 

        if ( m_bWaitKeyFrame ) 

        { 

            if ( m_RTP_Header.m ) // frame end 

            { 

                m_bPrevFrameEnd = true ; 

                if ( !m_bAssemblingFrame ) 

                { 

                    m_wSeq = m_RTP_Header.seq ; 

                    return NULL ; 

                } 

            } 

 

            if ( !m_bPrevFrameEnd ) 

            { 

                m_wSeq = m_RTP_Header.seq ; 

                return NULL ; 

            } 

            else 

            { 

                if ( NALType != 0x05 ) // KEY FRAME 

                { 

                    m_wSeq = m_RTP_Header.seq ; 

                    m_bPrevFrameEnd = false ; 

                    return NULL ; 

                } 

            }

        }

        if ( m_RTP_Header.seq != (WORD)( m_wSeq + 1 ) )//lost packet 

        { 

            m_wSeq = m_RTP_Header.seq ; 

            SetLostPacket () ;            

            return NULL ; 

        } 

        else 

        { 

            // 码流正常 

            m_wSeq = m_RTP_Header.seq ; 

            m_bAssemblingFrame = true ; 

            

            if ( PayloadType != 28 ) // whole NAL 

            { 

                *((DWORD*)(m_pStart)) = 0x01000000 ; 

                m_pStart += 4 ; 

                m_dwSize += 4 ; 

            } 

            else // FU_A 

            { 

                if ( pPayload[1] & 0x80 ) // FU_A start 

                { 

                    *((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 // memory overflow 

            { 

                SetLostPacket () ; 

                return NULL ; 

            } 

 

            if ( m_RTP_Header.m ) // frame end 

            { 

                *outSize = m_dwSize ; 

 

                m_pStart = m_pBuf ; 

                m_dwSize = 0 ; 

 

               if ( NALType == 0x05 ) // KEY FRAME 

                { 

                    m_bWaitKeyFrame = false ; 

                } 

                return m_pBuf ; 

            } 

            else 

            { 

                return NULL ; 

            } 

        } 

    } 

 

    void SetLostPacket() 

    { 

        m_bSPSFound = false ; 

        m_bWaitKeyFrame = true ; 

        m_bPrevFrameEnd = false ; 

        m_bAssemblingFrame = false ; 

        m_pStart = m_pBuf ; 

        m_dwSize = 0 ; 

    } 

 

private: 

    rtp_hdr_t m_RTP_Header ; 

 

    BYTE *m_pBuf ; 

 

    bool m_bSPSFound ; 

    bool m_bWaitKeyFrame ; 

    bool m_bAssemblingFrame ; 

    bool m_bPrevFrameEnd ; 

    BYTE *m_pStart ; 

    BYTE *m_pEnd ; 

    DWORD m_dwSize ; 

 

    WORD m_wSeq ; 

 

    BYTE m_H264PAYLOADTYPE ; 

    DWORD m_ssrc ; 

}; 

 

// class CH264_RTP_UNPACK end 

 

//使用范例

HRESULT hr ; 

CH264_RTP_UNPACK unpack ( hr ) ; 

BYTE *pRtpData ; 

WORD inSize; 

int outSize ; 

BYTE *pFrame = unpack.Parse_RTP_Packet ( pRtpData, inSize, &outSize ) ; 

if ( pFrame != NULL ) 

// frame process 

// ... 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值