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
fbd711a6
Commit
fbd711a6
authored
Aug 30, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
整理代码
parent
42559146
显示空白字符变更
内嵌
并排
正在显示
28 个修改的文件
包含
1026 行增加
和
985 行删除
+1026
-985
src/Common/MediaSource.h
+1
-1
src/Extension/AAC.cpp
+1
-1
src/Extension/AACRtmp.cpp
+21
-21
src/Extension/CommonRtmp.cpp
+10
-10
src/Extension/H264Rtmp.cpp
+50
-50
src/Extension/H265Rtmp.cpp
+32
-32
src/Rtmp/FlvMuxer.cpp
+9
-9
src/Rtmp/FlvMuxer.h
+12
-9
src/Rtmp/Rtmp.h
+52
-44
src/Rtmp/RtmpCodec.h
+8
-9
src/Rtmp/RtmpDemuxer.cpp
+17
-17
src/Rtmp/RtmpDemuxer.h
+7
-5
src/Rtmp/RtmpMediaSource.h
+4
-4
src/Rtmp/RtmpMediaSourceImp.h
+4
-3
src/Rtmp/RtmpMediaSourceMuxer.h
+9
-8
src/Rtmp/RtmpMuxer.cpp
+3
-3
src/Rtmp/RtmpMuxer.h
+1
-1
src/Rtmp/RtmpPlayer.cpp
+160
-154
src/Rtmp/RtmpPlayer.h
+41
-35
src/Rtmp/RtmpPlayerImp.h
+28
-20
src/Rtmp/RtmpProtocol.cpp
+302
-308
src/Rtmp/RtmpProtocol.h
+47
-44
src/Rtmp/RtmpPusher.cpp
+8
-8
src/Rtmp/RtmpPusher.h
+1
-1
src/Rtmp/RtmpSession.cpp
+152
-148
src/Rtmp/RtmpSession.h
+21
-18
src/Rtsp/RtspPlayer.cpp
+24
-21
src/Rtsp/RtspSession.cpp
+1
-1
没有找到文件。
src/Common/MediaSource.h
查看文件 @
fbd711a6
...
@@ -174,7 +174,7 @@ public:
...
@@ -174,7 +174,7 @@ public:
}
}
uint32_t
getStamp
(
const
RtmpPacket
::
Ptr
&
packet
)
{
uint32_t
getStamp
(
const
RtmpPacket
::
Ptr
&
packet
)
{
return
packet
->
time
S
tamp
;
return
packet
->
time
_s
tamp
;
}
}
bool
isFlushAble
(
bool
is_video
,
bool
is_key
,
uint32_t
new_stamp
,
int
cache_size
);
bool
isFlushAble
(
bool
is_video
,
bool
is_key
,
uint32_t
new_stamp
,
int
cache_size
);
...
...
src/Extension/AAC.cpp
查看文件 @
fbd711a6
...
@@ -144,7 +144,7 @@ int dumpAacConfig(const string &config, int length, uint8_t *out, int out_size)
...
@@ -144,7 +144,7 @@ int dumpAacConfig(const string &config, int length, uint8_t *out, int out_size)
#ifndef ENABLE_MP4
#ifndef ENABLE_MP4
AdtsHeader
header
;
AdtsHeader
header
;
parseAacConfig
(
config
,
header
);
parseAacConfig
(
config
,
header
);
header
.
aac_frame_length
=
length
;
header
.
aac_frame_length
=
ADTS_HEADER_LEN
+
length
;
dumpAdtsHeader
(
header
,
out
);
dumpAdtsHeader
(
header
,
out
);
return
ADTS_HEADER_LEN
;
return
ADTS_HEADER_LEN
;
#else
#else
...
...
src/Extension/AACRtmp.cpp
查看文件 @
fbd711a6
...
@@ -21,11 +21,11 @@ static string getAacCfg(const RtmpPacket &thiz) {
...
@@ -21,11 +21,11 @@ static string getAacCfg(const RtmpPacket &thiz) {
if
(
!
thiz
.
isCfgFrame
())
{
if
(
!
thiz
.
isCfgFrame
())
{
return
ret
;
return
ret
;
}
}
if
(
thiz
.
strBuf
.
size
()
<
4
)
{
if
(
thiz
.
buffer
.
size
()
<
4
)
{
WarnL
<<
"bad aac cfg!"
;
WarnL
<<
"bad aac cfg!"
;
return
ret
;
return
ret
;
}
}
ret
=
thiz
.
strBuf
.
substr
(
2
);
ret
=
thiz
.
buffer
.
substr
(
2
);
return
ret
;
return
ret
;
}
}
...
@@ -37,7 +37,7 @@ bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) {
...
@@ -37,7 +37,7 @@ bool AACRtmpDecoder::inputRtmp(const RtmpPacket::Ptr &pkt, bool) {
}
}
if
(
!
_aac_cfg
.
empty
())
{
if
(
!
_aac_cfg
.
empty
())
{
onGetAAC
(
pkt
->
strBuf
.
data
()
+
2
,
pkt
->
strBuf
.
size
()
-
2
,
pkt
->
timeS
tamp
);
onGetAAC
(
pkt
->
buffer
.
data
()
+
2
,
pkt
->
buffer
.
size
()
-
2
,
pkt
->
time_s
tamp
);
}
}
return
false
;
return
false
;
}
}
...
@@ -97,21 +97,21 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
...
@@ -97,21 +97,21 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
if
(
!
_aac_cfg
.
empty
()){
if
(
!
_aac_cfg
.
empty
()){
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
rtmpPkt
->
strBuf
.
clear
();
rtmpPkt
->
buffer
.
clear
();
//header
//header
uint8_t
is_config
=
false
;
uint8_t
is_config
=
false
;
rtmpPkt
->
strBuf
.
push_back
(
_audio_flv_flags
);
rtmpPkt
->
buffer
.
push_back
(
_audio_flv_flags
);
rtmpPkt
->
strBuf
.
push_back
(
!
is_config
);
rtmpPkt
->
buffer
.
push_back
(
!
is_config
);
//aac data
//aac data
rtmpPkt
->
strBuf
.
append
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
rtmpPkt
->
buffer
.
append
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
rtmpPkt
->
body
Size
=
rtmpPkt
->
strBuf
.
size
();
rtmpPkt
->
body
_size
=
rtmpPkt
->
buffer
.
size
();
rtmpPkt
->
chunk
I
d
=
CHUNK_AUDIO
;
rtmpPkt
->
chunk
_i
d
=
CHUNK_AUDIO
;
rtmpPkt
->
stream
Id
=
STREAM_MEDIA
;
rtmpPkt
->
stream
_index
=
STREAM_MEDIA
;
rtmpPkt
->
time
S
tamp
=
frame
->
dts
();
rtmpPkt
->
time
_s
tamp
=
frame
->
dts
();
rtmpPkt
->
type
I
d
=
MSG_AUDIO
;
rtmpPkt
->
type
_i
d
=
MSG_AUDIO
;
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
}
}
}
}
...
@@ -119,20 +119,20 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
...
@@ -119,20 +119,20 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
void
AACRtmpEncoder
::
makeAudioConfigPkt
()
{
void
AACRtmpEncoder
::
makeAudioConfigPkt
()
{
_audio_flv_flags
=
getAudioRtmpFlags
(
std
::
make_shared
<
AACTrack
>
(
_aac_cfg
));
_audio_flv_flags
=
getAudioRtmpFlags
(
std
::
make_shared
<
AACTrack
>
(
_aac_cfg
));
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
rtmpPkt
->
strBuf
.
clear
();
rtmpPkt
->
buffer
.
clear
();
//header
//header
uint8_t
is_config
=
true
;
uint8_t
is_config
=
true
;
rtmpPkt
->
strBuf
.
push_back
(
_audio_flv_flags
);
rtmpPkt
->
buffer
.
push_back
(
_audio_flv_flags
);
rtmpPkt
->
strBuf
.
push_back
(
!
is_config
);
rtmpPkt
->
buffer
.
push_back
(
!
is_config
);
//aac config
//aac config
rtmpPkt
->
strBuf
.
append
(
_aac_cfg
);
rtmpPkt
->
buffer
.
append
(
_aac_cfg
);
rtmpPkt
->
body
Size
=
rtmpPkt
->
strBuf
.
size
();
rtmpPkt
->
body
_size
=
rtmpPkt
->
buffer
.
size
();
rtmpPkt
->
chunk
I
d
=
CHUNK_AUDIO
;
rtmpPkt
->
chunk
_i
d
=
CHUNK_AUDIO
;
rtmpPkt
->
stream
Id
=
STREAM_MEDIA
;
rtmpPkt
->
stream
_index
=
STREAM_MEDIA
;
rtmpPkt
->
time
S
tamp
=
0
;
rtmpPkt
->
time
_s
tamp
=
0
;
rtmpPkt
->
type
I
d
=
MSG_AUDIO
;
rtmpPkt
->
type
_i
d
=
MSG_AUDIO
;
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
}
}
...
...
src/Extension/CommonRtmp.cpp
查看文件 @
fbd711a6
...
@@ -31,8 +31,8 @@ void CommonRtmpDecoder::obtainFrame() {
...
@@ -31,8 +31,8 @@ void CommonRtmpDecoder::obtainFrame() {
bool
CommonRtmpDecoder
::
inputRtmp
(
const
RtmpPacket
::
Ptr
&
rtmp
,
bool
)
{
bool
CommonRtmpDecoder
::
inputRtmp
(
const
RtmpPacket
::
Ptr
&
rtmp
,
bool
)
{
//拷贝负载
//拷贝负载
_frame
->
_buffer
.
assign
(
rtmp
->
strBuf
.
data
()
+
1
,
rtmp
->
strBuf
.
size
()
-
1
);
_frame
->
_buffer
.
assign
(
rtmp
->
buffer
.
data
()
+
1
,
rtmp
->
buffer
.
size
()
-
1
);
_frame
->
_dts
=
rtmp
->
time
S
tamp
;
_frame
->
_dts
=
rtmp
->
time
_s
tamp
;
//写入环形缓存
//写入环形缓存
RtmpCodec
::
inputFrame
(
_frame
);
RtmpCodec
::
inputFrame
(
_frame
);
//创建下一帧
//创建下一帧
...
@@ -51,16 +51,16 @@ void CommonRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
...
@@ -51,16 +51,16 @@ void CommonRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
return
;
return
;
}
}
RtmpPacket
::
Ptr
rtmp
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
RtmpPacket
::
Ptr
rtmp
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
rtmp
->
strBuf
.
clear
();
rtmp
->
buffer
.
clear
();
//header
//header
rtmp
->
strBuf
.
push_back
(
_audio_flv_flags
);
rtmp
->
buffer
.
push_back
(
_audio_flv_flags
);
//data
//data
rtmp
->
strBuf
.
append
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
rtmp
->
buffer
.
append
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
rtmp
->
body
Size
=
rtmp
->
strBuf
.
size
();
rtmp
->
body
_size
=
rtmp
->
buffer
.
size
();
rtmp
->
chunk
I
d
=
CHUNK_AUDIO
;
rtmp
->
chunk
_i
d
=
CHUNK_AUDIO
;
rtmp
->
stream
Id
=
STREAM_MEDIA
;
rtmp
->
stream
_index
=
STREAM_MEDIA
;
rtmp
->
time
S
tamp
=
frame
->
dts
();
rtmp
->
time
_s
tamp
=
frame
->
dts
();
rtmp
->
type
I
d
=
MSG_AUDIO
;
rtmp
->
type
_i
d
=
MSG_AUDIO
;
RtmpCodec
::
inputRtmp
(
rtmp
,
false
);
RtmpCodec
::
inputRtmp
(
rtmp
,
false
);
}
}
...
...
src/Extension/H264Rtmp.cpp
查看文件 @
fbd711a6
...
@@ -39,18 +39,18 @@ static string getH264SPS(const RtmpPacket &thiz) {
...
@@ -39,18 +39,18 @@ static string getH264SPS(const RtmpPacket &thiz) {
if
(
!
thiz
.
isCfgFrame
())
{
if
(
!
thiz
.
isCfgFrame
())
{
return
ret
;
return
ret
;
}
}
if
(
thiz
.
strBuf
.
size
()
<
13
)
{
if
(
thiz
.
buffer
.
size
()
<
13
)
{
WarnL
<<
"bad H264 cfg!"
;
WarnL
<<
"bad H264 cfg!"
;
return
ret
;
return
ret
;
}
}
uint16_t
sps_size
;
uint16_t
sps_size
;
memcpy
(
&
sps_size
,
thiz
.
strBuf
.
data
()
+
11
,
2
);
memcpy
(
&
sps_size
,
thiz
.
buffer
.
data
()
+
11
,
2
);
sps_size
=
ntohs
(
sps_size
);
sps_size
=
ntohs
(
sps_size
);
if
((
int
)
thiz
.
strBuf
.
size
()
<
13
+
sps_size
)
{
if
((
int
)
thiz
.
buffer
.
size
()
<
13
+
sps_size
)
{
WarnL
<<
"bad H264 cfg!"
;
WarnL
<<
"bad H264 cfg!"
;
return
ret
;
return
ret
;
}
}
ret
.
assign
(
thiz
.
strBuf
.
data
()
+
13
,
sps_size
);
ret
.
assign
(
thiz
.
buffer
.
data
()
+
13
,
sps_size
);
return
ret
;
return
ret
;
}
}
...
@@ -66,27 +66,27 @@ static string getH264PPS(const RtmpPacket &thiz) {
...
@@ -66,27 +66,27 @@ static string getH264PPS(const RtmpPacket &thiz) {
if
(
!
thiz
.
isCfgFrame
())
{
if
(
!
thiz
.
isCfgFrame
())
{
return
ret
;
return
ret
;
}
}
if
(
thiz
.
strBuf
.
size
()
<
13
)
{
if
(
thiz
.
buffer
.
size
()
<
13
)
{
WarnL
<<
"bad H264 cfg!"
;
WarnL
<<
"bad H264 cfg!"
;
return
ret
;
return
ret
;
}
}
uint16_t
sps_size
;
uint16_t
sps_size
;
memcpy
(
&
sps_size
,
thiz
.
strBuf
.
data
()
+
11
,
2
);
memcpy
(
&
sps_size
,
thiz
.
buffer
.
data
()
+
11
,
2
);
sps_size
=
ntohs
(
sps_size
);
sps_size
=
ntohs
(
sps_size
);
if
((
int
)
thiz
.
strBuf
.
size
()
<
13
+
sps_size
+
1
+
2
)
{
if
((
int
)
thiz
.
buffer
.
size
()
<
13
+
sps_size
+
1
+
2
)
{
WarnL
<<
"bad H264 cfg!"
;
WarnL
<<
"bad H264 cfg!"
;
return
ret
;
return
ret
;
}
}
uint16_t
pps_size
;
uint16_t
pps_size
;
memcpy
(
&
pps_size
,
thiz
.
strBuf
.
data
()
+
13
+
sps_size
+
1
,
2
);
memcpy
(
&
pps_size
,
thiz
.
buffer
.
data
()
+
13
+
sps_size
+
1
,
2
);
pps_size
=
ntohs
(
pps_size
);
pps_size
=
ntohs
(
pps_size
);
if
((
int
)
thiz
.
strBuf
.
size
()
<
13
+
sps_size
+
1
+
2
+
pps_size
)
{
if
((
int
)
thiz
.
buffer
.
size
()
<
13
+
sps_size
+
1
+
2
+
pps_size
)
{
WarnL
<<
"bad H264 cfg!"
;
WarnL
<<
"bad H264 cfg!"
;
return
ret
;
return
ret
;
}
}
ret
.
assign
(
thiz
.
strBuf
.
data
()
+
13
+
sps_size
+
1
+
2
,
pps_size
);
ret
.
assign
(
thiz
.
buffer
.
data
()
+
13
+
sps_size
+
1
+
2
,
pps_size
);
return
ret
;
return
ret
;
}
}
...
@@ -95,27 +95,27 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
...
@@ -95,27 +95,27 @@ bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
//缓存sps pps,后续插入到I帧之前
//缓存sps pps,后续插入到I帧之前
_sps
=
getH264SPS
(
*
pkt
);
_sps
=
getH264SPS
(
*
pkt
);
_pps
=
getH264PPS
(
*
pkt
);
_pps
=
getH264PPS
(
*
pkt
);
onGetH264
(
_sps
.
data
(),
_sps
.
size
(),
pkt
->
time
Stamp
,
pkt
->
timeS
tamp
);
onGetH264
(
_sps
.
data
(),
_sps
.
size
(),
pkt
->
time
_stamp
,
pkt
->
time_s
tamp
);
onGetH264
(
_pps
.
data
(),
_pps
.
size
(),
pkt
->
time
Stamp
,
pkt
->
timeS
tamp
);
onGetH264
(
_pps
.
data
(),
_pps
.
size
(),
pkt
->
time
_stamp
,
pkt
->
time_s
tamp
);
return
false
;
return
false
;
}
}
if
(
pkt
->
strBuf
.
size
()
>
9
)
{
if
(
pkt
->
buffer
.
size
()
>
9
)
{
uint32_t
iTotalLen
=
pkt
->
strBuf
.
size
();
uint32_t
iTotalLen
=
pkt
->
buffer
.
size
();
uint32_t
iOffset
=
5
;
uint32_t
iOffset
=
5
;
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
strBuf
.
data
()
+
2
);
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
buffer
.
data
()
+
2
);
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
auto
pts
=
pkt
->
time
S
tamp
+
cts
;
auto
pts
=
pkt
->
time
_s
tamp
+
cts
;
while
(
iOffset
+
4
<
iTotalLen
){
while
(
iOffset
+
4
<
iTotalLen
){
uint32_t
iFrameLen
;
uint32_t
iFrameLen
;
memcpy
(
&
iFrameLen
,
pkt
->
strBuf
.
data
()
+
iOffset
,
4
);
memcpy
(
&
iFrameLen
,
pkt
->
buffer
.
data
()
+
iOffset
,
4
);
iFrameLen
=
ntohl
(
iFrameLen
);
iFrameLen
=
ntohl
(
iFrameLen
);
iOffset
+=
4
;
iOffset
+=
4
;
if
(
iFrameLen
+
iOffset
>
iTotalLen
){
if
(
iFrameLen
+
iOffset
>
iTotalLen
){
break
;
break
;
}
}
onGetH264
(
pkt
->
strBuf
.
data
()
+
iOffset
,
iFrameLen
,
pkt
->
timeS
tamp
,
pts
);
onGetH264
(
pkt
->
buffer
.
data
()
+
iOffset
,
iFrameLen
,
pkt
->
time_s
tamp
,
pts
);
iOffset
+=
iFrameLen
;
iOffset
+=
iFrameLen
;
}
}
}
}
...
@@ -190,7 +190,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
...
@@ -190,7 +190,7 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
}
}
}
}
if
(
_lastPacket
&&
_lastPacket
->
time
S
tamp
!=
frame
->
dts
())
{
if
(
_lastPacket
&&
_lastPacket
->
time
_s
tamp
!=
frame
->
dts
())
{
RtmpCodec
::
inputRtmp
(
_lastPacket
,
_lastPacket
->
isVideoKeyFrame
());
RtmpCodec
::
inputRtmp
(
_lastPacket
,
_lastPacket
->
isVideoKeyFrame
());
_lastPacket
=
nullptr
;
_lastPacket
=
nullptr
;
}
}
...
@@ -202,23 +202,23 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
...
@@ -202,23 +202,23 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
_lastPacket
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
_lastPacket
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
_lastPacket
->
strBuf
.
clear
();
_lastPacket
->
buffer
.
clear
();
_lastPacket
->
strBuf
.
push_back
(
flags
);
_lastPacket
->
buffer
.
push_back
(
flags
);
_lastPacket
->
strBuf
.
push_back
(
!
is_config
);
_lastPacket
->
buffer
.
push_back
(
!
is_config
);
auto
cts
=
frame
->
pts
()
-
frame
->
dts
();
auto
cts
=
frame
->
pts
()
-
frame
->
dts
();
cts
=
htonl
(
cts
);
cts
=
htonl
(
cts
);
_lastPacket
->
strBuf
.
append
((
char
*
)
&
cts
+
1
,
3
);
_lastPacket
->
buffer
.
append
((
char
*
)
&
cts
+
1
,
3
);
_lastPacket
->
chunk
I
d
=
CHUNK_VIDEO
;
_lastPacket
->
chunk
_i
d
=
CHUNK_VIDEO
;
_lastPacket
->
stream
Id
=
STREAM_MEDIA
;
_lastPacket
->
stream
_index
=
STREAM_MEDIA
;
_lastPacket
->
time
S
tamp
=
frame
->
dts
();
_lastPacket
->
time
_s
tamp
=
frame
->
dts
();
_lastPacket
->
type
I
d
=
MSG_VIDEO
;
_lastPacket
->
type
_i
d
=
MSG_VIDEO
;
}
}
auto
size
=
htonl
(
iLen
);
auto
size
=
htonl
(
iLen
);
_lastPacket
->
strBuf
.
append
((
char
*
)
&
size
,
4
);
_lastPacket
->
buffer
.
append
((
char
*
)
&
size
,
4
);
_lastPacket
->
strBuf
.
append
(
pcData
,
iLen
);
_lastPacket
->
buffer
.
append
(
pcData
,
iLen
);
_lastPacket
->
body
Size
=
_lastPacket
->
strBuf
.
size
();
_lastPacket
->
body
_size
=
_lastPacket
->
buffer
.
size
();
}
}
void
H264RtmpEncoder
::
makeVideoConfigPkt
()
{
void
H264RtmpEncoder
::
makeVideoConfigPkt
()
{
...
@@ -227,38 +227,38 @@ void H264RtmpEncoder::makeVideoConfigPkt() {
...
@@ -227,38 +227,38 @@ void H264RtmpEncoder::makeVideoConfigPkt() {
bool
is_config
=
true
;
bool
is_config
=
true
;
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
rtmpPkt
->
strBuf
.
clear
();
rtmpPkt
->
buffer
.
clear
();
//header
//header
rtmpPkt
->
strBuf
.
push_back
(
flags
);
rtmpPkt
->
buffer
.
push_back
(
flags
);
rtmpPkt
->
strBuf
.
push_back
(
!
is_config
);
rtmpPkt
->
buffer
.
push_back
(
!
is_config
);
//cts
//cts
rtmpPkt
->
strBuf
.
append
(
"\x0\x0\x0"
,
3
);
rtmpPkt
->
buffer
.
append
(
"\x0\x0\x0"
,
3
);
//AVCDecoderConfigurationRecord start
//AVCDecoderConfigurationRecord start
rtmpPkt
->
strBuf
.
push_back
(
1
);
// version
rtmpPkt
->
buffer
.
push_back
(
1
);
// version
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
1
]);
// profile
rtmpPkt
->
buffer
.
push_back
(
_sps
[
1
]);
// profile
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
2
]);
// compat
rtmpPkt
->
buffer
.
push_back
(
_sps
[
2
]);
// compat
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
3
]);
// level
rtmpPkt
->
buffer
.
push_back
(
_sps
[
3
]);
// level
rtmpPkt
->
strBuf
.
push_back
(
0xff
);
// 6 bits reserved + 2 bits nal size length - 1 (11)
rtmpPkt
->
buffer
.
push_back
(
0xff
);
// 6 bits reserved + 2 bits nal size length - 1 (11)
rtmpPkt
->
strBuf
.
push_back
(
0xe1
);
// 3 bits reserved + 5 bits number of sps (00001)
rtmpPkt
->
buffer
.
push_back
(
0xe1
);
// 3 bits reserved + 5 bits number of sps (00001)
//sps
//sps
uint16_t
size
=
_sps
.
size
();
uint16_t
size
=
_sps
.
size
();
size
=
htons
(
size
);
size
=
htons
(
size
);
rtmpPkt
->
strBuf
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
buffer
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
strBuf
.
append
(
_sps
);
rtmpPkt
->
buffer
.
append
(
_sps
);
//pps
//pps
rtmpPkt
->
strBuf
.
push_back
(
1
);
// version
rtmpPkt
->
buffer
.
push_back
(
1
);
// version
size
=
_pps
.
size
();
size
=
_pps
.
size
();
size
=
htons
(
size
);
size
=
htons
(
size
);
rtmpPkt
->
strBuf
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
buffer
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
strBuf
.
append
(
_pps
);
rtmpPkt
->
buffer
.
append
(
_pps
);
rtmpPkt
->
body
Size
=
rtmpPkt
->
strBuf
.
size
();
rtmpPkt
->
body
_size
=
rtmpPkt
->
buffer
.
size
();
rtmpPkt
->
chunk
I
d
=
CHUNK_VIDEO
;
rtmpPkt
->
chunk
_i
d
=
CHUNK_VIDEO
;
rtmpPkt
->
stream
Id
=
STREAM_MEDIA
;
rtmpPkt
->
stream
_index
=
STREAM_MEDIA
;
rtmpPkt
->
time
S
tamp
=
0
;
rtmpPkt
->
time
_s
tamp
=
0
;
rtmpPkt
->
type
I
d
=
MSG_VIDEO
;
rtmpPkt
->
type
_i
d
=
MSG_VIDEO
;
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
}
}
...
...
src/Extension/H265Rtmp.cpp
查看文件 @
fbd711a6
...
@@ -43,13 +43,13 @@ static bool getH265ConfigFrame(const RtmpPacket &thiz,string &frame) {
...
@@ -43,13 +43,13 @@ static bool getH265ConfigFrame(const RtmpPacket &thiz,string &frame) {
if
(
!
thiz
.
isCfgFrame
())
{
if
(
!
thiz
.
isCfgFrame
())
{
return
false
;
return
false
;
}
}
if
(
thiz
.
strBuf
.
size
()
<
6
)
{
if
(
thiz
.
buffer
.
size
()
<
6
)
{
WarnL
<<
"bad H265 cfg!"
;
WarnL
<<
"bad H265 cfg!"
;
return
false
;
return
false
;
}
}
auto
extra
=
thiz
.
strBuf
.
data
()
+
5
;
auto
extra
=
thiz
.
buffer
.
data
()
+
5
;
auto
bytes
=
thiz
.
strBuf
.
size
()
-
5
;
auto
bytes
=
thiz
.
buffer
.
size
()
-
5
;
struct
mpeg4_hevc_t
hevc
=
{
0
};
struct
mpeg4_hevc_t
hevc
=
{
0
};
if
(
mpeg4_hevc_decoder_configuration_record_load
((
uint8_t
*
)
extra
,
bytes
,
&
hevc
)
>
0
)
{
if
(
mpeg4_hevc_decoder_configuration_record_load
((
uint8_t
*
)
extra
,
bytes
,
&
hevc
)
>
0
)
{
...
@@ -70,7 +70,7 @@ bool H265RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
...
@@ -70,7 +70,7 @@ bool H265RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
#ifdef ENABLE_MP4
#ifdef ENABLE_MP4
string
config
;
string
config
;
if
(
getH265ConfigFrame
(
*
pkt
,
config
)){
if
(
getH265ConfigFrame
(
*
pkt
,
config
)){
onGetH265
(
config
.
data
(),
config
.
size
(),
pkt
->
time
Stamp
,
pkt
->
timeS
tamp
);
onGetH265
(
config
.
data
(),
config
.
size
(),
pkt
->
time
_stamp
,
pkt
->
time_s
tamp
);
}
}
#else
#else
WarnL
<<
"请开启MP4相关功能并使能
\"
ENABLE_MP4
\"
,否则对H265-RTMP支持不完善"
;
WarnL
<<
"请开启MP4相关功能并使能
\"
ENABLE_MP4
\"
,否则对H265-RTMP支持不完善"
;
...
@@ -78,22 +78,22 @@ bool H265RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
...
@@ -78,22 +78,22 @@ bool H265RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
return
false
;
return
false
;
}
}
if
(
pkt
->
strBuf
.
size
()
>
9
)
{
if
(
pkt
->
buffer
.
size
()
>
9
)
{
uint32_t
iTotalLen
=
pkt
->
strBuf
.
size
();
uint32_t
iTotalLen
=
pkt
->
buffer
.
size
();
uint32_t
iOffset
=
5
;
uint32_t
iOffset
=
5
;
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
strBuf
.
data
()
+
2
);
uint8_t
*
cts_ptr
=
(
uint8_t
*
)
(
pkt
->
buffer
.
data
()
+
2
);
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
int32_t
cts
=
(((
cts_ptr
[
0
]
<<
16
)
|
(
cts_ptr
[
1
]
<<
8
)
|
(
cts_ptr
[
2
]))
+
0xff800000
)
^
0xff800000
;
auto
pts
=
pkt
->
time
S
tamp
+
cts
;
auto
pts
=
pkt
->
time
_s
tamp
+
cts
;
while
(
iOffset
+
4
<
iTotalLen
){
while
(
iOffset
+
4
<
iTotalLen
){
uint32_t
iFrameLen
;
uint32_t
iFrameLen
;
memcpy
(
&
iFrameLen
,
pkt
->
strBuf
.
data
()
+
iOffset
,
4
);
memcpy
(
&
iFrameLen
,
pkt
->
buffer
.
data
()
+
iOffset
,
4
);
iFrameLen
=
ntohl
(
iFrameLen
);
iFrameLen
=
ntohl
(
iFrameLen
);
iOffset
+=
4
;
iOffset
+=
4
;
if
(
iFrameLen
+
iOffset
>
iTotalLen
){
if
(
iFrameLen
+
iOffset
>
iTotalLen
){
break
;
break
;
}
}
onGetH265
(
pkt
->
strBuf
.
data
()
+
iOffset
,
iFrameLen
,
pkt
->
timeS
tamp
,
pts
);
onGetH265
(
pkt
->
buffer
.
data
()
+
iOffset
,
iFrameLen
,
pkt
->
time_s
tamp
,
pts
);
iOffset
+=
iFrameLen
;
iOffset
+=
iFrameLen
;
}
}
}
}
...
@@ -176,7 +176,7 @@ void H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
...
@@ -176,7 +176,7 @@ void H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
return
;
return
;
}
}
if
(
_lastPacket
&&
_lastPacket
->
time
S
tamp
!=
frame
->
dts
())
{
if
(
_lastPacket
&&
_lastPacket
->
time
_s
tamp
!=
frame
->
dts
())
{
RtmpCodec
::
inputRtmp
(
_lastPacket
,
_lastPacket
->
isVideoKeyFrame
());
RtmpCodec
::
inputRtmp
(
_lastPacket
,
_lastPacket
->
isVideoKeyFrame
());
_lastPacket
=
nullptr
;
_lastPacket
=
nullptr
;
}
}
...
@@ -188,23 +188,23 @@ void H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
...
@@ -188,23 +188,23 @@ void H265RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
flags
|=
(((
frame
->
configFrame
()
||
frame
->
keyFrame
())
?
FLV_KEY_FRAME
:
FLV_INTER_FRAME
)
<<
4
);
_lastPacket
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
_lastPacket
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
_lastPacket
->
strBuf
.
clear
();
_lastPacket
->
buffer
.
clear
();
_lastPacket
->
strBuf
.
push_back
(
flags
);
_lastPacket
->
buffer
.
push_back
(
flags
);
_lastPacket
->
strBuf
.
push_back
(
!
is_config
);
_lastPacket
->
buffer
.
push_back
(
!
is_config
);
auto
cts
=
frame
->
pts
()
-
frame
->
dts
();
auto
cts
=
frame
->
pts
()
-
frame
->
dts
();
cts
=
htonl
(
cts
);
cts
=
htonl
(
cts
);
_lastPacket
->
strBuf
.
append
((
char
*
)
&
cts
+
1
,
3
);
_lastPacket
->
buffer
.
append
((
char
*
)
&
cts
+
1
,
3
);
_lastPacket
->
chunk
I
d
=
CHUNK_VIDEO
;
_lastPacket
->
chunk
_i
d
=
CHUNK_VIDEO
;
_lastPacket
->
stream
Id
=
STREAM_MEDIA
;
_lastPacket
->
stream
_index
=
STREAM_MEDIA
;
_lastPacket
->
time
S
tamp
=
frame
->
dts
();
_lastPacket
->
time
_s
tamp
=
frame
->
dts
();
_lastPacket
->
type
I
d
=
MSG_VIDEO
;
_lastPacket
->
type
_i
d
=
MSG_VIDEO
;
}
}
auto
size
=
htonl
(
iLen
);
auto
size
=
htonl
(
iLen
);
_lastPacket
->
strBuf
.
append
((
char
*
)
&
size
,
4
);
_lastPacket
->
buffer
.
append
((
char
*
)
&
size
,
4
);
_lastPacket
->
strBuf
.
append
(
pcData
,
iLen
);
_lastPacket
->
buffer
.
append
(
pcData
,
iLen
);
_lastPacket
->
body
Size
=
_lastPacket
->
strBuf
.
size
();
_lastPacket
->
body
_size
=
_lastPacket
->
buffer
.
size
();
}
}
void
H265RtmpEncoder
::
makeVideoConfigPkt
()
{
void
H265RtmpEncoder
::
makeVideoConfigPkt
()
{
...
@@ -214,13 +214,13 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
...
@@ -214,13 +214,13 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
bool
is_config
=
true
;
bool
is_config
=
true
;
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
rtmpPkt
->
strBuf
.
clear
();
rtmpPkt
->
buffer
.
clear
();
//header
//header
rtmpPkt
->
strBuf
.
push_back
(
flags
);
rtmpPkt
->
buffer
.
push_back
(
flags
);
rtmpPkt
->
strBuf
.
push_back
(
!
is_config
);
rtmpPkt
->
buffer
.
push_back
(
!
is_config
);
//cts
//cts
rtmpPkt
->
strBuf
.
append
(
"\x0\x0\x0"
,
3
);
rtmpPkt
->
buffer
.
append
(
"\x0\x0\x0"
,
3
);
struct
mpeg4_hevc_t
hevc
=
{
0
};
struct
mpeg4_hevc_t
hevc
=
{
0
};
string
vps_sps_pps
=
string
(
"
\x00\x00\x00\x01
"
,
4
)
+
_vps
+
string
vps_sps_pps
=
string
(
"
\x00\x00\x00\x01
"
,
4
)
+
_vps
+
...
@@ -235,13 +235,13 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
...
@@ -235,13 +235,13 @@ void H265RtmpEncoder::makeVideoConfigPkt() {
}
}
//HEVCDecoderConfigurationRecord
//HEVCDecoderConfigurationRecord
rtmpPkt
->
strBuf
.
append
((
char
*
)
extra_data
,
extra_data_size
);
rtmpPkt
->
buffer
.
append
((
char
*
)
extra_data
,
extra_data_size
);
rtmpPkt
->
body
Size
=
rtmpPkt
->
strBuf
.
size
();
rtmpPkt
->
body
_size
=
rtmpPkt
->
buffer
.
size
();
rtmpPkt
->
chunk
I
d
=
CHUNK_VIDEO
;
rtmpPkt
->
chunk
_i
d
=
CHUNK_VIDEO
;
rtmpPkt
->
stream
Id
=
STREAM_MEDIA
;
rtmpPkt
->
stream
_index
=
STREAM_MEDIA
;
rtmpPkt
->
time
S
tamp
=
0
;
rtmpPkt
->
time
_s
tamp
=
0
;
rtmpPkt
->
type
I
d
=
MSG_VIDEO
;
rtmpPkt
->
type
_i
d
=
MSG_VIDEO
;
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
RtmpCodec
::
inputRtmp
(
rtmpPkt
,
false
);
#else
#else
WarnL
<<
"请开启MP4相关功能并使能
\"
ENABLE_MP4
\"
,否则对H265-RTMP支持不完善"
;
WarnL
<<
"请开启MP4相关功能并使能
\"
ENABLE_MP4
\"
,否则对H265-RTMP支持不完善"
;
...
...
src/Rtmp/FlvMuxer.cpp
查看文件 @
fbd711a6
...
@@ -73,10 +73,10 @@ void FlvMuxer::onWriteFlvHeader(const RtmpMediaSource::Ptr &mediaSrc) {
...
@@ -73,10 +73,10 @@ void FlvMuxer::onWriteFlvHeader(const RtmpMediaSource::Ptr &mediaSrc) {
bool
is_have_audio
=
false
,
is_have_video
=
false
;
bool
is_have_audio
=
false
,
is_have_video
=
false
;
mediaSrc
->
getConfigFrame
([
&
](
const
RtmpPacket
::
Ptr
&
pkt
){
mediaSrc
->
getConfigFrame
([
&
](
const
RtmpPacket
::
Ptr
&
pkt
){
if
(
pkt
->
type
I
d
==
MSG_VIDEO
){
if
(
pkt
->
type
_i
d
==
MSG_VIDEO
){
is_have_video
=
true
;
is_have_video
=
true
;
}
}
if
(
pkt
->
type
I
d
==
MSG_AUDIO
){
if
(
pkt
->
type
_i
d
==
MSG_AUDIO
){
is_have_audio
=
true
;
is_have_audio
=
true
;
}
}
});
});
...
@@ -133,16 +133,16 @@ public:
...
@@ -133,16 +133,16 @@ public:
#pragma pack(pop)
#pragma pack(pop)
#endif // defined(_WIN32)
#endif // defined(_WIN32)
void
FlvMuxer
::
onWriteFlvTag
(
const
RtmpPacket
::
Ptr
&
pkt
,
uint32_t
ui32TimeS
tamp
,
bool
flush
)
{
void
FlvMuxer
::
onWriteFlvTag
(
const
RtmpPacket
::
Ptr
&
pkt
,
uint32_t
time_s
tamp
,
bool
flush
)
{
onWriteFlvTag
(
pkt
->
type
Id
,
pkt
,
ui32TimeS
tamp
,
flush
);
onWriteFlvTag
(
pkt
->
type
_id
,
pkt
,
time_s
tamp
,
flush
);
}
}
void
FlvMuxer
::
onWriteFlvTag
(
uint8_t
ui8Type
,
const
Buffer
::
Ptr
&
buffer
,
uint32_t
ui32TimeS
tamp
,
bool
flush
)
{
void
FlvMuxer
::
onWriteFlvTag
(
uint8_t
type
,
const
Buffer
::
Ptr
&
buffer
,
uint32_t
time_s
tamp
,
bool
flush
)
{
RtmpTagHeader
header
;
RtmpTagHeader
header
;
header
.
type
=
ui8T
ype
;
header
.
type
=
t
ype
;
set_be24
(
header
.
data_size
,
buffer
->
size
());
set_be24
(
header
.
data_size
,
buffer
->
size
());
header
.
timestamp_ex
=
(
uint8_t
)
((
ui32TimeS
tamp
>>
24
)
&
0xff
);
header
.
timestamp_ex
=
(
uint8_t
)
((
time_s
tamp
>>
24
)
&
0xff
);
set_be24
(
header
.
timestamp
,
ui32TimeS
tamp
&
0xFFFFFF
);
set_be24
(
header
.
timestamp
,
time_s
tamp
&
0xFFFFFF
);
//tag header
//tag header
onWrite
(
std
::
make_shared
<
BufferRaw
>
((
char
*
)
&
header
,
sizeof
(
header
)),
false
);
onWrite
(
std
::
make_shared
<
BufferRaw
>
((
char
*
)
&
header
,
sizeof
(
header
)),
false
);
//tag data
//tag data
...
@@ -154,7 +154,7 @@ void FlvMuxer::onWriteFlvTag(uint8_t ui8Type, const Buffer::Ptr &buffer, uint32_
...
@@ -154,7 +154,7 @@ void FlvMuxer::onWriteFlvTag(uint8_t ui8Type, const Buffer::Ptr &buffer, uint32_
void
FlvMuxer
::
onWriteRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
,
bool
flush
)
{
void
FlvMuxer
::
onWriteRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
,
bool
flush
)
{
int64_t
dts_out
;
int64_t
dts_out
;
_stamp
[
pkt
->
type
Id
%
2
].
revise
(
pkt
->
timeS
tamp
,
0
,
dts_out
,
dts_out
);
_stamp
[
pkt
->
type
_id
%
2
].
revise
(
pkt
->
time_s
tamp
,
0
,
dts_out
,
dts_out
);
onWriteFlvTag
(
pkt
,
dts_out
,
flush
);
onWriteFlvTag
(
pkt
,
dts_out
,
flush
);
}
}
...
...
src/Rtmp/FlvMuxer.h
查看文件 @
fbd711a6
...
@@ -25,21 +25,23 @@ public:
...
@@ -25,21 +25,23 @@ public:
FlvMuxer
();
FlvMuxer
();
virtual
~
FlvMuxer
();
virtual
~
FlvMuxer
();
void
stop
();
void
stop
();
protected
:
protected
:
void
start
(
const
EventPoller
::
Ptr
&
poller
,
const
RtmpMediaSource
::
Ptr
&
media
);
void
start
(
const
EventPoller
::
Ptr
&
poller
,
const
RtmpMediaSource
::
Ptr
&
media
);
virtual
void
onWrite
(
const
Buffer
::
Ptr
&
data
,
bool
flush
)
=
0
;
virtual
void
onWrite
(
const
Buffer
::
Ptr
&
data
,
bool
flush
)
=
0
;
virtual
void
onDetach
()
=
0
;
virtual
void
onDetach
()
=
0
;
virtual
std
::
shared_ptr
<
FlvMuxer
>
getSharedPtr
()
=
0
;
virtual
std
::
shared_ptr
<
FlvMuxer
>
getSharedPtr
()
=
0
;
private
:
private
:
void
onWriteFlvHeader
(
const
RtmpMediaSource
::
Ptr
&
media
);
void
onWriteFlvHeader
(
const
RtmpMediaSource
::
Ptr
&
media
);
void
onWriteRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
,
bool
flush
);
void
onWriteRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
,
bool
flush
);
void
onWriteFlvTag
(
const
RtmpPacket
::
Ptr
&
pkt
,
uint32_t
ui32TimeStamp
,
bool
flush
);
void
onWriteFlvTag
(
const
RtmpPacket
::
Ptr
&
pkt
,
uint32_t
time_stamp
,
bool
flush
);
void
onWriteFlvTag
(
uint8_t
ui8Type
,
const
Buffer
::
Ptr
&
buffer
,
uint32_t
ui32TimeStamp
,
bool
flush
);
void
onWriteFlvTag
(
uint8_t
type
,
const
Buffer
::
Ptr
&
buffer
,
uint32_t
time_stamp
,
bool
flush
);
private
:
private
:
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_ring_reader
;
//时间戳修整器
//时间戳修整器
Stamp
_stamp
[
2
];
Stamp
_stamp
[
2
];
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_ring_reader
;
};
};
class
FlvRecorder
:
public
FlvMuxer
,
public
std
::
enable_shared_from_this
<
FlvRecorder
>
{
class
FlvRecorder
:
public
FlvMuxer
,
public
std
::
enable_shared_from_this
<
FlvRecorder
>
{
...
@@ -47,12 +49,14 @@ public:
...
@@ -47,12 +49,14 @@ public:
typedef
std
::
shared_ptr
<
FlvRecorder
>
Ptr
;
typedef
std
::
shared_ptr
<
FlvRecorder
>
Ptr
;
FlvRecorder
();
FlvRecorder
();
virtual
~
FlvRecorder
();
virtual
~
FlvRecorder
();
void
startRecord
(
const
EventPoller
::
Ptr
&
poller
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
,
const
string
&
file_path
);
void
startRecord
(
const
EventPoller
::
Ptr
&
poller
,
const
RtmpMediaSource
::
Ptr
&
media
,
const
string
&
file_path
);
void
startRecord
(
const
EventPoller
::
Ptr
&
poller
,
const
RtmpMediaSource
::
Ptr
&
media
,
const
string
&
file_path
);
void
startRecord
(
const
EventPoller
::
Ptr
&
poller
,
const
string
&
vhost
,
const
string
&
app
,
const
string
&
stream
,
const
string
&
file_path
);
private
:
private
:
virtual
void
onWrite
(
const
Buffer
::
Ptr
&
data
,
bool
flush
)
override
;
virtual
void
onWrite
(
const
Buffer
::
Ptr
&
data
,
bool
flush
)
override
;
virtual
void
onDetach
()
override
;
virtual
void
onDetach
()
override
;
virtual
std
::
shared_ptr
<
FlvMuxer
>
getSharedPtr
()
override
;
virtual
std
::
shared_ptr
<
FlvMuxer
>
getSharedPtr
()
override
;
private
:
private
:
std
::
shared_ptr
<
FILE
>
_file
;
std
::
shared_ptr
<
FILE
>
_file
;
recursive_mutex
_file_mtx
;
recursive_mutex
_file_mtx
;
...
@@ -60,5 +64,4 @@ private:
...
@@ -60,5 +64,4 @@ private:
}
//namespace mediakit
}
//namespace mediakit
#endif //ZLMEDIAKIT_FLVMUXER_H
#endif //ZLMEDIAKIT_FLVMUXER_H
src/Rtmp/Rtmp.h
查看文件 @
fbd711a6
...
@@ -23,9 +23,6 @@
...
@@ -23,9 +23,6 @@
using
namespace
toolkit
;
using
namespace
toolkit
;
#define PORT 1935
#define DEFAULT_CHUNK_LEN 128
#if !defined(_WIN32)
#if !defined(_WIN32)
#define PACKED __attribute__((packed))
#define PACKED __attribute__((packed))
#else
#else
...
@@ -33,6 +30,7 @@ using namespace toolkit;
...
@@ -33,6 +30,7 @@ using namespace toolkit;
#endif //!defined(_WIN32)
#endif //!defined(_WIN32)
#define DEFAULT_CHUNK_LEN 128
#define HANDSHAKE_PLAINTEXT 0x03
#define HANDSHAKE_PLAINTEXT 0x03
#define RANDOM_LEN (1536 - 8)
#define RANDOM_LEN (1536 - 8)
...
@@ -91,22 +89,24 @@ class RtmpHandshake {
...
@@ -91,22 +89,24 @@ class RtmpHandshake {
public
:
public
:
RtmpHandshake
(
uint32_t
_time
,
uint8_t
*
_random
=
nullptr
)
{
RtmpHandshake
(
uint32_t
_time
,
uint8_t
*
_random
=
nullptr
)
{
_time
=
htonl
(
_time
);
_time
=
htonl
(
_time
);
memcpy
(
time
S
tamp
,
&
_time
,
4
);
memcpy
(
time
_s
tamp
,
&
_time
,
4
);
if
(
!
_random
)
{
if
(
!
_random
)
{
random_generate
((
char
*
)
random
,
sizeof
(
random
));
random_generate
((
char
*
)
random
,
sizeof
(
random
));
}
else
{
}
else
{
memcpy
(
random
,
_random
,
sizeof
(
random
));
memcpy
(
random
,
_random
,
sizeof
(
random
));
}
}
}
}
uint8_t
timeStamp
[
4
];
uint8_t
time_stamp
[
4
];
uint8_t
zero
[
4
]
=
{
0
};
uint8_t
zero
[
4
]
=
{
0
};
uint8_t
random
[
RANDOM_LEN
];
uint8_t
random
[
RANDOM_LEN
];
void
random_generate
(
char
*
bytes
,
int
size
)
{
static
char
cdata
[]
=
{
0x73
,
0x69
,
0x6d
,
0x70
,
0x6c
,
0x65
,
0x2d
,
0x72
,
void
random_generate
(
char
*
bytes
,
int
size
)
{
static
char
cdata
[]
=
{
0x73
,
0x69
,
0x6d
,
0x70
,
0x6c
,
0x65
,
0x2d
,
0x72
,
0x74
,
0x6d
,
0x70
,
0x2d
,
0x73
,
0x65
,
0x72
,
0x76
,
0x65
,
0x72
,
0x74
,
0x6d
,
0x70
,
0x2d
,
0x73
,
0x65
,
0x72
,
0x76
,
0x65
,
0x72
,
0x2d
,
0x77
,
0x69
,
0x6e
,
0x6c
,
0x69
,
0x6e
,
0x2d
,
0x77
,
0x69
,
0x2d
,
0x77
,
0x69
,
0x6e
,
0x6c
,
0x69
,
0x6e
,
0x2d
,
0x77
,
0x69
,
0x6e
,
0x74
,
0x65
,
0x72
,
0x73
,
0x65
,
0x72
,
0x76
,
0x65
,
0x72
,
0x6e
,
0x74
,
0x65
,
0x72
,
0x73
,
0x65
,
0x72
,
0x76
,
0x65
,
0x72
,
0x40
,
0x31
,
0x32
,
0x36
,
0x2e
,
0x63
,
0x6f
,
0x6d
};
0x40
,
0x31
,
0x32
,
0x36
,
0x2e
,
0x63
,
0x6f
,
0x6d
};
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
for
(
int
i
=
0
;
i
<
size
;
i
++
)
{
bytes
[
i
]
=
cdata
[
rand
()
%
(
sizeof
(
cdata
)
-
1
)];
bytes
[
i
]
=
cdata
[
rand
()
%
(
sizeof
(
cdata
)
-
1
)];
}
}
...
@@ -116,10 +116,10 @@ public:
...
@@ -116,10 +116,10 @@ public:
class
RtmpHeader
{
class
RtmpHeader
{
public
:
public
:
uint8_t
flags
;
uint8_t
flags
;
uint8_t
time
S
tamp
[
3
];
uint8_t
time
_s
tamp
[
3
];
uint8_t
body
S
ize
[
3
];
uint8_t
body
_s
ize
[
3
];
uint8_t
type
I
d
;
uint8_t
type
_i
d
;
uint8_t
stream
Id
[
4
];
/* Note, this is little-endian while others are BE */
uint8_t
stream
_index
[
4
];
/* Note, this is little-endian while others are BE */
}
PACKED
;
}
PACKED
;
#if defined(_WIN32)
#if defined(_WIN32)
...
@@ -129,21 +129,23 @@ public:
...
@@ -129,21 +129,23 @@ public:
class
RtmpPacket
:
public
Buffer
{
class
RtmpPacket
:
public
Buffer
{
public
:
public
:
typedef
std
::
shared_ptr
<
RtmpPacket
>
Ptr
;
typedef
std
::
shared_ptr
<
RtmpPacket
>
Ptr
;
uint8_t
typeId
;
uint8_t
type_id
;
uint32_t
bodySize
=
0
;
uint32_t
body_size
=
0
;
uint32_t
timeStamp
=
0
;
uint32_t
time_stamp
=
0
;
bool
hasAbsStamp
=
false
;
bool
is_abs_stamp
=
false
;
uint32_t
tsField
=
0
;
uint32_t
ts_field
=
0
;
uint32_t
streamId
;
uint32_t
stream_index
;
uint32_t
chunkId
;
uint32_t
chunk_id
;
std
::
string
strBuf
;
std
::
string
buffer
;
public
:
public
:
char
*
data
()
const
override
{
char
*
data
()
const
override
{
return
(
char
*
)
strBuf
.
data
();
return
(
char
*
)
buffer
.
data
();
}
}
uint32_t
size
()
const
override
{
uint32_t
size
()
const
override
{
return
strBuf
.
size
();
return
buffer
.
size
();
};
}
public
:
public
:
RtmpPacket
()
=
default
;
RtmpPacket
()
=
default
;
RtmpPacket
(
const
RtmpPacket
&
that
)
=
delete
;
RtmpPacket
(
const
RtmpPacket
&
that
)
=
delete
;
...
@@ -151,58 +153,64 @@ public:
...
@@ -151,58 +153,64 @@ public:
RtmpPacket
&
operator
=
(
RtmpPacket
&&
that
)
=
delete
;
RtmpPacket
&
operator
=
(
RtmpPacket
&&
that
)
=
delete
;
RtmpPacket
(
RtmpPacket
&&
that
){
RtmpPacket
(
RtmpPacket
&&
that
){
type
Id
=
that
.
typeI
d
;
type
_id
=
that
.
type_i
d
;
body
Size
=
that
.
bodyS
ize
;
body
_size
=
that
.
body_s
ize
;
time
Stamp
=
that
.
timeS
tamp
;
time
_stamp
=
that
.
time_s
tamp
;
hasAbsStamp
=
that
.
hasAbsS
tamp
;
is_abs_stamp
=
that
.
is_abs_s
tamp
;
ts
Field
=
that
.
tsF
ield
;
ts
_field
=
that
.
ts_f
ield
;
stream
Id
=
that
.
streamId
;
stream
_index
=
that
.
stream_index
;
chunk
Id
=
that
.
chunkI
d
;
chunk
_id
=
that
.
chunk_i
d
;
strBuf
=
std
::
move
(
that
.
strBuf
);
buffer
=
std
::
move
(
that
.
buffer
);
}
}
bool
isVideoKeyFrame
()
const
{
bool
isVideoKeyFrame
()
const
{
return
type
Id
==
MSG_VIDEO
&&
(
uint8_t
)
strBuf
[
0
]
>>
4
==
FLV_KEY_FRAME
&&
(
uint8_t
)
strBuf
[
1
]
==
1
;
return
type
_id
==
MSG_VIDEO
&&
(
uint8_t
)
buffer
[
0
]
>>
4
==
FLV_KEY_FRAME
&&
(
uint8_t
)
buffer
[
1
]
==
1
;
}
}
bool
isCfgFrame
()
const
{
bool
isCfgFrame
()
const
{
switch
(
type
I
d
){
switch
(
type
_i
d
){
case
MSG_VIDEO
:
return
strBuf
[
1
]
==
0
;
case
MSG_VIDEO
:
return
buffer
[
1
]
==
0
;
case
MSG_AUDIO
:
{
case
MSG_AUDIO
:
{
switch
(
getMediaType
()){
switch
(
getMediaType
()){
case
FLV_CODEC_AAC
:
return
strBuf
[
1
]
==
0
;
case
FLV_CODEC_AAC
:
return
buffer
[
1
]
==
0
;
default
:
return
false
;
default
:
return
false
;
}
}
}
}
default
:
return
false
;
default
:
return
false
;
}
}
}
}
int
getMediaType
()
const
{
int
getMediaType
()
const
{
switch
(
type
I
d
)
{
switch
(
type
_i
d
)
{
case
MSG_VIDEO
:
return
(
uint8_t
)
strBuf
[
0
]
&
0x0F
;
case
MSG_VIDEO
:
return
(
uint8_t
)
buffer
[
0
]
&
0x0F
;
case
MSG_AUDIO
:
return
(
uint8_t
)
strBuf
[
0
]
>>
4
;
case
MSG_AUDIO
:
return
(
uint8_t
)
buffer
[
0
]
>>
4
;
default
:
return
0
;
default
:
return
0
;
}
}
}
}
int
getAudioSampleRate
()
const
{
int
getAudioSampleRate
()
const
{
if
(
type
I
d
!=
MSG_AUDIO
)
{
if
(
type
_i
d
!=
MSG_AUDIO
)
{
return
0
;
return
0
;
}
}
int
flvSampleRate
=
((
uint8_t
)
strBuf
[
0
]
&
0x0C
)
>>
2
;
int
flvSampleRate
=
((
uint8_t
)
buffer
[
0
]
&
0x0C
)
>>
2
;
const
static
int
sampleRate
[]
=
{
5512
,
11025
,
22050
,
44100
};
const
static
int
sampleRate
[]
=
{
5512
,
11025
,
22050
,
44100
};
return
sampleRate
[
flvSampleRate
];
return
sampleRate
[
flvSampleRate
];
}
}
int
getAudioSampleBit
()
const
{
int
getAudioSampleBit
()
const
{
if
(
type
I
d
!=
MSG_AUDIO
)
{
if
(
type
_i
d
!=
MSG_AUDIO
)
{
return
0
;
return
0
;
}
}
int
flvSampleBit
=
((
uint8_t
)
strBuf
[
0
]
&
0x02
)
>>
1
;
int
flvSampleBit
=
((
uint8_t
)
buffer
[
0
]
&
0x02
)
>>
1
;
const
static
int
sampleBit
[]
=
{
8
,
16
};
const
static
int
sampleBit
[]
=
{
8
,
16
};
return
sampleBit
[
flvSampleBit
];
return
sampleBit
[
flvSampleBit
];
}
}
int
getAudioChannel
()
const
{
int
getAudioChannel
()
const
{
if
(
type
I
d
!=
MSG_AUDIO
)
{
if
(
type
_i
d
!=
MSG_AUDIO
)
{
return
0
;
return
0
;
}
}
int
flvStereoOrMono
=
(
uint8_t
)
strBuf
[
0
]
&
0x01
;
int
flvStereoOrMono
=
(
uint8_t
)
buffer
[
0
]
&
0x01
;
const
static
int
channel
[]
=
{
1
,
2
};
const
static
int
channel
[]
=
{
1
,
2
};
return
channel
[
flvStereoOrMono
];
return
channel
[
flvStereoOrMono
];
}
}
...
...
src/Rtmp/RtmpCodec.h
查看文件 @
fbd711a6
...
@@ -23,14 +23,14 @@ public:
...
@@ -23,14 +23,14 @@ public:
typedef
std
::
shared_ptr
<
RtmpRing
>
Ptr
;
typedef
std
::
shared_ptr
<
RtmpRing
>
Ptr
;
typedef
RingBuffer
<
RtmpPacket
::
Ptr
>
RingType
;
typedef
RingBuffer
<
RtmpPacket
::
Ptr
>
RingType
;
RtmpRing
(){}
RtmpRing
()
{}
virtual
~
RtmpRing
(){}
virtual
~
RtmpRing
()
{}
/**
/**
* 获取rtmp环形缓存
* 获取rtmp环形缓存
* @return
* @return
*/
*/
virtual
RingType
::
Ptr
getRtmpRing
()
const
{
virtual
RingType
::
Ptr
getRtmpRing
()
const
{
return
_rtmpRing
;
return
_rtmpRing
;
}
}
...
@@ -38,7 +38,7 @@ public:
...
@@ -38,7 +38,7 @@ public:
* 设置rtmp环形缓存
* 设置rtmp环形缓存
* @param ring
* @param ring
*/
*/
virtual
void
setRtmpRing
(
const
RingType
::
Ptr
&
ring
){
virtual
void
setRtmpRing
(
const
RingType
::
Ptr
&
ring
)
{
_rtmpRing
=
ring
;
_rtmpRing
=
ring
;
}
}
...
@@ -48,17 +48,17 @@ public:
...
@@ -48,17 +48,17 @@ public:
* @param key_pos 是否为关键帧
* @param key_pos 是否为关键帧
* @return 是否为关键帧
* @return 是否为关键帧
*/
*/
virtual
bool
inputRtmp
(
const
RtmpPacket
::
Ptr
&
rtmp
,
bool
key_pos
){
virtual
bool
inputRtmp
(
const
RtmpPacket
::
Ptr
&
rtmp
,
bool
key_pos
)
{
if
(
_rtmpRing
)
{
if
(
_rtmpRing
)
{
_rtmpRing
->
write
(
rtmp
,
key_pos
);
_rtmpRing
->
write
(
rtmp
,
key_pos
);
}
}
return
key_pos
;
return
key_pos
;
}
}
protected
:
protected
:
RingType
::
Ptr
_rtmpRing
;
RingType
::
Ptr
_rtmpRing
;
};
};
class
RtmpCodec
:
public
RtmpRing
,
public
FrameDispatcher
,
public
CodecInfo
{
class
RtmpCodec
:
public
RtmpRing
,
public
FrameDispatcher
,
public
CodecInfo
{
public
:
public
:
typedef
std
::
shared_ptr
<
RtmpCodec
>
Ptr
;
typedef
std
::
shared_ptr
<
RtmpCodec
>
Ptr
;
...
@@ -69,5 +69,4 @@ public:
...
@@ -69,5 +69,4 @@ public:
}
//namespace mediakit
}
//namespace mediakit
#endif //ZLMEDIAKIT_RTMPCODEC_H
#endif //ZLMEDIAKIT_RTMPCODEC_H
src/Rtmp/RtmpDemuxer.cpp
查看文件 @
fbd711a6
...
@@ -66,27 +66,27 @@ bool RtmpDemuxer::loadMetaData(const AMFValue &val){
...
@@ -66,27 +66,27 @@ bool RtmpDemuxer::loadMetaData(const AMFValue &val){
}
}
bool
RtmpDemuxer
::
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
bool
RtmpDemuxer
::
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
switch
(
pkt
->
type
I
d
)
{
switch
(
pkt
->
type
_i
d
)
{
case
MSG_VIDEO
:
{
case
MSG_VIDEO
:
{
if
(
!
_try
edGetVideoT
rack
){
if
(
!
_try
_get_video_t
rack
){
_try
edGetVideoT
rack
=
true
;
_try
_get_video_t
rack
=
true
;
auto
codec
=
AMFValue
(
pkt
->
getMediaType
());
auto
codec
=
AMFValue
(
pkt
->
getMediaType
());
makeVideoTrack
(
codec
);
makeVideoTrack
(
codec
);
}
}
if
(
_video
RtmpD
ecoder
){
if
(
_video
_rtmp_d
ecoder
){
return
_video
RtmpD
ecoder
->
inputRtmp
(
pkt
,
true
);
return
_video
_rtmp_d
ecoder
->
inputRtmp
(
pkt
,
true
);
}
}
return
false
;
return
false
;
}
}
case
MSG_AUDIO
:
{
case
MSG_AUDIO
:
{
if
(
!
_try
edGetAudioT
rack
)
{
if
(
!
_try
_get_audio_t
rack
)
{
_try
edGetAudioT
rack
=
true
;
_try
_get_audio_t
rack
=
true
;
auto
codec
=
AMFValue
(
pkt
->
getMediaType
());
auto
codec
=
AMFValue
(
pkt
->
getMediaType
());
makeAudioTrack
(
codec
,
pkt
->
getAudioSampleRate
(),
pkt
->
getAudioChannel
(),
pkt
->
getAudioSampleBit
());
makeAudioTrack
(
codec
,
pkt
->
getAudioSampleRate
(),
pkt
->
getAudioChannel
(),
pkt
->
getAudioSampleBit
());
}
}
if
(
_audio
RtmpD
ecoder
){
if
(
_audio
_rtmp_d
ecoder
){
_audio
RtmpD
ecoder
->
inputRtmp
(
pkt
,
false
);
_audio
_rtmp_d
ecoder
->
inputRtmp
(
pkt
,
false
);
return
false
;
return
false
;
}
}
return
false
;
return
false
;
...
@@ -101,12 +101,12 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
...
@@ -101,12 +101,12 @@ void RtmpDemuxer::makeVideoTrack(const AMFValue &videoCodec) {
_videoTrack
=
dynamic_pointer_cast
<
VideoTrack
>
(
Factory
::
getVideoTrackByAmf
(
videoCodec
));
_videoTrack
=
dynamic_pointer_cast
<
VideoTrack
>
(
Factory
::
getVideoTrackByAmf
(
videoCodec
));
if
(
_videoTrack
)
{
if
(
_videoTrack
)
{
//生成rtmpCodec对象以便解码rtmp
//生成rtmpCodec对象以便解码rtmp
_video
RtmpD
ecoder
=
Factory
::
getRtmpCodecByTrack
(
_videoTrack
,
false
);
_video
_rtmp_d
ecoder
=
Factory
::
getRtmpCodecByTrack
(
_videoTrack
,
false
);
if
(
_video
RtmpD
ecoder
)
{
if
(
_video
_rtmp_d
ecoder
)
{
//设置rtmp解码器代理,生成的frame写入该Track
//设置rtmp解码器代理,生成的frame写入该Track
_video
RtmpD
ecoder
->
addDelegate
(
_videoTrack
);
_video
_rtmp_d
ecoder
->
addDelegate
(
_videoTrack
);
onAddTrack
(
_videoTrack
);
onAddTrack
(
_videoTrack
);
_try
edGetVideoT
rack
=
true
;
_try
_get_video_t
rack
=
true
;
}
else
{
}
else
{
//找不到相应的rtmp解码器,该track无效
//找不到相应的rtmp解码器,该track无效
_videoTrack
.
reset
();
_videoTrack
.
reset
();
...
@@ -119,12 +119,12 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int
...
@@ -119,12 +119,12 @@ void RtmpDemuxer::makeAudioTrack(const AMFValue &audioCodec,int sample_rate, int
_audioTrack
=
dynamic_pointer_cast
<
AudioTrack
>
(
Factory
::
getAudioTrackByAmf
(
audioCodec
,
sample_rate
,
channels
,
sample_bit
));
_audioTrack
=
dynamic_pointer_cast
<
AudioTrack
>
(
Factory
::
getAudioTrackByAmf
(
audioCodec
,
sample_rate
,
channels
,
sample_bit
));
if
(
_audioTrack
)
{
if
(
_audioTrack
)
{
//生成rtmpCodec对象以便解码rtmp
//生成rtmpCodec对象以便解码rtmp
_audio
RtmpD
ecoder
=
Factory
::
getRtmpCodecByTrack
(
_audioTrack
,
false
);
_audio
_rtmp_d
ecoder
=
Factory
::
getRtmpCodecByTrack
(
_audioTrack
,
false
);
if
(
_audio
RtmpD
ecoder
)
{
if
(
_audio
_rtmp_d
ecoder
)
{
//设置rtmp解码器代理,生成的frame写入该Track
//设置rtmp解码器代理,生成的frame写入该Track
_audio
RtmpD
ecoder
->
addDelegate
(
_audioTrack
);
_audio
_rtmp_d
ecoder
->
addDelegate
(
_audioTrack
);
onAddTrack
(
_audioTrack
);
onAddTrack
(
_audioTrack
);
_try
edGetAudioT
rack
=
true
;
_try
_get_audio_t
rack
=
true
;
}
else
{
}
else
{
//找不到相应的rtmp解码器,该track无效
//找不到相应的rtmp解码器,该track无效
_audioTrack
.
reset
();
_audioTrack
.
reset
();
...
...
src/Rtmp/RtmpDemuxer.h
查看文件 @
fbd711a6
...
@@ -28,7 +28,7 @@ public:
...
@@ -28,7 +28,7 @@ public:
typedef
std
::
shared_ptr
<
RtmpDemuxer
>
Ptr
;
typedef
std
::
shared_ptr
<
RtmpDemuxer
>
Ptr
;
RtmpDemuxer
()
=
default
;
RtmpDemuxer
()
=
default
;
virtual
~
RtmpDemuxer
()
=
default
;
~
RtmpDemuxer
()
override
=
default
;
bool
loadMetaData
(
const
AMFValue
&
metadata
);
bool
loadMetaData
(
const
AMFValue
&
metadata
);
...
@@ -38,14 +38,16 @@ public:
...
@@ -38,14 +38,16 @@ public:
* @return true 代表是i帧
* @return true 代表是i帧
*/
*/
bool
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
);
bool
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
);
private
:
private
:
void
makeVideoTrack
(
const
AMFValue
&
val
);
void
makeVideoTrack
(
const
AMFValue
&
val
);
void
makeAudioTrack
(
const
AMFValue
&
val
,
int
sample_rate
,
int
channels
,
int
sample_bit
);
void
makeAudioTrack
(
const
AMFValue
&
val
,
int
sample_rate
,
int
channels
,
int
sample_bit
);
private
:
private
:
bool
_try
edGetVideoT
rack
=
false
;
bool
_try
_get_video_t
rack
=
false
;
bool
_try
edGetAudioT
rack
=
false
;
bool
_try
_get_audio_t
rack
=
false
;
RtmpCodec
::
Ptr
_audio
RtmpD
ecoder
;
RtmpCodec
::
Ptr
_audio
_rtmp_d
ecoder
;
RtmpCodec
::
Ptr
_video
RtmpD
ecoder
;
RtmpCodec
::
Ptr
_video
_rtmp_d
ecoder
;
};
};
}
/* namespace mediakit */
}
/* namespace mediakit */
...
...
src/Rtmp/RtmpMediaSource.h
查看文件 @
fbd711a6
...
@@ -122,17 +122,17 @@ public:
...
@@ -122,17 +122,17 @@ public:
*/
*/
void
onWrite
(
const
RtmpPacket
::
Ptr
&
pkt
,
bool
key
=
true
)
override
{
void
onWrite
(
const
RtmpPacket
::
Ptr
&
pkt
,
bool
key
=
true
)
override
{
lock_guard
<
recursive_mutex
>
lock
(
_mtx
);
lock_guard
<
recursive_mutex
>
lock
(
_mtx
);
if
(
pkt
->
type
I
d
==
MSG_VIDEO
){
if
(
pkt
->
type
_i
d
==
MSG_VIDEO
){
//有视频,那么启用GOP缓存
//有视频,那么启用GOP缓存
_have_video
=
true
;
_have_video
=
true
;
}
}
if
(
pkt
->
isCfgFrame
())
{
if
(
pkt
->
isCfgFrame
())
{
_config_frame_map
[
pkt
->
type
I
d
]
=
pkt
;
_config_frame_map
[
pkt
->
type
_i
d
]
=
pkt
;
return
;
return
;
}
}
//保存当前时间戳
//保存当前时间戳
_track_stamps_map
[
pkt
->
type
Id
]
=
pkt
->
timeS
tamp
;
_track_stamps_map
[
pkt
->
type
_id
]
=
pkt
->
time_s
tamp
;
if
(
!
_ring
)
{
if
(
!
_ring
)
{
weak_ptr
<
RtmpMediaSource
>
weakSelf
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
shared_from_this
());
weak_ptr
<
RtmpMediaSource
>
weakSelf
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
shared_from_this
());
...
@@ -154,7 +154,7 @@ public:
...
@@ -154,7 +154,7 @@ public:
regist
();
regist
();
}
}
}
}
PacketCache
<
RtmpPacket
>::
inputPacket
(
pkt
->
type
I
d
==
MSG_VIDEO
,
pkt
,
key
);
PacketCache
<
RtmpPacket
>::
inputPacket
(
pkt
->
type
_i
d
==
MSG_VIDEO
,
pkt
,
key
);
}
}
/**
/**
...
...
src/Rtmp/RtmpMediaSourceImp.h
查看文件 @
fbd711a6
...
@@ -161,11 +161,12 @@ public:
...
@@ -161,11 +161,12 @@ public:
}
}
private
:
private
:
RtmpDemuxer
::
Ptr
_demuxer
;
MultiMediaSourceMuxer
::
Ptr
_muxer
;
AMFValue
_metadata
;
bool
_all_track_ready
=
false
;
bool
_all_track_ready
=
false
;
bool
_recreate_metadata
=
false
;
bool
_recreate_metadata
=
false
;
AMFValue
_metadata
;
RtmpDemuxer
::
Ptr
_demuxer
;
MultiMediaSourceMuxer
::
Ptr
_muxer
;
};
};
}
/* namespace mediakit */
}
/* namespace mediakit */
...
...
src/Rtmp/RtmpMediaSourceMuxer.h
查看文件 @
fbd711a6
...
@@ -24,34 +24,35 @@ public:
...
@@ -24,34 +24,35 @@ public:
const
string
&
strApp
,
const
string
&
strApp
,
const
string
&
strId
,
const
string
&
strId
,
const
TitleMeta
::
Ptr
&
title
=
nullptr
)
:
RtmpMuxer
(
title
){
const
TitleMeta
::
Ptr
&
title
=
nullptr
)
:
RtmpMuxer
(
title
){
_media
Souce
=
std
::
make_shared
<
RtmpMediaSource
>
(
vhost
,
strApp
,
strId
);
_media
_src
=
std
::
make_shared
<
RtmpMediaSource
>
(
vhost
,
strApp
,
strId
);
getRtmpRing
()
->
setDelegate
(
_media
Souce
);
getRtmpRing
()
->
setDelegate
(
_media
_src
);
}
}
virtual
~
RtmpMediaSourceMuxer
(){}
virtual
~
RtmpMediaSourceMuxer
(){}
void
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
){
void
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
){
_media
Souce
->
setListener
(
listener
);
_media
_src
->
setListener
(
listener
);
}
}
void
setTimeStamp
(
uint32_t
stamp
){
void
setTimeStamp
(
uint32_t
stamp
){
_media
Souce
->
setTimeStamp
(
stamp
);
_media
_src
->
setTimeStamp
(
stamp
);
}
}
int
readerCount
()
const
{
int
readerCount
()
const
{
return
_media
Souce
->
readerCount
();
return
_media
_src
->
readerCount
();
}
}
void
onAllTrackReady
(){
void
onAllTrackReady
(){
makeConfigPacket
();
makeConfigPacket
();
_media
Souce
->
setMetaData
(
getMetadata
());
_media
_src
->
setMetaData
(
getMetadata
());
}
}
// 设置TrackSource
// 设置TrackSource
void
setTrackSource
(
const
std
::
weak_ptr
<
TrackSource
>
&
track_src
){
void
setTrackSource
(
const
std
::
weak_ptr
<
TrackSource
>
&
track_src
){
_media
Souce
->
setTrackSource
(
track_src
);
_media
_src
->
setTrackSource
(
track_src
);
}
}
private
:
private
:
RtmpMediaSource
::
Ptr
_media
Souce
;
RtmpMediaSource
::
Ptr
_media
_src
;
};
};
...
...
src/Rtmp/RtmpMuxer.cpp
查看文件 @
fbd711a6
...
@@ -19,7 +19,7 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) {
...
@@ -19,7 +19,7 @@ RtmpMuxer::RtmpMuxer(const TitleMeta::Ptr &title) {
}
else
{
}
else
{
_metadata
=
title
->
getMetadata
();
_metadata
=
title
->
getMetadata
();
}
}
_rtmp
R
ing
=
std
::
make_shared
<
RtmpRing
::
RingType
>
();
_rtmp
_r
ing
=
std
::
make_shared
<
RtmpRing
::
RingType
>
();
}
}
void
RtmpMuxer
::
addTrack
(
const
Track
::
Ptr
&
track
)
{
void
RtmpMuxer
::
addTrack
(
const
Track
::
Ptr
&
track
)
{
...
@@ -31,7 +31,7 @@ void RtmpMuxer::addTrack(const Track::Ptr &track) {
...
@@ -31,7 +31,7 @@ void RtmpMuxer::addTrack(const Track::Ptr &track) {
}
}
//设置rtmp输出环形缓存
//设置rtmp输出环形缓存
encoder
->
setRtmpRing
(
_rtmp
R
ing
);
encoder
->
setRtmpRing
(
_rtmp
_r
ing
);
//添加metadata
//添加metadata
Metadata
::
addTrack
(
_metadata
,
track
);
Metadata
::
addTrack
(
_metadata
,
track
);
...
@@ -57,7 +57,7 @@ const AMFValue &RtmpMuxer::getMetadata() const {
...
@@ -57,7 +57,7 @@ const AMFValue &RtmpMuxer::getMetadata() const {
}
}
RtmpRing
::
RingType
::
Ptr
RtmpMuxer
::
getRtmpRing
()
const
{
RtmpRing
::
RingType
::
Ptr
RtmpMuxer
::
getRtmpRing
()
const
{
return
_rtmp
R
ing
;
return
_rtmp
_r
ing
;
}
}
void
RtmpMuxer
::
resetTracks
()
{
void
RtmpMuxer
::
resetTracks
()
{
...
...
src/Rtmp/RtmpMuxer.h
查看文件 @
fbd711a6
...
@@ -61,7 +61,7 @@ public:
...
@@ -61,7 +61,7 @@ public:
*/
*/
void
makeConfigPacket
();
void
makeConfigPacket
();
private
:
private
:
RtmpRing
::
RingType
::
Ptr
_rtmp
R
ing
;
RtmpRing
::
RingType
::
Ptr
_rtmp
_r
ing
;
AMFValue
_metadata
;
AMFValue
_metadata
;
RtmpCodec
::
Ptr
_encoder
[
TrackMax
];
RtmpCodec
::
Ptr
_encoder
[
TrackMax
];
};
};
...
...
src/Rtmp/RtmpPlayer.cpp
查看文件 @
fbd711a6
...
@@ -18,8 +18,7 @@ using namespace mediakit::Client;
...
@@ -18,8 +18,7 @@ using namespace mediakit::Client;
namespace
mediakit
{
namespace
mediakit
{
RtmpPlayer
::
RtmpPlayer
(
const
EventPoller
::
Ptr
&
poller
)
:
TcpClient
(
poller
)
{
RtmpPlayer
::
RtmpPlayer
(
const
EventPoller
::
Ptr
&
poller
)
:
TcpClient
(
poller
)
{}
}
RtmpPlayer
::~
RtmpPlayer
()
{
RtmpPlayer
::~
RtmpPlayer
()
{
DebugL
<<
endl
;
DebugL
<<
endl
;
...
@@ -29,97 +28,82 @@ void RtmpPlayer::teardown() {
...
@@ -29,97 +28,82 @@ void RtmpPlayer::teardown() {
if
(
alive
())
{
if
(
alive
())
{
shutdown
(
SockException
(
Err_shutdown
,
"teardown"
));
shutdown
(
SockException
(
Err_shutdown
,
"teardown"
));
}
}
_
strA
pp
.
clear
();
_
a
pp
.
clear
();
_str
Stream
.
clear
();
_str
eam_id
.
clear
();
_
strTcU
rl
.
clear
();
_
tc_u
rl
.
clear
();
_
pBeatT
imer
.
reset
();
_
beat_t
imer
.
reset
();
_p
PlayT
imer
.
reset
();
_p
lay_t
imer
.
reset
();
_
pMediaT
imer
.
reset
();
_
rtmp_recv_t
imer
.
reset
();
_
iSeekTo
=
0
;
_
seek_ms
=
0
;
RtmpProtocol
::
reset
();
RtmpProtocol
::
reset
();
CLEAR_ARR
(
_
aiFistS
tamp
);
CLEAR_ARR
(
_
fist_s
tamp
);
CLEAR_ARR
(
_
aiNowS
tamp
);
CLEAR_ARR
(
_
now_s
tamp
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnResultCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_result
);
_map
OnResultCB
.
clear
();
_map
_on_result
.
clear
();
lock_guard
<
recursive_mutex
>
lck2
(
_mtx
OnStatusCB
);
lock_guard
<
recursive_mutex
>
lck2
(
_mtx
_on_status
);
_d
qOnStatusCB
.
clear
();
_d
eque_on_status
.
clear
();
}
}
void
RtmpPlayer
::
play
(
const
string
&
strUrl
)
{
void
RtmpPlayer
::
play
(
const
string
&
strUrl
)
{
teardown
();
teardown
();
string
strHost
=
FindField
(
strUrl
.
data
(),
"://"
,
"/"
);
string
host_url
=
FindField
(
strUrl
.
data
(),
"://"
,
"/"
);
_
strApp
=
FindField
(
strUrl
.
data
(),
(
strHost
+
"/"
).
data
(),
"/"
);
_
app
=
FindField
(
strUrl
.
data
(),
(
host_url
+
"/"
).
data
(),
"/"
);
_str
Stream
=
FindField
(
strUrl
.
data
(),
(
strHost
+
"/"
+
_strA
pp
+
"/"
).
data
(),
NULL
);
_str
eam_id
=
FindField
(
strUrl
.
data
(),
(
host_url
+
"/"
+
_a
pp
+
"/"
).
data
(),
NULL
);
_
strTcUrl
=
string
(
"rtmp://"
)
+
strHost
+
"/"
+
_strA
pp
;
_
tc_url
=
string
(
"rtmp://"
)
+
host_url
+
"/"
+
_a
pp
;
if
(
!
_
strApp
.
size
()
||
!
_strStream
.
size
())
{
if
(
!
_
app
.
size
()
||
!
_stream_id
.
size
())
{
onPlayResult_l
(
SockException
(
Err_other
,
"rtmp url非法"
),
false
);
onPlayResult_l
(
SockException
(
Err_other
,
"rtmp url非法"
),
false
);
return
;
return
;
}
}
DebugL
<<
strHost
<<
" "
<<
_strApp
<<
" "
<<
_strStream
;
DebugL
<<
host_url
<<
" "
<<
_app
<<
" "
<<
_stream_id
;
auto
iPort
=
atoi
(
FindField
(
strHost
.
data
(),
":"
,
NULL
).
data
());
auto
iPort
=
atoi
(
FindField
(
host_url
.
data
(),
":"
,
NULL
).
data
());
if
(
iPort
<=
0
)
{
if
(
iPort
<=
0
)
{
//rtmp 默认端口1935
//rtmp 默认端口1935
iPort
=
1935
;
iPort
=
1935
;
}
else
{
}
else
{
//服务器域名
//服务器域名
strHost
=
FindField
(
strHost
.
data
(),
NULL
,
":"
);
host_url
=
FindField
(
host_url
.
data
(),
NULL
,
":"
);
}
}
if
(
!
(
*
this
)[
kNetAdapter
].
empty
())
{
if
(
!
(
*
this
)[
kNetAdapter
].
empty
())
{
setNetAdapter
((
*
this
)[
kNetAdapter
]);
setNetAdapter
((
*
this
)[
kNetAdapter
]);
}
}
weak_ptr
<
RtmpPlayer
>
weak
Self
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
weak_ptr
<
RtmpPlayer
>
weak
_self
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
float
play
TimeOutS
ec
=
(
*
this
)[
kTimeoutMS
].
as
<
int
>
()
/
1000.0
;
float
play
_timeout_s
ec
=
(
*
this
)[
kTimeoutMS
].
as
<
int
>
()
/
1000.0
;
_p
PlayTimer
.
reset
(
new
Timer
(
playTimeOutSec
,
[
weakS
elf
]()
{
_p
lay_timer
.
reset
(
new
Timer
(
play_timeout_sec
,
[
weak_s
elf
]()
{
auto
strong
Self
=
weakS
elf
.
lock
();
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
!
strongS
elf
)
{
if
(
!
strong_s
elf
)
{
return
false
;
return
false
;
}
}
strong
Self
->
onPlayResult_l
(
SockException
(
Err_timeout
,
"play rtmp timeout"
),
false
);
strong
_self
->
onPlayResult_l
(
SockException
(
Err_timeout
,
"play rtmp timeout"
),
false
);
return
false
;
return
false
;
},
getPoller
()));
},
getPoller
()));
_metadata_got
=
false
;
_metadata_got
=
false
;
startConnect
(
strHost
,
iPort
,
playTimeOutS
ec
);
startConnect
(
host_url
,
iPort
,
play_timeout_s
ec
);
}
}
void
RtmpPlayer
::
onErr
(
const
SockException
&
ex
){
void
RtmpPlayer
::
onErr
(
const
SockException
&
ex
){
//定时器_pPlayTimer为空后表明握手结束了
//定时器_pPlayTimer为空后表明握手结束了
onPlayResult_l
(
ex
,
!
_p
PlayT
imer
);
onPlayResult_l
(
ex
,
!
_p
lay_t
imer
);
}
}
void
RtmpPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshakeCompleted
)
{
void
RtmpPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshakeCompleted
)
{
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
if
(
ex
.
getErrCode
()
==
Err_shutdown
)
{
//主动shutdown的,不触发回调
if
(
!
ex
){
return
;
//播放成功,恢复rtmp接收超时定时器
_mediaTicker
.
resetTime
();
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
int
timeoutMS
=
(
*
this
)[
kMediaTimeoutMS
].
as
<
int
>
();
//创建rtmp数据接收超时检测定时器
_pMediaTimer
.
reset
(
new
Timer
(
timeoutMS
/
2000.0
,
[
weakSelf
,
timeoutMS
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
if
(
strongSelf
->
_mediaTicker
.
elapsedTime
()
>
timeoutMS
)
{
//接收rtmp媒体数据超时
strongSelf
->
onPlayResult_l
(
SockException
(
Err_timeout
,
"receive rtmp timeout"
),
true
);
return
false
;
}
return
true
;
},
getPoller
()));
}
}
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
if
(
!
handshakeCompleted
)
{
if
(
!
handshakeCompleted
)
{
//开始播放阶段
//开始播放阶段
_pPlayTimer
.
reset
();
_play_timer
.
reset
();
onPlayResult
(
ex
);
//是否为性能测试模式
//是否为性能测试模式
_benchmark_mode
=
(
*
this
)[
Client
::
kBenchmarkMode
].
as
<
int
>
();
_benchmark_mode
=
(
*
this
)[
Client
::
kBenchmarkMode
].
as
<
int
>
();
onPlayResult
(
ex
);
}
else
if
(
ex
)
{
}
else
if
(
ex
)
{
//播放成功后异常断开回调
//播放成功后异常断开回调
onShutdown
(
ex
);
onShutdown
(
ex
);
...
@@ -128,36 +112,58 @@ void RtmpPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete
...
@@ -128,36 +112,58 @@ void RtmpPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete
onResume
();
onResume
();
}
}
if
(
ex
){
if
(
!
ex
)
{
//播放成功,恢复rtmp接收超时定时器
_rtmp_recv_ticker
.
resetTime
();
int
timeout_ms
=
(
*
this
)[
kMediaTimeoutMS
].
as
<
int
>
();
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
auto
lam
=
[
weakSelf
,
timeout_ms
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
if
(
strongSelf
->
_rtmp_recv_ticker
.
elapsedTime
()
>
timeout_ms
)
{
//接收rtmp媒体数据超时
SockException
ex
(
Err_timeout
,
"receive rtmp timeout"
);
strongSelf
->
onPlayResult_l
(
ex
,
true
);
return
false
;
}
return
true
;
};
//创建rtmp数据接收超时检测定时器
_rtmp_recv_timer
=
std
::
make_shared
<
Timer
>
(
timeout_ms
/
2000.0
,
lam
,
getPoller
());
}
else
{
teardown
();
teardown
();
}
}
}
}
void
RtmpPlayer
::
onConnect
(
const
SockException
&
err
){
void
RtmpPlayer
::
onConnect
(
const
SockException
&
err
){
if
(
err
.
getErrCode
()
!=
Err_success
)
{
if
(
err
.
getErrCode
()
!=
Err_success
)
{
onPlayResult_l
(
err
,
false
);
onPlayResult_l
(
err
,
false
);
return
;
return
;
}
}
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
startClientSession
([
weakSelf
](){
startClientSession
([
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
if
(
!
strongSelf
)
{
return
;
return
;
}
}
strongSelf
->
send_connect
();
strongSelf
->
send_connect
();
});
});
}
}
void
RtmpPlayer
::
onRecv
(
const
Buffer
::
Ptr
&
pBuf
){
void
RtmpPlayer
::
onRecv
(
const
Buffer
::
Ptr
&
pBuf
){
try
{
try
{
if
(
_benchmark_mode
&&
!
_pPlayTimer
)
{
if
(
_benchmark_mode
&&
!
_play_timer
)
{
//在性能测试模式下,如果rtmp握手完毕后,不再解析rtmp包
//在性能测试模式下,如果rtmp握手完毕后,不再解析rtmp包
_
mediaT
icker
.
resetTime
();
_
rtmp_recv_t
icker
.
resetTime
();
return
;
return
;
}
}
onParseRtmp
(
pBuf
->
data
(),
pBuf
->
size
());
onParseRtmp
(
pBuf
->
data
(),
pBuf
->
size
());
}
catch
(
exception
&
e
)
{
}
catch
(
exception
&
e
)
{
SockException
ex
(
Err_other
,
e
.
what
());
SockException
ex
(
Err_other
,
e
.
what
());
//定时器_pPlayTimer为空后表明握手结束了
//定时器_pPlayTimer为空后表明握手结束了
onPlayResult_l
(
ex
,
!
_p
PlayT
imer
);
onPlayResult_l
(
ex
,
!
_p
lay_t
imer
);
}
}
}
}
...
@@ -167,8 +173,8 @@ void RtmpPlayer::pause(bool bPause) {
...
@@ -167,8 +173,8 @@ void RtmpPlayer::pause(bool bPause) {
inline
void
RtmpPlayer
::
send_connect
()
{
inline
void
RtmpPlayer
::
send_connect
()
{
AMFValue
obj
(
AMF_OBJECT
);
AMFValue
obj
(
AMF_OBJECT
);
obj
.
set
(
"app"
,
_
strA
pp
);
obj
.
set
(
"app"
,
_
a
pp
);
obj
.
set
(
"tcUrl"
,
_
strTcU
rl
);
obj
.
set
(
"tcUrl"
,
_
tc_u
rl
);
//未使用代理
//未使用代理
obj
.
set
(
"fpad"
,
false
);
obj
.
set
(
"fpad"
,
false
);
//参考librtmp,什么作用?
//参考librtmp,什么作用?
...
@@ -176,18 +182,18 @@ inline void RtmpPlayer::send_connect() {
...
@@ -176,18 +182,18 @@ inline void RtmpPlayer::send_connect() {
//SUPPORT_VID_CLIENT_SEEK 支持seek
//SUPPORT_VID_CLIENT_SEEK 支持seek
obj
.
set
(
"videoFunction"
,
1
);
obj
.
set
(
"videoFunction"
,
1
);
//只支持aac
//只支持aac
obj
.
set
(
"audioCodecs"
,
(
double
)(
0x0400
));
obj
.
set
(
"audioCodecs"
,
(
double
)
(
0x0400
));
//只支持H264
//只支持H264
obj
.
set
(
"videoCodecs"
,
(
double
)(
0x0080
));
obj
.
set
(
"videoCodecs"
,
(
double
)
(
0x0080
));
sendInvoke
(
"connect"
,
obj
);
sendInvoke
(
"connect"
,
obj
);
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
addOnResultCB
([
this
](
AMFDecoder
&
dec
)
{
//TraceL << "connect result";
//TraceL << "connect result";
dec
.
load
<
AMFValue
>
();
dec
.
load
<
AMFValue
>
();
auto
val
=
dec
.
load
<
AMFValue
>
();
auto
val
=
dec
.
load
<
AMFValue
>
();
auto
level
=
val
[
"level"
].
as_string
();
auto
level
=
val
[
"level"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
!=
"status"
)
{
if
(
level
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"connect 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
throw
std
::
runtime_error
(
StrPrinter
<<
"connect 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
}
}
send_createStream
();
send_createStream
();
});
});
...
@@ -196,24 +202,24 @@ inline void RtmpPlayer::send_connect() {
...
@@ -196,24 +202,24 @@ inline void RtmpPlayer::send_connect() {
inline
void
RtmpPlayer
::
send_createStream
()
{
inline
void
RtmpPlayer
::
send_createStream
()
{
AMFValue
obj
(
AMF_NULL
);
AMFValue
obj
(
AMF_NULL
);
sendInvoke
(
"createStream"
,
obj
);
sendInvoke
(
"createStream"
,
obj
);
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
addOnResultCB
([
this
](
AMFDecoder
&
dec
)
{
//TraceL << "createStream result";
//TraceL << "createStream result";
dec
.
load
<
AMFValue
>
();
dec
.
load
<
AMFValue
>
();
_
ui32StreamId
=
dec
.
load
<
int
>
();
_
stream_index
=
dec
.
load
<
int
>
();
send_play
();
send_play
();
});
});
}
}
inline
void
RtmpPlayer
::
send_play
()
{
inline
void
RtmpPlayer
::
send_play
()
{
AMFEncoder
enc
;
AMFEncoder
enc
;
enc
<<
"play"
<<
++
_
iReqID
<<
nullptr
<<
_strStream
<<
(
double
)
_ui32StreamId
;
enc
<<
"play"
<<
++
_
send_req_id
<<
nullptr
<<
_stream_id
<<
(
double
)
_stream_index
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
sendRequest
(
MSG_CMD
,
enc
.
data
());
auto
fun
=
[
this
](
AMFValue
&
val
){
auto
fun
=
[
this
](
AMFValue
&
val
)
{
//TraceL << "play onStatus";
//TraceL << "play onStatus";
auto
level
=
val
[
"level"
].
as_string
();
auto
level
=
val
[
"level"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
!=
"status"
)
{
if
(
level
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"play 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
throw
std
::
runtime_error
(
StrPrinter
<<
"play 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
}
}
};
};
addOnStatusCB
(
fun
);
addOnStatusCB
(
fun
);
...
@@ -222,76 +228,77 @@ inline void RtmpPlayer::send_play() {
...
@@ -222,76 +228,77 @@ inline void RtmpPlayer::send_play() {
inline
void
RtmpPlayer
::
send_pause
(
bool
bPause
)
{
inline
void
RtmpPlayer
::
send_pause
(
bool
bPause
)
{
AMFEncoder
enc
;
AMFEncoder
enc
;
enc
<<
"pause"
<<
++
_
iReqID
<<
nullptr
<<
bPause
;
enc
<<
"pause"
<<
++
_
send_req_id
<<
nullptr
<<
bPause
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
sendRequest
(
MSG_CMD
,
enc
.
data
());
auto
fun
=
[
this
,
bPause
](
AMFValue
&
val
)
{
auto
fun
=
[
this
,
bPause
](
AMFValue
&
val
)
{
//TraceL << "pause onStatus";
//TraceL << "pause onStatus";
auto
level
=
val
[
"level"
].
as_string
();
auto
level
=
val
[
"level"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
!=
"status"
)
{
if
(
level
!=
"status"
)
{
if
(
!
bPause
)
{
if
(
!
bPause
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"pause 恢复播放失败:"
<<
level
<<
" "
<<
code
<<
endl
);
throw
std
::
runtime_error
(
StrPrinter
<<
"pause 恢复播放失败:"
<<
level
<<
" "
<<
code
<<
endl
);
}
}
}
else
{
}
else
{
_
bP
aused
=
bPause
;
_
p
aused
=
bPause
;
if
(
!
bPause
)
{
if
(
!
bPause
)
{
onPlayResult_l
(
SockException
(
Err_success
,
"resum rtmp success"
),
true
);
onPlayResult_l
(
SockException
(
Err_success
,
"resum rtmp success"
),
true
);
}
else
{
}
else
{
//暂停播放
//暂停播放
_
pMediaT
imer
.
reset
();
_
rtmp_recv_t
imer
.
reset
();
}
}
}
}
};
};
addOnStatusCB
(
fun
);
addOnStatusCB
(
fun
);
_
pBeatT
imer
.
reset
();
_
beat_t
imer
.
reset
();
if
(
bPause
)
{
if
(
bPause
)
{
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
_
pBeatTimer
.
reset
(
new
Timer
((
*
this
)[
kBeatIntervalMS
].
as
<
int
>
()
/
1000.0
,[
weakSelf
]()
{
_
beat_timer
.
reset
(
new
Timer
((
*
this
)[
kBeatIntervalMS
].
as
<
int
>
()
/
1000.0
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
){
if
(
!
strongSelf
)
{
return
false
;
return
false
;
}
}
uint32_t
timeStamp
=
::
time
(
NULL
);
uint32_t
timeStamp
=
::
time
(
NULL
);
strongSelf
->
sendUserControl
(
CONTROL_PING_REQUEST
,
timeStamp
);
strongSelf
->
sendUserControl
(
CONTROL_PING_REQUEST
,
timeStamp
);
return
true
;
return
true
;
},
getPoller
()));
},
getPoller
()));
}
}
}
}
void
RtmpPlayer
::
onCmd_result
(
AMFDecoder
&
dec
){
void
RtmpPlayer
::
onCmd_result
(
AMFDecoder
&
dec
){
auto
iReqI
d
=
dec
.
load
<
int
>
();
auto
req_i
d
=
dec
.
load
<
int
>
();
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnResultCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_result
);
auto
it
=
_map
OnResultCB
.
find
(
iReqI
d
);
auto
it
=
_map
_on_result
.
find
(
req_i
d
);
if
(
it
!=
_mapOnResultCB
.
end
())
{
if
(
it
!=
_map_on_result
.
end
())
{
it
->
second
(
dec
);
it
->
second
(
dec
);
_map
OnResultCB
.
erase
(
it
);
_map
_on_result
.
erase
(
it
);
}
else
{
}
else
{
WarnL
<<
"unhandled _result"
;
WarnL
<<
"unhandled _result"
;
}
}
}
}
void
RtmpPlayer
::
onCmd_onStatus
(
AMFDecoder
&
dec
)
{
void
RtmpPlayer
::
onCmd_onStatus
(
AMFDecoder
&
dec
)
{
AMFValue
val
;
AMFValue
val
;
while
(
true
)
{
while
(
true
)
{
val
=
dec
.
load
<
AMFValue
>
();
val
=
dec
.
load
<
AMFValue
>
();
if
(
val
.
type
()
==
AMF_OBJECT
)
{
if
(
val
.
type
()
==
AMF_OBJECT
)
{
break
;
break
;
}
}
}
}
if
(
val
.
type
()
!=
AMF_OBJECT
)
{
if
(
val
.
type
()
!=
AMF_OBJECT
)
{
throw
std
::
runtime_error
(
"onStatus:the result object was not found"
);
throw
std
::
runtime_error
(
"onStatus:the result object was not found"
);
}
}
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnStatusCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_status
);
if
(
_dqOnStatusCB
.
size
())
{
if
(
_deque_on_status
.
size
())
{
_d
qOnStatusCB
.
front
()(
val
);
_d
eque_on_status
.
front
()(
val
);
_d
qOnStatusCB
.
pop_front
();
_d
eque_on_status
.
pop_front
();
}
else
{
}
else
{
auto
level
=
val
[
"level"
];
auto
level
=
val
[
"level"
];
auto
code
=
val
[
"code"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
.
type
()
==
AMF_STRING
)
{
if
(
level
.
type
()
==
AMF_STRING
)
{
if
(
level
.
as_string
()
!=
"status"
)
{
if
(
level
.
as_string
()
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"onStatus 失败:"
<<
level
.
as_string
()
<<
" "
<<
code
<<
endl
);
throw
std
::
runtime_error
(
StrPrinter
<<
"onStatus 失败:"
<<
level
.
as_string
()
<<
" "
<<
code
<<
endl
);
}
}
}
}
//WarnL << "unhandled onStatus:" << code;
//WarnL << "unhandled onStatus:" << code;
...
@@ -301,31 +308,31 @@ void RtmpPlayer::onCmd_onStatus(AMFDecoder &dec) {
...
@@ -301,31 +308,31 @@ void RtmpPlayer::onCmd_onStatus(AMFDecoder &dec) {
void
RtmpPlayer
::
onCmd_onMetaData
(
AMFDecoder
&
dec
)
{
void
RtmpPlayer
::
onCmd_onMetaData
(
AMFDecoder
&
dec
)
{
//TraceL;
//TraceL;
auto
val
=
dec
.
load
<
AMFValue
>
();
auto
val
=
dec
.
load
<
AMFValue
>
();
if
(
!
onCheckMeta
(
val
))
{
if
(
!
onCheckMeta
(
val
))
{
throw
std
::
runtime_error
(
"onCheckMeta failed"
);
throw
std
::
runtime_error
(
"onCheckMeta failed"
);
}
}
_metadata_got
=
true
;
_metadata_got
=
true
;
}
}
void
RtmpPlayer
::
onStreamDry
(
uint32_t
ui32StreamI
d
)
{
void
RtmpPlayer
::
onStreamDry
(
uint32_t
stream_i
d
)
{
//TraceL <<
ui32StreamI
d;
//TraceL <<
stream_i
d;
onPlayResult_l
(
SockException
(
Err_other
,
"rtmp stream dry"
),
true
);
onPlayResult_l
(
SockException
(
Err_other
,
"rtmp stream dry"
),
true
);
}
}
void
RtmpPlayer
::
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
packet
)
{
void
RtmpPlayer
::
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
packet
)
{
_
mediaT
icker
.
resetTime
();
_
rtmp_recv_t
icker
.
resetTime
();
if
(
!
_pPlayTimer
)
{
if
(
!
_play_timer
)
{
//已经触发了onPlayResult事件,直接触发onMediaData事件
//已经触发了onPlayResult事件,直接触发onMediaData事件
onMediaData
(
packet
);
onMediaData
(
packet
);
return
;
return
;
}
}
if
(
packet
->
isCfgFrame
())
{
if
(
packet
->
isCfgFrame
())
{
//输入配置帧以便初始化完成各个track
//输入配置帧以便初始化完成各个track
onMediaData
(
packet
);
onMediaData
(
packet
);
}
else
{
}
else
{
//先触发onPlayResult事件,这个时候解码器才能初始化完毕
//先触发onPlayResult事件,这个时候解码器才能初始化完毕
onPlayResult_l
(
SockException
(
Err_success
,
"play rtmp success"
),
false
);
onPlayResult_l
(
SockException
(
Err_success
,
"play rtmp success"
),
false
);
//触发onPlayResult事件后,再把帧数据输入到解码器
//触发onPlayResult事件后,再把帧数据输入到解码器
onMediaData
(
packet
);
onMediaData
(
packet
);
}
}
...
@@ -336,77 +343,76 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
...
@@ -336,77 +343,76 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
typedef
void
(
RtmpPlayer
::*
rtmp_func_ptr
)(
AMFDecoder
&
dec
);
typedef
void
(
RtmpPlayer
::*
rtmp_func_ptr
)(
AMFDecoder
&
dec
);
static
unordered_map
<
string
,
rtmp_func_ptr
>
s_func_map
;
static
unordered_map
<
string
,
rtmp_func_ptr
>
s_func_map
;
static
onceToken
token
([]()
{
static
onceToken
token
([]()
{
s_func_map
.
emplace
(
"_error"
,
&
RtmpPlayer
::
onCmd_result
);
s_func_map
.
emplace
(
"_error"
,
&
RtmpPlayer
::
onCmd_result
);
s_func_map
.
emplace
(
"_result"
,
&
RtmpPlayer
::
onCmd_result
);
s_func_map
.
emplace
(
"_result"
,
&
RtmpPlayer
::
onCmd_result
);
s_func_map
.
emplace
(
"onStatus"
,
&
RtmpPlayer
::
onCmd_onStatus
);
s_func_map
.
emplace
(
"onStatus"
,
&
RtmpPlayer
::
onCmd_onStatus
);
s_func_map
.
emplace
(
"onMetaData"
,
&
RtmpPlayer
::
onCmd_onMetaData
);
s_func_map
.
emplace
(
"onMetaData"
,
&
RtmpPlayer
::
onCmd_onMetaData
);
}
,
[]()
{}
);
});
switch
(
chunkData
.
type
I
d
)
{
switch
(
chunkData
.
type
_i
d
)
{
case
MSG_CMD
:
case
MSG_CMD
:
case
MSG_CMD3
:
case
MSG_CMD3
:
case
MSG_DATA
:
case
MSG_DATA
:
case
MSG_DATA3
:
{
case
MSG_DATA3
:
{
AMFDecoder
dec
(
chunkData
.
strBuf
,
0
);
AMFDecoder
dec
(
chunkData
.
buffer
,
0
);
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
auto
it
=
s_func_map
.
find
(
type
);
auto
it
=
s_func_map
.
find
(
type
);
if
(
it
!=
s_func_map
.
end
())
{
if
(
it
!=
s_func_map
.
end
())
{
auto
fun
=
it
->
second
;
auto
fun
=
it
->
second
;
(
this
->*
fun
)(
dec
);
(
this
->*
fun
)(
dec
);
}
else
{
}
else
{
WarnL
<<
"can not support cmd:"
<<
type
;
WarnL
<<
"can not support cmd:"
<<
type
;
}
}
}
break
;
break
;
}
case
MSG_AUDIO
:
case
MSG_AUDIO
:
case
MSG_VIDEO
:
{
case
MSG_VIDEO
:
{
auto
idx
=
chunkData
.
type
Id
%
2
;
auto
idx
=
chunkData
.
type
_id
%
2
;
if
(
_
aNowStampT
icker
[
idx
].
elapsedTime
()
>
500
)
{
if
(
_
now_stamp_t
icker
[
idx
].
elapsedTime
()
>
500
)
{
//计算播放进度时间轴用
//计算播放进度时间轴用
_
aiNowStamp
[
idx
]
=
chunkData
.
timeS
tamp
;
_
now_stamp
[
idx
]
=
chunkData
.
time_s
tamp
;
}
}
if
(
!
_metadata_got
)
{
if
(
!
_metadata_got
)
{
if
(
!
onCheckMeta
(
TitleMeta
().
getMetadata
()))
{
if
(
!
onCheckMeta
(
TitleMeta
().
getMetadata
()))
{
throw
std
::
runtime_error
(
"onCheckMeta failed"
);
throw
std
::
runtime_error
(
"onCheckMeta failed"
);
}
}
_metadata_got
=
true
;
_metadata_got
=
true
;
}
}
onMediaData_l
(
std
::
make_shared
<
RtmpPacket
>
(
std
::
move
(
chunkData
)));
onMediaData_l
(
std
::
make_shared
<
RtmpPacket
>
(
std
::
move
(
chunkData
)));
}
break
;
default
:
//WarnL << "unhandled message:" << (int) chunkData.typeId << hexdump(chunkData.strBuf.data(), chunkData.strBuf.size());
break
;
break
;
}
}
default
:
break
;
}
}
}
uint32_t
RtmpPlayer
::
getProgressMilliSecond
()
const
{
uint32_t
RtmpPlayer
::
getProgressMilliSecond
()
const
{
uint32_t
iTime
[
2
]
=
{
0
,
0
};
uint32_t
stamp
[
2
]
=
{
0
,
0
};
for
(
auto
i
=
0
;
i
<
2
;
i
++
)
{
for
(
auto
i
=
0
;
i
<
2
;
i
++
)
{
iTime
[
i
]
=
_aiNowStamp
[
i
]
-
_aiFistS
tamp
[
i
];
stamp
[
i
]
=
_now_stamp
[
i
]
-
_fist_s
tamp
[
i
];
}
}
return
_
iSeekTo
+
MAX
(
iTime
[
0
],
iTime
[
1
]);
return
_
seek_ms
+
MAX
(
stamp
[
0
],
stamp
[
1
]);
}
}
void
RtmpPlayer
::
seekToMilliSecond
(
uint32_t
seekMS
){
void
RtmpPlayer
::
seekToMilliSecond
(
uint32_t
seekMS
){
if
(
_
bP
aused
)
{
if
(
_
p
aused
)
{
pause
(
false
);
pause
(
false
);
}
}
AMFEncoder
enc
;
AMFEncoder
enc
;
enc
<<
"seek"
<<
++
_
iReqID
<<
nullptr
<<
seekMS
*
1.0
;
enc
<<
"seek"
<<
++
_
send_req_id
<<
nullptr
<<
seekMS
*
1.0
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
sendRequest
(
MSG_CMD
,
enc
.
data
());
addOnStatusCB
([
this
,
seekMS
](
AMFValue
&
val
)
{
addOnStatusCB
([
this
,
seekMS
](
AMFValue
&
val
)
{
//TraceL << "seek result";
//TraceL << "seek result";
_
aNowStampT
icker
[
0
].
resetTime
();
_
now_stamp_t
icker
[
0
].
resetTime
();
_
aNowStampT
icker
[
1
].
resetTime
();
_
now_stamp_t
icker
[
1
].
resetTime
();
int
iTimeInc
=
seekMS
-
getProgressMilliSecond
();
int
iTimeInc
=
seekMS
-
getProgressMilliSecond
();
for
(
auto
i
=
0
;
i
<
2
;
i
++
)
{
for
(
auto
i
=
0
;
i
<
2
;
i
++
)
{
_
aiFistStamp
[
i
]
=
_aiNowS
tamp
[
i
]
+
iTimeInc
;
_
fist_stamp
[
i
]
=
_now_s
tamp
[
i
]
+
iTimeInc
;
_
aiNowStamp
[
i
]
=
_aiFistS
tamp
[
i
];
_
now_stamp
[
i
]
=
_fist_s
tamp
[
i
];
}
}
_
iSeekTo
=
seekMS
;
_
seek_ms
=
seekMS
;
});
});
}
}
}
/* namespace mediakit */
}
/* namespace mediakit */
src/Rtmp/RtmpPlayer.h
查看文件 @
fbd711a6
...
@@ -8,8 +8,8 @@
...
@@ -8,8 +8,8 @@
* may be found in the AUTHORS file in the root of the source tree.
* may be found in the AUTHORS file in the root of the source tree.
*/
*/
#ifndef SRC_RTMP_RtmpPlayer
2
_H_
#ifndef SRC_RTMP_RtmpPlayer_H_
#define SRC_RTMP_RtmpPlayer
2
_H_
#define SRC_RTMP_RtmpPlayer_H_
#include <memory>
#include <memory>
#include <string>
#include <string>
...
@@ -28,21 +28,24 @@ using namespace toolkit;
...
@@ -28,21 +28,24 @@ using namespace toolkit;
using
namespace
mediakit
::
Client
;
using
namespace
mediakit
::
Client
;
namespace
mediakit
{
namespace
mediakit
{
//实现了rtmp播放器协议部分的功能,及数据接收功能
//实现了rtmp播放器协议部分的功能,及数据接收功能
class
RtmpPlayer
:
public
PlayerBase
,
public
TcpClient
,
public
RtmpProtocol
{
class
RtmpPlayer
:
public
PlayerBase
,
public
TcpClient
,
public
RtmpProtocol
{
public
:
public
:
typedef
std
::
shared_ptr
<
RtmpPlayer
>
Ptr
;
typedef
std
::
shared_ptr
<
RtmpPlayer
>
Ptr
;
RtmpPlayer
(
const
EventPoller
::
Ptr
&
poller
);
RtmpPlayer
(
const
EventPoller
::
Ptr
&
poller
);
virtual
~
RtmpPlayer
()
;
~
RtmpPlayer
()
override
;
void
play
(
const
string
&
strUrl
)
override
;
void
play
(
const
string
&
strUrl
)
override
;
void
pause
(
bool
bPause
)
override
;
void
pause
(
bool
bPause
)
override
;
void
teardown
()
override
;
void
teardown
()
override
;
protected
:
protected
:
virtual
bool
onCheckMeta
(
const
AMFValue
&
val
)
=
0
;
virtual
bool
onCheckMeta
(
const
AMFValue
&
val
)
=
0
;
virtual
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunkData
)
=
0
;
virtual
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunkData
)
=
0
;
uint32_t
getProgressMilliSecond
()
const
;
uint32_t
getProgressMilliSecond
()
const
;
void
seekToMilliSecond
(
uint32_t
ms
);
void
seekToMilliSecond
(
uint32_t
ms
);
protected
:
protected
:
void
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
chunkData
);
void
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
chunkData
);
//在获取config帧后才触发onPlayResult_l(而不是收到play命令回复),所以此时所有track都初始化完毕了
//在获取config帧后才触发onPlayResult_l(而不是收到play命令回复),所以此时所有track都初始化完毕了
...
@@ -59,15 +62,15 @@ protected:
...
@@ -59,15 +62,15 @@ protected:
send
(
buffer
);
send
(
buffer
);
}
}
template
<
typename
FUN
>
template
<
typename
FUN
C
>
inline
void
addOnResultCB
(
const
FUN
&
fun
)
{
inline
void
addOnResultCB
(
const
FUN
C
&
func
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnResultCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_result
);
_map
OnResultCB
.
emplace
(
_iReqID
,
fun
);
_map
_on_result
.
emplace
(
_send_req_id
,
func
);
}
}
template
<
typename
FUN
>
template
<
typename
FUN
C
>
inline
void
addOnStatusCB
(
const
FUN
&
fun
)
{
inline
void
addOnStatusCB
(
const
FUN
C
&
func
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnStatusCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_status
);
_d
qOnStatusCB
.
emplace_back
(
fun
);
_d
eque_on_status
.
emplace_back
(
func
);
}
}
void
onCmd_result
(
AMFDecoder
&
dec
);
void
onCmd_result
(
AMFDecoder
&
dec
);
...
@@ -78,34 +81,37 @@ protected:
...
@@ -78,34 +81,37 @@ protected:
inline
void
send_createStream
();
inline
void
send_createStream
();
inline
void
send_play
();
inline
void
send_play
();
inline
void
send_pause
(
bool
bPause
);
inline
void
send_pause
(
bool
bPause
);
private
:
private
:
string
_strApp
;
string
_app
;
string
_strStream
;
string
_stream_id
;
string
_strTcUrl
;
string
_tc_url
;
bool
_bPaused
=
false
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
_mapOnResultCB
;
recursive_mutex
_mtxOnResultCB
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
_dqOnStatusCB
;
recursive_mutex
_mtxOnStatusCB
;
//超时功能实现
Ticker
_mediaTicker
;
std
::
shared_ptr
<
Timer
>
_pMediaTimer
;
std
::
shared_ptr
<
Timer
>
_pPlayTimer
;
//心跳定时器
std
::
shared_ptr
<
Timer
>
_pBeatTimer
;
//播放进度控制
bool
_paused
=
false
;
uint32_t
_iSeekTo
=
0
;
uint32_t
_aiFistStamp
[
2
]
=
{
0
,
0
};
uint32_t
_aiNowStamp
[
2
]
=
{
0
,
0
};
Ticker
_aNowStampTicker
[
2
];
bool
_metadata_got
=
false
;
bool
_metadata_got
=
false
;
//是否为性能测试模式
//是否为性能测试模式
bool
_benchmark_mode
=
false
;
bool
_benchmark_mode
=
false
;
//播放进度控制
uint32_t
_seek_ms
=
0
;
uint32_t
_fist_stamp
[
2
]
=
{
0
,
0
};
uint32_t
_now_stamp
[
2
]
=
{
0
,
0
};
Ticker
_now_stamp_ticker
[
2
];
recursive_mutex
_mtx_on_result
;
recursive_mutex
_mtx_on_status
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
_deque_on_status
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
_map_on_result
;
//rtmp接收超时计时器
Ticker
_rtmp_recv_ticker
;
//心跳发送定时器
std
::
shared_ptr
<
Timer
>
_beat_timer
;
//播放超时定时器
std
::
shared_ptr
<
Timer
>
_play_timer
;
//rtmp接收超时定时器
std
::
shared_ptr
<
Timer
>
_rtmp_recv_timer
;
};
};
}
/* namespace mediakit */
}
/* namespace mediakit */
#endif
/* SRC_RTMP_RtmpPlayer_H_ */
#endif
/* SRC_RTMP_RtmpPlayer2_H_ */
src/Rtmp/RtmpPlayerImp.h
查看文件 @
fbd711a6
...
@@ -27,51 +27,59 @@ namespace mediakit {
...
@@ -27,51 +27,59 @@ namespace mediakit {
class
RtmpPlayerImp
:
public
PlayerImp
<
RtmpPlayer
,
RtmpDemuxer
>
{
class
RtmpPlayerImp
:
public
PlayerImp
<
RtmpPlayer
,
RtmpDemuxer
>
{
public
:
public
:
typedef
std
::
shared_ptr
<
RtmpPlayerImp
>
Ptr
;
typedef
std
::
shared_ptr
<
RtmpPlayerImp
>
Ptr
;
RtmpPlayerImp
(
const
EventPoller
::
Ptr
&
poller
)
:
PlayerImp
<
RtmpPlayer
,
RtmpDemuxer
>
(
poller
){};
virtual
~
RtmpPlayerImp
(){
RtmpPlayerImp
(
const
EventPoller
::
Ptr
&
poller
)
:
PlayerImp
<
RtmpPlayer
,
RtmpDemuxer
>
(
poller
)
{};
DebugL
<<
endl
;
};
~
RtmpPlayerImp
()
override
{
float
getProgress
()
const
override
{
DebugL
<<
endl
;
if
(
getDuration
()
>
0
){
}
float
getProgress
()
const
override
{
if
(
getDuration
()
>
0
)
{
return
getProgressMilliSecond
()
/
(
getDuration
()
*
1000
);
return
getProgressMilliSecond
()
/
(
getDuration
()
*
1000
);
}
}
return
PlayerBase
::
getProgress
();
return
PlayerBase
::
getProgress
();
};
}
void
seekTo
(
float
fProgress
)
override
{
fProgress
=
MAX
(
float
(
0
),
MIN
(
fProgress
,
float
(
1
.
0
)));
void
seekTo
(
float
fProgress
)
override
{
fProgress
=
MAX
(
float
(
0
),
MIN
(
fProgress
,
float
(
1
.
0
)));
seekToMilliSecond
(
fProgress
*
getDuration
()
*
1000
);
seekToMilliSecond
(
fProgress
*
getDuration
()
*
1000
);
};
}
void
play
(
const
string
&
strUrl
)
override
{
void
play
(
const
string
&
strUrl
)
override
{
PlayerImp
<
RtmpPlayer
,
RtmpDemuxer
>::
play
(
strUrl
);
PlayerImp
<
RtmpPlayer
,
RtmpDemuxer
>::
play
(
strUrl
);
}
}
private
:
private
:
//派生类回调函数
//派生类回调函数
bool
onCheckMeta
(
const
AMFValue
&
val
)
override
{
bool
onCheckMeta
(
const
AMFValue
&
val
)
override
{
_
pRtmpMediaS
rc
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
_pMediaSrc
);
_
rtmp_s
rc
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
_pMediaSrc
);
if
(
_pRtmpMediaSrc
)
{
if
(
_rtmp_src
)
{
_
pRtmpMediaS
rc
->
setMetaData
(
val
);
_
rtmp_s
rc
->
setMetaData
(
val
);
_set_meta_data
=
true
;
_set_meta_data
=
true
;
}
}
_delegate
.
reset
(
new
RtmpDemuxer
);
_delegate
.
reset
(
new
RtmpDemuxer
);
_delegate
->
loadMetaData
(
val
);
_delegate
->
loadMetaData
(
val
);
return
true
;
return
true
;
}
}
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunkData
)
override
{
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunkData
)
override
{
if
(
_pRtmpMediaSrc
)
{
if
(
_rtmp_src
)
{
if
(
!
_set_meta_data
&&
!
chunkData
->
isCfgFrame
())
{
if
(
!
_set_meta_data
&&
!
chunkData
->
isCfgFrame
())
{
_set_meta_data
=
true
;
_set_meta_data
=
true
;
_
pRtmpMediaS
rc
->
setMetaData
(
TitleMeta
().
getMetadata
());
_
rtmp_s
rc
->
setMetaData
(
TitleMeta
().
getMetadata
());
}
}
_
pRtmpMediaS
rc
->
onWrite
(
chunkData
);
_
rtmp_s
rc
->
onWrite
(
chunkData
);
}
}
if
(
!
_delegate
)
{
if
(
!
_delegate
)
{
//这个流没有metadata
//这个流没有metadata
_delegate
.
reset
(
new
RtmpDemuxer
());
_delegate
.
reset
(
new
RtmpDemuxer
());
}
}
_delegate
->
inputRtmp
(
chunkData
);
_delegate
->
inputRtmp
(
chunkData
);
}
}
private
:
private
:
RtmpMediaSource
::
Ptr
_
pRtmpMediaS
rc
;
RtmpMediaSource
::
Ptr
_
rtmp_s
rc
;
bool
_set_meta_data
=
false
;
bool
_set_meta_data
=
false
;
};
};
...
...
src/Rtmp/RtmpProtocol.cpp
查看文件 @
fbd711a6
...
@@ -20,9 +20,17 @@ using namespace toolkit;
...
@@ -20,9 +20,17 @@ using namespace toolkit;
#include <openssl/hmac.h>
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
#include <openssl/opensslv.h>
static
string
openssl_HMACsha256
(
const
void
*
key
,
unsigned
int
key_len
,
#define C1_DIGEST_SIZE 32
const
void
*
data
,
unsigned
int
data_len
){
#define C1_KEY_SIZE 128
std
::
shared_ptr
<
char
>
out
(
new
char
[
32
],[](
char
*
ptr
){
delete
[]
ptr
;});
#define C1_SCHEMA_SIZE 764
#define C1_HANDSHARK_SIZE (RANDOM_LEN + 8)
#define C1_FPKEY_SIZE 30
#define S1_FMS_KEY_SIZE 36
#define S2_FMS_KEY_SIZE 68
#define C1_OFFSET_SIZE 4
static
string
openssl_HMACsha256
(
const
void
*
key
,
unsigned
int
key_len
,
const
void
*
data
,
unsigned
int
data_len
){
std
::
shared_ptr
<
char
>
out
(
new
char
[
32
],
[](
char
*
ptr
)
{
delete
[]
ptr
;
});
unsigned
int
out_len
;
unsigned
int
out_len
;
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
#if defined(OPENSSL_VERSION_NUMBER) && (OPENSSL_VERSION_NUMBER > 0x10100000L)
...
@@ -46,273 +54,271 @@ static string openssl_HMACsha256(const void *key,unsigned int key_len,
...
@@ -46,273 +54,271 @@ static string openssl_HMACsha256(const void *key,unsigned int key_len,
}
}
#endif //ENABLE_OPENSSL
#endif //ENABLE_OPENSSL
#define C1_DIGEST_SIZE 32
#define C1_KEY_SIZE 128
#define C1_SCHEMA_SIZE 764
#define C1_HANDSHARK_SIZE (RANDOM_LEN + 8)
#define C1_FPKEY_SIZE 30
#define S1_FMS_KEY_SIZE 36
#define S2_FMS_KEY_SIZE 68
#define C1_OFFSET_SIZE 4
namespace
mediakit
{
namespace
mediakit
{
RtmpProtocol
::
RtmpProtocol
()
{
RtmpProtocol
::
RtmpProtocol
()
{
_next
Handle
=
[
this
]()
{
_next
_step_func
=
[
this
]()
{
handle_C0C1
();
handle_C0C1
();
};
};
}
}
RtmpProtocol
::~
RtmpProtocol
()
{
RtmpProtocol
::~
RtmpProtocol
()
{
reset
();
reset
();
}
}
void
RtmpProtocol
::
reset
()
{
void
RtmpProtocol
::
reset
()
{
////////////ChunkSize////////////
////////////ChunkSize////////////
_
iChunkLenI
n
=
DEFAULT_CHUNK_LEN
;
_
chunk_size_i
n
=
DEFAULT_CHUNK_LEN
;
_
iChunkLenO
ut
=
DEFAULT_CHUNK_LEN
;
_
chunk_size_o
ut
=
DEFAULT_CHUNK_LEN
;
////////////Acknowledgement////////////
////////////Acknowledgement////////////
_
ui32ByteS
ent
=
0
;
_
bytes_s
ent
=
0
;
_
ui32LastSen
t
=
0
;
_
bytes_sent_las
t
=
0
;
_
ui32WinS
ize
=
0
;
_
windows_s
ize
=
0
;
///////////PeerBandwidth///////////
///////////PeerBandwidth///////////
_
ui32B
andwidth
=
2500000
;
_
b
andwidth
=
2500000
;
_
ui8LimitT
ype
=
2
;
_
band_limit_t
ype
=
2
;
////////////Chunk////////////
////////////Chunk////////////
_map
ChunkD
ata
.
clear
();
_map
_chunk_d
ata
.
clear
();
_
iNowStreamID
=
0
;
_
now_stream_index
=
0
;
_
iNowChunkID
=
0
;
_
now_chunk_id
=
0
;
//////////Invoke Request//////////
//////////Invoke Request//////////
_
iReqID
=
0
;
_
send_req_id
=
0
;
//////////Rtmp parser//////////
//////////Rtmp parser//////////
_
strRcvB
uf
.
clear
();
_
recv_data_b
uf
.
clear
();
_
ui32StreamId
=
STREAM_CONTROL
;
_
stream_index
=
STREAM_CONTROL
;
_next
Handle
=
[
this
]()
{
_next
_step_func
=
[
this
]()
{
handle_C0C1
();
handle_C0C1
();
};
};
}
}
void
RtmpProtocol
::
sendAcknowledgement
(
uint32_t
ui32Size
)
{
void
RtmpProtocol
::
sendAcknowledgement
(
uint32_t
size
)
{
std
::
string
control
;
size
=
htonl
(
size
);
uint32_t
stream
=
htonl
(
ui32Size
);
std
::
string
acknowledgement
((
char
*
)
&
size
,
4
);
control
.
append
((
char
*
)
&
stream
,
4
);
sendRequest
(
MSG_ACK
,
acknowledgement
);
sendRequest
(
MSG_ACK
,
control
);
}
}
void
RtmpProtocol
::
sendAcknowledgementSize
(
uint32_t
ui32S
ize
)
{
void
RtmpProtocol
::
sendAcknowledgementSize
(
uint32_t
s
ize
)
{
uint32_t
windowSize
=
htonl
(
ui32S
ize
);
size
=
htonl
(
s
ize
);
std
::
string
set_windowSize
((
char
*
)
&
windowS
ize
,
4
);
std
::
string
set_windowSize
((
char
*
)
&
s
ize
,
4
);
sendRequest
(
MSG_WIN_SIZE
,
set_windowSize
);
sendRequest
(
MSG_WIN_SIZE
,
set_windowSize
);
}
}
void
RtmpProtocol
::
sendPeerBandwidth
(
uint32_t
ui32S
ize
)
{
void
RtmpProtocol
::
sendPeerBandwidth
(
uint32_t
s
ize
)
{
uint32_t
peerBandwidth
=
htonl
(
ui32S
ize
);
size
=
htonl
(
s
ize
);
std
::
string
set_peerBandwidth
((
char
*
)
&
peerBandwidth
,
4
);
std
::
string
set_peerBandwidth
((
char
*
)
&
size
,
4
);
set_peerBandwidth
.
push_back
((
char
)
0x02
);
set_peerBandwidth
.
push_back
((
char
)
0x02
);
sendRequest
(
MSG_SET_PEER_BW
,
set_peerBandwidth
);
sendRequest
(
MSG_SET_PEER_BW
,
set_peerBandwidth
);
}
}
void
RtmpProtocol
::
sendChunkSize
(
uint32_t
ui32S
ize
)
{
void
RtmpProtocol
::
sendChunkSize
(
uint32_t
s
ize
)
{
uint32_t
len
=
htonl
(
ui32S
ize
);
uint32_t
len
=
htonl
(
s
ize
);
std
::
string
set_chunk
((
char
*
)
&
len
,
4
);
std
::
string
set_chunk
((
char
*
)
&
len
,
4
);
sendRequest
(
MSG_SET_CHUNK
,
set_chunk
);
sendRequest
(
MSG_SET_CHUNK
,
set_chunk
);
_
iChunkLenOut
=
ui32S
ize
;
_
chunk_size_out
=
s
ize
;
}
}
void
RtmpProtocol
::
sendPingRequest
(
uint32_t
ui32TimeS
tamp
)
{
void
RtmpProtocol
::
sendPingRequest
(
uint32_t
s
tamp
)
{
sendUserControl
(
CONTROL_PING_REQUEST
,
ui32TimeS
tamp
);
sendUserControl
(
CONTROL_PING_REQUEST
,
s
tamp
);
}
}
void
RtmpProtocol
::
sendPingResponse
(
uint32_t
ui32TimeS
tamp
)
{
void
RtmpProtocol
::
sendPingResponse
(
uint32_t
time_s
tamp
)
{
sendUserControl
(
CONTROL_PING_RESPONSE
,
ui32TimeS
tamp
);
sendUserControl
(
CONTROL_PING_RESPONSE
,
time_s
tamp
);
}
}
void
RtmpProtocol
::
sendSetBufferLength
(
uint32_t
ui32StreamId
,
void
RtmpProtocol
::
sendSetBufferLength
(
uint32_t
stream_index
,
uint32_t
len
)
{
uint32_t
ui32Length
)
{
std
::
string
control
;
std
::
string
control
;
ui32StreamId
=
htonl
(
ui32StreamId
);
stream_index
=
htonl
(
stream_index
);
control
.
append
((
char
*
)
&
ui32StreamId
,
4
);
control
.
append
((
char
*
)
&
stream_index
,
4
);
ui32Length
=
htonl
(
ui32Length
);
control
.
append
((
char
*
)
&
ui32Length
,
4
);
len
=
htonl
(
len
);
control
.
append
((
char
*
)
&
len
,
4
);
sendUserControl
(
CONTROL_SETBUFFER
,
control
);
sendUserControl
(
CONTROL_SETBUFFER
,
control
);
}
}
void
RtmpProtocol
::
sendUserControl
(
uint16_t
ui16EventType
,
void
RtmpProtocol
::
sendUserControl
(
uint16_t
event_type
,
uint32_t
event_data
)
{
uint32_t
ui32EventData
)
{
std
::
string
control
;
std
::
string
control
;
uint16_t
type
=
htons
(
ui16EventType
);
event_type
=
htons
(
event_type
);
control
.
append
((
char
*
)
&
type
,
2
);
control
.
append
((
char
*
)
&
event_type
,
2
);
uint32_t
stream
=
htonl
(
ui32EventData
);
control
.
append
((
char
*
)
&
stream
,
4
);
event_data
=
htonl
(
event_data
);
control
.
append
((
char
*
)
&
event_data
,
4
);
sendRequest
(
MSG_USER_CONTROL
,
control
);
sendRequest
(
MSG_USER_CONTROL
,
control
);
}
}
void
RtmpProtocol
::
sendUserControl
(
uint16_t
ui16EventType
,
void
RtmpProtocol
::
sendUserControl
(
uint16_t
event_type
,
const
string
&
event_data
)
{
const
string
&
strEventData
)
{
std
::
string
control
;
std
::
string
control
;
uint16_t
type
=
htons
(
ui16EventT
ype
);
event_type
=
htons
(
event_t
ype
);
control
.
append
((
char
*
)
&
type
,
2
);
control
.
append
((
char
*
)
&
event_
type
,
2
);
control
.
append
(
strEventD
ata
);
control
.
append
(
event_d
ata
);
sendRequest
(
MSG_USER_CONTROL
,
control
);
sendRequest
(
MSG_USER_CONTROL
,
control
);
}
}
void
RtmpProtocol
::
sendResponse
(
int
iType
,
const
string
&
str
)
{
void
RtmpProtocol
::
sendResponse
(
int
type
,
const
string
&
str
)
{
if
(
!
_
bDataStarted
&&
(
iT
ype
==
MSG_DATA
)){
if
(
!
_
data_started
&&
(
t
ype
==
MSG_DATA
)){
_
bDataS
tarted
=
true
;
_
data_s
tarted
=
true
;
}
}
sendRtmp
(
iType
,
_iNowStreamID
,
str
,
0
,
_bDataS
tarted
?
CHUNK_CLIENT_REQUEST_AFTER
:
CHUNK_CLIENT_REQUEST_BEFORE
);
sendRtmp
(
type
,
_now_stream_index
,
str
,
0
,
_data_s
tarted
?
CHUNK_CLIENT_REQUEST_AFTER
:
CHUNK_CLIENT_REQUEST_BEFORE
);
}
}
void
RtmpProtocol
::
sendInvoke
(
const
string
&
strCmd
,
const
AMFValue
&
val
)
{
void
RtmpProtocol
::
sendInvoke
(
const
string
&
cmd
,
const
AMFValue
&
val
)
{
AMFEncoder
enc
;
AMFEncoder
enc
;
enc
<<
strCmd
<<
++
_iReqID
<<
val
;
enc
<<
cmd
<<
++
_send_req_id
<<
val
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
sendRequest
(
MSG_CMD
,
enc
.
data
());
}
}
void
RtmpProtocol
::
sendRequest
(
int
iC
md
,
const
string
&
str
)
{
void
RtmpProtocol
::
sendRequest
(
int
c
md
,
const
string
&
str
)
{
sendRtmp
(
iCmd
,
_ui32StreamId
,
str
,
0
,
CHUNK_SERVER_REQUEST
);
sendRtmp
(
cmd
,
_stream_index
,
str
,
0
,
CHUNK_SERVER_REQUEST
);
}
}
class
BufferPartial
:
public
Buffer
{
class
BufferPartial
:
public
Buffer
{
public
:
public
:
BufferPartial
(
const
Buffer
::
Ptr
&
buffer
,
uint32_t
offset
,
uint32_t
size
){
BufferPartial
(
const
Buffer
::
Ptr
&
buffer
,
uint32_t
offset
,
uint32_t
size
){
_buffer
=
buffer
;
_buffer
=
buffer
;
_data
=
buffer
->
data
()
+
offset
;
_data
=
buffer
->
data
()
+
offset
;
_size
=
size
;
_size
=
size
;
}
}
~
BufferPartial
(){}
~
BufferPartial
()
override
{}
char
*
data
()
const
override
{
char
*
data
()
const
override
{
return
_data
;
return
_data
;
}
}
uint32_t
size
()
const
override
{
uint32_t
size
()
const
override
{
return
_size
;
return
_size
;
}
}
private
:
private
:
Buffer
::
Ptr
_buffer
;
char
*
_data
;
char
*
_data
;
uint32_t
_size
;
uint32_t
_size
;
Buffer
::
Ptr
_buffer
;
};
};
void
RtmpProtocol
::
sendRtmp
(
uint8_t
ui8Type
,
uint32_t
ui32StreamId
,
void
RtmpProtocol
::
sendRtmp
(
uint8_t
type
,
uint32_t
stream_index
,
const
std
::
string
&
buffer
,
uint32_t
stamp
,
int
chunk_id
)
{
const
std
::
string
&
strBuf
,
uint32_t
ui32TimeStamp
,
int
iChunkId
)
{
sendRtmp
(
type
,
stream_index
,
std
::
make_shared
<
BufferString
>
(
buffer
),
stamp
,
chunk_id
);
sendRtmp
(
ui8Type
,
ui32StreamId
,
std
::
make_shared
<
BufferString
>
(
strBuf
),
ui32TimeStamp
,
iChunkId
);
}
}
void
RtmpProtocol
::
sendRtmp
(
uint8_t
ui8Type
,
uint32_t
ui32StreamId
,
void
RtmpProtocol
::
sendRtmp
(
uint8_t
type
,
uint32_t
stream_index
,
const
Buffer
::
Ptr
&
buf
,
uint32_t
stamp
,
int
chunk_id
){
const
Buffer
::
Ptr
&
buf
,
uint32_t
ui32TimeStamp
,
int
iChunkId
){
if
(
chunk_id
<
2
||
chunk_id
>
63
)
{
if
(
iChunkId
<
2
||
iChunkId
>
63
)
{
auto
strErr
=
StrPrinter
<<
"不支持发送该类型的块流 ID:"
<<
chunk_id
<<
endl
;
auto
strErr
=
StrPrinter
<<
"不支持发送该类型的块流 ID:"
<<
iChunkId
<<
endl
;
throw
std
::
runtime_error
(
strErr
);
throw
std
::
runtime_error
(
strErr
);
}
}
//是否有扩展时间戳
//是否有扩展时间戳
bool
bExtStamp
=
ui32TimeS
tamp
>=
0xFFFFFF
;
bool
ext_stamp
=
s
tamp
>=
0xFFFFFF
;
//rtmp头
//rtmp头
BufferRaw
::
Ptr
buffer
H
eader
=
obtainBuffer
();
BufferRaw
::
Ptr
buffer
_h
eader
=
obtainBuffer
();
buffer
H
eader
->
setCapacity
(
sizeof
(
RtmpHeader
));
buffer
_h
eader
->
setCapacity
(
sizeof
(
RtmpHeader
));
buffer
H
eader
->
setSize
(
sizeof
(
RtmpHeader
));
buffer
_h
eader
->
setSize
(
sizeof
(
RtmpHeader
));
//对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题
//对rtmp头赋值,如果使用整形赋值,在arm android上可能由于数据对齐导致总线错误的问题
RtmpHeader
*
header
=
(
RtmpHeader
*
)
bufferH
eader
->
data
();
RtmpHeader
*
header
=
(
RtmpHeader
*
)
buffer_h
eader
->
data
();
header
->
flags
=
(
iChunkI
d
&
0x3f
)
|
(
0
<<
6
);
header
->
flags
=
(
chunk_i
d
&
0x3f
)
|
(
0
<<
6
);
header
->
type
Id
=
ui8T
ype
;
header
->
type
_id
=
t
ype
;
set_be24
(
header
->
time
Stamp
,
bExtStamp
?
0xFFFFFF
:
ui32TimeS
tamp
);
set_be24
(
header
->
time
_stamp
,
ext_stamp
?
0xFFFFFF
:
s
tamp
);
set_be24
(
header
->
body
S
ize
,
buf
->
size
());
set_be24
(
header
->
body
_s
ize
,
buf
->
size
());
set_le32
(
header
->
stream
Id
,
ui32StreamId
);
set_le32
(
header
->
stream
_index
,
stream_index
);
//发送rtmp头
//发送rtmp头
onSendRawData
(
buffer
H
eader
);
onSendRawData
(
buffer
_h
eader
);
//扩展时间戳字段
//扩展时间戳字段
BufferRaw
::
Ptr
buffer
ExtS
tamp
;
BufferRaw
::
Ptr
buffer
_ext_s
tamp
;
if
(
bExtS
tamp
)
{
if
(
ext_s
tamp
)
{
//生成扩展时间戳
//生成扩展时间戳
buffer
ExtS
tamp
=
obtainBuffer
();
buffer
_ext_s
tamp
=
obtainBuffer
();
buffer
ExtS
tamp
->
setCapacity
(
4
);
buffer
_ext_s
tamp
->
setCapacity
(
4
);
buffer
ExtS
tamp
->
setSize
(
4
);
buffer
_ext_s
tamp
->
setSize
(
4
);
set_be32
(
buffer
ExtStamp
->
data
(),
ui32TimeS
tamp
);
set_be32
(
buffer
_ext_stamp
->
data
(),
s
tamp
);
}
}
//生成一个字节的flag,标明是什么chunkId
//生成一个字节的flag,标明是什么chunkId
BufferRaw
::
Ptr
buffer
F
lags
=
obtainBuffer
();
BufferRaw
::
Ptr
buffer
_f
lags
=
obtainBuffer
();
buffer
F
lags
->
setCapacity
(
1
);
buffer
_f
lags
->
setCapacity
(
1
);
buffer
F
lags
->
setSize
(
1
);
buffer
_f
lags
->
setSize
(
1
);
buffer
Flags
->
data
()[
0
]
=
(
iChunkI
d
&
0x3f
)
|
(
3
<<
6
);
buffer
_flags
->
data
()[
0
]
=
(
chunk_i
d
&
0x3f
)
|
(
3
<<
6
);
size_t
offset
=
0
;
size_t
offset
=
0
;
uint32_t
totalSize
=
sizeof
(
RtmpHeader
);
uint32_t
totalSize
=
sizeof
(
RtmpHeader
);
while
(
offset
<
buf
->
size
())
{
while
(
offset
<
buf
->
size
())
{
if
(
offset
)
{
if
(
offset
)
{
onSendRawData
(
buffer
F
lags
);
onSendRawData
(
buffer
_f
lags
);
totalSize
+=
1
;
totalSize
+=
1
;
}
}
if
(
bExtS
tamp
)
{
if
(
ext_s
tamp
)
{
//扩展时间戳
//扩展时间戳
onSendRawData
(
buffer
ExtS
tamp
);
onSendRawData
(
buffer
_ext_s
tamp
);
totalSize
+=
4
;
totalSize
+=
4
;
}
}
size_t
chunk
=
min
(
_
iChunkLenO
ut
,
buf
->
size
()
-
offset
);
size_t
chunk
=
min
(
_
chunk_size_o
ut
,
buf
->
size
()
-
offset
);
onSendRawData
(
std
::
make_shared
<
BufferPartial
>
(
buf
,
offset
,
chunk
));
onSendRawData
(
std
::
make_shared
<
BufferPartial
>
(
buf
,
offset
,
chunk
));
totalSize
+=
chunk
;
totalSize
+=
chunk
;
offset
+=
chunk
;
offset
+=
chunk
;
}
}
_
ui32ByteS
ent
+=
totalSize
;
_
bytes_s
ent
+=
totalSize
;
if
(
_
ui32WinSize
>
0
&&
_ui32ByteSent
-
_ui32LastSent
>=
_ui32WinS
ize
)
{
if
(
_
windows_size
>
0
&&
_bytes_sent
-
_bytes_sent_last
>=
_windows_s
ize
)
{
_
ui32LastSent
=
_ui32ByteS
ent
;
_
bytes_sent_last
=
_bytes_s
ent
;
sendAcknowledgement
(
_
ui32ByteS
ent
);
sendAcknowledgement
(
_
bytes_s
ent
);
}
}
}
}
void
RtmpProtocol
::
onParseRtmp
(
const
char
*
data
,
int
size
)
{
_recv_data_buf
.
append
(
data
,
size
);
//移动拷贝提高性能
function
<
void
()
>
next_step_func
(
std
::
move
(
_next_step_func
));
//执行下一步
next_step_func
();
void
RtmpProtocol
::
onParseRtmp
(
const
char
*
pcRawData
,
int
iSize
)
{
if
(
!
_next_step_func
)
{
_strRcvBuf
.
append
(
pcRawData
,
iSize
);
//为设置下一步,恢复之
auto
cb
=
_nextHandle
;
next_step_func
.
swap
(
_next_step_func
)
;
cb
();
}
}
}
////for client////
////for client////
void
RtmpProtocol
::
startClientSession
(
const
function
<
void
()
>
&
callBack
)
{
void
RtmpProtocol
::
startClientSession
(
const
function
<
void
()
>
&
func
)
{
//发送 C0C1
//发送 C0C1
char
handshake_head
=
HANDSHAKE_PLAINTEXT
;
char
handshake_head
=
HANDSHAKE_PLAINTEXT
;
onSendRawData
(
obtainBuffer
(
&
handshake_head
,
1
));
onSendRawData
(
obtainBuffer
(
&
handshake_head
,
1
));
RtmpHandshake
c1
(
0
);
RtmpHandshake
c1
(
0
);
onSendRawData
(
obtainBuffer
((
char
*
)
(
&
c1
),
sizeof
(
c1
)));
onSendRawData
(
obtainBuffer
((
char
*
)
(
&
c1
),
sizeof
(
c1
)));
_next
Handle
=
[
this
,
callBack
]()
{
_next
_step_func
=
[
this
,
func
]()
{
//等待 S0+S1+S2
//等待 S0+S1+S2
handle_S0S1S2
(
callBack
);
handle_S0S1S2
(
func
);
};
};
}
}
void
RtmpProtocol
::
handle_S0S1S2
(
const
function
<
void
()
>
&
callBack
)
{
if
(
_strRcvBuf
.
size
()
<
1
+
2
*
C1_HANDSHARK_SIZE
)
{
void
RtmpProtocol
::
handle_S0S1S2
(
const
function
<
void
()
>
&
func
)
{
if
(
_recv_data_buf
.
size
()
<
1
+
2
*
C1_HANDSHARK_SIZE
)
{
//数据不够
//数据不够
return
;
return
;
}
}
if
(
_
strRcvB
uf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
if
(
_
recv_data_b
uf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
throw
std
::
runtime_error
(
"only plaintext[0x03] handshake supported"
);
throw
std
::
runtime_error
(
"only plaintext[0x03] handshake supported"
);
}
}
//发送 C2
//发送 C2
const
char
*
pcC2
=
_
strRcvB
uf
.
data
()
+
1
;
const
char
*
pcC2
=
_
recv_data_b
uf
.
data
()
+
1
;
onSendRawData
(
obtainBuffer
(
pcC2
,
C1_HANDSHARK_SIZE
));
onSendRawData
(
obtainBuffer
(
pcC2
,
C1_HANDSHARK_SIZE
));
_
strRcvB
uf
.
erase
(
0
,
1
+
2
*
C1_HANDSHARK_SIZE
);
_
recv_data_b
uf
.
erase
(
0
,
1
+
2
*
C1_HANDSHARK_SIZE
);
//握手结束
//握手结束
_next
Handle
=
[
this
]()
{
_next
_step_func
=
[
this
]()
{
//握手结束并且开始进入解析命令模式
//握手结束并且开始进入解析命令模式
handle_rtmp
();
handle_rtmp
();
};
};
callBack
();
func
();
}
}
////for server ////
////for server ////
void
RtmpProtocol
::
handle_C0C1
()
{
void
RtmpProtocol
::
handle_C0C1
()
{
if
(
_
strRcvB
uf
.
size
()
<
1
+
C1_HANDSHARK_SIZE
)
{
if
(
_
recv_data_b
uf
.
size
()
<
1
+
C1_HANDSHARK_SIZE
)
{
//need more data!
//need more data!
return
;
return
;
}
}
if
(
_
strRcvB
uf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
if
(
_
recv_data_b
uf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
throw
std
::
runtime_error
(
"only plaintext[0x03] handshake supported"
);
throw
std
::
runtime_error
(
"only plaintext[0x03] handshake supported"
);
}
}
if
(
memcmp
(
_strRcvBuf
.
data
()
+
5
,
"
\x00\x00\x00\x00
"
,
4
)
==
0
)
{
if
(
memcmp
(
_recv_data_buf
.
data
()
+
5
,
"
\x00\x00\x00\x00
"
,
4
)
==
0
)
{
//simple handsharke
//simple handsharke
handle_C1_simple
();
handle_C1_simple
();
}
else
{
}
else
{
#ifdef ENABLE_OPENSSL
#ifdef ENABLE_OPENSSL
//complex handsharke
//complex handsharke
handle_C1_complex
();
handle_C1_complex
();
...
@@ -321,8 +327,9 @@ void RtmpProtocol::handle_C0C1() {
...
@@ -321,8 +327,9 @@ void RtmpProtocol::handle_C0C1() {
handle_C1_simple
();
handle_C1_simple
();
#endif//ENABLE_OPENSSL
#endif//ENABLE_OPENSSL
}
}
_
strRcvB
uf
.
erase
(
0
,
1
+
C1_HANDSHARK_SIZE
);
_
recv_data_b
uf
.
erase
(
0
,
1
+
C1_HANDSHARK_SIZE
);
}
}
void
RtmpProtocol
::
handle_C1_simple
(){
void
RtmpProtocol
::
handle_C1_simple
(){
//发送S0
//发送S0
char
handshake_head
=
HANDSHAKE_PLAINTEXT
;
char
handshake_head
=
HANDSHAKE_PLAINTEXT
;
...
@@ -331,51 +338,52 @@ void RtmpProtocol::handle_C1_simple(){
...
@@ -331,51 +338,52 @@ void RtmpProtocol::handle_C1_simple(){
RtmpHandshake
s1
(
0
);
RtmpHandshake
s1
(
0
);
onSendRawData
(
obtainBuffer
((
char
*
)
&
s1
,
C1_HANDSHARK_SIZE
));
onSendRawData
(
obtainBuffer
((
char
*
)
&
s1
,
C1_HANDSHARK_SIZE
));
//发送S2
//发送S2
onSendRawData
(
obtainBuffer
(
_
strRcvB
uf
.
data
()
+
1
,
C1_HANDSHARK_SIZE
));
onSendRawData
(
obtainBuffer
(
_
recv_data_b
uf
.
data
()
+
1
,
C1_HANDSHARK_SIZE
));
//等待C2
//等待C2
_next
Handle
=
[
this
]()
{
_next
_step_func
=
[
this
]()
{
handle_C2
();
handle_C2
();
};
};
}
}
#ifdef ENABLE_OPENSSL
#ifdef ENABLE_OPENSSL
void
RtmpProtocol
::
handle_C1_complex
(){
void
RtmpProtocol
::
handle_C1_complex
(){
//参考自:http://blog.csdn.net/win_lin/article/details/13006803
//参考自:http://blog.csdn.net/win_lin/article/details/13006803
//skip c0,time,version
//skip c0,time,version
const
char
*
c1_start
=
_
strRcvB
uf
.
data
()
+
1
;
const
char
*
c1_start
=
_
recv_data_b
uf
.
data
()
+
1
;
const
char
*
schema_start
=
c1_start
+
8
;
const
char
*
schema_start
=
c1_start
+
8
;
char
*
digest_start
;
char
*
digest_start
;
try
{
try
{
/* c1s1 schema0
/* c1s1 schema0
time: 4bytes
time: 4bytes
version: 4bytes
version: 4bytes
key: 764bytes
key: 764bytes
digest: 764bytes
digest: 764bytes
*/
*/
auto
digest
=
get_C1_digest
((
uint8_t
*
)
schema_start
+
C1_SCHEMA_SIZE
,
&
digest_start
);
auto
digest
=
get_C1_digest
((
uint8_t
*
)
schema_start
+
C1_SCHEMA_SIZE
,
&
digest_start
);
string
c1_joined
(
c1_start
,
C1_HANDSHARK_SIZE
);
string
c1_joined
(
c1_start
,
C1_HANDSHARK_SIZE
);
c1_joined
.
erase
(
digest_start
-
c1_start
,
C1_DIGEST_SIZE
);
c1_joined
.
erase
(
digest_start
-
c1_start
,
C1_DIGEST_SIZE
);
check_C1_Digest
(
digest
,
c1_joined
);
check_C1_Digest
(
digest
,
c1_joined
);
send_complex_S0S1S2
(
0
,
digest
);
send_complex_S0S1S2
(
0
,
digest
);
// InfoL << "schema0";
// InfoL << "schema0";
}
catch
(
std
::
exception
&
ex
)
{
}
catch
(
std
::
exception
&
ex
)
{
//貌似flash从来都不用schema1
//貌似flash从来都不用schema1
// WarnL << "try rtmp complex schema0 failed:" << ex.what();
// WarnL << "try rtmp complex schema0 failed:" << ex.what();
try
{
try
{
/* c1s1 schema1
/* c1s1 schema1
time: 4bytes
time: 4bytes
version: 4bytes
version: 4bytes
digest: 764bytes
digest: 764bytes
key: 764bytes
key: 764bytes
*/
*/
auto
digest
=
get_C1_digest
((
uint8_t
*
)
schema_start
,
&
digest_start
);
auto
digest
=
get_C1_digest
((
uint8_t
*
)
schema_start
,
&
digest_start
);
string
c1_joined
(
c1_start
,
C1_HANDSHARK_SIZE
);
string
c1_joined
(
c1_start
,
C1_HANDSHARK_SIZE
);
c1_joined
.
erase
(
digest_start
-
c1_start
,
C1_DIGEST_SIZE
);
c1_joined
.
erase
(
digest_start
-
c1_start
,
C1_DIGEST_SIZE
);
check_C1_Digest
(
digest
,
c1_joined
);
check_C1_Digest
(
digest
,
c1_joined
);
send_complex_S0S1S2
(
1
,
digest
);
send_complex_S0S1S2
(
1
,
digest
);
// InfoL << "schema1";
// InfoL << "schema1";
}
catch
(
std
::
exception
&
ex
)
{
}
catch
(
std
::
exception
&
ex
)
{
// WarnL << "try rtmp complex schema1 failed:" << ex.what();
// WarnL << "try rtmp complex schema1 failed:" << ex.what();
handle_C1_simple
();
handle_C1_simple
();
}
}
...
@@ -408,14 +416,16 @@ static u_int8_t FPKey[] = {
...
@@ -408,14 +416,16 @@ static u_int8_t FPKey[] = {
0x6E
,
0xEC
,
0x5D
,
0x2D
,
0x29
,
0x80
,
0x6F
,
0xAB
,
0x6E
,
0xEC
,
0x5D
,
0x2D
,
0x29
,
0x80
,
0x6F
,
0xAB
,
0x93
,
0xB8
,
0xE6
,
0x36
,
0xCF
,
0xEB
,
0x31
,
0xAE
0x93
,
0xB8
,
0xE6
,
0x36
,
0xCF
,
0xEB
,
0x31
,
0xAE
};
// 62
};
// 62
void
RtmpProtocol
::
check_C1_Digest
(
const
string
&
digest
,
const
string
&
data
){
void
RtmpProtocol
::
check_C1_Digest
(
const
string
&
digest
,
const
string
&
data
){
auto
sha256
=
openssl_HMACsha256
(
FPKey
,
C1_FPKEY_SIZE
,
data
.
data
(),
data
.
size
());
auto
sha256
=
openssl_HMACsha256
(
FPKey
,
C1_FPKEY_SIZE
,
data
.
data
(),
data
.
size
());
if
(
sha256
!=
digest
)
{
if
(
sha256
!=
digest
)
{
throw
std
::
runtime_error
(
"digest mismatched"
);
throw
std
::
runtime_error
(
"digest mismatched"
);
}
else
{
}
else
{
InfoL
<<
"check rtmp complex handshark success!"
;
InfoL
<<
"check rtmp complex handshark success!"
;
}
}
}
}
string
RtmpProtocol
::
get_C1_digest
(
const
uint8_t
*
ptr
,
char
**
digestPos
){
string
RtmpProtocol
::
get_C1_digest
(
const
uint8_t
*
ptr
,
char
**
digestPos
){
/* 764bytes digest结构
/* 764bytes digest结构
offset: 4bytes
offset: 4bytes
...
@@ -424,15 +434,16 @@ string RtmpProtocol::get_C1_digest(const uint8_t *ptr,char **digestPos){
...
@@ -424,15 +434,16 @@ string RtmpProtocol::get_C1_digest(const uint8_t *ptr,char **digestPos){
random-data: (764-4-offset-32)bytes
random-data: (764-4-offset-32)bytes
*/
*/
int
offset
=
0
;
int
offset
=
0
;
for
(
int
i
=
0
;
i
<
C1_OFFSET_SIZE
;
++
i
)
{
for
(
int
i
=
0
;
i
<
C1_OFFSET_SIZE
;
++
i
)
{
offset
+=
ptr
[
i
];
offset
+=
ptr
[
i
];
}
}
offset
%=
(
C1_SCHEMA_SIZE
-
C1_DIGEST_SIZE
-
C1_OFFSET_SIZE
);
offset
%=
(
C1_SCHEMA_SIZE
-
C1_DIGEST_SIZE
-
C1_OFFSET_SIZE
);
*
digestPos
=
(
char
*
)
ptr
+
C1_OFFSET_SIZE
+
offset
;
*
digestPos
=
(
char
*
)
ptr
+
C1_OFFSET_SIZE
+
offset
;
string
digest
(
*
digestPos
,
C1_DIGEST_SIZE
);
string
digest
(
*
digestPos
,
C1_DIGEST_SIZE
);
//DebugL << "digest offset:" << offset << ",digest:" << hexdump(digest.data(),digest.size());
//DebugL << "digest offset:" << offset << ",digest:" << hexdump(digest.data(),digest.size());
return
digest
;
return
digest
;
}
}
string
RtmpProtocol
::
get_C1_key
(
const
uint8_t
*
ptr
){
string
RtmpProtocol
::
get_C1_key
(
const
uint8_t
*
ptr
){
/* 764bytes key结构
/* 764bytes key结构
random-data: (offset)bytes
random-data: (offset)bytes
...
@@ -441,14 +452,15 @@ string RtmpProtocol::get_C1_key(const uint8_t *ptr){
...
@@ -441,14 +452,15 @@ string RtmpProtocol::get_C1_key(const uint8_t *ptr){
offset: 4bytes
offset: 4bytes
*/
*/
int
offset
=
0
;
int
offset
=
0
;
for
(
int
i
=
C1_SCHEMA_SIZE
-
C1_OFFSET_SIZE
;
i
<
C1_SCHEMA_SIZE
;
++
i
)
{
for
(
int
i
=
C1_SCHEMA_SIZE
-
C1_OFFSET_SIZE
;
i
<
C1_SCHEMA_SIZE
;
++
i
)
{
offset
+=
ptr
[
i
];
offset
+=
ptr
[
i
];
}
}
offset
%=
(
C1_SCHEMA_SIZE
-
C1_KEY_SIZE
-
C1_OFFSET_SIZE
);
offset
%=
(
C1_SCHEMA_SIZE
-
C1_KEY_SIZE
-
C1_OFFSET_SIZE
);
string
key
((
char
*
)
ptr
+
offset
,
C1_KEY_SIZE
);
string
key
((
char
*
)
ptr
+
offset
,
C1_KEY_SIZE
);
//DebugL << "key offset:" << offset << ",key:" << hexdump(key.data(),key.size());
//DebugL << "key offset:" << offset << ",key:" << hexdump(key.data(),key.size());
return
key
;
return
key
;
}
}
void
RtmpProtocol
::
send_complex_S0S1S2
(
int
schemeType
,
const
string
&
digest
){
void
RtmpProtocol
::
send_complex_S0S1S2
(
int
schemeType
,
const
string
&
digest
){
//S1S2计算参考自:https://github.com/hitYangfei/golang/blob/master/rtmpserver.go
//S1S2计算参考自:https://github.com/hitYangfei/golang/blob/master/rtmpserver.go
//发送S0
//发送S0
...
@@ -456,243 +468,253 @@ void RtmpProtocol::send_complex_S0S1S2(int schemeType,const string &digest){
...
@@ -456,243 +468,253 @@ void RtmpProtocol::send_complex_S0S1S2(int schemeType,const string &digest){
onSendRawData
(
obtainBuffer
(
&
handshake_head
,
1
));
onSendRawData
(
obtainBuffer
(
&
handshake_head
,
1
));
//S1
//S1
RtmpHandshake
s1
(
0
);
RtmpHandshake
s1
(
0
);
memcpy
(
s1
.
zero
,
"
\x04\x05\x00\x01
"
,
4
);
memcpy
(
s1
.
zero
,
"
\x04\x05\x00\x01
"
,
4
);
char
*
digestPos
;
char
*
digestPos
;
if
(
schemeType
==
0
)
{
if
(
schemeType
==
0
)
{
/* c1s1 schema0
/* c1s1 schema0
time: 4bytes
time: 4bytes
version: 4bytes
version: 4bytes
key: 764bytes
key: 764bytes
digest: 764bytes
digest: 764bytes
*/
*/
get_C1_digest
(
s1
.
random
+
C1_SCHEMA_SIZE
,
&
digestPos
);
get_C1_digest
(
s1
.
random
+
C1_SCHEMA_SIZE
,
&
digestPos
);
}
else
{
}
else
{
/* c1s1 schema1
/* c1s1 schema1
time: 4bytes
time: 4bytes
version: 4bytes
version: 4bytes
digest: 764bytes
digest: 764bytes
key: 764bytes
key: 764bytes
*/
*/
get_C1_digest
(
s1
.
random
,
&
digestPos
);
get_C1_digest
(
s1
.
random
,
&
digestPos
);
}
}
char
*
s1_start
=
(
char
*
)
&
s1
;
char
*
s1_start
=
(
char
*
)
&
s1
;
string
s1_joined
(
s1_start
,
sizeof
(
s1
));
string
s1_joined
(
s1_start
,
sizeof
(
s1
));
s1_joined
.
erase
(
digestPos
-
s1_start
,
C1_DIGEST_SIZE
);
s1_joined
.
erase
(
digestPos
-
s1_start
,
C1_DIGEST_SIZE
);
string
s1_digest
=
openssl_HMACsha256
(
FMSKey
,
S1_FMS_KEY_SIZE
,
s1_joined
.
data
(),
s1_joined
.
size
());
string
s1_digest
=
openssl_HMACsha256
(
FMSKey
,
S1_FMS_KEY_SIZE
,
s1_joined
.
data
(),
s1_joined
.
size
());
memcpy
(
digestPos
,
s1_digest
.
data
(),
s1_digest
.
size
());
memcpy
(
digestPos
,
s1_digest
.
data
(),
s1_digest
.
size
());
onSendRawData
(
obtainBuffer
((
char
*
)
&
s1
,
sizeof
(
s1
)));
onSendRawData
(
obtainBuffer
((
char
*
)
&
s1
,
sizeof
(
s1
)));
//S2
//S2
string
s2_key
=
openssl_HMACsha256
(
FMSKey
,
S2_FMS_KEY_SIZE
,
digest
.
data
(),
digest
.
size
());
string
s2_key
=
openssl_HMACsha256
(
FMSKey
,
S2_FMS_KEY_SIZE
,
digest
.
data
(),
digest
.
size
());
RtmpHandshake
s2
(
0
);
RtmpHandshake
s2
(
0
);
s2
.
random_generate
((
char
*
)
&
s2
,
8
);
s2
.
random_generate
((
char
*
)
&
s2
,
8
);
string
s2_digest
=
openssl_HMACsha256
(
s2_key
.
data
(),
s2_key
.
size
(),
&
s2
,
sizeof
(
s2
)
-
C1_DIGEST_SIZE
);
string
s2_digest
=
openssl_HMACsha256
(
s2_key
.
data
(),
s2_key
.
size
(),
&
s2
,
sizeof
(
s2
)
-
C1_DIGEST_SIZE
);
memcpy
((
char
*
)
&
s2
+
C1_HANDSHARK_SIZE
-
C1_DIGEST_SIZE
,
s2_digest
.
data
(),
C1_DIGEST_SIZE
);
memcpy
((
char
*
)
&
s2
+
C1_HANDSHARK_SIZE
-
C1_DIGEST_SIZE
,
s2_digest
.
data
(),
C1_DIGEST_SIZE
);
onSendRawData
(
obtainBuffer
((
char
*
)
&
s2
,
sizeof
(
s2
)));
onSendRawData
(
obtainBuffer
((
char
*
)
&
s2
,
sizeof
(
s2
)));
//等待C2
//等待C2
_next
Handle
=
[
this
]()
{
_next
_step_func
=
[
this
]()
{
handle_C2
();
handle_C2
();
};
};
}
}
#endif //ENABLE_OPENSSL
#endif //ENABLE_OPENSSL
void
RtmpProtocol
::
handle_C2
()
{
void
RtmpProtocol
::
handle_C2
()
{
if
(
_
strRcvB
uf
.
size
()
<
C1_HANDSHARK_SIZE
)
{
if
(
_
recv_data_b
uf
.
size
()
<
C1_HANDSHARK_SIZE
)
{
//need more data!
//need more data!
return
;
return
;
}
}
_
strRcvB
uf
.
erase
(
0
,
C1_HANDSHARK_SIZE
);
_
recv_data_b
uf
.
erase
(
0
,
C1_HANDSHARK_SIZE
);
//握手结束,进入命令模式
//握手结束,进入命令模式
if
(
!
_
strRcvB
uf
.
empty
())
{
if
(
!
_
recv_data_b
uf
.
empty
())
{
handle_rtmp
();
handle_rtmp
();
}
}
_next
Handle
=
[
this
]()
{
_next
_step_func
=
[
this
]()
{
handle_rtmp
();
handle_rtmp
();
};
};
}
}
static
const
size_t
HEADER_LENGTH
[]
=
{
12
,
8
,
4
,
1
};
void
RtmpProtocol
::
handle_rtmp
()
{
void
RtmpProtocol
::
handle_rtmp
()
{
while
(
!
_strRcvBuf
.
empty
())
{
while
(
!
_recv_data_buf
.
empty
())
{
uint8_t
flags
=
_strRcvBuf
[
0
];
int
offset
=
0
;
int
iOffset
=
0
;
uint8_t
flags
=
_recv_data_buf
[
0
];
static
const
size_t
HEADER_LENGTH
[]
=
{
12
,
8
,
4
,
1
};
size_t
header_len
=
HEADER_LENGTH
[
flags
>>
6
];
size_t
iHeaderLen
=
HEADER_LENGTH
[
flags
>>
6
];
_now_chunk_id
=
flags
&
0x3f
;
_iNowChunkID
=
flags
&
0x3f
;
switch
(
_now_chunk_id
)
{
switch
(
_iNowChunkID
)
{
case
0
:
{
case
0
:
{
//0 值表示二字节形式,并且 ID 范围 64 - 319
//0 值表示二字节形式,并且 ID 范围 64 - 319
//(第二个字节 + 64)。
//(第二个字节 + 64)。
if
(
_
strRcvB
uf
.
size
()
<
2
)
{
if
(
_
recv_data_b
uf
.
size
()
<
2
)
{
//need more data
//need more data
return
;
return
;
}
}
_iNowChunkID
=
64
+
(
uint8_t
)
(
_strRcvBuf
[
1
]);
_now_chunk_id
=
64
+
(
uint8_t
)
(
_recv_data_buf
[
1
]);
iOffset
=
1
;
offset
=
1
;
}
break
;
break
;
}
case
1
:
{
case
1
:
{
//1 值表示三字节形式,并且 ID 范围为 64 - 65599
//1 值表示三字节形式,并且 ID 范围为 64 - 65599
//((第三个字节) * 256 + 第二个字节 + 64)。
//((第三个字节) * 256 + 第二个字节 + 64)。
if
(
_
strRcvB
uf
.
size
()
<
3
)
{
if
(
_
recv_data_b
uf
.
size
()
<
3
)
{
//need more data
//need more data
return
;
return
;
}
}
_iNowChunkID
=
64
+
((
uint8_t
)
(
_strRcvBuf
[
2
])
<<
8
)
+
(
uint8_t
)
(
_strRcvBuf
[
1
]);
_now_chunk_id
=
64
+
((
uint8_t
)
(
_recv_data_buf
[
2
])
<<
8
)
+
(
uint8_t
)
(
_recv_data_buf
[
1
]);
iOffset
=
2
;
offset
=
2
;
}
break
;
break
;
default
:
}
//带有 2 值的块流 ID 被保留,用于下层协议控制消息和命令。
//带有 2 值的块流 ID 被保留,用于下层协议控制消息和命令。
break
;
default
:
break
;
}
}
if
(
_
strRcvBuf
.
size
()
<
iHeaderLen
+
iO
ffset
)
{
if
(
_
recv_data_buf
.
size
()
<
header_len
+
o
ffset
)
{
//need more data
//need more data
return
;
return
;
}
}
RtmpHeader
&
header
=
*
((
RtmpHeader
*
)
(
_strRcvBuf
.
data
()
+
iOffset
));
auto
&
chunkData
=
_mapChunkData
[
_iNowChunkID
];
RtmpHeader
&
header
=
*
((
RtmpHeader
*
)
(
_recv_data_buf
.
data
()
+
offset
));
chunkData
.
chunkId
=
_iNowChunkID
;
auto
&
chunk_data
=
_map_chunk_data
[
_now_chunk_id
];
switch
(
iHeaderLen
)
{
chunk_data
.
chunk_id
=
_now_chunk_id
;
switch
(
header_len
)
{
case
12
:
case
12
:
chunk
Data
.
hasAbsS
tamp
=
true
;
chunk
_data
.
is_abs_s
tamp
=
true
;
chunk
Data
.
streamId
=
load_le32
(
header
.
streamId
);
chunk
_data
.
stream_index
=
load_le32
(
header
.
stream_index
);
case
8
:
case
8
:
chunk
Data
.
bodySize
=
load_be24
(
header
.
bodyS
ize
);
chunk
_data
.
body_size
=
load_be24
(
header
.
body_s
ize
);
chunk
Data
.
typeId
=
header
.
typeI
d
;
chunk
_data
.
type_id
=
header
.
type_i
d
;
case
4
:
case
4
:
chunk
Data
.
tsField
=
load_be24
(
header
.
timeS
tamp
);
chunk
_data
.
ts_field
=
load_be24
(
header
.
time_s
tamp
);
}
}
auto
time
Stamp
=
chunkData
.
tsF
ield
;
auto
time
_stamp
=
chunk_data
.
ts_f
ield
;
if
(
chunk
Data
.
tsF
ield
==
0xFFFFFF
)
{
if
(
chunk
_data
.
ts_f
ield
==
0xFFFFFF
)
{
if
(
_
strRcvBuf
.
size
()
<
iHeaderLen
+
iO
ffset
+
4
)
{
if
(
_
recv_data_buf
.
size
()
<
header_len
+
o
ffset
+
4
)
{
//need more data
//need more data
return
;
return
;
}
}
time
Stamp
=
load_be32
(
_strRcvBuf
.
data
()
+
iOffset
+
iHeaderL
en
);
time
_stamp
=
load_be32
(
_recv_data_buf
.
data
()
+
offset
+
header_l
en
);
iO
ffset
+=
4
;
o
ffset
+=
4
;
}
}
if
(
chunk
Data
.
bodySize
<
chunkData
.
strBuf
.
size
())
{
if
(
chunk
_data
.
body_size
<
chunk_data
.
buffer
.
size
())
{
throw
std
::
runtime_error
(
"非法的bodySize"
);
throw
std
::
runtime_error
(
"非法的bodySize"
);
}
}
auto
iMore
=
min
(
_
iChunkLenIn
,
chunkData
.
bodySize
-
chunkData
.
strBuf
.
size
());
auto
iMore
=
min
(
_
chunk_size_in
,
chunk_data
.
body_size
-
chunk_data
.
buffer
.
size
());
if
(
_
strRcvBuf
.
size
()
<
iHeaderLen
+
iO
ffset
+
iMore
)
{
if
(
_
recv_data_buf
.
size
()
<
header_len
+
o
ffset
+
iMore
)
{
//need more data
//need more data
return
;
return
;
}
}
chunk
Data
.
strBuf
.
append
(
_strRcvBuf
,
iHeaderLen
+
iO
ffset
,
iMore
);
chunk
_data
.
buffer
.
append
(
_recv_data_buf
,
header_len
+
o
ffset
,
iMore
);
_
strRcvBuf
.
erase
(
0
,
iHeaderLen
+
iO
ffset
+
iMore
);
_
recv_data_buf
.
erase
(
0
,
header_len
+
o
ffset
+
iMore
);
if
(
chunk
Data
.
strBuf
.
size
()
==
chunkData
.
bodyS
ize
)
{
if
(
chunk
_data
.
buffer
.
size
()
==
chunk_data
.
body_s
ize
)
{
//frame is ready
//frame is ready
_
iNowStreamID
=
chunkData
.
streamId
;
_
now_stream_index
=
chunk_data
.
stream_index
;
chunk
Data
.
timeStamp
=
timeStamp
+
(
chunkData
.
hasAbsStamp
?
0
:
chunkData
.
timeS
tamp
);
chunk
_data
.
time_stamp
=
time_stamp
+
(
chunk_data
.
is_abs_stamp
?
0
:
chunk_data
.
time_s
tamp
);
if
(
chunkData
.
bodySize
)
{
if
(
chunk_data
.
body_size
)
{
handle_rtmpChunk
(
chunk
D
ata
);
handle_rtmpChunk
(
chunk
_d
ata
);
}
}
chunk
Data
.
strBuf
.
clear
();
chunk
_data
.
buffer
.
clear
();
chunk
Data
.
hasAbsS
tamp
=
false
;
chunk
_data
.
is_abs_s
tamp
=
false
;
}
}
}
}
}
}
void
RtmpProtocol
::
handle_rtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
{
void
RtmpProtocol
::
handle_rtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
{
switch
(
chunk
Data
.
typeI
d
)
{
switch
(
chunk
_data
.
type_i
d
)
{
case
MSG_ACK
:
{
case
MSG_ACK
:
{
if
(
chunk
Data
.
strBuf
.
size
()
<
4
)
{
if
(
chunk
_data
.
buffer
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"MSG_ACK: Not enough data"
);
throw
std
::
runtime_error
(
"MSG_ACK: Not enough data"
);
}
}
//auto bytePeerRecv = load_be32(&chunk
Data.strBuf
[0]);
//auto bytePeerRecv = load_be32(&chunk
_data.buffer
[0]);
//TraceL << "MSG_ACK:" << bytePeerRecv;
//TraceL << "MSG_ACK:" << bytePeerRecv;
}
break
;
break
;
}
case
MSG_SET_CHUNK
:
{
case
MSG_SET_CHUNK
:
{
if
(
chunk
Data
.
strBuf
.
size
()
<
4
)
{
if
(
chunk
_data
.
buffer
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"MSG_SET_CHUNK :Not enough data"
);
throw
std
::
runtime_error
(
"MSG_SET_CHUNK :Not enough data"
);
}
}
_iChunkLenIn
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
_chunk_size_in
=
load_be32
(
&
chunk_data
.
buffer
[
0
]);
TraceL
<<
"MSG_SET_CHUNK:"
<<
_iChunkLenIn
;
TraceL
<<
"MSG_SET_CHUNK:"
<<
_chunk_size_in
;
}
break
;
break
;
}
case
MSG_USER_CONTROL
:
{
case
MSG_USER_CONTROL
:
{
//user control message
//user control message
if
(
chunk
Data
.
strBuf
.
size
()
<
2
)
{
if
(
chunk
_data
.
buffer
.
size
()
<
2
)
{
throw
std
::
runtime_error
(
"MSG_USER_CONTROL: Not enough data."
);
throw
std
::
runtime_error
(
"MSG_USER_CONTROL: Not enough data."
);
}
}
uint16_t
event_type
=
load_be16
(
&
chunk
Data
.
strBuf
[
0
]);
uint16_t
event_type
=
load_be16
(
&
chunk
_data
.
buffer
[
0
]);
chunk
Data
.
strBuf
.
erase
(
0
,
2
);
chunk
_data
.
buffer
.
erase
(
0
,
2
);
switch
(
event_type
)
{
switch
(
event_type
)
{
case
CONTROL_PING_REQUEST
:
{
case
CONTROL_PING_REQUEST
:
{
if
(
chunk
Data
.
strBuf
.
size
()
<
4
)
{
if
(
chunk
_data
.
buffer
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"CONTROL_PING_REQUEST: Not enough data."
);
throw
std
::
runtime_error
(
"CONTROL_PING_REQUEST: Not enough data."
);
}
}
uint32_t
timeStamp
=
load_be32
(
&
chunk
Data
.
strBuf
[
0
]);
uint32_t
timeStamp
=
load_be32
(
&
chunk
_data
.
buffer
[
0
]);
//TraceL << "CONTROL_PING_REQUEST:" << time
S
tamp;
//TraceL << "CONTROL_PING_REQUEST:" << time
_s
tamp;
sendUserControl
(
CONTROL_PING_RESPONSE
,
timeStamp
);
sendUserControl
(
CONTROL_PING_RESPONSE
,
timeStamp
);
}
break
;
break
;
}
case
CONTROL_PING_RESPONSE
:
{
case
CONTROL_PING_RESPONSE
:
{
if
(
chunkData
.
strBuf
.
size
()
<
4
)
{
if
(
chunk_data
.
buffer
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"CONTROL_PING_RESPONSE: Not enough data."
);
throw
std
::
runtime_error
(
"CONTROL_PING_RESPONSE: Not enough data."
);
}
}
//uint32_t timeStamp = load_be32(&chunkData.strBuf[0]);
//uint32_t time_stamp = load_be32(&chunk_data.buffer[0]);
//TraceL << "CONTROL_PING_RESPONSE:" << timeStamp;
//TraceL << "CONTROL_PING_RESPONSE:" << time_stamp;
}
break
;
break
;
}
case
CONTROL_STREAM_BEGIN
:
{
case
CONTROL_STREAM_BEGIN
:
{
//开始播放
//开始播放
if
(
chunkData
.
strBuf
.
size
()
<
4
)
{
if
(
chunk_data
.
buffer
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"CONTROL_STREAM_BEGIN: Not enough data."
);
throw
std
::
runtime_error
(
"CONTROL_STREAM_BEGIN: Not enough data."
);
}
}
uint32_t
stramId
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
uint32_t
stream_index
=
load_be32
(
&
chunk_data
.
buffer
[
0
]);
onStreamBegin
(
stramId
);
onStreamBegin
(
stream_index
);
TraceL
<<
"CONTROL_STREAM_BEGIN:"
<<
stramId
;
TraceL
<<
"CONTROL_STREAM_BEGIN:"
<<
stream_index
;
}
break
;
break
;
}
case
CONTROL_STREAM_EOF
:
{
case
CONTROL_STREAM_EOF
:
{
//暂停
//暂停
if
(
chunkData
.
strBuf
.
size
()
<
4
)
{
if
(
chunk_data
.
buffer
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"CONTROL_STREAM_EOF: Not enough data."
);
throw
std
::
runtime_error
(
"CONTROL_STREAM_EOF: Not enough data."
);
}
}
uint32_t
stramId
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
uint32_t
stream_index
=
load_be32
(
&
chunk_data
.
buffer
[
0
]);
onStreamEof
(
stramId
);
onStreamEof
(
stream_index
);
TraceL
<<
"CONTROL_STREAM_EOF:"
<<
stramId
;
TraceL
<<
"CONTROL_STREAM_EOF:"
<<
stream_index
;
}
break
;
break
;
}
case
CONTROL_STREAM_DRY
:
{
case
CONTROL_STREAM_DRY
:
{
//停止播放
//停止播放
if
(
chunkData
.
strBuf
.
size
()
<
4
)
{
if
(
chunk_data
.
buffer
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"CONTROL_STREAM_DRY: Not enough data."
);
throw
std
::
runtime_error
(
"CONTROL_STREAM_DRY: Not enough data."
);
}
}
uint32_t
stramId
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
uint32_t
stream_index
=
load_be32
(
&
chunk_data
.
buffer
[
0
]);
onStreamDry
(
stramId
);
onStreamDry
(
stream_index
);
TraceL
<<
"CONTROL_STREAM_DRY:"
<<
stramId
;
TraceL
<<
"CONTROL_STREAM_DRY:"
<<
stream_index
;
}
break
;
default
:
//WarnL << "unhandled user control:" << event_type;
break
;
break
;
}
}
default
:
/*WarnL << "unhandled user control:" << event_type; */
break
;
}
}
break
;
break
;
}
case
MSG_WIN_SIZE
:
{
case
MSG_WIN_SIZE
:
{
_ui32WinSize
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
_windows_size
=
load_be32
(
&
chunk_data
.
buffer
[
0
]);
TraceL
<<
"MSG_WIN_SIZE:"
<<
_ui32WinSize
;
TraceL
<<
"MSG_WIN_SIZE:"
<<
_windows_size
;
}
break
;
break
;
case
MSG_SET_PEER_BW
:
{
_ui32Bandwidth
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
_ui8LimitType
=
chunkData
.
strBuf
[
4
];
TraceL
<<
"MSG_SET_PEER_BW:"
<<
_ui32WinSize
;
}
}
case
MSG_SET_PEER_BW
:
{
_bandwidth
=
load_be32
(
&
chunk_data
.
buffer
[
0
]);
_band_limit_type
=
chunk_data
.
buffer
[
4
];
TraceL
<<
"MSG_SET_PEER_BW:"
<<
_windows_size
;
break
;
break
;
}
case
MSG_AGGREGATE
:
{
case
MSG_AGGREGATE
:
{
auto
ptr
=
(
uint8_t
*
)
chunkData
.
strBuf
.
data
();
auto
ptr
=
(
uint8_t
*
)
chunk_data
.
buffer
.
data
();
auto
ptr_tail
=
ptr
+
chunk
Data
.
strBuf
.
length
()
;
auto
ptr_tail
=
ptr
+
chunk
_data
.
buffer
.
length
()
;
while
(
ptr
+
8
+
3
<
ptr_tail
)
{
while
(
ptr
+
8
+
3
<
ptr_tail
)
{
auto
type
=
*
ptr
;
auto
type
=
*
ptr
;
ptr
+=
1
;
ptr
+=
1
;
auto
size
=
load_be24
(
ptr
);
auto
size
=
load_be24
(
ptr
);
...
@@ -701,56 +723,28 @@ void RtmpProtocol::handle_rtmpChunk(RtmpPacket& chunkData) {
...
@@ -701,56 +723,28 @@ void RtmpProtocol::handle_rtmpChunk(RtmpPacket& chunkData) {
ptr
+=
3
;
ptr
+=
3
;
ts
|=
(
*
ptr
<<
24
);
ts
|=
(
*
ptr
<<
24
);
ptr
+=
1
;
ptr
+=
1
;
//参考ffmpeg忽略了3个字节
/**
* while (next - pkt->data < pkt->size - RTMP_HEADER) {
type = bytestream_get_byte(&next);
size = bytestream_get_be24(&next);
cts = bytestream_get_be24(&next);
cts |= bytestream_get_byte(&next) << 24;
if (!pts)
pts = cts;
ts += cts - pts;
pts = cts;
if (size + 3 + 4 > pkt->data + pkt->size - next)
break;
bytestream_put_byte(&p, type);
bytestream_put_be24(&p, size);
bytestream_put_be24(&p, ts);
bytestream_put_byte(&p, ts >> 24);
memcpy(p, next, size + 3 + 4);
p += size + 3;
bytestream_put_be32(&p, size + RTMP_HEADER);
next += size + 3 + 4;
}
*/
ptr
+=
3
;
ptr
+=
3
;
//参考FFmpeg多拷贝了4个字节
//参考FFmpeg多拷贝了4个字节
size
+=
4
;
size
+=
4
;
if
(
ptr
+
size
>
ptr_tail
){
if
(
ptr
+
size
>
ptr_tail
)
{
// ErrorL << ptr + size << " " << ptr_tail << " " << ptr_tail - ptr - size;
break
;
break
;
}
}
// DebugL << (int)type << " " << size << " " << ts << " " << chunkData.timeStamp << " " << ptr_tail - ptr;
RtmpPacket
sub_packet
;
RtmpPacket
sub_packet
;
sub_packet
.
buffer
.
resize
(
size
);
sub_packet
.
strBuf
.
resize
(
size
);
memcpy
((
char
*
)
sub_packet
.
buffer
.
data
(),
ptr
,
size
);
memcpy
((
char
*
)
sub_packet
.
strBuf
.
data
(),
ptr
,
size
);
sub_packet
.
type_id
=
type
;
sub_packet
.
typeId
=
type
;
sub_packet
.
body_size
=
size
;
sub_packet
.
bodySize
=
size
;
sub_packet
.
time_stamp
=
ts
;
sub_packet
.
timeStamp
=
ts
;
sub_packet
.
stream_index
=
chunk_data
.
stream_index
;
sub_packet
.
streamId
=
chunkData
.
streamId
;
sub_packet
.
chunk_id
=
chunk_data
.
chunk_id
;
sub_packet
.
chunkId
=
chunkData
.
chunkId
;
handle_rtmpChunk
(
sub_packet
);
handle_rtmpChunk
(
sub_packet
);
ptr
+=
size
;
ptr
+=
size
;
}
}
// InfoL << ptr_tail - ptr;
}
break
;
default
:
onRtmpChunk
(
chunkData
);
break
;
break
;
}
}
default
:
onRtmpChunk
(
chunk_data
);
break
;
}
}
}
BufferRaw
::
Ptr
RtmpProtocol
::
obtainBuffer
()
{
BufferRaw
::
Ptr
RtmpProtocol
::
obtainBuffer
()
{
...
@@ -759,7 +753,7 @@ BufferRaw::Ptr RtmpProtocol::obtainBuffer() {
...
@@ -759,7 +753,7 @@ BufferRaw::Ptr RtmpProtocol::obtainBuffer() {
BufferRaw
::
Ptr
RtmpProtocol
::
obtainBuffer
(
const
void
*
data
,
int
len
)
{
BufferRaw
::
Ptr
RtmpProtocol
::
obtainBuffer
(
const
void
*
data
,
int
len
)
{
auto
buffer
=
obtainBuffer
();
auto
buffer
=
obtainBuffer
();
buffer
->
assign
((
const
char
*
)
data
,
len
);
buffer
->
assign
((
const
char
*
)
data
,
len
);
return
buffer
;
return
buffer
;
}
}
...
...
src/Rtmp/RtmpProtocol.h
查看文件 @
fbd711a6
...
@@ -31,45 +31,42 @@ class RtmpProtocol {
...
@@ -31,45 +31,42 @@ class RtmpProtocol {
public
:
public
:
RtmpProtocol
();
RtmpProtocol
();
virtual
~
RtmpProtocol
();
virtual
~
RtmpProtocol
();
void
onParseRtmp
(
const
char
*
data
,
int
size
);
//作为客户端发送c0c1,等待s0s1s2并且回调
//作为客户端发送c0c1,等待s0s1s2并且回调
void
startClientSession
(
const
function
<
void
()
>
&
cb
);
void
startClientSession
(
const
function
<
void
()
>
&
cb
);
void
onParseRtmp
(
const
char
*
pcRawData
,
int
iSize
);
void
reset
();
protected
:
protected
:
virtual
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
=
0
;
virtual
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
=
0
;
virtual
void
onRtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
=
0
;
virtual
void
onRtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
=
0
;
virtual
void
onStreamBegin
(
uint32_t
ui32StreamId
){
virtual
void
onStreamBegin
(
uint32_t
stream_index
){
_
ui32StreamId
=
ui32StreamId
;
_
stream_index
=
stream_index
;
}
}
virtual
void
onStreamEof
(
uint32_t
ui32StreamId
){};
virtual
void
onStreamEof
(
uint32_t
stream_index
){};
virtual
void
onStreamDry
(
uint32_t
ui32StreamId
){};
virtual
void
onStreamDry
(
uint32_t
stream_index
){};
protected
:
void
sendAcknowledgement
(
uint32_t
ui32Size
);
void
sendAcknowledgementSize
(
uint32_t
ui32Size
);
void
sendPeerBandwidth
(
uint32_t
ui32Size
);
void
sendChunkSize
(
uint32_t
ui32Size
);
void
sendPingRequest
(
uint32_t
ui32TimeStamp
=
::
time
(
NULL
));
void
sendPingResponse
(
uint32_t
ui32TimeStamp
=
::
time
(
NULL
));
void
sendSetBufferLength
(
uint32_t
ui32StreamId
,
uint32_t
ui32Length
);
void
sendUserControl
(
uint16_t
ui16EventType
,
uint32_t
ui32EventData
);
void
sendUserControl
(
uint16_t
ui16EventType
,
const
string
&
strEventData
);
void
sendInvoke
(
const
string
&
strCmd
,
const
AMFValue
&
val
);
void
sendRequest
(
int
iCmd
,
const
string
&
str
);
void
sendResponse
(
int
iType
,
const
string
&
str
);
void
sendRtmp
(
uint8_t
ui8Type
,
uint32_t
ui32StreamId
,
const
std
::
string
&
strBuf
,
uint32_t
ui32TimeStamp
,
int
iChunkID
);
void
sendRtmp
(
uint8_t
ui8Type
,
uint32_t
ui32StreamId
,
const
Buffer
::
Ptr
&
buffer
,
uint32_t
ui32TimeStamp
,
int
iChunkID
);
protected
:
protected
:
int
_iReqID
=
0
;
void
reset
();
uint32_t
_ui32StreamId
=
STREAM_CONTROL
;
BufferRaw
::
Ptr
obtainBuffer
();
int
_iNowStreamID
=
0
;
BufferRaw
::
Ptr
obtainBuffer
(
const
void
*
data
,
int
len
);
int
_iNowChunkID
=
0
;
bool
_bDataStarted
=
false
;
void
sendAcknowledgement
(
uint32_t
size
);
inline
BufferRaw
::
Ptr
obtainBuffer
();
void
sendAcknowledgementSize
(
uint32_t
size
);
inline
BufferRaw
::
Ptr
obtainBuffer
(
const
void
*
data
,
int
len
);
void
sendPeerBandwidth
(
uint32_t
size
);
//ResourcePool<BufferRaw,MAX_SEND_PKT> _bufferPool;
void
sendChunkSize
(
uint32_t
size
);
void
sendPingRequest
(
uint32_t
ti
=
::
time
(
NULL
));
void
sendPingResponse
(
uint32_t
time_stamp
=
::
time
(
NULL
));
void
sendSetBufferLength
(
uint32_t
stream_index
,
uint32_t
len
);
void
sendUserControl
(
uint16_t
event_type
,
uint32_t
event_data
);
void
sendUserControl
(
uint16_t
event_type
,
const
string
&
event_data
);
void
sendInvoke
(
const
string
&
cmd
,
const
AMFValue
&
val
);
void
sendRequest
(
int
cmd
,
const
string
&
str
);
void
sendResponse
(
int
type
,
const
string
&
str
);
void
sendRtmp
(
uint8_t
type
,
uint32_t
stream_index
,
const
std
::
string
&
buffer
,
uint32_t
stamp
,
int
chunk_id
);
void
sendRtmp
(
uint8_t
type
,
uint32_t
stream_index
,
const
Buffer
::
Ptr
&
buffer
,
uint32_t
stamp
,
int
chunk_id
);
private
:
private
:
void
handle_S0S1S2
(
const
function
<
void
()
>
&
cb
);
void
handle_S0S1S2
(
const
function
<
void
()
>
&
func
);
void
handle_C0C1
();
void
handle_C0C1
();
void
handle_C1_simple
();
void
handle_C1_simple
();
#ifdef ENABLE_OPENSSL
#ifdef ENABLE_OPENSSL
...
@@ -82,26 +79,32 @@ private:
...
@@ -82,26 +79,32 @@ private:
void
handle_C2
();
void
handle_C2
();
void
handle_rtmp
();
void
handle_rtmp
();
void
handle_rtmpChunk
(
RtmpPacket
&
chunkData
);
void
handle_rtmpChunk
(
RtmpPacket
&
chunk_data
);
protected
:
int
_send_req_id
=
0
;
uint32_t
_stream_index
=
STREAM_CONTROL
;
private
:
private
:
int
_now_stream_index
=
0
;
int
_now_chunk_id
=
0
;
bool
_data_started
=
false
;
////////////ChunkSize////////////
////////////ChunkSize////////////
size_t
_
iChunkLenI
n
=
DEFAULT_CHUNK_LEN
;
size_t
_
chunk_size_i
n
=
DEFAULT_CHUNK_LEN
;
size_t
_
iChunkLenO
ut
=
DEFAULT_CHUNK_LEN
;
size_t
_
chunk_size_o
ut
=
DEFAULT_CHUNK_LEN
;
////////////Acknowledgement////////////
////////////Acknowledgement////////////
uint32_t
_
ui32ByteS
ent
=
0
;
uint32_t
_
bytes_s
ent
=
0
;
uint32_t
_
ui32LastSen
t
=
0
;
uint32_t
_
bytes_sent_las
t
=
0
;
uint32_t
_
ui32WinS
ize
=
0
;
uint32_t
_
windows_s
ize
=
0
;
///////////PeerBandwidth///////////
///////////PeerBandwidth///////////
uint32_t
_ui32Bandwidth
=
2500000
;
uint32_t
_bandwidth
=
2500000
;
uint8_t
_ui8LimitType
=
2
;
uint8_t
_band_limit_type
=
2
;
////////////Chunk////////////
unordered_map
<
int
,
RtmpPacket
>
_mapChunkData
;
//////////Rtmp parser//////////
//////////Rtmp parser//////////
string
_strRcvBuf
;
string
_recv_data_buf
;
function
<
void
()
>
_nextHandle
;
function
<
void
()
>
_next_step_func
;
////////////Chunk////////////
unordered_map
<
int
,
RtmpPacket
>
_map_chunk_data
;
};
};
}
/* namespace mediakit */
}
/* namespace mediakit */
#endif
/* SRC_RTMP_RTMPPROTOCOL_H_ */
#endif
/* SRC_RTMP_RTMPPROTOCOL_H_ */
src/Rtmp/RtmpPusher.cpp
查看文件 @
fbd711a6
...
@@ -164,13 +164,13 @@ inline void RtmpPusher::send_createStream() {
...
@@ -164,13 +164,13 @@ inline void RtmpPusher::send_createStream() {
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
//TraceL << "createStream result";
//TraceL << "createStream result";
dec
.
load
<
AMFValue
>
();
dec
.
load
<
AMFValue
>
();
_
ui32StreamId
=
dec
.
load
<
int
>
();
_
stream_index
=
dec
.
load
<
int
>
();
send_publish
();
send_publish
();
});
});
}
}
inline
void
RtmpPusher
::
send_publish
()
{
inline
void
RtmpPusher
::
send_publish
()
{
AMFEncoder
enc
;
AMFEncoder
enc
;
enc
<<
"publish"
<<
++
_
iReqID
<<
nullptr
<<
_strStream
<<
_strApp
;
enc
<<
"publish"
<<
++
_
send_req_id
<<
nullptr
<<
_strStream
<<
_strApp
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
sendRequest
(
MSG_CMD
,
enc
.
data
());
addOnStatusCB
([
this
](
AMFValue
&
val
)
{
addOnStatusCB
([
this
](
AMFValue
&
val
)
{
...
@@ -195,7 +195,7 @@ inline void RtmpPusher::send_metaData(){
...
@@ -195,7 +195,7 @@ inline void RtmpPusher::send_metaData(){
sendRequest
(
MSG_DATA
,
enc
.
data
());
sendRequest
(
MSG_DATA
,
enc
.
data
());
src
->
getConfigFrame
([
&
](
const
RtmpPacket
::
Ptr
&
pkt
){
src
->
getConfigFrame
([
&
](
const
RtmpPacket
::
Ptr
&
pkt
){
sendRtmp
(
pkt
->
type
Id
,
_ui32StreamId
,
pkt
,
pkt
->
timeStamp
,
pkt
->
chunkI
d
);
sendRtmp
(
pkt
->
type
_id
,
_stream_index
,
pkt
,
pkt
->
time_stamp
,
pkt
->
chunk_i
d
);
});
});
_pRtmpReader
=
src
->
getRing
()
->
attach
(
getPoller
());
_pRtmpReader
=
src
->
getRing
()
->
attach
(
getPoller
());
...
@@ -213,7 +213,7 @@ inline void RtmpPusher::send_metaData(){
...
@@ -213,7 +213,7 @@ inline void RtmpPusher::send_metaData(){
if
(
++
i
==
size
){
if
(
++
i
==
size
){
strongSelf
->
setSendFlushFlag
(
true
);
strongSelf
->
setSendFlushFlag
(
true
);
}
}
strongSelf
->
sendRtmp
(
rtmp
->
type
Id
,
strongSelf
->
_ui32StreamId
,
rtmp
,
rtmp
->
timeStamp
,
rtmp
->
chunkI
d
);
strongSelf
->
sendRtmp
(
rtmp
->
type
_id
,
strongSelf
->
_stream_index
,
rtmp
,
rtmp
->
time_stamp
,
rtmp
->
chunk_i
d
);
});
});
});
});
_pRtmpReader
->
setDetachCB
([
weakSelf
](){
_pRtmpReader
->
setDetachCB
([
weakSelf
](){
...
@@ -275,7 +275,7 @@ void RtmpPusher::onCmd_onStatus(AMFDecoder &dec) {
...
@@ -275,7 +275,7 @@ void RtmpPusher::onCmd_onStatus(AMFDecoder &dec) {
}
}
void
RtmpPusher
::
onRtmpChunk
(
RtmpPacket
&
chunkData
)
{
void
RtmpPusher
::
onRtmpChunk
(
RtmpPacket
&
chunkData
)
{
switch
(
chunkData
.
type
I
d
)
{
switch
(
chunkData
.
type
_i
d
)
{
case
MSG_CMD
:
case
MSG_CMD
:
case
MSG_CMD3
:
{
case
MSG_CMD3
:
{
typedef
void
(
RtmpPusher
::*
rtmpCMDHandle
)(
AMFDecoder
&
dec
);
typedef
void
(
RtmpPusher
::*
rtmpCMDHandle
)(
AMFDecoder
&
dec
);
...
@@ -284,9 +284,9 @@ void RtmpPusher::onRtmpChunk(RtmpPacket &chunkData) {
...
@@ -284,9 +284,9 @@ void RtmpPusher::onRtmpChunk(RtmpPacket &chunkData) {
g_mapCmd
.
emplace
(
"_error"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"_error"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"_result"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"_result"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"onStatus"
,
&
RtmpPusher
::
onCmd_onStatus
);
g_mapCmd
.
emplace
(
"onStatus"
,
&
RtmpPusher
::
onCmd_onStatus
);
}
,
[]()
{}
);
});
AMFDecoder
dec
(
chunkData
.
strBuf
,
0
);
AMFDecoder
dec
(
chunkData
.
buffer
,
0
);
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
auto
it
=
g_mapCmd
.
find
(
type
);
auto
it
=
g_mapCmd
.
find
(
type
);
if
(
it
!=
g_mapCmd
.
end
()){
if
(
it
!=
g_mapCmd
.
end
()){
...
@@ -298,7 +298,7 @@ void RtmpPusher::onRtmpChunk(RtmpPacket &chunkData) {
...
@@ -298,7 +298,7 @@ void RtmpPusher::onRtmpChunk(RtmpPacket &chunkData) {
}
}
break
;
break
;
default
:
default
:
//WarnL << "unhandled message:" << (int) chunkData.type
Id << hexdump(chunkData.strBuf.data(), chunkData.strBuf
.size());
//WarnL << "unhandled message:" << (int) chunkData.type
_id << hexdump(chunkData.buffer.data(), chunkData.buffer
.size());
break
;
break
;
}
}
}
}
...
...
src/Rtmp/RtmpPusher.h
查看文件 @
fbd711a6
...
@@ -52,7 +52,7 @@ private:
...
@@ -52,7 +52,7 @@ private:
template
<
typename
FUN
>
template
<
typename
FUN
>
inline
void
addOnResultCB
(
const
FUN
&
fun
)
{
inline
void
addOnResultCB
(
const
FUN
&
fun
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
_mapOnResultCB
.
emplace
(
_
iReqID
,
fun
);
_mapOnResultCB
.
emplace
(
_
send_req_id
,
fun
);
}
}
template
<
typename
FUN
>
template
<
typename
FUN
>
inline
void
addOnStatusCB
(
const
FUN
&
fun
)
{
inline
void
addOnStatusCB
(
const
FUN
&
fun
)
{
...
...
src/Rtmp/RtmpSession.cpp
查看文件 @
fbd711a6
...
@@ -13,12 +13,12 @@
...
@@ -13,12 +13,12 @@
#include "Util/onceToken.h"
#include "Util/onceToken.h"
namespace
mediakit
{
namespace
mediakit
{
RtmpSession
::
RtmpSession
(
const
Socket
::
Ptr
&
pSock
)
:
TcpSession
(
pS
ock
)
{
RtmpSession
::
RtmpSession
(
const
Socket
::
Ptr
&
sock
)
:
TcpSession
(
s
ock
)
{
DebugP
(
this
);
DebugP
(
this
);
GET_CONFIG
(
uint32_t
,
keep_alive_sec
,
Rtmp
::
kKeepAliveSecond
);
GET_CONFIG
(
uint32_t
,
keep_alive_sec
,
Rtmp
::
kKeepAliveSecond
);
pS
ock
->
setSendTimeOutSecond
(
keep_alive_sec
);
s
ock
->
setSendTimeOutSecond
(
keep_alive_sec
);
//起始接收buffer缓存设置为4K,节省内存
//起始接收buffer缓存设置为4K,节省内存
pS
ock
->
setReadBuffer
(
std
::
make_shared
<
BufferRaw
>
(
4
*
1024
));
s
ock
->
setReadBuffer
(
std
::
make_shared
<
BufferRaw
>
(
4
*
1024
));
}
}
RtmpSession
::~
RtmpSession
()
{
RtmpSession
::~
RtmpSession
()
{
...
@@ -26,20 +26,20 @@ RtmpSession::~RtmpSession() {
...
@@ -26,20 +26,20 @@ RtmpSession::~RtmpSession() {
}
}
void
RtmpSession
::
onError
(
const
SockException
&
err
)
{
void
RtmpSession
::
onError
(
const
SockException
&
err
)
{
bool
isPlayer
=
!
_p
PublisherS
rc
;
bool
isPlayer
=
!
_p
ublisher_s
rc
;
uint64_t
duration
=
_ticker
.
createdTime
()
/
1000
;
uint64_t
duration
=
_ticker
.
createdTime
()
/
1000
;
WarnP
(
this
)
<<
(
isPlayer
?
"RTMP播放器("
:
"RTMP推流器("
)
WarnP
(
this
)
<<
(
isPlayer
?
"RTMP播放器("
:
"RTMP推流器("
)
<<
_media
I
nfo
.
_vhost
<<
"/"
<<
_media
_i
nfo
.
_vhost
<<
"/"
<<
_media
I
nfo
.
_app
<<
"/"
<<
_media
_i
nfo
.
_app
<<
"/"
<<
_media
I
nfo
.
_streamid
<<
_media
_i
nfo
.
_streamid
<<
")断开:"
<<
err
.
what
()
<<
")断开:"
<<
err
.
what
()
<<
",耗时(s):"
<<
duration
;
<<
",耗时(s):"
<<
duration
;
//流量统计事件广播
//流量统计事件广播
GET_CONFIG
(
uint32_t
,
iFlowThreshold
,
General
::
kFlowThreshold
);
GET_CONFIG
(
uint32_t
,
iFlowThreshold
,
General
::
kFlowThreshold
);
if
(
_
ui64TotalB
ytes
>
iFlowThreshold
*
1024
){
if
(
_
total_b
ytes
>
iFlowThreshold
*
1024
){
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastFlowReport
,
_media
Info
,
_ui64TotalB
ytes
,
duration
,
isPlayer
,
static_cast
<
SockInfo
&>
(
*
this
));
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastFlowReport
,
_media
_info
,
_total_b
ytes
,
duration
,
isPlayer
,
static_cast
<
SockInfo
&>
(
*
this
));
}
}
}
}
...
@@ -48,11 +48,11 @@ void RtmpSession::onManager() {
...
@@ -48,11 +48,11 @@ void RtmpSession::onManager() {
GET_CONFIG
(
uint32_t
,
keep_alive_sec
,
Rtmp
::
kKeepAliveSecond
);
GET_CONFIG
(
uint32_t
,
keep_alive_sec
,
Rtmp
::
kKeepAliveSecond
);
if
(
_ticker
.
createdTime
()
>
handshake_sec
*
1000
)
{
if
(
_ticker
.
createdTime
()
>
handshake_sec
*
1000
)
{
if
(
!
_
pRingReader
&&
!
_pPublisherS
rc
)
{
if
(
!
_
ring_reader
&&
!
_publisher_s
rc
)
{
shutdown
(
SockException
(
Err_timeout
,
"illegal connection"
));
shutdown
(
SockException
(
Err_timeout
,
"illegal connection"
));
}
}
}
}
if
(
_p
PublisherS
rc
)
{
if
(
_p
ublisher_s
rc
)
{
//publisher
//publisher
if
(
_ticker
.
elapsedTime
()
>
keep_alive_sec
*
1000
)
{
if
(
_ticker
.
elapsedTime
()
>
keep_alive_sec
*
1000
)
{
shutdown
(
SockException
(
Err_timeout
,
"recv data from rtmp pusher timeout"
));
shutdown
(
SockException
(
Err_timeout
,
"recv data from rtmp pusher timeout"
));
...
@@ -60,22 +60,22 @@ void RtmpSession::onManager() {
...
@@ -60,22 +60,22 @@ void RtmpSession::onManager() {
}
}
}
}
void
RtmpSession
::
onRecv
(
const
Buffer
::
Ptr
&
pB
uf
)
{
void
RtmpSession
::
onRecv
(
const
Buffer
::
Ptr
&
b
uf
)
{
_ticker
.
resetTime
();
_ticker
.
resetTime
();
try
{
try
{
_
ui64TotalBytes
+=
pB
uf
->
size
();
_
total_bytes
+=
b
uf
->
size
();
onParseRtmp
(
pBuf
->
data
(),
pB
uf
->
size
());
onParseRtmp
(
buf
->
data
(),
b
uf
->
size
());
}
catch
(
exception
&
e
)
{
}
catch
(
exception
&
e
x
)
{
shutdown
(
SockException
(
Err_shutdown
,
e
.
what
()));
shutdown
(
SockException
(
Err_shutdown
,
e
x
.
what
()));
}
}
}
}
void
RtmpSession
::
onCmd_connect
(
AMFDecoder
&
dec
)
{
void
RtmpSession
::
onCmd_connect
(
AMFDecoder
&
dec
)
{
auto
params
=
dec
.
load
<
AMFValue
>
();
auto
params
=
dec
.
load
<
AMFValue
>
();
double
amf
V
er
=
0
;
double
amf
_v
er
=
0
;
AMFValue
objectEncoding
=
params
[
"objectEncoding"
];
AMFValue
objectEncoding
=
params
[
"objectEncoding"
];
if
(
objectEncoding
){
if
(
objectEncoding
){
amf
V
er
=
objectEncoding
.
as_number
();
amf
_v
er
=
objectEncoding
.
as_number
();
}
}
///////////set chunk size////////////////
///////////set chunk size////////////////
sendChunkSize
(
60000
);
sendChunkSize
(
60000
);
...
@@ -84,11 +84,11 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
...
@@ -84,11 +84,11 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
///////////set peerBandwidth////////////////
///////////set peerBandwidth////////////////
sendPeerBandwidth
(
5000000
);
sendPeerBandwidth
(
5000000
);
_media
I
nfo
.
_app
=
params
[
"app"
].
as_string
();
_media
_i
nfo
.
_app
=
params
[
"app"
].
as_string
();
_
strTcU
rl
=
params
[
"tcUrl"
].
as_string
();
_
tc_u
rl
=
params
[
"tcUrl"
].
as_string
();
if
(
_
strTcU
rl
.
empty
()){
if
(
_
tc_u
rl
.
empty
()){
//defaultVhost:默认vhost
//defaultVhost:默认vhost
_
strTcUrl
=
string
(
RTMP_SCHEMA
)
+
"://"
+
DEFAULT_VHOST
+
"/"
+
_mediaI
nfo
.
_app
;
_
tc_url
=
string
(
RTMP_SCHEMA
)
+
"://"
+
DEFAULT_VHOST
+
"/"
+
_media_i
nfo
.
_app
;
}
}
bool
ok
=
true
;
//(app == APP_NAME);
bool
ok
=
true
;
//(app == APP_NAME);
AMFValue
version
(
AMF_OBJECT
);
AMFValue
version
(
AMF_OBJECT
);
...
@@ -98,10 +98,10 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
...
@@ -98,10 +98,10 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"code"
,
ok
?
"NetConnection.Connect.Success"
:
"NetConnection.Connect.InvalidApp"
);
status
.
set
(
"code"
,
ok
?
"NetConnection.Connect.Success"
:
"NetConnection.Connect.InvalidApp"
);
status
.
set
(
"description"
,
ok
?
"Connection succeeded."
:
"InvalidApp."
);
status
.
set
(
"description"
,
ok
?
"Connection succeeded."
:
"InvalidApp."
);
status
.
set
(
"objectEncoding"
,
amf
V
er
);
status
.
set
(
"objectEncoding"
,
amf
_v
er
);
sendReply
(
ok
?
"_result"
:
"_error"
,
version
,
status
);
sendReply
(
ok
?
"_result"
:
"_error"
,
version
,
status
);
if
(
!
ok
)
{
if
(
!
ok
)
{
throw
std
::
runtime_error
(
"Unsupported application: "
+
_media
I
nfo
.
_app
);
throw
std
::
runtime_error
(
"Unsupported application: "
+
_media
_i
nfo
.
_app
);
}
}
AMFEncoder
invoke
;
AMFEncoder
invoke
;
...
@@ -114,75 +114,75 @@ void RtmpSession::onCmd_createStream(AMFDecoder &dec) {
...
@@ -114,75 +114,75 @@ void RtmpSession::onCmd_createStream(AMFDecoder &dec) {
}
}
void
RtmpSession
::
onCmd_publish
(
AMFDecoder
&
dec
)
{
void
RtmpSession
::
onCmd_publish
(
AMFDecoder
&
dec
)
{
std
::
shared_ptr
<
Ticker
>
pT
icker
(
new
Ticker
);
std
::
shared_ptr
<
Ticker
>
t
icker
(
new
Ticker
);
weak_ptr
<
RtmpSession
>
weak
S
elf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
weak_ptr
<
RtmpSession
>
weak
_s
elf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
std
::
shared_ptr
<
onceToken
>
pToken
(
new
onceToken
(
nullptr
,[
pTicker
,
weakS
elf
](){
std
::
shared_ptr
<
onceToken
>
pToken
(
new
onceToken
(
nullptr
,[
ticker
,
weak_s
elf
](){
auto
strong
Self
=
weakS
elf
.
lock
();
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
strong
S
elf
){
if
(
strong
_s
elf
){
DebugP
(
strong
Self
.
get
())
<<
"publish 回复时间:"
<<
pT
icker
->
elapsedTime
()
<<
"ms"
;
DebugP
(
strong
_self
.
get
())
<<
"publish 回复时间:"
<<
t
icker
->
elapsedTime
()
<<
"ms"
;
}
}
}));
}));
dec
.
load
<
AMFValue
>
();
/* NULL */
dec
.
load
<
AMFValue
>
();
/* NULL */
_media
Info
.
parse
(
_strTcU
rl
+
"/"
+
getStreamId
(
dec
.
load
<
std
::
string
>
()));
_media
_info
.
parse
(
_tc_u
rl
+
"/"
+
getStreamId
(
dec
.
load
<
std
::
string
>
()));
_media
I
nfo
.
_schema
=
RTMP_SCHEMA
;
_media
_i
nfo
.
_schema
=
RTMP_SCHEMA
;
auto
on
Res
=
[
this
,
pToken
](
const
string
&
err
,
bool
enableRtxp
,
bool
enableHls
,
bool
enableMP4
){
auto
on
_res
=
[
this
,
pToken
](
const
string
&
err
,
bool
enableRtxp
,
bool
enableHls
,
bool
enableMP4
){
auto
src
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
MediaSource
::
find
(
RTMP_SCHEMA
,
auto
src
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
MediaSource
::
find
(
RTMP_SCHEMA
,
_media
I
nfo
.
_vhost
,
_media
_i
nfo
.
_vhost
,
_media
I
nfo
.
_app
,
_media
_i
nfo
.
_app
,
_media
I
nfo
.
_streamid
));
_media
_i
nfo
.
_streamid
));
bool
auth
S
uccess
=
err
.
empty
();
bool
auth
_s
uccess
=
err
.
empty
();
bool
ok
=
(
!
src
&&
!
_p
PublisherSrc
&&
authS
uccess
);
bool
ok
=
(
!
src
&&
!
_p
ublisher_src
&&
auth_s
uccess
);
AMFValue
status
(
AMF_OBJECT
);
AMFValue
status
(
AMF_OBJECT
);
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"code"
,
ok
?
"NetStream.Publish.Start"
:
(
auth
S
uccess
?
"NetStream.Publish.BadName"
:
"NetStream.Publish.BadAuth"
));
status
.
set
(
"code"
,
ok
?
"NetStream.Publish.Start"
:
(
auth
_s
uccess
?
"NetStream.Publish.BadName"
:
"NetStream.Publish.BadAuth"
));
status
.
set
(
"description"
,
ok
?
"Started publishing stream."
:
(
auth
S
uccess
?
"Already publishing."
:
err
.
data
()));
status
.
set
(
"description"
,
ok
?
"Started publishing stream."
:
(
auth
_s
uccess
?
"Already publishing."
:
err
.
data
()));
status
.
set
(
"clientid"
,
"0"
);
status
.
set
(
"clientid"
,
"0"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
if
(
!
ok
)
{
if
(
!
ok
)
{
string
errMsg
=
StrPrinter
<<
(
auth
S
uccess
?
"already publishing:"
:
err
.
data
())
<<
" "
string
errMsg
=
StrPrinter
<<
(
auth
_s
uccess
?
"already publishing:"
:
err
.
data
())
<<
" "
<<
_mediaI
nfo
.
_vhost
<<
" "
<<
_media_i
nfo
.
_vhost
<<
" "
<<
_mediaI
nfo
.
_app
<<
" "
<<
_media_i
nfo
.
_app
<<
" "
<<
_mediaI
nfo
.
_streamid
;
<<
_media_i
nfo
.
_streamid
;
shutdown
(
SockException
(
Err_shutdown
,
errMsg
));
shutdown
(
SockException
(
Err_shutdown
,
errMsg
));
return
;
return
;
}
}
_p
PublisherSrc
.
reset
(
new
RtmpMediaSourceImp
(
_mediaInfo
.
_vhost
,
_mediaInfo
.
_app
,
_mediaI
nfo
.
_streamid
));
_p
ublisher_src
.
reset
(
new
RtmpMediaSourceImp
(
_media_info
.
_vhost
,
_media_info
.
_app
,
_media_i
nfo
.
_streamid
));
_p
PublisherS
rc
->
setListener
(
dynamic_pointer_cast
<
MediaSourceEvent
>
(
shared_from_this
()));
_p
ublisher_s
rc
->
setListener
(
dynamic_pointer_cast
<
MediaSourceEvent
>
(
shared_from_this
()));
//设置转协议
//设置转协议
_p
PublisherSrc
->
setProtocolTranslation
(
enableRtxp
,
enableHls
,
enableMP4
);
_p
ublisher_src
->
setProtocolTranslation
(
enableRtxp
,
enableHls
,
enableMP4
);
//如果是rtmp推流客户端,那么加大TCP接收缓存,这样能提升接收性能
//如果是rtmp推流客户端,那么加大TCP接收缓存,这样能提升接收性能
_sock
->
setReadBuffer
(
std
::
make_shared
<
BufferRaw
>
(
256
*
1024
));
_sock
->
setReadBuffer
(
std
::
make_shared
<
BufferRaw
>
(
256
*
1024
));
setSocketFlags
();
setSocketFlags
();
};
};
if
(
_media
Info
.
_app
.
empty
()
||
_mediaI
nfo
.
_streamid
.
empty
()){
if
(
_media
_info
.
_app
.
empty
()
||
_media_i
nfo
.
_streamid
.
empty
()){
//不允许莫名其妙的推流url
//不允许莫名其妙的推流url
on
R
es
(
"rtmp推流url非法"
,
false
,
false
,
false
);
on
_r
es
(
"rtmp推流url非法"
,
false
,
false
,
false
);
return
;
return
;
}
}
Broadcast
::
PublishAuthInvoker
invoker
=
[
weak
Self
,
onRes
,
pToken
](
const
string
&
err
,
bool
enableRtxp
,
bool
enableHls
,
bool
enableMP4
){
Broadcast
::
PublishAuthInvoker
invoker
=
[
weak
_self
,
on_res
,
pToken
](
const
string
&
err
,
bool
enableRtxp
,
bool
enableHls
,
bool
enableMP4
){
auto
strongSelf
=
weak
S
elf
.
lock
();
auto
strongSelf
=
weak
_s
elf
.
lock
();
if
(
!
strongSelf
){
if
(
!
strongSelf
){
return
;
return
;
}
}
strongSelf
->
async
([
weak
Self
,
onR
es
,
err
,
pToken
,
enableRtxp
,
enableHls
,
enableMP4
](){
strongSelf
->
async
([
weak
_self
,
on_r
es
,
err
,
pToken
,
enableRtxp
,
enableHls
,
enableMP4
](){
auto
strongSelf
=
weak
S
elf
.
lock
();
auto
strongSelf
=
weak
_s
elf
.
lock
();
if
(
!
strongSelf
){
if
(
!
strongSelf
){
return
;
return
;
}
}
on
Res
(
err
,
enableRtxp
,
enableHls
,
enableMP4
);
on
_res
(
err
,
enableRtxp
,
enableHls
,
enableMP4
);
});
});
};
};
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPublish
,
_mediaInfo
,
invoker
,
static_cast
<
SockInfo
&>
(
*
this
));
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPublish
,
_media_info
,
invoker
,
static_cast
<
SockInfo
&>
(
*
this
));
if
(
!
flag
){
if
(
!
flag
){
//该事件无人监听,默认鉴权成功
//该事件无人监听,默认鉴权成功
GET_CONFIG
(
bool
,
to
R
txp
,
General
::
kPublishToRtxp
);
GET_CONFIG
(
bool
,
to
_r
txp
,
General
::
kPublishToRtxp
);
GET_CONFIG
(
bool
,
to
H
ls
,
General
::
kPublishToHls
);
GET_CONFIG
(
bool
,
to
_h
ls
,
General
::
kPublishToHls
);
GET_CONFIG
(
bool
,
to
MP
4
,
General
::
kPublishToMP4
);
GET_CONFIG
(
bool
,
to
_mp
4
,
General
::
kPublishToMP4
);
on
Res
(
""
,
toRtxp
,
toHls
,
toMP
4
);
on
_res
(
""
,
to_rtxp
,
to_hls
,
to_mp
4
);
}
}
}
}
...
@@ -196,8 +196,8 @@ void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) {
...
@@ -196,8 +196,8 @@ void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) {
}
}
void
RtmpSession
::
sendPlayResponse
(
const
string
&
err
,
const
RtmpMediaSource
::
Ptr
&
src
){
void
RtmpSession
::
sendPlayResponse
(
const
string
&
err
,
const
RtmpMediaSource
::
Ptr
&
src
){
bool
auth
S
uccess
=
err
.
empty
();
bool
auth
_s
uccess
=
err
.
empty
();
bool
ok
=
(
src
.
operator
bool
()
&&
auth
S
uccess
);
bool
ok
=
(
src
.
operator
bool
()
&&
auth
_s
uccess
);
if
(
ok
)
{
if
(
ok
)
{
//stream begin
//stream begin
sendUserControl
(
CONTROL_STREAM_BEGIN
,
STREAM_MEDIA
);
sendUserControl
(
CONTROL_STREAM_BEGIN
,
STREAM_MEDIA
);
...
@@ -205,17 +205,17 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
...
@@ -205,17 +205,17 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
// onStatus(NetStream.Play.Reset)
// onStatus(NetStream.Play.Reset)
AMFValue
status
(
AMF_OBJECT
);
AMFValue
status
(
AMF_OBJECT
);
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"code"
,
ok
?
"NetStream.Play.Reset"
:
(
auth
S
uccess
?
"NetStream.Play.StreamNotFound"
:
"NetStream.Play.BadAuth"
));
status
.
set
(
"code"
,
ok
?
"NetStream.Play.Reset"
:
(
auth
_s
uccess
?
"NetStream.Play.StreamNotFound"
:
"NetStream.Play.BadAuth"
));
status
.
set
(
"description"
,
ok
?
"Resetting and playing."
:
(
auth
S
uccess
?
"No such stream."
:
err
.
data
()));
status
.
set
(
"description"
,
ok
?
"Resetting and playing."
:
(
auth
_s
uccess
?
"No such stream."
:
err
.
data
()));
status
.
set
(
"details"
,
_media
I
nfo
.
_streamid
);
status
.
set
(
"details"
,
_media
_i
nfo
.
_streamid
);
status
.
set
(
"clientid"
,
"0"
);
status
.
set
(
"clientid"
,
"0"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
if
(
!
ok
)
{
if
(
!
ok
)
{
string
err
Msg
=
StrPrinter
<<
(
authS
uccess
?
"no such stream:"
:
err
.
data
())
<<
" "
string
err
_msg
=
StrPrinter
<<
(
auth_s
uccess
?
"no such stream:"
:
err
.
data
())
<<
" "
<<
_mediaI
nfo
.
_vhost
<<
" "
<<
_media_i
nfo
.
_vhost
<<
" "
<<
_mediaI
nfo
.
_app
<<
" "
<<
_media_i
nfo
.
_app
<<
" "
<<
_mediaI
nfo
.
_streamid
;
<<
_media_i
nfo
.
_streamid
;
shutdown
(
SockException
(
Err_shutdown
,
errM
sg
));
shutdown
(
SockException
(
Err_shutdown
,
err_m
sg
));
return
;
return
;
}
}
...
@@ -224,7 +224,7 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
...
@@ -224,7 +224,7 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
status
.
set
(
"level"
,
"status"
);
status
.
set
(
"level"
,
"status"
);
status
.
set
(
"code"
,
"NetStream.Play.Start"
);
status
.
set
(
"code"
,
"NetStream.Play.Start"
);
status
.
set
(
"description"
,
"Started playing."
);
status
.
set
(
"description"
,
"Started playing."
);
status
.
set
(
"details"
,
_media
I
nfo
.
_streamid
);
status
.
set
(
"details"
,
_media
_i
nfo
.
_streamid
);
status
.
set
(
"clientid"
,
"0"
);
status
.
set
(
"clientid"
,
"0"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
...
@@ -245,7 +245,7 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
...
@@ -245,7 +245,7 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
status
.
set
(
"level"
,
"status"
);
status
.
set
(
"level"
,
"status"
);
status
.
set
(
"code"
,
"NetStream.Play.PublishNotify"
);
status
.
set
(
"code"
,
"NetStream.Play.PublishNotify"
);
status
.
set
(
"description"
,
"Now published."
);
status
.
set
(
"description"
,
"Now published."
);
status
.
set
(
"details"
,
_media
I
nfo
.
_streamid
);
status
.
set
(
"details"
,
_media
_i
nfo
.
_streamid
);
status
.
set
(
"clientid"
,
"0"
);
status
.
set
(
"clientid"
,
"0"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
...
@@ -273,9 +273,9 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
...
@@ -273,9 +273,9 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
//音频同步于视频
//音频同步于视频
_stamp
[
0
].
syncTo
(
_stamp
[
1
]);
_stamp
[
0
].
syncTo
(
_stamp
[
1
]);
_
pRingR
eader
=
src
->
getRing
()
->
attach
(
getPoller
());
_
ring_r
eader
=
src
->
getRing
()
->
attach
(
getPoller
());
weak_ptr
<
RtmpSession
>
weakSelf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
weak_ptr
<
RtmpSession
>
weakSelf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
_
pRingR
eader
->
setReadCB
([
weakSelf
](
const
RtmpMediaSource
::
RingDataType
&
pkt
)
{
_
ring_r
eader
->
setReadCB
([
weakSelf
](
const
RtmpMediaSource
::
RingDataType
&
pkt
)
{
auto
strongSelf
=
weakSelf
.
lock
();
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
if
(
!
strongSelf
)
{
return
;
return
;
...
@@ -293,14 +293,14 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
...
@@ -293,14 +293,14 @@ void RtmpSession::sendPlayResponse(const string &err,const RtmpMediaSource::Ptr
strongSelf
->
onSendMedia
(
rtmp
);
strongSelf
->
onSendMedia
(
rtmp
);
});
});
});
});
_
pRingR
eader
->
setDetachCB
([
weakSelf
]()
{
_
ring_r
eader
->
setDetachCB
([
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
if
(
!
strongSelf
)
{
return
;
return
;
}
}
strongSelf
->
shutdown
(
SockException
(
Err_shutdown
,
"rtmp ring buffer detached"
));
strongSelf
->
shutdown
(
SockException
(
Err_shutdown
,
"rtmp ring buffer detached"
));
});
});
_p
PlayerS
rc
=
src
;
_p
layer_s
rc
=
src
;
if
(
src
->
totalReaderCount
()
==
1
)
{
if
(
src
->
totalReaderCount
()
==
1
)
{
src
->
seekTo
(
0
);
src
->
seekTo
(
0
);
}
}
...
@@ -317,46 +317,47 @@ void RtmpSession::doPlayResponse(const string &err,const std::function<void(bool
...
@@ -317,46 +317,47 @@ void RtmpSession::doPlayResponse(const string &err,const std::function<void(bool
}
}
//鉴权成功,查找媒体源并回复
//鉴权成功,查找媒体源并回复
weak_ptr
<
RtmpSession
>
weak
S
elf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
weak_ptr
<
RtmpSession
>
weak
_s
elf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
MediaSource
::
findAsync
(
_media
Info
,
weakSelf
.
lock
(),[
weakS
elf
,
cb
](
const
MediaSource
::
Ptr
&
src
){
MediaSource
::
findAsync
(
_media
_info
,
weak_self
.
lock
(),
[
weak_s
elf
,
cb
](
const
MediaSource
::
Ptr
&
src
){
auto
rtmp_src
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
src
);
auto
rtmp_src
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
src
);
auto
strong
Self
=
weakS
elf
.
lock
();
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
strong
S
elf
){
if
(
strong
_s
elf
){
strong
S
elf
->
sendPlayResponse
(
""
,
rtmp_src
);
strong
_s
elf
->
sendPlayResponse
(
""
,
rtmp_src
);
}
}
cb
(
rtmp_src
.
operator
bool
());
cb
(
rtmp_src
.
operator
bool
());
});
});
}
}
void
RtmpSession
::
doPlay
(
AMFDecoder
&
dec
){
void
RtmpSession
::
doPlay
(
AMFDecoder
&
dec
){
std
::
shared_ptr
<
Ticker
>
pT
icker
(
new
Ticker
);
std
::
shared_ptr
<
Ticker
>
t
icker
(
new
Ticker
);
weak_ptr
<
RtmpSession
>
weak
S
elf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
weak_ptr
<
RtmpSession
>
weak
_s
elf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
std
::
shared_ptr
<
onceToken
>
pToken
(
new
onceToken
(
nullptr
,[
pTicker
,
weakS
elf
](){
std
::
shared_ptr
<
onceToken
>
token
(
new
onceToken
(
nullptr
,
[
ticker
,
weak_s
elf
](){
auto
strongSelf
=
weak
S
elf
.
lock
();
auto
strongSelf
=
weak
_s
elf
.
lock
();
if
(
strongSelf
)
{
if
(
strongSelf
)
{
DebugP
(
strongSelf
.
get
())
<<
"play 回复时间:"
<<
pT
icker
->
elapsedTime
()
<<
"ms"
;
DebugP
(
strongSelf
.
get
())
<<
"play 回复时间:"
<<
t
icker
->
elapsedTime
()
<<
"ms"
;
}
}
}));
}));
Broadcast
::
AuthInvoker
invoker
=
[
weak
Self
,
pT
oken
](
const
string
&
err
){
Broadcast
::
AuthInvoker
invoker
=
[
weak
_self
,
t
oken
](
const
string
&
err
){
auto
strong
Self
=
weakS
elf
.
lock
();
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
!
strongSelf
)
{
if
(
!
strong_self
)
{
return
;
return
;
}
}
strong
Self
->
async
([
weakSelf
,
err
,
pToken
]()
{
strong
_self
->
async
([
weak_self
,
err
,
token
]()
{
auto
strong
Self
=
weakS
elf
.
lock
();
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
!
strongSelf
)
{
if
(
!
strong_self
)
{
return
;
return
;
}
}
strong
Self
->
doPlayResponse
(
err
,[
pToken
](
bool
)
{});
strong
_self
->
doPlayResponse
(
err
,
[
token
](
bool
)
{});
});
});
};
};
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
_mediaInfo
,
invoker
,
static_cast
<
SockInfo
&>
(
*
this
));
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
_media_info
,
invoker
,
static_cast
<
SockInfo
&>
(
*
this
));
if
(
!
flag
){
if
(
!
flag
){
//该事件无人监听,默认不鉴权
//该事件无人监听,默认不鉴权
doPlayResponse
(
""
,[
pT
oken
](
bool
){});
doPlayResponse
(
""
,[
t
oken
](
bool
){});
}
}
}
}
void
RtmpSession
::
onCmd_play2
(
AMFDecoder
&
dec
)
{
void
RtmpSession
::
onCmd_play2
(
AMFDecoder
&
dec
)
{
doPlay
(
dec
);
doPlay
(
dec
);
}
}
...
@@ -365,30 +366,30 @@ string RtmpSession::getStreamId(const string &str){
...
@@ -365,30 +366,30 @@ string RtmpSession::getStreamId(const string &str){
string
stream_id
;
string
stream_id
;
string
params
;
string
params
;
auto
pos
=
str
.
find
(
'?'
);
auto
pos
=
str
.
find
(
'?'
);
if
(
pos
!=
string
::
npos
)
{
if
(
pos
!=
string
::
npos
)
{
//有url参数
//有url参数
stream_id
=
str
.
substr
(
0
,
pos
);
stream_id
=
str
.
substr
(
0
,
pos
);
//获取url参数
//获取url参数
params
=
str
.
substr
(
pos
+
1
);
params
=
str
.
substr
(
pos
+
1
);
}
else
{
}
else
{
//没有url参数
//没有url参数
stream_id
=
str
;
stream_id
=
str
;
}
}
pos
=
stream_id
.
find
(
":"
);
pos
=
stream_id
.
find
(
":"
);
if
(
pos
!=
string
::
npos
)
{
if
(
pos
!=
string
::
npos
)
{
//vlc和ffplay在播放 rtmp://127.0.0.1/record/0.mp4时,
//vlc和ffplay在播放 rtmp://127.0.0.1/record/0.mp4时,
//传过来的url会是rtmp://127.0.0.1/record/mp4:0,
//传过来的url会是rtmp://127.0.0.1/record/mp4:0,
//我们在这里还原成0.mp4
//我们在这里还原成0.mp4
//实际使用时发现vlc,mpv等会传过来rtmp://127.0.0.1/record/mp4:0.mp4,这里做个判断
//实际使用时发现vlc,mpv等会传过来rtmp://127.0.0.1/record/mp4:0.mp4,这里做个判断
auto
ext
=
stream_id
.
substr
(
0
,
pos
);
auto
ext
=
stream_id
.
substr
(
0
,
pos
);
stream_id
=
stream_id
.
substr
(
pos
+
1
);
stream_id
=
stream_id
.
substr
(
pos
+
1
);
if
(
stream_id
.
find
(
ext
)
==
string
::
npos
)
{
if
(
stream_id
.
find
(
ext
)
==
string
::
npos
)
{
stream_id
=
stream_id
+
"."
+
ext
;
stream_id
=
stream_id
+
"."
+
ext
;
}
}
}
}
if
(
params
.
empty
())
{
if
(
params
.
empty
())
{
//没有url参数
//没有url参数
return
stream_id
;
return
stream_id
;
}
}
...
@@ -399,8 +400,8 @@ string RtmpSession::getStreamId(const string &str){
...
@@ -399,8 +400,8 @@ string RtmpSession::getStreamId(const string &str){
void
RtmpSession
::
onCmd_play
(
AMFDecoder
&
dec
)
{
void
RtmpSession
::
onCmd_play
(
AMFDecoder
&
dec
)
{
dec
.
load
<
AMFValue
>
();
/* NULL */
dec
.
load
<
AMFValue
>
();
/* NULL */
_media
Info
.
parse
(
_strTcU
rl
+
"/"
+
getStreamId
(
dec
.
load
<
std
::
string
>
()));
_media
_info
.
parse
(
_tc_u
rl
+
"/"
+
getStreamId
(
dec
.
load
<
std
::
string
>
()));
_media
I
nfo
.
_schema
=
RTMP_SCHEMA
;
_media
_i
nfo
.
_schema
=
RTMP_SCHEMA
;
doPlay
(
dec
);
doPlay
(
dec
);
}
}
...
@@ -419,7 +420,7 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
...
@@ -419,7 +420,7 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
}
}
void
RtmpSession
::
setMetaData
(
AMFDecoder
&
dec
)
{
void
RtmpSession
::
setMetaData
(
AMFDecoder
&
dec
)
{
if
(
!
_p
PublisherS
rc
)
{
if
(
!
_p
ublisher_s
rc
)
{
throw
std
::
runtime_error
(
"not a publisher"
);
throw
std
::
runtime_error
(
"not a publisher"
);
}
}
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
...
@@ -428,22 +429,23 @@ void RtmpSession::setMetaData(AMFDecoder &dec) {
...
@@ -428,22 +429,23 @@ void RtmpSession::setMetaData(AMFDecoder &dec) {
}
}
auto
metadata
=
dec
.
load
<
AMFValue
>
();
auto
metadata
=
dec
.
load
<
AMFValue
>
();
// dumpMetadata(metadata);
// dumpMetadata(metadata);
_p
PublisherS
rc
->
setMetaData
(
metadata
);
_p
ublisher_s
rc
->
setMetaData
(
metadata
);
_set_meta_data
=
true
;
_set_meta_data
=
true
;
}
}
void
RtmpSession
::
onProcessCmd
(
AMFDecoder
&
dec
)
{
void
RtmpSession
::
onProcessCmd
(
AMFDecoder
&
dec
)
{
typedef
void
(
RtmpSession
::*
rtmpCMDHandle
)(
AMFDecoder
&
dec
);
typedef
void
(
RtmpSession
::*
cmd_function
)(
AMFDecoder
&
dec
);
static
unordered_map
<
string
,
rtmpCMDHandle
>
s_cmd_functions
;
static
unordered_map
<
string
,
cmd_function
>
s_cmd_functions
;
static
onceToken
token
([]()
{
static
onceToken
token
([]()
{
s_cmd_functions
.
emplace
(
"connect"
,
&
RtmpSession
::
onCmd_connect
);
s_cmd_functions
.
emplace
(
"connect"
,
&
RtmpSession
::
onCmd_connect
);
s_cmd_functions
.
emplace
(
"createStream"
,
&
RtmpSession
::
onCmd_createStream
);
s_cmd_functions
.
emplace
(
"createStream"
,
&
RtmpSession
::
onCmd_createStream
);
s_cmd_functions
.
emplace
(
"publish"
,
&
RtmpSession
::
onCmd_publish
);
s_cmd_functions
.
emplace
(
"publish"
,
&
RtmpSession
::
onCmd_publish
);
s_cmd_functions
.
emplace
(
"deleteStream"
,
&
RtmpSession
::
onCmd_deleteStream
);
s_cmd_functions
.
emplace
(
"deleteStream"
,
&
RtmpSession
::
onCmd_deleteStream
);
s_cmd_functions
.
emplace
(
"play"
,
&
RtmpSession
::
onCmd_play
);
s_cmd_functions
.
emplace
(
"play"
,
&
RtmpSession
::
onCmd_play
);
s_cmd_functions
.
emplace
(
"play2"
,
&
RtmpSession
::
onCmd_play2
);
s_cmd_functions
.
emplace
(
"play2"
,
&
RtmpSession
::
onCmd_play2
);
s_cmd_functions
.
emplace
(
"seek"
,
&
RtmpSession
::
onCmd_seek
);
s_cmd_functions
.
emplace
(
"seek"
,
&
RtmpSession
::
onCmd_seek
);
s_cmd_functions
.
emplace
(
"pause"
,
&
RtmpSession
::
onCmd_pause
);},
[]()
{});
s_cmd_functions
.
emplace
(
"pause"
,
&
RtmpSession
::
onCmd_pause
);
});
std
::
string
method
=
dec
.
load
<
std
::
string
>
();
std
::
string
method
=
dec
.
load
<
std
::
string
>
();
auto
it
=
s_cmd_functions
.
find
(
method
);
auto
it
=
s_cmd_functions
.
find
(
method
);
...
@@ -451,52 +453,54 @@ void RtmpSession::onProcessCmd(AMFDecoder &dec) {
...
@@ -451,52 +453,54 @@ void RtmpSession::onProcessCmd(AMFDecoder &dec) {
// TraceP(this) << "can not support cmd:" << method;
// TraceP(this) << "can not support cmd:" << method;
return
;
return
;
}
}
_
dNowReqID
=
dec
.
load
<
double
>
();
_
recv_req_id
=
dec
.
load
<
double
>
();
auto
fun
=
it
->
second
;
auto
fun
=
it
->
second
;
(
this
->*
fun
)(
dec
);
(
this
->*
fun
)(
dec
);
}
}
void
RtmpSession
::
onRtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
{
void
RtmpSession
::
onRtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
{
switch
(
chunk
Data
.
typeI
d
)
{
switch
(
chunk
_data
.
type_i
d
)
{
case
MSG_CMD
:
case
MSG_CMD
:
case
MSG_CMD3
:
{
case
MSG_CMD3
:
{
AMFDecoder
dec
(
chunk
Data
.
strBuf
,
chunkData
.
typeI
d
==
MSG_CMD3
?
1
:
0
);
AMFDecoder
dec
(
chunk
_data
.
buffer
,
chunk_data
.
type_i
d
==
MSG_CMD3
?
1
:
0
);
onProcessCmd
(
dec
);
onProcessCmd
(
dec
);
}
break
;
break
;
}
case
MSG_DATA
:
case
MSG_DATA
:
case
MSG_DATA3
:
{
case
MSG_DATA3
:
{
AMFDecoder
dec
(
chunk
Data
.
strBuf
,
chunkData
.
typeI
d
==
MSG_CMD3
?
1
:
0
);
AMFDecoder
dec
(
chunk
_data
.
buffer
,
chunk_data
.
type_i
d
==
MSG_CMD3
?
1
:
0
);
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
if
(
type
==
"@setDataFrame"
)
{
if
(
type
==
"@setDataFrame"
)
{
setMetaData
(
dec
);
setMetaData
(
dec
);
}
else
{
}
else
{
TraceP
(
this
)
<<
"unknown notify:"
<<
type
;
TraceP
(
this
)
<<
"unknown notify:"
<<
type
;
}
}
}
break
;
break
;
}
case
MSG_AUDIO
:
case
MSG_AUDIO
:
case
MSG_VIDEO
:
{
case
MSG_VIDEO
:
{
if
(
!
_p
PublisherS
rc
)
{
if
(
!
_p
ublisher_s
rc
)
{
throw
std
::
runtime_error
(
"Not a rtmp publisher!"
);
throw
std
::
runtime_error
(
"Not a rtmp publisher!"
);
}
}
GET_CONFIG
(
bool
,
rtmp_modify_stamp
,
Rtmp
::
kModifyStamp
);
GET_CONFIG
(
bool
,
rtmp_modify_stamp
,
Rtmp
::
kModifyStamp
);
if
(
rtmp_modify_stamp
)
{
if
(
rtmp_modify_stamp
)
{
int64_t
dts_out
;
int64_t
dts_out
;
_stamp
[
chunk
Data
.
typeId
%
2
].
revise
(
chunkData
.
timeStamp
,
chunkData
.
timeS
tamp
,
dts_out
,
dts_out
,
true
);
_stamp
[
chunk
_data
.
type_id
%
2
].
revise
(
chunk_data
.
time_stamp
,
chunk_data
.
time_s
tamp
,
dts_out
,
dts_out
,
true
);
chunk
Data
.
timeS
tamp
=
dts_out
;
chunk
_data
.
time_s
tamp
=
dts_out
;
}
}
if
(
!
_set_meta_data
&&
!
chunkData
.
isCfgFrame
())
{
if
(
!
_set_meta_data
&&
!
chunk_data
.
isCfgFrame
())
{
_set_meta_data
=
true
;
_set_meta_data
=
true
;
_pPublisherSrc
->
setMetaData
(
TitleMeta
().
getMetadata
());
_publisher_src
->
setMetaData
(
TitleMeta
().
getMetadata
());
}
_pPublisherSrc
->
onWrite
(
std
::
make_shared
<
RtmpPacket
>
(
std
::
move
(
chunkData
)));
}
}
_publisher_src
->
onWrite
(
std
::
make_shared
<
RtmpPacket
>
(
std
::
move
(
chunk_data
)));
break
;
break
;
}
default
:
default
:
WarnP
(
this
)
<<
"unhandled message:"
<<
(
int
)
chunk
Data
.
typeId
<<
hexdump
(
chunkData
.
strBuf
.
data
(),
chunkData
.
strBuf
.
size
());
WarnP
(
this
)
<<
"unhandled message:"
<<
(
int
)
chunk
_data
.
type_id
<<
hexdump
(
chunk_data
.
buffer
.
data
(),
chunk_data
.
buffer
.
size
());
break
;
break
;
}
}
}
}
...
@@ -512,23 +516,23 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
...
@@ -512,23 +516,23 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
auto
milliSeconds
=
dec
.
load
<
AMFValue
>
().
as_number
();
auto
milliSeconds
=
dec
.
load
<
AMFValue
>
().
as_number
();
InfoP
(
this
)
<<
"rtmp seekTo(ms):"
<<
milliSeconds
;
InfoP
(
this
)
<<
"rtmp seekTo(ms):"
<<
milliSeconds
;
auto
st
ongSrc
=
_pPlayerS
rc
.
lock
();
auto
st
rong_src
=
_player_s
rc
.
lock
();
if
(
st
ongS
rc
)
{
if
(
st
rong_s
rc
)
{
st
ongS
rc
->
seekTo
(
milliSeconds
);
st
rong_s
rc
->
seekTo
(
milliSeconds
);
}
}
}
}
void
RtmpSession
::
onSendMedia
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
void
RtmpSession
::
onSendMedia
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
//rtmp播放器时间戳从零开始
//rtmp播放器时间戳从零开始
int64_t
dts_out
;
int64_t
dts_out
;
_stamp
[
pkt
->
type
Id
%
2
].
revise
(
pkt
->
timeS
tamp
,
0
,
dts_out
,
dts_out
);
_stamp
[
pkt
->
type
_id
%
2
].
revise
(
pkt
->
time_s
tamp
,
0
,
dts_out
,
dts_out
);
sendRtmp
(
pkt
->
type
Id
,
pkt
->
streamId
,
pkt
,
dts_out
,
pkt
->
chunkI
d
);
sendRtmp
(
pkt
->
type
_id
,
pkt
->
stream_index
,
pkt
,
dts_out
,
pkt
->
chunk_i
d
);
}
}
bool
RtmpSession
::
close
(
MediaSource
&
sender
,
bool
force
)
{
bool
RtmpSession
::
close
(
MediaSource
&
sender
,
bool
force
)
{
//此回调在其他线程触发
//此回调在其他线程触发
if
(
!
_p
PublisherSrc
||
(
!
force
&&
_pPublisherS
rc
->
totalReaderCount
())){
if
(
!
_p
ublisher_src
||
(
!
force
&&
_publisher_s
rc
->
totalReaderCount
())){
return
false
;
return
false
;
}
}
string
err
=
StrPrinter
<<
"close media:"
<<
sender
.
getSchema
()
<<
"/"
<<
sender
.
getVhost
()
<<
"/"
<<
sender
.
getApp
()
<<
"/"
<<
sender
.
getId
()
<<
" "
<<
force
;
string
err
=
StrPrinter
<<
"close media:"
<<
sender
.
getSchema
()
<<
"/"
<<
sender
.
getVhost
()
<<
"/"
<<
sender
.
getApp
()
<<
"/"
<<
sender
.
getId
()
<<
" "
<<
force
;
...
@@ -537,12 +541,12 @@ bool RtmpSession::close(MediaSource &sender,bool force) {
...
@@ -537,12 +541,12 @@ bool RtmpSession::close(MediaSource &sender,bool force) {
}
}
int
RtmpSession
::
totalReaderCount
(
MediaSource
&
sender
)
{
int
RtmpSession
::
totalReaderCount
(
MediaSource
&
sender
)
{
return
_p
PublisherSrc
?
_pPublisherS
rc
->
totalReaderCount
()
:
sender
.
readerCount
();
return
_p
ublisher_src
?
_publisher_s
rc
->
totalReaderCount
()
:
sender
.
readerCount
();
}
}
void
RtmpSession
::
setSocketFlags
(){
void
RtmpSession
::
setSocketFlags
(){
GET_CONFIG
(
int
,
merge
WriteMS
,
General
::
kMergeWriteMS
);
GET_CONFIG
(
int
,
merge
_write_ms
,
General
::
kMergeWriteMS
);
if
(
mergeWriteMS
>
0
)
{
if
(
merge_write_ms
>
0
)
{
//推流模式下,关闭TCP_NODELAY会增加推流端的延时,但是服务器性能将提高
//推流模式下,关闭TCP_NODELAY会增加推流端的延时,但是服务器性能将提高
SockUtil
::
setNoDelay
(
_sock
->
rawFD
(),
false
);
SockUtil
::
setNoDelay
(
_sock
->
rawFD
(),
false
);
//播放模式下,开启MSG_MORE会增加延时,但是能提高发送性能
//播放模式下,开启MSG_MORE会增加延时,但是能提高发送性能
...
@@ -551,14 +555,14 @@ void RtmpSession::setSocketFlags(){
...
@@ -551,14 +555,14 @@ void RtmpSession::setSocketFlags(){
}
}
void
RtmpSession
::
dumpMetadata
(
const
AMFValue
&
metadata
)
{
void
RtmpSession
::
dumpMetadata
(
const
AMFValue
&
metadata
)
{
if
(
metadata
.
type
()
!=
AMF_OBJECT
&&
metadata
.
type
()
!=
AMF_ECMA_ARRAY
)
{
if
(
metadata
.
type
()
!=
AMF_OBJECT
&&
metadata
.
type
()
!=
AMF_ECMA_ARRAY
)
{
WarnL
<<
"invalid metadata type:"
<<
metadata
.
type
();
WarnL
<<
"invalid metadata type:"
<<
metadata
.
type
();
return
;
return
;
}
}
_StrPrinter
printer
;
_StrPrinter
printer
;
metadata
.
object_for_each
([
&
](
const
string
&
key
,
const
AMFValue
&
val
){
metadata
.
object_for_each
([
&
](
const
string
&
key
,
const
AMFValue
&
val
)
{
printer
<<
"
\r\n
"
<<
key
<<
"
\t
:"
<<
val
.
to_string
()
;
printer
<<
"
\r\n
"
<<
key
<<
"
\t
:"
<<
val
.
to_string
()
;
});
});
InfoL
<<
_media
Info
.
_vhost
<<
" "
<<
_mediaInfo
.
_app
<<
" "
<<
_mediaInfo
.
_streamid
<<
(
string
)
printer
;
InfoL
<<
_media
_info
.
_vhost
<<
" "
<<
_media_info
.
_app
<<
" "
<<
_media_info
.
_streamid
<<
(
string
)
printer
;
}
}
}
/* namespace mediakit */
}
/* namespace mediakit */
src/Rtmp/RtmpSession.h
查看文件 @
fbd711a6
...
@@ -30,11 +30,13 @@ namespace mediakit {
...
@@ -30,11 +30,13 @@ namespace mediakit {
class
RtmpSession
:
public
TcpSession
,
public
RtmpProtocol
,
public
MediaSourceEvent
{
class
RtmpSession
:
public
TcpSession
,
public
RtmpProtocol
,
public
MediaSourceEvent
{
public
:
public
:
typedef
std
::
shared_ptr
<
RtmpSession
>
Ptr
;
typedef
std
::
shared_ptr
<
RtmpSession
>
Ptr
;
RtmpSession
(
const
Socket
::
Ptr
&
_sock
);
RtmpSession
(
const
Socket
::
Ptr
&
sock
);
virtual
~
RtmpSession
();
~
RtmpSession
()
override
;
void
onRecv
(
const
Buffer
::
Ptr
&
pBuf
)
override
;
void
onRecv
(
const
Buffer
::
Ptr
&
buf
)
override
;
void
onError
(
const
SockException
&
err
)
override
;
void
onError
(
const
SockException
&
err
)
override
;
void
onManager
()
override
;
void
onManager
()
override
;
private
:
private
:
void
onProcessCmd
(
AMFDecoder
&
dec
);
void
onProcessCmd
(
AMFDecoder
&
dec
);
void
onCmd_connect
(
AMFDecoder
&
dec
);
void
onCmd_connect
(
AMFDecoder
&
dec
);
...
@@ -55,15 +57,15 @@ private:
...
@@ -55,15 +57,15 @@ private:
void
onSendMedia
(
const
RtmpPacket
::
Ptr
&
pkt
);
void
onSendMedia
(
const
RtmpPacket
::
Ptr
&
pkt
);
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
override
{
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
override
{
_
ui64TotalB
ytes
+=
buffer
->
size
();
_
total_b
ytes
+=
buffer
->
size
();
send
(
buffer
);
send
(
buffer
);
}
}
void
onRtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
override
;
void
onRtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
override
;
template
<
typename
first
,
typename
second
>
template
<
typename
first
,
typename
second
>
inline
void
sendReply
(
const
char
*
str
,
const
first
&
reply
,
const
second
&
status
)
{
inline
void
sendReply
(
const
char
*
str
,
const
first
&
reply
,
const
second
&
status
)
{
AMFEncoder
invoke
;
AMFEncoder
invoke
;
invoke
<<
str
<<
_
dNowReqID
<<
reply
<<
status
;
invoke
<<
str
<<
_
recv_req_id
<<
reply
<<
status
;
sendResponse
(
MSG_CMD
,
invoke
.
data
());
sendResponse
(
MSG_CMD
,
invoke
.
data
());
}
}
...
@@ -74,29 +76,30 @@ private:
...
@@ -74,29 +76,30 @@ private:
void
setSocketFlags
();
void
setSocketFlags
();
string
getStreamId
(
const
string
&
str
);
string
getStreamId
(
const
string
&
str
);
void
dumpMetadata
(
const
AMFValue
&
metadata
);
void
dumpMetadata
(
const
AMFValue
&
metadata
);
private
:
private
:
std
::
string
_strTcUrl
;
bool
_paused
=
false
;
MediaInfo
_mediaInfo
;
double
_dNowReqID
=
0
;
bool
_set_meta_data
=
false
;
bool
_set_meta_data
=
false
;
Ticker
_ticker
;
//数据接收时间
double
_recv_req_id
=
0
;
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_pRingReader
;
//消耗的总流量
std
::
shared_ptr
<
RtmpMediaSourceImp
>
_pPublisherSrc
;
uint64_t
_total_bytes
=
0
;
std
::
weak_ptr
<
RtmpMediaSource
>
_pPlayerSrc
;
std
::
string
_tc_url
;
//时间戳修整器
//时间戳修整器
Stamp
_stamp
[
2
];
Stamp
_stamp
[
2
];
//
消耗的总流量
//
数据接收超时计时器
uint64_t
_ui64TotalBytes
=
0
;
Ticker
_ticker
;
bool
_paused
=
false
;
MediaInfo
_media_info
;
std
::
weak_ptr
<
RtmpMediaSource
>
_player_src
;
std
::
shared_ptr
<
RtmpMediaSourceImp
>
_publisher_src
;
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_ring_reader
;
};
};
/**
/**
* 支持ssl加密的rtmp服务器
* 支持ssl加密的rtmp服务器
*/
*/
typedef
TcpSessionWithSSL
<
RtmpSession
>
RtmpSessionWithSSL
;
typedef
TcpSessionWithSSL
<
RtmpSession
>
RtmpSessionWithSSL
;
}
/* namespace mediakit */
}
/* namespace mediakit */
#endif
/* SRC_RTMP_RTMPSESSION_H_ */
#endif
/* SRC_RTMP_RTMPSESSION_H_ */
src/Rtsp/RtspPlayer.cpp
查看文件 @
fbd711a6
...
@@ -733,28 +733,12 @@ void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &rtp, const SdpTrack::Ptr &tra
...
@@ -733,28 +733,12 @@ void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &rtp, const SdpTrack::Ptr &tra
}
}
void
RtspPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshakeCompleted
)
{
void
RtspPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshakeCompleted
)
{
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
if
(
ex
.
getErrCode
()
==
Err_shutdown
)
{
//主动shutdown的,不触发回调
if
(
!
ex
){
return
;
//播放成功,恢复rtp接收超时定时器
_rtp_recv_ticker
.
resetTime
();
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
int
timeoutMS
=
(
*
this
)[
kMediaTimeoutMS
].
as
<
int
>
();
//创建rtp数据接收超时检测定时器
_rtp_check_timer
.
reset
(
new
Timer
(
timeoutMS
/
2000.0
,
[
weakSelf
,
timeoutMS
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
if
(
strongSelf
->
_rtp_recv_ticker
.
elapsedTime
()
>
timeoutMS
)
{
//接收rtp媒体数据包超时
strongSelf
->
onPlayResult_l
(
SockException
(
Err_timeout
,
"receive rtp timeout"
),
true
);
return
false
;
}
return
true
;
},
getPoller
()));
}
}
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
if
(
!
handshakeCompleted
)
{
if
(
!
handshakeCompleted
)
{
//开始播放阶段
//开始播放阶段
_play_check_timer
.
reset
();
_play_check_timer
.
reset
();
...
@@ -769,7 +753,26 @@ void RtspPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete
...
@@ -769,7 +753,26 @@ void RtspPlayer::onPlayResult_l(const SockException &ex , bool handshakeComplete
onResume
();
onResume
();
}
}
if
(
ex
){
if
(
!
ex
)
{
//播放成功,恢复rtp接收超时定时器
_rtp_recv_ticker
.
resetTime
();
int
timeoutMS
=
(
*
this
)[
kMediaTimeoutMS
].
as
<
int
>
();
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
auto
lam
=
[
weakSelf
,
timeoutMS
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
if
(
strongSelf
->
_rtp_recv_ticker
.
elapsedTime
()
>
timeoutMS
)
{
//接收rtp媒体数据包超时
strongSelf
->
onPlayResult_l
(
SockException
(
Err_timeout
,
"receive rtp timeout"
),
true
);
return
false
;
}
return
true
;
};
//创建rtp数据接收超时检测定时器
_rtp_check_timer
=
std
::
make_shared
<
Timer
>
(
timeoutMS
/
2000.0
,
lam
,
getPoller
());
}
else
{
teardown
();
teardown
();
}
}
}
}
...
...
src/Rtsp/RtspSession.cpp
查看文件 @
fbd711a6
...
@@ -1123,7 +1123,7 @@ inline void RtspSession::onSendRtpPacket(const RtpPacket::Ptr &pkt){
...
@@ -1123,7 +1123,7 @@ inline void RtspSession::onSendRtpPacket(const RtpPacket::Ptr &pkt){
//send rtcp every 5 second
//send rtcp every 5 second
ticker
.
resetTime
();
ticker
.
resetTime
();
//直接保存网络字节序
//直接保存网络字节序
memcpy
(
&
counter
.
time
S
tamp
,
pkt
->
data
()
+
8
,
4
);
memcpy
(
&
counter
.
time
_s
tamp
,
pkt
->
data
()
+
8
,
4
);
sendSenderReport
(
_rtp_type
==
Rtsp
::
RTP_TCP
,
track_index
);
sendSenderReport
(
_rtp_type
==
Rtsp
::
RTP_TCP
,
track_index
);
}
}
#endif
#endif
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论