Sdp.h 22 KB
Newer Older
xiongziliang committed
1 2 3 4 5 6 7 8 9
/*
 * Copyright (c) 2016 The ZLMediaKit project authors. All Rights Reserved.
 *
 * This file is part of ZLMediaKit(https://github.com/xia-chu/ZLMediaKit).
 *
 * 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.
 */
ziyue committed
10 11 12 13 14

#ifndef ZLMEDIAKIT_SDP_H
#define ZLMEDIAKIT_SDP_H

#include <string>
xiongziliang committed
15
#include <vector>
ziyue committed
16
#include "assert.h"
xiongziliang committed
17
#include "Extension/Frame.h"
ziyue committed
18
using namespace std;
xiongziliang committed
19
using namespace mediakit;
ziyue committed
20

ziyue committed
21 22
#define CHECK(exp) Assert_Throw(!(exp), #exp, __FUNCTION__, __FILE__, __LINE__);

xiongziliang committed
23
//https://datatracker.ietf.org/doc/rfc4566/?include_text=1
xiongziliang committed
24 25
//https://blog.csdn.net/aggresss/article/details/109850434
//https://aggresss.blog.csdn.net/article/details/106436703
ziyue committed
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
//Session description
//         v=  (protocol version)
//         o=  (originator and session identifier)
//         s=  (session name)
//         i=* (session information)
//         u=* (URI of description)
//         e=* (email address)
//         p=* (phone number)
//         c=* (connection information -- not required if included in
//              all media)
//         b=* (zero or more bandwidth information lines)
//         One or more time descriptions ("t=" and "r=" lines; see below)
//         z=* (time zone adjustments)
//         k=* (encryption key)
//         a=* (zero or more session attribute lines)
//         Zero or more media descriptions
//
//      Time description
//         t=  (time the session is active)
//         r=* (zero or more repeat times)
//
//      Media description, if present
//         m=  (media name and transport address)
//         i=* (media title)
//         c=* (connection information -- optional if included at
//              session level)
//         b=* (zero or more bandwidth information lines)
//         k=* (encryption key)
//         a=* (zero or more media attribute lines)

xiongziliang committed
56 57 58 59 60
enum class RtpDirection {
    invalid = -1,
    //只发送
    sendonly,
    //只接收
61
    recvonly,
xiongziliang committed
62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83
    //同时发送接收
    sendrecv,
    //禁止发送数据
    inactive
};

enum class DtlsRole {
    invalid = -1,
    //客户端
    active,
    //服务端
    passive,
    //既可作做客户端也可以做服务端
    actpass,
};

enum class SdpType {
    invalid = -1,
    offer,
    answer
};

84 85 86 87 88
DtlsRole getDtlsRole(const string &str);
const char* getDtlsRoleString(DtlsRole role);
RtpDirection getRtpDirection(const string &str);
const char* getRtpDirectionString(RtpDirection val);

ziyue committed
89 90
class SdpItem {
public:
91
    using Ptr = std::shared_ptr<SdpItem>;
ziyue committed
92
    virtual ~SdpItem() = default;
93 94 95 96 97 98
    virtual void parse(const string &str) {
        value  = str;
    }
    virtual string toString() const {
        return value;
    }
99
    virtual const char* getKey() const = 0;
100 101 102

protected:
    mutable string value;
ziyue committed
103 104
};

105 106 107
template <char KEY>
class SdpString : public SdpItem{
public:
ziyue committed
108
    SdpString() = default;
ziyue committed
109
    SdpString(string val) {value = std::move(val);}
110
    // *=*
111
    const char* getKey() const override { static string key(1, KEY); return key.data();}
112 113 114 115 116 117
};

class SdpCommon : public SdpItem {
public:
    string key;
    SdpCommon(string key) { this->key = std::move(key); }
ziyue committed
118 119 120 121 122
    SdpCommon(string key, string val) {
        this->key = std::move(key);
        this->value = std::move(val);
    }

123
    const char* getKey() const override { return key.data();}
124 125
};

ziyue committed
126 127
class SdpTime : public SdpItem{
public:
xiongziliang committed
128 129
    //5.9.  Timing ("t=")
    // t=<start-time> <stop-time>
130 131 132 133
    uint64_t start {0};
    uint64_t stop {0};
    void parse(const string &str) override;
    string toString() const override;
134
    const char* getKey() const override { return "t";}
ziyue committed
135 136 137 138
};

class SdpOrigin : public SdpItem{
public:
xiongziliang committed
139
    // 5.2.  Origin ("o=")
ziyue committed
140 141
    // o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5
    // o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
142
    string username {"-"};
ziyue committed
143 144
    string session_id;
    string session_version;
145 146 147 148 149
    string nettype {"IN"};
    string addrtype {"IP4"};
    string address {"0.0.0.0"};
    void parse(const string &str) override;
    string toString() const override;
150
    const char* getKey() const override { return "o";}
151 152 153 154
    bool empty() const {
        return username.empty() || session_id.empty() || session_version.empty()
               || nettype.empty() || addrtype.empty() || address.empty();
    }
ziyue committed
155 156 157 158
};

class SdpConnection : public SdpItem {
public:
xiongziliang committed
159
    // 5.7.  Connection Data ("c=")
ziyue committed
160 161
    // c=IN IP4 224.2.17.12/127
    // c=<nettype> <addrtype> <connection-address>
162 163 164 165 166
    string nettype {"IN"};
    string addrtype {"IP4"};
    string address {"0.0.0.0"};
    void parse(const string &str) override;
    string toString() const override;
167
    const char* getKey() const override { return "c";}
ziyue committed
168
    bool empty() const {return address.empty();}
xiongziliang committed
169 170 171 172 173 174 175 176
};

class SdpBandwidth : public SdpItem {
public:
    //5.8.  Bandwidth ("b=")
    //b=<bwtype>:<bandwidth>

    //AS、CT
177 178
    string bwtype {"AS"};
    uint32_t bandwidth {0};
xiongziliang committed
179

180 181
    void parse(const string &str) override;
    string toString() const override;
182
    const char* getKey() const override { return "b";}
ziyue committed
183
    bool empty() const {return bandwidth == 0;}
xiongziliang committed
184 185 186 187 188 189 190 191
};

class SdpMedia : public SdpItem {
public:
    // 5.14.  Media Descriptions ("m=")
    // m=<media> <port> <proto> <fmt> ...
    TrackType type;
    uint16_t port;
xiongziliang committed
192 193 194 195
    //RTP/AVP:应用场景为视频/音频的 RTP 协议。参考 RFC 3551
    //RTP/SAVP:应用场景为视频/音频的 SRTP 协议。参考 RFC 3711
    //RTP/AVPF: 应用场景为视频/音频的 RTP 协议,支持 RTCP-based Feedback。参考 RFC 4585
    //RTP/SAVPF: 应用场景为视频/音频的 SRTP 协议,支持 RTCP-based Feedback。参考 RFC 5124
196 197
    string proto;
    vector<uint32_t> fmts;
xiongziliang committed
198

199 200
    void parse(const string &str) override;
    string toString() const override;
201
    const char* getKey() const override { return "m";}
xiongziliang committed
202 203 204 205
};

class SdpAttr : public SdpItem{
public:
206
    using Ptr = std::shared_ptr<SdpAttr>;
xiongziliang committed
207 208 209
    //5.13.  Attributes ("a=")
    //a=<attribute>
    //a=<attribute>:<value>
210
    SdpItem::Ptr detail;
xiongziliang committed
211
    void parse(const string &str) override;
212
    string toString() const override;
213
    const char* getKey() const override { return "a";}
xiongziliang committed
214 215 216 217 218 219 220 221
};

class SdpAttrGroup : public SdpItem{
public:
    //a=group:BUNDLE line with all the 'mid' identifiers part of the
    //  BUNDLE group is included at the session-level.
    //a=group:LS session level attribute MUST be included wth the 'mid'
    //  identifiers that are part of the same lip sync group.
222 223 224 225
    string type {"BUNDLE"};
    vector<string> mids;
    void parse(const string &str) override ;
    string toString() const override ;
226
    const char* getKey() const override { return "group";}
ziyue committed
227 228
};

229
class SdpAttrMsidSemantic : public SdpItem {
ziyue committed
230
public:
231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254
    //https://tools.ietf.org/html/draft-alvestrand-rtcweb-msid-02#section-3
    //3.  The Msid-Semantic Attribute
    //
    //   In order to fully reproduce the semantics of the SDP and SSRC
    //   grouping frameworks, a session-level attribute is defined for
    //   signalling the semantics associated with an msid grouping.
    //
    //   This OPTIONAL attribute gives the message ID and its group semantic.
    //     a=msid-semantic: examplefoo LS
    //
    //
    //   The ABNF of msid-semantic is:
    //
    //     msid-semantic-attr = "msid-semantic:" " " msid token
    //     token = <as defined in RFC 4566>
    //
    //   The semantic field may hold values from the IANA registries
    //   "Semantics for the "ssrc-group" SDP Attribute" and "Semantics for the
    //   "group" SDP Attribute".
    //a=msid-semantic: WMS 616cfbb1-33a3-4d8c-8275-a199d6005549
    string msid{"WMS"};
    string token;
    void parse(const string &str) override;
    string toString() const override;
255
    const char* getKey() const override { return "msid-semantic";}
256 257 258
    bool empty() const {
        return msid.empty();
    }
259
};
ziyue committed
260

261 262
class SdpAttrRtcp : public SdpItem {
public:
263
    // a=rtcp:9 IN IP4 0.0.0.0
ziyue committed
264
    uint16_t port{0};
265 266 267 268 269
    string nettype {"IN"};
    string addrtype {"IP4"};
    string address {"0.0.0.0"};
    void parse(const string &str) override;;
    string toString() const override;
270
    const char* getKey() const override { return "rtcp";}
ziyue committed
271 272 273
    bool empty() const {
        return address.empty() || !port;
    }
274 275 276 277
};

class SdpAttrIceUfrag : public SdpItem {
public:
ziyue committed
278 279
    SdpAttrIceUfrag() = default;
    SdpAttrIceUfrag(string str) {value = std::move(str);}
280
    //a=ice-ufrag:sXJ3
281
    const char* getKey() const override { return "ice-ufrag";}
282 283 284 285
};

class SdpAttrIcePwd : public SdpItem {
public:
ziyue committed
286 287
    SdpAttrIcePwd() = default;
    SdpAttrIcePwd(string str) {value = std::move(str);}
288
    //a=ice-pwd:yEclOTrLg1gEubBFefOqtmyV
289 290 291 292 293 294
    const char* getKey() const override { return "ice-pwd";}
};

class SdpAttrIceOption : public SdpItem {
public:
    //a=ice-options:trickle
ziyue committed
295 296 297 298
    bool trickle{false};
    bool renomination{false};
    void parse(const string &str) override;
    string toString() const override;
299
    const char* getKey() const override { return "ice-options";}
300 301 302 303 304 305
};

class SdpAttrFingerprint : public SdpItem {
public:
    //a=fingerprint:sha-256 22:14:B5:AF:66:12:C7:C7:8D:EF:4B:DE:40:25:ED:5D:8F:17:54:DD:88:33:C0:13:2E:FD:1A:FA:7E:7A:1B:79
    string algorithm;
306 307 308
    string hash;
    void parse(const string &str) override;
    string toString() const override;
309
    const char* getKey() const override { return "fingerprint";}
xiongziliang committed
310
    bool empty() const { return algorithm.empty() || hash.empty(); }
311 312 313 314 315
};

class SdpAttrSetup : public SdpItem {
public:
    //a=setup:actpass
ziyue committed
316 317
    SdpAttrSetup() = default;
    SdpAttrSetup(DtlsRole r) { role = r; }
318 319 320
    DtlsRole role{DtlsRole::actpass};
    void parse(const string &str) override;
    string toString() const override;
321
    const char* getKey() const override { return "setup";}
322 323 324 325
};

class SdpAttrMid : public SdpItem {
public:
ziyue committed
326 327
    SdpAttrMid() = default;
    SdpAttrMid(string val) { value = std::move(val); }
328
    //a=mid:audio
329
    const char* getKey() const override { return "mid";}
330 331 332 333
};

class SdpAttrExtmap : public SdpItem {
public:
xiongziliang committed
334
    //https://aggresss.blog.csdn.net/article/details/106436703
xiongziliang committed
335
    //a=extmap:1[/sendonly] urn:ietf:params:rtp-hdrext:ssrc-audio-level
xiongziliang committed
336
    uint32_t index;
xiongziliang committed
337
    RtpDirection direction{RtpDirection::invalid};
338 339 340
    string ext;
    void parse(const string &str) override;
    string toString() const override;
341
    const char* getKey() const override { return "extmap";}
342 343 344 345 346 347 348
};

class SdpAttrRtpMap : public SdpItem {
public:
    //a=rtpmap:111 opus/48000/2
    uint8_t pt;
    string codec;
xiongziliang committed
349 350
    uint32_t sample_rate;
    uint32_t channel {0};
351 352
    void parse(const string &str) override;
    string toString() const override;
353
    const char* getKey() const override { return "rtpmap";}
354 355 356 357
};

class SdpAttrRtcpFb : public SdpItem {
public:
xiongziliang committed
358 359 360 361 362 363
    //a=rtcp-fb:98 nack pli
    //a=rtcp-fb:120 nack 支持 nack 重传,nack (Negative-Acknowledgment) 。
    //a=rtcp-fb:120 nack pli 支持 nack 关键帧重传,PLI (Picture Loss Indication) 。
    //a=rtcp-fb:120 ccm fir 支持编码层关键帧请求,CCM (Codec Control Message),FIR (Full Intra Request ),通常与 nack pli 有同样的效果,但是 nack pli 是用于重传时的关键帧请求。
    //a=rtcp-fb:120 goog-remb 支持 REMB (Receiver Estimated Maximum Bitrate) 。
    //a=rtcp-fb:120 transport-cc 支持 TCC (Transport Congest Control) 。
364
    uint8_t pt;
xiongziliang committed
365
    string rtcp_type;
366 367
    void parse(const string &str) override;
    string toString() const override;
368
    const char* getKey() const override { return "rtcp-fb";}
369 370 371 372
};

class SdpAttrFmtp : public SdpItem {
public:
373
    //fmtp:96 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
374
    uint8_t pt;
375 376 377
    vector<std::pair<string, string> > arr;
    void parse(const string &str) override;
    string toString() const override;
378
    const char* getKey() const override { return "fmtp";}
379 380 381 382
};

class SdpAttrSSRC : public SdpItem {
public:
xiongziliang committed
383 384 385 386
    //a=ssrc:3245185839 cname:Cx4i/VTR51etgjT7
    //a=ssrc:3245185839 msid:cb373bff-0fea-4edb-bc39-e49bb8e8e3b9 0cf7e597-36a2-4480-9796-69bf0955eef5
    //a=ssrc:3245185839 mslabel:cb373bff-0fea-4edb-bc39-e49bb8e8e3b9
    //a=ssrc:3245185839 label:0cf7e597-36a2-4480-9796-69bf0955eef5
387 388
    //a=ssrc:<ssrc-id> <attribute>
    //a=ssrc:<ssrc-id> <attribute>:<value>
xiongziliang committed
389 390 391 392 393 394 395 396
    //cname 是必须的,msid/mslabel/label 这三个属性都是 WebRTC 自创的,或者说 Google 自创的,可以参考 https://tools.ietf.org/html/draft-ietf-mmusic-msid-17,
    // 理解它们三者的关系需要先了解三个概念:RTP stream / MediaStreamTrack / MediaStream :
    //一个 a=ssrc 代表一个 RTP stream ;
    //一个 MediaStreamTrack 通常包含一个或多个 RTP stream,例如一个视频 MediaStreamTrack 中通常包含两个 RTP stream,一个用于常规传输,一个用于 nack 重传;
    //一个 MediaStream 通常包含一个或多个 MediaStreamTrack ,例如 simulcast 场景下,一个 MediaStream 通常会包含三个不同编码质量的 MediaStreamTrack ;
    //这种标记方式并不被 Firefox 认可,在 Firefox 生成的 SDP 中一个 a=ssrc 通常只有一行,例如:
    //a=ssrc:3245185839 cname:Cx4i/VTR51etgjT7

397
    uint32_t ssrc;
398 399 400 401
    string attribute;
    string attribute_value;
    void parse(const string &str) override;
    string toString() const override;
402 403 404 405 406
    const char* getKey() const override { return "ssrc";}
};

class SdpAttrSSRCGroup : public SdpItem {
public:
xiongziliang committed
407
    //a=ssrc-group 定义参考 RFC 5576(https://tools.ietf.org/html/rfc5576) ,用于描述多个 ssrc 之间的关联,常见的有两种:
408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    //a=ssrc-group:FID 2430709021 3715850271
    // FID (Flow Identification) 最初用在 FEC 的关联中,WebRTC 中通常用于关联一组常规 RTP stream 和 重传 RTP stream 。
    //a=ssrc-group:SIM 360918977 360918978 360918980
    // 在 Chrome 独有的 SDP munging 风格的 simulcast 中使用,将三组编码质量由低到高的 MediaStreamTrack 关联在一起。
    string type{"FID"};
    union {
        struct {
            uint32_t rtp_ssrc;
            uint32_t rtx_ssrc;
        } fid;
        struct {
            uint32_t rtp_ssrc_low;
            uint32_t rtp_ssrc_mid;
            uint32_t rtp_ssrc_high;
        } sim;
    } u;

xiongziliang committed
425 426
    bool isFID() const { return type == "FID"; }
    bool isSIM() const { return type == "SIM"; }
427 428 429
    void parse(const string &str) override;
    string toString() const override;
    const char* getKey() const override { return "ssrc-group";}
430 431 432 433
};

class SdpAttrSctpMap : public SdpItem {
public:
434 435 436
    //https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-05
    //a=sctpmap:5000 webrtc-datachannel 1024
    //a=sctpmap: sctpmap-number media-subtypes [streams]
437
    uint16_t port;
438
    string subtypes;
xiongziliang committed
439
    uint32_t streams;
440 441
    void parse(const string &str) override;
    string toString() const override;
442
    const char* getKey() const override { return "sctpmap";}
443 444 445 446
};

class SdpAttrCandidate : public SdpItem {
public:
ziyue committed
447
    using Ptr = std::shared_ptr<SdpAttrCandidate>;
448 449 450 451
    //https://tools.ietf.org/html/rfc5245
    //15.1.  "candidate" Attribute
    //a=candidate:4 1 udp 2 192.168.1.7 58107 typ host
    //a=candidate:<foundation> <component-id> <transport> <priority> <address> <port> typ <cand-type>
452
    string foundation;
ziyue committed
453
    //传输媒体的类型,1代表RTP;2代表 RTCP。
454 455 456 457 458 459 460 461 462 463
    uint32_t component;
    string transport {"udp"};
    uint32_t priority;
    string address;
    uint16_t port;
    string type;
    vector<std::pair<string, string> > arr;

    void parse(const string &str) override;
    string toString() const override;
464
    const char* getKey() const override { return "candidate";}
465 466
};

ziyue committed
467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
class SdpAttrMsid : public SdpItem{
public:
    const char* getKey() const override { return "msid";}
};

class SdpAttrExtmapAllowMixed : public SdpItem{
public:
    const char* getKey() const override { return "extmap-allow-mixed";}
};

class SdpAttrSimulcast : public SdpItem{
public:
    //todo
    const char* getKey() const override { return "simulcast";}
};

class SdpAttrRid : public SdpItem{
public:
    //todo
    const char* getKey() const override { return "rid";}
};

ziyue committed
489
class RtcSdpBase {
490 491
public:
    vector<SdpItem::Ptr> items;
ziyue committed
492 493

public:
xiongziliang committed
494
    virtual ~RtcSdpBase() = default;
ziyue committed
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510
    virtual string toString() const;

    int getVersion() const;
    SdpOrigin getOrigin() const;
    string getSessionName() const;
    string getSessionInfo() const;
    SdpTime getSessionTime() const;
    SdpConnection getConnection() const;
    SdpBandwidth getBandwidth() const;

    string getUri() const;
    string getEmail() const;
    string getPhone() const;
    string getTimeZone() const;
    string getEncryptKey() const;
    string getRepeatTimes() const;
511
    RtpDirection getDirection() const;
ziyue committed
512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528

    template<typename cls>
    cls getItemClass(char key, const char *attr_key = nullptr) const{
        auto item = dynamic_pointer_cast<cls>(getItem(key, attr_key));
        if (!item) {
            return cls();
        }
        return *item;
    }

    string getStringItem(char key, const char *attr_key = nullptr) const{
        auto item = getItem(key, attr_key);
        if (!item) {
            return "";
        }
        return item->toString();
    }
ziyue committed
529 530

    SdpItem::Ptr getItem(char key, const char *attr_key = nullptr) const;
xiongziliang committed
531 532

    template<typename cls>
533
    vector<cls> getAllItem(char key_c, const char *attr_key = nullptr) const {
xiongziliang committed
534 535
        vector<cls> ret;
        for (auto item : items) {
536 537
            string key(1, key_c);
            if (strcasecmp(item->getKey(), key.data()) == 0) {
xiongziliang committed
538 539 540 541 542 543 544
                if (!attr_key) {
                    auto c = dynamic_pointer_cast<cls>(item);
                    if (c) {
                        ret.emplace_back(*c);
                    }
                } else {
                    auto attr = dynamic_pointer_cast<SdpAttr>(item);
545
                    if (attr && !strcasecmp(attr->detail->getKey(), attr_key)) {
xiongziliang committed
546 547 548 549 550 551 552 553 554 555
                        auto c = dynamic_pointer_cast<cls>(attr->detail);
                        if (c) {
                            ret.emplace_back(*c);
                        }
                    }
                }
            }
        }
        return ret;
    }
ziyue committed
556
};
xiongziliang committed
557

ziyue committed
558
class RtcSessionSdp : public RtcSdpBase{
ziyue committed
559
public:
xiongziliang committed
560 561
    using Ptr = std::shared_ptr<RtcSessionSdp>;

ziyue committed
562
    vector<RtcSdpBase> medias;
563
    void parse(const string &str);
ziyue committed
564
    string toString() const override;
ziyue committed
565 566
};

ziyue committed
567 568 569 570 571
//////////////////////////////////////////////////////////////////

//ssrc相关信息
class RtcSSRC{
public:
xiongziliang committed
572
    uint32_t ssrc {0};
ziyue committed
573 574 575 576
    string cname;
    string msid;
    string mslabel;
    string label;
xiongziliang committed
577

578
    bool empty() const {return ssrc == 0 && cname.empty();}
ziyue committed
579 580 581
};

//rtc传输编码方案
ziyue committed
582
class RtcCodecPlan{
ziyue committed
583
public:
584
    using Ptr = shared_ptr<RtcCodecPlan>;
ziyue committed
585 586 587 588 589
    uint8_t pt;
    string codec;
    uint32_t sample_rate;
    //音频时有效
    uint32_t channel = 0;
xiongziliang committed
590
    //rtcp反馈
ziyue committed
591
    vector<string> rtcp_fb;
ziyue committed
592
    vector<std::pair<string/*key*/, string/*value*/> > fmtp;
xiongziliang committed
593 594

    string getFmtp(const char *key) const;
ziyue committed
595 596 597
};

//rtc 媒体描述
ziyue committed
598
class RtcMedia{
ziyue committed
599
public:
xiongziliang committed
600
    TrackType type{TrackType::TrackInvalid};
ziyue committed
601
    string mid;
xiongziliang committed
602 603
    uint16_t port{0};
    SdpConnection addr;
ziyue committed
604
    string proto;
xiongziliang committed
605 606
    RtpDirection direction{RtpDirection::invalid};
    vector<RtcCodecPlan> plan;
ziyue committed
607 608

    //////// rtp ////////
xiongziliang committed
609
    RtcSSRC rtp_ssrc;
xiongziliang committed
610 611 612
    RtcSSRC rtx_ssrc;

    //////// simulcast ////////
xiongziliang committed
613 614 615 616
    RtcSSRC rtp_ssrc_low;
    RtcSSRC rtp_ssrc_mid;
    RtcSSRC rtp_ssrc_high;

xiongziliang committed
617 618 619
    ////////  rtcp  ////////
    bool rtcp_mux{false};
    bool rtcp_rsize{false};
ziyue committed
620 621 622
    SdpAttrRtcp rtcp_addr;

    //////// ice ////////
xiongziliang committed
623 624 625
    bool ice_trickle{false};
    bool ice_lite{false};
    bool ice_renomination{false};
ziyue committed
626 627 628 629 630
    string ice_ufrag;
    string ice_pwd;
    std::vector<SdpAttrCandidate> candidate;

    //////// dtls ////////
xiongziliang committed
631
    DtlsRole role{DtlsRole::invalid};
ziyue committed
632 633 634 635
    SdpAttrFingerprint fingerprint;

    //////// extmap ////////
    vector<SdpAttrExtmap> extmap;
xiongziliang committed
636 637 638

    //////// sctp ////////////
    SdpAttrSctpMap sctpmap;
xiongziliang committed
639 640 641 642
    uint32_t sctp_port{0};

    void checkValid() const;
    const RtcCodecPlan *getPlan(uint8_t pt) const;
643
    const RtcCodecPlan *getPlan(const char *codec) const;
644
    const RtcCodecPlan *getRelatedRtxPlan(uint8_t pt) const;
ziyue committed
645
};
ziyue committed
646

ziyue committed
647 648
class RtcSession{
public:
ziyue committed
649 650
    using Ptr = std::shared_ptr<RtcSession>;

xiongziliang committed
651
    uint32_t version;
ziyue committed
652 653 654
    SdpOrigin origin;
    string session_name;
    string session_info;
655
    SdpTime time;
ziyue committed
656 657
    SdpConnection connection;
    SdpBandwidth bandwidth;
xiongziliang committed
658
    SdpAttrMsidSemantic msid_semantic;
ziyue committed
659
    vector<RtcMedia> media;
xiongziliang committed
660
    SdpAttrGroup group;
ziyue committed
661

ziyue committed
662
    void loadFrom(const string &sdp, bool check = true);
xiongziliang committed
663
    void checkValid() const;
ziyue committed
664
    string toString() const;
xiongziliang committed
665 666 667 668 669
    string toRtspSdp() const;
    const  RtcMedia *getMedia(TrackType type) const;

private:
    RtcSessionSdp::Ptr toRtcSessionSdp() const;
ziyue committed
670
};
ziyue committed
671

ziyue committed
672 673
class RtcConfigure {
public:
ziyue committed
674
    using Ptr = std::shared_ptr<RtcConfigure>;
ziyue committed
675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709
    class RtcTrackConfigure {
    public:
        bool enable;
        bool rtcp_mux;
        bool rtcp_rsize;
        bool group_bundle;
        bool support_rtx;
        bool support_red;
        bool support_ulpfec;
        bool ice_lite;
        bool ice_trickle;
        bool ice_renomination;
        string ice_ufrag;
        string ice_pwd;

        RtpDirection direction{RtpDirection::invalid};
        SdpAttrFingerprint fingerprint;

        vector<string> rtcp_fb;
        vector<CodecId> preferred_codec;
        vector<string> extmap;
        vector<SdpAttrCandidate> candidate;

        void setDefaultSetting(TrackType type);
    };

    RtcTrackConfigure video;
    RtcTrackConfigure audio;
    RtcTrackConfigure application;

    void setDefaultSetting(string ice_ufrag,
                           string ice_pwd,
                           RtpDirection direction,
                           const SdpAttrFingerprint &fingerprint);
    void addCandidate(const SdpAttrCandidate &candidate, TrackType type = TrackInvalid);
ziyue committed
710 711

    shared_ptr<RtcSession> createAnswer(const RtcSession &offer);
ziyue committed
712

713 714
    void setPlayRtspInfo(const string &sdp);

ziyue committed
715 716
private:
    void matchMedia(shared_ptr<RtcSession> &ret, TrackType type, const vector<RtcMedia> &medias, const RtcTrackConfigure &configure);
717
    bool onCheckCodecProfile(const RtcCodecPlan &plan, CodecId codec);
718 719 720 721

private:
    RtcCodecPlan::Ptr _rtsp_video_plan;
    RtcCodecPlan::Ptr _rtsp_audio_plan;
ziyue committed
722 723
};

ziyue committed
724 725

#endif //ZLMEDIAKIT_SDP_H