RtpReceiver.cpp 5.82 KB
Newer Older
xiongziliang committed
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
/*
 * MIT License
 *
 * Copyright (c) 2016 xiongziliang <771730766@qq.com>
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in all
 * copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
 * SOFTWARE.
 */

#include "Common/config.h"
#include "RtpReceiver.h"

#define POP_HEAD(trackidx) \
		auto it = _amapRtpSort[trackidx].begin(); \
		onRtpSorted(it->second, trackidx); \
		_amapRtpSort[trackidx].erase(it);

#   define AV_RB16(x)                           \
    ((((const uint8_t*)(x))[0] << 8) |          \
      ((const uint8_t*)(x))[1])


namespace mediakit {

RtpReceiver::RtpReceiver() {}
RtpReceiver::~RtpReceiver() {}

bool RtpReceiver::handleOneRtp(int iTrackidx,SdpTrack::Ptr &track, unsigned char *pucData, unsigned int uiLen) {
    auto pt_ptr=_pktPool.obtain();
    auto &rtppt=*pt_ptr;
    rtppt.interleaved = track->_interleaved;
    rtppt.length = uiLen + 4;

    rtppt.mark = pucData[1] >> 7;
    rtppt.PT = pucData[1] & 0x7F;
    //序列号
    memcpy(&rtppt.sequence,pucData+2,2);//内存对齐
    rtppt.sequence = ntohs(rtppt.sequence);
    //时间戳
    memcpy(&rtppt.timeStamp, pucData+4, 4);//内存对齐
xiongziliang committed
58 59 60 61

    if(!track->_samplerate){
        return false;
    }
xiongziliang committed
62
    //时间戳转换成毫秒
63
    rtppt.timeStamp = ntohl(rtppt.timeStamp) * 1000LL / track->_samplerate;
xiongziliang committed
64 65 66 67 68 69 70 71 72
    //ssrc
    memcpy(&rtppt.ssrc,pucData+8,4);//内存对齐
    rtppt.ssrc = ntohl(rtppt.ssrc);
    rtppt.type = track->_type;
    if (track->_ssrc == 0) {
        track->_ssrc = rtppt.ssrc;
        //保存SSRC
    } else if (track->_ssrc != rtppt.ssrc) {
        //ssrc错误
73
        WarnL << "ssrc错误:" << rtppt.ssrc << " != " << track->_ssrc;
xiongziliang committed
74
        if (_aui32SsrcErrorCnt[iTrackidx]++ > 10) {
75 76 77
            //ssrc切换后清除老数据
            WarnL << "ssrc更换:" << track->_ssrc << " -> " << rtppt.ssrc;
            _amapRtpSort[iTrackidx].clear();
xiongziliang committed
78 79 80 81 82 83 84 85
            track->_ssrc = rtppt.ssrc;
        }
        return false;
    }
    _aui32SsrcErrorCnt[iTrackidx] = 0;

    rtppt.payload[0] = '$';
    rtppt.payload[1] = rtppt.interleaved;
86
    rtppt.payload[2] = uiLen >> 8;
xiongziliang committed
87 88 89 90 91 92 93 94 95 96 97 98 99 100
    rtppt.payload[3] = (uiLen & 0x00FF);

    rtppt.offset 	= 16;
    int csrc     	= pucData[0] & 0x0f;
    int ext      	= pucData[0] & 0x10;
    rtppt.offset 	+= 4 * csrc;
    if (ext) {
        if(uiLen < rtppt.offset){
            return false;
        }
        /* calculate the header extension length (stored as number of 32-bit words) */
        ext = (AV_RB16(pucData + rtppt.offset - 2) + 1) << 2;
        rtppt.offset += ext;
    }
101

102
    if(rtppt.length - rtppt.offset <= 0){
103 104 105 106 107 108
        WarnL << "无有效负载的rtp包:" << rtppt.length << "<=" << (int)rtppt.offset;
        return false;
    }

    if(uiLen > sizeof(rtppt.payload) - 4){
        WarnL << "超长的rtp包:" << uiLen << ">" << sizeof(rtppt.payload) - 4;
109 110
        return false;
    }
xiongziliang committed
111 112 113
    memcpy(rtppt.payload + 4, pucData, uiLen);

    /////////////////////////////////RTP排序逻辑///////////////////////////////////
114
    if(rtppt.sequence != _aui16LastSeq[iTrackidx] + 1 && _aui16LastSeq[iTrackidx] != 0){
xiongziliang committed
115
        //包乱序或丢包
116
        _aui32SeqOkCnt[iTrackidx] = 0;
xiongziliang committed
117
        _abSortStarted[iTrackidx] = true;
118
//        WarnL << "包乱序或丢包:" << iTrackidx <<" " << rtppt.sequence << " " << _aui16LastSeq[iTrackidx];
119 120 121 122 123 124
        if(_aui16LastSeq[iTrackidx] > rtppt.sequence && _aui16LastSeq[iTrackidx] - rtppt.sequence > 0x7FFF){
            //sequence回环,清空所有排序缓存
            while (_amapRtpSort[iTrackidx].size()) {
                POP_HEAD(iTrackidx)
            }
        }
xiongziliang committed
125 126
    }else{
        //正确序列的包
127
        _aui32SeqOkCnt[iTrackidx]++;
xiongziliang committed
128 129 130 131 132 133 134 135
    }
    _aui16LastSeq[iTrackidx] = rtppt.sequence;

    //开始排序缓存
    if (_abSortStarted[iTrackidx]) {
        _amapRtpSort[iTrackidx].emplace(rtppt.sequence, pt_ptr);
        GET_CONFIG_AND_REGISTER(uint32_t,clearCount,Rtp::kClearCount);
        GET_CONFIG_AND_REGISTER(uint32_t,maxRtpCount,Rtp::kMaxRtpCount);
136
        if (_aui32SeqOkCnt[iTrackidx] >= clearCount) {
xiongziliang committed
137
            //网络环境改善,需要清空排序缓存
138
            _aui32SeqOkCnt[iTrackidx] = 0;
xiongziliang committed
139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157
            _abSortStarted[iTrackidx] = false;
            while (_amapRtpSort[iTrackidx].size()) {
                POP_HEAD(iTrackidx)
            }
        } else if (_amapRtpSort[iTrackidx].size() >= maxRtpCount) {
            //排序缓存溢出
            POP_HEAD(iTrackidx)
        }
    }else{
        //正确序列
        onRtpSorted(pt_ptr, iTrackidx);
    }
    //////////////////////////////////////////////////////////////////////////////////
    return true;
}

void RtpReceiver::clear() {
    CLEAR_ARR(_aui16LastSeq)
    CLEAR_ARR(_aui32SsrcErrorCnt)
158
    CLEAR_ARR(_aui32SeqOkCnt)
xiongziliang committed
159 160 161 162 163 164 165 166 167 168 169
    CLEAR_ARR(_abSortStarted)

    _amapRtpSort[0].clear();
    _amapRtpSort[1].clear();
}

void RtpReceiver::setPoolSize(int size) {
    _pktPool.setSize(size);
}

}//namespace mediakit