Skip to content
项目
群组
代码片段
帮助
当前项目
正在载入...
登录 / 注册
切换导航面板
Z
ZLMediaKit
概览
Overview
Details
Activity
Cycle Analytics
版本库
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
问题
0
Issues
0
列表
Board
标记
里程碑
合并请求
0
Merge Requests
0
CI / CD
CI / CD
流水线
作业
日程表
图表
维基
Wiki
代码片段
Snippets
成员
Collapse sidebar
Close sidebar
活动
图像
聊天
创建新问题
作业
提交
Issue Boards
Open sidebar
张翔宇
ZLMediaKit
Commits
81f29fea
Commit
81f29fea
authored
Mar 28, 2021
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
基本完成sdp的解析和生成
parent
f4746d16
隐藏空白字符变更
内嵌
并排
正在显示
3 个修改的文件
包含
650 行增加
和
225 行删除
+650
-225
src/Extension/Frame.h
+1
-1
webrtc/Sdp.cpp
+530
-5
webrtc/Sdp.h
+119
-219
没有找到文件。
src/Extension/Frame.h
查看文件 @
81f29fea
...
...
@@ -38,7 +38,7 @@ typedef enum {
TrackVideo
=
0
,
TrackAudio
,
TrackTitle
,
Track
Data
,
Track
Application
,
TrackMax
=
4
}
TrackType
;
...
...
webrtc/Sdp.cpp
查看文件 @
81f29fea
...
...
@@ -3,6 +3,7 @@
//
#include "Sdp.h"
#include <inttypes.h>
using
onCreateSdpItem
=
function
<
SdpItem
::
Ptr
(
const
string
&
key
,
const
string
&
value
)
>
;
static
unordered_map
<
string
,
onCreateSdpItem
>
sdpItemCreator
;
...
...
@@ -15,10 +16,38 @@ void registerSdpItem(){
return
ret
;
};
Item
item
;
InfoL
<<
"register sdp item:"
<<
item
.
getKey
();
sdpItemCreator
.
emplace
(
item
.
getKey
(),
std
::
move
(
func
));
}
class
DirectionInterface
{
public
:
virtual
RtpDirection
getDirection
()
=
0
;
};
class
SdpDirectionSendonly
:
public
SdpItem
,
public
DirectionInterface
{
public
:
const
char
*
getKey
()
override
{
return
getRtpDirectionString
(
getDirection
());}
RtpDirection
getDirection
()
override
{
return
RtpDirection
::
sendonly
;}
};
class
SdpDirectionRecvonly
:
public
SdpItem
,
public
DirectionInterface
{
public
:
const
char
*
getKey
()
override
{
return
getRtpDirectionString
(
getDirection
());}
RtpDirection
getDirection
()
override
{
return
RtpDirection
::
recvonly
;}
};
class
SdpDirectionSendrecv
:
public
SdpItem
,
public
DirectionInterface
{
public
:
const
char
*
getKey
()
override
{
return
getRtpDirectionString
(
getDirection
());}
RtpDirection
getDirection
()
override
{
return
RtpDirection
::
sendrecv
;}
};
class
SdpDirectionInactive
:
public
SdpItem
,
public
DirectionInterface
{
public
:
const
char
*
getKey
()
override
{
return
getRtpDirectionString
(
getDirection
());}
RtpDirection
getDirection
()
override
{
return
RtpDirection
::
inactive
;}
};
static
bool
registerAllItem
(){
registerSdpItem
<
SdpString
<
'v'
>
>
();
registerSdpItem
<
SdpString
<
's'
>
>
();
...
...
@@ -49,9 +78,87 @@ static bool registerAllItem(){
registerSdpItem
<
SdpAttrFmtp
>
();
registerSdpItem
<
SdpAttrSSRC
>
();
registerSdpItem
<
SdpAttrSctpMap
>
();
registerSdpItem
<
SdpAttrCandidate
>
();
registerSdpItem
<
SdpDirectionSendonly
>
();
registerSdpItem
<
SdpDirectionRecvonly
>
();
registerSdpItem
<
SdpDirectionSendrecv
>
();
registerSdpItem
<
SdpDirectionInactive
>
();
return
true
;
}
TrackType
getTrackType
(
const
string
&
str
){
if
(
str
==
"video"
)
{
return
TrackVideo
;
}
if
(
str
==
"audio"
)
{
return
TrackAudio
;
}
if
(
str
==
"application"
)
{
return
TrackApplication
;
}
return
TrackInvalid
;
}
const
char
*
getTrackString
(
TrackType
type
){
switch
(
type
)
{
case
TrackVideo
:
return
"video"
;
case
TrackAudio
:
return
"audio"
;
case
TrackApplication
:
return
"application"
;
default
:
return
"invalid"
;
}
}
DtlsRole
getDtlsRole
(
const
string
&
str
){
if
(
str
==
"active"
)
{
return
DtlsRole
::
active
;
}
if
(
str
==
"passive"
)
{
return
DtlsRole
::
passive
;
}
if
(
str
==
"actpass"
)
{
return
DtlsRole
::
actpass
;
}
return
DtlsRole
::
invalid
;
}
const
char
*
getDtlsRoleString
(
DtlsRole
role
){
switch
(
role
)
{
case
DtlsRole
:
:
active
:
return
"active"
;
case
DtlsRole
:
:
passive
:
return
"passive"
;
case
DtlsRole
:
:
actpass
:
return
"actpass"
;
default
:
return
"invalid"
;
}
}
RtpDirection
getRtpDirection
(
const
string
&
str
){
if
(
str
==
"sendonly"
)
{
return
RtpDirection
::
sendonly
;
}
if
(
str
==
"recvonly"
)
{
return
RtpDirection
::
recvonly
;
}
if
(
str
==
"sendrecv"
)
{
return
RtpDirection
::
sendrecv
;
}
if
(
str
==
"inactive"
)
{
return
RtpDirection
::
inactive
;
}
return
RtpDirection
::
invalid
;
}
const
char
*
getRtpDirectionString
(
RtpDirection
val
){
switch
(
val
)
{
case
RtpDirection
:
:
sendonly
:
return
"sendonly"
;
case
RtpDirection
:
:
recvonly
:
return
"recvonly"
;
case
RtpDirection
:
:
sendrecv
:
return
"sendrecv"
;
case
RtpDirection
:
:
inactive
:
return
"inactive"
;
default
:
return
"invalid"
;
}
}
//////////////////////////////////////////////////////////////////////////////////////////
void
RtcSdp
::
parse
(
const
string
&
str
)
{
static
auto
flag
=
registerAllItem
();
RtcMedia
*
media
=
nullptr
;
...
...
@@ -85,11 +192,142 @@ void RtcSdp::parse(const string &str) {
}
string
RtcSdp
::
toString
()
const
{
return
std
::
string
();
_StrPrinter
printer
;
for
(
auto
&
item
:
items
)
{
printer
<<
item
->
getKey
()
<<
"="
<<
item
->
toString
()
<<
"
\r\n
"
;
}
for
(
auto
&
media
:
medias
)
{
printer
<<
media
.
toString
();
}
return
std
::
move
(
printer
);
}
//////////////////////////////////////////////////////////////////////
string
RtcMedia
::
toString
()
const
{
_StrPrinter
printer
;
for
(
auto
&
item
:
items
)
{
printer
<<
item
->
getKey
()
<<
"="
<<
item
->
toString
()
<<
"
\r\n
"
;
}
return
std
::
move
(
printer
);
}
RtpDirection
RtcMedia
::
getDirection
()
const
{
for
(
auto
&
item
:
items
)
{
auto
attr
=
dynamic_pointer_cast
<
SdpAttr
>
(
item
);
if
(
attr
)
{
auto
dir
=
dynamic_pointer_cast
<
DirectionInterface
>
(
attr
->
detail
);
if
(
dir
)
{
return
dir
->
getDirection
();
}
}
}
return
RtpDirection
::
invalid
;
}
//////////////////////////////////////////////////////////////////////////////////////////
#define SDP_THROW() throw std::invalid_argument(StrPrinter << "解析sdp " << getKey() << " 字段失败:" << str)
void
SdpTime
::
parse
(
const
string
&
str
)
{
if
(
sscanf
(
str
.
data
(),
"%"
PRIu64
" %"
PRIu64
,
&
start
,
&
stop
)
!=
2
)
{
SDP_THROW
();
}
}
string
SdpTime
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
start
)
+
" "
+
to_string
(
stop
);
}
return
SdpItem
::
toString
();
}
void
SdpOrigin
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
!=
6
)
{
SDP_THROW
();
}
username
=
vec
[
0
];
session_id
=
vec
[
1
];
session_version
=
vec
[
2
];
nettype
=
vec
[
3
];
addrtype
=
vec
[
4
];
address
=
vec
[
6
];
}
string
SdpOrigin
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
username
+
" "
+
session_id
+
" "
+
session_version
+
" "
+
nettype
+
" "
+
addrtype
+
" "
+
address
;
}
return
SdpItem
::
toString
();
}
void
SdpConnection
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
!=
3
)
{
SDP_THROW
();
}
nettype
=
vec
[
0
];
addrtype
=
vec
[
1
];
address
=
vec
[
2
];
}
string
SdpConnection
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
nettype
+
" "
+
addrtype
+
" "
+
address
;
}
return
SdpItem
::
toString
();
}
void
SdpBandwidth
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
":"
);
if
(
vec
.
size
()
!=
2
)
{
SDP_THROW
();
}
bwtype
=
vec
[
0
];
bandwidth
=
atoi
(
vec
[
1
].
data
());
}
string
SdpBandwidth
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
bwtype
+
":"
+
to_string
(
bandwidth
);
}
return
SdpItem
::
toString
();
}
void
SdpMedia
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
<
4
)
{
SDP_THROW
();
}
type
=
getTrackType
(
vec
[
0
]);
if
(
type
==
TrackInvalid
)
{
SDP_THROW
();
}
port
=
atoi
(
vec
[
1
].
data
());
proto
=
vec
[
2
];
for
(
int
i
=
3
;
i
<
vec
.
size
();
++
i
)
{
auto
pt
=
atoi
(
vec
[
i
].
data
());
if
(
type
!=
TrackApplication
&&
pt
>
0xFF
)
{
SDP_THROW
();
}
fmts
.
emplace_back
(
pt
);
}
}
string
SdpMedia
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
string
(
getTrackString
(
type
))
+
" "
+
to_string
(
port
)
+
" "
+
proto
;
for
(
auto
fmt
:
fmts
)
{
value
+=
' '
;
value
+=
to_string
(
fmt
);
}
}
return
SdpItem
::
toString
();
}
void
SdpAttr
::
parse
(
const
string
&
str
)
{
SdpItem
::
parse
(
str
);
auto
pos
=
str
.
find
(
':'
);
auto
key
=
pos
==
string
::
npos
?
str
:
str
.
substr
(
0
,
pos
);
auto
value
=
pos
==
string
::
npos
?
string
()
:
str
.
substr
(
pos
+
1
);
...
...
@@ -102,10 +340,290 @@ void SdpAttr::parse(const string &str) {
}
}
string
SdpAttr
::
toString
()
const
{
if
(
value
.
empty
())
{
auto
detail_value
=
detail
->
toString
();
if
(
detail_value
.
empty
())
{
value
=
detail
->
getKey
();
}
else
{
value
=
string
(
detail
->
getKey
())
+
":"
+
detail_value
;
}
}
return
SdpItem
::
toString
();
}
void
SdpAttrGroup
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
<
2
)
{
SDP_THROW
();
}
type
=
vec
[
0
];
vec
.
erase
(
vec
.
begin
());
mids
=
std
::
move
(
vec
);
}
string
SdpAttrGroup
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
type
;
for
(
auto
mid
:
mids
)
{
value
+=
' '
;
value
+=
mid
;
}
}
return
SdpItem
::
toString
();
}
void
SdpAttrMsidSemantic
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
<
1
)
{
SDP_THROW
();
}
msid
=
vec
[
0
];
token
=
vec
.
size
()
>
1
?
vec
[
1
]
:
""
;
}
string
SdpAttrMsidSemantic
::
toString
()
const
{
if
(
value
.
empty
())
{
if
(
token
.
empty
())
{
value
=
string
(
" "
)
+
msid
;
}
else
{
value
=
string
(
" "
)
+
msid
+
" "
+
token
;
}
}
return
SdpItem
::
toString
();
}
void
SdpAttrRtcp
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
!=
4
)
{
SDP_THROW
();
}
port
=
atoi
(
vec
[
0
].
data
());
nettype
=
vec
[
1
];
addrtype
=
vec
[
2
];
address
=
vec
[
3
];
}
string
SdpAttrRtcp
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
port
)
+
" "
+
nettype
+
" "
+
addrtype
+
" "
+
address
;
}
return
SdpItem
::
toString
();
}
void
SdpAttrFingerprint
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
!=
2
)
{
SDP_THROW
();
}
algorithm
=
vec
[
0
];
hash
=
vec
[
1
];
}
string
SdpAttrFingerprint
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
algorithm
+
" "
+
hash
;
}
return
SdpItem
::
toString
();
}
void
SdpAttrSetup
::
parse
(
const
string
&
str
)
{
role
=
getDtlsRole
(
str
);
if
(
role
==
DtlsRole
::
invalid
)
{
SDP_THROW
();
}
}
string
SdpAttrSetup
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
getDtlsRoleString
(
role
);
}
return
SdpItem
::
toString
();
}
void
SdpAttrExtmap
::
parse
(
const
string
&
str
)
{
char
buf
[
128
]
=
{
0
};
if
(
sscanf
(
str
.
data
(),
"%"
PRId32
" %127s"
,
&
index
,
buf
)
!=
2
)
{
SDP_THROW
();
}
ext
=
buf
;
}
string
SdpAttrExtmap
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
index
)
+
" "
+
ext
;
}
return
SdpItem
::
toString
();
}
void
SdpAttrRtpMap
::
parse
(
const
string
&
str
)
{
char
buf
[
32
]
=
{
0
};
if
(
sscanf
(
str
.
data
(),
"%"
PRId8
" %31[^/]/%"
PRId32
"/%"
PRId32
,
&
pt
,
buf
,
&
sample_rate
,
&
channel
)
!=
4
)
{
if
(
sscanf
(
str
.
data
(),
"%"
PRId8
" %31[^/]/%"
PRId32
,
&
pt
,
buf
,
&
sample_rate
)
!=
3
)
{
SDP_THROW
();
}
}
codec
=
buf
;
}
string
SdpAttrRtpMap
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
pt
)
+
" "
+
codec
+
"/"
+
to_string
(
sample_rate
);
if
(
channel
)
{
value
+=
'/'
;
value
+=
to_string
(
channel
);
}
}
return
SdpItem
::
toString
();
}
void
SdpAttrRtcpFb
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
<
2
)
{
SDP_THROW
();
}
pt
=
atoi
(
vec
[
0
].
data
());
vec
.
erase
(
vec
.
begin
());
arr
=
std
::
move
(
vec
);
}
string
SdpAttrRtcpFb
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
pt
);
for
(
auto
&
item
:
arr
)
{
value
+=
' '
;
value
+=
item
;
}
}
return
SdpItem
::
toString
();
}
void
SdpAttrFmtp
::
parse
(
const
string
&
str
)
{
auto
pos
=
str
.
find
(
' '
);
if
(
pos
==
string
::
npos
)
{
SDP_THROW
();
}
pt
=
atoi
(
str
.
substr
(
0
,
pos
).
data
());
auto
vec
=
split
(
str
.
substr
(
pos
+
1
),
";"
);
for
(
auto
&
item
:
vec
)
{
trim
(
item
);
auto
pr_vec
=
split
(
item
,
"="
);
if
(
pr_vec
.
size
()
!=
2
)
{
SDP_THROW
();
}
arr
.
emplace_back
(
std
::
make_pair
(
pr_vec
[
0
],
pr_vec
[
1
]));
}
if
(
arr
.
empty
())
{
SDP_THROW
();
}
}
string
SdpAttrFmtp
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
pt
);
int
i
=
0
;
for
(
auto
&
pr
:
arr
)
{
value
+=
(
i
++
?
';'
:
' '
);
value
+=
pr
.
first
+
"="
+
pr
.
second
;
}
}
return
SdpItem
::
toString
();
}
void
SdpAttrSSRC
::
parse
(
const
string
&
str
)
{
char
attr_buf
[
32
]
=
{
0
};
char
attr_val_buf
[
128
]
=
{
0
};
if
(
3
==
sscanf
(
str
.
data
(),
"%"
PRIu32
" %31[^:]:%127[^
\0
]"
,
&
ssrc
,
attr_buf
,
attr_val_buf
))
{
attribute
=
attr_buf
;
attribute_value
=
attr_val_buf
;
}
else
if
(
2
==
sscanf
(
str
.
data
(),
"%"
PRIu32
" %31s"
,
&
ssrc
,
attr_buf
))
{
attribute
=
attr_buf
;
}
else
{
SDP_THROW
();
}
}
string
SdpAttrSSRC
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
ssrc
)
+
' '
;
value
+=
attribute
;
if
(
!
attribute_value
.
empty
())
{
value
+=
':'
;
value
+=
attribute_value
;
}
}
return
SdpItem
::
toString
();
}
void
SdpAttrSctpMap
::
parse
(
const
string
&
str
)
{
char
subtypes_buf
[
64
]
=
{
0
};
if
(
3
==
sscanf
(
str
.
data
(),
"%"
PRIu16
" %63[^ ] %"
PRId32
,
&
port
,
subtypes_buf
,
&
streams
))
{
subtypes
=
subtypes_buf
;
}
else
{
SDP_THROW
();
}
}
string
SdpAttrSctpMap
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
port
);
value
+=
' '
;
value
+=
subtypes
;
value
+=
' '
;
value
+=
to_string
(
streams
);
}
return
SdpItem
::
toString
();
}
void
SdpAttrCandidate
::
parse
(
const
string
&
str
)
{
char
transport_buf
[
16
]
=
{
0
};
char
address_buf
[
32
]
=
{
0
};
char
type_buf
[
16
]
=
{
0
};
if
(
7
!=
sscanf
(
str
.
data
(),
"%"
PRIu32
" %"
PRIu32
" %15[^ ] %"
PRIu32
" %31[^ ] %"
PRIu16
" typ %15[^
\0
]"
,
&
foundation
,
&
component
,
transport_buf
,
&
priority
,
address_buf
,
&
port
,
type_buf
))
{
SDP_THROW
();
}
transport
=
transport_buf
;
address
=
address_buf
;
type
=
type_buf
;
auto
pos
=
str
.
find
(
type
);
if
(
pos
!=
string
::
npos
)
{
auto
remain
=
str
.
substr
(
pos
+
type
.
size
());
trim
(
remain
);
if
(
!
remain
.
empty
())
{
auto
vec
=
split
(
remain
,
" "
);
string
key
;
for
(
auto
&
item
:
vec
)
{
if
(
key
.
empty
())
{
key
=
item
;
}
else
{
arr
.
emplace_back
(
std
::
make_pair
(
std
::
move
(
key
),
std
::
move
(
item
)));
}
}
}
}
}
string
SdpAttrCandidate
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
foundation
)
+
" "
+
to_string
(
component
)
+
" "
+
transport
+
" "
+
to_string
(
priority
)
+
" "
+
address
+
" "
+
to_string
(
port
)
+
" typ "
+
type
;
for
(
auto
&
pr
:
arr
)
{
value
+=
' '
;
value
+=
pr
.
first
;
value
+=
' '
;
value
+=
pr
.
second
;
}
}
return
SdpItem
::
toString
();
}
void
test_sdp
(){
char
str1
[]
=
"v=0
\n
"
"o=- 380154348540553537 2 IN IP4 127.0.0.1
\n
"
"s=-
\n
"
"b=CT:1900
\n
"
"t=0 0
\n
"
"a=group:BUNDLE video
\n
"
"a=msid-semantic: WMS
\n
"
...
...
@@ -212,7 +730,7 @@ void test_sdp(){
"a=ssrc:611523443 msid:616cfbb1-33a3-4d8c-8275-a199d6005549 bf270496-a23e-47b5-b901-ef23096cd961
\n
"
"a=ssrc:611523443 mslabel:616cfbb1-33a3-4d8c-8275-a199d6005549
\n
"
"a=ssrc:611523443 label:bf270496-a23e-47b5-b901-ef23096cd961
\n
"
"a=candidate:
1 1 udp %u %s %u typ host
\n
"
"a=candidate:
3575467457 1 udp 2113937151 10.15.83.23 57857 typ host generation 0 ufrag 6R0z network-cost 999
\n
"
"m=application 9 DTLS/SCTP 5000
\n
"
"c=IN IP4 0.0.0.0
\n
"
"a=ice-ufrag:sXJ3
\n
"
...
...
@@ -220,7 +738,8 @@ void test_sdp(){
"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
\n
"
"a=setup:actpass
\n
"
"a=mid:data
\n
"
"a=sctpmap:5000 webrtc-datachannel 1024"
;
"a=sctpmap:5000 webrtc-datachannel 1024
\n
"
"a=sctp-port:5000"
;
RtcSdp
sdp1
;
sdp1
.
parse
(
str1
);
...
...
@@ -228,6 +747,12 @@ void test_sdp(){
RtcSdp
sdp2
;
sdp2
.
parse
(
str2
);
for
(
auto
media
:
sdp1
.
medias
)
{
InfoL
<<
getRtpDirectionString
(
media
.
getDirection
());
}
for
(
auto
media
:
sdp2
.
medias
)
{
InfoL
<<
getRtpDirectionString
(
media
.
getDirection
());
}
InfoL
<<
sdp1
.
toString
();
InfoL
<<
sdp2
.
toString
();
}
webrtc/Sdp.h
查看文件 @
81f29fea
...
...
@@ -12,107 +12,6 @@ using namespace std;
using
namespace
mediakit
;
//https://datatracker.ietf.org/doc/rfc4566/?include_text=1
//v=0
//o=- 2584450093346841581 2 IN IP4 127.0.0.1
//s=-
//t=0 0
//a=group:BUNDLE audio video data
//a=msid-semantic: WMS 616cfbb1-33a3-4d8c-8275-a199d6005549
//m=audio 9 UDP/TLS/RTP/SAVPF 111 103 104 9 0 8 106 105 13 110 112 113 126
//c=IN IP4 0.0.0.0
//a=rtcp:9 IN IP4 0.0.0.0
//a=ice-ufrag:sXJ3
//a=ice-pwd:yEclOTrLg1gEubBFefOqtmyV
//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
//a=setup:actpass
//a=mid:audio
//a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
//a=sendrecv
//a=rtcp-mux
//a=rtpmap:111 opus/48000/2
//a=rtcp-fb:111 transport-cc
//a=fmtp:111 minptime=10;useinbandfec=1
//a=rtpmap:103 ISAC/16000
//a=rtpmap:104 ISAC/32000
//a=rtpmap:9 G722/8000
//a=rtpmap:0 PCMU/8000
//a=rtpmap:8 PCMA/8000
//a=rtpmap:106 CN/32000
//a=rtpmap:105 CN/16000
//a=rtpmap:13 CN/8000
//a=rtpmap:110 telephone-event/48000
//a=rtpmap:112 telephone-event/32000
//a=rtpmap:113 telephone-event/16000
//a=rtpmap:126 telephone-event/8000
//a=ssrc:120276603 cname:iSkJ2vn5cYYubTve
//a=ssrc:120276603 msid:616cfbb1-33a3-4d8c-8275-a199d6005549 1da3d329-7399-4fe9-b20f-69606bebd363
//a=ssrc:120276603 mslabel:616cfbb1-33a3-4d8c-8275-a199d6005549
//a=ssrc:120276603 label:1da3d329-7399-4fe9-b20f-69606bebd363
//m=video 9 UDP/TLS/RTP/SAVPF 96 98 100 102 127 97 99 101 125
//c=IN IP4 0.0.0.0
//a=rtcp:9 IN IP4 0.0.0.0
//a=ice-ufrag:sXJ3
//a=ice-pwd:yEclOTrLg1gEubBFefOqtmyV
//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
//a=setup:actpass
//a=mid:video
//a=extmap:2 urn:ietf:params:rtp-hdrext:toffset
//a=extmap:3 http://www.webrtc.org/experiments/rtp-hdrext/abs-send-time
//a=extmap:4 urn:3gpp:video-orientation
//a=extmap:5 http://www.ietf.org/id/draft-holmer-rmcat-transport-wide-cc-extensions-01
//a=extmap:6 http://www.webrtc.org/experiments/rtp-hdrext/playout-delay
//a=sendrecv
//a=rtcp-mux
//a=rtcp-rsize
//a=rtpmap:96 VP8/90000
//a=rtcp-fb:96 ccm fir
//a=rtcp-fb:96 nack
//a=rtcp-fb:96 nack pli
//a=rtcp-fb:96 goog-remb
//a=rtcp-fb:96 transport-cc
//a=rtpmap:98 VP9/90000
//a=rtcp-fb:98 ccm fir
//a=rtcp-fb:98 nack
//a=rtcp-fb:98 nack pli
//a=rtcp-fb:98 goog-remb
//a=rtcp-fb:98 transport-cc
//a=rtpmap:100 H264/90000
//a=rtcp-fb:100 ccm fir
//a=rtcp-fb:100 nack
//a=rtcp-fb:100 nack pli
//a=rtcp-fb:100 goog-remb
//a=rtcp-fb:100 transport-cc
//a=fmtp:100 level-asymmetry-allowed=1;packetization-mode=1;profile-level-id=42e01f
//a=rtpmap:102 red/90000
//a=rtpmap:127 ulpfec/90000
//a=rtpmap:97 rtx/90000
//a=fmtp:97 apt=96
//a=rtpmap:99 rtx/90000
//a=fmtp:99 apt=98
//a=rtpmap:101 rtx/90000
//a=fmtp:101 apt=100
//a=rtpmap:125 rtx/90000
//a=fmtp:125 apt=102
//a=ssrc-group:FID 2580761338 611523443
//a=ssrc:2580761338 cname:iSkJ2vn5cYYubTve
//a=ssrc:2580761338 msid:616cfbb1-33a3-4d8c-8275-a199d6005549 bf270496-a23e-47b5-b901-ef23096cd961
//a=ssrc:2580761338 mslabel:616cfbb1-33a3-4d8c-8275-a199d6005549
//a=ssrc:2580761338 label:bf270496-a23e-47b5-b901-ef23096cd961
//a=ssrc:611523443 cname:iSkJ2vn5cYYubTve
//a=ssrc:611523443 msid:616cfbb1-33a3-4d8c-8275-a199d6005549 bf270496-a23e-47b5-b901-ef23096cd961
//a=ssrc:611523443 mslabel:616cfbb1-33a3-4d8c-8275-a199d6005549
//a=ssrc:611523443 label:bf270496-a23e-47b5-b901-ef23096cd961
//a=candidate:1 1 udp %u %s %u typ host
//m=application 9 DTLS/SCTP 5000
//c=IN IP4 0.0.0.0
//a=ice-ufrag:sXJ3
//a=ice-pwd:yEclOTrLg1gEubBFefOqtmyV
//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
//a=setup:actpass
//a=mid:data
//a=sctpmap:5000 webrtc-datachannel 1024
//Session description
// v= (protocol version)
// o= (originator and session identifier)
...
...
@@ -148,7 +47,7 @@ enum class RtpDirection {
//只发送
sendonly
,
//只接收
revonly
,
re
c
vonly
,
//同时发送接收
sendrecv
,
//禁止发送数据
...
...
@@ -171,10 +70,16 @@ enum class SdpType {
answer
};
TrackType
getTrackType
(
const
string
&
str
);
const
char
*
getTrackString
(
TrackType
type
);
DtlsRole
getDtlsRole
(
const
string
&
str
);
const
char
*
getDtlsRoleString
(
DtlsRole
role
);
RtpDirection
getRtpDirection
(
const
string
&
str
);
const
char
*
getRtpDirectionString
(
RtpDirection
val
);
class
SdpItem
{
public
:
using
Ptr
=
std
::
shared_ptr
<
SdpItem
>
;
string
value
;
virtual
~
SdpItem
()
=
default
;
virtual
void
parse
(
const
string
&
str
)
{
value
=
str
;
...
...
@@ -183,6 +88,9 @@ public:
return
value
;
}
virtual
const
char
*
getKey
()
=
0
;
protected
:
mutable
string
value
;
};
template
<
char
KEY
>
...
...
@@ -203,10 +111,10 @@ class SdpTime : public SdpItem{
public
:
//5.9. Timing ("t=")
// t=<start-time> <stop-time>
uint64_t
start
;
uint64_t
stop
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
uint64_t
start
{
0
}
;
uint64_t
stop
{
0
}
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"t"
;}
};
...
...
@@ -215,14 +123,14 @@ public:
// 5.2. Origin ("o=")
// o=jdoe 2890844526 2890842807 IN IP4 10.47.16.5
// o=<username> <sess-id> <sess-version> <nettype> <addrtype> <unicast-address>
string
username
;
string
username
{
"-"
}
;
string
session_id
;
string
session_version
;
string
nettype
;
string
addrtype
;
string
address
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
nettype
{
"IN"
}
;
string
addrtype
{
"IP4"
}
;
string
address
{
"0.0.0.0"
}
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"o"
;}
};
...
...
@@ -231,11 +139,11 @@ public:
// 5.7. Connection Data ("c=")
// c=IN IP4 224.2.17.12/127
// c=<nettype> <addrtype> <connection-address>
string
nettype
;
string
addrtype
;
string
address
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
nettype
{
"IN"
}
;
string
addrtype
{
"IP4"
}
;
string
address
{
"0.0.0.0"
}
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"c"
;}
};
...
...
@@ -245,11 +153,11 @@ public:
//b=<bwtype>:<bandwidth>
//AS、CT
string
bwtype
;
int
bandwidth
;
string
bwtype
{
"AS"
}
;
uint32_t
bandwidth
{
0
}
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"b"
;}
};
...
...
@@ -259,11 +167,11 @@ public:
// m=<media> <port> <proto> <fmt> ...
TrackType
type
;
uint16_t
port
;
vector
<
string
>
proto
;
vector
<
uint
8_t
>
fmt
;
string
proto
;
vector
<
uint
32_t
>
fmts
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"m"
;}
};
...
...
@@ -275,7 +183,7 @@ public:
//a=<attribute>:<value>
SdpItem
::
Ptr
detail
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"a"
;}
};
...
...
@@ -285,50 +193,63 @@ public:
// 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.
string
type
;
vector
<
string
>
mid
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
type
{
"BUNDLE"
}
;
vector
<
string
>
mid
s
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"group"
;}
};
class
SdpAttrMsidSemantic
:
public
SdpItem
{
public
:
string
name
{
"WMS"
};
string
mid
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
};
string
toString
()
const
override
{
return
SdpItem
::
toString
();
};
//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
;
const
char
*
getKey
()
override
{
return
"msid-semantic"
;}
};
class
SdpAttrRtcp
:
public
SdpItem
{
public
:
// c=IN IP4 224.2.17.12/127
// c=<nettype> <addrtype> <connection-address>
// a=rtcp:9 IN IP4 0.0.0.0
uint16_t
port
;
string
nettype
;
string
addrtype
;
string
address
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
nettype
{
"IN"
}
;
string
addrtype
{
"IP4"
}
;
string
address
{
"0.0.0.0"
}
;
void
parse
(
const
string
&
str
)
override
;
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"rtcp"
;}
};
class
SdpAttrIceUfrag
:
public
SdpItem
{
public
:
//a=ice-ufrag:sXJ3
string
value
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
};
string
toString
()
const
override
{
return
SdpItem
::
toString
();
};
const
char
*
getKey
()
override
{
return
"ice-ufrag"
;}
};
class
SdpAttrIcePwd
:
public
SdpItem
{
public
:
//a=ice-pwd:yEclOTrLg1gEubBFefOqtmyV
string
value
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
};
string
toString
()
const
override
{
return
SdpItem
::
toString
();
};
const
char
*
getKey
()
override
{
return
"ice-pwd"
;}
};
...
...
@@ -336,27 +257,24 @@ 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
;
string
value
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
hash
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"fingerprint"
;}
};
class
SdpAttrSetup
:
public
SdpItem
{
public
:
//a=setup:actpass
DtlsRole
role
{
DtlsRole
::
invalid
};
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
DtlsRole
role
{
DtlsRole
::
actpass
};
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"setup"
;}
};
class
SdpAttrMid
:
public
SdpItem
{
public
:
//a=mid:audio
string
mid
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
};
string
toString
()
const
override
{
return
SdpItem
::
toString
();
};
const
char
*
getKey
()
override
{
return
"mid"
;}
};
...
...
@@ -364,9 +282,9 @@ class SdpAttrExtmap : public SdpItem {
public
:
//a=extmap:1 urn:ietf:params:rtp-hdrext:ssrc-audio-level
int
index
;
string
value
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
ext
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"extmap"
;}
};
...
...
@@ -376,68 +294,85 @@ public:
uint8_t
pt
;
string
codec
;
int
sample_rate
;
int
channel
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
int
channel
{
0
}
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"rtpmap"
;}
};
class
SdpAttrRtcpFb
:
public
SdpItem
{
public
:
//a=rtcp-fb:111 transport-cc
//a=rtcp-fb:98 nack pli
uint8_t
pt
;
string
value
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
vector
<
string
>
arr
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"rtcp-fb"
;}
};
class
SdpAttrFmtp
:
public
SdpItem
{
public
:
//
a=rtcp-fb:111 transport-cc
//
fmtp:96 level-asymmetry-allowed=1;packetization-mode=0;profile-level-id=42e01f
uint8_t
pt
;
map
<
string
,
string
>
values
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
vector
<
std
::
pair
<
string
,
string
>
>
arr
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"fmtp"
;}
};
class
SdpAttrSSRC
:
public
SdpItem
{
public
:
//a=ssrc:120276603 cname:iSkJ2vn5cYYubTve
//a=ssrc:<ssrc-id> <attribute>
//a=ssrc:<ssrc-id> <attribute>:<value>
uint32_t
ssrc
;
string
key
;
string
value
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
attribute
;
string
attribute_
value
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"ssrc"
;}
};
class
SdpAttrSctpMap
:
public
SdpItem
{
public
:
//a=ssrc:120276603 cname:iSkJ2vn5cYYubTve
//https://tools.ietf.org/html/draft-ietf-mmusic-sctp-sdp-05
//a=sctpmap:5000 webrtc-datachannel 1024
//a=sctpmap: sctpmap-number media-subtypes [streams]
uint16_t
port
;
string
name
;
int
mtu
;
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
}
;
string
toString
()
const
override
{
return
SdpItem
::
toString
();
}
;
string
subtypes
;
int
streams
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
override
{
return
"sctpmap"
;}
};
class
SdpAttrCandidate
:
public
SdpItem
{
public
:
//a=candidate:%s 1 udp %u %s %u typ %s
void
parse
(
const
string
&
str
)
override
{
SdpItem
::
parse
(
str
);
};
string
toString
()
const
override
{
return
SdpItem
::
toString
();
};
//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>
uint32_t
foundation
;
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
;
const
char
*
getKey
()
override
{
return
"candidate"
;}
};
class
RtcMedia
{
public
:
vector
<
SdpItem
::
Ptr
>
items
;
string
toString
()
const
;
bool
haveAttr
(
const
char
*
attr
)
const
;
string
getAttrValue
(
const
char
*
attr
)
const
;
RtpDirection
getDirection
()
const
;
};
class
RtcSdp
{
...
...
@@ -447,41 +382,6 @@ public:
void
parse
(
const
string
&
str
);
string
toString
()
const
;
#if 0
/////Session description(会话级别描述)////
//v= (protocol version)
int version;
//o= (session origin information )
SdpOrigin origin;
//s= (session name)
string session_name;
//t= (time the session is active)
SdpTime time;
//// 非必须 ////
//i=* (session information)
string information;
//u=* (URI of description)
string url;
//e=* (email address)
string email;
//p=* (phone number)
string phone;
//c=* (connection information -- not required if included in all media)
SdpConnection connection;
//b=* (zero or more bandwidth information lines)
SdpBandwidth bandwidth;
//z=* (time zone adjustments)
//z=<adjustment time> <offset> <adjustment time> <offset> ....
string time_zone;
//k=* (encryption key)
//k=<method>, k=<method>:<encryption key>
string crypt_key;
//r=* (zero or more repeat times)
//r=<repeat interval> <active duration> <offsets from start-time>
string repeat;
#endif
};
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论