Rtsp.h 8.52 KB
Newer Older
xiongziliang committed
1
/*
xiongziliang committed
2
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
xiongziliang committed
3
 *
4
 * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
xiongziliang committed
5
 *
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
 */
xiongziliang committed
10

xzl committed
11 12 13 14 15 16
#ifndef RTSP_RTSP_H_
#define RTSP_RTSP_H_

#include <string.h>
#include <string>
#include <memory>
xiongzilaing committed
17
#include <unordered_map>
xiongziliang committed
18
#include "Common/macros.h"
19
#include "Extension/Frame.h"
20
#include "Network/Socket.h"
xiongzilaing committed
21

xiongziliang committed
22 23 24 25
namespace mediakit {

namespace Rtsp {
typedef enum {
26 27 28 29
    RTP_Invalid = -1,
    RTP_TCP = 0,
    RTP_UDP = 1,
    RTP_MULTICAST = 2,
xiongziliang committed
30
} eRtpType;
xiongziliang committed
31 32

#define RTP_PT_MAP(XX) \
33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50
    XX(PCMU, TrackAudio, 0, 8000, 1, CodecG711U) \
    XX(GSM, TrackAudio , 3, 8000, 1, CodecInvalid) \
    XX(G723, TrackAudio, 4, 8000, 1, CodecInvalid) \
    XX(DVI4_8000, TrackAudio, 5, 8000, 1, CodecInvalid) \
    XX(DVI4_16000, TrackAudio, 6, 16000, 1, CodecInvalid) \
    XX(LPC, TrackAudio, 7, 8000, 1, CodecInvalid) \
    XX(PCMA, TrackAudio, 8, 8000, 1, CodecG711A) \
    XX(G722, TrackAudio, 9, 8000, 1, CodecInvalid) \
    XX(L16_Stereo, TrackAudio, 10, 44100, 2, CodecInvalid) \
    XX(L16_Mono, TrackAudio, 11, 44100, 1, CodecInvalid) \
    XX(QCELP, TrackAudio, 12, 8000, 1, CodecInvalid) \
    XX(CN, TrackAudio, 13, 8000, 1, CodecInvalid) \
    XX(MPA, TrackAudio, 14, 90000, 1, CodecInvalid) \
    XX(G728, TrackAudio, 15, 8000, 1, CodecInvalid) \
    XX(DVI4_11025, TrackAudio, 16, 11025, 1, CodecInvalid) \
    XX(DVI4_22050, TrackAudio, 17, 22050, 1, CodecInvalid) \
    XX(G729, TrackAudio, 18, 8000, 1, CodecInvalid) \
    XX(CelB, TrackVideo, 25, 90000, 1, CodecInvalid) \
51
    XX(JPEG, TrackVideo, 26, 90000, 1, CodecJPEG) \
52 53 54 55 56
    XX(nv, TrackVideo, 28, 90000, 1, CodecInvalid) \
    XX(H261, TrackVideo, 31, 90000, 1, CodecInvalid) \
    XX(MPV, TrackVideo, 32, 90000, 1, CodecInvalid) \
    XX(MP2T, TrackVideo, 33, 90000, 1, CodecInvalid) \
    XX(H263, TrackVideo, 34, 90000, 1, CodecInvalid) \
xiongziliang committed
57 58

typedef enum {
59
#define ENUM_DEF(name, type, value, clock_rate, channel, codec_id) PT_ ## name = value,
xiongziliang committed
60 61 62 63 64
    RTP_PT_MAP(ENUM_DEF)
#undef ENUM_DEF
    PT_MAX = 128
} PayloadType;

xiongziliang committed
65 66
};

xiongziliang committed
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116
#if defined(_WIN32)
#pragma pack(push, 1)
#endif // defined(_WIN32)

class RtpHeader {
public:
#if __BYTE_ORDER == __BIG_ENDIAN
    //版本号,固定为2
    uint32_t version: 2;
    //padding
    uint32_t padding: 1;
    //扩展
    uint32_t ext: 1;
    //csrc
    uint32_t csrc: 4;
    //mark
    uint32_t mark: 1;
    //负载类型
    uint32_t pt: 7;
#else
    //csrc
    uint32_t csrc: 4;
    //扩展
    uint32_t ext: 1;
    //padding
    uint32_t padding: 1;
    //版本号,固定为2
    uint32_t version: 2;
    //负载类型
    uint32_t pt: 7;
    //mark
    uint32_t mark: 1;
#endif
    //序列号
    uint32_t seq: 16;
    //时间戳
    uint32_t stamp;
    //ssrc
    uint32_t ssrc;
    //负载,如果有csrc和ext,前面为 4 * csrc + (4 + 4 * ext_len)
    uint8_t payload;

public:
    //返回csrc字段字节长度
    size_t getCsrcSize() const;
    //返回csrc字段首地址,不存在时返回nullptr
    uint8_t *getCsrcData();

    //返回ext字段字节长度
    size_t getExtSize() const;
xia-chu committed
117 118
    //返回ext reserved值
    uint16_t getExtReserved() const;
xiongziliang committed
119 120 121 122 123 124
    //返回ext段首地址,不存在时返回nullptr
    uint8_t *getExtData();

    //返回有效负载指针,跳过csrc、ext
    uint8_t* getPayloadData();
    //返回有效负载总长度,不包括csrc、ext、padding
125
    ssize_t getPayloadSize(size_t rtp_size) const;
xia-chu committed
126
    //打印调试信息
夏楚 committed
127
    std::string dumpString(size_t rtp_size) const;
xiongziliang committed
128 129 130 131 132 133 134 135 136 137 138 139 140

private:
    //返回有效负载偏移量
    size_t getPayloadOffset() const;
    //返回padding长度
    size_t getPaddingSize(size_t rtp_size) const;
} PACKED;

#if defined(_WIN32)
#pragma pack(pop)
#endif // defined(_WIN32)

//此rtp为rtp over tcp形式,需要忽略前4个字节
夏楚 committed
141
class RtpPacket : public toolkit::BufferRaw{
xiongziliang committed
142
public:
xiongziliang committed
143 144 145 146 147 148 149
    using Ptr = std::shared_ptr<RtpPacket>;
    enum {
        kRtpVersion = 2,
        kRtpHeaderSize = 12,
        kRtpTcpHeaderSize = 4
    };

xiongziliang committed
150
    //获取rtp头
xiongziliang committed
151
    RtpHeader* getHeader();
152 153
    const RtpHeader* getHeader() const;

xiongziliang committed
154
    //打印调试信息
夏楚 committed
155
    std::string dumpString() const;
xiongziliang committed
156

xiongziliang committed
157
    //主机字节序的seq
158 159
    uint16_t getSeq() const;
    uint32_t getStamp() const;
xiongziliang committed
160
    //主机字节序的时间戳,已经转换为毫秒
ziyue committed
161
    uint64_t getStampMS(bool ntp = true) const;
xiongziliang committed
162
    //主机字节序的ssrc
163
    uint32_t getSSRC() const;
xiongziliang committed
164 165 166
    //有效负载,跳过csrc、ext
    uint8_t* getPayload();
    //有效负载长度,不包括csrc、ext、padding
167
    size_t getPayloadSize() const;
xiongziliang committed
168 169

    //音视频类型
170
    TrackType type;
xiongziliang committed
171 172
    //音频为采样率,视频一般为90000
    uint32_t sample_rate;
173 174
    //ntp时间戳
    uint64_t ntp_stamp;
xia-chu committed
175 176 177 178

    static Ptr create();

private:
夏楚 committed
179
    friend class toolkit::ResourcePool_l<RtpPacket>;
xia-chu committed
180
    RtpPacket() = default;
xia-chu committed
181 182 183

private:
    //对象个数统计
夏楚 committed
184
    toolkit::ObjectStatistic<RtpPacket> _statistic;
xiongziliang committed
185 186
};

xiongziliang committed
187
class RtpPayload {
xiongziliang committed
188 189 190 191 192
public:
    static int getClockRate(int pt);
    static TrackType getTrackType(int pt);
    static int getAudioChannel(int pt);
    static const char *getName(int pt);
193
    static CodecId getCodecId(int pt);
xiongziliang committed
194

xiongziliang committed
195 196 197 198 199
private:
    RtpPayload() = delete;
    ~RtpPayload() = delete;
};

xiongziliang committed
200
class SdpTrack {
201
public:
xiongziliang committed
202
    using Ptr = std::shared_ptr<SdpTrack>;
夏楚 committed
203 204
    std::string _t;
    std::string _b;
xiongziliang committed
205
    uint16_t _port;
206

207 208 209
    float _duration = 0;
    float _start = 0;
    float _end = 0;
210

夏楚 committed
211 212
    std::map<char, std::string> _other;
    std::multimap<std::string, std::string> _attr;
213

夏楚 committed
214 215 216
    std::string toString(uint16_t port = 0) const;
    std::string getName() const;
    std::string getControlUrl(const std::string &base_url) const;
xiongziliang committed
217

218
public:
219
    int _pt = 0xff;
xiongziliang committed
220
    int _channel;
xiongziliang committed
221 222
    int _samplerate;
    TrackType _type;
夏楚 committed
223 224 225
    std::string _codec;
    std::string _fmtp;
    std::string _control;
xiongziliang committed
226

xiongziliang committed
227
public:
228
    bool _inited = false;
xiongziliang committed
229
    uint8_t _interleaved = 0;
230
    uint16_t _seq = 0;
xiongziliang committed
231
    uint32_t _ssrc = 0;
232 233
    //时间戳,单位毫秒
    uint32_t _time_stamp = 0;
234
};
xiongziliang committed
235

xiongziliang committed
236
class SdpParser {
237
public:
xiongziliang committed
238
    using Ptr = std::shared_ptr<SdpParser>;
239

xiongziliang committed
240
    SdpParser() = default;
夏楚 committed
241
    SdpParser(const std::string &sdp) { load(sdp); }
xiongziliang committed
242
    ~SdpParser() = default;
xiongziliang committed
243

夏楚 committed
244
    void load(const std::string &sdp);
245 246
    bool available() const;
    SdpTrack::Ptr getTrack(TrackType type) const;
夏楚 committed
247 248
    std::vector<SdpTrack::Ptr> getAvailableTrack() const;
    std::string toString() const;
xiongziliang committed
249

250
private:
夏楚 committed
251
    std::vector<SdpTrack::Ptr> _track_vec;
252
};
xzl committed
253

254
/**
xiongziliang committed
255 256 257 258
* rtsp sdp基类
*/
class Sdp : public CodecInfo{
public:
xiongziliang committed
259
    using Ptr = std::shared_ptr<Sdp>;
260 261 262 263

    /**
     * 构造sdp
     * @param sample_rate 采样率
xiongziliang committed
264
     * @param payload_type pt类型
265
     */
xiongziliang committed
266
    Sdp(uint32_t sample_rate, uint8_t payload_type){
267
        _sample_rate = sample_rate;
xiongziliang committed
268
        _payload_type = payload_type;
269 270
    }

xiongziliang committed
271
    virtual ~Sdp() = default;
272 273 274 275 276

    /**
     * 获取sdp字符串
     * @return
     */
夏楚 committed
277
    virtual std::string getSdp() const  = 0;
278 279 280 281 282

    /**
     * 获取pt
     * @return
     */
xiongziliang committed
283 284
    uint8_t getPayloadType() const{
        return _payload_type;
285 286 287 288 289 290 291 292 293
    }

    /**
     * 获取采样率
     * @return
     */
    uint32_t getSampleRate() const{
        return _sample_rate;
    }
xiongziliang committed
294

xiongziliang committed
295
private:
xiongziliang committed
296
    uint8_t _payload_type;
297
    uint32_t _sample_rate;
xiongziliang committed
298 299 300 301 302 303 304
};

/**
* sdp中除音视频外的其他描述部分
*/
class TitleSdp : public Sdp{
public:
305
    using Ptr = std::shared_ptr<TitleSdp>;
306 307 308 309 310 311 312
    /**
     * 构造title类型sdp
     * @param dur_sec rtsp点播时长,0代表直播,单位秒
     * @param header 自定义sdp描述
     * @param version sdp版本
     */
    TitleSdp(float dur_sec = 0,
夏楚 committed
313
             const std::map<std::string, std::string> &header = std::map<std::string, std::string>(),
mtdxc committed
314
             int version = 0);
315

夏楚 committed
316
    std::string getSdp() const override {
317 318 319
        return _printer;
    }

320
    CodecId getCodecId() const override {
321 322
        return CodecInvalid;
    }
323 324 325 326 327

    float getDuration() const {
        return _dur_sec;
    }

xiongziliang committed
328
private:
329
    float _dur_sec = 0;
夏楚 committed
330
    toolkit::_StrPrinter _printer;
xiongziliang committed
331 332
};

xiongziliang committed
333
//创建rtp over tcp4个字节的头
夏楚 committed
334
toolkit::Buffer::Ptr makeRtpOverTcpPrefix(uint16_t size, uint8_t interleaved);
xiongziliang committed
335
//创建rtp-rtcp端口对
336
void makeSockPair(std::pair<toolkit::Socket::Ptr, toolkit::Socket::Ptr> &pair, const std::string &local_ip, bool re_use_port = false, bool is_udp = true);
xiongziliang committed
337
//十六进制方式打印ssrc
夏楚 committed
338
std::string printSSRC(uint32_t ui32Ssrc);
339

340 341 342
bool isRtp(const char *buf, size_t size);
bool isRtcp(const char *buf,  size_t size);

xiongziliang committed
343
} //namespace mediakit
xzl committed
344
#endif //RTSP_RTSP_H_