rtp基本封包格式

rtp包易於過大,一般每個包不要超過1400,這裏設置爲1380,即DEFAULT_MTU=1380

這裏介紹的媒體格式有視頻:H264/H265,音頻:AAC

1、如果媒體包小於DEFAULT_MTU時可直接寫入rtp包中,示例代碼:

    unsigned char *pNAL;    //媒體數據包
    int nalsize;            //媒體數據包長度
    uint32_t timestamp;     //時間戳
    // RTPSession rtp_session;
    /* H264、H265 */
    // 以jrtplib以爲發送H264/H265視頻數據的rtp包,成功時返回值是0
    rtp_session.SendPacket(PacketData,PacketDataSize,96,true,(uint32_t)timestamp);

    /* AAC */
    uint8 aacHeader[4]={0x00,0x10,0x04,0xb8};
    aacHeader[2] = nalsize >> 5;
    aacHeader[3] = (nalsize & 0x1F) << 3;
    memcpy(PacketData,aacHeader,sizeof(aacHeader));
    memcpy(PacketData+sizeof(aacHeader),pNAL,nalsize);
    PacketDataSize = nalsize+sizeof(aacHeader);
    // 以jrtplib以爲發送AAC音頻數據的rtp包,成功時返回值是0
    rtp_session.SendPacket(PacketData,PacketDataSize,97,true,(uint32_t)timestamp);

2、當媒體數據的包長度超過DEFAULT_MTU時需要採用分片封包模式(FUs),示例代碼:

    unsigned char *pNAL;    //媒體數據包
    int nalsize;            //媒體數據包長度
    uint32_t timestamp;     //時間戳
    unsigned char PacketData[DEFAULT_MTU];  //rtp數據包
    uint32_t PacketDataSize = 0;            //rtp數據包長度
    int rtp_head_size = 0;

    //計算rtp包頭需要的信息
    #if H264 || AAC
        const uint8_t fu_indicator = (pNAL[0] & 0xe0) | 28;
        const uint8_t fu_header = pNAL[0] & 0x1f;
        pNAL++;
        nalsize--;
        rtp_head_size = 2;
    #else if H265
        const uint8_t payloadhdr[2]={(pNAL[0]&0x81)|(49<<1),pNAL[1]};
        const uint8_t fu_header = (pNAL[0] & 0x7E)>>1; 
        pNAL+=2;
        nalsize-=2;
        rtp_head_size = 3;
    #endif

    //計算需要拆分的片數
    uint32_t FU_size = 0;
    if((nalsize % (DEFAULT_MTU-rtp_head_size))!=0)
        FU_size=nalsize / (DEFAULT_MTU-rtp_head_size) +1;
    else
        FU_size=nalsize / (DEFAULT_MTU-rtp_head_size);

    int start = true;           //第一個分片標記
    bool end_mask = false;      //最後一個分片標誌
    while(nalsize>0){
        const uint32_t fraglen = MIN(DEFAULT_MTU-rtp_head_size, nalsize);
        PacketDataSize = fraglen+rtp_head_size;

        #if H264 || AAC
            PacketData[0]=fu_indicator;     //rtp包第一個字節
            PacketData[1]=fu_header;        //rtp包第二個字節
        #else if H265
            PacketData[0]=payloadhdr[0];    //rtp包第一個字節
            PacketData[1]=payloadhdr[1];    //rtp包第二個字節
            PacketData[2]=fu_header;        //rtp包第三個字節
        #endif

        if (start) {                    //第一個分片需要在最高位需要至1
            PacketData[rtp_head_size-1] |= (1<<7);
            start = false;
        }
        if (fraglen == nalsize) {       //最後一個分片需要在第2高位需要至1
            PacketData[rtp_head_size-1] |= (1<<6);
            end_mask=true;
        }
        memcpy(PacketData+rtp_head_size, pNAL, fraglen);    //剩下的數據接在後面
        // RTPSession rtp_session;
        // 以jrtplib以爲發送H264/H265視頻數據的rtp包,成功時返回值是0
        rtp_session.SendPacket(PacketData,PacketDataSize,96,end_mask,(uint32_t)timestamp);
        // 以jrtplib以爲發送AAC音頻數據的rtp包,成功時返回值是0
        rtp_session.SendPacket(PacketData,PacketDataSize,97,true,(uint32_t)timestamp);

        //媒體數據包去掉已經發送的部分
        nalsize -= fraglen;     
        pNAL += fraglen;
    }
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章