RtpReceiver.h 4.23 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
 */

#ifndef ZLMEDIAKIT_RTPRECEIVER_H
#define ZLMEDIAKIT_RTPRECEIVER_H

xiongziliang committed
14
#include <map>
xiongziliang committed
15 16
#include <string>
#include <memory>
xiongziliang committed
17
#include "RtpCodec.h"
xiongziliang committed
18 19 20 21 22 23
#include "RtspMediaSource.h"
using namespace std;
using namespace toolkit;

namespace mediakit {

24
template<typename T, typename SEQ = uint16_t, uint32_t kMax = 256, uint32_t kMin = 10>
xiongziliang committed
25 26 27 28 29
class PacketSortor {
public:
    PacketSortor() = default;
    ~PacketSortor() = default;

30
    void setOnSort(function<void(SEQ seq, T &packet)> cb) {
xiongziliang committed
31 32 33 34 35 36 37 38 39
        _cb = std::move(cb);
    }

    /**
     * 清空状态
     */
    void clear() {
        _seq_cycle_count = 0;
        _rtp_sort_cache_map.clear();
40 41
        _next_seq_out = 0;
        _max_sort_size = kMin;
xiongziliang committed
42 43 44 45 46
    }

    /**
     * 获取排序缓存长度
     */
47
    int getJitterSize() {
xiongziliang committed
48 49 50 51 52 53
        return _rtp_sort_cache_map.size();
    }

    /**
     * 获取seq回环次数
     */
54
    int getCycleCount() {
xiongziliang committed
55 56 57 58 59 60 61 62
        return _seq_cycle_count;
    }

    /**
     * 输入并排序
     * @param seq 序列号
     * @param packet 包负载
     */
63 64 65 66
    void sortPacket(SEQ seq, T packet) {
        if (seq < _next_seq_out && _next_seq_out - seq > kMax) {
            //回环
            ++_seq_cycle_count;
xiongziliang committed
67
        }
68 69 70 71
        //放入排序缓存
        _rtp_sort_cache_map.emplace(seq, std::move(packet));
        //尝试输出排序后的包
        tryPopPacket();
xiongziliang committed
72 73 74 75 76
    }

private:
    void popPacket() {
        auto it = _rtp_sort_cache_map.begin();
77 78
        _cb(it->first, it->second);
        _next_seq_out = it->first + 1;
xiongziliang committed
79 80 81
        _rtp_sort_cache_map.erase(it);
    }

82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105
    void tryPopPacket() {
        bool flag = false;
        while ((!_rtp_sort_cache_map.empty() && _rtp_sort_cache_map.begin()->first == _next_seq_out)) {
            //找到下个包,直接输出
            popPacket();
            flag = true;
        }

        if (flag) {
            setSortSize();
        } else if (_rtp_sort_cache_map.size() > _max_sort_size) {
            //排序缓存溢出,不再继续排序
            popPacket();
            setSortSize();
        }
    }

    void setSortSize() {
        _max_sort_size = 2 * _rtp_sort_cache_map.size();
        if (_max_sort_size > kMax) {
            _max_sort_size = kMax;
        } else if (_max_sort_size < kMin) {
            _max_sort_size = kMin;
        }
xiongziliang committed
106 107 108
    }

private:
109 110
    //下次应该输出的SEQ
    SEQ _next_seq_out = 0;
xiongziliang committed
111 112 113
    //seq回环次数计数
    uint32_t _seq_cycle_count = 0;
    //排序缓存长度
114
    uint32_t _max_sort_size = kMin;
xiongziliang committed
115 116 117
    //rtp排序缓存,根据seq排序
    map<SEQ, T> _rtp_sort_cache_map;
    //回调
118
    function<void(SEQ seq, T &packet)> _cb;
xiongziliang committed
119 120
};

xiongziliang committed
121 122 123 124 125
class RtpReceiver {
public:
    RtpReceiver();
    virtual ~RtpReceiver();

xiongziliang committed
126
protected:
xiongziliang committed
127 128
    /**
     * 输入数据指针生成并排序rtp包
129
     * @param track_index track下标索引
xiongziliang committed
130 131
     * @param type track类型
     * @param samplerate rtp时间戳基准时钟,视频为90000,音频为采样率
132 133
     * @param rtp_raw_ptr rtp数据指针
     * @param rtp_raw_len rtp数据指针长度
xiongziliang committed
134 135
     * @return 解析成功返回true
     */
xiongziliang committed
136
    bool handleOneRtp(int track_index, TrackType type, int samplerate, unsigned char *rtp_raw_ptr, unsigned int rtp_raw_len);
xiongziliang committed
137 138 139

    /**
     * rtp数据包排序后输出
xiongziliang committed
140 141
     * @param rtp rtp数据包
     * @param track_index track索引
xiongziliang committed
142
     */
143
    virtual void onRtpSorted(const RtpPacket::Ptr &rtp, int track_index) {}
xiongziliang committed
144

xiongziliang committed
145 146
    void clear();
    void setPoolSize(int size);
xiongziliang committed
147 148
    int getJitterSize(int track_index);
    int getCycleCount(int track_index);
xiongziliang committed
149

xiongziliang committed
150
private:
151
    void sortRtp(const RtpPacket::Ptr &rtp , int track_index);
xiongziliang committed
152

153
private:
154
    uint32_t _ssrc[2] = {0, 0};
155
    //ssrc不匹配计数
156
    uint32_t _ssrc_err_count[2] = {0, 0};
157
    //rtp排序缓存,根据seq排序
xiongziliang committed
158
    PacketSortor<RtpPacket::Ptr> _rtp_sortor[2];
159 160
    //rtp循环池
    RtspMediaSource::PoolType _rtp_pool;
xiongziliang committed
161 162 163 164 165 166
};

}//namespace mediakit


#endif //ZLMEDIAKIT_RTPRECEIVER_H