RtpReceiver.cpp 6.29 KB
Newer Older
xiongziliang committed
1 2 3
/*
 * MIT License
 *
xiongziliang committed
4
 * Copyright (c) 2016-2019 xiongziliang <771730766@qq.com>
xiongziliang committed
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
 *
 * 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) \
31
		auto it = _rtp_sort_cache_map[trackidx].begin(); \
xiongziliang committed
32
		onRtpSorted(it->second, trackidx); \
33
		_rtp_sort_cache_map[trackidx].erase(it);
xiongziliang committed
34

35
#define AV_RB16(x)                           \
xiongziliang committed
36 37 38
    ((((const uint8_t*)(x))[0] << 8) |          \
      ((const uint8_t*)(x))[1])

39
#define RTP_MAX_SIZE (10 * 1024)
xiongziliang committed
40 41 42 43 44 45

namespace mediakit {

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

46 47 48 49
bool RtpReceiver::handleOneRtp(int track_index,SdpTrack::Ptr &track, unsigned char *rtp_raw_ptr, unsigned int rtp_raw_len) {
    auto rtp_ptr = _rtp_pool.obtain();
    auto &rtp = *rtp_ptr;
    auto length = rtp_raw_len + 4;
xiongziliang committed
50

51
    rtp.interleaved = 2 * track->_type;
52 53
    rtp.mark = rtp_raw_ptr[1] >> 7;
    rtp.PT = rtp_raw_ptr[1] & 0x7F;
xiongziliang committed
54
    //序列号
55 56
    memcpy(&rtp.sequence,rtp_raw_ptr+2,2);//内存对齐
    rtp.sequence = ntohs(rtp.sequence);
xiongziliang committed
57
    //时间戳
58
    memcpy(&rtp.timeStamp, rtp_raw_ptr+4, 4);//内存对齐
xiongziliang committed
59 60

    if(!track->_samplerate){
61
        //无法把时间戳转换成毫秒
xiongziliang committed
62 63
        return false;
    }
xiongziliang committed
64
    //时间戳转换成毫秒
65
    rtp.timeStamp = ntohl(rtp.timeStamp) * 1000LL / track->_samplerate;
xiongziliang committed
66
    //ssrc
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84
    memcpy(&rtp.ssrc,rtp_raw_ptr+8,4);//内存对齐
    rtp.ssrc = ntohl(rtp.ssrc);
    rtp.type = track->_type;

    if (track->_ssrc != rtp.ssrc) {
        if (track->_ssrc == 0) {
            //保存SSRC至track对象
            track->_ssrc = rtp.ssrc;
        }else{
            //ssrc错误
            WarnL << "ssrc错误:" << rtp.ssrc << " != " << track->_ssrc;
            if (_ssrc_err_count[track_index]++ > 10) {
                //ssrc切换后清除老数据
                WarnL << "ssrc更换:" << track->_ssrc << " -> " << rtp.ssrc;
                _rtp_sort_cache_map[track_index].clear();
                track->_ssrc = rtp.ssrc;
            }
            return false;
xiongziliang committed
85 86
        }
    }
87 88 89

    //ssrc匹配正确,不匹配计数清零
    _ssrc_err_count[track_index] = 0;
xiongziliang committed
90

xiongziliang committed
91
    //获取rtp中媒体数据偏移量
92 93 94 95 96
    rtp.offset 	= 12 + 4;
    int csrc     	= rtp_raw_ptr[0] & 0x0f;
    int ext      	= rtp_raw_ptr[0] & 0x10;
    rtp.offset 	+= 4 * csrc;
    if (ext && rtp_raw_len >= rtp.offset) {
xiongziliang committed
97
        /* calculate the header extension length (stored as number of 32-bit words) */
98 99
        ext = (AV_RB16(rtp_raw_ptr + rtp.offset - 2) + 1) << 2;
        rtp.offset += ext;
xiongziliang committed
100
    }
101

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

107 108 109 110 111 112 113 114 115
    if(length > RTP_MAX_SIZE){
        WarnL << "超大的rtp包:" << length << ">" << RTP_MAX_SIZE;
        return false;
    }

    //设置rtp负载长度
    rtp.setCapacity(length);
    rtp.setSize(length);
    uint8_t *payload_ptr = (uint8_t *)rtp.data();
xiongziliang committed
116
    payload_ptr[0] = '$';
117 118 119
    payload_ptr[1] = rtp.interleaved;
    payload_ptr[2] = rtp_raw_len >> 8;
    payload_ptr[3] = (rtp_raw_len & 0x00FF);
xiongziliang committed
120
    //拷贝rtp负载
121 122 123 124 125
    memcpy(payload_ptr + 4, rtp_raw_ptr, rtp_raw_len);
    //排序rtp
    sortRtp(rtp_ptr,track_index);
    return true;
}
xiongziliang committed
126

127 128
void RtpReceiver::sortRtp(const RtpPacket::Ptr &rtp,int track_index){
    if(rtp->sequence != _last_seq[track_index] + 1 && _last_seq[track_index] != 0){
xiongziliang committed
129
        //包乱序或丢包
130 131 132
        _seq_ok_count[track_index] = 0;
        _sort_started[track_index] = true;
        if(_last_seq[track_index] > rtp->sequence && _last_seq[track_index] - rtp->sequence > 0xFF){
133
            //sequence回环,清空所有排序缓存
134 135
            while (_rtp_sort_cache_map[track_index].size()) {
                POP_HEAD(track_index)
136
            }
137
            ++_seq_cycle_count[track_index];
138
        }
xiongziliang committed
139 140
    }else{
        //正确序列的包
141
        _seq_ok_count[track_index]++;
xiongziliang committed
142
    }
143 144

    _last_seq[track_index] = rtp->sequence;
xiongziliang committed
145 146

    //开始排序缓存
147 148
    if (_sort_started[track_index]) {
        _rtp_sort_cache_map[track_index].emplace(rtp->sequence, rtp);
149 150
        GET_CONFIG(uint32_t,clearCount,Rtp::kClearCount);
        GET_CONFIG(uint32_t,maxRtpCount,Rtp::kMaxRtpCount);
151
        if (_seq_ok_count[track_index] >= clearCount) {
xiongziliang committed
152
            //网络环境改善,需要清空排序缓存
153 154 155 156
            _seq_ok_count[track_index] = 0;
            _sort_started[track_index] = false;
            while (_rtp_sort_cache_map[track_index].size()) {
                POP_HEAD(track_index)
xiongziliang committed
157
            }
158
        } else if (_rtp_sort_cache_map[track_index].size() >= maxRtpCount) {
xiongziliang committed
159
            //排序缓存溢出
160
            POP_HEAD(track_index)
xiongziliang committed
161 162 163
        }
    }else{
        //正确序列
164
        onRtpSorted(rtp, track_index);
xiongziliang committed
165 166 167 168
    }
}

void RtpReceiver::clear() {
169 170 171 172 173 174 175 176
    CLEAR_ARR(_last_seq)
    CLEAR_ARR(_ssrc_err_count)
    CLEAR_ARR(_seq_ok_count)
    CLEAR_ARR(_sort_started)
    CLEAR_ARR(_seq_cycle_count)

    _rtp_sort_cache_map[0].clear();
    _rtp_sort_cache_map[1].clear();
xiongziliang committed
177 178 179
}

void RtpReceiver::setPoolSize(int size) {
180
    _rtp_pool.setSize(size);
xiongziliang committed
181 182
}

xiongziliang committed
183 184
int RtpReceiver::getJitterSize(int track_index){
    return _rtp_sort_cache_map[track_index].size();
xiongziliang committed
185 186
}

xiongziliang committed
187 188
int RtpReceiver::getCycleCount(int track_index){
    return _seq_cycle_count[track_index];
xiongziliang committed
189 190 191
}


xiongziliang committed
192
}//namespace mediakit