RTP_h264打包源码

class CH264_RTP_PACK 

    #define RTP_VERSION 2

    typedef struct NAL_msg_s 

    { 

        bool eoFrame ; 

        unsigned char type;// NAL type 

        unsigned char *start;// pointer to first location in the send buffer 

        unsigned char *end;// pointer to last location in send buffer 

        unsigned long size ; 

    } NAL_MSG_t;

    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; 

 

    typedef struct tagRTP_INFO 

    { 

        NAL_MSG_t    nal;   // NAL information 

        rtp_hdr_t    rtp_hdr;// RTP header is assembled here 

        int hdr_len;// length of RTP header 

 

        unsigned char *pRTP;// pointer to where RTP packet has beem assembled 

        unsigned char *start;// pointer to start of payload 

        unsigned char *end; // pointer to end of payload 

 

        unsigned int s_bit; // bit in the FU header 

        unsigned int e_bit; // bit in the FU header 

        bool FU_flag;        // fragmented NAL Unit flag 

    } RTP_INFO; 

 

public: 

    CH264_RTP_PACK(unsigned long H264SSRC, unsigned char H264PAYLOADTYPE=96

, unsigned short MAXRTPPACKSIZE=1472 ) 

    { 

        m_MAXRTPPACKSIZE = MAXRTPPACKSIZE ; 

        if ( m_MAXRTPPACKSIZE > 10000 ) 

        { 

            m_MAXRTPPACKSIZE = 10000 ; 

        } 

        if ( m_MAXRTPPACKSIZE < 50 ) 

        { 

            m_MAXRTPPACKSIZE = 50 ; 

        } 

        

        memset ( &m_RTP_Info, 0, sizeof(m_RTP_Info) ) ; 

 

        m_RTP_Info.rtp_hdr.pt = H264PAYLOADTYPE ; 

        m_RTP_Info.rtp_hdr.ssrc = H264SSRC ; 

        m_RTP_Info.rtp_hdr.v = RTP_VERSION ; 

 

        m_RTP_Info.rtp_hdr.seq = 0 ; 

    } 

 

    ~CH264_RTP_PACK(void) 

    { 

    } 

 

//传入Set的数据必须是一个完整的NAL,起始码为0x00000001。 

//起始码之前至少预留10个字节,以避免内存COPY操作。 

//打包完成后,原缓冲区内的数据被破坏。 

    bool Set ( unsigned char *NAL_Buf, unsigned long NAL_Size

, unsigned long Time_Stamp, bool End_Of_Frame ) 

    { 

        unsigned long startcode = StartCode(NAL_Buf) ; 

        

        if ( startcode != 0x01000000 ) 

        { 

            return false ; 

        } 

 

        int type = NAL_Buf[4] & 0x1f ; 

        if ( type < 1 || type > 12 ) 

        { 

            return false ; 

        } 

 

        m_RTP_Info.nal.start = NAL_Buf ; 

        m_RTP_Info.nal.size = NAL_Size ; 

        m_RTP_Info.nal.eoFrame = End_Of_Frame ; 

        m_RTP_Info.nal.type = m_RTP_Info.nal.start[4] ; 

        m_RTP_Info.nal.end = m_RTP_Info.nal.start + m_RTP_Info.nal.size ; 

 

        m_RTP_Info.rtp_hdr.ts = Time_Stamp ; 

 

        m_RTP_Info.nal.start += 4 ;    // skip the syncword 

                                    

        if ( (m_RTP_Info.nal.size + 7) > m_MAXRTPPACKSIZE ) 

        { 

            m_RTP_Info.FU_flag = true ; 

            m_RTP_Info.s_bit = 1 ; 

            m_RTP_Info.e_bit = 0 ; 

 

            m_RTP_Info.nal.start += 1 ;    // skip NAL header 

        } 

        else 

        { 

            m_RTP_Info.FU_flag = false ; 

            m_RTP_Info.s_bit = m_RTP_Info.e_bit = 0 ; 

        } 

        

        m_RTP_Info.start = m_RTP_Info.end = m_RTP_Info.nal.start ; 

        m_bBeginNAL = true ; 

 

        return true ; 

    } 

 

    //循环调用Get获取RTP包,直到返回值为NULL 

    unsigned char* Get ( unsigned short *pPacketSize ) 

    { 

        if ( m_RTP_Info.end == m_RTP_Info.nal.end ) 

        { 

            *pPacketSize = 0 ; 

            return NULL ; 

        } 

 

        if ( m_bBeginNAL ) 

        { 

            m_bBeginNAL = false ; 

        } 

        else 

        { 

m_RTP_Info.start = m_RTP_Info.end;// continue with the next RTP-FU packet 

        } 

 

        int bytesLeft = m_RTP_Info.nal.end - m_RTP_Info.start ; 

int maxSize = m_MAXRTPPACKSIZE - 12 ;// sizeof(basic rtp header) == 12 bytes 

        if ( m_RTP_Info.FU_flag ) 

            maxSize -= 2 ; 

 

        if ( bytesLeft > maxSize ) 

        {

//limit RTP packetsize to 1472 bytes

            m_RTP_Info.end = m_RTP_Info.start + maxSize ;

        } 

        else 

        { 

            m_RTP_Info.end = m_RTP_Info.start + bytesLeft ; 

        } 

 

        if ( m_RTP_Info.FU_flag ) 

        {    // multiple packet NAL slice 

            if ( m_RTP_Info.end == m_RTP_Info.nal.end ) 

            { 

                m_RTP_Info.e_bit = 1 ; 

            } 

        }

//should be set at EofFrame

        m_RTP_Info.rtp_hdr.m =    m_RTP_Info.nal.eoFrame ? 1 : 0 ;

        if ( m_RTP_Info.FU_flag && !m_RTP_Info.e_bit )

        { 

            m_RTP_Info.rtp_hdr.m = 0 ; 

        } 

 

        m_RTP_Info.rtp_hdr.seq++ ; 

        unsigned char *cp = m_RTP_Info.start ; 

        cp -= ( m_RTP_Info.FU_flag ? 14 : 12 ) ; 

        m_RTP_Info.pRTP = cp ; 

        

        unsigned char *cp2 = (unsigned char *)&m_RTP_Info.rtp_hdr ; 

        cp[0] = cp2[0] ; 

        cp[1] = cp2[1] ; 

 

        cp[2] = ( m_RTP_Info.rtp_hdr.seq >> 8 ) & 0xff ; 

        cp[3] = m_RTP_Info.rtp_hdr.seq & 0xff ; 

 

        cp[4] = ( m_RTP_Info.rtp_hdr.ts >> 24 ) & 0xff ; 

        cp[5] = ( m_RTP_Info.rtp_hdr.ts >> 16 ) & 0xff ; 

        cp[6] = ( m_RTP_Info.rtp_hdr.ts >>  8 ) & 0xff ; 

        cp[7] = m_RTP_Info.rtp_hdr.ts & 0xff ; 

 

        cp[8] =  ( m_RTP_Info.rtp_hdr.ssrc >> 24 ) & 0xff ; 

        cp[9] =  ( m_RTP_Info.rtp_hdr.ssrc >> 16 ) & 0xff ; 

        cp[10] = ( m_RTP_Info.rtp_hdr.ssrc >>  8 ) & 0xff ; 

        cp[11] = m_RTP_Info.rtp_hdr.ssrc & 0xff ; 

        m_RTP_Info.hdr_len = 12 ; 

/*! 

* \n The FU indicator octet has the following format: 

* \n 

* \n      +---------------+ 

* \n MSB  |0|1|2|3|4|5|6|7|  LSB 

* \n      +-+-+-+-+-+-+-+-+ 

* \n      |F|NRI|  Type   | 

* \n      +---------------+ 

* \n 

* \n The FU header has the following format: 

* \n 

* \n      +---------------+ 

* \n      |0|1|2|3|4|5|6|7| 

* \n      +-+-+-+-+-+-+-+-+ 

* \n      |S|E|R|  Type   | 

* \n      +---------------+ 

*/ 

        if ( m_RTP_Info.FU_flag ) 

        { 

            // FU indicator  F|NRI|Type 

            cp[12] = ( m_RTP_Info.nal.type & 0xe0 ) | 28 ;//Type is 28 for FU_A 

            //FU header        S|E|R|Type 

            cp[13] = ( m_RTP_Info.s_bit << 7 )

 | ( m_RTP_Info.e_bit << 6 ) | ( m_RTP_Info.nal.type & 0x1f ) ;

//R = 0, must be ignored by receiver 

 

            m_RTP_Info.s_bit = m_RTP_Info.e_bit= 0 ; 

            m_RTP_Info.hdr_len = 14 ; 

        } 

        m_RTP_Info.start = &cp[m_RTP_Info.hdr_len] ;    // new start of payload 

 

        *pPacketSize = m_RTP_Info.hdr_len + ( m_RTP_Info.end - m_RTP_Info.start ) ; 

        return m_RTP_Info.pRTP ; 

    } 

 

private: 

    unsigned int StartCode( unsigned char *cp ) 

    { 

        unsigned int d32 ; 

        d32 = cp[3] ; 

        d32 <<= 8 ; 

        d32 |= cp[2] ; 

        d32 <<= 8 ; 

        d32 |= cp[1] ; 

        d32 <<= 8 ; 

        d32 |= cp[0] ; 

        return d32 ; 

    } 

 

private: 

    RTP_INFO m_RTP_Info ; 

    bool m_bBeginNAL ; 

    unsigned short m_MAXRTPPACKSIZE ; 

}; 

//END

//使用代码:

DWORD H264SSRC ; 

CH264_RTP_PACK pack ( H264SSRC ) ; 

BYTE *pVideoData ; 

DWORD Size, ts ; 

bool IsEndOfFrame ; 

WORD wLen ; 

pack.Set ( pVideoData, Size, ts, IsEndOfFrame ) ; 

BYTE *pPacket ; 

while ( pPacket = pack.Get ( &wLen ) ) 

 // rtp packet process 

 // ... 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值