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
87c53dab
Commit
87c53dab
authored
Mar 29, 2021
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
完成sdp的分析
parent
62036d0f
隐藏空白字符变更
内嵌
并排
正在显示
2 个修改的文件
包含
198 行增加
和
37 行删除
+198
-37
webrtc/Sdp.cpp
+148
-25
webrtc/Sdp.h
+50
-12
没有找到文件。
webrtc/Sdp.cpp
查看文件 @
87c53dab
...
...
@@ -189,7 +189,7 @@ SdpItem::Ptr RtcSdpBase::getItem(char key, const char *attr_key) const {
return
item
;
}
auto
attr
=
dynamic_pointer_cast
<
SdpAttr
>
(
item
);
if
(
attr
&&
attr
->
detail
->
getKey
()
==
attr_key
)
{
if
(
attr
&&
!
strcmp
(
attr
->
detail
->
getKey
()
,
attr_key
)
)
{
return
attr
->
detail
;
}
}
...
...
@@ -554,23 +554,18 @@ string SdpAttrRtpMap::toString() const {
return
SdpItem
::
toString
();
}
void
SdpAttrRtcpFb
::
parse
(
const
string
&
str
)
{
auto
vec
=
split
(
str
,
" "
);
if
(
vec
.
size
()
<
2
)
{
void
SdpAttrRtcpFb
::
parse
(
const
string
&
str_in
)
{
auto
str
=
str_in
+
"
\n
"
;
char
rtcp_type_buf
[
32
]
=
{
0
};
if
(
2
!=
sscanf
(
str
.
data
(),
"%"
SCNu8
" %31[^
\n
]"
,
&
pt
,
rtcp_type_buf
))
{
SDP_THROW
();
}
pt
=
atoi
(
vec
[
0
].
data
());
vec
.
erase
(
vec
.
begin
());
arr
=
std
::
move
(
vec
);
rtcp_type
=
rtcp_type_buf
;
}
string
SdpAttrRtcpFb
::
toString
()
const
{
if
(
value
.
empty
())
{
value
=
to_string
(
pt
);
for
(
auto
&
item
:
arr
)
{
value
+=
' '
;
value
+=
item
;
}
value
=
to_string
(
pt
)
+
" "
+
rtcp_type
;
}
return
SdpItem
::
toString
();
}
...
...
@@ -870,6 +865,13 @@ void test_sdp(){
}
InfoL
<<
sdp1
.
toString
();
InfoL
<<
sdp2
.
toString
();
RtcSession
session1
;
session1
.
loadFrom
(
str1
);
RtcSession
session2
;
session2
.
loadFrom
(
str2
);
InfoL
;
}
void
RtcSession
::
loadFrom
(
const
string
&
str
)
{
...
...
@@ -882,32 +884,153 @@ void RtcSession::loadFrom(const string &str) {
session_info
=
sdp
.
getSessionInfo
();
connection
=
sdp
.
getConnection
();
bandwidth
=
sdp
.
getBandwidth
();
auto
group
=
sdp
.
getItemClass
<
SdpAttrGroup
>
(
'a'
,
"group"
);
auto
mids
=
group
.
mids
;
msid_semantic
=
sdp
.
getItemClass
<
SdpAttrMsidSemantic
>
(
'a'
,
"msid-semantic"
);
for
(
auto
&
media
:
sdp
.
medias
)
{
auto
mline
=
media
.
getItemClass
<
SdpMedia
>
(
'm'
);
switch
(
mline
.
type
)
{
case
TrackVideo
:
case
TrackAudio
:
case
TrackApplication
:
break
;
case
TrackApplication
:
break
;
default
:
throw
std
::
invalid_argument
(
StrPrinter
<<
"不识别的media类型:"
<<
mline
.
toString
());
}
RtcMedia
rtc_media
;
this
->
media
.
emplace_back
();
auto
&
rtc_media
=
this
->
media
.
back
();
rtc_media
.
type
=
mline
.
type
;
rtc_media
.
mid
=
media
.
getStringItem
(
'a'
,
"mid"
);
rtc_media
.
proto
=
mline
.
proto
;
rtc_media
.
type
=
mline
.
type
;
rtc_media
.
port
=
mline
.
port
;
rtc_media
.
direction
=
media
.
getDirection
();
rtc_media
.
rtp_addr
=
media
.
getItemClass
<
SdpConnection
>
(
'c'
);
rtc_media
.
rtcp_addr
=
media
.
getItemClass
<
SdpAttrRtcp
>
(
'a'
,
"rtcp"
);
rtc_media
.
ice_ufrag
=
media
.
getStringItem
(
'a'
,
"ice-ufrag"
);
rtc_media
.
ice_ufrag
=
media
.
getStringItem
(
'a'
,
"ice-pwd"
);
rtc_media
.
addr
=
media
.
getItemClass
<
SdpConnection
>
(
'c'
);
rtc_media
.
ice_ufrag
=
media
.
getStringItem
(
'a'
,
"ice-ufrag"
);
rtc_media
.
ice_pwd
=
media
.
getStringItem
(
'a'
,
"ice-pwd"
);
rtc_media
.
role
=
media
.
getItemClass
<
SdpAttrSetup
>
(
'a'
,
"setup"
).
role
;
rtc_media
.
fingerprint
=
media
.
getItemClass
<
SdpAttrFingerprint
>
(
'a'
,
"fingerprint"
);
rtc_media
.
role
=
media
.
getItemClass
<
SdpAttrSetup
>
(
'a'
,
"setup"
).
role
;
// rtc_media.rtcp_mux =
rtc_media
.
ice_trickle
=
media
.
getItem
(
'a'
,
"ice-trickle"
).
operator
bool
();
rtc_media
.
ice_lite
=
media
.
getItem
(
'a'
,
"ice-lite"
).
operator
bool
();
rtc_media
.
ice_renomination
=
media
.
getItem
(
'a'
,
"ice-renomination"
).
operator
bool
();
rtc_media
.
candidate
=
media
.
getAllItem
<
SdpAttrCandidate
>
(
'a'
,
"candidate"
);
if
(
mline
.
type
==
TrackType
::
TrackApplication
)
{
rtc_media
.
sctp_port
=
atoi
(
media
.
getStringItem
(
'a'
,
"sctp-port"
).
data
());
rtc_media
.
sctpmap
=
media
.
getItemClass
<
SdpAttrSctpMap
>
(
'a'
,
"sctpmap"
);
continue
;
}
rtc_media
.
rtcp_addr
=
media
.
getItemClass
<
SdpAttrRtcp
>
(
'a'
,
"rtcp"
);
rtc_media
.
direction
=
media
.
getDirection
();
rtc_media
.
extmap
=
media
.
getAllItem
<
SdpAttrExtmap
>
(
'a'
,
"extmap"
);
rtc_media
.
rtcp_mux
=
media
.
getItem
(
'a'
,
"rtcp-mux"
).
operator
bool
();
rtc_media
.
rtcp_rsize
=
media
.
getItem
(
'a'
,
"rtcp-rsize"
).
operator
bool
();
map
<
uint32_t
,
RtcSSRC
>
rtc_ssrc_map
;
for
(
auto
&
ssrc
:
media
.
getAllItem
<
SdpAttrSSRC
>
(
'a'
,
"ssrc"
))
{
auto
&
rtc_ssrc
=
rtc_ssrc_map
[
ssrc
.
ssrc
];
rtc_ssrc
.
ssrc
=
ssrc
.
ssrc
;
if
(
ssrc
.
attribute
==
"cname"
)
{
rtc_ssrc
.
cname
=
ssrc
.
attribute_value
;
continue
;
}
if
(
ssrc
.
attribute
==
"msid"
)
{
rtc_ssrc
.
msid
=
ssrc
.
attribute_value
;
continue
;
}
if
(
ssrc
.
attribute
==
"mslabel"
)
{
rtc_ssrc
.
mslabel
=
ssrc
.
attribute_value
;
continue
;
}
if
(
ssrc
.
attribute
==
"label"
)
{
rtc_ssrc
.
label
=
ssrc
.
attribute_value
;
continue
;
}
}
uint32_t
ssrc_rtp
=
0
,
ssrc_rtx
=
0
,
ssrc_rtp_low
=
0
,
ssrc_rtp_mid
=
0
,
ssrc_rtp_high
=
0
;
auto
ssrc_groups
=
media
.
getAllItem
<
SdpAttrSSRCGroup
>
(
'a'
,
"ssrc-group"
);
for
(
auto
&
group
:
ssrc_groups
)
{
if
(
group
.
isFID
())
{
ssrc_rtp
=
group
.
u
.
fid
.
rtp_ssrc
;
ssrc_rtx
=
group
.
u
.
fid
.
rtx_ssrc
;
rtc_media
.
rtx
=
true
;
}
else
if
(
group
.
isSIM
())
{
rtc_media
.
simulcast
=
true
;
ssrc_rtp_low
=
group
.
u
.
sim
.
rtp_ssrc_low
;
ssrc_rtp_mid
=
group
.
u
.
sim
.
rtp_ssrc_mid
;
ssrc_rtp_high
=
group
.
u
.
sim
.
rtp_ssrc_high
;
}
}
if
(
!
ssrc_rtp
)
{
//没有指定ssrc-group字段,那么只有一个ssrc
if
(
rtc_ssrc_map
.
size
()
>
1
)
{
throw
std
::
invalid_argument
(
"sdp中不存在a=ssrc-group:FID字段,但是ssrc却有多个"
);
}
ssrc_rtp
=
rtc_ssrc_map
.
begin
()
->
second
.
ssrc
;
}
for
(
auto
&
pr
:
rtc_ssrc_map
)
{
auto
&
rtc_ssrc
=
pr
.
second
;
if
(
rtc_ssrc
.
ssrc
==
ssrc_rtp
)
{
rtc_media
.
rtp_ssrc
=
rtc_ssrc
;
}
if
(
rtc_ssrc
.
ssrc
==
ssrc_rtx
)
{
rtc_media
.
rtx_ssrc
=
rtc_ssrc
;
}
if
(
rtc_ssrc
.
ssrc
==
ssrc_rtp_low
)
{
rtc_media
.
rtp_ssrc_low
=
rtc_ssrc
;
}
if
(
rtc_ssrc
.
ssrc
==
ssrc_rtp_mid
)
{
rtc_media
.
rtp_ssrc_mid
=
rtc_ssrc
;
}
if
(
rtc_ssrc
.
ssrc
==
ssrc_rtp_high
)
{
rtc_media
.
rtp_ssrc_high
=
rtc_ssrc
;
}
}
auto
rtpmap_arr
=
media
.
getAllItem
<
SdpAttrRtpMap
>
(
'a'
,
"rtpmap"
);
auto
rtcpfb_arr
=
media
.
getAllItem
<
SdpAttrRtcpFb
>
(
'a'
,
"rtcp-fb"
);
auto
fmtp_aar
=
media
.
getAllItem
<
SdpAttrFmtp
>
(
'a'
,
"fmtp"
);
//方便根据pt查找rtpmap,一个pt必有一条
map
<
uint8_t
,
SdpAttrRtpMap
&>
rtpmap_map
;
//方便根据pt查找rtcp-fb,一个pt可能有多条或0条
multimap
<
uint8_t
,
SdpAttrRtcpFb
&>
rtcpfb_map
;
//方便根据pt查找fmtp,一个pt最多一条
map
<
uint8_t
,
SdpAttrFmtp
&>
fmtp_map
;
for
(
auto
&
rtpmap
:
rtpmap_arr
)
{
if
(
!
rtpmap_map
.
emplace
(
rtpmap
.
pt
,
rtpmap
).
second
)
{
//添加失败,有多条
throw
std
::
invalid_argument
(
StrPrinter
<<
"该pt存在多条a=rtpmap:"
<<
rtpmap
.
pt
);
}
}
for
(
auto
&
rtpfb
:
rtcpfb_arr
)
{
rtcpfb_map
.
emplace
(
rtpfb
.
pt
,
rtpfb
);
}
for
(
auto
&
fmtp
:
fmtp_aar
)
{
if
(
!
fmtp_map
.
emplace
(
fmtp
.
pt
,
fmtp
).
second
)
{
//添加失败,有多条
throw
std
::
invalid_argument
(
StrPrinter
<<
"该pt存在多条a=fmtp:"
<<
fmtp
.
pt
);
}
}
for
(
auto
&
pt
:
mline
.
fmts
)
{
//遍历所有编码方案的pt
rtc_media
.
plan
.
emplace_back
();
auto
&
plan
=
rtc_media
.
plan
.
back
();
auto
rtpmap_it
=
rtpmap_map
.
find
(
pt
);
if
(
rtpmap_it
==
rtpmap_map
.
end
())
{
throw
std
::
invalid_argument
(
StrPrinter
<<
"该pt不存在相对于的a=rtpmap:"
<<
pt
);
}
plan
.
pt
=
rtpmap_it
->
second
.
pt
;
plan
.
codec
=
rtpmap_it
->
second
.
codec
;
plan
.
sample_rate
=
rtpmap_it
->
second
.
sample_rate
;
plan
.
channel
=
rtpmap_it
->
second
.
channel
;
auto
fmtp_it
=
fmtp_map
.
find
(
pt
);
if
(
fmtp_it
!=
fmtp_map
.
end
())
{
plan
.
fmtp
=
fmtp_it
->
second
.
arr
;
}
for
(
auto
rtpfb_it
=
rtcpfb_map
.
find
(
pt
);
rtpfb_it
!=
rtcpfb_map
.
end
()
&&
rtpfb_it
->
second
.
pt
==
pt
;
++
rtpfb_it
)
{
plan
.
rtcp_fb
.
emplace_back
(
rtpfb_it
->
second
.
rtcp_type
);
}
}
}
group
=
sdp
.
getItemClass
<
SdpAttrGroup
>
(
'a'
,
"group"
);
}
webrtc/Sdp.h
查看文件 @
87c53dab
...
...
@@ -294,7 +294,7 @@ class SdpAttrExtmap : public SdpItem {
public
:
//https://aggresss.blog.csdn.net/article/details/106436703
//a=extmap:1[/sendonly] urn:ietf:params:rtp-hdrext:ssrc-audio-level
in
t
index
;
uint32_
t
index
;
RtpDirection
direction
{
RtpDirection
::
invalid
};
string
ext
;
void
parse
(
const
string
&
str
)
override
;
...
...
@@ -307,8 +307,8 @@ public:
//a=rtpmap:111 opus/48000/2
uint8_t
pt
;
string
codec
;
in
t
sample_rate
;
in
t
channel
{
0
};
uint32_
t
sample_rate
;
uint32_
t
channel
{
0
};
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
const
override
{
return
"rtpmap"
;}
...
...
@@ -323,7 +323,7 @@ public:
//a=rtcp-fb:120 goog-remb 支持 REMB (Receiver Estimated Maximum Bitrate) 。
//a=rtcp-fb:120 transport-cc 支持 TCC (Transport Congest Control) 。
uint8_t
pt
;
vector
<
string
>
arr
;
string
rtcp_type
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
const
override
{
return
"rtcp-fb"
;}
...
...
@@ -383,6 +383,8 @@ public:
}
sim
;
}
u
;
bool
isFID
()
const
{
return
type
==
"FID"
;
}
bool
isSIM
()
const
{
return
type
==
"SIM"
;
}
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
const
override
{
return
"ssrc-group"
;}
...
...
@@ -395,7 +397,7 @@ public:
//a=sctpmap: sctpmap-number media-subtypes [streams]
uint16_t
port
;
string
subtypes
;
in
t
streams
;
uint32_
t
streams
;
void
parse
(
const
string
&
str
)
override
;
string
toString
()
const
override
;
const
char
*
getKey
()
const
override
{
return
"sctpmap"
;}
...
...
@@ -426,6 +428,7 @@ public:
vector
<
SdpItem
::
Ptr
>
items
;
public
:
virtual
~
RtcSdpBase
()
=
default
;
virtual
string
toString
()
const
;
int
getVersion
()
const
;
...
...
@@ -461,8 +464,31 @@ public:
return
item
->
toString
();
}
private
:
SdpItem
::
Ptr
getItem
(
char
key
,
const
char
*
attr_key
=
nullptr
)
const
;
template
<
typename
cls
>
vector
<
cls
>
getAllItem
(
char
key
,
const
char
*
attr_key
=
nullptr
)
const
{
vector
<
cls
>
ret
;
for
(
auto
item
:
items
)
{
if
(
item
->
getKey
()[
0
]
==
key
)
{
if
(
!
attr_key
)
{
auto
c
=
dynamic_pointer_cast
<
cls
>
(
item
);
if
(
c
)
{
ret
.
emplace_back
(
*
c
);
}
}
else
{
auto
attr
=
dynamic_pointer_cast
<
SdpAttr
>
(
item
);
if
(
attr
&&
!
strcmp
(
attr
->
detail
->
getKey
(),
attr_key
))
{
auto
c
=
dynamic_pointer_cast
<
cls
>
(
attr
->
detail
);
if
(
c
)
{
ret
.
emplace_back
(
*
c
);
}
}
}
}
}
return
ret
;
}
};
class
RtcSessionSdp
:
public
RtcSdpBase
{
...
...
@@ -486,7 +512,7 @@ enum class RtcSSRCType {
//ssrc相关信息
class
RtcSSRC
{
public
:
RtcSSRCType
type
;
uint32_t
ssrc
{
0
}
;
string
cname
;
string
msid
;
string
mslabel
;
...
...
@@ -514,15 +540,22 @@ public:
string
proto
;
//////// rtp ////////
RtcSSRC
ssrc
;
SdpConnection
rtp_addr
;
RtcSSRC
rtp_ssrc
;
// for simulcast
bool
simulcast
{
false
};
RtcSSRC
rtp_ssrc_low
;
RtcSSRC
rtp_ssrc_mid
;
RtcSSRC
rtp_ssrc_high
;
SdpConnection
addr
;
RtpDirection
direction
;
vector
<
RtcCodecPlan
>
plan
;
//////// rtx - rtcp ////////
bool
rtx
{
false
};
bool
rtcp_mux
;
bool
rtcp_rsize
;
uint32_t
rtx_ssrc
;
RtcSSRC
rtx_ssrc
;
SdpAttrRtcp
rtcp_addr
;
//////// ice ////////
...
...
@@ -539,18 +572,23 @@ public:
//////// extmap ////////
vector
<
SdpAttrExtmap
>
extmap
;
//////// sctp ////////////
SdpAttrSctpMap
sctpmap
;
uint32_t
sctp_port
{
0
};
};
class
RtcSession
{
public
:
in
t
version
;
uint32_
t
version
;
SdpOrigin
origin
;
string
session_name
;
string
session_info
;
SdpConnection
connection
;
SdpBandwidth
bandwidth
;
set
<
TrackType
>
group_bundle
;
SdpAttrMsidSemantic
msid_semantic
;
vector
<
RtcMedia
>
media
;
SdpAttrGroup
group
;
void
loadFrom
(
const
string
&
sdp
);
};
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论