RtpReceiver.cpp 4.66 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
xiongziliang committed
3 4 5
 *
 * This file is part of ZLMediaKit(https://github.com/xiongziliang/ZLMediaKit).
 *
xiongziliang committed
6 7 8
 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
xiongziliang committed
9 10 11 12 13
 */

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

14
#define AV_RB16(x)                           \
xiongziliang committed
15 16 17
    ((((const uint8_t*)(x))[0] << 8) |          \
      ((const uint8_t*)(x))[1])

18
#define RTP_MAX_SIZE (10 * 1024)
xiongziliang committed
19 20 21

namespace mediakit {

xiongziliang committed
22 23 24
RtpReceiver::RtpReceiver() {
    int index = 0;
    for (auto &sortor : _rtp_sortor) {
25
        sortor.setOnSort([this, index](uint16_t seq, RtpPacket::Ptr &packet) {
xiongziliang committed
26 27 28 29 30
            onRtpSorted(packet, index);
        });
        ++index;
    }
}
xiongziliang committed
31 32
RtpReceiver::~RtpReceiver() {}

xiongziliang committed
33
bool RtpReceiver::handleOneRtp(int track_index, TrackType type, int samplerate, unsigned char *rtp_raw_ptr, unsigned int rtp_raw_len) {
34
    if (rtp_raw_len < 12) {
35
        WarnL << "rtp包太小:" << rtp_raw_len;
xiongziliang committed
36 37
        return false;
    }
38

xiongziliang committed
39
    uint32_t version = rtp_raw_ptr[0] >> 6;
40
    uint8_t padding = 0;
xiongziliang committed
41 42 43
    uint8_t ext = rtp_raw_ptr[0] & 0x10;
    uint8_t csrc = rtp_raw_ptr[0] & 0x0f;

44
    if (rtp_raw_ptr[0] & 0x20) {
45 46 47
        //获取padding大小
        padding = rtp_raw_ptr[rtp_raw_len - 1];
        //移除padding flag
48
        rtp_raw_ptr[0] &= ~0x20;
49 50 51 52
        //移除padding字节
        rtp_raw_len -= padding;
    }

xiongziliang committed
53 54 55 56
    if (version != 2) {
        throw std::invalid_argument("非法的rtp,version != 2");
    }

57 58
    auto rtp_ptr = _rtp_pool.obtain();
    auto &rtp = *rtp_ptr;
xiongziliang committed
59

xiongziliang committed
60 61
    rtp.type = type;
    rtp.interleaved = 2 * type;
62 63
    rtp.mark = rtp_raw_ptr[1] >> 7;
    rtp.PT = rtp_raw_ptr[1] & 0x7F;
64 65 66

    //序列号,内存对齐
    memcpy(&rtp.sequence, rtp_raw_ptr + 2, 2);
67
    rtp.sequence = ntohs(rtp.sequence);
68 69 70 71

    //时间戳,内存对齐
    memcpy(&rtp.timeStamp, rtp_raw_ptr + 4, 4);
    rtp.timeStamp = ntohl(rtp.timeStamp);
xiongziliang committed
72

73
    if (!samplerate) {
74
        //无法把时间戳转换成毫秒
xiongziliang committed
75 76
        return false;
    }
xiongziliang committed
77
    //时间戳转换成毫秒
xiongziliang committed
78
    rtp.timeStamp = rtp.timeStamp * 1000LL / samplerate;
79 80 81

    //ssrc,内存对齐
    memcpy(&rtp.ssrc, rtp_raw_ptr + 8, 4);
82 83
    rtp.ssrc = ntohl(rtp.ssrc);

xiongziliang committed
84 85
    if (_ssrc[track_index] != rtp.ssrc) {
        if (_ssrc[track_index] == 0) {
86
            //保存SSRC至track对象
xiongziliang committed
87
            _ssrc[track_index] = rtp.ssrc;
88
        } else {
89
            //ssrc错误
xiongziliang committed
90
            WarnL << "ssrc错误:" << rtp.ssrc << " != " << _ssrc[track_index];
91 92
            if (_ssrc_err_count[track_index]++ > 10) {
                //ssrc切换后清除老数据
xiongziliang committed
93
                WarnL << "ssrc更换:" << _ssrc[track_index] << " -> " << rtp.ssrc;
xiongziliang committed
94
                _rtp_sortor[track_index].clear();
xiongziliang committed
95
                _ssrc[track_index] = rtp.ssrc;
96 97
            }
            return false;
xiongziliang committed
98 99
        }
    }
100 101 102

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

104 105 106
    //rtp 12个固定字节头
    rtp.offset = 12;
    //rtp有csrc
107
    rtp.offset += 4 * csrc;
108 109 110 111 112
    if (ext) {
        //rtp有ext
        uint16_t reserved = AV_RB16(rtp_raw_ptr + rtp.offset);
        uint16_t extlen = AV_RB16(rtp_raw_ptr + rtp.offset + 2) << 2;
        rtp.offset += extlen + 4;
xiongziliang committed
113
    }
114

115
    if (rtp_raw_len <= rtp.offset) {
116
        //无有效负载的rtp包
117 118 119
        return false;
    }

120
    if (rtp_raw_len > RTP_MAX_SIZE) {
121
        WarnL << "超大的rtp包:" << rtp_raw_len << " > " << RTP_MAX_SIZE;
122 123 124 125
        return false;
    }

    //设置rtp负载长度
126 127
    rtp.setCapacity(rtp_raw_len + 4);
    rtp.setSize(rtp_raw_len + 4);
128
    uint8_t *payload_ptr = (uint8_t *) rtp.data();
xiongziliang committed
129
    payload_ptr[0] = '$';
130 131 132
    payload_ptr[1] = rtp.interleaved;
    payload_ptr[2] = rtp_raw_len >> 8;
    payload_ptr[3] = (rtp_raw_len & 0x00FF);
133 134
    //添加rtp over tcp前4个字节的偏移量
    rtp.offset += 4;
xiongziliang committed
135
    //拷贝rtp负载
136 137
    memcpy(payload_ptr + 4, rtp_raw_ptr, rtp_raw_len);
    //排序rtp
xiongziliang committed
138 139
    auto seq = rtp_ptr->sequence;
    _rtp_sortor[track_index].sortPacket(seq, std::move(rtp_ptr));
140 141
    return true;
}
xiongziliang committed
142 143

void RtpReceiver::clear() {
xiongziliang committed
144 145
    CLEAR_ARR(_ssrc);
    CLEAR_ARR(_ssrc_err_count);
xiongziliang committed
146 147 148
    for (auto &sortor : _rtp_sortor) {
        sortor.clear();
    }
xiongziliang committed
149 150 151
}

void RtpReceiver::setPoolSize(int size) {
152
    _rtp_pool.setSize(size);
xiongziliang committed
153 154
}

ziyue committed
155
int RtpReceiver::getJitterSize(int track_index) const{
xiongziliang committed
156
    return _rtp_sortor[track_index].getJitterSize();
xiongziliang committed
157 158
}

ziyue committed
159
int RtpReceiver::getCycleCount(int track_index) const{
xiongziliang committed
160
    return _rtp_sortor[track_index].getCycleCount();
xiongziliang committed
161 162
}

ziyue committed
163 164 165
uint32_t RtpReceiver::getSSRC(int track_index) const{
    return _ssrc[track_index];
}
xiongziliang committed
166

xiongziliang committed
167
}//namespace mediakit