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
cffc0743
Commit
cffc0743
authored
Jul 14, 2022
by
xiongguangjie
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
format code use clang-format
parent
602b475a
显示空白字符变更
内嵌
并排
正在显示
7 个修改的文件
包含
674 行增加
和
645 行删除
+674
-645
src/Rtcp/Rtcp.cpp
+180
-180
src/Rtcp/Rtcp.h
+71
-76
src/Rtcp/RtcpContext.cpp
+49
-43
src/Rtcp/RtcpContext.h
+22
-23
src/Rtcp/RtcpFCI.cpp
+106
-100
src/Rtcp/RtcpFCI.h
+30
-29
webrtc/WebRtcTransport.cpp
+216
-194
没有找到文件。
src/Rtcp/Rtcp.cpp
查看文件 @
cffc0743
...
...
@@ -8,55 +8,67 @@
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <stddef.h>
#include <assert.h>
#include "Rtcp.h"
#include "Util/logger.h"
#include "RtcpFCI.h"
#include "Util/logger.h"
#include <assert.h>
#include <stddef.h>
using
namespace
std
;
using
namespace
toolkit
;
namespace
mediakit
{
const
char
*
rtcpTypeToStr
(
RtcpType
type
){
switch
(
type
){
#define SWITCH_CASE(key, value) case RtcpType::key : return #value "(" #key ")";
const
char
*
rtcpTypeToStr
(
RtcpType
type
)
{
switch
(
type
)
{
#define SWITCH_CASE(key, value) \
case RtcpType::key: \
return #value "(" #key ")";
RTCP_PT_MAP
(
SWITCH_CASE
)
#undef SWITCH_CASE
default
:
return
"unknown rtcp pt"
;
default
:
return
"unknown rtcp pt"
;
}
}
const
char
*
sdesTypeToStr
(
SdesType
type
){
switch
(
type
){
#define SWITCH_CASE(key, value) case SdesType::key : return #value "(" #key ")";
const
char
*
sdesTypeToStr
(
SdesType
type
)
{
switch
(
type
)
{
#define SWITCH_CASE(key, value) \
case SdesType::key: \
return #value "(" #key ")";
SDES_TYPE_MAP
(
SWITCH_CASE
)
#undef SWITCH_CASE
default
:
return
"unknown source description type"
;
default
:
return
"unknown source description type"
;
}
}
const
char
*
psfbTypeToStr
(
PSFBType
type
)
{
switch
(
type
){
#define SWITCH_CASE(key, value) case PSFBType::key : return #value "(" #key ")";
switch
(
type
)
{
#define SWITCH_CASE(key, value) \
case PSFBType::key: \
return #value "(" #key ")";
PSFB_TYPE_MAP
(
SWITCH_CASE
)
#undef SWITCH_CASE
default
:
return
"unknown payload-specific fb message fmt type"
;
default
:
return
"unknown payload-specific fb message fmt type"
;
}
}
const
char
*
rtpfbTypeToStr
(
RTPFBType
type
)
{
switch
(
type
){
#define SWITCH_CASE(key, value) case RTPFBType::key : return #value "(" #key ")";
switch
(
type
)
{
#define SWITCH_CASE(key, value) \
case RTPFBType::key: \
return #value "(" #key ")";
RTPFB_TYPE_MAP
(
SWITCH_CASE
)
#undef SWITCH_CASE
default
:
return
"unknown transport layer feedback messages fmt type"
;
default
:
return
"unknown transport layer feedback messages fmt type"
;
}
}
static
size_t
alignSize
(
size_t
bytes
)
{
return
(
size_t
)
((
bytes
+
3
)
>>
2
)
<<
2
;
return
(
size_t
)((
bytes
+
3
)
>>
2
)
<<
2
;
}
static
void
setupHeader
(
RtcpHeader
*
rtcp
,
RtcpType
type
,
size_t
report_count
,
size_t
total_bytes
)
{
...
...
@@ -65,16 +77,16 @@ static void setupHeader(RtcpHeader *rtcp, RtcpType type, size_t report_count, si
if
(
report_count
>
0x1F
)
{
throw
std
::
invalid_argument
(
StrPrinter
<<
"rtcp report_count最大赋值为31,当前为:"
<<
report_count
);
}
//items总个数
//
items总个数
rtcp
->
report_count
=
report_count
;
rtcp
->
pt
=
(
uint8_t
)
type
;
rtcp
->
pt
=
(
uint8_t
)
type
;
rtcp
->
setSize
(
total_bytes
);
}
static
void
setupPadding
(
RtcpHeader
*
rtcp
,
size_t
padding_size
)
{
if
(
padding_size
)
{
rtcp
->
padding
=
1
;
((
uint8_t
*
)
rtcp
)[
rtcp
->
getSize
()
-
1
]
=
padding_size
&
0xFF
;
((
uint8_t
*
)
rtcp
)[
rtcp
->
getSize
()
-
1
]
=
padding_size
&
0xFF
;
}
else
{
rtcp
->
padding
=
0
;
}
...
...
@@ -91,123 +103,125 @@ string RtcpHeader::dumpHeader() const {
printer
<<
"padding:"
<<
padding
<<
"
\r\n
"
;
}
switch
((
RtcpType
)
pt
)
{
case
RtcpType
:
:
RTCP_RTPFB
:
{
printer
<<
"report_count:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
"
\r\n
"
;
switch
((
RtcpType
)
pt
)
{
case
RtcpType
:
:
RTCP_RTPFB
:
{
printer
<<
"report_count:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
"
\r\n
"
;
break
;
}
case
RtcpType
:
:
RTCP_PSFB
:
{
printer
<<
"report_count:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
"
\r\n
"
;
case
RtcpType
:
:
RTCP_PSFB
:
{
printer
<<
"report_count:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
"
\r\n
"
;
break
;
}
default
:
{
default
:
{
printer
<<
"report_count:"
<<
report_count
<<
"
\r\n
"
;
break
;
}
}
printer
<<
"pt:"
<<
rtcpTypeToStr
((
RtcpType
)
pt
)
<<
"
\r\n
"
;
printer
<<
"pt:"
<<
rtcpTypeToStr
((
RtcpType
)
pt
)
<<
"
\r\n
"
;
printer
<<
"size:"
<<
getSize
()
<<
"
\r\n
"
;
printer
<<
"--------
\r\n
"
;
return
std
::
move
(
printer
);
}
string
RtcpHeader
::
dumpString
()
const
{
switch
((
RtcpType
)
pt
)
{
switch
((
RtcpType
)
pt
)
{
case
RtcpType
:
:
RTCP_SR
:
{
RtcpSR
*
rtcp
=
(
RtcpSR
*
)
this
;
RtcpSR
*
rtcp
=
(
RtcpSR
*
)
this
;
return
rtcp
->
dumpString
();
}
case
RtcpType
:
:
RTCP_RR
:
{
RtcpRR
*
rtcp
=
(
RtcpRR
*
)
this
;
RtcpRR
*
rtcp
=
(
RtcpRR
*
)
this
;
return
rtcp
->
dumpString
();
}
case
RtcpType
:
:
RTCP_SDES
:
{
RtcpSdes
*
rtcp
=
(
RtcpSdes
*
)
this
;
RtcpSdes
*
rtcp
=
(
RtcpSdes
*
)
this
;
return
rtcp
->
dumpString
();
}
case
RtcpType
:
:
RTCP_RTPFB
:
case
RtcpType
:
:
RTCP_PSFB
:
{
RtcpFB
*
rtcp
=
(
RtcpFB
*
)
this
;
RtcpFB
*
rtcp
=
(
RtcpFB
*
)
this
;
return
rtcp
->
dumpString
();
}
case
RtcpType
:
:
RTCP_BYE
:
{
RtcpBye
*
rtcp
=
(
RtcpBye
*
)
this
;
RtcpBye
*
rtcp
=
(
RtcpBye
*
)
this
;
return
rtcp
->
dumpString
();
}
default
:
return
StrPrinter
<<
dumpHeader
()
<<
hexdump
((
char
*
)
this
+
sizeof
(
*
this
),
getSize
()
-
sizeof
(
*
this
));
default
:
return
StrPrinter
<<
dumpHeader
()
<<
hexdump
((
char
*
)
this
+
sizeof
(
*
this
),
getSize
()
-
sizeof
(
*
this
));
}
}
size_t
RtcpHeader
::
getSize
()
const
{
//加上rtcp头长度
//
加上rtcp头长度
return
(
1
+
ntohs
(
length
))
<<
2
;
}
size_t
RtcpHeader
::
getPaddingSize
()
const
{
size_t
RtcpHeader
::
getPaddingSize
()
const
{
if
(
!
padding
)
{
return
0
;
}
return
((
uint8_t
*
)
this
)[
getSize
()
-
1
];
return
((
uint8_t
*
)
this
)[
getSize
()
-
1
];
}
void
RtcpHeader
::
setSize
(
size_t
size
)
{
//不包含rtcp头的长度
length
=
htons
((
uint16_t
)
((
size
>>
2
)
-
1
));
//
不包含rtcp头的长度
length
=
htons
((
uint16_t
)((
size
>>
2
)
-
1
));
}
void
RtcpHeader
::
net2Host
(
size_t
len
)
{
switch
((
RtcpType
)
pt
)
{
switch
((
RtcpType
)
pt
)
{
case
RtcpType
:
:
RTCP_SR
:
{
RtcpSR
*
sr
=
(
RtcpSR
*
)
this
;
RtcpSR
*
sr
=
(
RtcpSR
*
)
this
;
sr
->
net2Host
(
len
);
break
;
}
case
RtcpType
:
:
RTCP_RR
:
{
RtcpRR
*
rr
=
(
RtcpRR
*
)
this
;
RtcpRR
*
rr
=
(
RtcpRR
*
)
this
;
rr
->
net2Host
(
len
);
break
;
}
case
RtcpType
:
:
RTCP_SDES
:
{
RtcpSdes
*
sdes
=
(
RtcpSdes
*
)
this
;
RtcpSdes
*
sdes
=
(
RtcpSdes
*
)
this
;
sdes
->
net2Host
(
len
);
break
;
}
case
RtcpType
:
:
RTCP_RTPFB
:
case
RtcpType
:
:
RTCP_PSFB
:
{
RtcpFB
*
fb
=
(
RtcpFB
*
)
this
;
RtcpFB
*
fb
=
(
RtcpFB
*
)
this
;
fb
->
net2Host
(
len
);
break
;
}
case
RtcpType
:
:
RTCP_BYE
:
{
RtcpBye
*
bye
=
(
RtcpBye
*
)
this
;
RtcpBye
*
bye
=
(
RtcpBye
*
)
this
;
bye
->
net2Host
(
len
);
break
;
}
case
RtcpType
:
:
RTCP_XR
:
{
RtcpXRRRTR
*
xr
=
(
RtcpXRRRTR
*
)
this
;
if
(
xr
->
bt
==
4
)
{
case
RtcpType
:
:
RTCP_XR
:
{
RtcpXRRRTR
*
xr
=
(
RtcpXRRRTR
*
)
this
;
if
(
xr
->
bt
==
4
)
{
xr
->
net2Host
(
len
);
//
TraceL<<xr->dumpString();
}
else
if
(
xr
->
bt
==
5
)
{
RtcpXRDLRR
*
dlrr
=
(
RtcpXRDLRR
*
)
this
;
//
TraceL<<xr->dumpString();
}
else
if
(
xr
->
bt
==
5
)
{
RtcpXRDLRR
*
dlrr
=
(
RtcpXRDLRR
*
)
this
;
dlrr
->
net2Host
(
len
);
TraceL
<<
dlrr
->
dumpString
();
}
else
{
throw
std
::
runtime_error
(
StrPrinter
<<
"rtcp xr bt "
<<
xr
->
bt
<<
" not support"
);
TraceL
<<
dlrr
->
dumpString
();
}
else
{
throw
std
::
runtime_error
(
StrPrinter
<<
"rtcp xr bt "
<<
xr
->
bt
<<
" not support"
);
}
break
;
}
default
:
throw
std
::
runtime_error
(
StrPrinter
<<
"未处理的rtcp包:"
<<
rtcpTypeToStr
((
RtcpType
)
this
->
pt
));
default
:
throw
std
::
runtime_error
(
StrPrinter
<<
"未处理的rtcp包:"
<<
rtcpTypeToStr
((
RtcpType
)
this
->
pt
));
}
}
...
...
@@ -215,10 +229,10 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len) {
vector
<
RtcpHeader
*>
ret
;
ssize_t
remain
=
len
;
char
*
ptr
=
data
;
while
(
remain
>
(
ssize_t
)
sizeof
(
RtcpHeader
))
{
RtcpHeader
*
rtcp
=
(
RtcpHeader
*
)
ptr
;
while
(
remain
>
(
ssize_t
)
sizeof
(
RtcpHeader
))
{
RtcpHeader
*
rtcp
=
(
RtcpHeader
*
)
ptr
;
auto
rtcp_len
=
rtcp
->
getSize
();
if
(
remain
<
(
ssize_t
)
rtcp_len
)
{
if
(
remain
<
(
ssize_t
)
rtcp_len
)
{
WarnL
<<
"非法的rtcp包,声明的长度超过实际数据长度"
;
break
;
}
...
...
@@ -226,7 +240,7 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len) {
rtcp
->
net2Host
(
rtcp_len
);
ret
.
emplace_back
(
rtcp
);
}
catch
(
std
::
exception
&
ex
)
{
//不能处理的rtcp包,或者无法解析的rtcp包,忽略掉
//
不能处理的rtcp包,或者无法解析的rtcp包,忽略掉
WarnL
<<
ex
.
what
()
<<
",长度为:"
<<
rtcp_len
;
}
ptr
+=
rtcp_len
;
...
...
@@ -237,19 +251,13 @@ vector<RtcpHeader *> RtcpHeader::loadFromBytes(char *data, size_t len) {
class
BufferRtcp
:
public
Buffer
{
public
:
BufferRtcp
(
std
::
shared_ptr
<
RtcpHeader
>
rtcp
)
{
_rtcp
=
std
::
move
(
rtcp
);
}
BufferRtcp
(
std
::
shared_ptr
<
RtcpHeader
>
rtcp
)
{
_rtcp
=
std
::
move
(
rtcp
);
}
~
BufferRtcp
()
override
{}
char
*
data
()
const
override
{
return
(
char
*
)
_rtcp
.
get
();
}
char
*
data
()
const
override
{
return
(
char
*
)
_rtcp
.
get
();
}
size_t
size
()
const
override
{
return
_rtcp
->
getSize
();
}
size_t
size
()
const
override
{
return
_rtcp
->
getSize
();
}
private
:
std
::
shared_ptr
<
RtcpHeader
>
_rtcp
;
...
...
@@ -264,36 +272,34 @@ Buffer::Ptr RtcpHeader::toBuffer(std::shared_ptr<RtcpHeader> rtcp) {
std
::
shared_ptr
<
RtcpSR
>
RtcpSR
::
create
(
size_t
item_count
)
{
auto
real_size
=
sizeof
(
RtcpSR
)
-
sizeof
(
ReportItem
)
+
item_count
*
sizeof
(
ReportItem
);
auto
bytes
=
alignSize
(
real_size
);
auto
ptr
=
(
RtcpSR
*
)
new
char
[
bytes
];
auto
ptr
=
(
RtcpSR
*
)
new
char
[
bytes
];
setupHeader
(
ptr
,
RtcpType
::
RTCP_SR
,
item_count
,
bytes
);
setupPadding
(
ptr
,
bytes
-
real_size
);
return
std
::
shared_ptr
<
RtcpSR
>
(
ptr
,
[](
RtcpSR
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
return
std
::
shared_ptr
<
RtcpSR
>
(
ptr
,
[](
RtcpSR
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
}
string
RtcpSR
::
getNtpStamp
()
const
{
struct
timeval
tv
;
tv
.
tv_sec
=
ntpmsw
-
0x83AA7E80
;
tv
.
tv_usec
=
(
decltype
(
tv
.
tv_usec
))
(
ntplsw
/
((
double
)
(((
uint64_t
)
1
)
<<
32
)
*
1.0e-6
));
tv
.
tv_usec
=
(
decltype
(
tv
.
tv_usec
))
(
ntplsw
/
((
double
)(((
uint64_t
)
1
)
<<
32
)
*
1.0e-6
));
return
LogChannel
::
printTime
(
tv
);
}
uint64_t
RtcpSR
::
getNtpUnixStampMS
()
const
{
if
(
ntpmsw
<
0x83AA7E80
)
{
//ntp时间戳起始时间为1900年,但是utc时间戳起始时间为1970年,两者相差0x83AA7E80秒
//ntp时间戳不得早于1970年,否则无法转换为utc时间戳
//
ntp时间戳起始时间为1900年,但是utc时间戳起始时间为1970年,两者相差0x83AA7E80秒
//
ntp时间戳不得早于1970年,否则无法转换为utc时间戳
return
0
;
}
struct
timeval
tv
;
tv
.
tv_sec
=
ntpmsw
-
0x83AA7E80
;
tv
.
tv_usec
=
(
decltype
(
tv
.
tv_usec
))
(
ntplsw
/
((
double
)
(((
uint64_t
)
1
)
<<
32
)
*
1.0e-6
));
tv
.
tv_usec
=
(
decltype
(
tv
.
tv_usec
))
(
ntplsw
/
((
double
)(((
uint64_t
)
1
)
<<
32
)
*
1.0e-6
));
return
1000
*
tv
.
tv_sec
+
tv
.
tv_usec
/
1000
;
}
void
RtcpSR
::
setNtpStamp
(
struct
timeval
tv
)
{
ntpmsw
=
htonl
(
tv
.
tv_sec
+
0x83AA7E80
);
/* 0x83AA7E80 is the number of seconds from 1900 to 1970 */
ntplsw
=
htonl
((
uint32_t
)
((
double
)
tv
.
tv_usec
*
(
double
)
(((
uint64_t
)
1
)
<<
32
)
*
1.0e-6
));
ntplsw
=
htonl
((
uint32_t
)
((
double
)
tv
.
tv_usec
*
(
double
)(((
uint64_t
)
1
)
<<
32
)
*
1.0e-6
));
}
void
RtcpSR
::
setNtpStamp
(
uint64_t
unix_stamp_ms
)
{
...
...
@@ -313,7 +319,7 @@ string RtcpSR::dumpString() const {
printer
<<
"rtpts:"
<<
rtpts
<<
"
\r\n
"
;
printer
<<
"packet_count:"
<<
packet_count
<<
"
\r\n
"
;
printer
<<
"octet_count:"
<<
octet_count
<<
"
\r\n
"
;
auto
items
=
((
RtcpSR
*
)
this
)
->
getItemList
();
auto
items
=
((
RtcpSR
*
)
this
)
->
getItemList
();
auto
i
=
0
;
for
(
auto
&
item
:
items
)
{
printer
<<
"---- item:"
<<
i
++
<<
" ----
\r\n
"
;
...
...
@@ -323,16 +329,18 @@ string RtcpSR::dumpString() const {
}
#define CHECK_MIN_SIZE(size, kMinSize) \
if (size < kMinSize) { \
throw std::out_of_range(StrPrinter << rtcpTypeToStr((RtcpType)pt) << " 长度不足:" << size << " < " << kMinSize); \
}
if (size < kMinSize) { \
throw std::out_of_range( \
StrPrinter << rtcpTypeToStr((RtcpType)pt) << " 长度不足:" << size << " < " << kMinSize); \
}
#define CHECK_REPORT_COUNT(item_count) \
/*修正个数,防止getItemList时内存越界*/
\
if (report_count != item_count) { \
WarnL << rtcpTypeToStr((RtcpType)pt) << " report_count 字段不正确,已修正为:" << (int)report_count << " -> " << item_count; \
/*修正个数,防止getItemList时内存越界*/
\
if (report_count != item_count) { \
WarnL << rtcpTypeToStr((RtcpType)pt) << " report_count 字段不正确,已修正为:" << (int)report_count << " -> " \
<< item_count; \
report_count = item_count; \
}
}
void
RtcpSR
::
net2Host
(
size_t
size
)
{
static
const
size_t
kMinSize
=
sizeof
(
RtcpSR
)
-
sizeof
(
items
);
...
...
@@ -347,7 +355,7 @@ void RtcpSR::net2Host(size_t size) {
ReportItem
*
ptr
=
&
items
;
int
item_count
=
0
;
for
(
int
i
=
0
;
i
<
(
int
)
report_count
&&
(
char
*
)
(
ptr
)
+
sizeof
(
ReportItem
)
<=
(
char
*
)
(
this
)
+
size
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
report_count
&&
(
char
*
)(
ptr
)
+
sizeof
(
ReportItem
)
<=
(
char
*
)
(
this
)
+
size
;
++
i
)
{
ptr
->
net2Host
();
++
ptr
;
++
item_count
;
...
...
@@ -358,7 +366,7 @@ void RtcpSR::net2Host(size_t size) {
vector
<
ReportItem
*>
RtcpSR
::
getItemList
()
{
vector
<
ReportItem
*>
ret
;
ReportItem
*
ptr
=
&
items
;
for
(
int
i
=
0
;
i
<
(
int
)
report_count
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
report_count
;
++
i
)
{
ret
.
emplace_back
(
ptr
);
++
ptr
;
}
...
...
@@ -395,19 +403,17 @@ void ReportItem::net2Host() {
std
::
shared_ptr
<
RtcpRR
>
RtcpRR
::
create
(
size_t
item_count
)
{
auto
real_size
=
sizeof
(
RtcpRR
)
-
sizeof
(
ReportItem
)
+
item_count
*
sizeof
(
ReportItem
);
auto
bytes
=
alignSize
(
real_size
);
auto
ptr
=
(
RtcpRR
*
)
new
char
[
bytes
];
auto
ptr
=
(
RtcpRR
*
)
new
char
[
bytes
];
setupHeader
(
ptr
,
RtcpType
::
RTCP_RR
,
item_count
,
bytes
);
setupPadding
(
ptr
,
bytes
-
real_size
);
return
std
::
shared_ptr
<
RtcpRR
>
(
ptr
,
[](
RtcpRR
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
return
std
::
shared_ptr
<
RtcpRR
>
(
ptr
,
[](
RtcpRR
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
}
string
RtcpRR
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
RtcpHeader
::
dumpHeader
();
printer
<<
"ssrc:"
<<
ssrc
<<
"
\r\n
"
;
auto
items
=
((
RtcpRR
*
)
this
)
->
getItemList
();
auto
items
=
((
RtcpRR
*
)
this
)
->
getItemList
();
auto
i
=
0
;
for
(
auto
&
item
:
items
)
{
printer
<<
"---- item:"
<<
i
++
<<
" ----
\r\n
"
;
...
...
@@ -423,7 +429,7 @@ void RtcpRR::net2Host(size_t size) {
ReportItem
*
ptr
=
&
items
;
int
item_count
=
0
;
for
(
int
i
=
0
;
i
<
(
int
)
report_count
&&
(
char
*
)
(
ptr
)
+
sizeof
(
ReportItem
)
<=
(
char
*
)
(
this
)
+
size
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
report_count
&&
(
char
*
)(
ptr
)
+
sizeof
(
ReportItem
)
<=
(
char
*
)
(
this
)
+
size
;
++
i
)
{
ptr
->
net2Host
();
++
ptr
;
++
item_count
;
...
...
@@ -434,7 +440,7 @@ void RtcpRR::net2Host(size_t size) {
vector
<
ReportItem
*>
RtcpRR
::
getItemList
()
{
vector
<
ReportItem
*>
ret
;
ReportItem
*
ptr
=
&
items
;
for
(
int
i
=
0
;
i
<
(
int
)
report_count
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
report_count
;
++
i
)
{
ret
.
emplace_back
(
ptr
);
++
ptr
;
}
...
...
@@ -458,8 +464,8 @@ size_t SdesChunk::minSize() {
string
SdesChunk
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
"ssrc:"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"type:"
<<
sdesTypeToStr
((
SdesType
)
type
)
<<
"
\r\n
"
;
printer
<<
"txt_len:"
<<
(
int
)
txt_len
<<
"
\r\n
"
;
printer
<<
"type:"
<<
sdesTypeToStr
((
SdesType
)
type
)
<<
"
\r\n
"
;
printer
<<
"txt_len:"
<<
(
int
)
txt_len
<<
"
\r\n
"
;
printer
<<
"text:"
<<
(
txt_len
?
string
(
text
,
txt_len
)
:
""
)
<<
"
\r\n
"
;
return
std
::
move
(
printer
);
}
...
...
@@ -469,32 +475,30 @@ string SdesChunk::dumpString() const {
std
::
shared_ptr
<
RtcpSdes
>
RtcpSdes
::
create
(
const
std
::
vector
<
string
>
&
item_text
)
{
size_t
item_total_size
=
0
;
for
(
auto
&
text
:
item_text
)
{
//统计所有SdesChunk对象占用的空间
//
统计所有SdesChunk对象占用的空间
item_total_size
+=
alignSize
(
SdesChunk
::
minSize
()
+
(
0xFF
&
text
.
size
()));
}
auto
real_size
=
sizeof
(
RtcpSdes
)
-
sizeof
(
SdesChunk
)
+
item_total_size
;
auto
bytes
=
alignSize
(
real_size
);
auto
ptr
=
(
RtcpSdes
*
)
new
char
[
bytes
];
auto
ptr
=
(
RtcpSdes
*
)
new
char
[
bytes
];
memset
(
ptr
,
0x00
,
bytes
);
auto
item_ptr
=
&
ptr
->
chunks
;
for
(
auto
&
text
:
item_text
)
{
item_ptr
->
txt_len
=
(
0xFF
&
text
.
size
());
//确保赋值\0为RTCP_SDES_END
//
确保赋值\0为RTCP_SDES_END
memcpy
(
item_ptr
->
text
,
text
.
data
(),
item_ptr
->
txt_len
+
1
);
item_ptr
=
(
SdesChunk
*
)
((
char
*
)
item_ptr
+
item_ptr
->
totalBytes
());
item_ptr
=
(
SdesChunk
*
)
((
char
*
)
item_ptr
+
item_ptr
->
totalBytes
());
}
setupHeader
(
ptr
,
RtcpType
::
RTCP_SDES
,
item_text
.
size
(),
bytes
);
setupPadding
(
ptr
,
bytes
-
real_size
);
return
std
::
shared_ptr
<
RtcpSdes
>
(
ptr
,
[](
RtcpSdes
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
return
std
::
shared_ptr
<
RtcpSdes
>
(
ptr
,
[](
RtcpSdes
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
}
string
RtcpSdes
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
RtcpHeader
::
dumpHeader
();
auto
items
=
((
RtcpSdes
*
)
this
)
->
getChunkList
();
auto
items
=
((
RtcpSdes
*
)
this
)
->
getChunkList
();
auto
i
=
0
;
for
(
auto
&
item
:
items
)
{
printer
<<
"---- item:"
<<
i
++
<<
" ----
\r\n
"
;
...
...
@@ -508,9 +512,9 @@ void RtcpSdes::net2Host(size_t size) {
CHECK_MIN_SIZE
(
size
,
kMinSize
);
SdesChunk
*
ptr
=
&
chunks
;
int
item_count
=
0
;
for
(
int
i
=
0
;
i
<
(
int
)
report_count
&&
(
char
*
)
(
ptr
)
+
SdesChunk
::
minSize
()
<=
(
char
*
)
(
this
)
+
size
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
report_count
&&
(
char
*
)(
ptr
)
+
SdesChunk
::
minSize
()
<=
(
char
*
)
(
this
)
+
size
;
++
i
)
{
ptr
->
net2Host
();
ptr
=
(
SdesChunk
*
)
((
char
*
)
ptr
+
ptr
->
totalBytes
());
ptr
=
(
SdesChunk
*
)
((
char
*
)
ptr
+
ptr
->
totalBytes
());
++
item_count
;
}
CHECK_REPORT_COUNT
(
item_count
);
...
...
@@ -519,9 +523,9 @@ void RtcpSdes::net2Host(size_t size) {
vector
<
SdesChunk
*>
RtcpSdes
::
getChunkList
()
{
vector
<
SdesChunk
*>
ret
;
SdesChunk
*
ptr
=
&
chunks
;
for
(
int
i
=
0
;
i
<
(
int
)
report_count
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
report_count
;
++
i
)
{
ret
.
emplace_back
(
ptr
);
ptr
=
(
SdesChunk
*
)
((
char
*
)
ptr
+
ptr
->
totalBytes
());
ptr
=
(
SdesChunk
*
)
((
char
*
)
ptr
+
ptr
->
totalBytes
());
}
return
ret
;
}
...
...
@@ -534,31 +538,29 @@ std::shared_ptr<RtcpFB> RtcpFB::create_l(RtcpType type, int fmt, const void *fci
}
auto
real_size
=
sizeof
(
RtcpFB
)
+
fci_len
;
auto
bytes
=
alignSize
(
real_size
);
auto
ptr
=
(
RtcpFB
*
)
new
char
[
bytes
];
auto
ptr
=
(
RtcpFB
*
)
new
char
[
bytes
];
if
(
fci
&&
fci_len
)
{
memcpy
((
char
*
)
ptr
+
sizeof
(
RtcpFB
),
fci
,
fci_len
);
memcpy
((
char
*
)
ptr
+
sizeof
(
RtcpFB
),
fci
,
fci_len
);
}
setupHeader
(
ptr
,
type
,
fmt
,
bytes
);
setupPadding
(
ptr
,
bytes
-
real_size
);
return
std
::
shared_ptr
<
RtcpFB
>
((
RtcpFB
*
)
ptr
,
[](
RtcpFB
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
return
std
::
shared_ptr
<
RtcpFB
>
((
RtcpFB
*
)
ptr
,
[](
RtcpFB
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
}
std
::
shared_ptr
<
RtcpFB
>
RtcpFB
::
create
(
PSFBType
fmt
,
const
void
*
fci
,
size_t
fci_len
)
{
return
RtcpFB
::
create_l
(
RtcpType
::
RTCP_PSFB
,
(
int
)
fmt
,
fci
,
fci_len
);
return
RtcpFB
::
create_l
(
RtcpType
::
RTCP_PSFB
,
(
int
)
fmt
,
fci
,
fci_len
);
}
std
::
shared_ptr
<
RtcpFB
>
RtcpFB
::
create
(
RTPFBType
fmt
,
const
void
*
fci
,
size_t
fci_len
)
{
return
RtcpFB
::
create_l
(
RtcpType
::
RTCP_RTPFB
,
(
int
)
fmt
,
fci
,
fci_len
);
return
RtcpFB
::
create_l
(
RtcpType
::
RTCP_RTPFB
,
(
int
)
fmt
,
fci
,
fci_len
);
}
const
void
*
RtcpFB
::
getFciPtr
()
const
{
return
(
uint8_t
*
)
&
ssrc_media
+
sizeof
(
ssrc_media
);
return
(
uint8_t
*
)
&
ssrc_media
+
sizeof
(
ssrc_media
);
}
size_t
RtcpFB
::
getFciSize
()
const
{
auto
fci_len
=
(
ssize_t
)
getSize
()
-
getPaddingSize
()
-
sizeof
(
RtcpFB
);
auto
fci_len
=
(
ssize_t
)
getSize
()
-
getPaddingSize
()
-
sizeof
(
RtcpFB
);
CHECK
(
fci_len
>=
0
);
return
fci_len
;
}
...
...
@@ -568,58 +570,60 @@ string RtcpFB::dumpString() const {
printer
<<
RtcpHeader
::
dumpHeader
();
printer
<<
"ssrc:"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"ssrc_media:"
<<
ssrc_media
<<
"
\r\n
"
;
switch
((
RtcpType
)
pt
)
{
case
RtcpType
:
:
RTCP_PSFB
:
{
switch
((
PSFBType
)
report_count
)
{
case
PSFBType
:
:
RTCP_PSFB_SLI
:
{
switch
((
RtcpType
)
pt
)
{
case
RtcpType
:
:
RTCP_PSFB
:
{
switch
((
PSFBType
)
report_count
)
{
case
PSFBType
:
:
RTCP_PSFB_SLI
:
{
auto
&
fci
=
getFci
<
FCI_SLI
>
();
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
break
;
}
case
PSFBType
:
:
RTCP_PSFB_PLI
:
{
case
PSFBType
:
:
RTCP_PSFB_PLI
:
{
getFciSize
();
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
);
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
);
break
;
}
case
PSFBType
:
:
RTCP_PSFB_FIR
:
{
case
PSFBType
:
:
RTCP_PSFB_FIR
:
{
auto
&
fci
=
getFci
<
FCI_FIR
>
();
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
break
;
}
case
PSFBType
:
:
RTCP_PSFB_REMB
:
{
case
PSFBType
:
:
RTCP_PSFB_REMB
:
{
auto
&
fci
=
getFci
<
FCI_REMB
>
();
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
break
;
}
default
:
{
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
hexdump
(
getFciPtr
(),
getFciSize
());
default
:
{
printer
<<
"fci:"
<<
psfbTypeToStr
((
PSFBType
)
report_count
)
<<
" "
<<
hexdump
(
getFciPtr
(),
getFciSize
());
break
;
}
}
break
;
}
case
RtcpType
:
:
RTCP_RTPFB
:
{
switch
((
RTPFBType
)
report_count
)
{
case
RTPFBType
:
:
RTCP_RTPFB_NACK
:
{
case
RtcpType
:
:
RTCP_RTPFB
:
{
switch
((
RTPFBType
)
report_count
)
{
case
RTPFBType
:
:
RTCP_RTPFB_NACK
:
{
auto
&
fci
=
getFci
<
FCI_NACK
>
();
printer
<<
"fci:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
printer
<<
"fci:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
();
break
;
}
case
RTPFBType
:
:
RTCP_RTPFB_TWCC
:
{
case
RTPFBType
:
:
RTCP_RTPFB_TWCC
:
{
auto
&
fci
=
getFci
<
FCI_TWCC
>
();
printer
<<
"fci:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
(
getFciSize
());
printer
<<
"fci:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
" "
<<
fci
.
dumpString
(
getFciSize
());
break
;
}
default
:
{
printer
<<
"fci:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
" "
<<
hexdump
(
getFciPtr
(),
getFciSize
());
printer
<<
"fci:"
<<
rtpfbTypeToStr
((
RTPFBType
)
report_count
)
<<
" "
<<
hexdump
(
getFciPtr
(),
getFciSize
());
break
;
}
}
break
;
}
default
:
/*不可达*/
assert
(
0
);
break
;
default
:
/*不可达*/
assert
(
0
);
break
;
}
return
std
::
move
(
printer
);
}
...
...
@@ -637,24 +641,22 @@ std::shared_ptr<RtcpBye> RtcpBye::create(const std::vector<uint32_t> &ssrcs, con
assert
(
reason
.
size
()
<=
0xFF
);
auto
real_size
=
sizeof
(
RtcpHeader
)
+
sizeof
(
uint32_t
)
*
ssrcs
.
size
()
+
1
+
reason
.
size
();
auto
bytes
=
alignSize
(
real_size
);
auto
ptr
=
(
RtcpBye
*
)
new
char
[
bytes
];
auto
ptr
=
(
RtcpBye
*
)
new
char
[
bytes
];
setupHeader
(
ptr
,
RtcpType
::
RTCP_BYE
,
ssrcs
.
size
(),
bytes
);
setupPadding
(
ptr
,
bytes
-
real_size
);
int
i
=
0
;
for
(
auto
ssrc
:
ssrcs
)
{
((
RtcpBye
*
)
ptr
)
->
ssrc
[
i
++
]
=
htonl
(
ssrc
);
((
RtcpBye
*
)
ptr
)
->
ssrc
[
i
++
]
=
htonl
(
ssrc
);
}
if
(
!
reason
.
empty
())
{
uint8_t
*
reason_len_ptr
=
(
uint8_t
*
)
ptr
+
sizeof
(
RtcpHeader
)
+
sizeof
(
uint32_t
)
*
ssrcs
.
size
();
uint8_t
*
reason_len_ptr
=
(
uint8_t
*
)
ptr
+
sizeof
(
RtcpHeader
)
+
sizeof
(
uint32_t
)
*
ssrcs
.
size
();
*
reason_len_ptr
=
reason
.
size
()
&
0xFF
;
memcpy
(
reason_len_ptr
+
1
,
reason
.
data
(),
*
reason_len_ptr
);
}
return
std
::
shared_ptr
<
RtcpBye
>
(
ptr
,
[](
RtcpBye
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
return
std
::
shared_ptr
<
RtcpBye
>
(
ptr
,
[](
RtcpBye
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
}
vector
<
uint32_t
*>
RtcpBye
::
getSSRC
()
{
...
...
@@ -667,16 +669,16 @@ vector<uint32_t *> RtcpBye::getSSRC() {
string
RtcpBye
::
getReason
()
const
{
auto
*
reason_len_ptr
=
&
reason_len
+
sizeof
(
ssrc
)
*
(
report_count
-
1
);
if
(
reason_len_ptr
+
1
>=
(
uint8_t
*
)
this
+
getSize
())
{
if
(
reason_len_ptr
+
1
>=
(
uint8_t
*
)
this
+
getSize
())
{
return
""
;
}
return
string
((
char
*
)
reason_len_ptr
+
1
,
*
reason_len_ptr
);
return
string
((
char
*
)
reason_len_ptr
+
1
,
*
reason_len_ptr
);
}
string
RtcpBye
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
RtcpHeader
::
dumpHeader
();
for
(
auto
ssrc
:
((
RtcpBye
*
)
this
)
->
getSSRC
())
{
for
(
auto
ssrc
:
((
RtcpBye
*
)
this
)
->
getSSRC
())
{
printer
<<
"ssrc:"
<<
*
ssrc
<<
"
\r\n
"
;
}
printer
<<
"reason:"
<<
getReason
();
...
...
@@ -692,15 +694,15 @@ void RtcpBye::net2Host(size_t size) {
ssrc
[
i
]
=
ntohl
(
ssrc
[
i
]);
offset
+=
sizeof
(
ssrc
);
}
//修正ssrc个数
//
修正ssrc个数
CHECK_REPORT_COUNT
(
i
);
if
(
offset
<
size
)
{
uint8_t
*
reason_len_ptr
=
&
reason_len
+
sizeof
(
ssrc
)
*
(
report_count
-
1
);
if
(
reason_len_ptr
+
1
+
*
reason_len_ptr
>
(
uint8_t
*
)
this
+
size
)
{
if
(
reason_len_ptr
+
1
+
*
reason_len_ptr
>
(
uint8_t
*
)
this
+
size
)
{
WarnL
<<
"invalid rtcp bye reason length"
;
//修正reason_len长度
*
reason_len_ptr
=
((
uint8_t
*
)
this
+
size
-
reason_len_ptr
-
1
)
&
0xFF
;
//
修正reason_len长度
*
reason_len_ptr
=
((
uint8_t
*
)
this
+
size
-
reason_len_ptr
-
1
)
&
0xFF
;
}
}
}
...
...
@@ -708,19 +710,21 @@ void RtcpBye::net2Host(size_t size) {
string
RtcpXRRRTR
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
RtcpHeader
::
dumpHeader
();
printer
<<
"ssrc :"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"bt :"
<<
(
int
)
bt
<<
"
\r\n
"
;
printer
<<
"block_length : "
<<
block_length
<<
"
\r\n
"
;
printer
<<
"ntp msw : "
<<
ntpmsw
<<
"
\r\n
"
;
printer
<<
"ntp lsw : "
<<
ntplsw
<<
"
\r\n
"
;
printer
<<
"ssrc :"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"bt :"
<<
(
int
)
bt
<<
"
\r\n
"
;
printer
<<
"block_length : "
<<
block_length
<<
"
\r\n
"
;
printer
<<
"ntp msw : "
<<
ntpmsw
<<
"
\r\n
"
;
printer
<<
"ntp lsw : "
<<
ntplsw
<<
"
\r\n
"
;
return
std
::
move
(
printer
);
}
void
RtcpXRRRTR
::
net2Host
(
size_t
size
)
{
static
const
size_t
kMinSize
=
sizeof
(
RtcpHeader
);
CHECK_MIN_SIZE
(
size
,
kMinSize
);
if
(
size
!=
sizeof
(
RtcpXRRRTR
)){
throw
std
::
invalid_argument
(
StrPrinter
<<
"rtcp xr Receiver Reference Time Report Block must is "
<<
sizeof
(
RtcpXRRRTR
)
<<
" actual size "
<<
size
);
if
(
size
!=
sizeof
(
RtcpXRRRTR
))
{
throw
std
::
invalid_argument
(
StrPrinter
<<
"rtcp xr Receiver Reference Time Report Block must is "
<<
sizeof
(
RtcpXRRRTR
)
<<
" actual size "
<<
size
);
}
ssrc
=
ntohl
(
ssrc
);
block_length
=
ntohs
(
block_length
);
...
...
@@ -728,13 +732,12 @@ void RtcpXRRRTR::net2Host(size_t size) {
ntplsw
=
ntohl
(
ntplsw
);
}
string
RtcpXRDLRRReportItem
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
"ssrc :"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"last RR (lrr) :"
<<
lrr
<<
"
\r\n
"
;
printer
<<
"delay since last RR (dlrr): "
<<
dlrr
<<
"
\r\n
"
;
printer
<<
"ssrc :"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"last RR (lrr) :"
<<
lrr
<<
"
\r\n
"
;
printer
<<
"delay since last RR (dlrr): "
<<
dlrr
<<
"
\r\n
"
;
return
std
::
move
(
printer
);
}
...
...
@@ -745,24 +748,23 @@ void RtcpXRDLRRReportItem::net2Host() {
dlrr
=
ntohl
(
dlrr
);
}
std
::
vector
<
RtcpXRDLRRReportItem
*>
RtcpXRDLRR
::
getItemList
()
{
auto
count
=
block_length
/
3
;
std
::
vector
<
RtcpXRDLRRReportItem
*>
RtcpXRDLRR
::
getItemList
()
{
auto
count
=
block_length
/
3
;
RtcpXRDLRRReportItem
*
ptr
=
&
items
;
vector
<
RtcpXRDLRRReportItem
*>
ret
;
for
(
int
i
=
0
;
i
<
(
int
)
count
;
++
i
)
{
for
(
int
i
=
0
;
i
<
(
int
)
count
;
++
i
)
{
ret
.
emplace_back
(
ptr
);
++
ptr
;
}
return
ret
;
}
string
RtcpXRDLRR
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
RtcpHeader
::
dumpHeader
();
printer
<<
"ssrc :"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"bt :"
<<
(
int
)
bt
<<
"
\r\n
"
;
printer
<<
"block_length : "
<<
block_length
<<
"
\r\n
"
;
auto
items_list
=
((
RtcpXRDLRR
*
)
this
)
->
getItemList
();
printer
<<
"ssrc :"
<<
ssrc
<<
"
\r\n
"
;
printer
<<
"bt :"
<<
(
int
)
bt
<<
"
\r\n
"
;
printer
<<
"block_length : "
<<
block_length
<<
"
\r\n
"
;
auto
items_list
=
((
RtcpXRDLRR
*
)
this
)
->
getItemList
();
auto
i
=
0
;
for
(
auto
&
item
:
items_list
)
{
printer
<<
"---- item:"
<<
i
++
<<
" ----
\r\n
"
;
...
...
@@ -778,23 +780,21 @@ void RtcpXRDLRR::net2Host(size_t size) {
ssrc
=
ntohl
(
ssrc
);
block_length
=
ntohs
(
block_length
);
auto
count
=
block_length
/
3
;
for
(
int
i
=
0
;
i
<
(
int
)
count
;
++
i
)
{
auto
count
=
block_length
/
3
;
for
(
int
i
=
0
;
i
<
(
int
)
count
;
++
i
)
{
RtcpXRDLRRReportItem
*
ptr
=
&
items
;
ptr
->
net2Host
();
ptr
++
;
}
}
std
::
shared_ptr
<
RtcpXRDLRR
>
RtcpXRDLRR
::
create
(
size_t
item_count
)
{
std
::
shared_ptr
<
RtcpXRDLRR
>
RtcpXRDLRR
::
create
(
size_t
item_count
)
{
auto
real_size
=
sizeof
(
RtcpXRDLRR
)
-
sizeof
(
RtcpXRDLRRReportItem
)
+
item_count
*
sizeof
(
RtcpXRDLRRReportItem
);
auto
bytes
=
alignSize
(
real_size
);
auto
ptr
=
(
RtcpXRDLRR
*
)
new
char
[
bytes
];
auto
ptr
=
(
RtcpXRDLRR
*
)
new
char
[
bytes
];
setupHeader
(
ptr
,
RtcpType
::
RTCP_XR
,
0
,
bytes
);
setupPadding
(
ptr
,
bytes
-
real_size
);
return
std
::
shared_ptr
<
RtcpXRDLRR
>
(
ptr
,
[](
RtcpXRDLRR
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
return
std
::
shared_ptr
<
RtcpXRDLRR
>
(
ptr
,
[](
RtcpXRDLRR
*
ptr
)
{
delete
[]
(
char
*
)
ptr
;
});
}
#if 0
...
...
@@ -811,4 +811,4 @@ static toolkit::onceToken token([](){
});
#endif
}
//
namespace
mediakit
\ No newline at end of file
}
//
namespace
mediakit
\ No newline at end of file
src/Rtcp/Rtcp.h
查看文件 @
cffc0743
...
...
@@ -11,11 +11,11 @@
#ifndef ZLMEDIAKIT_RTCP_H
#define ZLMEDIAKIT_RTCP_H
#include "Common/macros.h"
#include "Network/Buffer.h"
#include "Util/util.h"
#include <stdint.h>
#include <vector>
#include "Util/util.h"
#include "Network/Buffer.h"
#include "Common/macros.h"
namespace
mediakit
{
...
...
@@ -23,7 +23,7 @@ namespace mediakit {
#pragma pack(push, 1)
#endif // defined(_WIN32)
//http://www.networksorcery.com/enp/protocol/rtcp.htm
//
http://www.networksorcery.com/enp/protocol/rtcp.htm
#define RTCP_PT_MAP(XX) \
XX(RTCP_FIR, 192) \
XX(RTCP_NACK, 193) \
...
...
@@ -41,7 +41,7 @@ namespace mediakit {
XX(RTCP_RSI, 209) \
XX(RTCP_TOKEN, 210)
//https://tools.ietf.org/html/rfc3550#section-6.5
//
https://tools.ietf.org/html/rfc3550#section-6.5
#define SDES_TYPE_MAP(XX) \
XX(RTCP_SDES_END, 0) \
XX(RTCP_SDES_CNAME, 1) \
...
...
@@ -53,8 +53,8 @@ namespace mediakit {
XX(RTCP_SDES_NOTE, 7) \
XX(RTCP_SDES_PRIVATE, 8)
//https://datatracker.ietf.org/doc/rfc4585/?include_text=1
//6.3. Payload-Specific Feedback Messages
//
https://datatracker.ietf.org/doc/rfc4585/?include_text=1
//
6.3. Payload-Specific Feedback Messages
//
// Payload-Specific FB messages are identified by the value PT=PSFB as
// RTCP message type.
...
...
@@ -80,13 +80,13 @@ namespace mediakit {
XX(RTCP_PSFB_SLI, 2) \
XX(RTCP_PSFB_RPSI, 3) \
XX(RTCP_PSFB_FIR, 4) \
XX(RTCP_PSFB_TSTR, 5)
\
XX(RTCP_PSFB_TSTN, 6)
\
XX(RTCP_PSFB_TSTR, 5)
\
XX(RTCP_PSFB_TSTN, 6)
\
XX(RTCP_PSFB_VBCM, 7) \
XX(RTCP_PSFB_REMB, 15)
//https://tools.ietf.org/html/rfc4585#section-6.2
//6.2. Transport Layer Feedback Messages
//
https://tools.ietf.org/html/rfc4585#section-6.2
//
6.2. Transport Layer Feedback Messages
//
// Transport layer FB messages are identified by the value RTPFB as RTCP
// message type.
...
...
@@ -110,28 +110,28 @@ namespace mediakit {
XX(RTCP_RTPFB_TMMBN, 4) \
XX(RTCP_RTPFB_TWCC, 15)
//rtcp类型枚举
//
rtcp类型枚举
enum
class
RtcpType
:
uint8_t
{
#define XX(key, value) key = value,
RTCP_PT_MAP
(
XX
)
#undef XX
};
//sdes类型枚举
//
sdes类型枚举
enum
class
SdesType
:
uint8_t
{
#define XX(key, value) key = value,
SDES_TYPE_MAP
(
XX
)
#undef XX
};
//psfb类型枚举
//
psfb类型枚举
enum
class
PSFBType
:
uint8_t
{
#define XX(key, value) key = value,
PSFB_TYPE_MAP
(
XX
)
#undef XX
};
//rtpfb类型枚举
//
rtpfb类型枚举
enum
class
RTPFBType
:
uint8_t
{
#define XX(key, value) key = value,
RTPFB_TYPE_MAP
(
XX
)
...
...
@@ -161,26 +161,26 @@ const char *rtpfbTypeToStr(RTPFBType type);
class
RtcpHeader
{
public
:
#if __BYTE_ORDER == __BIG_ENDIAN
//版本号,固定为2
uint32_t
version
:
2
;
//padding,固定为0
uint32_t
padding
:
1
;
//reception report count
uint32_t
report_count
:
5
;
//
版本号,固定为2
uint32_t
version
:
2
;
//
padding,固定为0
uint32_t
padding
:
1
;
//
reception report count
uint32_t
report_count
:
5
;
#else
//reception report count
uint32_t
report_count
:
5
;
//padding,末尾是否有追加填充
uint32_t
padding
:
1
;
//版本号,固定为2
uint32_t
version
:
2
;
//
reception report count
uint32_t
report_count
:
5
;
//
padding,末尾是否有追加填充
uint32_t
padding
:
1
;
//
版本号,固定为2
uint32_t
version
:
2
;
#endif
//rtcp类型,RtcpType
uint32_t
pt
:
8
;
//
rtcp类型,RtcpType
uint32_t
pt
:
8
;
private
:
//长度
uint32_t
length
:
16
;
//
长度
uint32_t
length
:
16
;
public
:
/**
...
...
@@ -222,7 +222,6 @@ public:
void
setSize
(
size_t
size
);
protected
:
/**
* 打印字段详情
* 使用net2Host转换成主机字节序后才可使用此函数
...
...
@@ -240,26 +239,26 @@ private:
/////////////////////////////////////////////////////////////////////////////
//ReportBlock
//
ReportBlock
class
ReportItem
{
public
:
friend
class
RtcpSR
;
friend
class
RtcpRR
;
uint32_t
ssrc
;
//Fraction lost
uint32_t
fraction
:
8
;
//Cumulative number of packets lost
uint32_t
cumulative
:
24
;
//Sequence number cycles count
//
Fraction lost
uint32_t
fraction
:
8
;
//
Cumulative number of packets lost
uint32_t
cumulative
:
24
;
//
Sequence number cycles count
uint16_t
seq_cycles
;
//Highest sequence number received
//
Highest sequence number received
uint16_t
seq_max
;
//Interarrival jitter
//
Interarrival jitter
uint32_t
jitter
;
//Last SR timestamp, NTP timestamp,(ntpmsw & 0xFFFF) << 16 | (ntplsw >> 16) & 0xFFFF)
//
Last SR timestamp, NTP timestamp,(ntpmsw & 0xFFFF) << 16 | (ntplsw >> 16) & 0xFFFF)
uint32_t
last_sr_stamp
;
//Delay since last SR timestamp,expressed in units of 1/65536 seconds
//
Delay since last SR timestamp,expressed in units of 1/65536 seconds
uint32_t
delay_since_last_sr
;
private
:
...
...
@@ -273,7 +272,7 @@ private:
* 网络字节序转换为主机字节序
*/
void
net2Host
();
}
PACKED
;
}
PACKED
;
/*
* 6.4.1 SR: Sender Report RTCP Packet
...
...
@@ -329,7 +328,7 @@ public:
uint32_t
packet_count
;
// sender octet count
uint32_t
octet_count
;
//可能有很多个
//
可能有很多个
ReportItem
items
;
public
:
...
...
@@ -358,7 +357,7 @@ public:
* 获取ReportItem对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std
::
vector
<
ReportItem
*>
getItemList
();
std
::
vector
<
ReportItem
*>
getItemList
();
private
:
/**
...
...
@@ -406,13 +405,13 @@ block +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
//Receiver Report
//
Receiver Report
class
RtcpRR
:
public
RtcpHeader
{
public
:
friend
class
RtcpHeader
;
uint32_t
ssrc
;
//可能有很多个
//
可能有很多个
ReportItem
items
;
public
:
...
...
@@ -427,7 +426,7 @@ public:
* 获取ReportItem对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std
::
vector
<
ReportItem
*>
getItemList
();
std
::
vector
<
ReportItem
*>
getItemList
();
private
:
/**
...
...
@@ -475,20 +474,20 @@ SDES items 定义
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
//Source description Chunk
//
Source description Chunk
class
SdesChunk
{
public
:
friend
class
RtcpSdes
;
uint32_t
ssrc
;
//SdesType
//
SdesType
uint8_t
type
;
//text长度股,可以为0
//
text长度股,可以为0
uint8_t
txt_len
;
//不定长
//
不定长
char
text
[
1
];
//最后以RTCP_SDES_END结尾
//只字段为占位字段,不代表真实位置
//
最后以RTCP_SDES_END结尾
//
只字段为占位字段,不代表真实位置
uint8_t
end
;
public
:
...
...
@@ -515,12 +514,12 @@ private:
void
net2Host
();
}
PACKED
;
//Source description
//
Source description
class
RtcpSdes
:
public
RtcpHeader
{
public
:
friend
class
RtcpHeader
;
//可能有很多个
//
可能有很多个
SdesChunk
chunks
;
public
:
...
...
@@ -535,7 +534,7 @@ public:
* 获取SdesChunk对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std
::
vector
<
SdesChunk
*>
getChunkList
();
std
::
vector
<
SdesChunk
*>
getChunkList
();
private
:
/**
...
...
@@ -591,11 +590,11 @@ public:
* @tparam Type 对象类型
* @return 对象指针
*/
template
<
typename
Type
>
const
Type
&
getFci
()
const
{
template
<
typename
Type
>
const
Type
&
getFci
()
const
{
auto
fci_data
=
getFciPtr
();
auto
fci_len
=
getFciSize
();
Type
*
fci
=
(
Type
*
)
fci_data
;
Type
*
fci
=
(
Type
*
)
fci_data
;
fci
->
check
(
fci_len
);
return
*
fci
;
}
...
...
@@ -627,7 +626,7 @@ private:
static
std
::
shared_ptr
<
RtcpFB
>
create_l
(
RtcpType
type
,
int
fmt
,
const
void
*
fci
,
size_t
fci_len
);
}
PACKED
;
//BYE
//
BYE
/*
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
...
...
@@ -712,8 +711,7 @@ private:
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
*/
class
RtcpXRRRTR
:
public
RtcpHeader
{
class
RtcpXRRRTR
:
public
RtcpHeader
{
public
:
friend
class
RtcpHeader
;
uint32_t
ssrc
;
...
...
@@ -726,6 +724,7 @@ public:
uint32_t
ntpmsw
;
// ntp timestamp LSW(in picosecond)
uint32_t
ntplsw
;
private
:
/**
* 打印字段详情
...
...
@@ -739,7 +738,7 @@ private:
*/
void
net2Host
(
size_t
size
);
}
PACKED
;
}
PACKED
;
/*
...
...
@@ -759,13 +758,13 @@ private:
: ... : 2
+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
*/
class
RtcpXRDLRRReportItem
{
class
RtcpXRDLRRReportItem
{
public
:
friend
class
RtcpXRDLRR
;
uint32_t
ssrc
;
uint32_t
lrr
;
uint32_t
dlrr
;
private
:
/**
* 打印字段详情
...
...
@@ -778,12 +777,9 @@ private:
* @param size 字节长度,防止内存越界
*/
void
net2Host
();
}
PACKED
;
}
PACKED
;
class
RtcpXRDLRR
:
public
RtcpHeader
{
class
RtcpXRDLRR
:
public
RtcpHeader
{
public
:
friend
class
RtcpHeader
;
uint32_t
ssrc
;
...
...
@@ -803,7 +799,7 @@ public:
* 获取RtcpXRDLRRReportItem对象指针列表
* 使用net2Host转换成主机字节序后才可使用此函数
*/
std
::
vector
<
RtcpXRDLRRReportItem
*>
getItemList
();
std
::
vector
<
RtcpXRDLRRReportItem
*>
getItemList
();
private
:
/**
...
...
@@ -818,12 +814,11 @@ private:
*/
void
net2Host
(
size_t
size
);
}
PACKED
;
}
PACKED
;
#if defined(_WIN32)
#pragma pack(pop)
#endif // defined(_WIN32)
}
//namespace mediakit
#endif //ZLMEDIAKIT_RTCP_H
}
//
namespace mediakit
#endif //
ZLMEDIAKIT_RTCP_H
src/Rtcp/RtcpContext.cpp
查看文件 @
cffc0743
...
...
@@ -14,7 +14,8 @@ using namespace toolkit;
namespace
mediakit
{
void
RtcpContext
::
onRtp
(
uint16_t
/*seq*/
,
uint32_t
stamp
,
uint64_t
ntp_stamp_ms
,
uint32_t
/*sample_rate*/
,
size_t
bytes
)
{
void
RtcpContext
::
onRtp
(
uint16_t
/*seq*/
,
uint32_t
stamp
,
uint64_t
ntp_stamp_ms
,
uint32_t
/*sample_rate*/
,
size_t
bytes
)
{
++
_packets
;
_bytes
+=
bytes
;
_last_rtp_stamp
=
stamp
;
...
...
@@ -52,9 +53,9 @@ Buffer::Ptr RtcpContext::createRtcpXRDLRR(uint32_t rtcp_ssrc, uint32_t rtp_ssrc)
////////////////////////////////////////////////////////////////////////////////////
void
RtcpContextForSend
::
onRtcp
(
RtcpHeader
*
rtcp
)
{
switch
((
RtcpType
)
rtcp
->
pt
)
{
switch
((
RtcpType
)
rtcp
->
pt
)
{
case
RtcpType
:
:
RTCP_RR
:
{
auto
rtcp_rr
=
(
RtcpRR
*
)
rtcp
;
auto
rtcp_rr
=
(
RtcpRR
*
)
rtcp
;
for
(
auto
item
:
rtcp_rr
->
getItemList
())
{
if
(
!
item
->
last_sr_stamp
)
{
continue
;
...
...
@@ -63,32 +64,34 @@ void RtcpContextForSend::onRtcp(RtcpHeader *rtcp) {
if
(
it
==
_sender_report_ntp
.
end
())
{
continue
;
}
//
发送sr到收到rr之间的时间戳增量
//
发送sr到收到rr之间的时间戳增量
auto
ms_inc
=
getCurrentMillisecond
()
-
it
->
second
;
//
rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒
auto
delay_ms
=
(
uint64_t
)
item
->
delay_since_last_sr
*
1000
/
65536
;
auto
rtt
=
(
int
)
(
ms_inc
-
delay_ms
);
//
rtp接收端收到sr包后,回复rr包的延时,已转换为毫秒
auto
delay_ms
=
(
uint64_t
)
item
->
delay_since_last_sr
*
1000
/
65536
;
auto
rtt
=
(
int
)
(
ms_inc
-
delay_ms
);
if
(
rtt
>=
0
)
{
//
rtt不可能小于0
//
rtt不可能小于0
_rtt
[
item
->
ssrc
]
=
rtt
;
//
InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt;
//
InfoL << "ssrc:" << item->ssrc << ",rtt:" << rtt;
}
}
break
;
}
case
RtcpType
:
:
RTCP_XR
:
{
auto
rtcp_xr
=
(
RtcpXRRRTR
*
)
rtcp
;
if
(
rtcp_xr
->
bt
==
4
){
_xr_xrrtr_recv_last_rr
[
rtcp_xr
->
ssrc
]
=
((
rtcp_xr
->
ntpmsw
&
0xFFFF
)
<<
16
)
|
((
rtcp_xr
->
ntplsw
>>
16
)
&
0xFFFF
);
case
RtcpType
:
:
RTCP_XR
:
{
auto
rtcp_xr
=
(
RtcpXRRRTR
*
)
rtcp
;
if
(
rtcp_xr
->
bt
==
4
)
{
_xr_xrrtr_recv_last_rr
[
rtcp_xr
->
ssrc
]
=
((
rtcp_xr
->
ntpmsw
&
0xFFFF
)
<<
16
)
|
((
rtcp_xr
->
ntplsw
>>
16
)
&
0xFFFF
);
_xr_rrtr_recv_sys_stamp
[
rtcp_xr
->
ssrc
]
=
getCurrentMillisecond
();
}
else
if
(
rtcp_xr
->
bt
==
5
)
{
TraceL
<<
"for sender not recive dlrr"
;
}
else
{
TraceL
<<
"not support xr bt "
<<
rtcp_xr
->
bt
;
}
else
if
(
rtcp_xr
->
bt
==
5
)
{
TraceL
<<
"for sender not recive dlrr"
;
}
else
{
TraceL
<<
"not support xr bt "
<<
rtcp_xr
->
bt
;
}
break
;
}
default
:
break
;
default
:
break
;
}
}
...
...
@@ -105,21 +108,21 @@ Buffer::Ptr RtcpContextForSend::createRtcpSR(uint32_t rtcp_ssrc) {
rtcp
->
setNtpStamp
(
_last_ntp_stamp_ms
);
rtcp
->
rtpts
=
htonl
(
_last_rtp_stamp
);
rtcp
->
ssrc
=
htonl
(
rtcp_ssrc
);
rtcp
->
packet_count
=
htonl
((
uint32_t
)
_packets
);
rtcp
->
octet_count
=
htonl
((
uint32_t
)
_bytes
);
rtcp
->
packet_count
=
htonl
((
uint32_t
)
_packets
);
rtcp
->
octet_count
=
htonl
((
uint32_t
)
_bytes
);
//记录上次发送的sender report信息,用于后续统计rtt
//
记录上次发送的sender report信息,用于后续统计rtt
auto
last_sr_lsr
=
((
ntohl
(
rtcp
->
ntpmsw
)
&
0xFFFF
)
<<
16
)
|
((
ntohl
(
rtcp
->
ntplsw
)
>>
16
)
&
0xFFFF
);
_sender_report_ntp
[
last_sr_lsr
]
=
getCurrentMillisecond
();
if
(
_sender_report_ntp
.
size
()
>=
5
)
{
//删除最早的sr rtcp
//
删除最早的sr rtcp
_sender_report_ntp
.
erase
(
_sender_report_ntp
.
begin
());
}
return
RtcpHeader
::
toBuffer
(
std
::
move
(
rtcp
));
}
toolkit
::
Buffer
::
Ptr
RtcpContextForSend
::
createRtcpXRDLRR
(
uint32_t
rtcp_ssrc
,
uint32_t
rtp_ssrc
){
toolkit
::
Buffer
::
Ptr
RtcpContextForSend
::
createRtcpXRDLRR
(
uint32_t
rtcp_ssrc
,
uint32_t
rtp_ssrc
)
{
auto
rtcp
=
RtcpXRDLRR
::
create
(
1
);
rtcp
->
bt
=
5
;
rtcp
->
reserved
=
0
;
...
...
@@ -127,14 +130,14 @@ toolkit::Buffer::Ptr RtcpContextForSend::createRtcpXRDLRR(uint32_t rtcp_ssrc, ui
rtcp
->
ssrc
=
htonl
(
rtcp_ssrc
);
rtcp
->
items
.
ssrc
=
htonl
(
rtp_ssrc
);
if
(
_xr_xrrtr_recv_last_rr
.
find
(
rtp_ssrc
)
==
_xr_xrrtr_recv_last_rr
.
end
())
{
if
(
_xr_xrrtr_recv_last_rr
.
find
(
rtp_ssrc
)
==
_xr_xrrtr_recv_last_rr
.
end
())
{
rtcp
->
items
.
lrr
=
0
;
WarnL
;
}
else
{
}
else
{
rtcp
->
items
.
lrr
=
htonl
(
_xr_xrrtr_recv_last_rr
[
rtp_ssrc
]);
}
if
(
_xr_rrtr_recv_sys_stamp
.
find
(
rtp_ssrc
)
==
_xr_rrtr_recv_sys_stamp
.
end
())
{
if
(
_xr_rrtr_recv_sys_stamp
.
find
(
rtp_ssrc
)
==
_xr_rrtr_recv_sys_stamp
.
end
())
{
rtcp
->
items
.
dlrr
=
0
;
WarnL
;
}
else
{
...
...
@@ -149,39 +152,41 @@ toolkit::Buffer::Ptr RtcpContextForSend::createRtcpXRDLRR(uint32_t rtcp_ssrc, ui
////////////////////////////////////////////////////////////////////////////////////
void
RtcpContextForRecv
::
onRtp
(
uint16_t
seq
,
uint32_t
stamp
,
uint64_t
ntp_stamp_ms
,
uint32_t
sample_rate
,
size_t
bytes
)
{
void
RtcpContextForRecv
::
onRtp
(
uint16_t
seq
,
uint32_t
stamp
,
uint64_t
ntp_stamp_ms
,
uint32_t
sample_rate
,
size_t
bytes
)
{
{
//接收者才做复杂的统计运算
//
接收者才做复杂的统计运算
auto
sys_stamp
=
getCurrentMillisecond
();
if
(
_last_rtp_sys_stamp
)
{
//计算时间戳抖动值
double
diff
=
double
((
int64_t
(
sys_stamp
)
-
int64_t
(
_last_rtp_sys_stamp
))
*
(
sample_rate
/
double
(
1000.0
))
// 计算时间戳抖动值
double
diff
=
double
(
(
int64_t
(
sys_stamp
)
-
int64_t
(
_last_rtp_sys_stamp
))
*
(
sample_rate
/
double
(
1000.0
))
-
(
int64_t
(
stamp
)
-
int64_t
(
_last_rtp_stamp
)));
if
(
diff
<
0
)
{
diff
=
-
diff
;
}
//抖动单位为采样次数
//
抖动单位为采样次数
_jitter
+=
(
diff
-
_jitter
)
/
16.0
;
}
else
{
_jitter
=
0
;
}
if
(
_last_rtp_seq
>
0xFF00
&&
seq
<
0xFF
&&
(
!
_seq_cycles
||
_packets
-
_last_cycle_packets
>
0x1FFF
))
{
//上次seq大于0xFF00且本次seq小于0xFF,
//且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环
//
上次seq大于0xFF00且本次seq小于0xFF,
//
且未发生回环或者距离上次回环间隔超过0x1FFF个包,则认为回环
++
_seq_cycles
;
_last_cycle_packets
=
_packets
;
_seq_max
=
seq
;
}
else
if
(
seq
>
_seq_max
)
{
//本次回环前最大seq
//
本次回环前最大seq
_seq_max
=
seq
;
}
if
(
!
_seq_base
)
{
//记录第一个rtp的seq
//
记录第一个rtp的seq
_seq_base
=
seq
;
}
else
if
(
!
_seq_cycles
&&
seq
<
_seq_base
)
{
//未发生回环,那么取最新的seq为基准seq
//
未发生回环,那么取最新的seq为基准seq
_seq_base
=
seq
;
}
...
...
@@ -192,9 +197,9 @@ void RtcpContextForRecv::onRtp(uint16_t seq, uint32_t stamp, uint64_t ntp_stamp_
}
void
RtcpContextForRecv
::
onRtcp
(
RtcpHeader
*
rtcp
)
{
switch
((
RtcpType
)
rtcp
->
pt
)
{
switch
((
RtcpType
)
rtcp
->
pt
)
{
case
RtcpType
:
:
RTCP_SR
:
{
auto
rtcp_sr
=
(
RtcpSR
*
)
rtcp
;
auto
rtcp_sr
=
(
RtcpSR
*
)
rtcp
;
/**
last SR timestamp (LSR): 32 bits
The middle 32 bits out of 64 in the NTP timestamp (as explained in
...
...
@@ -206,7 +211,8 @@ void RtcpContextForRecv::onRtcp(RtcpHeader *rtcp) {
_last_sr_ntp_sys
=
getCurrentMillisecond
();
break
;
}
default
:
break
;
default
:
break
;
}
}
...
...
@@ -236,7 +242,7 @@ Buffer::Ptr RtcpContextForRecv::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ss
auto
rtcp
=
RtcpRR
::
create
(
1
);
rtcp
->
ssrc
=
htonl
(
rtcp_ssrc
);
ReportItem
*
item
=
(
ReportItem
*
)
&
rtcp
->
items
;
ReportItem
*
item
=
(
ReportItem
*
)
&
rtcp
->
items
;
item
->
ssrc
=
htonl
(
rtp_ssrc
);
uint8_t
fraction
=
0
;
...
...
@@ -255,9 +261,9 @@ Buffer::Ptr RtcpContextForRecv::createRtcpRR(uint32_t rtcp_ssrc, uint32_t rtp_ss
// now - Last SR time,单位毫秒
auto
delay
=
getCurrentMillisecond
()
-
_last_sr_ntp_sys
;
// in units of 1/65536 seconds
auto
dlsr
=
(
uint32_t
)
(
delay
/
1000.0
f
*
65536
);
auto
dlsr
=
(
uint32_t
)(
delay
/
1000.0
f
*
65536
);
item
->
delay_since_last_sr
=
htonl
(
_last_sr_lsr
?
dlsr
:
0
);
return
RtcpHeader
::
toBuffer
(
rtcp
);
}
}
//
namespace
mediakit
\ No newline at end of file
}
//
namespace
mediakit
\ No newline at end of file
src/Rtcp/RtcpContext.h
查看文件 @
cffc0743
...
...
@@ -11,9 +11,9 @@
#ifndef ZLMEDIAKIT_RTCPCONTEXT_H
#define ZLMEDIAKIT_RTCPCONTEXT_H
#include <stdint.h>
#include <stddef.h>
#include "Rtcp.h"
#include <stddef.h>
#include <stdint.h>
namespace
mediakit
{
...
...
@@ -55,7 +55,6 @@ public:
*/
virtual
toolkit
::
Buffer
::
Ptr
createRtcpSR
(
uint32_t
rtcp_ssrc
);
/**
* @brief 创建xr的dlrr包,用于接收者估算rtt
*
...
...
@@ -82,11 +81,11 @@ public:
virtual
size_t
geLostInterval
();
protected
:
//收到或发送的rtp的字节数
//
收到或发送的rtp的字节数
size_t
_bytes
=
0
;
//收到或发送的rtp的个数
//
收到或发送的rtp的个数
size_t
_packets
=
0
;
//上次的rtp时间戳,毫秒
//
上次的rtp时间戳,毫秒
uint32_t
_last_rtp_stamp
=
0
;
uint64_t
_last_ntp_stamp_ms
=
0
;
};
...
...
@@ -107,11 +106,11 @@ public:
uint32_t
getRtt
(
uint32_t
ssrc
)
const
;
private
:
std
::
map
<
uint32_t
/*ssrc*/
,
uint32_t
/*rtt*/
>
_rtt
;
std
::
map
<
uint32_t
/*last_sr_lsr*/
,
uint64_t
/*ntp stamp*/
>
_sender_report_ntp
;
std
::
map
<
uint32_t
/*ssrc*/
,
uint32_t
/*rtt*/
>
_rtt
;
std
::
map
<
uint32_t
/*last_sr_lsr*/
,
uint64_t
/*ntp stamp*/
>
_sender_report_ntp
;
std
::
map
<
uint32_t
/*ssrc*/
,
uint64_t
/*xr rrtr sys stamp*/
>
_xr_rrtr_recv_sys_stamp
;
std
::
map
<
uint32_t
/*ssrc*/
,
uint32_t
/*last rr */
>
_xr_xrrtr_recv_last_rr
;
std
::
map
<
uint32_t
/*ssrc*/
,
uint64_t
/*xr rrtr sys stamp*/
>
_xr_rrtr_recv_sys_stamp
;
std
::
map
<
uint32_t
/*ssrc*/
,
uint32_t
/*last rr */
>
_xr_xrrtr_recv_last_rr
;
};
class
RtcpContextForRecv
:
public
RtcpContext
{
...
...
@@ -125,29 +124,29 @@ public:
void
onRtcp
(
RtcpHeader
*
rtcp
)
override
;
private
:
//时间戳抖动值
//
时间戳抖动值
double
_jitter
=
0
;
//第一个seq的值
//
第一个seq的值
uint16_t
_seq_base
=
0
;
//rtp最大seq
//
rtp最大seq
uint16_t
_seq_max
=
0
;
//rtp回环次数
//
rtp回环次数
uint16_t
_seq_cycles
=
0
;
//上次回环发生时,记录的rtp包数
//
上次回环发生时,记录的rtp包数
size_t
_last_cycle_packets
=
0
;
//上次的seq
//
上次的seq
uint16_t
_last_rtp_seq
=
0
;
//上次的rtp的系统时间戳(毫秒)用于统计抖动
//
上次的rtp的系统时间戳(毫秒)用于统计抖动
uint64_t
_last_rtp_sys_stamp
=
0
;
//上次统计的丢包总数
//
上次统计的丢包总数
size_t
_last_lost
=
0
;
//上次统计应收rtp包总数
//
上次统计应收rtp包总数
size_t
_last_expected
=
0
;
//上次收到sr包时计算出的Last SR timestamp
//
上次收到sr包时计算出的Last SR timestamp
uint32_t
_last_sr_lsr
=
0
;
//上次收到sr时的系统时间戳,单位毫秒
//
上次收到sr时的系统时间戳,单位毫秒
uint64_t
_last_sr_ntp_sys
=
0
;
};
}
//
namespace mediakit
#endif //ZLMEDIAKIT_RTCPCONTEXT_H
}
//
namespace mediakit
#endif //
ZLMEDIAKIT_RTCPCONTEXT_H
src/Rtcp/RtcpFCI.cpp
查看文件 @
cffc0743
...
...
@@ -16,16 +16,16 @@ using namespace toolkit;
namespace
mediakit
{
void
FCI_SLI
::
check
(
size_t
size
){
void
FCI_SLI
::
check
(
size_t
size
)
{
CHECK
(
size
>=
kSize
);
}
FCI_SLI
::
FCI_SLI
(
uint16_t
first
,
uint16_t
number
,
uint8_t
pic_id
)
{
//13 bits
//
13 bits
first
&=
0x1FFF
;
//13 bits
//
13 bits
number
&=
0x1FFF
;
//6 bits
//
6 bits
pic_id
&=
0x3F
;
data
=
(
first
<<
19
)
|
(
number
<<
6
)
|
pic_id
;
data
=
htonl
(
data
);
...
...
@@ -49,19 +49,19 @@ string FCI_SLI::dumpString() const {
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
FCI_FIR
::
check
(
size_t
size
){
void
FCI_FIR
::
check
(
size_t
size
)
{
CHECK
(
size
>=
kSize
);
}
uint32_t
FCI_FIR
::
getSSRC
()
const
{
uint32_t
FCI_FIR
::
getSSRC
()
const
{
return
ntohl
(
ssrc
);
}
uint8_t
FCI_FIR
::
getSeq
()
const
{
uint8_t
FCI_FIR
::
getSeq
()
const
{
return
seq_number
;
}
uint32_t
FCI_FIR
::
getReserved
()
const
{
uint32_t
FCI_FIR
::
getReserved
()
const
{
return
(
reserved
[
0
]
<<
16
)
|
(
reserved
[
1
]
<<
8
)
|
reserved
[
2
];
}
...
...
@@ -81,7 +81,7 @@ FCI_FIR::FCI_FIR(uint32_t ssrc, uint8_t seq_number, uint32_t reserved) {
static
const
char
kRembMagic
[]
=
"REMB"
;
void
FCI_REMB
::
check
(
size_t
size
){
void
FCI_REMB
::
check
(
size_t
size
)
{
CHECK
(
size
>=
kSize
);
CHECK
(
memcmp
(
magic
,
kRembMagic
,
sizeof
(
magic
))
==
0
);
auto
num_ssrc
=
bitrate
[
0
];
...
...
@@ -93,7 +93,7 @@ string FCI_REMB::create(const vector<uint32_t> &ssrcs, uint32_t bitrate) {
CHECK
(
ssrcs
.
size
()
>
0
&&
ssrcs
.
size
()
<=
0xFF
);
string
ret
;
ret
.
resize
(
kSize
+
ssrcs
.
size
()
*
4
);
FCI_REMB
*
thiz
=
(
FCI_REMB
*
)
ret
.
data
();
FCI_REMB
*
thiz
=
(
FCI_REMB
*
)
ret
.
data
();
memcpy
(
thiz
->
magic
,
kRembMagic
,
sizeof
(
magic
));
/* bitrate --> BR Exp/BR Mantissa */
...
...
@@ -101,7 +101,7 @@ string FCI_REMB::create(const vector<uint32_t> &ssrcs, uint32_t bitrate) {
uint8_t
exp
=
0
;
uint32_t
mantissa
=
0
;
for
(
b
=
0
;
b
<
32
;
b
++
)
{
if
(
bitrate
<=
((
uint32_t
)
0x3FFFF
<<
b
))
{
if
(
bitrate
<=
((
uint32_t
)
0x3FFFF
<<
b
))
{
exp
=
b
;
break
;
}
...
...
@@ -110,16 +110,16 @@ string FCI_REMB::create(const vector<uint32_t> &ssrcs, uint32_t bitrate) {
b
=
31
;
}
mantissa
=
bitrate
>>
b
;
//Num SSRC (8 bits)
//
Num SSRC (8 bits)
thiz
->
bitrate
[
0
]
=
ssrcs
.
size
()
&
0xFF
;
//BR Exp (6 bits)/BR Mantissa (18 bits)
thiz
->
bitrate
[
1
]
=
(
uint8_t
)
((
exp
<<
2
)
+
((
mantissa
>>
16
)
&
0x03
));
//BR Mantissa (18 bits)
thiz
->
bitrate
[
2
]
=
(
uint8_t
)
(
mantissa
>>
8
);
//BR Mantissa (18 bits)
thiz
->
bitrate
[
3
]
=
(
uint8_t
)
(
mantissa
);
//设置ssrc列表
//
BR Exp (6 bits)/BR Mantissa (18 bits)
thiz
->
bitrate
[
1
]
=
(
uint8_t
)((
exp
<<
2
)
+
((
mantissa
>>
16
)
&
0x03
));
//
BR Mantissa (18 bits)
thiz
->
bitrate
[
2
]
=
(
uint8_t
)(
mantissa
>>
8
);
//
BR Mantissa (18 bits)
thiz
->
bitrate
[
3
]
=
(
uint8_t
)(
mantissa
);
//
设置ssrc列表
int
i
=
0
;
for
(
auto
ssrc
:
ssrcs
)
{
thiz
->
ssrc_feedback
[
i
++
]
=
htonl
(
ssrc
);
...
...
@@ -149,7 +149,7 @@ vector<uint32_t> FCI_REMB::getSSRC() {
string
FCI_REMB
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
"bitrate:"
<<
getBitRate
()
<<
", ssrc:"
;
for
(
auto
&
ssrc
:
((
FCI_REMB
*
)
this
)
->
getSSRC
())
{
for
(
auto
&
ssrc
:
((
FCI_REMB
*
)
this
)
->
getSSRC
())
{
printer
<<
ssrc
<<
" "
;
}
return
std
::
move
(
printer
);
...
...
@@ -171,7 +171,7 @@ FCI_NACK::FCI_NACK(uint16_t pid_h, const vector<bool> &type) {
pid
=
htons
(
pid_h
);
}
void
FCI_NACK
::
check
(
size_t
size
){
void
FCI_NACK
::
check
(
size_t
size
)
{
CHECK
(
size
>=
kSize
);
}
...
...
@@ -186,7 +186,7 @@ uint16_t FCI_NACK::getBlp() const {
vector
<
bool
>
FCI_NACK
::
getBitArray
()
const
{
vector
<
bool
>
ret
;
ret
.
resize
(
kBitSize
+
1
);
//nack第一个包丢包
//
nack第一个包丢包
ret
[
0
]
=
true
;
auto
blp_h
=
getBlp
();
...
...
@@ -220,25 +220,25 @@ public:
// |T| S | Run Length |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#if __BYTE_ORDER == __BIG_ENDIAN
uint16_t
type
:
1
;
uint16_t
symbol
:
2
;
uint16_t
run_length_high
:
5
;
uint16_t
type
:
1
;
uint16_t
symbol
:
2
;
uint16_t
run_length_high
:
5
;
#else
// Run Length 高5位
uint16_t
run_length_high
:
5
;
//参考SymbolStatus定义
uint16_t
symbol
:
2
;
//固定为0
uint16_t
type
:
1
;
uint16_t
run_length_high
:
5
;
//
参考SymbolStatus定义
uint16_t
symbol
:
2
;
//
固定为0
uint16_t
type
:
1
;
#endif
// Run Length 低8位
uint16_t
run_length_low
:
8
;
uint16_t
run_length_low
:
8
;
//获取Run Length
//
获取Run Length
uint16_t
getRunLength
()
const
;
//构造函数
//
构造函数
RunLengthChunk
(
SymbolStatus
status
,
uint16_t
run_length
);
//打印本对象
//
打印本对象
string
dumpString
()
const
;
}
PACKED
;
...
...
@@ -254,7 +254,7 @@ uint16_t RunLengthChunk::getRunLength() const {
return
run_length_high
<<
8
|
run_length_low
;
}
string
RunLengthChunk
::
dumpString
()
const
{
string
RunLengthChunk
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
"run length chunk, symbol:"
<<
(
int
)
symbol
<<
", run length:"
<<
getRunLength
();
return
std
::
move
(
printer
);
...
...
@@ -271,30 +271,30 @@ public:
// |T|S| symbol list |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
#if __BYTE_ORDER == __BIG_ENDIAN
uint16_t
type
:
1
;
uint16_t
symbol
:
1
;
uint16_t
symbol_list_high
:
6
;
uint16_t
type
:
1
;
uint16_t
symbol
:
1
;
uint16_t
symbol_list_high
:
6
;
#else
// symbol_list 高6位
uint16_t
symbol_list_high
:
6
;
//symbol_list中元素是1个还是2个bit
uint16_t
symbol
:
1
;
//固定为1
uint16_t
type
:
1
;
uint16_t
symbol_list_high
:
6
;
//
symbol_list中元素是1个还是2个bit
uint16_t
symbol
:
1
;
//
固定为1
uint16_t
type
:
1
;
#endif
// symbol_list 低8位
uint16_t
symbol_list_low
:
8
;
uint16_t
symbol_list_low
:
8
;
//获取symbollist
//
获取symbollist
vector
<
SymbolStatus
>
getSymbolList
()
const
;
//构造函数
//
构造函数
StatusVecChunk
(
bool
symbol_bit
,
const
vector
<
SymbolStatus
>
&
status
);
//打印本对象
//
打印本对象
string
dumpString
()
const
;
}
PACKED
;
StatusVecChunk
::
StatusVecChunk
(
bool
symbol_bit
,
const
vector
<
SymbolStatus
>
&
status
)
{
CHECK
(
status
.
size
()
<<
symbol_bit
<=
14
);
CHECK
(
status
.
size
()
<<
symbol_bit
<=
14
);
uint16_t
value
=
0
;
type
=
1
;
symbol
=
symbol_bit
;
...
...
@@ -303,31 +303,31 @@ StatusVecChunk::StatusVecChunk(bool symbol_bit, const vector<SymbolStatus> &stat
CHECK
(
item
<=
SymbolStatus
::
reserved
);
if
(
!
symbol
)
{
CHECK
(
item
<=
SymbolStatus
::
small_delta
);
value
|=
(
int
)
item
<<
i
;
value
|=
(
int
)
item
<<
i
;
--
i
;
}
else
{
value
|=
(
int
)
item
<<
(
i
-
1
);
value
|=
(
int
)
item
<<
(
i
-
1
);
i
-=
2
;
}
}
symbol_list_low
=
value
&
0xFF
;
symbol_list_high
=
(
value
>>
8
)
&
0x3F
;
symbol_list_high
=
(
value
>>
8
)
&
0x3F
;
}
vector
<
SymbolStatus
>
StatusVecChunk
::
getSymbolList
()
const
{
CHECK
(
type
==
1
);
vector
<
SymbolStatus
>
ret
;
auto
thiz
=
ntohs
(
*
((
uint16_t
*
)
this
));
auto
thiz
=
ntohs
(
*
((
uint16_t
*
)
this
));
if
(
symbol
==
0
)
{
//s = 0 时,表示symbollist的每一个bit能表示一个数据包的到达状态
//
s = 0 时,表示symbollist的每一个bit能表示一个数据包的到达状态
for
(
int
i
=
13
;
i
>=
0
;
--
i
)
{
SymbolStatus
status
=
(
SymbolStatus
)
((
bool
)
(
thiz
&
(
1
<<
i
)));
SymbolStatus
status
=
(
SymbolStatus
)
((
bool
)
(
thiz
&
(
1
<<
i
)));
ret
.
emplace_back
(
status
);
}
}
else
{
//s = 1 时,表示symbollist每两个bit表示一个数据包的状态
//
s = 1 时,表示symbollist每两个bit表示一个数据包的状态
for
(
int
i
=
12
;
i
>=
0
;
i
-=
2
)
{
SymbolStatus
status
=
(
SymbolStatus
)
((
thiz
&
(
3
<<
i
))
>>
i
);
SymbolStatus
status
=
(
SymbolStatus
)((
thiz
&
(
3
<<
i
))
>>
i
);
ret
.
emplace_back
(
status
);
}
}
...
...
@@ -336,17 +336,17 @@ vector<SymbolStatus> StatusVecChunk::getSymbolList() const {
string
StatusVecChunk
::
dumpString
()
const
{
_StrPrinter
printer
;
printer
<<
"status vector chunk, symbol:"
<<
(
int
)
symbol
<<
", symbol list:"
;
printer
<<
"status vector chunk, symbol:"
<<
(
int
)
symbol
<<
", symbol list:"
;
auto
vec
=
getSymbolList
();
for
(
auto
&
item
:
vec
)
{
printer
<<
(
int
)
item
<<
" "
;
printer
<<
(
int
)
item
<<
" "
;
}
return
std
::
move
(
printer
);
}
///////////////////////////////////////////////////////
void
FCI_TWCC
::
check
(
size_t
size
){
void
FCI_TWCC
::
check
(
size_t
size
)
{
CHECK
(
size
>=
kSize
);
}
...
...
@@ -365,7 +365,7 @@ uint32_t FCI_TWCC::getReferenceTime() const {
ret
|=
ref_time
[
2
];
return
ret
;
}
//3.1.5. Receive Delta
//
3.1.5. Receive Delta
//
// Deltas are represented as multiples of 250us:
//
...
...
@@ -392,33 +392,33 @@ uint32_t FCI_TWCC::getReferenceTime() const {
// be represented. With a 1200 bytes/packet payload, that amounts to
// 38.4 Mbit/s payload bandwidth.
static
int16_t
getRecvDelta
(
SymbolStatus
status
,
uint8_t
*&
ptr
,
const
uint8_t
*
end
){
static
int16_t
getRecvDelta
(
SymbolStatus
status
,
uint8_t
*&
ptr
,
const
uint8_t
*
end
)
{
int16_t
delta
=
0
;
switch
(
status
)
{
case
SymbolStatus
:
:
not_received
:
{
//
丢包, recv delta为0个字节
case
SymbolStatus
:
:
not_received
:
{
//
丢包, recv delta为0个字节
break
;
}
case
SymbolStatus
:
:
small_delta
:
{
case
SymbolStatus
:
:
small_delta
:
{
CHECK
(
ptr
+
1
<=
end
);
//
时间戳增量小于256, recv delta为1个字节
//
时间戳增量小于256, recv delta为1个字节
delta
=
*
ptr
;
ptr
+=
1
;
break
;
}
case
SymbolStatus
:
:
large_delta
:
{
case
SymbolStatus
:
:
large_delta
:
{
CHECK
(
ptr
+
2
<=
end
);
//
时间戳增量256~65535间,recv delta为2个字节
//
时间戳增量256~65535间,recv delta为2个字节
delta
=
*
ptr
<<
8
|
*
(
ptr
+
1
);
ptr
+=
2
;
break
;
}
case
SymbolStatus
:
:
reserved
:
{
//
没有时间戳
case
SymbolStatus
:
:
reserved
:
{
//
没有时间戳
break
;
}
default
:
//
这个逻辑分支不可达到
//
这个逻辑分支不可达到
CHECK
(
0
);
break
;
}
...
...
@@ -427,25 +427,25 @@ static int16_t getRecvDelta(SymbolStatus status, uint8_t *&ptr, const uint8_t *e
FCI_TWCC
::
TwccPacketStatus
FCI_TWCC
::
getPacketChunkList
(
size_t
total_size
)
const
{
TwccPacketStatus
ret
;
auto
ptr
=
(
uint8_t
*
)
this
+
kSize
;
auto
end
=
(
uint8_t
*
)
this
+
total_size
;
auto
ptr
=
(
uint8_t
*
)
this
+
kSize
;
auto
end
=
(
uint8_t
*
)
this
+
total_size
;
CHECK
(
ptr
<
end
);
auto
seq
=
getBaseSeq
();
auto
rtp_count
=
getPacketCount
();
for
(
uint8_t
i
=
0
;
i
<
rtp_count
;)
{
CHECK
(
ptr
+
RunLengthChunk
::
kSize
<=
end
);
RunLengthChunk
*
chunk
=
(
RunLengthChunk
*
)
ptr
;
RunLengthChunk
*
chunk
=
(
RunLengthChunk
*
)
ptr
;
if
(
!
chunk
->
type
)
{
//RunLengthChunk
//
RunLengthChunk
for
(
auto
j
=
0
;
j
<
chunk
->
getRunLength
();
++
j
)
{
ret
.
emplace
(
seq
++
,
std
::
make_pair
((
SymbolStatus
)
chunk
->
symbol
,
0
));
ret
.
emplace
(
seq
++
,
std
::
make_pair
((
SymbolStatus
)
chunk
->
symbol
,
0
));
if
(
++
i
>=
rtp_count
)
{
break
;
}
}
}
else
{
//StatusVecChunk
StatusVecChunk
*
chunk
=
(
StatusVecChunk
*
)
ptr
;
//
StatusVecChunk
StatusVecChunk
*
chunk
=
(
StatusVecChunk
*
)
ptr
;
for
(
auto
&
symbol
:
chunk
->
getSymbolList
())
{
ret
.
emplace
(
seq
++
,
std
::
make_pair
(
symbol
,
0
));
if
(
++
i
>=
rtp_count
)
{
...
...
@@ -465,23 +465,29 @@ FCI_TWCC::TwccPacketStatus FCI_TWCC::getPacketChunkList(size_t total_size) const
string
FCI_TWCC
::
dumpString
(
size_t
total_size
)
const
{
_StrPrinter
printer
;
auto
map
=
getPacketChunkList
(
total_size
);
printer
<<
"twcc fci, base_seq:"
<<
getBaseSeq
()
<<
", pkt_status_count:"
<<
getPacketCount
()
<<
", ref time:"
<<
getReferenceTime
()
<<
", fb count:"
<<
(
int
)
fb_pkt_count
<<
"
\n
"
;
printer
<<
"twcc fci, base_seq:"
<<
getBaseSeq
()
<<
", pkt_status_count:"
<<
getPacketCount
()
<<
", ref time:"
<<
getReferenceTime
()
<<
", fb count:"
<<
(
int
)
fb_pkt_count
<<
"
\n
"
;
for
(
auto
&
pr
:
map
)
{
printer
<<
"rtp seq:"
<<
pr
.
first
<<
", packet status:"
<<
(
int
)(
pr
.
second
.
first
)
<<
", delta:"
<<
pr
.
second
.
second
<<
"
\n
"
;
printer
<<
"rtp seq:"
<<
pr
.
first
<<
", packet status:"
<<
(
int
)(
pr
.
second
.
first
)
<<
", delta:"
<<
pr
.
second
.
second
<<
"
\n
"
;
}
return
std
::
move
(
printer
);
}
static
void
appendDeltaString
(
string
&
delta_str
,
FCI_TWCC
::
TwccPacketStatus
&
status
,
int
count
){
static
void
appendDeltaString
(
string
&
delta_str
,
FCI_TWCC
::
TwccPacketStatus
&
status
,
int
count
)
{
for
(
auto
it
=
status
.
begin
();
it
!=
status
.
end
()
&&
count
--
;)
{
switch
(
it
->
second
.
first
)
{
//large delta模式先写高字节,再写低字节
case
SymbolStatus
:
:
large_delta
:
delta_str
.
push_back
((
it
->
second
.
second
>>
8
)
&
0xFF
);
//small delta模式只写低字节
case
SymbolStatus
:
:
small_delta
:
delta_str
.
push_back
(
it
->
second
.
second
&
0xFF
);
break
;
default
:
break
;
// large delta模式先写高字节,再写低字节
case
SymbolStatus
:
:
large_delta
:
delta_str
.
push_back
((
it
->
second
.
second
>>
8
)
&
0xFF
);
// small delta模式只写低字节
case
SymbolStatus
:
:
small_delta
:
delta_str
.
push_back
(
it
->
second
.
second
&
0xFF
);
break
;
default
:
break
;
}
//移除已经处理过的数据
//
移除已经处理过的数据
it
=
status
.
erase
(
it
);
}
}
...
...
@@ -489,7 +495,7 @@ static void appendDeltaString(string &delta_str, FCI_TWCC::TwccPacketStatus &sta
string
FCI_TWCC
::
create
(
uint32_t
ref_time
,
uint8_t
fb_pkt_count
,
TwccPacketStatus
&
status
)
{
string
fci
;
fci
.
resize
(
FCI_TWCC
::
kSize
);
FCI_TWCC
*
ptr
=
(
FCI_TWCC
*
)
(
fci
.
data
());
FCI_TWCC
*
ptr
=
(
FCI_TWCC
*
)(
fci
.
data
());
ptr
->
base_seq
=
htons
(
status
.
begin
()
->
first
);
ptr
->
pkt_status_count
=
htons
(
status
.
size
());
ptr
->
fb_pkt_count
=
fb_pkt_count
;
...
...
@@ -500,21 +506,21 @@ string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatu
string
delta_str
;
while
(
!
status
.
empty
())
{
{
//第一个rtp的状态
//
第一个rtp的状态
auto
symbol
=
status
.
begin
()
->
second
.
first
;
int16_t
count
=
0
;
for
(
auto
&
pr
:
status
)
{
if
(
pr
.
second
.
first
!=
symbol
)
{
//状态发送变更了,本chunk结束
//
状态发送变更了,本chunk结束
break
;
}
if
(
++
count
>=
(
0xFFFF
>>
3
))
{
//RunLengthChunk 13个bit表明rtp个数,最多可以表述0xFFFF >> 3个rtp状态
//
RunLengthChunk 13个bit表明rtp个数,最多可以表述0xFFFF >> 3个rtp状态
break
;
}
}
if
(
count
>=
7
)
{
//连续状态相同个数大于6个时,使用RunLengthChunk模式比较节省带宽
//
连续状态相同个数大于6个时,使用RunLengthChunk模式比较节省带宽
RunLengthChunk
chunk
(
symbol
,
count
);
fci
.
append
((
char
*
)
&
chunk
,
RunLengthChunk
::
kSize
);
appendDeltaString
(
delta_str
,
status
,
count
);
...
...
@@ -523,20 +529,20 @@ string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatu
}
{
//StatusVecChunk模式
//symbol_list中元素是1个bit
//
StatusVecChunk模式
//
symbol_list中元素是1个bit
auto
symbol
=
0
;
vector
<
SymbolStatus
>
vec
;
for
(
auto
&
pr
:
status
)
{
vec
.
push_back
(
pr
.
second
.
first
);
if
(
pr
.
second
.
first
>=
SymbolStatus
::
large_delta
)
{
//symbol_list中元素是2个bit
//
symbol_list中元素是2个bit
symbol
=
1
;
}
if
(
vec
.
size
()
<<
symbol
>=
14
)
{
//symbol为0时,最多存放14个rtp的状态
//symbol为1时,最多存放7个rtp的状态
//
symbol为0时,最多存放14个rtp的状态
//
symbol为1时,最多存放7个rtp的状态
break
;
}
}
...
...
@@ -547,9 +553,9 @@ string FCI_TWCC::create(uint32_t ref_time, uint8_t fb_pkt_count, TwccPacketStatu
}
}
//recv delta部分
//
recv delta部分
fci
.
append
(
delta_str
);
return
fci
;
}
}
//
namespace
mediakit
\ No newline at end of file
}
//
namespace
mediakit
\ No newline at end of file
src/Rtcp/RtcpFCI.h
查看文件 @
cffc0743
...
...
@@ -11,21 +11,21 @@
#ifndef ZLMEDIAKIT_RTCPFCI_H
#define ZLMEDIAKIT_RTCPFCI_H
#include "Rtcp.h"
#include "Common/config.h"
#include "Rtcp.h"
namespace
mediakit
{
/////////////////////////////////////////// PSFB ////////////////////////////////////////////////////
//PSFB fmt = 2
//https://tools.ietf.org/html/rfc4585#section-6.3.2.2
//
PSFB fmt = 2
//
https://tools.ietf.org/html/rfc4585#section-6.3.2.2
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | First | Number | PictureID |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
//First: 13 bits
//
First: 13 bits
// The macroblock (MB) address of the first lost macroblock. The MB
// numbering is done such that the macroblock in the upper left
// corner of the picture is considered macroblock number 1 and the
...
...
@@ -101,8 +101,8 @@ public:
}
PACKED
;
#endif
//PSFB fmt = 4
//https://tools.ietf.org/html/rfc5104#section-4.3.1.1
//
PSFB fmt = 4
//
https://tools.ietf.org/html/rfc5104#section-4.3.1.1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...
...
@@ -188,8 +188,8 @@ private:
#endif
//PSFB fmt = 15
//https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
//
PSFB fmt = 15
//
https://tools.ietf.org/html/draft-alvestrand-rmcat-remb-03
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...
...
@@ -227,9 +227,9 @@ public:
std
::
vector
<
uint32_t
>
getSSRC
();
private
:
//Unique identifier 'R' 'E' 'M' 'B'
//
Unique identifier 'R' 'E' 'M' 'B'
char
magic
[
4
];
//Num SSRC (8 bits)/BR Exp (6 bits)/ BR Mantissa (18 bits)
//
Num SSRC (8 bits)/BR Exp (6 bits)/ BR Mantissa (18 bits)
uint8_t
bitrate
[
4
];
// SSRC feedback (32 bits) Consists of one or more SSRC entries which
// this feedback message applies to.
...
...
@@ -238,8 +238,8 @@ private:
/////////////////////////////////////////// RTPFB ////////////////////////////////////////////////////
//RTPFB fmt = 1
//https://tools.ietf.org/html/rfc4585#section-6.2.1
//
RTPFB fmt = 1
//
https://tools.ietf.org/html/rfc4585#section-6.2.1
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...
...
@@ -255,7 +255,7 @@ public:
void
check
(
size_t
size
);
uint16_t
getPid
()
const
;
uint16_t
getBlp
()
const
;
//返回丢包列表,总长度17,第一个包必丢
//
返回丢包列表,总长度17,第一个包必丢
// TODO: replace std::bitset
std
::
vector
<
bool
>
getBitArray
()
const
;
std
::
string
dumpString
()
const
;
...
...
@@ -318,20 +318,20 @@ public:
} PACKED;
#endif
enum
class
SymbolStatus
:
uint8_t
{
//Packet not received
enum
class
SymbolStatus
:
uint8_t
{
//
Packet not received
not_received
=
0
,
//Packet received, small delta (所谓small detal是指能用一个字节表示的数值)
//
Packet received, small delta (所谓small detal是指能用一个字节表示的数值)
small_delta
=
1
,
// Packet received, large ornegative delta (large即是能用两个字节表示的数值)
large_delta
=
2
,
//Reserved
//
Reserved
reserved
=
3
};
//RTPFB fmt = 15
//https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1
//https://zhuanlan.zhihu.com/p/206656654
//
RTPFB fmt = 15
//
https://tools.ietf.org/html/draft-holmer-rmcat-transport-wide-cc-extensions-01#section-3.1
//
https://zhuanlan.zhihu.com/p/206656654
// 0 1 2 3
// 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
...
...
@@ -351,14 +351,15 @@ enum class SymbolStatus : uint8_t{
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
// | recv delta | recv delta | zero padding |
// +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
class
FCI_TWCC
{
class
FCI_TWCC
{
public
:
static
size_t
constexpr
kSize
=
8
;
using
TwccPacketStatus
=
std
::
map
<
uint16_t
/*rtp ext seq*/
,
std
::
pair
<
SymbolStatus
,
int16_t
/*recv delta,单位为250us*/
>
>
;
using
TwccPacketStatus
=
std
::
map
<
uint16_t
/*rtp ext seq*/
,
std
::
pair
<
SymbolStatus
,
int16_t
/*recv delta,单位为250us*/
>>
;
void
check
(
size_t
size
);
std
::
string
dumpString
(
size_t
total_size
)
const
;
uint16_t
getBaseSeq
()
const
;
//单位64ms
//
单位64ms
uint32_t
getReferenceTime
()
const
;
uint16_t
getPacketCount
()
const
;
TwccPacketStatus
getPacketChunkList
(
size_t
total_size
)
const
;
...
...
@@ -366,15 +367,15 @@ public:
static
std
::
string
create
(
uint32_t
ref_time
,
uint8_t
fb_pkt_count
,
TwccPacketStatus
&
status
);
private
:
//base sequence number,基础序号,本次反馈的第一个包的序号;也就是RTP扩展头的序列号
//
base sequence number,基础序号,本次反馈的第一个包的序号;也就是RTP扩展头的序列号
uint16_t
base_seq
;
//packet status count, 包个数,本次反馈包含多少个包的状态;从基础序号开始算
//
packet status count, 包个数,本次反馈包含多少个包的状态;从基础序号开始算
uint16_t
pkt_status_count
;
//reference time,基准时间,绝对时间;计算该包中每个媒体包的到达时间都要基于这个基准时间计算
//
reference time,基准时间,绝对时间;计算该包中每个媒体包的到达时间都要基于这个基准时间计算
uint8_t
ref_time
[
3
];
//feedback packet count,反馈包号,本包是第几个transport-cc包,每次加1 |
//
feedback packet count,反馈包号,本包是第几个transport-cc包,每次加1 |
uint8_t
fb_pkt_count
;
}
PACKED
;
}
//namespace mediakit
#endif //ZLMEDIAKIT_RTCPFCI_H
}
//
namespace mediakit
#endif //
ZLMEDIAKIT_RTCPFCI_H
webrtc/WebRtcTransport.cpp
查看文件 @
cffc0743
...
...
@@ -9,11 +9,11 @@
*/
#include "WebRtcTransport.h"
#include <iostream>
#include "RtpExt.h"
#include "Rtcp/Rtcp.h"
#include "Rtcp/RtcpFCI.h"
#include "RtpExt.h"
#include "Rtsp/RtpReceiver.h"
#include <iostream>
#define RTP_SSRC_OFFSET 1
#define RTX_SSRC_OFFSET 2
...
...
@@ -25,17 +25,17 @@
using
namespace
std
;
using
namespace
mediakit
;
//RTC配置项目
//
RTC配置项目
namespace
RTC
{
#define RTC_FIELD "rtc."
//rtp和rtcp接受超时时间
const
string
kTimeOutSec
=
RTC_FIELD
"timeoutSec"
;
//服务器外网ip
const
string
kExternIP
=
RTC_FIELD
"externIP"
;
//设置remb比特率,非0时关闭twcc并开启remb。该设置在rtc推流时有效,可以控制推流画质
const
string
kRembBitRate
=
RTC_FIELD
"rembBitRate"
;
//webrtc单端口udp服务器
const
string
kPort
=
RTC_FIELD
"port"
;
//
rtp和rtcp接受超时时间
const
string
kTimeOutSec
=
RTC_FIELD
"timeoutSec"
;
//
服务器外网ip
const
string
kExternIP
=
RTC_FIELD
"externIP"
;
//
设置remb比特率,非0时关闭twcc并开启remb。该设置在rtc推流时有效,可以控制推流画质
const
string
kRembBitRate
=
RTC_FIELD
"rembBitRate"
;
//
webrtc单端口udp服务器
const
string
kPort
=
RTC_FIELD
"port"
;
static
onceToken
token
([]()
{
mINI
::
Instance
()[
kTimeOutSec
]
=
15
;
...
...
@@ -44,9 +44,9 @@ static onceToken token([]() {
mINI
::
Instance
()[
kPort
]
=
8000
;
});
}
//
namespace RTC
}
//
namespace RTC
static
atomic
<
uint64_t
>
s_key
{
0
};
static
atomic
<
uint64_t
>
s_key
{
0
};
static
void
translateIPFromEnv
(
std
::
vector
<
std
::
string
>
&
v
)
{
for
(
auto
iter
=
v
.
begin
();
iter
!=
v
.
end
();)
{
...
...
@@ -69,12 +69,12 @@ WebRtcTransport::WebRtcTransport(const EventPoller::Ptr &poller) {
_packet_pool
.
setSize
(
64
);
}
void
WebRtcTransport
::
onCreate
(){
void
WebRtcTransport
::
onCreate
()
{
_dtls_transport
=
std
::
make_shared
<
RTC
::
DtlsTransport
>
(
_poller
,
this
);
_ice_server
=
std
::
make_shared
<
RTC
::
IceServer
>
(
this
,
_identifier
,
makeRandStr
(
24
));
}
void
WebRtcTransport
::
onDestory
(){
void
WebRtcTransport
::
onDestory
()
{
#ifdef ENABLE_SCTP
_sctp
=
nullptr
;
#endif
...
...
@@ -82,7 +82,7 @@ void WebRtcTransport::onDestory(){
_ice_server
=
nullptr
;
}
const
EventPoller
::
Ptr
&
WebRtcTransport
::
getPoller
()
const
{
const
EventPoller
::
Ptr
&
WebRtcTransport
::
getPoller
()
const
{
return
_poller
;
}
...
...
@@ -92,8 +92,9 @@ const string &WebRtcTransport::getIdentifier() const {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
WebRtcTransport
::
OnIceServerSendStunPacket
(
const
RTC
::
IceServer
*
iceServer
,
const
RTC
::
StunPacket
*
packet
,
RTC
::
TransportTuple
*
tuple
)
{
sendSockData
((
char
*
)
packet
->
GetData
(),
packet
->
GetSize
(),
tuple
);
void
WebRtcTransport
::
OnIceServerSendStunPacket
(
const
RTC
::
IceServer
*
iceServer
,
const
RTC
::
StunPacket
*
packet
,
RTC
::
TransportTuple
*
tuple
)
{
sendSockData
((
char
*
)
packet
->
GetData
(),
packet
->
GetSize
(),
tuple
);
}
void
WebRtcTransport
::
OnIceServerSelectedTuple
(
const
RTC
::
IceServer
*
iceServer
,
RTC
::
TransportTuple
*
tuple
)
{
...
...
@@ -120,16 +121,13 @@ void WebRtcTransport::OnIceServerDisconnected(const RTC::IceServer *iceServer) {
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
WebRtcTransport
::
OnDtlsTransportConnected
(
const
RTC
::
DtlsTransport
*
dtlsTransport
,
RTC
::
SrtpSession
::
CryptoSuite
srtpCryptoSuite
,
uint8_t
*
srtpLocalKey
,
size_t
srtpLocalKeyLen
,
uint8_t
*
srtpRemoteKey
,
size_t
srtpRemoteKeyLen
,
std
::
string
&
remoteCert
)
{
const
RTC
::
DtlsTransport
*
dtlsTransport
,
RTC
::
SrtpSession
::
CryptoSuite
srtpCryptoSuite
,
uint8_t
*
srtpLocalKey
,
size_t
srtpLocalKeyLen
,
uint8_t
*
srtpRemoteKey
,
size_t
srtpRemoteKeyLen
,
std
::
string
&
remoteCert
)
{
InfoL
;
_srtp_session_send
=
std
::
make_shared
<
RTC
::
SrtpSession
>
(
RTC
::
SrtpSession
::
Type
::
OUTBOUND
,
srtpCryptoSuite
,
srtpLocalKey
,
srtpLocalKeyLen
);
_srtp_session_recv
=
std
::
make_shared
<
RTC
::
SrtpSession
>
(
RTC
::
SrtpSession
::
Type
::
INBOUND
,
srtpCryptoSuite
,
srtpRemoteKey
,
srtpRemoteKeyLen
);
_srtp_session_send
=
std
::
make_shared
<
RTC
::
SrtpSession
>
(
RTC
::
SrtpSession
::
Type
::
OUTBOUND
,
srtpCryptoSuite
,
srtpLocalKey
,
srtpLocalKeyLen
);
_srtp_session_recv
=
std
::
make_shared
<
RTC
::
SrtpSession
>
(
RTC
::
SrtpSession
::
Type
::
INBOUND
,
srtpCryptoSuite
,
srtpRemoteKey
,
srtpRemoteKeyLen
);
#ifdef ENABLE_SCTP
_sctp
=
std
::
make_shared
<
RTC
::
SctpAssociationImp
>
(
getPoller
(),
this
,
128
,
128
,
262144
,
true
);
_sctp
->
TransportConnected
();
...
...
@@ -137,7 +135,8 @@ void WebRtcTransport::OnDtlsTransportConnected(
onStartWebRTC
();
}
void
WebRtcTransport
::
OnDtlsTransportSendData
(
const
RTC
::
DtlsTransport
*
dtlsTransport
,
const
uint8_t
*
data
,
size_t
len
)
{
void
WebRtcTransport
::
OnDtlsTransportSendData
(
const
RTC
::
DtlsTransport
*
dtlsTransport
,
const
uint8_t
*
data
,
size_t
len
)
{
sendSockData
((
char
*
)
data
,
len
,
nullptr
);
}
...
...
@@ -155,7 +154,8 @@ void WebRtcTransport::OnDtlsTransportClosed(const RTC::DtlsTransport *dtlsTransp
onShutdown
(
SockException
(
Err_shutdown
,
"dtls close notify received"
));
}
void
WebRtcTransport
::
OnDtlsTransportApplicationDataReceived
(
const
RTC
::
DtlsTransport
*
dtlsTransport
,
const
uint8_t
*
data
,
size_t
len
)
{
void
WebRtcTransport
::
OnDtlsTransportApplicationDataReceived
(
const
RTC
::
DtlsTransport
*
dtlsTransport
,
const
uint8_t
*
data
,
size_t
len
)
{
#ifdef ENABLE_SCTP
_sctp
->
ProcessSctpData
(
data
,
len
);
#else
...
...
@@ -165,63 +165,64 @@ void WebRtcTransport::OnDtlsTransportApplicationDataReceived(const RTC::DtlsTran
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
#ifdef ENABLE_SCTP
void
WebRtcTransport
::
OnSctpAssociationConnecting
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
void
WebRtcTransport
::
OnSctpAssociationConnecting
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
TraceL
;
}
void
WebRtcTransport
::
OnSctpAssociationConnected
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
void
WebRtcTransport
::
OnSctpAssociationConnected
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
InfoL
<<
getIdentifier
();
}
void
WebRtcTransport
::
OnSctpAssociationFailed
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
void
WebRtcTransport
::
OnSctpAssociationFailed
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
WarnL
<<
getIdentifier
();
}
void
WebRtcTransport
::
OnSctpAssociationClosed
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
void
WebRtcTransport
::
OnSctpAssociationClosed
(
RTC
::
SctpAssociation
*
sctpAssociation
)
{
InfoL
<<
getIdentifier
();
}
void
WebRtcTransport
::
OnSctpAssociationSendData
(
RTC
::
SctpAssociation
*
sctpAssociation
,
const
uint8_t
*
data
,
size_t
len
)
{
void
WebRtcTransport
::
OnSctpAssociationSendData
(
RTC
::
SctpAssociation
*
sctpAssociation
,
const
uint8_t
*
data
,
size_t
len
)
{
_dtls_transport
->
SendApplicationData
(
data
,
len
);
}
void
WebRtcTransport
::
OnSctpAssociationMessageReceived
(
RTC
::
SctpAssociation
*
sctpAssociation
,
uint16_t
streamId
,
uint32_t
ppid
,
const
uint8_t
*
msg
,
size_t
len
)
{
void
WebRtcTransport
::
OnSctpAssociationMessageReceived
(
RTC
::
SctpAssociation
*
sctpAssociation
,
uint16_t
streamId
,
uint32_t
ppid
,
const
uint8_t
*
msg
,
size_t
len
)
{
InfoL
<<
getIdentifier
()
<<
" "
<<
streamId
<<
" "
<<
ppid
<<
" "
<<
len
<<
" "
<<
string
((
char
*
)
msg
,
len
);
RTC
::
SctpStreamParameters
params
;
params
.
streamId
=
streamId
;
//回显数据
//
回显数据
_sctp
->
SendSctpMessage
(
params
,
ppid
,
msg
,
len
);
}
#endif
//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
void
WebRtcTransport
::
sendSockData
(
const
char
*
buf
,
size_t
len
,
RTC
::
TransportTuple
*
tuple
){
void
WebRtcTransport
::
sendSockData
(
const
char
*
buf
,
size_t
len
,
RTC
::
TransportTuple
*
tuple
)
{
auto
pkt
=
_packet_pool
.
obtain2
();
pkt
->
assign
(
buf
,
len
);
onSendSockData
(
std
::
move
(
pkt
),
true
,
tuple
?
tuple
:
_ice_server
->
GetSelectedTuple
());
}
RTC
::
TransportTuple
*
WebRtcTransport
::
getSelectedTuple
()
const
{
RTC
::
TransportTuple
*
WebRtcTransport
::
getSelectedTuple
()
const
{
return
_ice_server
->
GetSelectedTuple
();
}
void
WebRtcTransport
::
sendRtcpRemb
(
uint32_t
ssrc
,
size_t
bit_rate
)
{
auto
remb
=
FCI_REMB
::
create
({
ssrc
},
(
uint32_t
)
bit_rate
);
auto
remb
=
FCI_REMB
::
create
({
ssrc
},
(
uint32_t
)
bit_rate
);
auto
fb
=
RtcpFB
::
create
(
PSFBType
::
RTCP_PSFB_REMB
,
remb
.
data
(),
remb
.
size
());
fb
->
ssrc
=
htonl
(
0
);
fb
->
ssrc_media
=
htonl
(
ssrc
);
sendRtcpPacket
((
char
*
)
fb
.
get
(),
fb
->
getSize
(),
true
);
sendRtcpPacket
((
char
*
)
fb
.
get
(),
fb
->
getSize
(),
true
);
}
void
WebRtcTransport
::
sendRtcpPli
(
uint32_t
ssrc
)
{
auto
pli
=
RtcpFB
::
create
(
PSFBType
::
RTCP_PSFB_PLI
);
pli
->
ssrc
=
htonl
(
0
);
pli
->
ssrc_media
=
htonl
(
ssrc
);
sendRtcpPacket
((
char
*
)
pli
.
get
(),
pli
->
getSize
(),
true
);
sendRtcpPacket
((
char
*
)
pli
.
get
(),
pli
->
getSize
(),
true
);
}
string
getFingerprint
(
const
string
&
algorithm_str
,
const
std
::
shared_ptr
<
RTC
::
DtlsTransport
>
&
transport
){
string
getFingerprint
(
const
string
&
algorithm_str
,
const
std
::
shared_ptr
<
RTC
::
DtlsTransport
>
&
transport
)
{
auto
algorithm
=
RTC
::
DtlsTransport
::
GetFingerprintAlgorithm
(
algorithm_str
);
for
(
auto
&
finger_prints
:
transport
->
GetLocalFingerprints
())
{
if
(
finger_prints
.
algorithm
==
algorithm
)
{
...
...
@@ -231,21 +232,22 @@ string getFingerprint(const string &algorithm_str, const std::shared_ptr<RTC::Dt
throw
std
::
invalid_argument
(
StrPrinter
<<
"不支持的加密算法:"
<<
algorithm_str
);
}
void
WebRtcTransport
::
setRemoteDtlsFingerprint
(
const
RtcSession
&
remote
){
//设置远端dtls签名
void
WebRtcTransport
::
setRemoteDtlsFingerprint
(
const
RtcSession
&
remote
)
{
//
设置远端dtls签名
RTC
::
DtlsTransport
::
Fingerprint
remote_fingerprint
;
remote_fingerprint
.
algorithm
=
RTC
::
DtlsTransport
::
GetFingerprintAlgorithm
(
_offer_sdp
->
media
[
0
].
fingerprint
.
algorithm
);
remote_fingerprint
.
algorithm
=
RTC
::
DtlsTransport
::
GetFingerprintAlgorithm
(
_offer_sdp
->
media
[
0
].
fingerprint
.
algorithm
);
remote_fingerprint
.
value
=
_offer_sdp
->
media
[
0
].
fingerprint
.
hash
;
_dtls_transport
->
SetRemoteFingerprint
(
remote_fingerprint
);
}
void
WebRtcTransport
::
onRtcConfigure
(
RtcConfigure
&
configure
)
const
{
//开启remb后关闭twcc,因为开启twcc后remb无效
//
开启remb后关闭twcc,因为开启twcc后remb无效
GET_CONFIG
(
size_t
,
remb_bit_rate
,
RTC
::
kRembBitRate
);
configure
.
enableTWCC
(
!
remb_bit_rate
);
}
std
::
string
WebRtcTransport
::
getAnswerSdp
(
const
string
&
offer
){
std
::
string
WebRtcTransport
::
getAnswerSdp
(
const
string
&
offer
)
{
try
{
//// 解析offer sdp ////
_offer_sdp
=
std
::
make_shared
<
RtcSession
>
();
...
...
@@ -259,8 +261,8 @@ std::string WebRtcTransport::getAnswerSdp(const string &offer){
fingerprint
.
algorithm
=
_offer_sdp
->
media
[
0
].
fingerprint
.
algorithm
;
fingerprint
.
hash
=
getFingerprint
(
fingerprint
.
algorithm
,
_dtls_transport
);
RtcConfigure
configure
;
configure
.
setDefaultSetting
(
_ice_server
->
GetUsernameFragment
(),
_ice_server
->
GetPassword
(),
RtpDirection
::
sendrecv
,
fingerprint
);
configure
.
setDefaultSetting
(
_ice_server
->
GetUsernameFragment
(),
_ice_server
->
GetPassword
(),
RtpDirection
::
sendrecv
,
fingerprint
);
onRtcConfigure
(
configure
);
//// 生成answer sdp ////
...
...
@@ -279,22 +281,22 @@ static bool is_dtls(char *buf) {
}
static
bool
is_rtp
(
char
*
buf
)
{
RtpHeader
*
header
=
(
RtpHeader
*
)
buf
;
RtpHeader
*
header
=
(
RtpHeader
*
)
buf
;
return
((
header
->
pt
<
64
)
||
(
header
->
pt
>=
96
));
}
static
bool
is_rtcp
(
char
*
buf
)
{
RtpHeader
*
header
=
(
RtpHeader
*
)
buf
;
RtpHeader
*
header
=
(
RtpHeader
*
)
buf
;
return
((
header
->
pt
>=
64
)
&&
(
header
->
pt
<
96
));
}
static
string
getPeerAddress
(
RTC
::
TransportTuple
*
tuple
){
static
string
getPeerAddress
(
RTC
::
TransportTuple
*
tuple
)
{
return
SockUtil
::
inet_ntoa
(
tuple
);
}
void
WebRtcTransport
::
inputSockData
(
char
*
buf
,
int
len
,
RTC
::
TransportTuple
*
tuple
)
{
if
(
RTC
::
StunPacket
::
IsStun
((
const
uint8_t
*
)
buf
,
len
))
{
std
::
unique_ptr
<
RTC
::
StunPacket
>
packet
(
RTC
::
StunPacket
::
Parse
((
const
uint8_t
*
)
buf
,
len
));
if
(
RTC
::
StunPacket
::
IsStun
((
const
uint8_t
*
)
buf
,
len
))
{
std
::
unique_ptr
<
RTC
::
StunPacket
>
packet
(
RTC
::
StunPacket
::
Parse
((
const
uint8_t
*
)
buf
,
len
));
if
(
!
packet
)
{
WarnL
<<
"parse stun error"
<<
std
::
endl
;
return
;
...
...
@@ -303,7 +305,7 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
return
;
}
if
(
is_dtls
(
buf
))
{
_dtls_transport
->
ProcessDtlsData
((
uint8_t
*
)
buf
,
len
);
_dtls_transport
->
ProcessDtlsData
((
uint8_t
*
)
buf
,
len
);
return
;
}
if
(
is_rtp
(
buf
))
{
...
...
@@ -311,7 +313,7 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
WarnL
<<
"received rtp packet when dtls not completed from:"
<<
getPeerAddress
(
tuple
);
return
;
}
if
(
_srtp_session_recv
->
DecryptSrtp
((
uint8_t
*
)
buf
,
&
len
))
{
if
(
_srtp_session_recv
->
DecryptSrtp
((
uint8_t
*
)
buf
,
&
len
))
{
onRtp
(
buf
,
len
,
_ticker
.
createdTime
());
}
return
;
...
...
@@ -321,7 +323,7 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
WarnL
<<
"received rtcp packet when dtls not completed from:"
<<
getPeerAddress
(
tuple
);
return
;
}
if
(
_srtp_session_recv
->
DecryptSrtcp
((
uint8_t
*
)
buf
,
&
len
))
{
if
(
_srtp_session_recv
->
DecryptSrtcp
((
uint8_t
*
)
buf
,
&
len
))
{
onRtcp
(
buf
,
len
);
}
return
;
...
...
@@ -331,8 +333,8 @@ void WebRtcTransport::inputSockData(char *buf, int len, RTC::TransportTuple *tup
void
WebRtcTransport
::
sendRtpPacket
(
const
char
*
buf
,
int
len
,
bool
flush
,
void
*
ctx
)
{
if
(
_srtp_session_send
)
{
auto
pkt
=
_packet_pool
.
obtain2
();
//预留rtx加入的两个字节
pkt
->
setCapacity
((
size_t
)
len
+
SRTP_MAX_TRAILER_LEN
+
2
);
//
预留rtx加入的两个字节
pkt
->
setCapacity
((
size_t
)
len
+
SRTP_MAX_TRAILER_LEN
+
2
);
pkt
->
assign
(
buf
,
len
);
onBeforeEncryptRtp
(
pkt
->
data
(),
len
,
ctx
);
if
(
_srtp_session_send
->
EncryptRtp
(
reinterpret_cast
<
uint8_t
*>
(
pkt
->
data
()),
&
len
))
{
...
...
@@ -345,8 +347,8 @@ void WebRtcTransport::sendRtpPacket(const char *buf, int len, bool flush, void *
void
WebRtcTransport
::
sendRtcpPacket
(
const
char
*
buf
,
int
len
,
bool
flush
,
void
*
ctx
)
{
if
(
_srtp_session_send
)
{
auto
pkt
=
_packet_pool
.
obtain2
();
//预留rtx加入的两个字节
pkt
->
setCapacity
((
size_t
)
len
+
SRTP_MAX_TRAILER_LEN
+
2
);
//
预留rtx加入的两个字节
pkt
->
setCapacity
((
size_t
)
len
+
SRTP_MAX_TRAILER_LEN
+
2
);
pkt
->
assign
(
buf
,
len
);
onBeforeEncryptRtcp
(
pkt
->
data
(),
len
,
ctx
);
if
(
_srtp_session_send
->
EncryptRtcp
(
reinterpret_cast
<
uint8_t
*>
(
pkt
->
data
()),
&
len
))
{
...
...
@@ -358,13 +360,15 @@ void WebRtcTransport::sendRtcpPacket(const char *buf, int len, bool flush, void
///////////////////////////////////////////////////////////////////////////////////
void
WebRtcTransportImp
::
onCreate
(){
void
WebRtcTransportImp
::
onCreate
()
{
WebRtcTransport
::
onCreate
();
registerSelf
();
weak_ptr
<
WebRtcTransportImp
>
weak_self
=
static_pointer_cast
<
WebRtcTransportImp
>
(
shared_from_this
());
GET_CONFIG
(
float
,
timeoutSec
,
RTC
::
kTimeOutSec
);
_timer
=
std
::
make_shared
<
Timer
>
(
timeoutSec
/
2
,
[
weak_self
]()
{
_timer
=
std
::
make_shared
<
Timer
>
(
timeoutSec
/
2
,
[
weak_self
]()
{
auto
strong_self
=
weak_self
.
lock
();
if
(
!
strong_self
)
{
return
false
;
...
...
@@ -373,14 +377,14 @@ void WebRtcTransportImp::onCreate(){
strong_self
->
onShutdown
(
SockException
(
Err_timeout
,
"接受rtp和rtcp超时"
));
}
return
true
;
},
getPoller
());
},
getPoller
());
_twcc_ctx
.
setOnSendTwccCB
([
this
](
uint32_t
ssrc
,
string
fci
)
{
onSendTwcc
(
ssrc
,
fci
);
});
_twcc_ctx
.
setOnSendTwccCB
([
this
](
uint32_t
ssrc
,
string
fci
)
{
onSendTwcc
(
ssrc
,
fci
);
});
}
WebRtcTransportImp
::
WebRtcTransportImp
(
const
EventPoller
::
Ptr
&
poller
)
:
WebRtcTransport
(
poller
)
{
WebRtcTransportImp
::
WebRtcTransportImp
(
const
EventPoller
::
Ptr
&
poller
)
:
WebRtcTransport
(
poller
)
{
InfoL
<<
getIdentifier
();
}
...
...
@@ -398,14 +402,14 @@ void WebRtcTransportImp::onSendSockData(Buffer::Ptr buf, bool flush, RTC::Transp
WarnL
<<
"send data failed:"
<<
buf
->
size
();
return
;
}
//一次性发送一帧的rtp数据,提高网络io性能
//
一次性发送一帧的rtp数据,提高网络io性能
_selected_session
->
setSendFlushFlag
(
flush
);
_selected_session
->
send
(
std
::
move
(
buf
));
}
///////////////////////////////////////////////////////////////////
bool
WebRtcTransportImp
::
canSendRtp
()
const
{
bool
WebRtcTransportImp
::
canSendRtp
()
const
{
for
(
auto
&
m
:
_answer_sdp
->
media
)
{
if
(
m
.
direction
==
RtpDirection
::
sendrecv
||
m
.
direction
==
RtpDirection
::
sendonly
)
{
return
true
;
...
...
@@ -414,7 +418,7 @@ bool WebRtcTransportImp::canSendRtp() const{
return
false
;
}
bool
WebRtcTransportImp
::
canRecvRtp
()
const
{
bool
WebRtcTransportImp
::
canRecvRtp
()
const
{
for
(
auto
&
m
:
_answer_sdp
->
media
)
{
if
(
m
.
direction
==
RtpDirection
::
sendrecv
||
m
.
direction
==
RtpDirection
::
recvonly
)
{
return
true
;
...
...
@@ -424,7 +428,7 @@ bool WebRtcTransportImp::canRecvRtp() const{
}
void
WebRtcTransportImp
::
onStartWebRTC
()
{
//获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息
//
获取ssrc和pt相关信息,届时收到rtp和rtcp时分别可以根据pt和ssrc找到相关的信息
for
(
auto
&
m_answer
:
_answer_sdp
->
media
)
{
if
(
m_answer
.
type
==
TrackApplication
)
{
continue
;
...
...
@@ -441,42 +445,43 @@ void WebRtcTransportImp::onStartWebRTC() {
track
->
plan_rtx
=
m_answer
.
getRelatedRtxPlan
(
track
->
plan_rtp
->
pt
);
track
->
rtcp_context_send
=
std
::
make_shared
<
RtcpContextForSend
>
();
//rtp track type --> MediaTrack
//
rtp track type --> MediaTrack
if
(
m_answer
.
direction
==
RtpDirection
::
sendonly
||
m_answer
.
direction
==
RtpDirection
::
sendrecv
)
{
//该类型的track 才支持发送
//
该类型的track 才支持发送
_type_to_track
[
m_answer
.
type
]
=
track
;
}
//send ssrc --> MediaTrack
//
send ssrc --> MediaTrack
_ssrc_to_track
[
track
->
answer_ssrc_rtp
]
=
track
;
_ssrc_to_track
[
track
->
answer_ssrc_rtx
]
=
track
;
//recv ssrc --> MediaTrack
//
recv ssrc --> MediaTrack
_ssrc_to_track
[
track
->
offer_ssrc_rtp
]
=
track
;
_ssrc_to_track
[
track
->
offer_ssrc_rtx
]
=
track
;
//rtp pt --> MediaTrack
_pt_to_track
.
emplace
(
track
->
plan_rtp
->
pt
,
std
::
unique_ptr
<
WrappedMediaTrack
>
(
new
WrappedRtpTrack
(
track
,
_twcc_ctx
,
*
this
)));
// rtp pt --> MediaTrack
_pt_to_track
.
emplace
(
track
->
plan_rtp
->
pt
,
std
::
unique_ptr
<
WrappedMediaTrack
>
(
new
WrappedRtpTrack
(
track
,
_twcc_ctx
,
*
this
)));
if
(
track
->
plan_rtx
)
{
//rtx pt --> MediaTrack
//
rtx pt --> MediaTrack
_pt_to_track
.
emplace
(
track
->
plan_rtx
->
pt
,
std
::
unique_ptr
<
WrappedMediaTrack
>
(
new
WrappedRtxTrack
(
track
)));
}
//记录rtp ext类型与id的关系,方便接收或发送rtp时修改rtp ext id
//
记录rtp ext类型与id的关系,方便接收或发送rtp时修改rtp ext id
track
->
rtp_ext_ctx
=
std
::
make_shared
<
RtpExtContext
>
(
*
m_offer
);
weak_ptr
<
MediaTrack
>
weak_track
=
track
;
track
->
rtp_ext_ctx
->
setOnGetRtp
([
this
,
weak_track
](
uint8_t
pt
,
uint32_t
ssrc
,
const
string
&
rid
)
{
//ssrc --> MediaTrack
//
ssrc --> MediaTrack
auto
track
=
weak_track
.
lock
();
assert
(
track
);
_ssrc_to_track
[
ssrc
]
=
std
::
move
(
track
);
InfoL
<<
"get rtp, pt:"
<<
(
int
)
pt
<<
", ssrc:"
<<
ssrc
<<
", rid:"
<<
rid
;
InfoL
<<
"get rtp, pt:"
<<
(
int
)
pt
<<
", ssrc:"
<<
ssrc
<<
", rid:"
<<
rid
;
});
size_t
index
=
0
;
for
(
auto
&
ssrc
:
m_offer
->
rtp_ssrc_sim
)
{
//记录ssrc对应的MediaTrack
//
记录ssrc对应的MediaTrack
_ssrc_to_track
[
ssrc
.
ssrc
]
=
track
;
if
(
m_offer
->
rtp_rids
.
size
()
>
index
)
{
//支持firefox的simulcast, 提前映射好ssrc和rid的关系
//
支持firefox的simulcast, 提前映射好ssrc和rid的关系
track
->
rtp_ext_ctx
->
setRid
(
ssrc
.
ssrc
,
m_offer
->
rtp_rids
[
index
]);
}
else
{
// SDP munging没有rid, 它通过group-ssrc:SIM给出ssrc列表;
...
...
@@ -493,7 +498,7 @@ void WebRtcTransportImp::onStartWebRTC() {
}
void
WebRtcTransportImp
::
onCheckAnswer
(
RtcSession
&
sdp
)
{
//修改answer sdp的ip、端口信息
//
修改answer sdp的ip、端口信息
GET_CONFIG_FUNC
(
std
::
vector
<
std
::
string
>
,
extern_ips
,
RTC
::
kExternIP
,
[](
string
str
)
{
std
::
vector
<
std
::
string
>
ret
;
if
(
str
.
length
())
{
...
...
@@ -515,7 +520,7 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
}
if
(
!
canSendRtp
())
{
//设置我们发送的rtp的ssrc
//
设置我们发送的rtp的ssrc
return
;
}
...
...
@@ -524,13 +529,13 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
continue
;
}
if
(
!
m
.
rtp_rtx_ssrc
.
empty
())
{
//已经生成了ssrc
//
已经生成了ssrc
continue
;
}
//添加answer sdp的ssrc信息
//
添加answer sdp的ssrc信息
m
.
rtp_rtx_ssrc
.
emplace_back
();
auto
&
ssrc
=
m
.
rtp_rtx_ssrc
.
back
();
//发送的ssrc我们随便定义,因为在发送rtp时会修改为此值
//
发送的ssrc我们随便定义,因为在发送rtp时会修改为此值
ssrc
.
ssrc
=
m
.
type
+
RTP_SSRC_OFFSET
;
ssrc
.
cname
=
RTP_CNAME
;
ssrc
.
label
=
RTP_LABEL
;
...
...
@@ -538,7 +543,7 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
ssrc
.
msid
=
RTP_MSID
;
if
(
m
.
getRelatedRtxPlan
(
m
.
plan
[
0
].
pt
))
{
//rtx ssrc
//
rtx ssrc
ssrc
.
rtx_ssrc
=
ssrc
.
ssrc
+
RTX_SSRC_OFFSET
;
}
}
...
...
@@ -546,20 +551,25 @@ void WebRtcTransportImp::onCheckAnswer(RtcSession &sdp) {
void
WebRtcTransportImp
::
onCheckSdp
(
SdpType
type
,
RtcSession
&
sdp
)
{
switch
(
type
)
{
case
SdpType
:
:
answer
:
onCheckAnswer
(
sdp
);
break
;
case
SdpType
:
:
offer
:
break
;
default
:
/*不可达*/
assert
(
0
);
break
;
case
SdpType
:
:
answer
:
onCheckAnswer
(
sdp
);
break
;
case
SdpType
:
:
offer
:
break
;
default
:
/*不可达*/
assert
(
0
);
break
;
}
}
SdpAttrCandidate
::
Ptr
makeIceCandidate
(
std
::
string
ip
,
uint16_t
port
,
uint32_t
priority
=
100
,
std
::
string
proto
=
"udp"
)
{
SdpAttrCandidate
::
Ptr
makeIceCandidate
(
std
::
string
ip
,
uint16_t
port
,
uint32_t
priority
=
100
,
std
::
string
proto
=
"udp"
)
{
auto
candidate
=
std
::
make_shared
<
SdpAttrCandidate
>
();
//rtp端口
//
rtp端口
candidate
->
component
=
1
;
candidate
->
transport
=
proto
;
candidate
->
foundation
=
proto
+
"candidate"
;
//优先级,单candidate时随便
//
优先级,单candidate时随便
candidate
->
priority
=
priority
;
candidate
->
address
=
ip
;
candidate
->
port
=
port
;
...
...
@@ -571,8 +581,8 @@ void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const {
WebRtcTransport
::
onRtcConfigure
(
configure
);
GET_CONFIG
(
uint16_t
,
local_port
,
RTC
::
kPort
);
//添加接收端口candidate信息
GET_CONFIG_FUNC
(
std
::
vector
<
std
::
string
>
,
extern_ips
,
RTC
::
kExternIP
,
[](
string
str
){
//
添加接收端口candidate信息
GET_CONFIG_FUNC
(
std
::
vector
<
std
::
string
>
,
extern_ips
,
RTC
::
kExternIP
,
[](
string
str
)
{
std
::
vector
<
std
::
string
>
ret
;
if
(
str
.
length
())
{
ret
=
split
(
str
,
","
);
...
...
@@ -593,19 +603,18 @@ void WebRtcTransportImp::onRtcConfigure(RtcConfigure &configure) const {
}
}
///////////////////////////////////////////////////////////////////
class
RtpChannel
:
public
RtpTrackImp
,
public
std
::
enable_shared_from_this
<
RtpChannel
>
{
class
RtpChannel
:
public
RtpTrackImp
,
public
std
::
enable_shared_from_this
<
RtpChannel
>
{
public
:
RtpChannel
(
EventPoller
::
Ptr
poller
,
RtpTrackImp
::
OnSorted
cb
,
function
<
void
(
const
FCI_NACK
&
nack
)
>
on_nack
)
{
_poller
=
std
::
move
(
poller
);
_on_nack
=
std
::
move
(
on_nack
);
setOnSorted
(
std
::
move
(
cb
));
_nack_ctx
.
setOnNack
([
this
](
const
FCI_NACK
&
nack
)
{
onNack
(
nack
);
});
_nack_ctx
.
setOnNack
([
this
](
const
FCI_NACK
&
nack
)
{
onNack
(
nack
);
});
}
~
RtpChannel
()
override
=
default
;
...
...
@@ -618,7 +627,7 @@ public:
auto
seq
=
rtp
->
getSeq
();
_nack_ctx
.
received
(
seq
,
is_rtx
);
if
(
!
is_rtx
)
{
//统计rtp接受情况,便于生成nack rtcp包
//
统计rtp接受情况,便于生成nack rtcp包
_rtcp_context
.
onRtp
(
seq
,
rtp
->
getStamp
(),
rtp
->
ntp_stamp
,
sample_rate
,
len
);
}
return
rtp
;
...
...
@@ -638,7 +647,7 @@ public:
}
private
:
void
starNackTimer
(){
void
starNackTimer
()
{
if
(
_delay_task
)
{
return
;
}
...
...
@@ -669,7 +678,7 @@ private:
function
<
void
(
const
FCI_NACK
&
nack
)
>
_on_nack
;
};
std
::
shared_ptr
<
RtpChannel
>
MediaTrack
::
getRtpChannel
(
uint32_t
ssrc
)
const
{
std
::
shared_ptr
<
RtpChannel
>
MediaTrack
::
getRtpChannel
(
uint32_t
ssrc
)
const
{
auto
it_chn
=
rtp_channel
.
find
(
rtp_ext_ctx
->
getRid
(
ssrc
));
if
(
it_chn
==
rtp_channel
.
end
())
{
return
nullptr
;
...
...
@@ -693,12 +702,12 @@ int WebRtcTransportImp::getLossRate(mediakit::TrackType type) {
void
WebRtcTransportImp
::
onRtcp
(
const
char
*
buf
,
size_t
len
)
{
_bytes_usage
+=
len
;
auto
rtcps
=
RtcpHeader
::
loadFromBytes
((
char
*
)
buf
,
len
);
auto
rtcps
=
RtcpHeader
::
loadFromBytes
((
char
*
)
buf
,
len
);
for
(
auto
rtcp
:
rtcps
)
{
switch
((
RtcpType
)
rtcp
->
pt
)
{
case
RtcpType
:
:
RTCP_SR
:
{
//
对方汇报rtp发送情况
RtcpSR
*
sr
=
(
RtcpSR
*
)
rtcp
;
switch
((
RtcpType
)
rtcp
->
pt
)
{
case
RtcpType
:
:
RTCP_SR
:
{
//
对方汇报rtp发送情况
RtcpSR
*
sr
=
(
RtcpSR
*
)
rtcp
;
auto
it
=
_ssrc_to_track
.
find
(
sr
->
ssrc
);
if
(
it
!=
_ssrc_to_track
.
end
())
{
auto
&
track
=
it
->
second
;
...
...
@@ -706,8 +715,8 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
if
(
!
rtp_chn
)
{
WarnL
<<
"未识别的sr rtcp包:"
<<
rtcp
->
dumpString
();
}
else
{
//
InfoL << "接收丢包率,ssrc:" << sr->ssrc << ",loss rate(%):" << rtp_chn->getLossRate();
//
设置rtp时间戳与ntp时间戳的对应关系
//
InfoL << "接收丢包率,ssrc:" << sr->ssrc << ",loss rate(%):" << rtp_chn->getLossRate();
//
设置rtp时间戳与ntp时间戳的对应关系
rtp_chn
->
setNtpStamp
(
sr
->
rtpts
,
sr
->
getNtpUnixStampMS
());
auto
rr
=
rtp_chn
->
createRtcpRR
(
sr
,
track
->
answer_ssrc_rtp
);
sendRtcpPacket
(
rr
->
data
(),
rr
->
size
(),
true
);
...
...
@@ -717,10 +726,10 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
}
break
;
}
case
RtcpType
:
:
RTCP_RR
:
{
case
RtcpType
:
:
RTCP_RR
:
{
_alive_ticker
.
resetTime
();
//
对方汇报rtp接收情况
RtcpRR
*
rr
=
(
RtcpRR
*
)
rtcp
;
//
对方汇报rtp接收情况
RtcpRR
*
rr
=
(
RtcpRR
*
)
rtcp
;
for
(
auto
item
:
rr
->
getItemList
())
{
auto
it
=
_ssrc_to_track
.
find
(
item
->
ssrc
);
if
(
it
!=
_ssrc_to_track
.
end
())
{
...
...
@@ -734,9 +743,9 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
}
break
;
}
case
RtcpType
:
:
RTCP_BYE
:
{
//
对方汇报停止发送rtp
RtcpBye
*
bye
=
(
RtcpBye
*
)
rtcp
;
case
RtcpType
:
:
RTCP_BYE
:
{
//
对方汇报停止发送rtp
RtcpBye
*
bye
=
(
RtcpBye
*
)
rtcp
;
for
(
auto
ssrc
:
bye
->
getSSRC
())
{
auto
it
=
_ssrc_to_track
.
find
(
*
ssrc
);
if
(
it
==
_ssrc_to_track
.
end
())
{
...
...
@@ -750,13 +759,13 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
}
case
RtcpType
:
:
RTCP_PSFB
:
case
RtcpType
:
:
RTCP_RTPFB
:
{
if
((
RtcpType
)
rtcp
->
pt
==
RtcpType
::
RTCP_PSFB
)
{
if
((
RtcpType
)
rtcp
->
pt
==
RtcpType
::
RTCP_PSFB
)
{
break
;
}
//
RTPFB
switch
((
RTPFBType
)
rtcp
->
report_count
)
{
case
RTPFBType
:
:
RTCP_RTPFB_NACK
:
{
RtcpFB
*
fb
=
(
RtcpFB
*
)
rtcp
;
//
RTPFB
switch
((
RTPFBType
)
rtcp
->
report_count
)
{
case
RTPFBType
:
:
RTCP_RTPFB_NACK
:
{
RtcpFB
*
fb
=
(
RtcpFB
*
)
rtcp
;
auto
it
=
_ssrc_to_track
.
find
(
fb
->
ssrc_media
);
if
(
it
==
_ssrc_to_track
.
end
())
{
WarnL
<<
"未识别的 rtcp包:"
<<
rtcp
->
dumpString
();
...
...
@@ -765,18 +774,19 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
auto
&
track
=
it
->
second
;
auto
&
fci
=
fb
->
getFci
<
FCI_NACK
>
();
track
->
nack_list
.
forEach
(
fci
,
[
&
](
const
RtpPacket
::
Ptr
&
rtp
)
{
//
rtp重传
//
rtp重传
onSendRtp
(
rtp
,
true
,
true
);
});
break
;
}
default
:
break
;
default
:
break
;
}
break
;
}
case
RtcpType
:
:
RTCP_XR
:
{
RtcpXRRRTR
*
xr
=
(
RtcpXRRRTR
*
)
rtcp
;
if
(
xr
->
bt
!=
4
)
{
case
RtcpType
:
:
RTCP_XR
:
{
RtcpXRRRTR
*
xr
=
(
RtcpXRRRTR
*
)
rtcp
;
if
(
xr
->
bt
!=
4
)
{
break
;
}
auto
it
=
_ssrc_to_track
.
find
(
xr
->
ssrc
);
...
...
@@ -786,12 +796,13 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
}
auto
&
track
=
it
->
second
;
track
->
rtcp_context_send
->
onRtcp
(
rtcp
);
auto
xrdlrr
=
track
->
rtcp_context_send
->
createRtcpXRDLRR
(
track
->
answer_ssrc_rtp
,
track
->
answer_ssrc_rtp
);
auto
xrdlrr
=
track
->
rtcp_context_send
->
createRtcpXRDLRR
(
track
->
answer_ssrc_rtp
,
track
->
answer_ssrc_rtp
);
sendRtcpPacket
(
xrdlrr
->
data
(),
xrdlrr
->
size
(),
true
);
break
;
}
default
:
break
;
default
:
break
;
}
}
}
...
...
@@ -799,13 +810,13 @@ void WebRtcTransportImp::onRtcp(const char *buf, size_t len) {
///////////////////////////////////////////////////////////////////
void
WebRtcTransportImp
::
createRtpChannel
(
const
string
&
rid
,
uint32_t
ssrc
,
MediaTrack
&
track
)
{
//rid --> RtpReceiverImp
//
rid --> RtpReceiverImp
auto
&
ref
=
track
.
rtp_channel
[
rid
];
weak_ptr
<
WebRtcTransportImp
>
weak_self
=
dynamic_pointer_cast
<
WebRtcTransportImp
>
(
shared_from_this
());
ref
=
std
::
make_shared
<
RtpChannel
>
(
getPoller
(),
[
&
track
,
this
,
rid
](
RtpPacket
::
Ptr
rtp
)
mutable
{
onSortedRtp
(
track
,
rid
,
std
::
move
(
rtp
));
},
[
&
track
,
weak_self
,
ssrc
](
const
FCI_NACK
&
nack
)
mutable
{
//
nack发送可能由定时器异步触发
ref
=
std
::
make_shared
<
RtpChannel
>
(
getPoller
(),
[
&
track
,
this
,
rid
](
RtpPacket
::
Ptr
rtp
)
mutable
{
onSortedRtp
(
track
,
rid
,
std
::
move
(
rtp
));
},
[
&
track
,
weak_self
,
ssrc
](
const
FCI_NACK
&
nack
)
mutable
{
//
nack发送可能由定时器异步触发
auto
strong_self
=
weak_self
.
lock
();
if
(
strong_self
)
{
strong_self
->
onSendNack
(
track
,
nack
,
ssrc
);
...
...
@@ -822,8 +833,8 @@ void WebRtcTransportImp::onRtp(const char *buf, size_t len, uint64_t stamp_ms) {
_bytes_usage
+=
len
;
_alive_ticker
.
resetTime
();
RtpHeader
*
rtp
=
(
RtpHeader
*
)
buf
;
//根据接收到的rtp的pt信息,找到该流的信息
RtpHeader
*
rtp
=
(
RtpHeader
*
)
buf
;
//
根据接收到的rtp的pt信息,找到该流的信息
auto
it
=
_pt_to_track
.
find
(
rtp
->
pt
);
if
(
it
==
_pt_to_track
.
end
())
{
WarnL
<<
"unknown rtp pt:"
<<
(
int
)
rtp
->
pt
;
...
...
@@ -843,7 +854,7 @@ void WrappedRtpTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, R
auto
ssrc
=
ntohl
(
rtp
->
ssrc
);
//修改ext id至统一
//
修改ext id至统一
string
rid
;
auto
twcc_ext
=
track
->
rtp_ext_ctx
->
changeRtpExtId
(
rtp
,
true
,
&
rid
,
RtpExtType
::
transport_cc
);
...
...
@@ -856,23 +867,24 @@ void WrappedRtpTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, R
_transport
.
createRtpChannel
(
rid
,
ssrc
,
*
track
);
}
//解析并排序rtp
ref
->
inputRtp
(
track
->
media
->
type
,
track
->
plan_rtp
->
sample_rate
,
(
uint8_t
*
)
buf
,
len
,
false
);
//
解析并排序rtp
ref
->
inputRtp
(
track
->
media
->
type
,
track
->
plan_rtp
->
sample_rate
,
(
uint8_t
*
)
buf
,
len
,
false
);
}
void
WrappedRtxTrack
::
inputRtp
(
const
char
*
buf
,
size_t
len
,
uint64_t
stamp_ms
,
RtpHeader
*
rtp
)
{
//修改ext id至统一
//
修改ext id至统一
string
rid
;
track
->
rtp_ext_ctx
->
changeRtpExtId
(
rtp
,
true
,
&
rid
,
RtpExtType
::
transport_cc
);
auto
&
ref
=
track
->
rtp_channel
[
rid
];
if
(
!
ref
)
{
//再接收到对应的rtp前,丢弃rtx包
WarnL
<<
"unknown rtx rtp, rid:"
<<
rid
<<
", ssrc:"
<<
ntohl
(
rtp
->
ssrc
)
<<
", codec:"
<<
track
->
plan_rtp
->
codec
<<
", seq:"
<<
ntohs
(
rtp
->
seq
);
// 再接收到对应的rtp前,丢弃rtx包
WarnL
<<
"unknown rtx rtp, rid:"
<<
rid
<<
", ssrc:"
<<
ntohl
(
rtp
->
ssrc
)
<<
", codec:"
<<
track
->
plan_rtp
->
codec
<<
", seq:"
<<
ntohs
(
rtp
->
seq
);
return
;
}
//这里是rtx重传包
//
这里是rtx重传包
// https://datatracker.ietf.org/doc/html/rfc4588#section-4
auto
payload
=
rtp
->
getPayloadData
();
auto
size
=
rtp
->
getPayloadSize
(
len
);
...
...
@@ -880,42 +892,42 @@ void WrappedRtxTrack::inputRtp(const char *buf, size_t len, uint64_t stamp_ms, R
return
;
}
//前两个字节是原始的rtp的seq
//
前两个字节是原始的rtp的seq
auto
origin_seq
=
payload
[
0
]
<<
8
|
payload
[
1
];
// rtx 转换为 rtp
rtp
->
pt
=
track
->
plan_rtp
->
pt
;
rtp
->
seq
=
htons
(
origin_seq
);
rtp
->
ssrc
=
htonl
(
ref
->
getSSRC
());
memmove
((
uint8_t
*
)
buf
+
2
,
buf
,
payload
-
(
uint8_t
*
)
buf
);
memmove
((
uint8_t
*
)
buf
+
2
,
buf
,
payload
-
(
uint8_t
*
)
buf
);
buf
+=
2
;
len
-=
2
;
ref
->
inputRtp
(
track
->
media
->
type
,
track
->
plan_rtp
->
sample_rate
,
(
uint8_t
*
)
buf
,
len
,
true
);
ref
->
inputRtp
(
track
->
media
->
type
,
track
->
plan_rtp
->
sample_rate
,
(
uint8_t
*
)
buf
,
len
,
true
);
}
void
WebRtcTransportImp
::
onSendNack
(
MediaTrack
&
track
,
const
FCI_NACK
&
nack
,
uint32_t
ssrc
)
{
auto
rtcp
=
RtcpFB
::
create
(
RTPFBType
::
RTCP_RTPFB_NACK
,
&
nack
,
FCI_NACK
::
kSize
);
rtcp
->
ssrc
=
htonl
(
track
.
answer_ssrc_rtp
);
rtcp
->
ssrc_media
=
htonl
(
ssrc
);
sendRtcpPacket
((
char
*
)
rtcp
.
get
(),
rtcp
->
getSize
(),
true
);
sendRtcpPacket
((
char
*
)
rtcp
.
get
(),
rtcp
->
getSize
(),
true
);
}
void
WebRtcTransportImp
::
onSendTwcc
(
uint32_t
ssrc
,
const
string
&
twcc_fci
)
{
auto
rtcp
=
RtcpFB
::
create
(
RTPFBType
::
RTCP_RTPFB_TWCC
,
twcc_fci
.
data
(),
twcc_fci
.
size
());
rtcp
->
ssrc
=
htonl
(
0
);
rtcp
->
ssrc_media
=
htonl
(
ssrc
);
sendRtcpPacket
((
char
*
)
rtcp
.
get
(),
rtcp
->
getSize
(),
true
);
sendRtcpPacket
((
char
*
)
rtcp
.
get
(),
rtcp
->
getSize
(),
true
);
}
///////////////////////////////////////////////////////////////////
void
WebRtcTransportImp
::
onSortedRtp
(
MediaTrack
&
track
,
const
string
&
rid
,
RtpPacket
::
Ptr
rtp
)
{
if
(
track
.
media
->
type
==
TrackVideo
&&
_pli_ticker
.
elapsedTime
()
>
2000
)
{
//定期发送pli请求关键帧,方便非rtc等协议
//
定期发送pli请求关键帧,方便非rtc等协议
_pli_ticker
.
resetTime
();
sendRtcpPli
(
rtp
->
getSSRC
());
//开启remb,则发送remb包调节比特率
//
开启remb,则发送remb包调节比特率
GET_CONFIG
(
size_t
,
remb_bit_rate
,
RTC
::
kRembBitRate
);
if
(
remb_bit_rate
&&
_answer_sdp
->
supportRtcpFb
(
SdpConst
::
kRembRtcpFb
))
{
sendRtcpRemb
(
rtp
->
getSSRC
(),
remb_bit_rate
);
...
...
@@ -930,12 +942,14 @@ void WebRtcTransportImp::onSortedRtp(MediaTrack &track, const string &rid, RtpPa
void
WebRtcTransportImp
::
onSendRtp
(
const
RtpPacket
::
Ptr
&
rtp
,
bool
flush
,
bool
rtx
)
{
auto
&
track
=
_type_to_track
[
rtp
->
type
];
if
(
!
track
)
{
//忽略,对方不支持该编码类型
//
忽略,对方不支持该编码类型
return
;
}
if
(
!
rtx
)
{
//统计rtp发送情况,好做sr汇报
track
->
rtcp_context_send
->
onRtp
(
rtp
->
getSeq
(),
rtp
->
getStamp
(),
rtp
->
ntp_stamp
,
rtp
->
sample_rate
,
rtp
->
size
()
-
RtpPacket
::
kRtpTcpHeaderSize
);
// 统计rtp发送情况,好做sr汇报
track
->
rtcp_context_send
->
onRtp
(
rtp
->
getSeq
(),
rtp
->
getStamp
(),
rtp
->
ntp_stamp
,
rtp
->
sample_rate
,
rtp
->
size
()
-
RtpPacket
::
kRtpTcpHeaderSize
);
track
->
nack_list
.
pushBack
(
rtp
);
#if 0
//此处模拟发送丢包
...
...
@@ -944,45 +958,45 @@ void WebRtcTransportImp::onSendRtp(const RtpPacket::Ptr &rtp, bool flush, bool r
}
#endif
}
else
{
//发送rtx重传包
//TraceL << "send rtx rtp:" << rtp->getSeq();
//
发送rtx重传包
//
TraceL << "send rtx rtp:" << rtp->getSeq();
}
pair
<
bool
/*rtx*/
,
MediaTrack
*>
ctx
{
rtx
,
track
.
get
()
};
pair
<
bool
/*rtx*/
,
MediaTrack
*>
ctx
{
rtx
,
track
.
get
()
};
sendRtpPacket
(
rtp
->
data
()
+
RtpPacket
::
kRtpTcpHeaderSize
,
rtp
->
size
()
-
RtpPacket
::
kRtpTcpHeaderSize
,
flush
,
&
ctx
);
_bytes_usage
+=
rtp
->
size
()
-
RtpPacket
::
kRtpTcpHeaderSize
;
}
void
WebRtcTransportImp
::
onBeforeEncryptRtp
(
const
char
*
buf
,
int
&
len
,
void
*
ctx
)
{
auto
pr
=
(
pair
<
bool
/*rtx*/
,
MediaTrack
*>
*
)
ctx
;
auto
header
=
(
RtpHeader
*
)
buf
;
auto
pr
=
(
pair
<
bool
/*rtx*/
,
MediaTrack
*>
*
)
ctx
;
auto
header
=
(
RtpHeader
*
)
buf
;
if
(
!
pr
->
first
||
!
pr
->
second
->
plan_rtx
)
{
//普通的rtp,或者不支持rtx, 修改目标pt和ssrc
//
普通的rtp,或者不支持rtx, 修改目标pt和ssrc
pr
->
second
->
rtp_ext_ctx
->
changeRtpExtId
(
header
,
false
);
header
->
pt
=
pr
->
second
->
plan_rtp
->
pt
;
header
->
ssrc
=
htonl
(
pr
->
second
->
answer_ssrc_rtp
);
}
else
{
//重传的rtp, rtx
//
重传的rtp, rtx
pr
->
second
->
rtp_ext_ctx
->
changeRtpExtId
(
header
,
false
);
header
->
pt
=
pr
->
second
->
plan_rtx
->
pt
;
if
(
pr
->
second
->
answer_ssrc_rtx
)
{
//有rtx单独的ssrc,有些情况下,浏览器支持rtx,但是未指定rtx单独的ssrc
//
有rtx单独的ssrc,有些情况下,浏览器支持rtx,但是未指定rtx单独的ssrc
header
->
ssrc
=
htonl
(
pr
->
second
->
answer_ssrc_rtx
);
}
else
{
//未单独指定rtx的ssrc,那么使用rtp的ssrc
//
未单独指定rtx的ssrc,那么使用rtp的ssrc
header
->
ssrc
=
htonl
(
pr
->
second
->
answer_ssrc_rtp
);
}
auto
origin_seq
=
ntohs
(
header
->
seq
);
//seq跟原来的不一样
//
seq跟原来的不一样
header
->
seq
=
htons
(
_rtx_seq
[
pr
->
second
->
media
->
type
]);
++
_rtx_seq
[
pr
->
second
->
media
->
type
];
auto
payload
=
header
->
getPayloadData
();
auto
payload_size
=
header
->
getPayloadSize
(
len
);
if
(
payload_size
)
{
//rtp负载后移两个字节,这两个字节用于存放osn
//https://datatracker.ietf.org/doc/html/rfc4588#section-4
//
rtp负载后移两个字节,这两个字节用于存放osn
//
https://datatracker.ietf.org/doc/html/rfc4588#section-4
memmove
(
payload
+
2
,
payload
,
payload_size
);
}
payload
[
0
]
=
origin_seq
>>
8
;
...
...
@@ -991,7 +1005,7 @@ void WebRtcTransportImp::onBeforeEncryptRtp(const char *buf, int &len, void *ctx
}
}
void
WebRtcTransportImp
::
onShutdown
(
const
SockException
&
ex
){
void
WebRtcTransportImp
::
onShutdown
(
const
SockException
&
ex
)
{
WarnL
<<
ex
.
what
();
unrefSelf
();
for
(
auto
&
pr
:
_history_sessions
)
{
...
...
@@ -1005,8 +1019,9 @@ void WebRtcTransportImp::onShutdown(const SockException &ex){
void
WebRtcTransportImp
::
setSession
(
Session
::
Ptr
session
)
{
_history_sessions
.
emplace
(
session
.
get
(),
session
);
if
(
_selected_session
)
{
InfoL
<<
"rtc network changed: "
<<
_selected_session
->
get_peer_ip
()
<<
":"
<<
_selected_session
->
get_peer_port
()
<<
" -> "
<<
session
->
get_peer_ip
()
<<
":"
<<
session
->
get_peer_port
()
<<
", id:"
<<
getIdentifier
();
InfoL
<<
"rtc network changed: "
<<
_selected_session
->
get_peer_ip
()
<<
":"
<<
_selected_session
->
get_peer_port
()
<<
" -> "
<<
session
->
get_peer_ip
()
<<
":"
<<
session
->
get_peer_port
()
<<
", id:"
<<
getIdentifier
();
}
_selected_session
=
std
::
move
(
session
);
unrefSelf
();
...
...
@@ -1016,11 +1031,11 @@ const Session::Ptr &WebRtcTransportImp::getSession() const {
return
_selected_session
;
}
uint64_t
WebRtcTransportImp
::
getBytesUsage
()
const
{
uint64_t
WebRtcTransportImp
::
getBytesUsage
()
const
{
return
_bytes_usage
;
}
uint64_t
WebRtcTransportImp
::
getDuration
()
const
{
uint64_t
WebRtcTransportImp
::
getDuration
()
const
{
return
_alive_ticker
.
createdTime
()
/
1000
;
}
...
...
@@ -1079,8 +1094,8 @@ void WebRtcPluginManager::registerPlugin(const string &type, Plugin cb) {
_map_creator
[
type
]
=
std
::
move
(
cb
);
}
void
WebRtcPluginManager
::
getAnswerSdp
(
Session
&
sender
,
const
string
&
type
,
const
string
&
offer
,
const
WebRtcArgs
&
args
,
const
onCreateRtc
&
cb
)
{
void
WebRtcPluginManager
::
getAnswerSdp
(
Session
&
sender
,
const
string
&
type
,
const
string
&
offer
,
const
WebRtcArgs
&
args
,
const
onCreateRtc
&
cb
)
{
lock_guard
<
mutex
>
lck
(
_mtx_creator
);
auto
it
=
_map_creator
.
find
(
type
);
if
(
it
==
_map_creator
.
end
())
{
...
...
@@ -1090,17 +1105,20 @@ void WebRtcPluginManager::getAnswerSdp(Session &sender, const string &type, cons
it
->
second
(
sender
,
offer
,
args
,
cb
);
}
#include "WebRtcEchoTest.h"
#include "WebRtcPlayer.h"
#include "WebRtcPusher.h"
#include "WebRtcEchoTest.h"
void
echo_plugin
(
Session
&
sender
,
const
string
&
offer
,
const
WebRtcArgs
&
args
,
const
WebRtcPluginManager
::
onCreateRtc
&
cb
)
{
void
echo_plugin
(
Session
&
sender
,
const
string
&
offer
,
const
WebRtcArgs
&
args
,
const
WebRtcPluginManager
::
onCreateRtc
&
cb
)
{
cb
(
*
WebRtcEchoTest
::
create
(
EventPollerPool
::
Instance
().
getPoller
()));
}
void
push_plugin
(
Session
&
sender
,
const
string
&
offer_sdp
,
const
WebRtcArgs
&
args
,
const
WebRtcPluginManager
::
onCreateRtc
&
cb
)
{
void
push_plugin
(
Session
&
sender
,
const
string
&
offer_sdp
,
const
WebRtcArgs
&
args
,
const
WebRtcPluginManager
::
onCreateRtc
&
cb
)
{
MediaInfo
info
(
args
[
"url"
]);
Broadcast
::
PublishAuthInvoker
invoker
=
[
cb
,
offer_sdp
,
info
](
const
string
&
err
,
const
ProtocolOption
&
option
)
mutable
{
Broadcast
::
PublishAuthInvoker
invoker
=
[
cb
,
offer_sdp
,
info
](
const
string
&
err
,
const
ProtocolOption
&
option
)
mutable
{
if
(
!
err
.
empty
())
{
cb
(
WebRtcException
(
SockException
(
Err_other
,
err
)));
return
;
...
...
@@ -1112,15 +1130,15 @@ void push_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
auto
push_failed
=
(
bool
)
src
;
while
(
src
)
{
//尝试断连后继续推流
//
尝试断连后继续推流
auto
rtsp_src
=
dynamic_pointer_cast
<
RtspMediaSourceImp
>
(
src
);
if
(
!
rtsp_src
)
{
//源不是rtsp推流产生的
//
源不是rtsp推流产生的
break
;
}
auto
ownership
=
rtsp_src
->
getOwnership
();
if
(
!
ownership
)
{
//获取推流源所有权失败
//
获取推流源所有权失败
break
;
}
push_src
=
std
::
move
(
rtsp_src
);
...
...
@@ -1139,20 +1157,23 @@ void push_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
push_src_ownership
=
push_src
->
getOwnership
();
push_src
->
setProtocolOption
(
option
);
}
auto
rtc
=
WebRtcPusher
::
create
(
EventPollerPool
::
Instance
().
getPoller
(),
push_src
,
push_src_ownership
,
info
,
option
);
auto
rtc
=
WebRtcPusher
::
create
(
EventPollerPool
::
Instance
().
getPoller
(),
push_src
,
push_src_ownership
,
info
,
option
);
push_src
->
setListener
(
rtc
);
cb
(
*
rtc
);
};
//rtsp推流需要鉴权
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPublish
,
MediaOriginType
::
rtc_push
,
info
,
invoker
,
static_cast
<
SockInfo
&>
(
sender
));
// rtsp推流需要鉴权
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPublish
,
MediaOriginType
::
rtc_push
,
info
,
invoker
,
static_cast
<
SockInfo
&>
(
sender
));
if
(
!
flag
)
{
//该事件无人监听,默认不鉴权
//
该事件无人监听,默认不鉴权
invoker
(
""
,
ProtocolOption
());
}
}
void
play_plugin
(
Session
&
sender
,
const
string
&
offer_sdp
,
const
WebRtcArgs
&
args
,
const
WebRtcPluginManager
::
onCreateRtc
&
cb
)
{
void
play_plugin
(
Session
&
sender
,
const
string
&
offer_sdp
,
const
WebRtcArgs
&
args
,
const
WebRtcPluginManager
::
onCreateRtc
&
cb
)
{
MediaInfo
info
(
args
[
"url"
]);
auto
session_ptr
=
sender
.
shared_from_this
();
Broadcast
::
AuthInvoker
invoker
=
[
cb
,
offer_sdp
,
info
,
session_ptr
](
const
string
&
err
)
mutable
{
...
...
@@ -1161,7 +1182,7 @@ void play_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
return
;
}
//webrtc播放的是rtsp的源
//
webrtc播放的是rtsp的源
info
.
_schema
=
RTSP_SCHEMA
;
MediaSource
::
findAsync
(
info
,
session_ptr
,
[
=
](
const
MediaSource
::
Ptr
&
src_in
)
mutable
{
auto
src
=
dynamic_pointer_cast
<
RtspMediaSource
>
(
src_in
);
...
...
@@ -1169,22 +1190,23 @@ void play_plugin(Session &sender, const string &offer_sdp, const WebRtcArgs &arg
cb
(
WebRtcException
(
SockException
(
Err_other
,
"stream not found"
)));
return
;
}
//还原成rtc,目的是为了hook时识别哪种播放协议
//
还原成rtc,目的是为了hook时识别哪种播放协议
info
.
_schema
=
RTC_SCHEMA
;
auto
rtc
=
WebRtcPlayer
::
create
(
EventPollerPool
::
Instance
().
getPoller
(),
src
,
info
);
cb
(
*
rtc
);
});
};
//广播通用播放url鉴权事件
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
info
,
invoker
,
static_cast
<
SockInfo
&>
(
sender
));
// 广播通用播放url鉴权事件
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
info
,
invoker
,
static_cast
<
SockInfo
&>
(
sender
));
if
(
!
flag
)
{
//该事件无人监听,默认不鉴权
//
该事件无人监听,默认不鉴权
invoker
(
""
);
}
}
static
onceToken
s_rtc_auto_register
([](){
static
onceToken
s_rtc_auto_register
([]()
{
WebRtcPluginManager
::
Instance
().
registerPlugin
(
"echo"
,
echo_plugin
);
WebRtcPluginManager
::
Instance
().
registerPlugin
(
"push"
,
push_plugin
);
WebRtcPluginManager
::
Instance
().
registerPlugin
(
"play"
,
play_plugin
);
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论