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
39baaebc
Commit
39baaebc
authored
Oct 24, 2018
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
统一成员变量命名风格
parent
97567ec3
隐藏空白字符变更
内嵌
并排
正在显示
74 个修改的文件
包含
2052 行增加
和
2051 行删除
+2052
-2051
src/Codec/AACEncoder.cpp
+26
-26
src/Codec/AACEncoder.h
+7
-7
src/Codec/H264Encoder.cpp
+31
-31
src/Codec/H264Encoder.h
+4
-4
src/Common/MediaSource.cpp
+27
-27
src/Common/MediaSource.h
+27
-27
src/Device/Device.cpp
+107
-107
src/Device/Device.h
+15
-15
src/Device/PlayerProxy.cpp
+26
-26
src/Device/PlayerProxy.h
+9
-9
src/H264/H264Parser.cpp
+22
-22
src/H264/H264Parser.h
+13
-13
src/Http/HttpSession.cpp
+52
-52
src/Http/HttpSession.h
+7
-7
src/Http/HttpsSession.h
+6
-6
src/MediaFile/HLSMaker.cpp
+35
-35
src/MediaFile/HLSMaker.h
+10
-10
src/MediaFile/MediaReader.cpp
+114
-114
src/MediaFile/MediaReader.h
+28
-28
src/MediaFile/MediaRecorder.cpp
+10
-10
src/MediaFile/MediaRecorder.h
+4
-4
src/MediaFile/Mp4Maker.cpp
+65
-65
src/MediaFile/Mp4Maker.h
+15
-15
src/Player/MediaPlayer.cpp
+14
-14
src/Player/MediaPlayer.h
+1
-1
src/Player/PlayerBase.h
+28
-28
src/RTP/AACRtpCodec.cpp
+38
-38
src/RTP/AACRtpCodec.h
+3
-3
src/RTP/H264RtpCodec.cpp
+43
-42
src/RTP/H264RtpCodec.h
+2
-2
src/RTP/RtpCodec.h
+19
-19
src/RTP/RtpMaker.h
+21
-21
src/RTP/RtpMakerAAC.cpp
+27
-27
src/RTP/RtpMakerAAC.h
+1
-1
src/RTP/RtpMakerH264.cpp
+13
-13
src/Rtmp/FlvMuxer.cpp
+8
-8
src/Rtmp/FlvMuxer.h
+2
-2
src/Rtmp/RtmpMediaSource.h
+28
-28
src/Rtmp/RtmpParser.cpp
+53
-53
src/Rtmp/RtmpParser.h
+21
-21
src/Rtmp/RtmpPlayer.cpp
+47
-47
src/Rtmp/RtmpPlayer.h
+29
-29
src/Rtmp/RtmpPlayerImp.h
+12
-12
src/Rtmp/RtmpProtocol.cpp
+74
-74
src/Rtmp/RtmpProtocol.h
+17
-17
src/Rtmp/RtmpPusher.cpp
+34
-34
src/Rtmp/RtmpPusher.h
+25
-25
src/Rtmp/RtmpSession.cpp
+71
-71
src/Rtmp/RtmpSession.h
+15
-15
src/Rtmp/RtmpToRtspMediaSource.cpp
+33
-33
src/Rtmp/RtmpToRtspMediaSource.h
+14
-14
src/Rtmp/amf.cpp
+34
-34
src/Rtmp/amf.h
+35
-35
src/RtmpCodec/AACRtmpCodec.cpp
+3
-3
src/RtmpCodec/AACRtmpCodec.h
+1
-1
src/RtmpCodec/H264RtmpCodec.cpp
+26
-26
src/RtmpCodec/H264RtmpCodec.h
+3
-3
src/Rtsp/RtpBroadCaster.cpp
+34
-34
src/Rtsp/RtpBroadCaster.h
+9
-9
src/Rtsp/RtpParser.cpp
+1
-1
src/Rtsp/RtpParser.h
+2
-2
src/Rtsp/Rtsp.h
+36
-36
src/Rtsp/RtspMediaSource.h
+12
-12
src/Rtsp/RtspPlayer.cpp
+155
-155
src/Rtsp/RtspPlayer.h
+28
-28
src/Rtsp/RtspPlayerImp.h
+12
-12
src/Rtsp/RtspSession.cpp
+178
-178
src/Rtsp/RtspSession.h
+36
-36
src/Rtsp/RtspToRtmpMediaSource.cpp
+39
-39
src/Rtsp/RtspToRtmpMediaSource.h
+15
-15
src/Rtsp/UDPServer.cpp
+16
-16
src/Rtsp/UDPServer.h
+4
-4
src/Shell/ShellSession.cpp
+16
-16
src/Shell/ShellSession.h
+4
-4
没有找到文件。
src/Codec/AACEncoder.cpp
查看文件 @
39baaebc
...
...
@@ -48,17 +48,17 @@ AACEncoder::AACEncoder() {
}
AACEncoder
::~
AACEncoder
()
{
if
(
m
_hEncoder
!=
nullptr
)
{
faacEncClose
(
m
_hEncoder
);
m
_hEncoder
=
nullptr
;
if
(
_hEncoder
!=
nullptr
)
{
faacEncClose
(
_hEncoder
);
_hEncoder
=
nullptr
;
}
if
(
m
_pucAacBuf
!=
nullptr
)
{
delete
[]
m
_pucAacBuf
;
m
_pucAacBuf
=
nullptr
;
if
(
_pucAacBuf
!=
nullptr
)
{
delete
[]
_pucAacBuf
;
_pucAacBuf
=
nullptr
;
}
if
(
m
_pucPcmBuf
!=
nullptr
)
{
delete
[]
m
_pucPcmBuf
;
m
_pucPcmBuf
=
nullptr
;
if
(
_pucPcmBuf
!=
nullptr
)
{
delete
[]
_pucPcmBuf
;
_pucPcmBuf
=
nullptr
;
}
}
...
...
@@ -67,19 +67,19 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
return
false
;
}
// (1) Open FAAC engine
m_hEncoder
=
faacEncOpen
(
iSampleRate
,
iChannels
,
&
m
_ulInputSamples
,
&
m
_ulMaxOutputBytes
);
if
(
m
_hEncoder
==
NULL
)
{
_hEncoder
=
faacEncOpen
(
iSampleRate
,
iChannels
,
&
_ulInputSamples
,
&
_ulMaxOutputBytes
);
if
(
_hEncoder
==
NULL
)
{
return
false
;
}
m_pucAacBuf
=
new
unsigned
char
[
m
_ulMaxOutputBytes
];
m_ulMaxInputBytes
=
m
_ulInputSamples
*
iSampleBit
/
8
;
m_pucPcmBuf
=
new
unsigned
char
[
m
_ulMaxInputBytes
*
4
];
_pucAacBuf
=
new
unsigned
char
[
_ulMaxOutputBytes
];
_ulMaxInputBytes
=
_ulInputSamples
*
iSampleBit
/
8
;
_pucPcmBuf
=
new
unsigned
char
[
_ulMaxInputBytes
*
4
];
// (2.1) Get current encoding configuration
faacEncConfigurationPtr
pConfiguration
=
faacEncGetCurrentConfiguration
(
m
_hEncoder
);
faacEncConfigurationPtr
pConfiguration
=
faacEncGetCurrentConfiguration
(
_hEncoder
);
if
(
pConfiguration
==
NULL
)
{
faacEncClose
(
m
_hEncoder
);
faacEncClose
(
_hEncoder
);
return
false
;
}
pConfiguration
->
aacObjectType
=
LOW
;
...
...
@@ -95,25 +95,25 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
pConfiguration
->
inputFormat
=
FAAC_INPUT_16BIT
;
// (2.2) Set encoding configuration
if
(
!
faacEncSetConfiguration
(
m
_hEncoder
,
pConfiguration
)){
if
(
!
faacEncSetConfiguration
(
_hEncoder
,
pConfiguration
)){
ErrorL
<<
"faacEncSetConfiguration failed"
;
faacEncClose
(
m
_hEncoder
);
faacEncClose
(
_hEncoder
);
return
false
;
}
return
true
;
}
int
AACEncoder
::
inputData
(
char
*
pcPcmBufr
,
int
iLen
,
unsigned
char
**
ppucOutBuffer
)
{
memcpy
(
m_pucPcmBuf
+
m
_uiPcmLen
,
pcPcmBufr
,
iLen
);
m
_uiPcmLen
+=
iLen
;
if
(
m_uiPcmLen
<
m
_ulMaxInputBytes
)
{
memcpy
(
_pucPcmBuf
+
_uiPcmLen
,
pcPcmBufr
,
iLen
);
_uiPcmLen
+=
iLen
;
if
(
_uiPcmLen
<
_ulMaxInputBytes
)
{
return
0
;
}
int
nRet
=
faacEncEncode
(
m_hEncoder
,
(
int32_t
*
)
(
m_pucPcmBuf
),
m_ulInputSamples
,
m_pucAacBuf
,
m
_ulMaxOutputBytes
);
m_uiPcmLen
-=
m
_ulMaxInputBytes
;
memmove
(
m_pucPcmBuf
,
m_pucPcmBuf
+
m_ulMaxInputBytes
,
m
_uiPcmLen
);
*
ppucOutBuffer
=
m
_pucAacBuf
;
int
nRet
=
faacEncEncode
(
_hEncoder
,
(
int32_t
*
)
(
_pucPcmBuf
),
_ulInputSamples
,
_pucAacBuf
,
_ulMaxOutputBytes
);
_uiPcmLen
-=
_ulMaxInputBytes
;
memmove
(
_pucPcmBuf
,
_pucPcmBuf
+
_ulMaxInputBytes
,
_uiPcmLen
);
*
ppucOutBuffer
=
_pucAacBuf
;
return
nRet
;
}
...
...
src/Codec/AACEncoder.h
查看文件 @
39baaebc
...
...
@@ -39,15 +39,15 @@ public:
int
inputData
(
char
*
pcData
,
int
iLen
,
unsigned
char
**
ppucOutBuffer
);
private
:
unsigned
char
*
m
_pucPcmBuf
=
nullptr
;
unsigned
int
m
_uiPcmLen
=
0
;
unsigned
char
*
_pucPcmBuf
=
nullptr
;
unsigned
int
_uiPcmLen
=
0
;
unsigned
char
*
m
_pucAacBuf
=
nullptr
;
void
*
m
_hEncoder
=
nullptr
;
unsigned
char
*
_pucAacBuf
=
nullptr
;
void
*
_hEncoder
=
nullptr
;
unsigned
long
m
_ulInputSamples
=
0
;
unsigned
long
m
_ulMaxInputBytes
=
0
;
unsigned
long
m
_ulMaxOutputBytes
=
0
;
unsigned
long
_ulInputSamples
=
0
;
unsigned
long
_ulMaxInputBytes
=
0
;
unsigned
long
_ulMaxOutputBytes
=
0
;
};
...
...
src/Codec/H264Encoder.cpp
查看文件 @
39baaebc
...
...
@@ -39,19 +39,19 @@ H264Encoder::H264Encoder() {
H264Encoder
::~
H264Encoder
()
{
//* 清除图像区域
if
(
m
_pPicIn
)
{
delete
m
_pPicIn
;
m
_pPicIn
=
nullptr
;
if
(
_pPicIn
)
{
delete
_pPicIn
;
_pPicIn
=
nullptr
;
}
if
(
m
_pPicOut
)
{
delete
m
_pPicOut
;
m
_pPicOut
=
nullptr
;
if
(
_pPicOut
)
{
delete
_pPicOut
;
_pPicOut
=
nullptr
;
}
//* 关闭编码器句柄
if
(
m
_pX264Handle
)
{
x264_encoder_close
(
m
_pX264Handle
);
m
_pX264Handle
=
nullptr
;
if
(
_pX264Handle
)
{
x264_encoder_close
(
_pX264Handle
);
_pX264Handle
=
nullptr
;
}
}
...
...
@@ -229,7 +229,7 @@ Value的值就是fps。
} x264_param_t;*/
bool
H264Encoder
::
init
(
int
iWidth
,
int
iHeight
,
int
iFps
)
{
if
(
m
_pX264Handle
)
{
if
(
_pX264Handle
)
{
return
true
;
}
x264_param_t
X264Param
,
*
pX264Param
=
&
X264Param
;
...
...
@@ -307,43 +307,43 @@ bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
//* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264
//* 的参数.通过x264_encoder_reconfig更新X264的参数
m
_pX264Handle
=
x264_encoder_open
(
pX264Param
);
if
(
!
m
_pX264Handle
)
{
_pX264Handle
=
x264_encoder_open
(
pX264Param
);
if
(
!
_pX264Handle
)
{
return
false
;
}
m
_pPicIn
=
new
x264_picture_t
;
m
_pPicOut
=
new
x264_picture_t
;
x264_picture_init
(
m
_pPicIn
);
x264_picture_init
(
m
_pPicOut
);
m
_pPicIn
->
img
.
i_csp
=
X264_CSP_I420
;
m
_pPicIn
->
img
.
i_plane
=
3
;
_pPicIn
=
new
x264_picture_t
;
_pPicOut
=
new
x264_picture_t
;
x264_picture_init
(
_pPicIn
);
x264_picture_init
(
_pPicOut
);
_pPicIn
->
img
.
i_csp
=
X264_CSP_I420
;
_pPicIn
->
img
.
i_plane
=
3
;
return
true
;
}
int
H264Encoder
::
inputData
(
char
*
apcYuv
[
3
],
int
aiYuvLen
[
3
],
int64_t
i64Pts
,
H264Frame
**
ppFrame
)
{
//TimeTicker1(5);
m
_pPicIn
->
img
.
i_stride
[
0
]
=
aiYuvLen
[
0
];
m
_pPicIn
->
img
.
i_stride
[
1
]
=
aiYuvLen
[
1
];
m
_pPicIn
->
img
.
i_stride
[
2
]
=
aiYuvLen
[
2
];
m
_pPicIn
->
img
.
plane
[
0
]
=
(
uint8_t
*
)
apcYuv
[
0
];
m
_pPicIn
->
img
.
plane
[
1
]
=
(
uint8_t
*
)
apcYuv
[
1
];
m
_pPicIn
->
img
.
plane
[
2
]
=
(
uint8_t
*
)
apcYuv
[
2
];
m
_pPicIn
->
i_pts
=
i64Pts
;
_pPicIn
->
img
.
i_stride
[
0
]
=
aiYuvLen
[
0
];
_pPicIn
->
img
.
i_stride
[
1
]
=
aiYuvLen
[
1
];
_pPicIn
->
img
.
i_stride
[
2
]
=
aiYuvLen
[
2
];
_pPicIn
->
img
.
plane
[
0
]
=
(
uint8_t
*
)
apcYuv
[
0
];
_pPicIn
->
img
.
plane
[
1
]
=
(
uint8_t
*
)
apcYuv
[
1
];
_pPicIn
->
img
.
plane
[
2
]
=
(
uint8_t
*
)
apcYuv
[
2
];
_pPicIn
->
i_pts
=
i64Pts
;
int
iNal
;
x264_nal_t
*
pNals
;
int
iResult
=
x264_encoder_encode
(
m_pX264Handle
,
&
pNals
,
&
iNal
,
m
_pPicIn
,
m
_pPicOut
);
int
iResult
=
x264_encoder_encode
(
_pX264Handle
,
&
pNals
,
&
iNal
,
_pPicIn
,
_pPicOut
);
if
(
iResult
<=
0
)
{
return
0
;
}
for
(
int
i
=
0
;
i
<
iNal
;
i
++
)
{
x264_nal_t
pNal
=
pNals
[
i
];
m
_aFrames
[
i
].
iType
=
pNal
.
i_type
;
m
_aFrames
[
i
].
iLength
=
pNal
.
i_payload
;
m
_aFrames
[
i
].
pucData
=
pNal
.
p_payload
;
_aFrames
[
i
].
iType
=
pNal
.
i_type
;
_aFrames
[
i
].
iLength
=
pNal
.
i_payload
;
_aFrames
[
i
].
pucData
=
pNal
.
p_payload
;
}
*
ppFrame
=
m
_aFrames
;
*
ppFrame
=
_aFrames
;
return
iNal
;
}
...
...
src/Codec/H264Encoder.h
查看文件 @
39baaebc
...
...
@@ -54,10 +54,10 @@ public:
bool
init
(
int
iWidth
,
int
iHeight
,
int
iFps
);
int
inputData
(
char
*
apcYuv
[
3
],
int
aiYuvLen
[
3
],
int64_t
i64Pts
,
H264Frame
**
ppFrame
);
private
:
x264_t
*
m
_pX264Handle
=
nullptr
;
x264_picture_t
*
m
_pPicIn
=
nullptr
;
x264_picture_t
*
m
_pPicOut
=
nullptr
;
H264Frame
m
_aFrames
[
10
];
x264_t
*
_pX264Handle
=
nullptr
;
x264_picture_t
*
_pPicIn
=
nullptr
;
x264_picture_t
*
_pPicOut
=
nullptr
;
H264Frame
_aFrames
[
10
];
};
}
/* namespace Codec */
...
...
src/Common/MediaSource.cpp
查看文件 @
39baaebc
...
...
@@ -77,16 +77,16 @@ MediaSource::Ptr MediaSource::find(
bool
MediaSource
::
regist
()
{
//注册该源,注册后服务器才能找到该源
lock_guard
<
recursive_mutex
>
lock
(
g_mtxMediaSrc
);
auto
pr
=
g_mapMediaSrc
[
m_strSchema
][
m_strVhost
][
m_strApp
].
emplace
(
m
_strId
,
shared_from_this
());
auto
pr
=
g_mapMediaSrc
[
_strSchema
][
_strVhost
][
_strApp
].
emplace
(
_strId
,
shared_from_this
());
auto
success
=
pr
.
second
;
if
(
success
){
InfoL
<<
m_strSchema
<<
" "
<<
m_strVhost
<<
" "
<<
m_strApp
<<
" "
<<
m
_strId
;
InfoL
<<
_strSchema
<<
" "
<<
_strVhost
<<
" "
<<
_strApp
<<
" "
<<
_strId
;
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaChanged
,
true
,
m
_strSchema
,
m
_strVhost
,
m
_strApp
,
m
_strId
,
_strSchema
,
_strVhost
,
_strApp
,
_strId
,
*
this
);
}
return
success
;
...
...
@@ -94,7 +94,7 @@ bool MediaSource::regist() {
bool
MediaSource
::
unregist
()
{
//反注册该源
lock_guard
<
recursive_mutex
>
lock
(
g_mtxMediaSrc
);
return
searchMedia
(
m_strSchema
,
m_strVhost
,
m_strApp
,
m
_strId
,
[
&
](
SchemaVhostAppStreamMap
::
iterator
&
it0
,
return
searchMedia
(
_strSchema
,
_strVhost
,
_strApp
,
_strId
,
[
&
](
SchemaVhostAppStreamMap
::
iterator
&
it0
,
VhostAppStreamMap
::
iterator
&
it1
,
AppStreamMap
::
iterator
&
it2
,
StreamMap
::
iterator
&
it3
){
...
...
@@ -110,13 +110,13 @@ bool MediaSource::unregist() {
});
}
void
MediaSource
::
unregisted
(){
InfoL
<<
""
<<
m_strSchema
<<
" "
<<
m_strVhost
<<
" "
<<
m_strApp
<<
" "
<<
m
_strId
;
InfoL
<<
""
<<
_strSchema
<<
" "
<<
_strVhost
<<
" "
<<
_strApp
<<
" "
<<
_strId
;
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaChanged
,
false
,
m
_strSchema
,
m
_strVhost
,
m
_strApp
,
m
_strId
,
_strSchema
,
_strVhost
,
_strApp
,
_strId
,
*
this
);
}
...
...
@@ -124,7 +124,7 @@ void MediaInfo::parse(const string &url){
//string url = "rtsp://127.0.0.1:8554/live/id?key=val&a=1&&b=2&vhost=vhost.com";
auto
schema_pos
=
url
.
find
(
"://"
);
if
(
schema_pos
!=
string
::
npos
){
m
_schema
=
url
.
substr
(
0
,
schema_pos
);
_schema
=
url
.
substr
(
0
,
schema_pos
);
}
else
{
schema_pos
=
-
3
;
}
...
...
@@ -133,14 +133,14 @@ void MediaInfo::parse(const string &url){
auto
vhost
=
split_vec
[
0
];
auto
pos
=
vhost
.
find
(
":"
);
if
(
pos
!=
string
::
npos
){
m_host
=
m
_vhost
=
vhost
.
substr
(
0
,
pos
);
m
_port
=
vhost
.
substr
(
pos
+
1
);
_host
=
_vhost
=
vhost
.
substr
(
0
,
pos
);
_port
=
vhost
.
substr
(
pos
+
1
);
}
else
{
m_host
=
m
_vhost
=
vhost
;
_host
=
_vhost
=
vhost
;
}
}
if
(
split_vec
.
size
()
>
1
){
m
_app
=
split_vec
[
1
];
_app
=
split_vec
[
1
];
}
if
(
split_vec
.
size
()
>
2
){
string
steamid
;
...
...
@@ -152,23 +152,23 @@ void MediaInfo::parse(const string &url){
}
auto
pos
=
steamid
.
find
(
"?"
);
if
(
pos
!=
string
::
npos
){
m
_streamid
=
steamid
.
substr
(
0
,
pos
);
m_param
_strs
=
steamid
.
substr
(
pos
+
1
);
m_params
=
Parser
::
parseArgs
(
m_param
_strs
);
if
(
m_params
.
find
(
VHOST_KEY
)
!=
m
_params
.
end
()){
m_vhost
=
m
_params
[
VHOST_KEY
];
_streamid
=
steamid
.
substr
(
0
,
pos
);
_para
_strs
=
steamid
.
substr
(
pos
+
1
);
_params
=
Parser
::
parseArgs
(
_para
_strs
);
if
(
_params
.
find
(
VHOST_KEY
)
!=
_params
.
end
()){
_vhost
=
_params
[
VHOST_KEY
];
}
}
else
{
m
_streamid
=
steamid
;
_streamid
=
steamid
;
}
}
if
(
m
_vhost
.
empty
()){
if
(
_vhost
.
empty
()){
//无效vhost
m
_vhost
=
DEFAULT_VHOST
;
_vhost
=
DEFAULT_VHOST
;
}
else
{
if
(
INADDR_NONE
!=
inet_addr
(
m
_vhost
.
data
())){
if
(
INADDR_NONE
!=
inet_addr
(
_vhost
.
data
())){
//这是ip,未指定vhost;使用默认vhost
m
_vhost
=
DEFAULT_VHOST
;
_vhost
=
DEFAULT_VHOST
;
}
}
}
...
...
src/Common/MediaSource.h
查看文件 @
39baaebc
...
...
@@ -77,17 +77,17 @@ public:
void
parse
(
const
string
&
url
);
string
&
operator
[](
const
string
&
key
){
return
m
_params
[
key
];
return
_params
[
key
];
}
public
:
string
m
_schema
;
string
m
_host
;
string
m
_port
;
string
m
_vhost
;
string
m
_app
;
string
m
_streamid
;
StrCaseMap
m
_params
;
string
m_param
_strs
;
string
_schema
;
string
_host
;
string
_port
;
string
_vhost
;
string
_app
;
string
_streamid
;
StrCaseMap
_params
;
string
_para
_strs
;
};
...
...
@@ -104,13 +104,13 @@ public:
const
string
&
strVhost
,
const
string
&
strApp
,
const
string
&
strId
)
:
m
_strSchema
(
strSchema
),
m
_strApp
(
strApp
),
m
_strId
(
strId
)
{
_strSchema
(
strSchema
),
_strApp
(
strApp
),
_strId
(
strId
)
{
if
(
strVhost
.
empty
()){
m
_strVhost
=
DEFAULT_VHOST
;
_strVhost
=
DEFAULT_VHOST
;
}
else
{
m
_strVhost
=
strVhost
;
_strVhost
=
strVhost
;
}
}
virtual
~
MediaSource
()
{
...
...
@@ -124,21 +124,21 @@ public:
bool
bMake
=
true
)
;
const
string
&
getSchema
()
const
{
return
m
_strSchema
;
return
_strSchema
;
}
const
string
&
getVhost
()
const
{
return
m
_strVhost
;
return
_strVhost
;
}
const
string
&
getApp
()
const
{
//获取该源的id
return
m
_strApp
;
return
_strApp
;
}
const
string
&
getId
()
const
{
return
m
_strId
;
return
_strId
;
}
bool
seekTo
(
uint32_t
ui32Stamp
)
{
auto
listener
=
m
_listener
.
lock
();
auto
listener
=
_listener
.
lock
();
if
(
!
listener
){
return
false
;
}
...
...
@@ -146,21 +146,21 @@ public:
}
uint32_t
getStamp
()
{
auto
listener
=
m
_listener
.
lock
();
auto
listener
=
_listener
.
lock
();
if
(
!
listener
){
return
0
;
}
return
listener
->
getStamp
();
}
bool
shutDown
()
{
auto
listener
=
m
_listener
.
lock
();
auto
listener
=
_listener
.
lock
();
if
(
!
listener
){
return
false
;
}
return
listener
->
shutDown
();
}
void
setListener
(
const
std
::
weak_ptr
<
MediaSourceEvent
>
&
listener
){
m
_listener
=
listener
;
_listener
=
listener
;
}
template
<
typename
FUN
>
...
...
@@ -224,12 +224,12 @@ private:
void
unregisted
();
protected
:
std
::
weak_ptr
<
MediaSourceEvent
>
m
_listener
;
std
::
weak_ptr
<
MediaSourceEvent
>
_listener
;
private
:
string
m
_strSchema
;
//协议类型
string
m
_strVhost
;
//vhost
string
m
_strApp
;
//媒体app
string
m
_strId
;
//媒体id
string
_strSchema
;
//协议类型
string
_strVhost
;
//vhost
string
_strApp
;
//媒体app
string
_strId
;
//媒体id
static
SchemaVhostAppStreamMap
g_mapMediaSrc
;
//静态的媒体源表
static
recursive_mutex
g_mtxMediaSrc
;
//访问静态的媒体源表的互斥锁
};
...
...
src/Device/Device.cpp
查看文件 @
39baaebc
...
...
@@ -44,19 +44,19 @@ DevChannel::DevChannel(const char *strVhost,
bool
bEnableMp4
)
:
RtspToRtmpMediaSource
(
strVhost
,
strApp
,
strId
,
bEanbleHls
,
bEnableMp4
)
{
m
_strSdp
=
"v=0
\r\n
"
;
m
_strSdp
+=
"o=- 1383190487994921 1 IN IP4 0.0.0.0
\r\n
"
;
m
_strSdp
+=
"s=RTSP Session, streamed by the ZL
\r\n
"
;
m
_strSdp
+=
"i=ZL Live Stream
\r\n
"
;
m
_strSdp
+=
"c=IN IP4 0.0.0.0
\r\n
"
;
m
_strSdp
+=
"t=0 0
\r\n
"
;
_strSdp
=
"v=0
\r\n
"
;
_strSdp
+=
"o=- 1383190487994921 1 IN IP4 0.0.0.0
\r\n
"
;
_strSdp
+=
"s=RTSP Session, streamed by the ZL
\r\n
"
;
_strSdp
+=
"i=ZL Live Stream
\r\n
"
;
_strSdp
+=
"c=IN IP4 0.0.0.0
\r\n
"
;
_strSdp
+=
"t=0 0
\r\n
"
;
//直播,时间长度永远
if
(
fDuration
<=
0
){
m
_strSdp
+=
"a=range:npt=0-
\r\n
"
;
_strSdp
+=
"a=range:npt=0-
\r\n
"
;
}
else
{
m
_strSdp
+=
StrPrinter
<<
"a=range:npt=0-"
<<
fDuration
<<
"
\r\n
"
<<
endl
;
_strSdp
+=
StrPrinter
<<
"a=range:npt=0-"
<<
fDuration
<<
"
\r\n
"
<<
endl
;
}
m
_strSdp
+=
"a=control:*
\r\n
"
;
_strSdp
+=
"a=control:*
\r\n
"
;
}
DevChannel
::~
DevChannel
()
{
}
...
...
@@ -64,16 +64,16 @@ DevChannel::~DevChannel() {
#ifdef ENABLE_X264
void
DevChannel
::
inputYUV
(
char
*
apcYuv
[
3
],
int
aiYuvLen
[
3
],
uint32_t
uiStamp
)
{
//TimeTicker1(50);
if
(
!
m
_pH264Enc
)
{
m
_pH264Enc
.
reset
(
new
H264Encoder
());
if
(
!
m_pH264Enc
->
init
(
m_video
->
iWidth
,
m_video
->
iHeight
,
m
_video
->
iFrameRate
))
{
m
_pH264Enc
.
reset
();
if
(
!
_pH264Enc
)
{
_pH264Enc
.
reset
(
new
H264Encoder
());
if
(
!
_pH264Enc
->
init
(
_video
->
iWidth
,
_video
->
iHeight
,
_video
->
iFrameRate
))
{
_pH264Enc
.
reset
();
WarnL
<<
"H264Encoder init failed!"
;
}
}
if
(
m
_pH264Enc
)
{
if
(
_pH264Enc
)
{
H264Encoder
::
H264Frame
*
pOut
;
int
iFrames
=
m
_pH264Enc
->
inputData
(
apcYuv
,
aiYuvLen
,
uiStamp
,
&
pOut
);
int
iFrames
=
_pH264Enc
->
inputData
(
apcYuv
,
aiYuvLen
,
uiStamp
,
&
pOut
);
for
(
int
i
=
0
;
i
<
iFrames
;
i
++
)
{
inputH264
((
char
*
)
pOut
[
i
].
pucData
,
pOut
[
i
].
iLength
,
uiStamp
);
}
...
...
@@ -83,16 +83,16 @@ void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) {
#ifdef ENABLE_FAAC
void
DevChannel
::
inputPCM
(
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
)
{
if
(
!
m
_pAacEnc
)
{
m
_pAacEnc
.
reset
(
new
AACEncoder
());
if
(
!
m_pAacEnc
->
init
(
m_audio
->
iSampleRate
,
m_audio
->
iChannel
,
m
_audio
->
iSampleBit
))
{
m
_pAacEnc
.
reset
();
if
(
!
_pAacEnc
)
{
_pAacEnc
.
reset
(
new
AACEncoder
());
if
(
!
_pAacEnc
->
init
(
_audio
->
iSampleRate
,
_audio
->
iChannel
,
_audio
->
iSampleBit
))
{
_pAacEnc
.
reset
();
WarnL
<<
"AACEncoder init failed!"
;
}
}
if
(
m
_pAacEnc
)
{
if
(
_pAacEnc
)
{
unsigned
char
*
pucOut
;
int
iRet
=
m
_pAacEnc
->
inputData
(
pcData
,
iDataLen
,
&
pucOut
);
int
iRet
=
_pAacEnc
->
inputData
(
pcData
,
iDataLen
,
&
pucOut
);
if
(
iRet
>
0
)
{
inputAAC
((
char
*
)
pucOut
,
iRet
,
uiStamp
);
}
...
...
@@ -101,16 +101,16 @@ void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
#endif //ENABLE_FAAC
void
DevChannel
::
inputH264
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
)
{
if
(
!
m
_pRtpMaker_h264
)
{
if
(
!
_pRtpMaker_h264
)
{
uint32_t
ui32Ssrc
;
memcpy
(
&
ui32Ssrc
,
makeRandStr
(
4
,
false
).
data
(),
4
);
auto
lam
=
[
this
](
const
RtpPacket
::
Ptr
&
pkt
,
bool
bKeyPos
)
{
onGetRTP
(
pkt
,
bKeyPos
);
};
GET_CONFIG_AND_REGISTER
(
uint32_t
,
videoMtu
,
Config
::
Rtp
::
kVideoMtuSize
);
m
_pRtpMaker_h264
.
reset
(
new
RtpMaker_H264
(
lam
,
ui32Ssrc
,
videoMtu
));
_pRtpMaker_h264
.
reset
(
new
RtpMaker_H264
(
lam
,
ui32Ssrc
,
videoMtu
));
}
if
(
!
m_bSdp_gotH264
&&
m
_video
)
{
if
(
!
_bSdp_gotH264
&&
_video
)
{
makeSDP_264
((
unsigned
char
*
)
pcData
,
iDataLen
);
}
int
iOffset
=
4
;
...
...
@@ -118,38 +118,38 @@ void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t uiStamp) {
iOffset
=
3
;
}
if
(
uiStamp
==
0
){
uiStamp
=
(
uint32_t
)
m
_aTicker
[
0
].
elapsedTime
();
uiStamp
=
(
uint32_t
)
_aTicker
[
0
].
elapsedTime
();
}
m
_pRtpMaker_h264
->
makeRtp
(
pcData
+
iOffset
,
iDataLen
-
iOffset
,
uiStamp
);
_pRtpMaker_h264
->
makeRtp
(
pcData
+
iOffset
,
iDataLen
-
iOffset
,
uiStamp
);
}
void
DevChannel
::
inputAAC
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
,
bool
withAdtsHeader
)
{
if
(
withAdtsHeader
){
inputAAC
(
pcData
+
7
,
iDataLen
-
7
,
uiStamp
,
pcData
);
}
else
if
(
m
_pAdtsHeader
){
m
_pAdtsHeader
->
aac_frame_length
=
iDataLen
;
writeAdtsHeader
(
*
m_pAdtsHeader
,(
uint8_t
*
)
m
_pAdtsHeader
->
buffer
);
inputAAC
(
pcData
,
iDataLen
,
uiStamp
,(
const
char
*
)
m
_pAdtsHeader
->
buffer
);
}
else
if
(
_pAdtsHeader
){
_pAdtsHeader
->
aac_frame_length
=
iDataLen
;
writeAdtsHeader
(
*
_pAdtsHeader
,(
uint8_t
*
)
_pAdtsHeader
->
buffer
);
inputAAC
(
pcData
,
iDataLen
,
uiStamp
,(
const
char
*
)
_pAdtsHeader
->
buffer
);
}
}
void
DevChannel
::
inputAAC
(
const
char
*
pcDataWithoutAdts
,
int
iDataLen
,
uint32_t
uiStamp
,
const
char
*
pcAdtsHeader
){
if
(
!
m
_pRtpMaker_aac
)
{
if
(
!
_pRtpMaker_aac
)
{
uint32_t
ssrc
;
memcpy
(
&
ssrc
,
makeRandStr
(
8
,
false
).
data
()
+
4
,
4
);
auto
lam
=
[
this
](
const
RtpPacket
::
Ptr
&
pkt
,
bool
keyPos
)
{
onGetRTP
(
pkt
,
keyPos
);
};
GET_CONFIG_AND_REGISTER
(
uint32_t
,
audioMtu
,
Config
::
Rtp
::
kAudioMtuSize
);
m_pRtpMaker_aac
.
reset
(
new
RtpMaker_AAC
(
lam
,
ssrc
,
audioMtu
,
m
_audio
->
iSampleRate
));
_pRtpMaker_aac
.
reset
(
new
RtpMaker_AAC
(
lam
,
ssrc
,
audioMtu
,
_audio
->
iSampleRate
));
}
if
(
!
m_bSdp_gotAAC
&&
m
_audio
&&
pcAdtsHeader
)
{
if
(
!
_bSdp_gotAAC
&&
_audio
&&
pcAdtsHeader
)
{
makeSDP_AAC
((
unsigned
char
*
)
pcAdtsHeader
);
}
if
(
uiStamp
==
0
){
uiStamp
=
(
uint32_t
)
m
_aTicker
[
1
].
elapsedTime
();
uiStamp
=
(
uint32_t
)
_aTicker
[
1
].
elapsedTime
();
}
if
(
pcDataWithoutAdts
&&
iDataLen
){
m
_pRtpMaker_aac
->
makeRtp
(
pcDataWithoutAdts
,
iDataLen
,
uiStamp
);
_pRtpMaker_aac
->
makeRtp
(
pcDataWithoutAdts
,
iDataLen
,
uiStamp
);
}
}
...
...
@@ -161,77 +161,77 @@ inline void DevChannel::makeSDP_264(unsigned char *pcData, int iDataLen) {
switch
(
pcData
[
offset
]
&
0x1F
)
{
case
7
:
/*SPS frame*/
{
if
(
m
_uiSPSLen
!=
0
)
{
if
(
_uiSPSLen
!=
0
)
{
break
;
}
memcpy
(
m
_aucSPS
,
pcData
+
offset
,
iDataLen
-
offset
);
m
_uiSPSLen
=
iDataLen
-
offset
;
memcpy
(
_aucSPS
,
pcData
+
offset
,
iDataLen
-
offset
);
_uiSPSLen
=
iDataLen
-
offset
;
}
break
;
case
8
:
/*PPS frame*/
{
if
(
m
_uiPPSLen
!=
0
)
{
if
(
_uiPPSLen
!=
0
)
{
break
;
}
memcpy
(
m
_aucPPS
,
pcData
+
offset
,
iDataLen
-
offset
);
m
_uiPPSLen
=
iDataLen
-
offset
;
memcpy
(
_aucPPS
,
pcData
+
offset
,
iDataLen
-
offset
);
_uiPPSLen
=
iDataLen
-
offset
;
}
break
;
default
:
break
;
}
if
(
!
m_uiSPSLen
||
!
m
_uiPPSLen
)
{
if
(
!
_uiSPSLen
||
!
_uiPPSLen
)
{
return
;
}
char
acTmp
[
256
];
int
profile_level_id
=
0
;
if
(
m
_uiSPSLen
>=
4
)
{
// sanity check
profile_level_id
=
(
m_aucSPS
[
1
]
<<
16
)
|
(
m_aucSPS
[
2
]
<<
8
)
|
m
_aucSPS
[
3
];
// profile_idc|constraint_setN_flag|level_idc
if
(
_uiSPSLen
>=
4
)
{
// sanity check
profile_level_id
=
(
_aucSPS
[
1
]
<<
16
)
|
(
_aucSPS
[
2
]
<<
8
)
|
_aucSPS
[
3
];
// profile_idc|constraint_setN_flag|level_idc
}
//视频通道
m
_strSdp
+=
StrPrinter
<<
"m=video 0 RTP/AVP "
<<
m
_pRtpMaker_h264
->
getPlayloadType
()
<<
"
\r\n
"
<<
endl
;
m
_strSdp
+=
"b=AS:5100
\r\n
"
;
m_strSdp
+=
StrPrinter
<<
"a=rtpmap:"
<<
m
_pRtpMaker_h264
->
getPlayloadType
()
<<
" H264/"
<<
m
_pRtpMaker_h264
->
getSampleRate
()
<<
"
\r\n
"
<<
endl
;
m_strSdp
+=
StrPrinter
<<
"a=fmtp:"
<<
m
_pRtpMaker_h264
->
getPlayloadType
()
_strSdp
+=
StrPrinter
<<
"m=video 0 RTP/AVP "
<<
_pRtpMaker_h264
->
getPlayloadType
()
<<
"
\r\n
"
<<
endl
;
_strSdp
+=
"b=AS:5100
\r\n
"
;
_strSdp
+=
StrPrinter
<<
"a=rtpmap:"
<<
_pRtpMaker_h264
->
getPlayloadType
()
<<
" H264/"
<<
_pRtpMaker_h264
->
getSampleRate
()
<<
"
\r\n
"
<<
endl
;
_strSdp
+=
StrPrinter
<<
"a=fmtp:"
<<
_pRtpMaker_h264
->
getPlayloadType
()
<<
" packetization-mode=1;profile-level-id="
<<
endl
;
memset
(
acTmp
,
0
,
sizeof
(
acTmp
));
sprintf
(
acTmp
,
"%06X"
,
profile_level_id
);
m
_strSdp
+=
acTmp
;
m
_strSdp
+=
";sprop-parameter-sets="
;
_strSdp
+=
acTmp
;
_strSdp
+=
";sprop-parameter-sets="
;
memset
(
acTmp
,
0
,
sizeof
(
acTmp
));
av_base64_encode
(
acTmp
,
sizeof
(
acTmp
),
(
uint8_t
*
)
m_aucSPS
,
m
_uiSPSLen
);
av_base64_encode
(
acTmp
,
sizeof
(
acTmp
),
(
uint8_t
*
)
_aucSPS
,
_uiSPSLen
);
//WarnL<<"SPS base64:"<<strTemp;
//WarnL<<"SPS hexdump:"<<hexdump(SPS_BUF, SPS_LEN);
m
_strSdp
+=
acTmp
;
m
_strSdp
+=
","
;
_strSdp
+=
acTmp
;
_strSdp
+=
","
;
memset
(
acTmp
,
0
,
sizeof
(
acTmp
));
av_base64_encode
(
acTmp
,
sizeof
(
acTmp
),
(
uint8_t
*
)
m_aucPPS
,
m
_uiPPSLen
);
m
_strSdp
+=
acTmp
;
m
_strSdp
+=
"
\r\n
"
;
if
(
m_video
->
iFrameRate
>
0
&&
m_video
->
iHeight
>
0
&&
m
_video
->
iWidth
>
0
)
{
m
_strSdp
+=
"a=framerate:"
;
m_strSdp
+=
StrPrinter
<<
m
_video
->
iFrameRate
<<
endl
;
m
_strSdp
+=
StrPrinter
<<
"
\r\n
a=framesize:"
<<
m
_pRtpMaker_h264
->
getPlayloadType
()
<<
" "
<<
endl
;
m_strSdp
+=
StrPrinter
<<
m
_video
->
iWidth
<<
endl
;
m
_strSdp
+=
"-"
;
m_strSdp
+=
StrPrinter
<<
m
_video
->
iHeight
<<
endl
;
m
_strSdp
+=
"
\r\n
"
;
av_base64_encode
(
acTmp
,
sizeof
(
acTmp
),
(
uint8_t
*
)
_aucPPS
,
_uiPPSLen
);
_strSdp
+=
acTmp
;
_strSdp
+=
"
\r\n
"
;
if
(
_video
->
iFrameRate
>
0
&&
_video
->
iHeight
>
0
&&
_video
->
iWidth
>
0
)
{
_strSdp
+=
"a=framerate:"
;
_strSdp
+=
StrPrinter
<<
_video
->
iFrameRate
<<
endl
;
_strSdp
+=
StrPrinter
<<
"
\r\n
a=framesize:"
<<
_pRtpMaker_h264
->
getPlayloadType
()
<<
" "
<<
endl
;
_strSdp
+=
StrPrinter
<<
_video
->
iWidth
<<
endl
;
_strSdp
+=
"-"
;
_strSdp
+=
StrPrinter
<<
_video
->
iHeight
<<
endl
;
_strSdp
+=
"
\r\n
"
;
}
m
_strSdp
+=
StrPrinter
<<
"a=control:trackID="
<<
m
_pRtpMaker_h264
->
getInterleaved
()
/
2
<<
"
\r\n
"
<<
endl
;
m
_bSdp_gotH264
=
true
;
if
(
m
_audio
)
{
if
(
m
_bSdp_gotAAC
)
{
makeSDP
(
m
_strSdp
);
_strSdp
+=
StrPrinter
<<
"a=control:trackID="
<<
_pRtpMaker_h264
->
getInterleaved
()
/
2
<<
"
\r\n
"
<<
endl
;
_bSdp_gotH264
=
true
;
if
(
_audio
)
{
if
(
_bSdp_gotAAC
)
{
makeSDP
(
_strSdp
);
}
}
else
{
makeSDP
(
m
_strSdp
);
makeSDP
(
_strSdp
);
}
}
...
...
@@ -244,27 +244,27 @@ inline void DevChannel::makeSDP_AAC(unsigned char *fixedHeader) {
char
fConfigStr
[
5
]
=
{
0
};
sprintf
(
fConfigStr
,
"%02X%02x"
,
(
uint8_t
)
audioSpecificConfig
[
0
],(
uint8_t
)
audioSpecificConfig
[
1
]);
m
_strSdp
+=
StrPrinter
<<
"m=audio 0 RTP/AVP "
<<
m
_pRtpMaker_aac
->
getPlayloadType
()
<<
"
\r\n
"
<<
endl
;
m
_strSdp
+=
"b=AS:96
\r\n
"
;
m_strSdp
+=
StrPrinter
<<
"a=rtpmap:"
<<
m
_pRtpMaker_aac
->
getPlayloadType
()
<<
" MPEG4-GENERIC/"
<<
m
_pRtpMaker_aac
->
getSampleRate
()
<<
"
\r\n
"
_strSdp
+=
StrPrinter
<<
"m=audio 0 RTP/AVP "
<<
_pRtpMaker_aac
->
getPlayloadType
()
<<
"
\r\n
"
<<
endl
;
_strSdp
+=
"b=AS:96
\r\n
"
;
_strSdp
+=
StrPrinter
<<
"a=rtpmap:"
<<
_pRtpMaker_aac
->
getPlayloadType
()
<<
" MPEG4-GENERIC/"
<<
_pRtpMaker_aac
->
getSampleRate
()
<<
"
\r\n
"
<<
endl
;
m_strSdp
+=
StrPrinter
<<
"a=fmtp:"
<<
m
_pRtpMaker_aac
->
getPlayloadType
()
_strSdp
+=
StrPrinter
<<
"a=fmtp:"
<<
_pRtpMaker_aac
->
getPlayloadType
()
<<
" streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config="
<<
endl
;
m
_strSdp
+=
fConfigStr
;
m
_strSdp
+=
"
\r\n
"
;
m
_strSdp
+=
StrPrinter
<<
"a=control:trackID="
<<
m
_pRtpMaker_aac
->
getInterleaved
()
/
2
<<
"
\r\n
"
<<
endl
;
_strSdp
+=
fConfigStr
;
_strSdp
+=
"
\r\n
"
;
_strSdp
+=
StrPrinter
<<
"a=control:trackID="
<<
_pRtpMaker_aac
->
getInterleaved
()
/
2
<<
"
\r\n
"
<<
endl
;
m
_bSdp_gotAAC
=
true
;
if
(
m
_video
)
{
if
(
m
_bSdp_gotH264
)
{
makeSDP
(
m
_strSdp
);
_bSdp_gotAAC
=
true
;
if
(
_video
)
{
if
(
_bSdp_gotH264
)
{
makeSDP
(
_strSdp
);
}
}
else
{
makeSDP
(
m
_strSdp
);
makeSDP
(
_strSdp
);
}
}
...
...
@@ -273,35 +273,35 @@ void DevChannel::makeSDP(const string& strSdp) {
}
void
DevChannel
::
initVideo
(
const
VideoInfo
&
info
)
{
m
_video
.
reset
(
new
VideoInfo
(
info
));
_video
.
reset
(
new
VideoInfo
(
info
));
}
void
DevChannel
::
initAudio
(
const
AudioInfo
&
info
)
{
m
_audio
.
reset
(
new
AudioInfo
(
info
));
m
_pAdtsHeader
=
std
::
make_shared
<
AACFrame
>
();
_audio
.
reset
(
new
AudioInfo
(
info
));
_pAdtsHeader
=
std
::
make_shared
<
AACFrame
>
();
m
_pAdtsHeader
->
syncword
=
0x0FFF
;
m
_pAdtsHeader
->
id
=
0
;
m
_pAdtsHeader
->
layer
=
0
;
m
_pAdtsHeader
->
protection_absent
=
1
;
m
_pAdtsHeader
->
profile
=
info
.
iProfile
;
//audioObjectType - 1;
_pAdtsHeader
->
syncword
=
0x0FFF
;
_pAdtsHeader
->
id
=
0
;
_pAdtsHeader
->
layer
=
0
;
_pAdtsHeader
->
protection_absent
=
1
;
_pAdtsHeader
->
profile
=
info
.
iProfile
;
//audioObjectType - 1;
int
i
=
0
;
for
(
auto
rate
:
samplingFrequencyTable
){
if
(
rate
==
info
.
iSampleRate
){
m
_pAdtsHeader
->
sf_index
=
i
;
_pAdtsHeader
->
sf_index
=
i
;
};
++
i
;
}
m
_pAdtsHeader
->
private_bit
=
0
;
m
_pAdtsHeader
->
channel_configuration
=
info
.
iChannel
;
m
_pAdtsHeader
->
original
=
0
;
m
_pAdtsHeader
->
home
=
0
;
m
_pAdtsHeader
->
copyright_identification_bit
=
0
;
m
_pAdtsHeader
->
copyright_identification_start
=
0
;
m
_pAdtsHeader
->
aac_frame_length
=
7
;
m
_pAdtsHeader
->
adts_buffer_fullness
=
2047
;
m
_pAdtsHeader
->
no_raw_data_blocks_in_frame
=
0
;
_pAdtsHeader
->
private_bit
=
0
;
_pAdtsHeader
->
channel_configuration
=
info
.
iChannel
;
_pAdtsHeader
->
original
=
0
;
_pAdtsHeader
->
home
=
0
;
_pAdtsHeader
->
copyright_identification_bit
=
0
;
_pAdtsHeader
->
copyright_identification_start
=
0
;
_pAdtsHeader
->
aac_frame_length
=
7
;
_pAdtsHeader
->
adts_buffer_fullness
=
2047
;
_pAdtsHeader
->
no_raw_data_blocks_in_frame
=
0
;
}
}
/* namespace DEV */
...
...
src/Device/Device.h
查看文件 @
39baaebc
...
...
@@ -102,25 +102,25 @@ private:
inline
void
makeSDP_AAC
(
unsigned
char
*
pucData
);
inline
void
makeSDP
(
const
string
&
strSdp
);
#ifdef ENABLE_X264
std
::
shared_ptr
<
H264Encoder
>
m
_pH264Enc
;
std
::
shared_ptr
<
H264Encoder
>
_pH264Enc
;
#endif //ENABLE_X264
#ifdef ENABLE_FAAC
std
::
shared_ptr
<
AACEncoder
>
m
_pAacEnc
;
std
::
shared_ptr
<
AACEncoder
>
_pAacEnc
;
#endif //ENABLE_FAAC
RtpMaker_AAC
::
Ptr
m
_pRtpMaker_aac
;
RtpMaker_H264
::
Ptr
m
_pRtpMaker_h264
;
bool
m
_bSdp_gotH264
=
false
;
bool
m
_bSdp_gotAAC
=
false
;
unsigned
char
m
_aucSPS
[
256
];
unsigned
int
m
_uiSPSLen
=
0
;
unsigned
char
m
_aucPPS
[
256
];
unsigned
int
m
_uiPPSLen
=
0
;
std
::
shared_ptr
<
VideoInfo
>
m
_video
;
std
::
shared_ptr
<
AudioInfo
>
m
_audio
;
SmoothTicker
m
_aTicker
[
2
];
std
::
shared_ptr
<
AACFrame
>
m
_pAdtsHeader
;
RtpMaker_AAC
::
Ptr
_pRtpMaker_aac
;
RtpMaker_H264
::
Ptr
_pRtpMaker_h264
;
bool
_bSdp_gotH264
=
false
;
bool
_bSdp_gotAAC
=
false
;
unsigned
char
_aucSPS
[
256
];
unsigned
int
_uiSPSLen
=
0
;
unsigned
char
_aucPPS
[
256
];
unsigned
int
_uiPPSLen
=
0
;
std
::
shared_ptr
<
VideoInfo
>
_video
;
std
::
shared_ptr
<
AudioInfo
>
_audio
;
SmoothTicker
_aTicker
[
2
];
std
::
shared_ptr
<
AACFrame
>
_pAdtsHeader
;
};
...
...
src/Device/PlayerProxy.cpp
查看文件 @
39baaebc
...
...
@@ -74,12 +74,12 @@ PlayerProxy::PlayerProxy(const char *strVhost,
bool
bEnableHls
,
bool
bEnableMp4
,
int
iRetryCount
){
m
_strVhost
=
strVhost
;
m
_strApp
=
strApp
;
m
_strSrc
=
strSrc
;
m
_bEnableHls
=
bEnableHls
;
m
_bEnableMp4
=
bEnableMp4
;
m
_iRetryCount
=
iRetryCount
;
_strVhost
=
strVhost
;
_strApp
=
strApp
;
_strSrc
=
strSrc
;
_bEnableHls
=
bEnableHls
;
_bEnableMp4
=
bEnableMp4
;
_iRetryCount
=
iRetryCount
;
}
void
PlayerProxy
::
play
(
const
char
*
strUrl
)
{
weak_ptr
<
PlayerProxy
>
weakSelf
=
shared_from_this
();
...
...
@@ -90,9 +90,9 @@ void PlayerProxy::play(const char* strUrl) {
// if(!strongSelf){
// return;
// }
// if(strongSelf->
m
_pChn){
// strongSelf->
m
_pChn->inputH264((char *)data.data(), data.size(), data.timeStamp);
// if(!strongSelf->
m
_haveAudio){
// if(strongSelf->_pChn){
// strongSelf->_pChn->inputH264((char *)data.data(), data.size(), data.timeStamp);
// if(!strongSelf->_haveAudio){
// strongSelf->makeMuteAudio(data.timeStamp);
// }
// }else{
...
...
@@ -104,8 +104,8 @@ void PlayerProxy::play(const char* strUrl) {
// if(!strongSelf){
// return;
// }
// if(strongSelf->
m
_pChn){
// strongSelf->
m
_pChn->inputAAC((char *)data.data(), data.size(), data.timeStamp);
// if(strongSelf->_pChn){
// strongSelf->_pChn->inputAAC((char *)data.data(), data.size(), data.timeStamp);
// }else{
// strongSelf->initMedia();
// }
...
...
@@ -121,7 +121,7 @@ void PlayerProxy::play(const char* strUrl) {
if
(
!
err
)
{
// 播放成功
*
piFailedCnt
=
0
;
//连续播放失败次数清0
}
else
if
(
*
piFailedCnt
<
strongSelf
->
m_iRetryCount
||
strongSelf
->
m
_iRetryCount
<
0
)
{
}
else
if
(
*
piFailedCnt
<
strongSelf
->
_iRetryCount
||
strongSelf
->
_iRetryCount
<
0
)
{
// 播放失败,延时重试播放
strongSelf
->
rePlay
(
strUrlTmp
,(
*
piFailedCnt
)
++
);
}
...
...
@@ -131,11 +131,11 @@ void PlayerProxy::play(const char* strUrl) {
if
(
!
strongSelf
)
{
return
;
}
if
(
strongSelf
->
m
_pChn
)
{
strongSelf
->
m
_pChn
.
reset
();
if
(
strongSelf
->
_pChn
)
{
strongSelf
->
_pChn
.
reset
();
}
//播放异常中断,延时重试播放
if
(
*
piFailedCnt
<
strongSelf
->
m_iRetryCount
||
strongSelf
->
m
_iRetryCount
<
0
)
{
if
(
*
piFailedCnt
<
strongSelf
->
_iRetryCount
||
strongSelf
->
_iRetryCount
<
0
)
{
strongSelf
->
rePlay
(
strUrlTmp
,(
*
piFailedCnt
)
++
);
}
});
...
...
@@ -166,8 +166,8 @@ void PlayerProxy::initMedia() {
if
(
!
isInited
())
{
return
;
}
m_pChn
.
reset
(
new
DevChannel
(
m_strVhost
.
data
(),
m_strApp
.
data
(),
m_strSrc
.
data
(),
getDuration
(),
m_bEnableHls
,
m
_bEnableMp4
));
m
_pChn
->
setListener
(
shared_from_this
());
_pChn
.
reset
(
new
DevChannel
(
_strVhost
.
data
(),
_strApp
.
data
(),
_strSrc
.
data
(),
getDuration
(),
_bEnableHls
,
_bEnableMp4
));
_pChn
->
setListener
(
shared_from_this
());
//todo(xzl) 修复此处
...
...
@@ -176,22 +176,22 @@ void PlayerProxy::initMedia() {
// info.iFrameRate = getVideoFps();
// info.iWidth = getVideoWidth();
// info.iHeight = getVideoHeight();
//
m
_pChn->initVideo(info);
// _pChn->initVideo(info);
// }
//
//
m
_haveAudio = containAudio();
// _haveAudio = containAudio();
// if (containAudio()) {
// AudioInfo info;
// info.iSampleRate = getAudioSampleRate();
// info.iChannel = getAudioChannel();
// info.iSampleBit = getAudioSampleBit();
//
m
_pChn->initAudio(info);
// _pChn->initAudio(info);
// }else{
// AudioInfo info;
// info.iSampleRate = MUTE_ADTS_SAMPLE_RATE;
// info.iChannel = MUTE_ADTS_CHN_CNT;
// info.iSampleBit = MUTE_ADTS_SAMPLE_BIT;
//
m
_pChn->initAudio(info);
// _pChn->initAudio(info);
// }
}
bool
PlayerProxy
::
shutDown
()
{
...
...
@@ -202,7 +202,7 @@ bool PlayerProxy::shutDown() {
executor
->
async_first
([
weakSlef
]()
{
auto
stronSelf
=
weakSlef
.
lock
();
if
(
stronSelf
)
{
stronSelf
->
m
_pChn
.
reset
();
stronSelf
->
_pChn
.
reset
();
stronSelf
->
teardown
();
}
});
...
...
@@ -212,10 +212,10 @@ bool PlayerProxy::shutDown() {
void
PlayerProxy
::
makeMuteAudio
(
uint32_t
stamp
)
{
auto
iAudioIndex
=
stamp
/
MUTE_ADTS_DATA_MS
;
if
(
m
_iAudioIndex
!=
iAudioIndex
){
m
_iAudioIndex
=
iAudioIndex
;
m_pChn
->
inputAAC
((
char
*
)
MUTE_ADTS_DATA
,
MUTE_ADTS_DATA_LEN
,
m
_iAudioIndex
*
MUTE_ADTS_DATA_MS
);
//DebugL <<
m
_iAudioIndex * MUTE_ADTS_DATA_MS << " " << stamp;
if
(
_iAudioIndex
!=
iAudioIndex
){
_iAudioIndex
=
iAudioIndex
;
_pChn
->
inputAAC
((
char
*
)
MUTE_ADTS_DATA
,
MUTE_ADTS_DATA_LEN
,
_iAudioIndex
*
MUTE_ADTS_DATA_MS
);
//DebugL << _iAudioIndex * MUTE_ADTS_DATA_MS << " " << stamp;
}
}
...
...
src/Device/PlayerProxy.h
查看文件 @
39baaebc
...
...
@@ -60,15 +60,15 @@ private:
void
rePlay
(
const
string
&
strUrl
,
int
iFailedCnt
);
void
makeMuteAudio
(
uint32_t
stamp
);
private
:
bool
m
_bEnableHls
;
bool
m
_bEnableMp4
;
int
m
_iRetryCount
;
DevChannel
::
Ptr
m
_pChn
;
string
m
_strVhost
;
string
m
_strApp
;
string
m
_strSrc
;
bool
m
_haveAudio
=
false
;
int
m
_iAudioIndex
=
0
;
bool
_bEnableHls
;
bool
_bEnableMp4
;
int
_iRetryCount
;
DevChannel
::
Ptr
_pChn
;
string
_strVhost
;
string
_strApp
;
string
_strSrc
;
bool
_haveAudio
=
false
;
int
_iAudioIndex
=
0
;
};
}
/* namespace Player */
...
...
src/H264/H264Parser.cpp
查看文件 @
39baaebc
...
...
@@ -37,19 +37,19 @@ H264Parser::~H264Parser(){
}
void
H264Parser
::
inputH264
(
const
string
&
h264
,
uint32_t
dts
){
m
_parser
.
SetStream
((
const
uint8_t
*
)
h264
.
data
(),
h264
.
size
());
_parser
.
SetStream
((
const
uint8_t
*
)
h264
.
data
(),
h264
.
size
());
while
(
true
)
{
if
(
media
::
H264Parser
::
kOk
!=
m_parser
.
AdvanceToNextNALU
(
&
m
_nalu
)){
if
(
media
::
H264Parser
::
kOk
!=
_parser
.
AdvanceToNextNALU
(
&
_nalu
)){
break
;
}
switch
(
m
_nalu
.
nal_unit_type
)
{
switch
(
_nalu
.
nal_unit_type
)
{
case
media
:
:
H264NALU
::
kNonIDRSlice
:
case
media
:
:
H264NALU
::
kIDRSlice
:
{
if
(
media
::
H264Parser
::
kOk
==
m_parser
.
ParseSliceHeader
(
m_nalu
,
&
m
_shdr
)){
const
media
::
H264SPS
*
pPps
=
m_parser
.
GetSPS
(
m
_shdr
.
pic_parameter_set_id
);
if
(
media
::
H264Parser
::
kOk
==
_parser
.
ParseSliceHeader
(
_nalu
,
&
_shdr
)){
const
media
::
H264SPS
*
pPps
=
_parser
.
GetSPS
(
_shdr
.
pic_parameter_set_id
);
if
(
pPps
)
{
m_poc
.
ComputePicOrderCnt
(
pPps
,
m_shdr
,
&
m
_iNowPOC
);
_poc
.
ComputePicOrderCnt
(
pPps
,
_shdr
,
&
_iNowPOC
);
computePts
(
dts
);
}
}
...
...
@@ -57,12 +57,12 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
break
;
case
media
:
:
H264NALU
::
kSPS
:
{
int
sps_id
;
m
_parser
.
ParseSPS
(
&
sps_id
);
_parser
.
ParseSPS
(
&
sps_id
);
}
break
;
case
media
:
:
H264NALU
::
kPPS
:
{
int
pps_id
;
m
_parser
.
ParsePPS
(
&
pps_id
);
_parser
.
ParsePPS
(
&
pps_id
);
}
break
;
default
:
...
...
@@ -72,33 +72,33 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
}
void
H264Parser
::
computePts
(
uint32_t
iNowDTS
)
{
auto
iPOCInc
=
m_iNowPOC
-
m
_iLastPOC
;
if
(
m
_shdr
.
slice_type
%
5
==
1
)
{
auto
iPOCInc
=
_iNowPOC
-
_iLastPOC
;
if
(
_shdr
.
slice_type
%
5
==
1
)
{
//这是B帧
m_iNowPTS
=
m_iLastPTS
+
m
_iMsPerPOC
*
(
iPOCInc
);
_iNowPTS
=
_iLastPTS
+
_iMsPerPOC
*
(
iPOCInc
);
}
else
{
//这是I帧或者P帧
m
_iNowPTS
=
iNowDTS
;
_iNowPTS
=
iNowDTS
;
//计算每一POC的时间
if
(
iPOCInc
==
0
){
WarnL
<<
"iPOCInc = 0,"
<<
m_iNowPOC
<<
" "
<<
m
_iLastPOC
;
WarnL
<<
"iPOCInc = 0,"
<<
_iNowPOC
<<
" "
<<
_iLastPOC
;
}
else
{
m_iMsPerPOC
=
(
m_iNowPTS
-
m
_iLastPTS
)
/
iPOCInc
;
_iMsPerPOC
=
(
_iNowPTS
-
_iLastPTS
)
/
iPOCInc
;
}
m_iLastPTS
=
m
_iNowPTS
;
m_iLastPOC
=
m
_iNowPOC
;
_iLastPTS
=
_iNowPTS
;
_iLastPOC
=
_iNowPOC
;
}
// DebugL <<
m
_shdr.slice_type
// DebugL << _shdr.slice_type
// <<"\r\nNOW:"
// <<
m
_iNowPOC << " "
// <<
m
_iNowPTS << " "
// << _iNowPOC << " "
// << _iNowPTS << " "
// << iNowDTS << " "
// << "\r\nLST:"
// <<
m
_iLastPOC << " "
// <<
m
_iLastPTS << " "
// <<
m
_iMsPerPOC << endl;
// << _iLastPOC << " "
// << _iLastPTS << " "
// << _iMsPerPOC << endl;
}
...
...
src/H264/H264Parser.h
查看文件 @
39baaebc
...
...
@@ -44,29 +44,29 @@ public:
void
inputH264
(
const
string
&
h264
,
uint32_t
dts
);
int32_t
getPOC
()
const
{
return
m
_iNowPOC
;
return
_iNowPOC
;
}
int
getSliceType
()
const
{
return
m
_shdr
.
slice_type
;
return
_shdr
.
slice_type
;
}
int
getNaluType
()
const
{
return
m
_nalu
.
nal_unit_type
;
return
_nalu
.
nal_unit_type
;
}
uint32_t
getPts
()
const
{
return
m
_iNowPTS
;
return
_iNowPTS
;
}
private
:
media
::
H264Parser
m
_parser
;
media
::
H264POC
m
_poc
;
media
::
H264NALU
m
_nalu
;
media
::
H264SliceHeader
m
_shdr
;
media
::
H264Parser
_parser
;
media
::
H264POC
_poc
;
media
::
H264NALU
_nalu
;
media
::
H264SliceHeader
_shdr
;
int32_t
m
_iNowPOC
=
INT32_MAX
;
int32_t
m
_iLastPOC
=
INT32_MAX
;
int32_t
_iNowPOC
=
INT32_MAX
;
int32_t
_iLastPOC
=
INT32_MAX
;
uint32_t
m
_iNowPTS
=
INT32_MAX
;
uint32_t
m
_iLastPTS
=
INT32_MAX
;
int32_t
m
_iMsPerPOC
=
30
;
uint32_t
_iNowPTS
=
INT32_MAX
;
uint32_t
_iLastPTS
=
INT32_MAX
;
int32_t
_iMsPerPOC
=
30
;
void
computePts
(
uint32_t
dts
);
...
...
src/Http/HttpSession.cpp
查看文件 @
39baaebc
...
...
@@ -110,7 +110,7 @@ HttpSession::HttpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::P
pSock
->
setSendTimeOutSecond
(
15
);
GET_CONFIG_AND_REGISTER
(
string
,
rootPath
,
Config
::
Http
::
kRootPath
);
m
_strPath
=
rootPath
;
_strPath
=
rootPath
;
}
HttpSession
::~
HttpSession
()
{
...
...
@@ -125,9 +125,9 @@ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
g_mapCmdIndex
.
emplace
(
"POST"
,
&
HttpSession
::
Handle_Req_POST
);
},
nullptr
);
m
_parser
.
Parse
(
header
);
urlDecode
(
m
_parser
);
string
cmd
=
m
_parser
.
Method
();
_parser
.
Parse
(
header
);
urlDecode
(
_parser
);
string
cmd
=
_parser
.
Method
();
auto
it
=
g_mapCmdIndex
.
find
(
cmd
);
if
(
it
==
g_mapCmdIndex
.
end
())
{
WarnL
<<
cmd
;
...
...
@@ -143,15 +143,15 @@ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
shutdown
();
}
//清空解析器节省内存
m
_parser
.
Clear
();
_parser
.
Clear
();
//返回content长度
return
content_len
;
}
void
HttpSession
::
onRecvContent
(
const
char
*
data
,
uint64_t
len
)
{
if
(
m
_contentCallBack
){
if
(
!
m
_contentCallBack
(
data
,
len
)){
m
_contentCallBack
=
nullptr
;
if
(
_contentCallBack
){
if
(
!
_contentCallBack
(
data
,
len
)){
_contentCallBack
=
nullptr
;
}
}
}
...
...
@@ -160,7 +160,7 @@ void HttpSession::onRecv(const Buffer::Ptr &pBuf) {
onRecv
(
pBuf
->
data
(),
pBuf
->
size
());
}
void
HttpSession
::
onRecv
(
const
char
*
data
,
int
size
){
m
_ticker
.
resetTime
();
_ticker
.
resetTime
();
input
(
data
,
size
);
}
...
...
@@ -168,11 +168,11 @@ void HttpSession::onError(const SockException& err) {
//WarnL << err.what();
GET_CONFIG_AND_REGISTER
(
uint32_t
,
iFlowThreshold
,
Broadcast
::
kFlowThreshold
);
if
(
m
_ui64TotalBytes
>
iFlowThreshold
*
1024
){
if
(
_ui64TotalBytes
>
iFlowThreshold
*
1024
){
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastFlowReport
,
m
_mediaInfo
,
m
_ui64TotalBytes
,
m
_ticker
.
createdTime
()
/
1000
,
_mediaInfo
,
_ui64TotalBytes
,
_ticker
.
createdTime
()
/
1000
,
*
this
);
}
}
...
...
@@ -180,7 +180,7 @@ void HttpSession::onError(const SockException& err) {
void
HttpSession
::
onManager
()
{
GET_CONFIG_AND_REGISTER
(
uint32_t
,
keepAliveSec
,
Config
::
Http
::
kKeepAliveSecond
);
if
(
m
_ticker
.
elapsedTime
()
>
keepAliveSec
*
1000
){
if
(
_ticker
.
elapsedTime
()
>
keepAliveSec
*
1000
){
//1分钟超时
WarnL
<<
"HttpSession timeouted!"
;
shutdown
();
...
...
@@ -189,7 +189,7 @@ void HttpSession::onManager() {
inline
bool
HttpSession
::
checkWebSocket
(){
auto
Sec_WebSocket_Key
=
m
_parser
[
"Sec-WebSocket-Key"
];
auto
Sec_WebSocket_Key
=
_parser
[
"Sec-WebSocket-Key"
];
if
(
Sec_WebSocket_Key
.
empty
()){
return
false
;
}
...
...
@@ -205,7 +205,7 @@ inline bool HttpSession::checkWebSocket(){
//http-flv 链接格式:http://vhost-url:port/app/streamid.flv?key1=value1&key2=value2
//如果url(除去?以及后面的参数)后缀是.flv,那么表明该url是一个http-flv直播。
inline
bool
HttpSession
::
checkLiveFlvStream
(){
auto
pos
=
strrchr
(
m
_parser
.
Url
().
data
(),
'.'
);
auto
pos
=
strrchr
(
_parser
.
Url
().
data
(),
'.'
);
if
(
!
pos
){
//未找到".flv"后缀
return
false
;
...
...
@@ -215,11 +215,11 @@ inline bool HttpSession::checkLiveFlvStream(){
return
false
;
}
//拼接成完整url
auto
fullUrl
=
string
(
HTTP_SCHEMA
)
+
"://"
+
m_parser
[
"Host"
]
+
m
_parser
.
FullUrl
();
m
_mediaInfo
.
parse
(
fullUrl
);
m_mediaInfo
.
m_streamid
.
erase
(
m_mediaInfo
.
m
_streamid
.
size
()
-
4
);
//去除.flv后缀
auto
fullUrl
=
string
(
HTTP_SCHEMA
)
+
"://"
+
_parser
[
"Host"
]
+
_parser
.
FullUrl
();
_mediaInfo
.
parse
(
fullUrl
);
_mediaInfo
.
_streamid
.
erase
(
_mediaInfo
.
_streamid
.
size
()
-
4
);
//去除.flv后缀
auto
mediaSrc
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
MediaSource
::
find
(
RTMP_SCHEMA
,
m_mediaInfo
.
m_vhost
,
m_mediaInfo
.
m_app
,
m_mediaInfo
.
m
_streamid
));
auto
mediaSrc
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
MediaSource
::
find
(
RTMP_SCHEMA
,
_mediaInfo
.
_vhost
,
_mediaInfo
.
_app
,
_mediaInfo
.
_streamid
));
if
(
!
mediaSrc
){
//该rtmp源不存在
return
false
;
...
...
@@ -262,7 +262,7 @@ inline bool HttpSession::checkLiveFlvStream(){
onRes
(
err
);
});
};
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
m
_mediaInfo
,
invoker
,
*
this
);
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
_mediaInfo
,
invoker
,
*
this
);
if
(
!
flag
){
//该事件无人监听,默认不鉴权
onRes
(
""
);
...
...
@@ -273,10 +273,10 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
//先看看是否为WebSocket请求
if
(
checkWebSocket
()){
content_len
=
-
1
;
auto
parserCopy
=
m
_parser
;
m
_contentCallBack
=
[
this
,
parserCopy
](
const
char
*
data
,
uint64_t
len
){
auto
parserCopy
=
_parser
;
_contentCallBack
=
[
this
,
parserCopy
](
const
char
*
data
,
uint64_t
len
){
onRecvWebSocketData
(
parserCopy
,
data
,
len
);
//
m
_contentCallBack是可持续的,后面还要处理后续数据
//_contentCallBack是可持续的,后面还要处理后续数据
return
true
;
};
return
true
;
...
...
@@ -293,19 +293,19 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
}
//事件未被拦截,则认为是http下载请求
auto
fullUrl
=
string
(
HTTP_SCHEMA
)
+
"://"
+
m_parser
[
"Host"
]
+
m
_parser
.
FullUrl
();
m
_mediaInfo
.
parse
(
fullUrl
);
auto
fullUrl
=
string
(
HTTP_SCHEMA
)
+
"://"
+
_parser
[
"Host"
]
+
_parser
.
FullUrl
();
_mediaInfo
.
parse
(
fullUrl
);
string
strFile
=
m_strPath
+
"/"
+
m_mediaInfo
.
m_vhost
+
m
_parser
.
Url
();
string
strFile
=
_strPath
+
"/"
+
_mediaInfo
.
_vhost
+
_parser
.
Url
();
/////////////HTTP连接是否需要被关闭////////////////
GET_CONFIG_AND_REGISTER
(
uint32_t
,
reqCnt
,
Config
::
Http
::
kMaxReqCount
);
bool
bClose
=
(
strcasecmp
(
m_parser
[
"Connection"
].
data
(),
"close"
)
==
0
)
||
(
++
m
_iReqCnt
>
reqCnt
);
bool
bClose
=
(
strcasecmp
(
_parser
[
"Connection"
].
data
(),
"close"
)
==
0
)
||
(
++
_iReqCnt
>
reqCnt
);
//访问的是文件夹
if
(
strFile
.
back
()
==
'/'
)
{
//生成文件夹菜单索引
string
strMeun
;
if
(
!
makeMeun
(
strFile
,
m_mediaInfo
.
m
_vhost
,
strMeun
))
{
if
(
!
makeMeun
(
strFile
,
_mediaInfo
.
_vhost
,
strMeun
))
{
//文件夹不存在
sendNotFound
(
bClose
);
return
!
bClose
;
...
...
@@ -334,7 +334,7 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
}
//判断是不是分节下载
auto
&
strRange
=
m
_parser
[
"Range"
];
auto
&
strRange
=
_parser
[
"Range"
];
int64_t
iRangeStart
=
0
,
iRangeEnd
=
0
;
iRangeStart
=
atoll
(
FindField
(
strRange
.
data
(),
"bytes="
,
"-"
).
data
());
iRangeEnd
=
atoll
(
FindField
(
strRange
.
data
(),
"-"
,
"
\r\n
"
).
data
());
...
...
@@ -355,7 +355,7 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
//分节下载返回Content-Range头
httpHeader
.
emplace
(
"Content-Range"
,
StrPrinter
<<
"bytes "
<<
iRangeStart
<<
"-"
<<
iRangeEnd
<<
"/"
<<
tFileStat
.
st_size
<<
endl
);
}
auto
Origin
=
m
_parser
[
"Origin"
];
auto
Origin
=
_parser
[
"Origin"
];
if
(
!
Origin
.
empty
()){
httpHeader
[
"Access-Control-Allow-Origin"
]
=
Origin
;
httpHeader
[
"Access-Control-Allow-Credentials"
]
=
"true"
;
...
...
@@ -377,7 +377,7 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
auto
strongSelf
=
weakSelf
.
lock
();
while
(
*
piLeft
&&
strongSelf
){
//更新超时定时器
strongSelf
->
m
_ticker
.
resetTime
();
strongSelf
->
_ticker
.
resetTime
();
//从循环池获取一个内存片
auto
sendBuf
=
strongSelf
->
obtainBuffer
();
sendBuf
->
setCapacity
(
sendBufSize
);
...
...
@@ -449,7 +449,7 @@ inline bool HttpSession::makeMeun(const string &strFullPath,const string &vhost,
"<h1>文件索引:"
;
string
strPath
=
strFullPath
;
strPath
=
strPath
.
substr
(
m
_strPath
.
length
()
+
vhost
.
length
()
+
1
);
strPath
=
strPath
.
substr
(
_strPath
.
length
()
+
vhost
.
length
()
+
1
);
strRet
+=
strPath
;
strRet
+=
"</h1>
\r\n
"
;
if
(
strPath
!=
"/"
)
{
...
...
@@ -525,7 +525,7 @@ inline void HttpSession::sendResponse(const char* pcStatus, const KeyValue& head
auto
strSend
=
printer
<<
endl
;
//DebugL << strSend;
send
(
strSend
);
m
_ticker
.
resetTime
();
_ticker
.
resetTime
();
}
inline
HttpSession
::
KeyValue
HttpSession
::
makeHttpHeader
(
bool
bClose
,
int64_t
iContentSize
,
const
char
*
pcContentType
)
{
KeyValue
headerOut
;
...
...
@@ -563,7 +563,7 @@ string HttpSession::urlDecode(const string &str){
inline
void
HttpSession
::
urlDecode
(
Parser
&
parser
){
parser
.
setUrl
(
urlDecode
(
parser
.
Url
()));
for
(
auto
&
pr
:
m
_parser
.
getUrlArgs
()){
for
(
auto
&
pr
:
_parser
.
getUrlArgs
()){
const_cast
<
string
&>
(
pr
.
second
)
=
urlDecode
(
pr
.
second
);
}
}
...
...
@@ -572,8 +572,8 @@ inline bool HttpSession::emitHttpEvent(bool doInvoke){
///////////////////是否断开本链接///////////////////////
GET_CONFIG_AND_REGISTER
(
uint32_t
,
reqCnt
,
Config
::
Http
::
kMaxReqCount
);
bool
bClose
=
(
strcasecmp
(
m_parser
[
"Connection"
].
data
(),
"close"
)
==
0
)
||
(
++
m
_iReqCnt
>
reqCnt
);
auto
Origin
=
m
_parser
[
"Origin"
];
bool
bClose
=
(
strcasecmp
(
_parser
[
"Connection"
].
data
(),
"close"
)
==
0
)
||
(
++
_iReqCnt
>
reqCnt
);
auto
Origin
=
_parser
[
"Origin"
];
/////////////////////异步回复Invoker///////////////////////////////
weak_ptr
<
HttpSession
>
weakSelf
=
dynamic_pointer_cast
<
HttpSession
>
(
shared_from_this
());
HttpResponseInvoker
invoker
=
[
weakSelf
,
bClose
,
Origin
](
const
string
&
codeOut
,
const
KeyValue
&
headerOut
,
const
string
&
contentOut
){
...
...
@@ -594,7 +594,7 @@ inline bool HttpSession::emitHttpEvent(bool doInvoke){
};
///////////////////广播HTTP事件///////////////////////////
bool
consumed
=
false
;
//该事件是否被消费
NoticeCenter
::
Instance
().
emitEvent
(
Config
::
Broadcast
::
kBroadcastHttpRequest
,
m
_parser
,
invoker
,
consumed
,
*
this
);
NoticeCenter
::
Instance
().
emitEvent
(
Config
::
Broadcast
::
kBroadcastHttpRequest
,
_parser
,
invoker
,
consumed
,
*
this
);
if
(
!
consumed
&&
doInvoke
){
//该事件无人消费,所以返回404
invoker
(
"404 Not Found"
,
KeyValue
(),
""
);
...
...
@@ -609,7 +609,7 @@ inline bool HttpSession::Handle_Req_POST(int64_t &content_len) {
GET_CONFIG_AND_REGISTER
(
uint64_t
,
maxReqSize
,
Config
::
Http
::
kMaxReqSize
);
GET_CONFIG_AND_REGISTER
(
int
,
maxReqCnt
,
Config
::
Http
::
kMaxReqCount
);
int64_t
totalContentLen
=
m_parser
[
"Content-Length"
].
empty
()
?
-
1
:
atoll
(
m
_parser
[
"Content-Length"
].
data
());
int64_t
totalContentLen
=
_parser
[
"Content-Length"
].
empty
()
?
-
1
:
atoll
(
_parser
[
"Content-Length"
].
data
());
if
(
totalContentLen
==
0
){
//content为空
...
...
@@ -621,34 +621,34 @@ inline bool HttpSession::Handle_Req_POST(int64_t &content_len) {
if
(
totalContentLen
>
0
&&
totalContentLen
<
maxReqSize
){
//返回固定长度的content
content_len
=
totalContentLen
;
auto
parserCopy
=
m
_parser
;
m
_contentCallBack
=
[
this
,
parserCopy
](
const
char
*
data
,
uint64_t
len
){
auto
parserCopy
=
_parser
;
_contentCallBack
=
[
this
,
parserCopy
](
const
char
*
data
,
uint64_t
len
){
//恢复http头
m
_parser
=
parserCopy
;
_parser
=
parserCopy
;
//设置content
m
_parser
.
setContent
(
string
(
data
,
len
));
_parser
.
setContent
(
string
(
data
,
len
));
//触发http事件,emitHttpEvent内部会选择是否关闭连接
emitHttpEvent
(
true
);
//清空数据,节省内存
m
_parser
.
Clear
();
_parser
.
Clear
();
//content已经接收完毕
return
false
;
};
}
else
{
//返回不固定长度的content
content_len
=
-
1
;
auto
parserCopy
=
m
_parser
;
auto
parserCopy
=
_parser
;
std
::
shared_ptr
<
uint64_t
>
recvedContentLen
=
std
::
make_shared
<
uint64_t
>
(
0
);
bool
bClose
=
(
strcasecmp
(
m_parser
[
"Connection"
].
data
(),
"close"
)
==
0
)
||
(
++
m
_iReqCnt
>
maxReqCnt
);
bool
bClose
=
(
strcasecmp
(
_parser
[
"Connection"
].
data
(),
"close"
)
==
0
)
||
(
++
_iReqCnt
>
maxReqCnt
);
m
_contentCallBack
=
[
this
,
parserCopy
,
totalContentLen
,
recvedContentLen
,
bClose
](
const
char
*
data
,
uint64_t
len
){
_contentCallBack
=
[
this
,
parserCopy
,
totalContentLen
,
recvedContentLen
,
bClose
](
const
char
*
data
,
uint64_t
len
){
*
(
recvedContentLen
)
+=
len
;
onRecvUnlimitedContent
(
parserCopy
,
data
,
len
,
totalContentLen
,
*
(
recvedContentLen
));
if
(
*
(
recvedContentLen
)
<
totalContentLen
){
//数据还没接收完毕
//
m
_contentCallBack是可持续的,后面还要处理后续content数据
//_contentCallBack是可持续的,后面还要处理后续content数据
return
true
;
}
...
...
@@ -698,8 +698,8 @@ void HttpSession::onWrite(const Buffer::Ptr &buffer) {
if
(
!
strongSelf
)
{
return
;
}
strongSelf
->
m
_ticker
.
resetTime
();
strongSelf
->
m
_ui64TotalBytes
+=
buffer
->
size
();
strongSelf
->
_ticker
.
resetTime
();
strongSelf
->
_ui64TotalBytes
+=
buffer
->
size
();
strongSelf
->
send
(
buffer
);
});
}
...
...
@@ -714,8 +714,8 @@ void HttpSession::onWrite(const char *data, int len) {
if
(
!
strongSelf
)
{
return
;
}
strongSelf
->
m
_ticker
.
resetTime
();
strongSelf
->
m
_ui64TotalBytes
+=
buffer
->
size
();
strongSelf
->
_ticker
.
resetTime
();
strongSelf
->
_ui64TotalBytes
+=
buffer
->
size
();
strongSelf
->
send
(
buffer
);
});
}
...
...
src/Http/HttpSession.h
查看文件 @
39baaebc
...
...
@@ -101,16 +101,16 @@ protected:
WebSocketSplitter
::
decode
((
uint8_t
*
)
data
,
len
);
}
private
:
Parser
m
_parser
;
string
m
_strPath
;
Ticker
m
_ticker
;
uint32_t
m
_iReqCnt
=
0
;
Parser
_parser
;
string
_strPath
;
Ticker
_ticker
;
uint32_t
_iReqCnt
=
0
;
//消耗的总流量
uint64_t
m
_ui64TotalBytes
=
0
;
uint64_t
_ui64TotalBytes
=
0
;
//flv over http
MediaInfo
m
_mediaInfo
;
MediaInfo
_mediaInfo
;
//处理content数据的callback
function
<
bool
(
const
char
*
data
,
uint64_t
len
)
>
m
_contentCallBack
;
function
<
bool
(
const
char
*
data
,
uint64_t
len
)
>
_contentCallBack
;
private
:
inline
bool
Handle_Req_GET
(
int64_t
&
content_len
);
inline
bool
Handle_Req_POST
(
int64_t
&
content_len
);
...
...
src/Http/HttpsSession.h
查看文件 @
39baaebc
...
...
@@ -40,14 +40,14 @@ class HttpsSession: public HttpSession {
public
:
HttpsSession
(
const
std
::
shared_ptr
<
ThreadPool
>
&
pTh
,
const
Socket
::
Ptr
&
pSock
)
:
HttpSession
(
pTh
,
pSock
){
m
_sslBox
.
setOnEncData
([
&
](
const
char
*
data
,
uint32_t
len
){
_sslBox
.
setOnEncData
([
&
](
const
char
*
data
,
uint32_t
len
){
#if defined(__GNUC__) && (__GNUC__ < 5)
public_send
(
data
,
len
);
#else//defined(__GNUC__) && (__GNUC__ < 5)
HttpSession
::
send
(
obtainBuffer
(
data
,
len
));
#endif//defined(__GNUC__) && (__GNUC__ < 5)
});
m
_sslBox
.
setOnDecData
([
&
](
const
char
*
data
,
uint32_t
len
){
_sslBox
.
setOnDecData
([
&
](
const
char
*
data
,
uint32_t
len
){
#if defined(__GNUC__) && (__GNUC__ < 5)
public_onRecv
(
data
,
len
);
#else//defined(__GNUC__) && (__GNUC__ < 5)
...
...
@@ -56,11 +56,11 @@ public:
});
}
virtual
~
HttpsSession
(){
//
m
_sslBox.shutdown();
//_sslBox.shutdown();
}
void
onRecv
(
const
Buffer
::
Ptr
&
pBuf
)
override
{
TimeTicker
();
m
_sslBox
.
onRecv
(
pBuf
->
data
(),
pBuf
->
size
());
_sslBox
.
onRecv
(
pBuf
->
data
(),
pBuf
->
size
());
}
#if defined(__GNUC__) && (__GNUC__ < 5)
int
public_send
(
const
char
*
data
,
uint32_t
len
){
...
...
@@ -73,10 +73,10 @@ public:
protected
:
virtual
int
send
(
const
Buffer
::
Ptr
&
buf
)
override
{
TimeTicker
();
m
_sslBox
.
onSend
(
buf
->
data
(),
buf
->
size
());
_sslBox
.
onSend
(
buf
->
data
(),
buf
->
size
());
return
buf
->
size
();
}
SSL_Box
m
_sslBox
;
SSL_Box
_sslBox
;
};
...
...
src/MediaFile/HLSMaker.cpp
查看文件 @
39baaebc
...
...
@@ -43,35 +43,35 @@ HLSMaker::HLSMaker(const string& strM3u8File,
if
(
ui32Num
<
1
){
ui32Num
=
1
;
}
m
_ui32BufSize
=
ui32BufSize
;
m
_ui64TsCnt
=
0
;
m
_strM3u8File
=
strM3u8File
;
m
_ui32NumSegments
=
ui32Num
;
m
_ui32SegmentDuration
=
ui32Duration
;
m
_ui32LastStamp
=
0
;
m
_strOutputPrefix
=
strM3u8File
.
substr
(
0
,
strM3u8File
.
rfind
(
'.'
));
m_strFileName
=
m_strOutputPrefix
.
substr
(
m
_strOutputPrefix
.
rfind
(
'/'
)
+
1
);
m_ts
.
init
(
m_strOutputPrefix
+
"-0.ts"
,
m
_ui32BufSize
);
_ui32BufSize
=
ui32BufSize
;
_ui64TsCnt
=
0
;
_strM3u8File
=
strM3u8File
;
_ui32NumSegments
=
ui32Num
;
_ui32SegmentDuration
=
ui32Duration
;
_ui32LastStamp
=
0
;
_strOutputPrefix
=
strM3u8File
.
substr
(
0
,
strM3u8File
.
rfind
(
'.'
));
_strFileName
=
_strOutputPrefix
.
substr
(
_strOutputPrefix
.
rfind
(
'/'
)
+
1
);
_ts
.
init
(
_strOutputPrefix
+
"-0.ts"
,
_ui32BufSize
);
}
HLSMaker
::~
HLSMaker
()
{
m
_ts
.
clear
();
string
strDir
=
m_strOutputPrefix
.
substr
(
0
,
m
_strOutputPrefix
.
rfind
(
'/'
));
_ts
.
clear
();
string
strDir
=
_strOutputPrefix
.
substr
(
0
,
_strOutputPrefix
.
rfind
(
'/'
));
File
::
delete_file
(
strDir
.
data
());
}
bool
HLSMaker
::
write_index_file
(
int
iFirstSegment
,
unsigned
int
uiLastSegment
,
int
iEnd
)
{
char
acWriteBuf
[
1024
];
std
::
shared_ptr
<
FILE
>
pM3u8File
(
File
::
createfile_file
(
m
_strM3u8File
.
data
(),
"w"
),[](
FILE
*
fp
){
std
::
shared_ptr
<
FILE
>
pM3u8File
(
File
::
createfile_file
(
_strM3u8File
.
data
(),
"w"
),[](
FILE
*
fp
){
if
(
fp
){
fflush
(
fp
);
fclose
(
fp
);
}
});
if
(
!
pM3u8File
)
{
WarnL
<<
"Could not open temporary m3u8 index file ("
<<
m
_strM3u8File
<<
"), no index file will be created"
;
WarnL
<<
"Could not open temporary m3u8 index file ("
<<
_strM3u8File
<<
"), no index file will be created"
;
return
false
;
}
if
(
iFirstSegment
<
0
)
{
...
...
@@ -80,13 +80,13 @@ bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, i
//最少1秒
int
maxSegmentDuration
=
0
;
for
(
auto
dur
:
m
_iDurations
)
{
for
(
auto
dur
:
_iDurations
)
{
dur
/=
1000
;
if
(
dur
>
maxSegmentDuration
){
maxSegmentDuration
=
dur
;
}
}
if
(
m
_ui32NumSegments
)
{
if
(
_ui32NumSegments
)
{
snprintf
(
acWriteBuf
,
sizeof
(
acWriteBuf
),
"#EXTM3U
\r\n
"
...
...
@@ -114,8 +114,8 @@ bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, i
snprintf
(
acWriteBuf
,
sizeof
(
acWriteBuf
),
"#EXTINF:%.3f,
\r\n
%s-%u.ts
\r\n
"
,
m
_iDurations
[
i
-
iFirstSegment
]
/
1000.0
,
m
_strFileName
.
c_str
(),
_iDurations
[
i
-
iFirstSegment
]
/
1000.0
,
_strFileName
.
c_str
(),
i
);
if
(
fwrite
(
acWriteBuf
,
strlen
(
acWriteBuf
),
1
,
pM3u8File
.
get
())
!=
1
)
{
WarnL
<<
"Could not write to m3u8 index file, will not continue writing to index file"
;
...
...
@@ -134,36 +134,36 @@ bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, i
}
void
HLSMaker
::
inputH264
(
void
*
data
,
uint32_t
length
,
uint32_t
timeStamp
,
int
type
)
{
if
(
m
_ui32LastStamp
==
0
){
m
_ui32LastStamp
=
timeStamp
;
if
(
_ui32LastStamp
==
0
){
_ui32LastStamp
=
timeStamp
;
}
int
stampInc
=
timeStamp
-
m
_ui32LastStamp
;
int
stampInc
=
timeStamp
-
_ui32LastStamp
;
switch
(
type
)
{
case
7
:
//SPS
if
(
stampInc
>=
m
_ui32SegmentDuration
*
1000
)
{
m
_ui32LastStamp
=
timeStamp
;
if
(
stampInc
>=
_ui32SegmentDuration
*
1000
)
{
_ui32LastStamp
=
timeStamp
;
//关闭文件
m
_ts
.
clear
();
auto
strTmpFileName
=
StrPrinter
<<
m_strOutputPrefix
<<
'-'
<<
(
++
m
_ui64TsCnt
)
<<
".ts"
<<
endl
;
if
(
!
m_ts
.
init
(
strTmpFileName
,
m
_ui32BufSize
))
{
_ts
.
clear
();
auto
strTmpFileName
=
StrPrinter
<<
_strOutputPrefix
<<
'-'
<<
(
++
_ui64TsCnt
)
<<
".ts"
<<
endl
;
if
(
!
_ts
.
init
(
strTmpFileName
,
_ui32BufSize
))
{
//创建文件失败
return
;
}
//记录切片时间
m
_iDurations
.
push_back
(
stampInc
);
_iDurations
.
push_back
(
stampInc
);
if
(
removets
()){
//删除老的时间戳
m
_iDurations
.
pop_front
();
_iDurations
.
pop_front
();
}
write_index_file
(
m_ui64TsCnt
-
m_ui32NumSegments
,
m
_ui64TsCnt
,
0
);
write_index_file
(
_ui64TsCnt
-
_ui32NumSegments
,
_ui64TsCnt
,
0
);
}
case
1
:
//P
//insert aud frame before p and SPS frame
m
_ts
.
inputH264
(
"\x0\x0\x0\x1\x9
\xf0
"
,
6
,
timeStamp
*
90
);
_ts
.
inputH264
(
"\x0\x0\x0\x1\x9
\xf0
"
,
6
,
timeStamp
*
90
);
case
5
:
//IDR
case
8
:
//PPS
m
_ts
.
inputH264
((
char
*
)
data
,
length
,
timeStamp
*
90
);
_ts
.
inputH264
((
char
*
)
data
,
length
,
timeStamp
*
90
);
break
;
default
:
break
;
...
...
@@ -171,15 +171,15 @@ void HLSMaker::inputH264(void *data, uint32_t length, uint32_t timeStamp, int ty
}
void
HLSMaker
::
inputAAC
(
void
*
data
,
uint32_t
length
,
uint32_t
timeStamp
)
{
m
_ts
.
inputAAC
((
char
*
)
data
,
length
,
timeStamp
*
90
);
_ts
.
inputAAC
((
char
*
)
data
,
length
,
timeStamp
*
90
);
}
bool
HLSMaker
::
removets
()
{
if
(
m_ui64TsCnt
<
m
_ui32NumSegments
+
2
)
{
if
(
_ui64TsCnt
<
_ui32NumSegments
+
2
)
{
return
false
;
}
File
::
delete_file
((
StrPrinter
<<
m
_strOutputPrefix
<<
"-"
<<
m_ui64TsCnt
-
m
_ui32NumSegments
-
2
File
::
delete_file
((
StrPrinter
<<
_strOutputPrefix
<<
"-"
<<
_ui64TsCnt
-
_ui32NumSegments
-
2
<<
".ts"
<<
endl
).
data
());
return
true
;
}
...
...
src/MediaFile/HLSMaker.h
查看文件 @
39baaebc
...
...
@@ -60,16 +60,16 @@ public:
uint32_t
ui32Length
,
uint32_t
ui32TimeStamp
);
private
:
TSMaker
m
_ts
;
string
m
_strM3u8File
;
string
m
_strFileName
;
string
m
_strOutputPrefix
;
uint32_t
m
_ui32SegmentDuration
;
uint32_t
m
_ui32NumSegments
;
uint64_t
m
_ui64TsCnt
;
uint32_t
m
_ui32BufSize
;
uint32_t
m
_ui32LastStamp
;
std
::
deque
<
int
>
m
_iDurations
;
TSMaker
_ts
;
string
_strM3u8File
;
string
_strFileName
;
string
_strOutputPrefix
;
uint32_t
_ui32SegmentDuration
;
uint32_t
_ui32NumSegments
;
uint64_t
_ui64TsCnt
;
uint32_t
_ui32BufSize
;
uint32_t
_ui32LastStamp
;
std
::
deque
<
int
>
_iDurations
;
bool
write_index_file
(
int
iFirstSegment
,
unsigned
int
uiLastSegment
,
int
iEnd
);
bool
removets
();
...
...
src/MediaFile/MediaReader.cpp
查看文件 @
39baaebc
...
...
@@ -41,21 +41,21 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri
auto
strFileName
=
recordPath
+
"/"
+
strVhost
+
"/"
+
strApp
+
"/"
+
strId
;
m
_hMP4File
=
MP4Read
(
strFileName
.
data
());
if
(
m
_hMP4File
==
MP4_INVALID_FILE_HANDLE
){
_hMP4File
=
MP4Read
(
strFileName
.
data
());
if
(
_hMP4File
==
MP4_INVALID_FILE_HANDLE
){
throw
runtime_error
(
StrPrinter
<<
"打开MP4文件失败:"
<<
strFileName
<<
endl
);
}
m_video_trId
=
MP4FindTrackId
(
m
_hMP4File
,
0
,
MP4_VIDEO_TRACK_TYPE
,
0
);
if
(
m
_video_trId
!=
MP4_INVALID_TRACK_ID
){
if
(
strcmp
(
MP4GetTrackMediaDataName
(
m_hMP4File
,
m
_video_trId
),
"avc1"
)
==
0
){
auto
m_video_timescale
=
MP4GetTrackTimeScale
(
m_hMP4File
,
m
_video_trId
);
auto
m_video_duration
=
MP4GetTrackDuration
(
m_hMP4File
,
m
_video_trId
);
m_video_num_samples
=
MP4GetTrackNumberOfSamples
(
m_hMP4File
,
m
_video_trId
);
m_video_sample_max_size
=
MP4GetTrackMaxSampleSize
(
m_hMP4File
,
m
_video_trId
);
m_video_width
=
MP4GetTrackVideoWidth
(
m_hMP4File
,
m
_video_trId
);
m_video_height
=
MP4GetTrackVideoHeight
(
m_hMP4File
,
m
_video_trId
);
m_video_framerate
=
MP4GetTrackVideoFrameRate
(
m_hMP4File
,
m
_video_trId
);
m_pcVideoSample
=
std
::
shared_ptr
<
uint8_t
>
(
new
uint8_t
[
m
_video_sample_max_size
],[](
uint8_t
*
ptr
){
_video_trId
=
MP4FindTrackId
(
_hMP4File
,
0
,
MP4_VIDEO_TRACK_TYPE
,
0
);
if
(
_video_trId
!=
MP4_INVALID_TRACK_ID
){
if
(
strcmp
(
MP4GetTrackMediaDataName
(
_hMP4File
,
_video_trId
),
"avc1"
)
==
0
){
auto
_video_timescale
=
MP4GetTrackTimeScale
(
_hMP4File
,
_video_trId
);
auto
_video_duration
=
MP4GetTrackDuration
(
_hMP4File
,
_video_trId
);
_video_num_samples
=
MP4GetTrackNumberOfSamples
(
_hMP4File
,
_video_trId
);
_video_sample_max_size
=
MP4GetTrackMaxSampleSize
(
_hMP4File
,
_video_trId
);
_video_width
=
MP4GetTrackVideoWidth
(
_hMP4File
,
_video_trId
);
_video_height
=
MP4GetTrackVideoHeight
(
_hMP4File
,
_video_trId
);
_video_framerate
=
MP4GetTrackVideoFrameRate
(
_hMP4File
,
_video_trId
);
_pcVideoSample
=
std
::
shared_ptr
<
uint8_t
>
(
new
uint8_t
[
_video_sample_max_size
],[](
uint8_t
*
ptr
){
delete
[]
ptr
;
});
uint8_t
**
seqheader
;
...
...
@@ -63,106 +63,106 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri
uint32_t
*
pictheadersize
;
uint32_t
*
seqheadersize
;
uint32_t
ix
;
if
(
MP4GetTrackH264SeqPictHeaders
(
m_hMP4File
,
m
_video_trId
,
&
seqheader
,
&
seqheadersize
,
&
pictheader
,
&
pictheadersize
)){
if
(
MP4GetTrackH264SeqPictHeaders
(
_hMP4File
,
_video_trId
,
&
seqheader
,
&
seqheadersize
,
&
pictheader
,
&
pictheadersize
)){
for
(
ix
=
0
;
seqheadersize
[
ix
]
!=
0
;
ix
++
)
{
m
_strSps
.
assign
((
char
*
)(
seqheader
[
ix
]),
seqheadersize
[
ix
]);
_strSps
.
assign
((
char
*
)(
seqheader
[
ix
]),
seqheadersize
[
ix
]);
float
framerate
;
getAVCInfo
(
m_strSps
,
(
int
&
)
m_video_width
,
(
int
&
)
m
_video_height
,
framerate
);
m
_video_framerate
=
framerate
;
m_strSps
=
string
(
"\x0\x0\x0\x1"
,
4
)
+
m
_strSps
;
getAVCInfo
(
_strSps
,
(
int
&
)
_video_width
,
(
int
&
)
_video_height
,
framerate
);
_video_framerate
=
framerate
;
_strSps
=
string
(
"\x0\x0\x0\x1"
,
4
)
+
_strSps
;
MP4Free
(
seqheader
[
ix
]);
}
MP4Free
(
seqheader
);
MP4Free
(
seqheadersize
);
for
(
ix
=
0
;
pictheadersize
[
ix
]
!=
0
;
ix
++
)
{
m
_strPps
.
assign
(
"\x0\x0\x0\x1"
,
4
);
m
_strPps
.
append
((
char
*
)(
pictheader
[
ix
]),
pictheadersize
[
ix
]);
_strPps
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_strPps
.
append
((
char
*
)(
pictheader
[
ix
]),
pictheadersize
[
ix
]);
MP4Free
(
pictheader
[
ix
]);
}
MP4Free
(
pictheader
);
MP4Free
(
pictheadersize
);
}
m_video_ms
=
1000.0
*
m_video_duration
/
m
_video_timescale
;
_video_ms
=
1000.0
*
_video_duration
/
_video_timescale
;
/*InfoL << "\r\n"
<<
m
_video_ms << "\r\n"
<<
m
_video_num_samples << "\r\n"
<<
m
_video_framerate << "\r\n"
<<
m
_video_width << "\r\n"
<<
m
_video_height << "\r\n";*/
<< _video_ms << "\r\n"
<< _video_num_samples << "\r\n"
<< _video_framerate << "\r\n"
<< _video_width << "\r\n"
<< _video_height << "\r\n";*/
}
else
{
//如果不是h264,则忽略
m
_video_trId
=
MP4_INVALID_TRACK_ID
;
_video_trId
=
MP4_INVALID_TRACK_ID
;
}
}
m_audio_trId
=
MP4FindTrackId
(
m
_hMP4File
,
0
,
MP4_AUDIO_TRACK_TYPE
,
0
);
if
(
m
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
if
(
strcmp
(
MP4GetTrackMediaDataName
(
m_hMP4File
,
m
_audio_trId
),
"mp4a"
)
==
0
)
{
m_audio_sample_rate
=
MP4GetTrackTimeScale
(
m_hMP4File
,
m
_audio_trId
);
auto
m_audio_duration
=
MP4GetTrackDuration
(
m_hMP4File
,
m
_audio_trId
);
m_audio_num_samples
=
MP4GetTrackNumberOfSamples
(
m_hMP4File
,
m
_audio_trId
);
m_audio_num_channels
=
MP4GetTrackAudioChannels
(
m_hMP4File
,
m
_audio_trId
);
m_audio_sample_max_size
=
MP4GetTrackMaxSampleSize
(
m_hMP4File
,
m
_audio_trId
);
_audio_trId
=
MP4FindTrackId
(
_hMP4File
,
0
,
MP4_AUDIO_TRACK_TYPE
,
0
);
if
(
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
if
(
strcmp
(
MP4GetTrackMediaDataName
(
_hMP4File
,
_audio_trId
),
"mp4a"
)
==
0
)
{
_audio_sample_rate
=
MP4GetTrackTimeScale
(
_hMP4File
,
_audio_trId
);
auto
_audio_duration
=
MP4GetTrackDuration
(
_hMP4File
,
_audio_trId
);
_audio_num_samples
=
MP4GetTrackNumberOfSamples
(
_hMP4File
,
_audio_trId
);
_audio_num_channels
=
MP4GetTrackAudioChannels
(
_hMP4File
,
_audio_trId
);
_audio_sample_max_size
=
MP4GetTrackMaxSampleSize
(
_hMP4File
,
_audio_trId
);
uint8_t
*
ppConfig
;
uint32_t
pConfigSize
;
if
(
MP4GetTrackESConfiguration
(
m_hMP4File
,
m
_audio_trId
,
&
ppConfig
,
&
pConfigSize
)){
m
_strAacCfg
.
assign
((
char
*
)
ppConfig
,
pConfigSize
);
makeAdtsHeader
(
m_strAacCfg
,
m
_adts
);
writeAdtsHeader
(
m_adts
,
m
_adts
.
buffer
);
getAACInfo
(
m_adts
,
(
int
&
)
m_audio_sample_rate
,
(
int
&
)
m
_audio_num_channels
);
if
(
MP4GetTrackESConfiguration
(
_hMP4File
,
_audio_trId
,
&
ppConfig
,
&
pConfigSize
)){
_strAacCfg
.
assign
((
char
*
)
ppConfig
,
pConfigSize
);
makeAdtsHeader
(
_strAacCfg
,
_adts
);
writeAdtsHeader
(
_adts
,
_adts
.
buffer
);
getAACInfo
(
_adts
,
(
int
&
)
_audio_sample_rate
,
(
int
&
)
_audio_num_channels
);
MP4Free
(
ppConfig
);
}
m_audio_ms
=
1000.0
*
m_audio_duration
/
m
_audio_sample_rate
;
_audio_ms
=
1000.0
*
_audio_duration
/
_audio_sample_rate
;
/*InfoL << "\r\n"
<<
m
_audio_ms << "\r\n"
<<
m
_audio_num_samples << "\r\n"
<<
m
_audio_num_channels << "\r\n"
<<
m
_audio_sample_rate << "\r\n";*/
<< _audio_ms << "\r\n"
<< _audio_num_samples << "\r\n"
<< _audio_num_channels << "\r\n"
<< _audio_sample_rate << "\r\n";*/
}
else
{
m
_audio_trId
=
MP4_INVALID_TRACK_ID
;
_audio_trId
=
MP4_INVALID_TRACK_ID
;
}
}
if
(
m_audio_trId
==
MP4_INVALID_TRACK_ID
&&
m
_video_trId
==
MP4_INVALID_TRACK_ID
){
MP4Close
(
m
_hMP4File
);
m
_hMP4File
=
MP4_INVALID_FILE_HANDLE
;
if
(
_audio_trId
==
MP4_INVALID_TRACK_ID
&&
_video_trId
==
MP4_INVALID_TRACK_ID
){
MP4Close
(
_hMP4File
);
_hMP4File
=
MP4_INVALID_FILE_HANDLE
;
throw
runtime_error
(
StrPrinter
<<
"该MP4文件音视频格式不支持:"
<<
strFileName
<<
endl
);
}
m_iDuration
=
MAX
(
m_video_ms
,
m
_audio_ms
);
m_pChn
.
reset
(
new
DevChannel
(
strVhost
.
data
(),
strApp
.
data
(),
strId
.
data
(),
m
_iDuration
/
1000.0
,
false
,
false
));
if
(
m
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
_iDuration
=
MAX
(
_video_ms
,
_audio_ms
);
_pChn
.
reset
(
new
DevChannel
(
strVhost
.
data
(),
strApp
.
data
(),
strId
.
data
(),
_iDuration
/
1000.0
,
false
,
false
));
if
(
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
AudioInfo
info
;
info
.
iChannel
=
m
_audio_num_channels
;
info
.
iChannel
=
_audio_num_channels
;
info
.
iSampleBit
=
16
;
info
.
iSampleRate
=
m
_audio_sample_rate
;
m
_pChn
->
initAudio
(
info
);
info
.
iSampleRate
=
_audio_sample_rate
;
_pChn
->
initAudio
(
info
);
}
if
(
m
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
if
(
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
VideoInfo
info
;
info
.
iFrameRate
=
m
_video_framerate
;
info
.
iWidth
=
m
_video_width
;
info
.
iHeight
=
m
_video_height
;
m
_pChn
->
initVideo
(
info
);
info
.
iFrameRate
=
_video_framerate
;
info
.
iWidth
=
_video_width
;
info
.
iHeight
=
_video_height
;
_pChn
->
initVideo
(
info
);
}
if
(
m
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
m_pChn
->
inputAAC
((
char
*
)
m
_adts
.
buffer
,
7
,
0
);
if
(
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
_pChn
->
inputAAC
((
char
*
)
_adts
.
buffer
,
7
,
0
);
}
if
(
m
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
//
m
_pChn->initVideo(info);
m_pChn
->
inputH264
((
char
*
)
m_strSps
.
data
(),
m
_strSps
.
size
(),
0
);
m_pChn
->
inputH264
((
char
*
)
m_strPps
.
data
(),
m
_strPps
.
size
(),
0
);
if
(
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
//_pChn->initVideo(info);
_pChn
->
inputH264
((
char
*
)
_strSps
.
data
(),
_strSps
.
size
(),
0
);
_pChn
->
inputH264
((
char
*
)
_strPps
.
data
(),
_strPps
.
size
(),
0
);
}
}
MediaReader
::~
MediaReader
()
{
if
(
m
_hMP4File
!=
MP4_INVALID_FILE_HANDLE
)
{
MP4Close
(
m
_hMP4File
);
m
_hMP4File
=
MP4_INVALID_FILE_HANDLE
;
if
(
_hMP4File
!=
MP4_INVALID_FILE_HANDLE
)
{
MP4Close
(
_hMP4File
);
_hMP4File
=
MP4_INVALID_FILE_HANDLE
;
}
}
...
...
@@ -174,14 +174,14 @@ void MediaReader::startReadMP4() {
AsyncTaskThread
::
Instance
().
DoTaskDelay
(
reinterpret_cast
<
uint64_t
>
(
this
),
sampleMS
,
[
strongSelf
](){
return
strongSelf
->
readSample
();
});
m
_pChn
->
setListener
(
strongSelf
);
_pChn
->
setListener
(
strongSelf
);
}
bool
MediaReader
::
seekTo
(
uint32_t
ui32Stamp
){
seek
(
ui32Stamp
);
return
true
;
}
uint32_t
MediaReader
::
getStamp
()
{
return
m_iSeekTime
+
m
_ticker
.
elapsedTime
();
return
_iSeekTime
+
_ticker
.
elapsedTime
();
}
bool
MediaReader
::
shutDown
(){
AsyncTaskThread
::
Instance
().
CancelTask
(
reinterpret_cast
<
uint64_t
>
(
this
));
...
...
@@ -190,25 +190,25 @@ bool MediaReader::shutDown(){
bool
MediaReader
::
readSample
(
int
iTimeInc
)
{
TimeTicker
();
lock_guard
<
recursive_mutex
>
lck
(
m
_mtx
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
auto
bFlag0
=
readVideoSample
(
iTimeInc
);
//数据没读完
auto
bFlag1
=
readAudioSample
(
iTimeInc
);
//数据没读完
auto
bFlag2
=
m
_pChn
->
readerCount
()
>
0
;
//读取者大于0
auto
bFlag2
=
_pChn
->
readerCount
()
>
0
;
//读取者大于0
if
((
bFlag0
||
bFlag1
)
&&
bFlag2
){
m
_alive
.
resetTime
();
_alive
.
resetTime
();
}
//DebugL << "alive ...";
//3秒延时关闭
return
m
_alive
.
elapsedTime
()
<
3
*
1000
;
return
_alive
.
elapsedTime
()
<
3
*
1000
;
}
inline
bool
MediaReader
::
readVideoSample
(
int
iTimeInc
)
{
if
(
m
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
if
(
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
auto
iNextSample
=
getVideoSampleId
(
iTimeInc
);
MP4SampleId
iIdx
=
m
_video_current
;
for
(
iIdx
=
m
_video_current
;
iIdx
<
iNextSample
;
iIdx
++
)
{
uint8_t
*
pBytes
=
m
_pcVideoSample
.
get
();
uint32_t
numBytes
=
m
_video_sample_max_size
;
if
(
MP4ReadSample
(
m_hMP4File
,
m_video_trId
,
iIdx
+
1
,
&
pBytes
,
&
numBytes
,
NULL
,
NULL
,
NULL
,
&
m
_bSyncSample
)){
MP4SampleId
iIdx
=
_video_current
;
for
(
iIdx
=
_video_current
;
iIdx
<
iNextSample
;
iIdx
++
)
{
uint8_t
*
pBytes
=
_pcVideoSample
.
get
();
uint32_t
numBytes
=
_video_sample_max_size
;
if
(
MP4ReadSample
(
_hMP4File
,
_video_trId
,
iIdx
+
1
,
&
pBytes
,
&
numBytes
,
NULL
,
NULL
,
NULL
,
&
_bSyncSample
)){
if
(
!
iTimeInc
)
{
uint32_t
iOffset
=
0
;
while
(
iOffset
<
numBytes
)
{
...
...
@@ -219,97 +219,97 @@ inline bool MediaReader::readVideoSample(int iTimeInc) {
break
;
}
memcpy
(
pBytes
+
iOffset
,
"\x0\x0\x0\x1"
,
4
);
writeH264
(
pBytes
+
iOffset
,
iFrameLen
+
4
,
(
double
)
m_video_ms
*
iIdx
/
m
_video_num_samples
);
writeH264
(
pBytes
+
iOffset
,
iFrameLen
+
4
,
(
double
)
_video_ms
*
iIdx
/
_video_num_samples
);
iOffset
+=
(
iFrameLen
+
4
);
}
}
else
if
(
m
_bSyncSample
){
}
else
if
(
_bSyncSample
){
break
;
}
}
else
{
ErrorL
<<
"读取视频失败:"
<<
iIdx
+
1
;
}
}
m
_video_current
=
iIdx
;
return
m_video_current
<
m
_video_num_samples
;
_video_current
=
iIdx
;
return
_video_current
<
_video_num_samples
;
}
return
false
;
}
inline
bool
MediaReader
::
readAudioSample
(
int
iTimeInc
)
{
if
(
m
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
if
(
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
auto
iNextSample
=
getAudioSampleId
(
iTimeInc
);
for
(
auto
i
=
m
_audio_current
;
i
<
iNextSample
;
i
++
)
{
uint32_t
numBytes
=
m
_audio_sample_max_size
;
uint8_t
*
pBytes
=
m
_adts
.
buffer
+
7
;
if
(
MP4ReadSample
(
m_hMP4File
,
m
_audio_trId
,
i
+
1
,
&
pBytes
,
&
numBytes
)){
for
(
auto
i
=
_audio_current
;
i
<
iNextSample
;
i
++
)
{
uint32_t
numBytes
=
_audio_sample_max_size
;
uint8_t
*
pBytes
=
_adts
.
buffer
+
7
;
if
(
MP4ReadSample
(
_hMP4File
,
_audio_trId
,
i
+
1
,
&
pBytes
,
&
numBytes
)){
if
(
!
iTimeInc
)
{
m
_adts
.
aac_frame_length
=
7
+
numBytes
;
writeAdtsHeader
(
m_adts
,
m
_adts
.
buffer
);
writeAAC
(
m_adts
.
buffer
,
m_adts
.
aac_frame_length
,
(
double
)
m_audio_ms
*
i
/
m
_audio_num_samples
);
_adts
.
aac_frame_length
=
7
+
numBytes
;
writeAdtsHeader
(
_adts
,
_adts
.
buffer
);
writeAAC
(
_adts
.
buffer
,
_adts
.
aac_frame_length
,
(
double
)
_audio_ms
*
i
/
_audio_num_samples
);
}
}
else
{
ErrorL
<<
"读取音频失败:"
<<
i
+
1
;
}
}
m
_audio_current
=
iNextSample
;
return
m_audio_current
<
m
_audio_num_samples
;
_audio_current
=
iNextSample
;
return
_audio_current
<
_audio_num_samples
;
}
return
false
;
}
inline
void
MediaReader
::
writeH264
(
uint8_t
*
pucData
,
int
iLen
,
uint32_t
uiStamp
)
{
m
_pChn
->
inputH264
((
char
*
)
pucData
,
iLen
,
uiStamp
);
_pChn
->
inputH264
((
char
*
)
pucData
,
iLen
,
uiStamp
);
}
inline
void
MediaReader
::
writeAAC
(
uint8_t
*
pucData
,
int
iLen
,
uint32_t
uiStamp
)
{
m
_pChn
->
inputAAC
((
char
*
)
pucData
,
iLen
,
uiStamp
);
_pChn
->
inputAAC
((
char
*
)
pucData
,
iLen
,
uiStamp
);
}
inline
MP4SampleId
MediaReader
::
getVideoSampleId
(
int
iTimeInc
)
{
MP4SampleId
video_current
=
(
double
)
m_video_num_samples
*
(
m_iSeekTime
+
m_ticker
.
elapsedTime
()
+
iTimeInc
)
/
m
_video_ms
;
video_current
=
MAX
(
0
,
MIN
(
m
_video_num_samples
,
video_current
));
MP4SampleId
video_current
=
(
double
)
_video_num_samples
*
(
_iSeekTime
+
_ticker
.
elapsedTime
()
+
iTimeInc
)
/
_video_ms
;
video_current
=
MAX
(
0
,
MIN
(
_video_num_samples
,
video_current
));
return
video_current
;
}
inline
MP4SampleId
MediaReader
::
getAudioSampleId
(
int
iTimeInc
)
{
MP4SampleId
audio_current
=
(
double
)
m_audio_num_samples
*
(
m_iSeekTime
+
m_ticker
.
elapsedTime
()
+
iTimeInc
)
/
m
_audio_ms
;
audio_current
=
MAX
(
0
,
MIN
(
m
_audio_num_samples
,
audio_current
));
MP4SampleId
audio_current
=
(
double
)
_audio_num_samples
*
(
_iSeekTime
+
_ticker
.
elapsedTime
()
+
iTimeInc
)
/
_audio_ms
;
audio_current
=
MAX
(
0
,
MIN
(
_audio_num_samples
,
audio_current
));
return
audio_current
;
}
inline
void
MediaReader
::
setSeekTime
(
int
iSeekTime
){
m_iSeekTime
=
MAX
(
0
,
MIN
(
iSeekTime
,
m
_iDuration
));
m
_ticker
.
resetTime
();
if
(
m
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
m
_audio_current
=
getAudioSampleId
();
_iSeekTime
=
MAX
(
0
,
MIN
(
iSeekTime
,
_iDuration
));
_ticker
.
resetTime
();
if
(
_audio_trId
!=
MP4_INVALID_TRACK_ID
)
{
_audio_current
=
getAudioSampleId
();
}
if
(
m
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
m
_video_current
=
getVideoSampleId
();
if
(
_video_trId
!=
MP4_INVALID_TRACK_ID
)
{
_video_current
=
getVideoSampleId
();
}
}
inline
uint32_t
MediaReader
::
getVideoCurrentTime
(){
return
(
double
)
m_video_current
*
m_video_ms
/
m
_video_num_samples
;
return
(
double
)
_video_current
*
_video_ms
/
_video_num_samples
;
}
void
MediaReader
::
seek
(
int
iSeekTime
,
bool
bReStart
){
lock_guard
<
recursive_mutex
>
lck
(
m
_mtx
);
if
(
iSeekTime
==
0
||
m
_video_trId
==
MP4_INVALID_TRACK_ID
){
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
if
(
iSeekTime
==
0
||
_video_trId
==
MP4_INVALID_TRACK_ID
){
setSeekTime
(
iSeekTime
);
}
else
{
setSeekTime
(
iSeekTime
-
5000
);
//在之后的10秒查找关键帧
readVideoSample
(
10000
);
if
(
m
_bSyncSample
)
{
if
(
_bSyncSample
)
{
//找到关键帧
auto
iIdr
=
m
_video_current
;
auto
iIdr
=
_video_current
;
setSeekTime
(
getVideoCurrentTime
());
m
_video_current
=
iIdr
;
_video_current
=
iIdr
;
}
else
{
//未找到关键帧
setSeekTime
(
iSeekTime
);
}
}
m_pChn
->
updateTimeStamp
(
m
_iSeekTime
);
_pChn
->
updateTimeStamp
(
_iSeekTime
);
if
(
bReStart
){
AsyncTaskThread
::
Instance
().
CancelTask
(
reinterpret_cast
<
uint64_t
>
(
this
));
...
...
src/MediaFile/MediaReader.h
查看文件 @
39baaebc
...
...
@@ -55,37 +55,37 @@ public:
private
:
#ifdef ENABLE_MP4V2
MP4FileHandle
m
_hMP4File
=
MP4_INVALID_FILE_HANDLE
;
MP4TrackId
m
_video_trId
=
MP4_INVALID_TRACK_ID
;
uint32_t
m
_video_ms
=
0
;
uint32_t
m
_video_num_samples
=
0
;
uint32_t
m
_video_sample_max_size
=
0
;
uint32_t
m
_video_width
=
0
;
uint32_t
m
_video_height
=
0
;
uint32_t
m
_video_framerate
=
0
;
string
m
_strPps
;
string
m
_strSps
;
bool
m
_bSyncSample
=
false
;
MP4FileHandle
_hMP4File
=
MP4_INVALID_FILE_HANDLE
;
MP4TrackId
_video_trId
=
MP4_INVALID_TRACK_ID
;
uint32_t
_video_ms
=
0
;
uint32_t
_video_num_samples
=
0
;
uint32_t
_video_sample_max_size
=
0
;
uint32_t
_video_width
=
0
;
uint32_t
_video_height
=
0
;
uint32_t
_video_framerate
=
0
;
string
_strPps
;
string
_strSps
;
bool
_bSyncSample
=
false
;
MP4TrackId
m
_audio_trId
=
MP4_INVALID_TRACK_ID
;
uint32_t
m
_audio_ms
=
0
;
uint32_t
m
_audio_num_samples
=
0
;
uint32_t
m
_audio_sample_max_size
=
0
;
uint32_t
m
_audio_sample_rate
=
0
;
uint32_t
m
_audio_num_channels
=
0
;
string
m
_strAacCfg
;
AACFrame
m
_adts
;
MP4TrackId
_audio_trId
=
MP4_INVALID_TRACK_ID
;
uint32_t
_audio_ms
=
0
;
uint32_t
_audio_num_samples
=
0
;
uint32_t
_audio_sample_max_size
=
0
;
uint32_t
_audio_sample_rate
=
0
;
uint32_t
_audio_num_channels
=
0
;
string
_strAacCfg
;
AACFrame
_adts
;
int
m
_iDuration
=
0
;
DevChannel
::
Ptr
m
_pChn
;
MP4SampleId
m
_video_current
=
0
;
MP4SampleId
m
_audio_current
=
0
;
std
::
shared_ptr
<
uint8_t
>
m
_pcVideoSample
;
int
_iDuration
=
0
;
DevChannel
::
Ptr
_pChn
;
MP4SampleId
_video_current
=
0
;
MP4SampleId
_audio_current
=
0
;
std
::
shared_ptr
<
uint8_t
>
_pcVideoSample
;
int
m
_iSeekTime
=
0
;
Ticker
m
_ticker
;
Ticker
m
_alive
;
recursive_mutex
m
_mtx
;
int
_iSeekTime
=
0
;
Ticker
_ticker
;
Ticker
_alive
;
recursive_mutex
_mtx
;
void
seek
(
int
iSeekTime
,
bool
bReStart
=
true
);
inline
void
setSeekTime
(
int
iSeekTime
);
...
...
src/MediaFile/MediaRecorder.cpp
查看文件 @
39baaebc
...
...
@@ -57,7 +57,7 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp,
if
(
enableHls
)
{
auto
m3u8FilePath
=
hlsPath
+
"/"
+
strVhost
+
"/"
+
strApp
+
"/"
+
strId
+
"/hls.m3u8"
;
m
_hlsMaker
.
reset
(
new
HLSMaker
(
m3u8FilePath
,
hlsBufSize
,
hlsDuration
,
hlsNum
));
_hlsMaker
.
reset
(
new
HLSMaker
(
m3u8FilePath
,
hlsBufSize
,
hlsDuration
,
hlsNum
));
}
#ifdef ENABLE_MP4V2
...
...
@@ -66,7 +66,7 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp,
if
(
enableMp4
){
auto
mp4FilePath
=
recordPath
+
"/"
+
strVhost
+
"/"
+
recordAppName
+
"/"
+
strApp
+
"/"
+
strId
+
"/"
;
m
_mp4Maker
.
reset
(
new
Mp4Maker
(
mp4FilePath
,
strVhost
,
strApp
,
strId
,
pPlayer
));
_mp4Maker
.
reset
(
new
Mp4Maker
(
mp4FilePath
,
strVhost
,
strApp
,
strId
,
pPlayer
));
}
#endif //ENABLE_MP4V2
}
...
...
@@ -75,23 +75,23 @@ MediaRecorder::~MediaRecorder() {
}
void
MediaRecorder
::
inputH264
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui32TimeStamp
,
int
iType
)
{
if
(
m
_hlsMaker
){
m
_hlsMaker
->
inputH264
(
pData
,
ui32Length
,
ui32TimeStamp
,
iType
);
if
(
_hlsMaker
){
_hlsMaker
->
inputH264
(
pData
,
ui32Length
,
ui32TimeStamp
,
iType
);
}
#ifdef ENABLE_MP4V2
if
(
m
_mp4Maker
){
m
_mp4Maker
->
inputH264
(
pData
,
ui32Length
,
ui32TimeStamp
,
iType
);
if
(
_mp4Maker
){
_mp4Maker
->
inputH264
(
pData
,
ui32Length
,
ui32TimeStamp
,
iType
);
}
#endif //ENABLE_MP4V2
}
void
MediaRecorder
::
inputAAC
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui32TimeStamp
)
{
if
(
m
_hlsMaker
){
m
_hlsMaker
->
inputAAC
(
pData
,
ui32Length
,
ui32TimeStamp
);
if
(
_hlsMaker
){
_hlsMaker
->
inputAAC
(
pData
,
ui32Length
,
ui32TimeStamp
);
}
#ifdef ENABLE_MP4V2
if
(
m
_mp4Maker
){
m
_mp4Maker
->
inputAAC
(
pData
,
ui32Length
,
ui32TimeStamp
);
if
(
_mp4Maker
){
_mp4Maker
->
inputAAC
(
pData
,
ui32Length
,
ui32TimeStamp
);
}
#endif //ENABLE_MP4V2
}
...
...
src/MediaFile/MediaRecorder.h
查看文件 @
39baaebc
...
...
@@ -50,8 +50,8 @@ public:
const
string
&
strApp
,
const
string
&
strId
,
const
std
::
shared_ptr
<
PlayerBase
>
&
pPlayer
,
bool
m_
enableHls
=
true
,
bool
m_
enableMp4
=
false
);
bool
enableHls
=
true
,
bool
enableMp4
=
false
);
virtual
~
MediaRecorder
();
void
inputH264
(
void
*
pData
,
...
...
@@ -63,9 +63,9 @@ public:
uint32_t
ui32Length
,
uint32_t
ui32TimeStamp
);
private
:
std
::
shared_ptr
<
HLSMaker
>
m
_hlsMaker
;
std
::
shared_ptr
<
HLSMaker
>
_hlsMaker
;
#ifdef ENABLE_MP4V2
std
::
shared_ptr
<
Mp4Maker
>
m
_mp4Maker
;
std
::
shared_ptr
<
Mp4Maker
>
_mp4Maker
;
#endif //ENABLE_MP4V2
};
...
...
src/MediaFile/Mp4Maker.cpp
查看文件 @
39baaebc
...
...
@@ -62,14 +62,14 @@ Mp4Maker::Mp4Maker(const string& strPath,
const
string
&
strStreamId
,
const
PlayerBase
::
Ptr
&
pPlayer
)
{
DebugL
<<
strPath
;
m
_pPlayer
=
pPlayer
;
m
_strPath
=
strPath
;
_pPlayer
=
pPlayer
;
_strPath
=
strPath
;
/////record 业务逻辑//////
m
_info
.
strAppName
=
strApp
;
m
_info
.
strStreamId
=
strStreamId
;
m
_info
.
strVhost
=
strVhost
;
m
_info
.
strFolder
=
strPath
;
_info
.
strAppName
=
strApp
;
_info
.
strStreamId
=
strStreamId
;
_info
.
strVhost
=
strVhost
;
_info
.
strFolder
=
strPath
;
//----record 业务逻辑----//
}
Mp4Maker
::~
Mp4Maker
()
{
...
...
@@ -80,22 +80,22 @@ void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStam
switch
(
iType
)
{
case
1
:
//P
case
5
:
{
//IDR
if
(
m
_strLastVideo
.
size
())
{
int64_t
iTimeInc
=
(
int64_t
)
ui32TimeStamp
-
(
int64_t
)
m
_ui32LastVideoTime
;
if
(
_strLastVideo
.
size
())
{
int64_t
iTimeInc
=
(
int64_t
)
ui32TimeStamp
-
(
int64_t
)
_ui32LastVideoTime
;
iTimeInc
=
MAX
(
0
,
MIN
(
iTimeInc
,
500
));
if
(
iTimeInc
==
0
||
iTimeInc
==
500
){
WarnL
<<
"abnormal time stamp increment:"
<<
ui32TimeStamp
<<
" "
<<
m
_ui32LastVideoTime
;
WarnL
<<
"abnormal time stamp increment:"
<<
ui32TimeStamp
<<
" "
<<
_ui32LastVideoTime
;
}
_inputH264
((
char
*
)
m_strLastVideo
.
data
(),
m_strLastVideo
.
size
(),
iTimeInc
,
m
_iLastVideoType
);
_inputH264
((
char
*
)
_strLastVideo
.
data
(),
_strLastVideo
.
size
(),
iTimeInc
,
_iLastVideoType
);
}
//
m
_strLastVideo.assign(("\x0\x0\x0\x2\x9\xf0"), 6);
//_strLastVideo.assign(("\x0\x0\x0\x2\x9\xf0"), 6);
uint32_t
*
p
=
(
uint32_t
*
)
pData
;
*
p
=
htonl
(
ui32Length
-
4
);
m
_strLastVideo
.
assign
((
char
*
)
pData
,
ui32Length
);
_strLastVideo
.
assign
((
char
*
)
pData
,
ui32Length
);
memcpy
(
pData
,
"
\x00\x00\x00\x01
"
,
4
);
m
_ui32LastVideoTime
=
ui32TimeStamp
;
m
_iLastVideoType
=
iType
;
_ui32LastVideoTime
=
ui32TimeStamp
;
_iLastVideoType
=
iType
;
}
break
;
default
:
...
...
@@ -103,28 +103,28 @@ void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStam
}
}
void
Mp4Maker
::
inputAAC
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui32TimeStamp
){
if
(
m
_strLastAudio
.
size
())
{
int64_t
iTimeInc
=
(
int64_t
)
ui32TimeStamp
-
(
int64_t
)
m
_ui32LastAudioTime
;
if
(
_strLastAudio
.
size
())
{
int64_t
iTimeInc
=
(
int64_t
)
ui32TimeStamp
-
(
int64_t
)
_ui32LastAudioTime
;
iTimeInc
=
MAX
(
0
,
MIN
(
iTimeInc
,
500
));
if
(
iTimeInc
==
0
||
iTimeInc
==
500
){
WarnL
<<
"abnormal time stamp increment:"
<<
ui32TimeStamp
<<
" "
<<
m
_ui32LastAudioTime
;
WarnL
<<
"abnormal time stamp increment:"
<<
ui32TimeStamp
<<
" "
<<
_ui32LastAudioTime
;
}
_inputAAC
((
char
*
)
m_strLastAudio
.
data
(),
m
_strLastAudio
.
size
(),
iTimeInc
);
_inputAAC
((
char
*
)
_strLastAudio
.
data
(),
_strLastAudio
.
size
(),
iTimeInc
);
}
m
_strLastAudio
.
assign
((
char
*
)
pData
,
ui32Length
);
m
_ui32LastAudioTime
=
ui32TimeStamp
;
_strLastAudio
.
assign
((
char
*
)
pData
,
ui32Length
);
_ui32LastAudioTime
=
ui32TimeStamp
;
}
void
Mp4Maker
::
_inputH264
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui32Duration
,
int
iType
)
{
GET_CONFIG_AND_REGISTER
(
uint32_t
,
recordSec
,
Config
::
Record
::
kFileSecond
);
if
(
iType
==
5
&&
(
m_hMp4
==
MP4_INVALID_FILE_HANDLE
||
m
_ticker
.
elapsedTime
()
>
recordSec
*
1000
)){
if
(
iType
==
5
&&
(
_hMp4
==
MP4_INVALID_FILE_HANDLE
||
_ticker
.
elapsedTime
()
>
recordSec
*
1000
)){
//在I帧率处新建MP4文件
//如果文件未创建或者文件超过10分钟则创建新文件
createFile
();
}
if
(
m
_hVideo
!=
MP4_INVALID_TRACK_ID
)
{
MP4WriteSample
(
m_hMp4
,
m
_hVideo
,
(
uint8_t
*
)
pData
,
ui32Length
,
ui32Duration
*
90
,
0
,
iType
==
5
);
if
(
_hVideo
!=
MP4_INVALID_TRACK_ID
)
{
MP4WriteSample
(
_hMp4
,
_hVideo
,
(
uint8_t
*
)
pData
,
ui32Length
,
ui32Duration
*
90
,
0
,
iType
==
5
);
}
}
...
...
@@ -134,39 +134,39 @@ void Mp4Maker::_inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32Duration
//todo(xzl) 修复此处
//
// if (!
m_pPlayer->containVideo() && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m
_ticker.elapsedTime() > recordSec * 1000)) {
// if (!
_pPlayer->containVideo() && (_hMp4 == MP4_INVALID_FILE_HANDLE ||
_ticker.elapsedTime() > recordSec * 1000)) {
// //在I帧率处新建MP4文件
// //如果文件未创建或者文件超过10分钟则创建新文件
// createFile();
// }
// if (
m
_hAudio != MP4_INVALID_TRACK_ID) {
// auto duration = ui32Duration *
m
_pPlayer->getAudioSampleRate() /1000.0;
// MP4WriteSample(
m_hMp4, m
_hAudio, (uint8_t*)pData + 7, ui32Length - 7,duration,0,false);
// if (_hAudio != MP4_INVALID_TRACK_ID) {
// auto duration = ui32Duration * _pPlayer->getAudioSampleRate() /1000.0;
// MP4WriteSample(
_hMp4,
_hAudio, (uint8_t*)pData + 7, ui32Length - 7,duration,0,false);
// }
}
void
Mp4Maker
::
createFile
()
{
if
(
!
m
_pPlayer
->
isInited
()){
if
(
!
_pPlayer
->
isInited
()){
return
;
}
closeFile
();
auto
strDate
=
timeStr
(
"%Y-%m-%d"
);
auto
strTime
=
timeStr
(
"%H-%M-%S"
);
auto
strFileTmp
=
m
_strPath
+
strDate
+
"/."
+
strTime
+
".mp4"
;
auto
strFile
=
m
_strPath
+
strDate
+
"/"
+
strTime
+
".mp4"
;
auto
strFileTmp
=
_strPath
+
strDate
+
"/."
+
strTime
+
".mp4"
;
auto
strFile
=
_strPath
+
strDate
+
"/"
+
strTime
+
".mp4"
;
/////record 业务逻辑//////
m
_info
.
ui64StartedTime
=
::
time
(
NULL
);
m
_info
.
strFileName
=
strTime
+
".mp4"
;
m
_info
.
strFilePath
=
strFile
;
_info
.
ui64StartedTime
=
::
time
(
NULL
);
_info
.
strFileName
=
strTime
+
".mp4"
;
_info
.
strFilePath
=
strFile
;
GET_CONFIG_AND_REGISTER
(
string
,
appName
,
Config
::
Record
::
kAppName
);
m_info
.
strUrl
=
m
_info
.
strVhost
+
"/"
_info
.
strUrl
=
_info
.
strVhost
+
"/"
+
appName
+
"/"
+
m
_info
.
strAppName
+
"/"
+
m
_info
.
strStreamId
+
"/"
+
_info
.
strAppName
+
"/"
+
_info
.
strStreamId
+
"/"
+
strDate
+
"/"
+
strTime
+
".mp4"
;
//----record 业务逻辑----//
...
...
@@ -176,36 +176,36 @@ void Mp4Maker::createFile() {
#else
File
::
createfile_path
(
strFileTmp
.
data
(),
0
);
#endif
m
_hMp4
=
MP4Create
(
strFileTmp
.
data
());
if
(
m
_hMp4
==
MP4_INVALID_FILE_HANDLE
)
{
_hMp4
=
MP4Create
(
strFileTmp
.
data
());
if
(
_hMp4
==
MP4_INVALID_FILE_HANDLE
)
{
WarnL
<<
"创建MP4文件失败:"
<<
strFileTmp
;
return
;
}
//MP4SetTimeScale(
m
_hMp4, 90000);
m
_strFileTmp
=
strFileTmp
;
m
_strFile
=
strFile
;
m
_ticker
.
resetTime
();
//MP4SetTimeScale(_hMp4, 90000);
_strFileTmp
=
strFileTmp
;
_strFile
=
strFile
;
_ticker
.
resetTime
();
//todo(xzl) 修复此处
// if(
m
_pPlayer->containVideo()){
// auto &sps =
m
_pPlayer->getSps();
// auto &pps =
m
_pPlayer->getPps();
//
m_hVideo = MP4AddH264VideoTrack(m
_hMp4, 90000, MP4_INVALID_DURATION,
//
m_pPlayer->getVideoWidth(), m
_pPlayer->getVideoHeight(),
// if(_pPlayer->containVideo()){
// auto &sps = _pPlayer->getSps();
// auto &pps = _pPlayer->getPps();
//
_hVideo = MP4AddH264VideoTrack(
_hMp4, 90000, MP4_INVALID_DURATION,
//
_pPlayer->getVideoWidth(),
_pPlayer->getVideoHeight(),
// sps[5], sps[6], sps[7], 3);
// if(
m
_hVideo !=MP4_INVALID_TRACK_ID){
// MP4AddH264SequenceParameterSet(
m_hMp4, m
_hVideo, (uint8_t *)sps.data() + 4, sps.size() - 4);
// MP4AddH264PictureParameterSet(
m_hMp4, m
_hVideo, (uint8_t *)pps.data() + 4, pps.size() - 4);
// if(_hVideo !=MP4_INVALID_TRACK_ID){
// MP4AddH264SequenceParameterSet(
_hMp4,
_hVideo, (uint8_t *)sps.data() + 4, sps.size() - 4);
// MP4AddH264PictureParameterSet(
_hMp4,
_hVideo, (uint8_t *)pps.data() + 4, pps.size() - 4);
// }else{
// WarnL << "添加视频通道失败:" << strFileTmp;
// }
// }
// if(
m
_pPlayer->containAudio()){
//
m_hAudio = MP4AddAudioTrack(m_hMp4, m
_pPlayer->getAudioSampleRate(), MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
// if (
m
_hAudio != MP4_INVALID_TRACK_ID) {
// auto &cfg =
m
_pPlayer->getAudioCfg();
// MP4SetTrackESConfiguration(
m_hMp4, m
_hAudio,(uint8_t *)cfg.data(), cfg.size());
// if(_pPlayer->containAudio()){
//
_hAudio = MP4AddAudioTrack(_hMp4,
_pPlayer->getAudioSampleRate(), MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
// if (_hAudio != MP4_INVALID_TRACK_ID) {
// auto &cfg = _pPlayer->getAudioCfg();
// MP4SetTrackESConfiguration(
_hMp4,
_hAudio,(uint8_t *)cfg.data(), cfg.size());
// }else{
// WarnL << "添加音频通道失败:" << strFileTmp;
// }
...
...
@@ -213,24 +213,24 @@ void Mp4Maker::createFile() {
}
void
Mp4Maker
::
closeFile
()
{
if
(
m
_hMp4
!=
MP4_INVALID_FILE_HANDLE
)
{
if
(
_hMp4
!=
MP4_INVALID_FILE_HANDLE
)
{
{
TimeTicker
();
MP4Close
(
m
_hMp4
,
MP4_CLOSE_DO_NOT_COMPUTE_BITRATE
);
MP4Close
(
_hMp4
,
MP4_CLOSE_DO_NOT_COMPUTE_BITRATE
);
}
rename
(
m_strFileTmp
.
data
(),
m
_strFile
.
data
());
m
_hMp4
=
MP4_INVALID_FILE_HANDLE
;
m
_hVideo
=
MP4_INVALID_TRACK_ID
;
m
_hAudio
=
MP4_INVALID_TRACK_ID
;
rename
(
_strFileTmp
.
data
(),
_strFile
.
data
());
_hMp4
=
MP4_INVALID_FILE_HANDLE
;
_hVideo
=
MP4_INVALID_TRACK_ID
;
_hAudio
=
MP4_INVALID_TRACK_ID
;
/////record 业务逻辑//////
m_info
.
ui64TimeLen
=
::
time
(
NULL
)
-
m
_info
.
ui64StartedTime
;
_info
.
ui64TimeLen
=
::
time
(
NULL
)
-
_info
.
ui64StartedTime
;
//获取文件大小
struct
stat
fileData
;
stat
(
m
_strFile
.
data
(),
&
fileData
);
m
_info
.
ui64FileSize
=
fileData
.
st_size
;
stat
(
_strFile
.
data
(),
&
fileData
);
_info
.
ui64FileSize
=
fileData
.
st_size
;
//----record 业务逻辑----//
NoticeCenter
::
Instance
().
emitEvent
(
Config
::
Broadcast
::
kBroadcastRecordMP4
,
m
_info
,
*
this
);
NoticeCenter
::
Instance
().
emitEvent
(
Config
::
Broadcast
::
kBroadcastRecordMP4
,
_info
,
*
this
);
}
}
...
...
src/MediaFile/Mp4Maker.h
查看文件 @
39baaebc
...
...
@@ -73,29 +73,29 @@ public:
//时间戳:参考频率1000
void
inputAAC
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui32TimeStamp
);
private
:
MP4FileHandle
m
_hMp4
=
MP4_INVALID_FILE_HANDLE
;
MP4TrackId
m
_hVideo
=
MP4_INVALID_TRACK_ID
;
MP4TrackId
m
_hAudio
=
MP4_INVALID_TRACK_ID
;
PlayerBase
::
Ptr
m
_pPlayer
;
string
m
_strPath
;
string
m
_strFile
;
string
m
_strFileTmp
;
Ticker
m
_ticker
;
SmoothTicker
m
_mediaTicker
[
2
];
MP4FileHandle
_hMp4
=
MP4_INVALID_FILE_HANDLE
;
MP4TrackId
_hVideo
=
MP4_INVALID_TRACK_ID
;
MP4TrackId
_hAudio
=
MP4_INVALID_TRACK_ID
;
PlayerBase
::
Ptr
_pPlayer
;
string
_strPath
;
string
_strFile
;
string
_strFileTmp
;
Ticker
_ticker
;
SmoothTicker
_mediaTicker
[
2
];
void
createFile
();
void
closeFile
();
void
_inputH264
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui64Duration
,
int
iType
);
void
_inputAAC
(
void
*
pData
,
uint32_t
ui32Length
,
uint32_t
ui64Duration
);
string
m
_strLastVideo
;
string
m
_strLastAudio
;
string
_strLastVideo
;
string
_strLastAudio
;
uint32_t
m
_ui32LastVideoTime
=
0
;
uint32_t
m
_ui32LastAudioTime
=
0
;
int
m
_iLastVideoType
=
0
;
uint32_t
_ui32LastVideoTime
=
0
;
uint32_t
_ui32LastAudioTime
=
0
;
int
_iLastVideoType
=
0
;
Mp4Info
m
_info
;
Mp4Info
_info
;
};
}
/* namespace MediaFile */
...
...
src/Player/MediaPlayer.cpp
查看文件 @
39baaebc
...
...
@@ -43,22 +43,22 @@ MediaPlayer::~MediaPlayer() {
}
void
MediaPlayer
::
play
(
const
char
*
strUrl
)
{
string
strPrefix
=
FindField
(
strUrl
,
NULL
,
"://"
);
if
((
strcasecmp
(
m
_strPrefix
.
data
(),
strPrefix
.
data
())
!=
0
)
||
strPrefix
.
empty
())
{
if
((
strcasecmp
(
_strPrefix
.
data
(),
strPrefix
.
data
())
!=
0
)
||
strPrefix
.
empty
())
{
//协议切换
m
_strPrefix
=
strPrefix
;
m
_parser
=
PlayerBase
::
createPlayer
(
strUrl
);
m_parser
->
setOnShutdown
(
m
_shutdownCB
);
_strPrefix
=
strPrefix
;
_parser
=
PlayerBase
::
createPlayer
(
strUrl
);
_parser
->
setOnShutdown
(
_shutdownCB
);
//todo(xzl) 修复此处
//
m_parser->setOnVideoCB(m
_onGetVideoCB);
//
m_parser->setOnAudioCB(m
_onGetAudioCB);
//
_parser->setOnVideoCB(
_onGetVideoCB);
//
_parser->setOnAudioCB(
_onGetAudioCB);
}
m_parser
->
setOnPlayResult
(
m
_playResultCB
);
m
_parser
->
mINI
::
operator
=
(
*
this
);
m
_parser
->
play
(
strUrl
);
_parser
->
setOnPlayResult
(
_playResultCB
);
_parser
->
mINI
::
operator
=
(
*
this
);
_parser
->
play
(
strUrl
);
}
TaskExecutor
::
Ptr
MediaPlayer
::
getExecutor
(){
auto
parser
=
dynamic_pointer_cast
<
SocketHelper
>
(
m
_parser
);
auto
parser
=
dynamic_pointer_cast
<
SocketHelper
>
(
_parser
);
if
(
!
parser
){
return
nullptr
;
}
...
...
@@ -66,14 +66,14 @@ TaskExecutor::Ptr MediaPlayer::getExecutor(){
}
void
MediaPlayer
::
pause
(
bool
bPause
)
{
if
(
m
_parser
)
{
m
_parser
->
pause
(
bPause
);
if
(
_parser
)
{
_parser
->
pause
(
bPause
);
}
}
void
MediaPlayer
::
teardown
()
{
if
(
m
_parser
)
{
m
_parser
->
teardown
();
if
(
_parser
)
{
_parser
->
teardown
();
}
}
...
...
src/Player/MediaPlayer.h
查看文件 @
39baaebc
...
...
@@ -54,7 +54,7 @@ public:
void
teardown
()
override
;
TaskExecutor
::
Ptr
getExecutor
();
private
:
string
m
_strPrefix
;
string
_strPrefix
;
};
...
...
src/Player/PlayerBase.h
查看文件 @
39baaebc
...
...
@@ -101,73 +101,73 @@ public:
PlayerImp
(){}
virtual
~
PlayerImp
(){}
void
setOnShutdown
(
const
function
<
void
(
const
SockException
&
)
>
&
cb
)
override
{
if
(
m
_parser
)
{
m
_parser
->
setOnShutdown
(
cb
);
if
(
_parser
)
{
_parser
->
setOnShutdown
(
cb
);
}
m
_shutdownCB
=
cb
;
_shutdownCB
=
cb
;
}
void
setOnPlayResult
(
const
function
<
void
(
const
SockException
&
ex
)
>
&
cb
)
override
{
if
(
m
_parser
)
{
m
_parser
->
setOnPlayResult
(
cb
);
if
(
_parser
)
{
_parser
->
setOnPlayResult
(
cb
);
}
m
_playResultCB
=
cb
;
_playResultCB
=
cb
;
}
bool
isInited
()
const
override
{
if
(
m
_parser
)
{
return
m
_parser
->
isInited
();
if
(
_parser
)
{
return
_parser
->
isInited
();
}
return
PlayerBase
::
isInited
();
}
float
getDuration
()
const
override
{
if
(
m
_parser
)
{
return
m
_parser
->
getDuration
();
if
(
_parser
)
{
return
_parser
->
getDuration
();
}
return
PlayerBase
::
getDuration
();
}
float
getProgress
()
const
override
{
if
(
m
_parser
)
{
return
m
_parser
->
getProgress
();
if
(
_parser
)
{
return
_parser
->
getProgress
();
}
return
PlayerBase
::
getProgress
();
}
void
seekTo
(
float
fProgress
)
override
{
if
(
m
_parser
)
{
return
m
_parser
->
seekTo
(
fProgress
);
if
(
_parser
)
{
return
_parser
->
seekTo
(
fProgress
);
}
return
PlayerBase
::
seekTo
(
fProgress
);
}
void
setMediaSouce
(
const
MediaSource
::
Ptr
&
src
)
override
{
if
(
m
_parser
)
{
return
m
_parser
->
setMediaSouce
(
src
);
if
(
_parser
)
{
return
_parser
->
setMediaSouce
(
src
);
}
m
_pMediaSrc
=
src
;
_pMediaSrc
=
src
;
}
vector
<
Track
::
Ptr
>
getTracks
()
const
override
{
if
(
m
_parser
)
{
return
m
_parser
->
getTracks
();
if
(
_parser
)
{
return
_parser
->
getTracks
();
}
return
PlayerBase
::
getTracks
();
}
protected
:
void
onShutdown
(
const
SockException
&
ex
)
override
{
if
(
m
_shutdownCB
)
{
m
_shutdownCB
(
ex
);
if
(
_shutdownCB
)
{
_shutdownCB
(
ex
);
}
}
void
onPlayResult
(
const
SockException
&
ex
)
override
{
if
(
m
_playResultCB
)
{
m
_playResultCB
(
ex
);
m
_playResultCB
=
nullptr
;
if
(
_playResultCB
)
{
_playResultCB
(
ex
);
_playResultCB
=
nullptr
;
}
}
protected
:
function
<
void
(
const
SockException
&
ex
)
>
m
_shutdownCB
;
function
<
void
(
const
SockException
&
ex
)
>
m
_playResultCB
;
std
::
shared_ptr
<
Parser
>
m
_parser
;
MediaSource
::
Ptr
m
_pMediaSrc
;
function
<
void
(
const
SockException
&
ex
)
>
_shutdownCB
;
function
<
void
(
const
SockException
&
ex
)
>
_playResultCB
;
std
::
shared_ptr
<
Parser
>
_parser
;
MediaSource
::
Ptr
_pMediaSrc
;
};
}
/* namespace Player */
...
...
src/RTP/AACRtpCodec.cpp
查看文件 @
39baaebc
...
...
@@ -29,41 +29,41 @@ void AACRtpEncoder::inputFrame(const Frame::Ptr &frame) {
char
*
ptr
=
(
char
*
)
pcData
;
int
iSize
=
iLen
;
while
(
iSize
>
0
)
{
if
(
iSize
<=
m
_ui32MtuSize
-
20
)
{
m
_aucSectionBuf
[
0
]
=
0
;
m
_aucSectionBuf
[
1
]
=
16
;
m
_aucSectionBuf
[
2
]
=
iLen
>>
5
;
m
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
m
_aucSectionBuf
+
4
,
ptr
,
iSize
);
makeAACRtp
(
m
_aucSectionBuf
,
iSize
+
4
,
true
,
uiStamp
);
if
(
iSize
<=
_ui32MtuSize
-
20
)
{
_aucSectionBuf
[
0
]
=
0
;
_aucSectionBuf
[
1
]
=
16
;
_aucSectionBuf
[
2
]
=
iLen
>>
5
;
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
_aucSectionBuf
+
4
,
ptr
,
iSize
);
makeAACRtp
(
_aucSectionBuf
,
iSize
+
4
,
true
,
uiStamp
);
break
;
}
m
_aucSectionBuf
[
0
]
=
0
;
m
_aucSectionBuf
[
1
]
=
16
;
m
_aucSectionBuf
[
2
]
=
(
iLen
)
>>
5
;
m
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
m_aucSectionBuf
+
4
,
ptr
,
m
_ui32MtuSize
-
20
);
makeAACRtp
(
m_aucSectionBuf
,
m
_ui32MtuSize
-
16
,
false
,
uiStamp
);
ptr
+=
(
m
_ui32MtuSize
-
20
);
iSize
-=
(
m
_ui32MtuSize
-
20
);
_aucSectionBuf
[
0
]
=
0
;
_aucSectionBuf
[
1
]
=
16
;
_aucSectionBuf
[
2
]
=
(
iLen
)
>>
5
;
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
_aucSectionBuf
+
4
,
ptr
,
_ui32MtuSize
-
20
);
makeAACRtp
(
_aucSectionBuf
,
_ui32MtuSize
-
16
,
false
,
uiStamp
);
ptr
+=
(
_ui32MtuSize
-
20
);
iSize
-=
(
_ui32MtuSize
-
20
);
}
}
void
AACRtpEncoder
::
makeAACRtp
(
const
void
*
pData
,
unsigned
int
uiLen
,
bool
bMark
,
uint32_t
uiStamp
)
{
uint16_t
u16RtpLen
=
uiLen
+
12
;
m_ui32TimeStamp
=
(
m
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
m
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
m
_ui16Sequence
);
uint32_t
sc
=
htonl
(
m
_ui32Ssrc
);
_ui32TimeStamp
=
(
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
_ui16Sequence
);
uint32_t
sc
=
htonl
(
_ui32Ssrc
);
auto
pRtppkt
=
ResourcePoolHelper
<
RtpPacket
>::
obtainObj
();
auto
&
rtppkt
=
*
pRtppkt
;
unsigned
char
*
pucRtp
=
rtppkt
.
payload
;
pucRtp
[
0
]
=
'$'
;
pucRtp
[
1
]
=
m
_ui8Interleaved
;
pucRtp
[
1
]
=
_ui8Interleaved
;
pucRtp
[
2
]
=
u16RtpLen
>>
8
;
pucRtp
[
3
]
=
u16RtpLen
&
0x00FF
;
pucRtp
[
4
]
=
0x80
;
pucRtp
[
5
]
=
(
bMark
<<
7
)
|
m
_ui8PlayloadType
;
pucRtp
[
5
]
=
(
bMark
<<
7
)
|
_ui8PlayloadType
;
memcpy
(
&
pucRtp
[
6
],
&
sq
,
2
);
memcpy
(
&
pucRtp
[
8
],
&
ts
,
4
);
//ssrc
...
...
@@ -71,24 +71,24 @@ void AACRtpEncoder::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark
//playload
memcpy
(
&
pucRtp
[
16
],
pData
,
uiLen
);
rtppkt
.
PT
=
m
_ui8PlayloadType
;
rtppkt
.
interleaved
=
m
_ui8Interleaved
;
rtppkt
.
PT
=
_ui8PlayloadType
;
rtppkt
.
interleaved
=
_ui8Interleaved
;
rtppkt
.
mark
=
bMark
;
rtppkt
.
length
=
uiLen
+
16
;
rtppkt
.
sequence
=
m
_ui16Sequence
;
rtppkt
.
timeStamp
=
m
_ui32TimeStamp
;
rtppkt
.
ssrc
=
m
_ui32Ssrc
;
rtppkt
.
sequence
=
_ui16Sequence
;
rtppkt
.
timeStamp
=
_ui32TimeStamp
;
rtppkt
.
ssrc
=
_ui32Ssrc
;
rtppkt
.
type
=
TrackAudio
;
rtppkt
.
offset
=
16
;
RtpCodec
::
inputRtp
(
pRtppkt
,
false
);
m
_ui16Sequence
++
;
_ui16Sequence
++
;
}
/////////////////////////////////////////////////////////////////////////////////////
AACRtpDecoder
::
AACRtpDecoder
(
uint32_t
ui32SampleRate
)
{
m
_adts
=
obtainFrame
();
m
_sampleRate
=
ui32SampleRate
;
_adts
=
obtainFrame
();
_sampleRate
=
ui32SampleRate
;
}
AACFrame
::
Ptr
AACRtpDecoder
::
obtainFrame
()
{
...
...
@@ -103,18 +103,18 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
RtpCodec
::
inputRtp
(
rtppack
,
false
);
int
length
=
rtppack
->
length
-
rtppack
->
offset
;
if
(
m
_adts
->
aac_frame_length
+
length
-
4
>
sizeof
(
AACFrame
::
buffer
))
{
m
_adts
->
aac_frame_length
=
7
;
if
(
_adts
->
aac_frame_length
+
length
-
4
>
sizeof
(
AACFrame
::
buffer
))
{
_adts
->
aac_frame_length
=
7
;
WarnL
<<
"aac负载数据太长"
;
return
false
;
}
memcpy
(
m_adts
->
buffer
+
m
_adts
->
aac_frame_length
,
rtppack
->
payload
+
rtppack
->
offset
+
4
,
length
-
4
);
m
_adts
->
aac_frame_length
+=
(
length
-
4
);
memcpy
(
_adts
->
buffer
+
_adts
->
aac_frame_length
,
rtppack
->
payload
+
rtppack
->
offset
+
4
,
length
-
4
);
_adts
->
aac_frame_length
+=
(
length
-
4
);
if
(
rtppack
->
mark
==
true
)
{
m
_adts
->
sequence
=
rtppack
->
sequence
;
m_adts
->
timeStamp
=
rtppack
->
timeStamp
*
(
1000.0
/
m
_sampleRate
);
writeAdtsHeader
(
*
m_adts
,
m
_adts
->
buffer
);
onGetAAC
(
m
_adts
);
_adts
->
sequence
=
rtppack
->
sequence
;
_adts
->
timeStamp
=
rtppack
->
timeStamp
*
(
1000.0
/
_sampleRate
);
writeAdtsHeader
(
*
_adts
,
_adts
->
buffer
);
onGetAAC
(
_adts
);
}
return
false
;
}
...
...
@@ -122,7 +122,7 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
void
AACRtpDecoder
::
onGetAAC
(
const
AACFrame
::
Ptr
&
frame
)
{
//写入环形缓存
RtpCodec
::
inputFrame
(
frame
);
m
_adts
=
obtainFrame
();
_adts
=
obtainFrame
();
}
...
...
src/RTP/AACRtpCodec.h
查看文件 @
39baaebc
...
...
@@ -38,8 +38,8 @@ private:
void
onGetAAC
(
const
AACFrame
::
Ptr
&
frame
);
AACFrame
::
Ptr
obtainFrame
();
private
:
AACFrame
::
Ptr
m
_adts
;
uint32_t
m
_sampleRate
;
AACFrame
::
Ptr
_adts
;
uint32_t
_sampleRate
;
};
...
...
@@ -72,7 +72,7 @@ public:
private
:
void
makeAACRtp
(
const
void
*
pData
,
unsigned
int
uiLen
,
bool
bMark
,
uint32_t
uiStamp
);
private
:
unsigned
char
m
_aucSectionBuf
[
1600
];
unsigned
char
_aucSectionBuf
[
1600
];
};
...
...
src/RTP/H264RtpCodec.cpp
查看文件 @
39baaebc
...
...
@@ -6,7 +6,7 @@
H264RtpDecoder
::
H264RtpDecoder
()
{
m
_h264frame
=
obtainFrame
();
_h264frame
=
obtainFrame
();
}
H264Frame
::
Ptr
H264RtpDecoder
::
obtainFrame
()
{
...
...
@@ -40,13 +40,13 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if
(
nal
.
type
>=
0
&&
nal
.
type
<
24
)
{
//a full frame
m
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
m
_h264frame
->
buffer
.
append
((
char
*
)
frame
,
length
);
m
_h264frame
->
type
=
nal
.
type
;
m
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
/
90
;
m
_h264frame
->
sequence
=
rtppack
->
sequence
;
auto
isIDR
=
m
_h264frame
->
type
==
5
;
onGetH264
(
m
_h264frame
);
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
buffer
.
append
((
char
*
)
frame
,
length
);
_h264frame
->
type
=
nal
.
type
;
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
/
90
;
_h264frame
->
sequence
=
rtppack
->
sequence
;
auto
isIDR
=
_h264frame
->
type
==
5
;
onGetH264
(
_h264frame
);
return
(
isIDR
);
//i frame
}
...
...
@@ -57,31 +57,31 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if
(
fu
.
S
==
1
)
{
//FU-A start
char
tmp
=
(
nal
.
forbidden_zero_bit
<<
7
|
nal
.
nal_ref_idc
<<
5
|
fu
.
type
);
m
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
m
_h264frame
->
buffer
.
push_back
(
tmp
);
m
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
m
_h264frame
->
type
=
fu
.
type
;
m
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
/
90
;
m
_h264frame
->
sequence
=
rtppack
->
sequence
;
return
(
m
_h264frame
->
type
==
5
);
//i frame
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
_h264frame
->
buffer
.
push_back
(
tmp
);
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
type
=
fu
.
type
;
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
/
90
;
_h264frame
->
sequence
=
rtppack
->
sequence
;
return
(
_h264frame
->
type
==
5
);
//i frame
}
if
(
rtppack
->
sequence
!=
(
uint16_t
)(
m
_h264frame
->
sequence
+
1
))
{
m
_h264frame
->
buffer
.
clear
();
WarnL
<<
"丢包,帧废弃:"
<<
rtppack
->
sequence
<<
","
<<
m
_h264frame
->
sequence
;
if
(
rtppack
->
sequence
!=
(
uint16_t
)(
_h264frame
->
sequence
+
1
))
{
_h264frame
->
buffer
.
clear
();
WarnL
<<
"丢包,帧废弃:"
<<
rtppack
->
sequence
<<
","
<<
_h264frame
->
sequence
;
return
false
;
}
m
_h264frame
->
sequence
=
rtppack
->
sequence
;
_h264frame
->
sequence
=
rtppack
->
sequence
;
if
(
fu
.
E
==
1
)
{
//FU-A end
m
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
m
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
/
90
;
auto
isIDR
=
m
_h264frame
->
type
==
5
;
onGetH264
(
m
_h264frame
);
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
timeStamp
=
rtppack
->
timeStamp
/
90
;
auto
isIDR
=
_h264frame
->
type
==
5
;
onGetH264
(
_h264frame
);
return
isIDR
;
}
//FU-A mid
m
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
_h264frame
->
buffer
.
append
((
char
*
)
frame
+
2
,
length
-
2
);
return
false
;
}
...
...
@@ -100,7 +100,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
void
H264RtpDecoder
::
onGetH264
(
const
H264Frame
::
Ptr
&
frame
)
{
//写入环形缓存
RtpCodec
::
inputFrame
(
frame
);
m
_h264frame
=
obtainFrame
();
_h264frame
=
obtainFrame
();
}
...
...
@@ -127,7 +127,7 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
auto
iLen
=
frame
->
size
()
-
frame
->
prefixSize
();
uiStamp
%=
cycleMS
;
int
iSize
=
m
_ui32MtuSize
-
2
;
int
iSize
=
_ui32MtuSize
-
2
;
if
(
iLen
>
iSize
)
{
//超过MTU
const
unsigned
char
s_e_r_Start
=
0x80
;
const
unsigned
char
s_e_r_Mid
=
0x00
;
...
...
@@ -156,11 +156,11 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
s_e_r_type
=
s_e_r_Mid
+
naluType
;
}
}
memcpy
(
m
_aucSectionBuf
,
&
f_nri_type
,
1
);
memcpy
(
m
_aucSectionBuf
+
1
,
&
s_e_r_type
,
1
);
memcpy
(
m
_aucSectionBuf
+
2
,
(
unsigned
char
*
)
pcData
+
nOffset
,
iSize
);
memcpy
(
_aucSectionBuf
,
&
f_nri_type
,
1
);
memcpy
(
_aucSectionBuf
+
1
,
&
s_e_r_type
,
1
);
memcpy
(
_aucSectionBuf
+
2
,
(
unsigned
char
*
)
pcData
+
nOffset
,
iSize
);
nOffset
+=
iSize
;
makeH264Rtp
(
m
_aucSectionBuf
,
iSize
+
2
,
mark
,
uiStamp
);
makeH264Rtp
(
_aucSectionBuf
,
iSize
+
2
,
mark
,
uiStamp
);
}
}
else
{
makeH264Rtp
(
pcData
,
iLen
,
true
,
uiStamp
);
...
...
@@ -169,19 +169,19 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
void
H264RtpEncoder
::
makeH264Rtp
(
const
void
*
data
,
unsigned
int
len
,
bool
mark
,
uint32_t
uiStamp
)
{
uint16_t
ui16RtpLen
=
len
+
12
;
m_ui32TimeStamp
=
(
m
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
m
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
m
_ui16Sequence
);
uint32_t
sc
=
htonl
(
m
_ui32Ssrc
);
_ui32TimeStamp
=
(
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
_ui16Sequence
);
uint32_t
sc
=
htonl
(
_ui32Ssrc
);
auto
rtppkt
=
ResourcePoolHelper
<
RtpPacket
>::
obtainObj
();
unsigned
char
*
pucRtp
=
rtppkt
->
payload
;
pucRtp
[
0
]
=
'$'
;
pucRtp
[
1
]
=
m
_ui8Interleaved
;
pucRtp
[
1
]
=
_ui8Interleaved
;
pucRtp
[
2
]
=
ui16RtpLen
>>
8
;
pucRtp
[
3
]
=
ui16RtpLen
&
0x00FF
;
pucRtp
[
4
]
=
0x80
;
pucRtp
[
5
]
=
(
mark
<<
7
)
|
m
_ui8PlayloadType
;
pucRtp
[
5
]
=
(
mark
<<
7
)
|
_ui8PlayloadType
;
memcpy
(
&
pucRtp
[
6
],
&
sq
,
2
);
memcpy
(
&
pucRtp
[
8
],
&
ts
,
4
);
//ssrc
...
...
@@ -189,17 +189,17 @@ void H264RtpEncoder::makeH264Rtp(const void* data, unsigned int len, bool mark,
//playload
memcpy
(
&
pucRtp
[
16
],
data
,
len
);
rtppkt
->
PT
=
m
_ui8PlayloadType
;
rtppkt
->
interleaved
=
m
_ui8Interleaved
;
rtppkt
->
PT
=
_ui8PlayloadType
;
rtppkt
->
interleaved
=
_ui8Interleaved
;
rtppkt
->
mark
=
mark
;
rtppkt
->
length
=
len
+
16
;
rtppkt
->
sequence
=
m
_ui16Sequence
;
rtppkt
->
timeStamp
=
m
_ui32TimeStamp
;
rtppkt
->
ssrc
=
m
_ui32Ssrc
;
rtppkt
->
sequence
=
_ui16Sequence
;
rtppkt
->
timeStamp
=
_ui32TimeStamp
;
rtppkt
->
ssrc
=
_ui32Ssrc
;
rtppkt
->
type
=
TrackVideo
;
rtppkt
->
offset
=
16
;
uint8_t
type
=
((
uint8_t
*
)
(
data
))[
0
]
&
0x1F
;
RtpCodec
::
inputRtp
(
rtppkt
,
type
==
5
);
m
_ui16Sequence
++
;
_ui16Sequence
++
;
}
\ No newline at end of file
src/RTP/H264RtpCodec.h
查看文件 @
39baaebc
...
...
@@ -39,7 +39,7 @@ private:
void
onGetH264
(
const
H264Frame
::
Ptr
&
frame
);
H264Frame
::
Ptr
obtainFrame
();
private
:
H264Frame
::
Ptr
m
_h264frame
;
H264Frame
::
Ptr
_h264frame
;
};
/**
...
...
@@ -71,7 +71,7 @@ public:
private
:
void
makeH264Rtp
(
const
void
*
pData
,
unsigned
int
uiLen
,
bool
bMark
,
uint32_t
uiStamp
);
private
:
unsigned
char
m
_aucSectionBuf
[
1600
];
unsigned
char
_aucSectionBuf
[
1600
];
};
...
...
src/RTP/RtpCodec.h
查看文件 @
39baaebc
...
...
@@ -105,48 +105,48 @@ public:
if
(
ui32Ssrc
==
0
){
ui32Ssrc
=
((
uint64_t
)
this
)
&
0xFFFFFFFF
;
}
m
_ui32Ssrc
=
ui32Ssrc
;
m
_ui32SampleRate
=
ui32SampleRate
;
m
_ui32MtuSize
=
ui32MtuSize
;
m
_ui8PlayloadType
=
ui8PlayloadType
;
m
_ui8Interleaved
=
ui8Interleaved
;
_ui32Ssrc
=
ui32Ssrc
;
_ui32SampleRate
=
ui32SampleRate
;
_ui32MtuSize
=
ui32MtuSize
;
_ui8PlayloadType
=
ui8PlayloadType
;
_ui8Interleaved
=
ui8Interleaved
;
}
virtual
~
RtpInfo
(){}
int
getInterleaved
()
const
{
return
m
_ui8Interleaved
;
return
_ui8Interleaved
;
}
int
getPlayloadType
()
const
{
return
m
_ui8PlayloadType
;
return
_ui8PlayloadType
;
}
int
getSampleRate
()
const
{
return
m
_ui32SampleRate
;
return
_ui32SampleRate
;
}
uint32_t
getSsrc
()
const
{
return
m
_ui32Ssrc
;
return
_ui32Ssrc
;
}
uint16_t
getSeqence
()
const
{
return
m
_ui16Sequence
;
return
_ui16Sequence
;
}
uint32_t
getTimestamp
()
const
{
return
m
_ui32TimeStamp
;
return
_ui32TimeStamp
;
}
uint32_t
getMtuSize
()
const
{
return
m
_ui32MtuSize
;
return
_ui32MtuSize
;
}
protected
:
uint32_t
m
_ui32Ssrc
;
uint32_t
m
_ui32SampleRate
;
uint32_t
m
_ui32MtuSize
;
uint8_t
m
_ui8PlayloadType
;
uint8_t
m
_ui8Interleaved
;
uint16_t
m
_ui16Sequence
=
0
;
uint32_t
m
_ui32TimeStamp
=
0
;
uint32_t
_ui32Ssrc
;
uint32_t
_ui32SampleRate
;
uint32_t
_ui32MtuSize
;
uint8_t
_ui8PlayloadType
;
uint8_t
_ui8Interleaved
;
uint16_t
_ui16Sequence
=
0
;
uint32_t
_ui32TimeStamp
=
0
;
};
class
RtpCodec
:
public
RtpRing
,
public
FrameRingInterfaceDelegate
,
public
CodecInfo
,
public
ResourcePoolHelper
<
RtpPacket
>
{
...
...
src/RTP/RtpMaker.h
查看文件 @
39baaebc
...
...
@@ -49,12 +49,12 @@ public:
RtpMaker
(
const
onGetRTP
&
cb
,
uint32_t
ui32Ssrc
,
int
iMtuSize
,
int
iSampleRate
,
uint8_t
ui8PlayloadType
,
uint8_t
ui8Interleaved
)
{
callBack
=
cb
;
m
_ui32Ssrc
=
ui32Ssrc
;
m
_ui32SampleRate
=
iSampleRate
;
m
_iMtuSize
=
iMtuSize
;
m
_ui8PlayloadType
=
ui8PlayloadType
;
m
_ui8Interleaved
=
ui8Interleaved
;
m
_pktPool
.
setSize
(
64
);
_ui32Ssrc
=
ui32Ssrc
;
_ui32SampleRate
=
iSampleRate
;
_iMtuSize
=
iMtuSize
;
_ui8PlayloadType
=
ui8PlayloadType
;
_ui8Interleaved
=
ui8Interleaved
;
_pktPool
.
setSize
(
64
);
}
virtual
~
RtpMaker
()
{
}
...
...
@@ -62,43 +62,43 @@ public:
virtual
void
makeRtp
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
)
=
0
;
int
getInterleaved
()
const
{
return
m
_ui8Interleaved
;
return
_ui8Interleaved
;
}
int
getPlayloadType
()
const
{
return
m
_ui8PlayloadType
;
return
_ui8PlayloadType
;
}
int
getSampleRate
()
const
{
return
m
_ui32SampleRate
;
return
_ui32SampleRate
;
}
uint32_t
getSsrc
()
const
{
return
m
_ui32Ssrc
;
return
_ui32Ssrc
;
}
uint16_t
getSeqence
()
const
{
return
m
_ui16Sequence
;
return
_ui16Sequence
;
}
uint32_t
getTimestamp
()
const
{
return
m
_ui32TimeStamp
;
return
_ui32TimeStamp
;
}
protected
:
uint32_t
m
_ui32Ssrc
;
uint32_t
m
_ui32SampleRate
;
int
m
_iMtuSize
;
uint8_t
m
_ui8PlayloadType
;
uint8_t
m
_ui8Interleaved
;
uint16_t
m
_ui16Sequence
=
0
;
uint32_t
m
_ui32TimeStamp
=
0
;
uint32_t
_ui32Ssrc
;
uint32_t
_ui32SampleRate
;
int
_iMtuSize
;
uint8_t
_ui8PlayloadType
;
uint8_t
_ui8Interleaved
;
uint16_t
_ui16Sequence
=
0
;
uint32_t
_ui32TimeStamp
=
0
;
virtual
void
onMakeRtp
(
const
RtpPacket
::
Ptr
&
pkt
,
bool
bKeyPos
=
true
)
{
callBack
(
pkt
,
bKeyPos
);
}
inline
RtpPacket
::
Ptr
obtainPkt
()
{
return
m
_pktPool
.
obtain
();
return
_pktPool
.
obtain
();
}
private
:
RtspMediaSource
::
PoolType
m
_pktPool
;
RtspMediaSource
::
PoolType
_pktPool
;
onGetRTP
callBack
;
};
...
...
src/RTP/RtpMakerAAC.cpp
查看文件 @
39baaebc
...
...
@@ -42,42 +42,42 @@ void RtpMaker_AAC::makeRtp(const char *pcData, int iLen, uint32_t uiStamp) {
char
*
ptr
=
(
char
*
)
pcData
;
int
iSize
=
iLen
;
while
(
iSize
>
0
)
{
if
(
iSize
<=
m
_iMtuSize
-
20
)
{
m
_aucSectionBuf
[
0
]
=
0
;
m
_aucSectionBuf
[
1
]
=
16
;
m
_aucSectionBuf
[
2
]
=
iLen
>>
5
;
m
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
m
_aucSectionBuf
+
4
,
ptr
,
iSize
);
makeAACRtp
(
m
_aucSectionBuf
,
iSize
+
4
,
true
,
uiStamp
);
if
(
iSize
<=
_iMtuSize
-
20
)
{
_aucSectionBuf
[
0
]
=
0
;
_aucSectionBuf
[
1
]
=
16
;
_aucSectionBuf
[
2
]
=
iLen
>>
5
;
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
_aucSectionBuf
+
4
,
ptr
,
iSize
);
makeAACRtp
(
_aucSectionBuf
,
iSize
+
4
,
true
,
uiStamp
);
break
;
}
m
_aucSectionBuf
[
0
]
=
0
;
m
_aucSectionBuf
[
1
]
=
16
;
m
_aucSectionBuf
[
2
]
=
(
iLen
)
>>
5
;
m
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
m_aucSectionBuf
+
4
,
ptr
,
m
_iMtuSize
-
20
);
makeAACRtp
(
m_aucSectionBuf
,
m
_iMtuSize
-
16
,
false
,
uiStamp
);
ptr
+=
(
m
_iMtuSize
-
20
);
iSize
-=
(
m
_iMtuSize
-
20
);
_aucSectionBuf
[
0
]
=
0
;
_aucSectionBuf
[
1
]
=
16
;
_aucSectionBuf
[
2
]
=
(
iLen
)
>>
5
;
_aucSectionBuf
[
3
]
=
(
iLen
&
0x1F
)
<<
3
;
memcpy
(
_aucSectionBuf
+
4
,
ptr
,
_iMtuSize
-
20
);
makeAACRtp
(
_aucSectionBuf
,
_iMtuSize
-
16
,
false
,
uiStamp
);
ptr
+=
(
_iMtuSize
-
20
);
iSize
-=
(
_iMtuSize
-
20
);
}
}
inline
void
RtpMaker_AAC
::
makeAACRtp
(
const
void
*
pData
,
unsigned
int
uiLen
,
bool
bMark
,
uint32_t
uiStamp
)
{
uint16_t
u16RtpLen
=
uiLen
+
12
;
m_ui32TimeStamp
=
(
m
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
m
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
m
_ui16Sequence
);
uint32_t
sc
=
htonl
(
m
_ui32Ssrc
);
_ui32TimeStamp
=
(
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
_ui16Sequence
);
uint32_t
sc
=
htonl
(
_ui32Ssrc
);
auto
pRtppkt
=
obtainPkt
();
auto
&
rtppkt
=
*
(
pRtppkt
.
get
());
unsigned
char
*
pucRtp
=
rtppkt
.
payload
;
pucRtp
[
0
]
=
'$'
;
pucRtp
[
1
]
=
m
_ui8Interleaved
;
pucRtp
[
1
]
=
_ui8Interleaved
;
pucRtp
[
2
]
=
u16RtpLen
>>
8
;
pucRtp
[
3
]
=
u16RtpLen
&
0x00FF
;
pucRtp
[
4
]
=
0x80
;
pucRtp
[
5
]
=
(
bMark
<<
7
)
|
m
_ui8PlayloadType
;
pucRtp
[
5
]
=
(
bMark
<<
7
)
|
_ui8PlayloadType
;
memcpy
(
&
pucRtp
[
6
],
&
sq
,
2
);
memcpy
(
&
pucRtp
[
8
],
&
ts
,
4
);
//ssrc
...
...
@@ -85,18 +85,18 @@ inline void RtpMaker_AAC::makeAACRtp(const void *pData, unsigned int uiLen, bool
//playload
memcpy
(
&
pucRtp
[
16
],
pData
,
uiLen
);
rtppkt
.
PT
=
m
_ui8PlayloadType
;
rtppkt
.
interleaved
=
m
_ui8Interleaved
;
rtppkt
.
PT
=
_ui8PlayloadType
;
rtppkt
.
interleaved
=
_ui8Interleaved
;
rtppkt
.
mark
=
bMark
;
rtppkt
.
length
=
uiLen
+
16
;
rtppkt
.
sequence
=
m
_ui16Sequence
;
rtppkt
.
timeStamp
=
m
_ui32TimeStamp
;
rtppkt
.
ssrc
=
m
_ui32Ssrc
;
rtppkt
.
sequence
=
_ui16Sequence
;
rtppkt
.
timeStamp
=
_ui32TimeStamp
;
rtppkt
.
ssrc
=
_ui32Ssrc
;
rtppkt
.
type
=
TrackAudio
;
rtppkt
.
offset
=
16
;
onMakeRtp
(
pRtppkt
,
false
);
m
_ui16Sequence
++
;
_ui16Sequence
++
;
}
}
/* namespace RTP */
...
...
src/RTP/RtpMakerAAC.h
查看文件 @
39baaebc
...
...
@@ -53,7 +53,7 @@ public:
void
makeRtp
(
const
char
*
pcData
,
int
iDataLen
,
uint32_t
uiStamp
)
override
;
private
:
inline
void
makeAACRtp
(
const
void
*
pData
,
unsigned
int
uiLen
,
bool
bMark
,
uint32_t
uiStamp
);
unsigned
char
m
_aucSectionBuf
[
1600
];
unsigned
char
_aucSectionBuf
[
1600
];
};
}
/* namespace RTP */
...
...
src/RTP/RtpMakerH264.cpp
查看文件 @
39baaebc
...
...
@@ -39,7 +39,7 @@ void RtpMaker_H264::makeRtp(const char* pcData, int iLen, uint32_t uiStamp) {
GET_CONFIG_AND_REGISTER
(
uint32_t
,
cycleMS
,
Config
::
Rtp
::
kCycleMS
);
uiStamp
%=
cycleMS
;
int
iSize
=
m
_iMtuSize
-
2
;
int
iSize
=
_iMtuSize
-
2
;
if
(
iLen
>
iSize
)
{
//超过MTU
const
unsigned
char
s_e_r_Start
=
0x80
;
const
unsigned
char
s_e_r_Mid
=
0x00
;
...
...
@@ -81,20 +81,20 @@ void RtpMaker_H264::makeRtp(const char* pcData, int iLen, uint32_t uiStamp) {
inline
void
RtpMaker_H264
::
makeH264Rtp
(
const
void
*
data
,
unsigned
int
len
,
bool
mark
,
uint32_t
uiStamp
)
{
uint16_t
ui16RtpLen
=
len
+
12
;
m_ui32TimeStamp
=
(
m
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
m
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
m
_ui16Sequence
);
uint32_t
sc
=
htonl
(
m
_ui32Ssrc
);
_ui32TimeStamp
=
(
_ui32SampleRate
/
1000
)
*
uiStamp
;
uint32_t
ts
=
htonl
(
_ui32TimeStamp
);
uint16_t
sq
=
htons
(
_ui16Sequence
);
uint32_t
sc
=
htonl
(
_ui32Ssrc
);
auto
pRtppkt
=
obtainPkt
();
auto
&
rtppkt
=
*
(
pRtppkt
.
get
());
unsigned
char
*
pucRtp
=
rtppkt
.
payload
;
pucRtp
[
0
]
=
'$'
;
pucRtp
[
1
]
=
m
_ui8Interleaved
;
pucRtp
[
1
]
=
_ui8Interleaved
;
pucRtp
[
2
]
=
ui16RtpLen
>>
8
;
pucRtp
[
3
]
=
ui16RtpLen
&
0x00FF
;
pucRtp
[
4
]
=
0x80
;
pucRtp
[
5
]
=
(
mark
<<
7
)
|
m
_ui8PlayloadType
;
pucRtp
[
5
]
=
(
mark
<<
7
)
|
_ui8PlayloadType
;
memcpy
(
&
pucRtp
[
6
],
&
sq
,
2
);
memcpy
(
&
pucRtp
[
8
],
&
ts
,
4
);
//ssrc
...
...
@@ -102,19 +102,19 @@ inline void RtpMaker_H264::makeH264Rtp(const void* data, unsigned int len, bool
//playload
memcpy
(
&
pucRtp
[
16
],
data
,
len
);
rtppkt
.
PT
=
m
_ui8PlayloadType
;
rtppkt
.
interleaved
=
m
_ui8Interleaved
;
rtppkt
.
PT
=
_ui8PlayloadType
;
rtppkt
.
interleaved
=
_ui8Interleaved
;
rtppkt
.
mark
=
mark
;
rtppkt
.
length
=
len
+
16
;
rtppkt
.
sequence
=
m
_ui16Sequence
;
rtppkt
.
timeStamp
=
m
_ui32TimeStamp
;
rtppkt
.
ssrc
=
m
_ui32Ssrc
;
rtppkt
.
sequence
=
_ui16Sequence
;
rtppkt
.
timeStamp
=
_ui32TimeStamp
;
rtppkt
.
ssrc
=
_ui32Ssrc
;
rtppkt
.
type
=
TrackVideo
;
rtppkt
.
offset
=
16
;
uint8_t
type
=
((
uint8_t
*
)
(
data
))[
0
]
&
0x1F
;
onMakeRtp
(
pRtppkt
,
type
==
5
);
m
_ui16Sequence
++
;
_ui16Sequence
++
;
//InfoL<<timeStamp<<" "<<time<<" "<<sampleRate;
}
...
...
src/Rtmp/FlvMuxer.cpp
查看文件 @
39baaebc
...
...
@@ -43,8 +43,8 @@ void FlvMuxer::start(const RtmpMediaSource::Ptr &media) {
}
void
FlvMuxer
::
onWriteFlvHeader
(
const
RtmpMediaSource
::
Ptr
&
mediaSrc
)
{
m
_previousTagSize
=
0
;
CLEAR_ARR
(
m
_aui32FirstStamp
);
_previousTagSize
=
0
;
CLEAR_ARR
(
_aui32FirstStamp
);
//发送flv文件头
char
flv_file_header
[]
=
"FLV\x1\x5\x0\x0\x0\x9"
;
// have audio and have video
...
...
@@ -118,7 +118,7 @@ private:
void
FlvMuxer
::
onWriteFlvTag
(
const
RtmpPacket
::
Ptr
&
pkt
,
uint32_t
ui32TimeStamp
)
{
auto
size
=
htonl
(
m
_previousTagSize
);
auto
size
=
htonl
(
_previousTagSize
);
onWrite
((
char
*
)
&
size
,
4
);
//onWrite PreviousTagSize
RtmpTagHeader
header
;
header
.
type
=
pkt
->
typeId
;
...
...
@@ -127,11 +127,11 @@ void FlvMuxer::onWriteFlvTag(const RtmpPacket::Ptr &pkt, uint32_t ui32TimeStamp)
set_be24
(
header
.
timestamp
,
ui32TimeStamp
&
0xFFFFFF
);
onWrite
((
char
*
)
&
header
,
sizeof
(
header
));
//onWrite tag header
onWrite
(
std
::
make_shared
<
BufferRtmp
>
(
pkt
));
//onWrite tag data
m
_previousTagSize
+=
(
pkt
->
strBuf
.
size
()
+
sizeof
(
header
));
_previousTagSize
+=
(
pkt
->
strBuf
.
size
()
+
sizeof
(
header
));
}
void
FlvMuxer
::
onWriteFlvTag
(
uint8_t
ui8Type
,
const
std
::
string
&
strBuf
,
uint32_t
ui32TimeStamp
)
{
auto
size
=
htonl
(
m
_previousTagSize
);
auto
size
=
htonl
(
_previousTagSize
);
onWrite
((
char
*
)
&
size
,
4
);
//onWrite PreviousTagSize
RtmpTagHeader
header
;
header
.
type
=
ui8Type
;
...
...
@@ -140,12 +140,12 @@ void FlvMuxer::onWriteFlvTag(uint8_t ui8Type, const std::string &strBuf, uint32_
set_be24
(
header
.
timestamp
,
ui32TimeStamp
&
0xFFFFFF
);
onWrite
((
char
*
)
&
header
,
sizeof
(
header
));
//onWrite tag header
onWrite
(
std
::
make_shared
<
BufferString
>
(
strBuf
));
//onWrite tag data
m
_previousTagSize
+=
(
strBuf
.
size
()
+
sizeof
(
header
));
_previousTagSize
+=
(
strBuf
.
size
()
+
sizeof
(
header
));
}
void
FlvMuxer
::
onWriteRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
auto
modifiedStamp
=
pkt
->
timeStamp
;
auto
&
firstStamp
=
m
_aui32FirstStamp
[
pkt
->
typeId
%
2
];
auto
&
firstStamp
=
_aui32FirstStamp
[
pkt
->
typeId
%
2
];
if
(
!
firstStamp
){
firstStamp
=
modifiedStamp
;
}
...
...
@@ -154,7 +154,7 @@ void FlvMuxer::onWriteRtmp(const RtmpPacket::Ptr &pkt) {
modifiedStamp
-=
firstStamp
;
}
else
{
//发生回环,重新计算时间戳增量
CLEAR_ARR
(
m
_aui32FirstStamp
);
CLEAR_ARR
(
_aui32FirstStamp
);
modifiedStamp
=
0
;
}
onWriteFlvTag
(
pkt
,
modifiedStamp
);
...
...
src/Rtmp/FlvMuxer.h
查看文件 @
39baaebc
...
...
@@ -33,8 +33,8 @@ private:
void
onWriteFlvTag
(
uint8_t
ui8Type
,
const
std
::
string
&
strBuf
,
uint32_t
ui32TimeStamp
);
private
:
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_ring_reader
;
uint32_t
m
_aui32FirstStamp
[
2
]
=
{
0
};
uint32_t
m
_previousTagSize
=
0
;
uint32_t
_aui32FirstStamp
[
2
]
=
{
0
};
uint32_t
_previousTagSize
=
0
;
};
class
FlvRecorder
:
public
FlvMuxer
,
public
std
::
enable_shared_from_this
<
FlvRecorder
>
{
...
...
src/Rtmp/RtmpMediaSource.h
查看文件 @
39baaebc
...
...
@@ -60,66 +60,66 @@ public:
RtmpMediaSource
(
const
string
&
vhost
,
const
string
&
strApp
,
const
string
&
strId
)
:
MediaSource
(
RTMP_SCHEMA
,
vhost
,
strApp
,
strId
),
m
_pRing
(
new
RingBuffer
<
RtmpPacket
::
Ptr
>
())
{
_pRing
(
new
RingBuffer
<
RtmpPacket
::
Ptr
>
())
{
}
virtual
~
RtmpMediaSource
()
{}
const
RingType
::
Ptr
&
getRing
()
const
{
//获取媒体源的rtp环形缓冲
return
m
_pRing
;
return
_pRing
;
}
const
AMFValue
&
getMetaData
()
const
{
lock_guard
<
recursive_mutex
>
lock
(
m
_mtxMap
);
return
m
_metadata
;
lock_guard
<
recursive_mutex
>
lock
(
_mtxMap
);
return
_metadata
;
}
template
<
typename
FUN
>
void
getConfigFrame
(
const
FUN
&
f
)
{
lock_guard
<
recursive_mutex
>
lock
(
m
_mtxMap
);
for
(
auto
&
pr
:
m
_mapCfgFrame
)
{
lock_guard
<
recursive_mutex
>
lock
(
_mtxMap
);
for
(
auto
&
pr
:
_mapCfgFrame
)
{
f
(
pr
.
second
);
}
}
virtual
void
onGetMetaData
(
const
AMFValue
&
_
metadata
)
{
lock_guard
<
recursive_mutex
>
lock
(
m
_mtxMap
);
m_metadata
=
_
metadata
;
RtmpParser
parser
(
_
metadata
);
m
_iCfgFrameSize
=
parser
.
getTracks
().
size
();
virtual
void
onGetMetaData
(
const
AMFValue
&
metadata
)
{
lock_guard
<
recursive_mutex
>
lock
(
_mtxMap
);
_metadata
=
metadata
;
RtmpParser
parser
(
metadata
);
_iCfgFrameSize
=
parser
.
getTracks
().
size
();
if
(
ready
()){
MediaSource
::
regist
();
m
_bRegisted
=
true
;
_bRegisted
=
true
;
}
else
{
m
_bAsyncRegist
=
true
;
_bAsyncRegist
=
true
;
}
}
virtual
void
onGetMedia
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
lock_guard
<
recursive_mutex
>
lock
(
m
_mtxMap
);
lock_guard
<
recursive_mutex
>
lock
(
_mtxMap
);
if
(
pkt
->
isCfgFrame
())
{
m
_mapCfgFrame
.
emplace
(
pkt
->
typeId
,
pkt
);
_mapCfgFrame
.
emplace
(
pkt
->
typeId
,
pkt
);
if
(
m_bAsyncRegist
&&
!
m_bRegisted
&&
m_mapCfgFrame
.
size
()
==
m
_iCfgFrameSize
){
m
_bAsyncRegist
=
false
;
if
(
_bAsyncRegist
&&
!
_bRegisted
&&
_mapCfgFrame
.
size
()
==
_iCfgFrameSize
){
_bAsyncRegist
=
false
;
MediaSource
::
regist
();
m
_bRegisted
=
true
;
_bRegisted
=
true
;
}
}
m
_pRing
->
write
(
pkt
,
pkt
->
isVideoKeyFrame
());
_pRing
->
write
(
pkt
,
pkt
->
isVideoKeyFrame
());
}
private
:
bool
ready
(){
lock_guard
<
recursive_mutex
>
lock
(
m
_mtxMap
);
return
m_iCfgFrameSize
!=
-
1
&&
m_iCfgFrameSize
==
m
_mapCfgFrame
.
size
();
lock_guard
<
recursive_mutex
>
lock
(
_mtxMap
);
return
_iCfgFrameSize
!=
-
1
&&
_iCfgFrameSize
==
_mapCfgFrame
.
size
();
}
protected
:
AMFValue
m
_metadata
;
unordered_map
<
int
,
RtmpPacket
::
Ptr
>
m
_mapCfgFrame
;
mutable
recursive_mutex
m
_mtxMap
;
RingBuffer
<
RtmpPacket
::
Ptr
>::
Ptr
m
_pRing
;
//rtp环形缓冲
int
m
_iCfgFrameSize
=
-
1
;
bool
m
_bAsyncRegist
=
false
;
bool
m
_bRegisted
=
false
;
AMFValue
_metadata
;
unordered_map
<
int
,
RtmpPacket
::
Ptr
>
_mapCfgFrame
;
mutable
recursive_mutex
_mtxMap
;
RingBuffer
<
RtmpPacket
::
Ptr
>::
Ptr
_pRing
;
//rtp环形缓冲
int
_iCfgFrameSize
=
-
1
;
bool
_bAsyncRegist
=
false
;
bool
_bRegisted
=
false
;
};
}
/* namespace Rtmp */
...
...
src/Rtmp/RtmpParser.cpp
查看文件 @
39baaebc
...
...
@@ -36,13 +36,13 @@ RtmpParser::RtmpParser(const AMFValue &val) {
if
(
videoCodec
.
type
()
==
AMF_STRING
)
{
if
(
videoCodec
.
as_string
()
==
"avc1"
)
{
//h264
m
_iVideoCodecID
=
H264_CODEC_ID
;
_iVideoCodecID
=
H264_CODEC_ID
;
}
else
{
InfoL
<<
"不支持RTMP视频格式:"
<<
videoCodec
.
as_string
();
}
}
else
if
(
videoCodec
.
type
()
!=
AMF_NULL
){
m
_iVideoCodecID
=
videoCodec
.
as_integer
();
if
(
m
_iVideoCodecID
!=
H264_CODEC_ID
)
{
_iVideoCodecID
=
videoCodec
.
as_integer
();
if
(
_iVideoCodecID
!=
H264_CODEC_ID
)
{
InfoL
<<
"不支持RTMP视频格式:"
<<
videoCodec
.
as_integer
();
}
}
...
...
@@ -50,13 +50,13 @@ RtmpParser::RtmpParser(const AMFValue &val) {
if
(
audioCodec
.
type
()
==
AMF_STRING
)
{
if
(
audioCodec
.
as_string
()
==
"mp4a"
)
{
//aac
m
_iAudioCodecID
=
AAC_CODEC_ID
;
_iAudioCodecID
=
AAC_CODEC_ID
;
}
else
{
InfoL
<<
"不支持RTMP音频格式:"
<<
audioCodec
.
as_string
();
}
}
else
if
(
audioCodec
.
type
()
!=
AMF_NULL
)
{
m
_iAudioCodecID
=
audioCodec
.
as_integer
();
if
(
m
_iAudioCodecID
!=
AAC_CODEC_ID
)
{
_iAudioCodecID
=
audioCodec
.
as_integer
();
if
(
_iAudioCodecID
!=
AAC_CODEC_ID
)
{
InfoL
<<
"不支持RTMP音频格式:"
<<
audioCodec
.
as_integer
();
}
}
...
...
@@ -69,28 +69,28 @@ RtmpParser::~RtmpParser() {
bool
RtmpParser
::
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
switch
(
pkt
->
typeId
)
{
case
MSG_VIDEO
:{
if
(
m
_iVideoCodecID
==
0
){
if
(
_iVideoCodecID
==
0
){
//未初始化视频
m
_iVideoCodecID
=
pkt
->
getMediaType
();
if
(
m
_iVideoCodecID
!=
H264_CODEC_ID
){
InfoL
<<
"不支持RTMP视频格式:"
<<
m
_iVideoCodecID
;
_iVideoCodecID
=
pkt
->
getMediaType
();
if
(
_iVideoCodecID
!=
H264_CODEC_ID
){
InfoL
<<
"不支持RTMP视频格式:"
<<
_iVideoCodecID
;
}
}
if
(
m
_iVideoCodecID
==
H264_CODEC_ID
){
if
(
_iVideoCodecID
==
H264_CODEC_ID
){
return
inputVideo
(
pkt
);
}
return
false
;
}
case
MSG_AUDIO
:
{
if
(
m
_iAudioCodecID
==
0
){
if
(
_iAudioCodecID
==
0
){
//未初始化音频
m
_iAudioCodecID
=
pkt
->
getMediaType
();
if
(
m
_iAudioCodecID
!=
AAC_CODEC_ID
){
InfoL
<<
"不支持RTMP音频格式:"
<<
m
_iAudioCodecID
;
_iAudioCodecID
=
pkt
->
getMediaType
();
if
(
_iAudioCodecID
!=
AAC_CODEC_ID
){
InfoL
<<
"不支持RTMP音频格式:"
<<
_iAudioCodecID
;
}
}
if
(
m
_iAudioCodecID
==
AAC_CODEC_ID
)
{
if
(
_iAudioCodecID
==
AAC_CODEC_ID
)
{
return
inputAudio
(
pkt
);
}
return
false
;
...
...
@@ -104,20 +104,20 @@ bool RtmpParser::inputRtmp(const RtmpPacket::Ptr &pkt) {
inline
bool
RtmpParser
::
inputVideo
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
if
(
pkt
->
isCfgFrame
())
{
//WarnL << " got h264 cfg";
if
(
m
_strSPS
.
size
())
{
if
(
_strSPS
.
size
())
{
return
false
;
}
m
_strSPS
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
m
_strSPS
.
append
(
pkt
->
getH264SPS
());
_strSPS
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
_strSPS
.
append
(
pkt
->
getH264SPS
());
m
_strPPS
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
m
_strPPS
.
append
(
pkt
->
getH264PPS
());
_strPPS
.
assign
(
"
\x00\x00\x00\x01
"
,
4
);
_strPPS
.
append
(
pkt
->
getH264PPS
());
getAVCInfo
(
pkt
->
getH264SPS
(),
m_iVideoWidth
,
m_iVideoHeight
,
m
_fVideoFps
);
getAVCInfo
(
pkt
->
getH264SPS
(),
_iVideoWidth
,
_iVideoHeight
,
_fVideoFps
);
return
false
;
}
if
(
m
_strSPS
.
size
())
{
if
(
_strSPS
.
size
())
{
uint32_t
iTotalLen
=
pkt
->
strBuf
.
size
();
uint32_t
iOffset
=
5
;
while
(
iOffset
+
4
<
iTotalLen
){
...
...
@@ -137,8 +137,8 @@ inline bool RtmpParser::inputVideo(const RtmpPacket::Ptr &pkt) {
inline
void
RtmpParser
::
_onGetH264
(
const
char
*
pcData
,
int
iLen
,
uint32_t
ui32TimeStamp
)
{
switch
(
pcData
[
0
]
&
0x1F
)
{
case
5
:
{
onGetH264
(
m_strSPS
.
data
()
+
4
,
m
_strSPS
.
length
()
-
4
,
ui32TimeStamp
);
onGetH264
(
m_strPPS
.
data
()
+
4
,
m
_strPPS
.
length
()
-
4
,
ui32TimeStamp
);
onGetH264
(
_strSPS
.
data
()
+
4
,
_strSPS
.
length
()
-
4
,
ui32TimeStamp
);
onGetH264
(
_strPPS
.
data
()
+
4
,
_strPPS
.
length
()
-
4
,
ui32TimeStamp
);
}
case
1
:
{
onGetH264
(
pcData
,
iLen
,
ui32TimeStamp
);
...
...
@@ -150,82 +150,82 @@ inline void RtmpParser::_onGetH264(const char* pcData, int iLen, uint32_t ui32Ti
}
}
inline
void
RtmpParser
::
onGetH264
(
const
char
*
pcData
,
int
iLen
,
uint32_t
ui32TimeStamp
)
{
m
_h264frame
.
type
=
pcData
[
0
]
&
0x1F
;
m
_h264frame
.
timeStamp
=
ui32TimeStamp
;
m
_h264frame
.
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
//添加264头
m
_h264frame
.
buffer
.
append
(
pcData
,
iLen
);
_h264frame
.
type
=
pcData
[
0
]
&
0x1F
;
_h264frame
.
timeStamp
=
ui32TimeStamp
;
_h264frame
.
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
//添加264头
_h264frame
.
buffer
.
append
(
pcData
,
iLen
);
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtxCB
);
if
(
onVideo
)
{
onVideo
(
m
_h264frame
);
onVideo
(
_h264frame
);
}
}
m
_h264frame
.
buffer
.
clear
();
_h264frame
.
buffer
.
clear
();
}
inline
bool
RtmpParser
::
inputAudio
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
if
(
pkt
->
isCfgFrame
())
{
if
(
m
_strAudioCfg
.
size
())
{
if
(
_strAudioCfg
.
size
())
{
return
false
;
}
m
_strAudioCfg
=
pkt
->
getAacCfg
();
m
_iSampleBit
=
pkt
->
getAudioSampleBit
();
makeAdtsHeader
(
m_strAudioCfg
,
m
_adts
);
getAACInfo
(
m_adts
,
m_iSampleRate
,
m
_iChannel
);
_strAudioCfg
=
pkt
->
getAacCfg
();
_iSampleBit
=
pkt
->
getAudioSampleBit
();
makeAdtsHeader
(
_strAudioCfg
,
_adts
);
getAACInfo
(
_adts
,
_iSampleRate
,
_iChannel
);
return
false
;
}
if
(
m
_strAudioCfg
.
size
())
{
if
(
_strAudioCfg
.
size
())
{
onGetAAC
(
pkt
->
strBuf
.
data
()
+
2
,
pkt
->
strBuf
.
size
()
-
2
,
pkt
->
timeStamp
);
}
return
false
;
}
inline
void
RtmpParser
::
onGetAAC
(
const
char
*
pcData
,
int
iLen
,
uint32_t
ui32TimeStamp
)
{
if
(
iLen
+
7
>
sizeof
(
m
_adts
.
buffer
)){
if
(
iLen
+
7
>
sizeof
(
_adts
.
buffer
)){
WarnL
<<
"Illegal adts data, exceeding the length limit."
;
return
;
}
//添加adts头
memcpy
(
m
_adts
.
buffer
+
7
,
pcData
,
iLen
);
m
_adts
.
aac_frame_length
=
7
+
iLen
;
m
_adts
.
timeStamp
=
ui32TimeStamp
;
writeAdtsHeader
(
m_adts
,
m
_adts
.
buffer
);
memcpy
(
_adts
.
buffer
+
7
,
pcData
,
iLen
);
_adts
.
aac_frame_length
=
7
+
iLen
;
_adts
.
timeStamp
=
ui32TimeStamp
;
writeAdtsHeader
(
_adts
,
_adts
.
buffer
);
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxCB
);
lock_guard
<
recursive_mutex
>
lck
(
_mtxCB
);
if
(
onAudio
)
{
onAudio
(
m
_adts
);
onAudio
(
_adts
);
}
}
m
_adts
.
aac_frame_length
=
7
;
_adts
.
aac_frame_length
=
7
;
}
inline
void
RtmpParser
::
onCheckMedia
(
const
AMFValue
&
obj
)
{
obj
.
object_for_each
([
&
](
const
string
&
key
,
const
AMFValue
&
val
)
{
if
(
key
==
"duration"
)
{
m
_fDuration
=
val
.
as_number
();
_fDuration
=
val
.
as_number
();
return
;
}
if
(
key
==
"width"
)
{
m
_iVideoWidth
=
val
.
as_number
();
_iVideoWidth
=
val
.
as_number
();
return
;
}
if
(
key
==
"height"
)
{
m
_iVideoHeight
=
val
.
as_number
();
_iVideoHeight
=
val
.
as_number
();
return
;
}
if
(
key
==
"framerate"
)
{
m
_fVideoFps
=
val
.
as_number
();
_fVideoFps
=
val
.
as_number
();
return
;
}
if
(
key
==
"audiosamplerate"
)
{
m
_iSampleRate
=
val
.
as_number
();
_iSampleRate
=
val
.
as_number
();
return
;
}
if
(
key
==
"audiosamplesize"
)
{
m
_iSampleBit
=
val
.
as_number
();
_iSampleBit
=
val
.
as_number
();
return
;
}
if
(
key
==
"stereo"
)
{
m
_iChannel
=
val
.
as_boolean
()
?
2
:
1
;
_iChannel
=
val
.
as_boolean
()
?
2
:
1
;
return
;
}
});
...
...
src/Rtmp/RtmpParser.h
查看文件 @
39baaebc
...
...
@@ -54,19 +54,19 @@ public:
bool
inputRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
);
bool
isInited
()
const
override
{
if
((
m_iAudioCodecID
|
m
_iVideoCodecID
)
==
0
){
if
((
_iAudioCodecID
|
_iVideoCodecID
)
==
0
){
//音视频codec_id都未获取到,说明还未初始化成功
return
false
;
}
if
((
m_iAudioCodecID
&
m_iVideoCodecID
)
==
0
&&
m
_ticker
.
elapsedTime
()
<
300
){
if
((
_iAudioCodecID
&
_iVideoCodecID
)
==
0
&&
_ticker
.
elapsedTime
()
<
300
){
//音视频codec_id有其一未获取到,且最少分析300ms才能断定没有音频或视频
return
false
;
}
if
(
m_iAudioCodecID
&&
!
m
_strAudioCfg
.
size
())
{
if
(
_iAudioCodecID
&&
!
_strAudioCfg
.
size
())
{
//如果音频是aac但是还未获取aac config ,则未初始化成功
return
false
;
}
if
(
m_iVideoCodecID
&&
!
m
_strSPS
.
size
())
{
if
(
_iVideoCodecID
&&
!
_strSPS
.
size
())
{
//如果视频是h264但是还未获取sps ,则未初始化成功
return
false
;
}
...
...
@@ -74,7 +74,7 @@ public:
return
true
;
}
float
getDuration
()
const
override
{
return
m
_fDuration
;
return
_fDuration
;
}
private
:
inline
void
onCheckMedia
(
const
AMFValue
&
obj
);
...
...
@@ -86,28 +86,28 @@ private:
inline
void
onGetH264
(
const
char
*
pcData
,
int
iLen
,
uint32_t
ui32TimeStamp
);
inline
void
onGetAAC
(
const
char
*
pcData
,
int
iLen
,
uint32_t
ui32TimeStamp
);
//video
H264Frame
m
_h264frame
;
H264Frame
_h264frame
;
//aduio
AACFrame
m
_adts
;
AACFrame
_adts
;
int
m
_iSampleRate
=
44100
;
int
m
_iSampleBit
=
16
;
int
m
_iChannel
=
1
;
int
_iSampleRate
=
44100
;
int
_iSampleBit
=
16
;
int
_iChannel
=
1
;
string
m
_strSPS
;
string
m
_strPPS
;
string
m
_strAudioCfg
;
int
m
_iVideoWidth
=
0
;
int
m
_iVideoHeight
=
0
;
float
m
_fVideoFps
=
0
;
string
_strSPS
;
string
_strPPS
;
string
_strAudioCfg
;
int
_iVideoWidth
=
0
;
int
_iVideoHeight
=
0
;
float
_fVideoFps
=
0
;
//音视频codec_id初始为0代表尚未获取到
int
m
_iAudioCodecID
=
0
;
int
m
_iVideoCodecID
=
0
;
float
m
_fDuration
=
0
;
mutable
Ticker
m
_ticker
;
int
_iAudioCodecID
=
0
;
int
_iVideoCodecID
=
0
;
float
_fDuration
=
0
;
mutable
Ticker
_ticker
;
function
<
void
(
const
H264Frame
&
frame
)
>
onVideo
;
function
<
void
(
const
AACFrame
&
frame
)
>
onAudio
;
recursive_mutex
m
_mtxCB
;
recursive_mutex
_mtxCB
;
};
...
...
src/Rtmp/RtmpPlayer.cpp
查看文件 @
39baaebc
...
...
@@ -53,24 +53,24 @@ RtmpPlayer::~RtmpPlayer() {
}
void
RtmpPlayer
::
teardown
()
{
if
(
alive
())
{
m
_strApp
.
clear
();
m
_strStream
.
clear
();
m
_strTcUrl
.
clear
();
_strApp
.
clear
();
_strStream
.
clear
();
_strTcUrl
.
clear
();
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnResultCB
);
m
_mapOnResultCB
.
clear
();
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
_mapOnResultCB
.
clear
();
}
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnStatusCB
);
m
_dqOnStatusCB
.
clear
();
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnStatusCB
);
_dqOnStatusCB
.
clear
();
}
m
_pBeatTimer
.
reset
();
m
_pPlayTimer
.
reset
();
m
_pMediaTimer
.
reset
();
m
_fSeekTo
=
0
;
CLEAR_ARR
(
m
_adFistStamp
);
CLEAR_ARR
(
m
_adNowStamp
);
_pBeatTimer
.
reset
();
_pPlayTimer
.
reset
();
_pMediaTimer
.
reset
();
_fSeekTo
=
0
;
CLEAR_ARR
(
_adFistStamp
);
CLEAR_ARR
(
_adNowStamp
);
reset
();
shutdown
();
}
...
...
@@ -78,15 +78,15 @@ void RtmpPlayer::teardown() {
void
RtmpPlayer
::
play
(
const
char
*
strUrl
)
{
teardown
();
string
strHost
=
FindField
(
strUrl
,
"://"
,
"/"
);
m
_strApp
=
FindField
(
strUrl
,
(
strHost
+
"/"
).
data
(),
"/"
);
m_strStream
=
FindField
(
strUrl
,
(
strHost
+
"/"
+
m
_strApp
+
"/"
).
data
(),
NULL
);
m_strTcUrl
=
string
(
"rtmp://"
)
+
strHost
+
"/"
+
m
_strApp
;
_strApp
=
FindField
(
strUrl
,
(
strHost
+
"/"
).
data
(),
"/"
);
_strStream
=
FindField
(
strUrl
,
(
strHost
+
"/"
+
_strApp
+
"/"
).
data
(),
NULL
);
_strTcUrl
=
string
(
"rtmp://"
)
+
strHost
+
"/"
+
_strApp
;
if
(
!
m_strApp
.
size
()
||
!
m
_strStream
.
size
())
{
if
(
!
_strApp
.
size
()
||
!
_strStream
.
size
())
{
_onPlayResult
(
SockException
(
Err_other
,
"rtmp url非法"
));
return
;
}
DebugL
<<
strHost
<<
" "
<<
m_strApp
<<
" "
<<
m
_strStream
;
DebugL
<<
strHost
<<
" "
<<
_strApp
<<
" "
<<
_strStream
;
auto
iPort
=
atoi
(
FindField
(
strHost
.
c_str
(),
":"
,
NULL
).
c_str
());
if
(
iPort
<=
0
)
{
...
...
@@ -111,7 +111,7 @@ void RtmpPlayer::onConnect(const SockException &err){
}
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
m
_pPlayTimer
.
reset
(
new
Timer
(
10
,
[
weakSelf
]()
{
_pPlayTimer
.
reset
(
new
Timer
(
10
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
...
...
@@ -145,8 +145,8 @@ void RtmpPlayer::pause(bool bPause) {
inline
void
RtmpPlayer
::
send_connect
()
{
AMFValue
obj
(
AMF_OBJECT
);
obj
.
set
(
"app"
,
m
_strApp
);
obj
.
set
(
"tcUrl"
,
m
_strTcUrl
);
obj
.
set
(
"app"
,
_strApp
);
obj
.
set
(
"tcUrl"
,
_strTcUrl
);
//未使用代理
obj
.
set
(
"fpad"
,
false
);
//参考librtmp,什么作用?
...
...
@@ -177,14 +177,14 @@ inline void RtmpPlayer::send_createStream() {
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
//TraceL << "createStream result";
dec
.
load
<
AMFValue
>
();
m
_ui32StreamId
=
dec
.
load
<
int
>
();
_ui32StreamId
=
dec
.
load
<
int
>
();
send_play
();
});
}
inline
void
RtmpPlayer
::
send_play
()
{
AMFEncoder
enc
;
enc
<<
"play"
<<
++
m_iReqID
<<
nullptr
<<
m_strStream
<<
(
double
)
m
_ui32StreamId
;
enc
<<
"play"
<<
++
_iReqID
<<
nullptr
<<
_strStream
<<
(
double
)
_ui32StreamId
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
auto
fun
=
[
this
](
AMFValue
&
val
){
//TraceL << "play onStatus";
...
...
@@ -200,7 +200,7 @@ inline void RtmpPlayer::send_play() {
inline
void
RtmpPlayer
::
send_pause
(
bool
bPause
)
{
AMFEncoder
enc
;
enc
<<
"pause"
<<
++
m
_iReqID
<<
nullptr
<<
bPause
;
enc
<<
"pause"
<<
++
_iReqID
<<
nullptr
<<
bPause
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
auto
fun
=
[
this
,
bPause
](
AMFValue
&
val
){
//TraceL << "pause onStatus";
...
...
@@ -211,21 +211,21 @@ inline void RtmpPlayer::send_pause(bool bPause) {
throw
std
::
runtime_error
(
StrPrinter
<<
"pause 恢复播放失败:"
<<
level
<<
" "
<<
code
<<
endl
);
}
}
else
{
m
_bPaused
=
bPause
;
_bPaused
=
bPause
;
if
(
!
bPause
){
_onPlayResult
(
SockException
(
Err_success
,
"rtmp resum success"
));
}
else
{
//暂停播放
m
_pMediaTimer
.
reset
();
_pMediaTimer
.
reset
();
}
}
};
addOnStatusCB
(
fun
);
m
_pBeatTimer
.
reset
();
_pBeatTimer
.
reset
();
if
(
bPause
){
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
m
_pBeatTimer
.
reset
(
new
Timer
(
3
,[
weakSelf
](){
_pBeatTimer
.
reset
(
new
Timer
(
3
,[
weakSelf
](){
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
){
return
false
;
...
...
@@ -239,11 +239,11 @@ inline void RtmpPlayer::send_pause(bool bPause) {
void
RtmpPlayer
::
onCmd_result
(
AMFDecoder
&
dec
){
auto
iReqId
=
dec
.
load
<
int
>
();
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnResultCB
);
auto
it
=
m
_mapOnResultCB
.
find
(
iReqId
);
if
(
it
!=
m
_mapOnResultCB
.
end
()){
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
auto
it
=
_mapOnResultCB
.
find
(
iReqId
);
if
(
it
!=
_mapOnResultCB
.
end
()){
it
->
second
(
dec
);
m
_mapOnResultCB
.
erase
(
it
);
_mapOnResultCB
.
erase
(
it
);
}
else
{
WarnL
<<
"unhandled _result"
;
}
...
...
@@ -260,10 +260,10 @@ void RtmpPlayer::onCmd_onStatus(AMFDecoder &dec) {
throw
std
::
runtime_error
(
"onStatus:the result object was not found"
);
}
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnStatusCB
);
if
(
m
_dqOnStatusCB
.
size
()){
m
_dqOnStatusCB
.
front
()(
val
);
m
_dqOnStatusCB
.
pop_front
();
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnStatusCB
);
if
(
_dqOnStatusCB
.
size
()){
_dqOnStatusCB
.
front
()(
val
);
_dqOnStatusCB
.
pop_front
();
}
else
{
auto
level
=
val
[
"level"
];
auto
code
=
val
[
"code"
].
as_string
();
...
...
@@ -311,8 +311,8 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
case
MSG_AUDIO
:
case
MSG_VIDEO
:
{
auto
idx
=
chunkData
.
typeId
%
2
;
if
(
m
_aNowStampTicker
[
idx
].
elapsedTime
()
>
500
)
{
m
_adNowStamp
[
idx
]
=
chunkData
.
timeStamp
;
if
(
_aNowStampTicker
[
idx
].
elapsedTime
()
>
500
)
{
_adNowStamp
[
idx
]
=
chunkData
.
timeStamp
;
}
_onMediaData
(
std
::
make_shared
<
RtmpPacket
>
(
chunkData
));
}
...
...
@@ -326,27 +326,27 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
float
RtmpPlayer
::
getProgressTime
()
const
{
double
iTime
[
2
]
=
{
0
,
0
};
for
(
auto
i
=
0
;
i
<
2
;
i
++
){
iTime
[
i
]
=
(
m_adNowStamp
[
i
]
-
m
_adFistStamp
[
i
])
/
1000.0
;
iTime
[
i
]
=
(
_adNowStamp
[
i
]
-
_adFistStamp
[
i
])
/
1000.0
;
}
return
m
_fSeekTo
+
MAX
(
iTime
[
0
],
iTime
[
1
]);
return
_fSeekTo
+
MAX
(
iTime
[
0
],
iTime
[
1
]);
}
void
RtmpPlayer
::
seekToTime
(
float
fTime
){
if
(
m
_bPaused
)
{
if
(
_bPaused
)
{
pause
(
false
);
}
AMFEncoder
enc
;
enc
<<
"seek"
<<
++
m
_iReqID
<<
nullptr
<<
fTime
*
1000.0
;
enc
<<
"seek"
<<
++
_iReqID
<<
nullptr
<<
fTime
*
1000.0
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
addOnStatusCB
([
this
,
fTime
](
AMFValue
&
val
)
{
//TraceL << "seek result";
m
_aNowStampTicker
[
0
].
resetTime
();
m
_aNowStampTicker
[
1
].
resetTime
();
_aNowStampTicker
[
0
].
resetTime
();
_aNowStampTicker
[
1
].
resetTime
();
float
iTimeInc
=
fTime
-
getProgressTime
();
for
(
auto
i
=
0
;
i
<
2
;
i
++
){
m_adFistStamp
[
i
]
=
m
_adNowStamp
[
i
]
+
iTimeInc
*
1000.0
;
m_adNowStamp
[
i
]
=
m
_adFistStamp
[
i
];
_adFistStamp
[
i
]
=
_adNowStamp
[
i
]
+
iTimeInc
*
1000.0
;
_adNowStamp
[
i
]
=
_adFistStamp
[
i
];
}
m
_fSeekTo
=
fTime
;
_fSeekTo
=
fTime
;
});
}
...
...
src/Rtmp/RtmpPlayer.h
查看文件 @
39baaebc
...
...
@@ -65,28 +65,28 @@ protected:
private
:
void
_onShutdown
(
const
SockException
&
ex
)
{
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
m
_pPlayTimer
.
reset
();
m
_pMediaTimer
.
reset
();
m
_pBeatTimer
.
reset
();
_pPlayTimer
.
reset
();
_pMediaTimer
.
reset
();
_pBeatTimer
.
reset
();
onShutdown
(
ex
);
}
void
_onMediaData
(
const
RtmpPacket
::
Ptr
&
chunkData
)
{
m
_mediaTicker
.
resetTime
();
_mediaTicker
.
resetTime
();
onMediaData
(
chunkData
);
}
void
_onPlayResult
(
const
SockException
&
ex
)
{
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
m
_pPlayTimer
.
reset
();
m
_pMediaTimer
.
reset
();
_pPlayTimer
.
reset
();
_pMediaTimer
.
reset
();
if
(
!
ex
)
{
m
_mediaTicker
.
resetTime
();
_mediaTicker
.
resetTime
();
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
m
_pMediaTimer
.
reset
(
new
Timer
(
5
,
[
weakSelf
]()
{
_pMediaTimer
.
reset
(
new
Timer
(
5
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
if
(
strongSelf
->
m
_mediaTicker
.
elapsedTime
()
>
10000
)
{
if
(
strongSelf
->
_mediaTicker
.
elapsedTime
()
>
10000
)
{
//recv media timeout!
strongSelf
->
_onShutdown
(
SockException
(
Err_timeout
,
"recv rtmp timeout"
));
strongSelf
->
teardown
();
...
...
@@ -111,13 +111,13 @@ private:
template
<
typename
FUN
>
inline
void
addOnResultCB
(
const
FUN
&
fun
)
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnResultCB
);
m_mapOnResultCB
.
emplace
(
m
_iReqID
,
fun
);
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
_mapOnResultCB
.
emplace
(
_iReqID
,
fun
);
}
template
<
typename
FUN
>
inline
void
addOnStatusCB
(
const
FUN
&
fun
)
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnStatusCB
);
m
_dqOnStatusCB
.
emplace_back
(
fun
);
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnStatusCB
);
_dqOnStatusCB
.
emplace_back
(
fun
);
}
void
onCmd_result
(
AMFDecoder
&
dec
);
...
...
@@ -129,31 +129,31 @@ private:
inline
void
send_play
();
inline
void
send_pause
(
bool
bPause
);
string
m
_strApp
;
string
m
_strStream
;
string
m
_strTcUrl
;
bool
m
_bPaused
=
false
;
string
_strApp
;
string
_strStream
;
string
_strTcUrl
;
bool
_bPaused
=
false
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
m
_mapOnResultCB
;
recursive_mutex
m
_mtxOnResultCB
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
m
_dqOnStatusCB
;
recursive_mutex
m
_mtxOnStatusCB
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
_mapOnResultCB
;
recursive_mutex
_mtxOnResultCB
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
_dqOnStatusCB
;
recursive_mutex
_mtxOnStatusCB
;
typedef
void
(
RtmpPlayer
::*
rtmpCMDHandle
)(
AMFDecoder
&
dec
);
static
unordered_map
<
string
,
rtmpCMDHandle
>
g_mapCmd
;
//超时功能实现
Ticker
m
_mediaTicker
;
std
::
shared_ptr
<
Timer
>
m
_pMediaTimer
;
std
::
shared_ptr
<
Timer
>
m
_pPlayTimer
;
Ticker
_mediaTicker
;
std
::
shared_ptr
<
Timer
>
_pMediaTimer
;
std
::
shared_ptr
<
Timer
>
_pPlayTimer
;
//心跳定时器
std
::
shared_ptr
<
Timer
>
m
_pBeatTimer
;
std
::
shared_ptr
<
Timer
>
_pBeatTimer
;
//播放进度控制
float
m
_fSeekTo
=
0
;
double
m
_adFistStamp
[
2
]
=
{
0
,
0
};
double
m
_adNowStamp
[
2
]
=
{
0
,
0
};
Ticker
m
_aNowStampTicker
[
2
];
float
_fSeekTo
=
0
;
double
_adFistStamp
[
2
]
=
{
0
,
0
};
double
_adNowStamp
[
2
]
=
{
0
,
0
};
Ticker
_aNowStampTicker
[
2
];
};
}
/* namespace Rtmp */
...
...
src/Rtmp/RtmpPlayerImp.h
查看文件 @
39baaebc
...
...
@@ -63,32 +63,32 @@ public:
private
:
//派生类回调函数
bool
onCheckMeta
(
AMFValue
&
val
)
override
{
m_pRtmpMediaSrc
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
m
_pMediaSrc
);
if
(
m
_pRtmpMediaSrc
){
m
_pRtmpMediaSrc
->
onGetMetaData
(
val
);
_pRtmpMediaSrc
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
_pMediaSrc
);
if
(
_pRtmpMediaSrc
){
_pRtmpMediaSrc
->
onGetMetaData
(
val
);
}
try
{
m
_parser
.
reset
(
new
RtmpParser
(
val
));
_parser
.
reset
(
new
RtmpParser
(
val
));
//todo(xzl) 修复此处
//
m_parser->setOnVideoCB(m
_onGetVideoCB);
//
m_parser->setOnAudioCB(m
_onGetAudioCB);
//
_parser->setOnVideoCB(
_onGetVideoCB);
//
_parser->setOnAudioCB(
_onGetAudioCB);
return
true
;
}
catch
(
std
::
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
return
m
_pRtmpMediaSrc
?
true
:
false
;
return
_pRtmpMediaSrc
?
true
:
false
;
}
}
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunkData
)
override
{
if
(
m
_parser
){
m
_parser
->
inputRtmp
(
chunkData
);
if
(
_parser
){
_parser
->
inputRtmp
(
chunkData
);
}
if
(
m
_pRtmpMediaSrc
){
m
_pRtmpMediaSrc
->
onGetMedia
(
chunkData
);
if
(
_pRtmpMediaSrc
){
_pRtmpMediaSrc
->
onGetMedia
(
chunkData
);
}
}
private
:
RtmpMediaSource
::
Ptr
m
_pRtmpMediaSrc
;
RtmpMediaSource
::
Ptr
_pRtmpMediaSrc
;
};
...
...
src/Rtmp/RtmpProtocol.cpp
查看文件 @
39baaebc
...
...
@@ -76,7 +76,7 @@ namespace ZL {
namespace
Rtmp
{
RtmpProtocol
::
RtmpProtocol
()
{
m
_nextHandle
=
[
this
](){
_nextHandle
=
[
this
](){
handle_C0C1
();
};
}
...
...
@@ -85,25 +85,25 @@ RtmpProtocol::~RtmpProtocol() {
}
void
RtmpProtocol
::
reset
()
{
////////////ChunkSize////////////
m
_iChunkLenIn
=
DEFAULT_CHUNK_LEN
;
m
_iChunkLenOut
=
DEFAULT_CHUNK_LEN
;
_iChunkLenIn
=
DEFAULT_CHUNK_LEN
;
_iChunkLenOut
=
DEFAULT_CHUNK_LEN
;
////////////Acknowledgement////////////
m
_ui32ByteSent
=
0
;
m
_ui32LastSent
=
0
;
m
_ui32WinSize
=
0
;
_ui32ByteSent
=
0
;
_ui32LastSent
=
0
;
_ui32WinSize
=
0
;
///////////PeerBandwidth///////////
m
_ui32Bandwidth
=
2500000
;
m
_ui8LimitType
=
2
;
_ui32Bandwidth
=
2500000
;
_ui8LimitType
=
2
;
////////////Chunk////////////
m
_mapChunkData
.
clear
();
m
_iNowStreamID
=
0
;
m
_iNowChunkID
=
0
;
_mapChunkData
.
clear
();
_iNowStreamID
=
0
;
_iNowChunkID
=
0
;
//////////Invoke Request//////////
m
_iReqID
=
0
;
_iReqID
=
0
;
//////////Rtmp parser//////////
m
_strRcvBuf
.
clear
();
m
_ui32StreamId
=
STREAM_CONTROL
;
m
_nextHandle
=
[
this
]()
{
_strRcvBuf
.
clear
();
_ui32StreamId
=
STREAM_CONTROL
;
_nextHandle
=
[
this
]()
{
handle_C0C1
();
};
}
...
...
@@ -132,7 +132,7 @@ void RtmpProtocol::sendChunkSize(uint32_t ui32Size) {
uint32_t
len
=
htonl
(
ui32Size
);
std
::
string
set_chunk
((
char
*
)
&
len
,
4
);
sendRequest
(
MSG_SET_CHUNK
,
set_chunk
);
m
_iChunkLenOut
=
ui32Size
;
_iChunkLenOut
=
ui32Size
;
}
void
RtmpProtocol
::
sendPingRequest
(
uint32_t
ui32TimeStamp
)
{
...
...
@@ -173,20 +173,20 @@ void RtmpProtocol::sendUserControl(uint16_t ui16EventType,
}
void
RtmpProtocol
::
sendResponse
(
int
iType
,
const
string
&
str
)
{
if
(
!
m
_bDataStarted
&&
(
iType
==
MSG_DATA
)){
m
_bDataStarted
=
true
;
if
(
!
_bDataStarted
&&
(
iType
==
MSG_DATA
)){
_bDataStarted
=
true
;
}
sendRtmp
(
iType
,
m_iNowStreamID
,
str
,
0
,
m
_bDataStarted
?
CHUNK_CLIENT_REQUEST_AFTER
:
CHUNK_CLIENT_REQUEST_BEFORE
);
sendRtmp
(
iType
,
_iNowStreamID
,
str
,
0
,
_bDataStarted
?
CHUNK_CLIENT_REQUEST_AFTER
:
CHUNK_CLIENT_REQUEST_BEFORE
);
}
void
RtmpProtocol
::
sendInvoke
(
const
string
&
strCmd
,
const
AMFValue
&
val
)
{
AMFEncoder
enc
;
enc
<<
strCmd
<<
++
m
_iReqID
<<
val
;
enc
<<
strCmd
<<
++
_iReqID
<<
val
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
}
void
RtmpProtocol
::
sendRequest
(
int
iCmd
,
const
string
&
str
)
{
sendRtmp
(
iCmd
,
m
_ui32StreamId
,
str
,
0
,
CHUNK_SERVER_REQUEST
);
sendRtmp
(
iCmd
,
_ui32StreamId
,
str
,
0
,
CHUNK_SERVER_REQUEST
);
}
void
RtmpProtocol
::
sendRtmp
(
uint8_t
ui8Type
,
uint32_t
ui32StreamId
,
...
...
@@ -205,7 +205,7 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
set_le32
(
header
.
streamId
,
ui32StreamId
);
//估算rtmp包数据大小
uint32_t
capacity
=
((
bExtStamp
?
5
:
1
)
*
(
1
+
(
strBuf
.
size
()
/
m
_iChunkLenOut
)))
+
strBuf
.
size
()
+
sizeof
(
header
);
uint32_t
capacity
=
((
bExtStamp
?
5
:
1
)
*
(
1
+
(
strBuf
.
size
()
/
_iChunkLenOut
)))
+
strBuf
.
size
()
+
sizeof
(
header
);
uint32_t
totalSize
=
0
;
BufferRaw
::
Ptr
buffer
=
obtainBuffer
();
buffer
->
setCapacity
(
capacity
);
...
...
@@ -229,23 +229,23 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
memcpy
(
buffer
->
data
()
+
totalSize
,
acExtStamp
,
4
);
totalSize
+=
4
;
}
size_t
chunk
=
min
(
m
_iChunkLenOut
,
strBuf
.
size
()
-
pos
);
size_t
chunk
=
min
(
_iChunkLenOut
,
strBuf
.
size
()
-
pos
);
memcpy
(
buffer
->
data
()
+
totalSize
,
strBuf
.
data
()
+
pos
,
chunk
);
totalSize
+=
chunk
;
pos
+=
chunk
;
}
buffer
->
setSize
(
totalSize
);
onSendRawData
(
buffer
);
m
_ui32ByteSent
+=
totalSize
;
if
(
m_ui32WinSize
>
0
&&
m_ui32ByteSent
-
m_ui32LastSent
>=
m
_ui32WinSize
)
{
m_ui32LastSent
=
m
_ui32ByteSent
;
sendAcknowledgement
(
m
_ui32ByteSent
);
_ui32ByteSent
+=
totalSize
;
if
(
_ui32WinSize
>
0
&&
_ui32ByteSent
-
_ui32LastSent
>=
_ui32WinSize
)
{
_ui32LastSent
=
_ui32ByteSent
;
sendAcknowledgement
(
_ui32ByteSent
);
}
}
void
RtmpProtocol
::
onParseRtmp
(
const
char
*
pcRawData
,
int
iSize
)
{
m
_strRcvBuf
.
append
(
pcRawData
,
iSize
);
auto
cb
=
m
_nextHandle
;
_strRcvBuf
.
append
(
pcRawData
,
iSize
);
auto
cb
=
_nextHandle
;
cb
();
}
...
...
@@ -256,25 +256,25 @@ void RtmpProtocol::startClientSession(const function<void()> &callBack) {
onSendRawData
(
obtainBuffer
(
&
handshake_head
,
1
));
RtmpHandshake
c1
(
0
);
onSendRawData
(
obtainBuffer
((
char
*
)
(
&
c1
),
sizeof
(
c1
)));
m
_nextHandle
=
[
this
,
callBack
]()
{
_nextHandle
=
[
this
,
callBack
]()
{
//等待 S0+S1+S2
handle_S0S1S2
(
callBack
);
};
}
void
RtmpProtocol
::
handle_S0S1S2
(
const
function
<
void
()
>
&
callBack
)
{
if
(
m
_strRcvBuf
.
size
()
<
1
+
2
*
C1_HANDSHARK_SIZE
)
{
if
(
_strRcvBuf
.
size
()
<
1
+
2
*
C1_HANDSHARK_SIZE
)
{
//数据不够
return
;
}
if
(
m
_strRcvBuf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
if
(
_strRcvBuf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
throw
std
::
runtime_error
(
"only plaintext[0x03] handshake supported"
);
}
//发送 C2
const
char
*
pcC2
=
m
_strRcvBuf
.
data
()
+
1
;
const
char
*
pcC2
=
_strRcvBuf
.
data
()
+
1
;
onSendRawData
(
obtainBuffer
(
pcC2
,
C1_HANDSHARK_SIZE
));
m
_strRcvBuf
.
erase
(
0
,
1
+
2
*
C1_HANDSHARK_SIZE
);
_strRcvBuf
.
erase
(
0
,
1
+
2
*
C1_HANDSHARK_SIZE
);
//握手结束
m
_nextHandle
=
[
this
]()
{
_nextHandle
=
[
this
]()
{
//握手结束并且开始进入解析命令模式
handle_rtmp
();
};
...
...
@@ -282,14 +282,14 @@ void RtmpProtocol::handle_S0S1S2(const function<void()> &callBack) {
}
////for server ////
void
RtmpProtocol
::
handle_C0C1
()
{
if
(
m
_strRcvBuf
.
size
()
<
1
+
C1_HANDSHARK_SIZE
)
{
if
(
_strRcvBuf
.
size
()
<
1
+
C1_HANDSHARK_SIZE
)
{
//need more data!
return
;
}
if
(
m
_strRcvBuf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
if
(
_strRcvBuf
[
0
]
!=
HANDSHAKE_PLAINTEXT
)
{
throw
std
::
runtime_error
(
"only plaintext[0x03] handshake supported"
);
}
if
(
memcmp
(
m
_strRcvBuf
.
c_str
()
+
5
,
"
\x00\x00\x00\x00
"
,
4
)
==
0
){
if
(
memcmp
(
_strRcvBuf
.
c_str
()
+
5
,
"
\x00\x00\x00\x00
"
,
4
)
==
0
){
//simple handsharke
handle_C1_simple
();
}
else
{
...
...
@@ -301,7 +301,7 @@ void RtmpProtocol::handle_C0C1() {
handle_C1_simple
();
#endif//ENABLE_OPENSSL
}
m
_strRcvBuf
.
erase
(
0
,
1
+
C1_HANDSHARK_SIZE
);
_strRcvBuf
.
erase
(
0
,
1
+
C1_HANDSHARK_SIZE
);
}
void
RtmpProtocol
::
handle_C1_simple
(){
//发送S0
...
...
@@ -311,9 +311,9 @@ void RtmpProtocol::handle_C1_simple(){
RtmpHandshake
s1
(
0
);
onSendRawData
(
obtainBuffer
((
char
*
)
&
s1
,
C1_HANDSHARK_SIZE
));
//发送S2
onSendRawData
(
obtainBuffer
(
m
_strRcvBuf
.
c_str
()
+
1
,
C1_HANDSHARK_SIZE
));
onSendRawData
(
obtainBuffer
(
_strRcvBuf
.
c_str
()
+
1
,
C1_HANDSHARK_SIZE
));
//等待C2
m
_nextHandle
=
[
this
]()
{
_nextHandle
=
[
this
]()
{
handle_C2
();
};
}
...
...
@@ -321,7 +321,7 @@ void RtmpProtocol::handle_C1_simple(){
void
RtmpProtocol
::
handle_C1_complex
(){
//参考自:http://blog.csdn.net/win_lin/article/details/13006803
//skip c0,time,version
const
char
*
c1_start
=
m
_strRcvBuf
.
data
()
+
1
;
const
char
*
c1_start
=
_strRcvBuf
.
data
()
+
1
;
const
char
*
schema_start
=
c1_start
+
8
;
char
*
digest_start
;
try
{
...
...
@@ -470,57 +470,57 @@ void RtmpProtocol::send_complex_S0S1S2(int schemeType,const string &digest){
memcpy
((
char
*
)
&
s2
+
C1_HANDSHARK_SIZE
-
C1_DIGEST_SIZE
,
s2_digest
.
data
(),
C1_DIGEST_SIZE
);
onSendRawData
(
obtainBuffer
((
char
*
)
&
s2
,
sizeof
(
s2
)));
//等待C2
m
_nextHandle
=
[
this
]()
{
_nextHandle
=
[
this
]()
{
handle_C2
();
};
}
#endif //ENABLE_OPENSSL
void
RtmpProtocol
::
handle_C2
()
{
if
(
m
_strRcvBuf
.
size
()
<
C1_HANDSHARK_SIZE
)
{
if
(
_strRcvBuf
.
size
()
<
C1_HANDSHARK_SIZE
)
{
//need more data!
return
;
}
m
_strRcvBuf
.
erase
(
0
,
C1_HANDSHARK_SIZE
);
_strRcvBuf
.
erase
(
0
,
C1_HANDSHARK_SIZE
);
//握手结束,进入命令模式
if
(
!
m
_strRcvBuf
.
empty
())
{
if
(
!
_strRcvBuf
.
empty
())
{
handle_rtmp
();
}
m
_nextHandle
=
[
this
]()
{
_nextHandle
=
[
this
]()
{
handle_rtmp
();
};
}
void
RtmpProtocol
::
handle_rtmp
()
{
while
(
!
m
_strRcvBuf
.
empty
())
{
uint8_t
flags
=
m
_strRcvBuf
[
0
];
while
(
!
_strRcvBuf
.
empty
())
{
uint8_t
flags
=
_strRcvBuf
[
0
];
int
iOffset
=
0
;
static
const
size_t
HEADER_LENGTH
[]
=
{
12
,
8
,
4
,
1
};
size_t
iHeaderLen
=
HEADER_LENGTH
[
flags
>>
6
];
m
_iNowChunkID
=
flags
&
0x3f
;
if
(
m
_iNowChunkID
>
10
){
_iNowChunkID
=
flags
&
0x3f
;
if
(
_iNowChunkID
>
10
){
int
i
=
0
;
i
++
;
}
switch
(
m
_iNowChunkID
)
{
switch
(
_iNowChunkID
)
{
case
0
:
{
//0 值表示二字节形式,并且 ID 范围 64 - 319
//(第二个字节 + 64)。
if
(
m
_strRcvBuf
.
size
()
<
2
)
{
if
(
_strRcvBuf
.
size
()
<
2
)
{
//need more data
return
;
}
m_iNowChunkID
=
64
+
(
uint8_t
)
(
m
_strRcvBuf
[
1
]);
_iNowChunkID
=
64
+
(
uint8_t
)
(
_strRcvBuf
[
1
]);
iOffset
=
1
;
}
break
;
case
1
:
{
//1 值表示三字节形式,并且 ID 范围为 64 - 65599
//((第三个字节) * 256 + 第二个字节 + 64)。
if
(
m
_strRcvBuf
.
size
()
<
3
)
{
if
(
_strRcvBuf
.
size
()
<
3
)
{
//need more data
return
;
}
m_iNowChunkID
=
64
+
((
uint8_t
)
(
m_strRcvBuf
[
2
])
<<
8
)
+
(
uint8_t
)
(
m
_strRcvBuf
[
1
]);
_iNowChunkID
=
64
+
((
uint8_t
)
(
_strRcvBuf
[
2
])
<<
8
)
+
(
uint8_t
)
(
_strRcvBuf
[
1
]);
iOffset
=
2
;
}
break
;
...
...
@@ -529,13 +529,13 @@ void RtmpProtocol::handle_rtmp() {
break
;
}
if
(
m
_strRcvBuf
.
size
()
<
iHeaderLen
+
iOffset
)
{
if
(
_strRcvBuf
.
size
()
<
iHeaderLen
+
iOffset
)
{
//need more data
return
;
}
RtmpHeader
&
header
=
*
((
RtmpHeader
*
)
(
m
_strRcvBuf
.
data
()
+
iOffset
));
auto
&
chunkData
=
m_mapChunkData
[
m
_iNowChunkID
];
chunkData
.
chunkId
=
m
_iNowChunkID
;
RtmpHeader
&
header
=
*
((
RtmpHeader
*
)
(
_strRcvBuf
.
data
()
+
iOffset
));
auto
&
chunkData
=
_mapChunkData
[
_iNowChunkID
];
chunkData
.
chunkId
=
_iNowChunkID
;
switch
(
iHeaderLen
)
{
case
12
:
chunkData
.
hasAbsStamp
=
true
;
...
...
@@ -549,11 +549,11 @@ void RtmpProtocol::handle_rtmp() {
}
if
(
chunkData
.
hasExtStamp
)
{
if
(
m
_strRcvBuf
.
size
()
<
iHeaderLen
+
iOffset
+
4
)
{
if
(
_strRcvBuf
.
size
()
<
iHeaderLen
+
iOffset
+
4
)
{
//need more data
return
;
}
chunkData
.
deltaStamp
=
load_be32
(
m
_strRcvBuf
.
data
()
+
iOffset
+
iHeaderLen
);
chunkData
.
deltaStamp
=
load_be32
(
_strRcvBuf
.
data
()
+
iOffset
+
iHeaderLen
);
iOffset
+=
4
;
}
...
...
@@ -561,18 +561,18 @@ void RtmpProtocol::handle_rtmp() {
throw
std
::
runtime_error
(
"非法的bodySize"
);
}
auto
iMore
=
min
(
m
_iChunkLenIn
,
chunkData
.
bodySize
-
chunkData
.
strBuf
.
size
());
if
(
m
_strRcvBuf
.
size
()
<
iHeaderLen
+
iOffset
+
iMore
)
{
auto
iMore
=
min
(
_iChunkLenIn
,
chunkData
.
bodySize
-
chunkData
.
strBuf
.
size
());
if
(
_strRcvBuf
.
size
()
<
iHeaderLen
+
iOffset
+
iMore
)
{
//need more data
return
;
}
chunkData
.
strBuf
.
append
(
m
_strRcvBuf
,
iHeaderLen
+
iOffset
,
iMore
);
m
_strRcvBuf
.
erase
(
0
,
iHeaderLen
+
iOffset
+
iMore
);
chunkData
.
strBuf
.
append
(
_strRcvBuf
,
iHeaderLen
+
iOffset
,
iMore
);
_strRcvBuf
.
erase
(
0
,
iHeaderLen
+
iOffset
+
iMore
);
if
(
chunkData
.
strBuf
.
size
()
==
chunkData
.
bodySize
)
{
//frame is ready
m
_iNowStreamID
=
chunkData
.
streamId
;
_iNowStreamID
=
chunkData
.
streamId
;
chunkData
.
timeStamp
=
chunkData
.
deltaStamp
+
(
chunkData
.
hasAbsStamp
?
0
:
chunkData
.
timeStamp
);
if
(
chunkData
.
bodySize
){
...
...
@@ -600,8 +600,8 @@ void RtmpProtocol::handle_rtmpChunk(RtmpPacket& chunkData) {
if
(
chunkData
.
strBuf
.
size
()
<
4
)
{
throw
std
::
runtime_error
(
"MSG_SET_CHUNK :Not enough data"
);
}
m
_iChunkLenIn
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
TraceL
<<
"MSG_SET_CHUNK:"
<<
m
_iChunkLenIn
;
_iChunkLenIn
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
TraceL
<<
"MSG_SET_CHUNK:"
<<
_iChunkLenIn
;
}
break
;
case
MSG_USER_CONTROL
:
{
...
...
@@ -668,14 +668,14 @@ void RtmpProtocol::handle_rtmpChunk(RtmpPacket& chunkData) {
break
;
case
MSG_WIN_SIZE
:
{
m
_ui32WinSize
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
TraceL
<<
"MSG_WIN_SIZE:"
<<
m
_ui32WinSize
;
_ui32WinSize
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
TraceL
<<
"MSG_WIN_SIZE:"
<<
_ui32WinSize
;
}
break
;
case
MSG_SET_PEER_BW
:
{
m
_ui32Bandwidth
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
m
_ui8LimitType
=
chunkData
.
strBuf
[
4
];
TraceL
<<
"MSG_SET_PEER_BW:"
<<
m
_ui32WinSize
;
_ui32Bandwidth
=
load_be32
(
&
chunkData
.
strBuf
[
0
]);
_ui8LimitType
=
chunkData
.
strBuf
[
4
];
TraceL
<<
"MSG_SET_PEER_BW:"
<<
_ui32WinSize
;
}
break
;
case
MSG_AGGREGATE
:
...
...
src/Rtmp/RtmpProtocol.h
查看文件 @
39baaebc
...
...
@@ -57,7 +57,7 @@ protected:
virtual
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
=
0
;
virtual
void
onRtmpChunk
(
RtmpPacket
&
chunkData
)
=
0
;
virtual
void
onStreamBegin
(
uint32_t
ui32StreamId
){
m
_ui32StreamId
=
ui32StreamId
;
_ui32StreamId
=
ui32StreamId
;
}
virtual
void
onStreamEof
(
uint32_t
ui32StreamId
){};
virtual
void
onStreamDry
(
uint32_t
ui32StreamId
){};
...
...
@@ -77,14 +77,14 @@ protected:
void
sendResponse
(
int
iType
,
const
string
&
str
);
void
sendRtmp
(
uint8_t
ui8Type
,
uint32_t
ui32StreamId
,
const
std
::
string
&
strBuf
,
uint32_t
ui32TimeStamp
,
int
iChunkID
);
protected
:
int
m
_iReqID
=
0
;
uint32_t
m
_ui32StreamId
=
STREAM_CONTROL
;
int
m
_iNowStreamID
=
0
;
int
m
_iNowChunkID
=
0
;
bool
m
_bDataStarted
=
false
;
int
_iReqID
=
0
;
uint32_t
_ui32StreamId
=
STREAM_CONTROL
;
int
_iNowStreamID
=
0
;
int
_iNowChunkID
=
0
;
bool
_bDataStarted
=
false
;
inline
BufferRaw
::
Ptr
obtainBuffer
();
inline
BufferRaw
::
Ptr
obtainBuffer
(
const
void
*
data
,
int
len
);
//ResourcePool<BufferRaw,MAX_SEND_PKT>
m
_bufferPool;
//ResourcePool<BufferRaw,MAX_SEND_PKT> _bufferPool;
private:
void
handle_S0S1S2
(
const
function
<
void
()
>
&
cb
);
void
handle_C0C1
();
...
...
@@ -103,20 +103,20 @@ private:
private
:
////////////ChunkSize////////////
size_t
m
_iChunkLenIn
=
DEFAULT_CHUNK_LEN
;
size_t
m
_iChunkLenOut
=
DEFAULT_CHUNK_LEN
;
size_t
_iChunkLenIn
=
DEFAULT_CHUNK_LEN
;
size_t
_iChunkLenOut
=
DEFAULT_CHUNK_LEN
;
////////////Acknowledgement////////////
uint32_t
m
_ui32ByteSent
=
0
;
uint32_t
m
_ui32LastSent
=
0
;
uint32_t
m
_ui32WinSize
=
0
;
uint32_t
_ui32ByteSent
=
0
;
uint32_t
_ui32LastSent
=
0
;
uint32_t
_ui32WinSize
=
0
;
///////////PeerBandwidth///////////
uint32_t
m
_ui32Bandwidth
=
2500000
;
uint8_t
m
_ui8LimitType
=
2
;
uint32_t
_ui32Bandwidth
=
2500000
;
uint8_t
_ui8LimitType
=
2
;
////////////Chunk////////////
unordered_map
<
int
,
RtmpPacket
>
m
_mapChunkData
;
unordered_map
<
int
,
RtmpPacket
>
_mapChunkData
;
//////////Rtmp parser//////////
string
m
_strRcvBuf
;
function
<
void
()
>
m
_nextHandle
;
string
_strRcvBuf
;
function
<
void
()
>
_nextHandle
;
};
}
/* namespace Rtmp */
...
...
src/Rtmp/RtmpPusher.cpp
查看文件 @
39baaebc
...
...
@@ -56,7 +56,7 @@ void RtmpPusher::init(const RtmpMediaSource::Ptr &src){
g_mapCmd
.
emplace
(
"_result"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"onStatus"
,
&
RtmpPusher
::
onCmd_onStatus
);
},
[]()
{});
m
_pMediaSrc
=
src
;
_pMediaSrc
=
src
;
}
RtmpPusher
::~
RtmpPusher
()
{
...
...
@@ -65,18 +65,18 @@ RtmpPusher::~RtmpPusher() {
}
void
RtmpPusher
::
teardown
()
{
if
(
alive
())
{
m
_strApp
.
clear
();
m
_strStream
.
clear
();
m
_strTcUrl
.
clear
();
_strApp
.
clear
();
_strStream
.
clear
();
_strTcUrl
.
clear
();
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnResultCB
);
m
_mapOnResultCB
.
clear
();
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
_mapOnResultCB
.
clear
();
}
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnStatusCB
);
m
_dqOnStatusCB
.
clear
();
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnStatusCB
);
_dqOnStatusCB
.
clear
();
}
m
_pPublishTimer
.
reset
();
_pPublishTimer
.
reset
();
reset
();
shutdown
();
}
...
...
@@ -85,15 +85,15 @@ void RtmpPusher::teardown() {
void
RtmpPusher
::
publish
(
const
char
*
strUrl
)
{
teardown
();
string
strHost
=
FindField
(
strUrl
,
"://"
,
"/"
);
m
_strApp
=
FindField
(
strUrl
,
(
strHost
+
"/"
).
data
(),
"/"
);
m_strStream
=
FindField
(
strUrl
,
(
strHost
+
"/"
+
m
_strApp
+
"/"
).
data
(),
NULL
);
m_strTcUrl
=
string
(
"rtmp://"
)
+
strHost
+
"/"
+
m
_strApp
;
_strApp
=
FindField
(
strUrl
,
(
strHost
+
"/"
).
data
(),
"/"
);
_strStream
=
FindField
(
strUrl
,
(
strHost
+
"/"
+
_strApp
+
"/"
).
data
(),
NULL
);
_strTcUrl
=
string
(
"rtmp://"
)
+
strHost
+
"/"
+
_strApp
;
if
(
!
m_strApp
.
size
()
||
!
m
_strStream
.
size
())
{
if
(
!
_strApp
.
size
()
||
!
_strStream
.
size
())
{
onPublishResult
(
SockException
(
Err_other
,
"rtmp url非法"
));
return
;
}
DebugL
<<
strHost
<<
" "
<<
m_strApp
<<
" "
<<
m
_strStream
;
DebugL
<<
strHost
<<
" "
<<
_strApp
<<
" "
<<
_strStream
;
auto
iPort
=
atoi
(
FindField
(
strHost
.
c_str
(),
":"
,
NULL
).
c_str
());
if
(
iPort
<=
0
)
{
...
...
@@ -115,7 +115,7 @@ void RtmpPusher::onConnect(const SockException &err){
return
;
}
weak_ptr
<
RtmpPusher
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
m
_pPublishTimer
.
reset
(
new
Timer
(
10
,
[
weakSelf
]()
{
_pPublishTimer
.
reset
(
new
Timer
(
10
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
...
...
@@ -147,10 +147,10 @@ void RtmpPusher::onRecv(const Buffer::Ptr &pBuf){
inline
void
RtmpPusher
::
send_connect
()
{
AMFValue
obj
(
AMF_OBJECT
);
obj
.
set
(
"app"
,
m
_strApp
);
obj
.
set
(
"app"
,
_strApp
);
obj
.
set
(
"type"
,
"nonprivate"
);
obj
.
set
(
"tcUrl"
,
m
_strTcUrl
);
obj
.
set
(
"swfUrl"
,
m
_strTcUrl
);
obj
.
set
(
"tcUrl"
,
_strTcUrl
);
obj
.
set
(
"swfUrl"
,
_strTcUrl
);
sendInvoke
(
"connect"
,
obj
);
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
//TraceL << "connect result";
...
...
@@ -171,13 +171,13 @@ inline void RtmpPusher::send_createStream() {
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
//TraceL << "createStream result";
dec
.
load
<
AMFValue
>
();
m
_ui32StreamId
=
dec
.
load
<
int
>
();
_ui32StreamId
=
dec
.
load
<
int
>
();
send_publish
();
});
}
inline
void
RtmpPusher
::
send_publish
()
{
AMFEncoder
enc
;
enc
<<
"publish"
<<
++
m_iReqID
<<
nullptr
<<
m_strStream
<<
m
_strApp
;
enc
<<
"publish"
<<
++
_iReqID
<<
nullptr
<<
_strStream
<<
_strApp
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
addOnStatusCB
([
this
](
AMFValue
&
val
)
{
...
...
@@ -192,7 +192,7 @@ inline void RtmpPusher::send_publish() {
}
inline
void
RtmpPusher
::
send_metaData
(){
auto
src
=
m
_pMediaSrc
.
lock
();
auto
src
=
_pMediaSrc
.
lock
();
if
(
!
src
)
{
throw
std
::
runtime_error
(
"the media source was released"
);
}
...
...
@@ -202,19 +202,19 @@ inline void RtmpPusher::send_metaData(){
sendRequest
(
MSG_DATA
,
enc
.
data
());
src
->
getConfigFrame
([
&
](
const
RtmpPacket
::
Ptr
&
pkt
){
sendRtmp
(
pkt
->
typeId
,
m
_ui32StreamId
,
pkt
->
strBuf
,
pkt
->
timeStamp
,
pkt
->
chunkId
);
sendRtmp
(
pkt
->
typeId
,
_ui32StreamId
,
pkt
->
strBuf
,
pkt
->
timeStamp
,
pkt
->
chunkId
);
});
m
_pRtmpReader
=
src
->
getRing
()
->
attach
();
_pRtmpReader
=
src
->
getRing
()
->
attach
();
weak_ptr
<
RtmpPusher
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
m
_pRtmpReader
->
setReadCB
([
weakSelf
](
const
RtmpPacket
::
Ptr
&
pkt
){
_pRtmpReader
->
setReadCB
([
weakSelf
](
const
RtmpPacket
::
Ptr
&
pkt
){
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
}
strongSelf
->
sendRtmp
(
pkt
->
typeId
,
strongSelf
->
m
_ui32StreamId
,
pkt
->
strBuf
,
pkt
->
timeStamp
,
pkt
->
chunkId
);
strongSelf
->
sendRtmp
(
pkt
->
typeId
,
strongSelf
->
_ui32StreamId
,
pkt
->
strBuf
,
pkt
->
timeStamp
,
pkt
->
chunkId
);
});
m
_pRtmpReader
->
setDetachCB
([
weakSelf
](){
_pRtmpReader
->
setDetachCB
([
weakSelf
](){
auto
strongSelf
=
weakSelf
.
lock
();
if
(
strongSelf
){
strongSelf
->
onShutdown
(
SockException
(
Err_other
,
"媒体源被释放"
));
...
...
@@ -228,11 +228,11 @@ inline void RtmpPusher::send_metaData(){
}
void
RtmpPusher
::
onCmd_result
(
AMFDecoder
&
dec
){
auto
iReqId
=
dec
.
load
<
int
>
();
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnResultCB
);
auto
it
=
m
_mapOnResultCB
.
find
(
iReqId
);
if
(
it
!=
m
_mapOnResultCB
.
end
()){
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
auto
it
=
_mapOnResultCB
.
find
(
iReqId
);
if
(
it
!=
_mapOnResultCB
.
end
()){
it
->
second
(
dec
);
m
_mapOnResultCB
.
erase
(
it
);
_mapOnResultCB
.
erase
(
it
);
}
else
{
WarnL
<<
"unhandled _result"
;
}
...
...
@@ -249,10 +249,10 @@ void RtmpPusher::onCmd_onStatus(AMFDecoder &dec) {
throw
std
::
runtime_error
(
"onStatus:the result object was not found"
);
}
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnStatusCB
);
if
(
m
_dqOnStatusCB
.
size
()){
m
_dqOnStatusCB
.
front
()(
val
);
m
_dqOnStatusCB
.
pop_front
();
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnStatusCB
);
if
(
_dqOnStatusCB
.
size
()){
_dqOnStatusCB
.
front
()(
val
);
_dqOnStatusCB
.
pop_front
();
}
else
{
auto
level
=
val
[
"level"
];
auto
code
=
val
[
"code"
].
as_string
();
...
...
src/Rtmp/RtmpPusher.h
查看文件 @
39baaebc
...
...
@@ -46,11 +46,11 @@ public:
void
teardown
();
void
setOnPublished
(
Event
onPublished
)
{
m
_onPublished
=
onPublished
;
_onPublished
=
onPublished
;
}
void
setOnShutdown
(
Event
onShutdown
)
{
m
_onShutdown
=
onShutdown
;
_onShutdown
=
onShutdown
;
}
protected
:
...
...
@@ -67,28 +67,28 @@ protected:
private
:
void
init
(
const
RtmpMediaSource
::
Ptr
&
src
);
void
onShutdown
(
const
SockException
&
ex
)
{
m
_pPublishTimer
.
reset
();
if
(
m
_onShutdown
){
m
_onShutdown
(
ex
);
_pPublishTimer
.
reset
();
if
(
_onShutdown
){
_onShutdown
(
ex
);
}
m
_pRtmpReader
.
reset
();
_pRtmpReader
.
reset
();
}
void
onPublishResult
(
const
SockException
&
ex
)
{
m
_pPublishTimer
.
reset
();
if
(
m
_onPublished
){
m
_onPublished
(
ex
);
_pPublishTimer
.
reset
();
if
(
_onPublished
){
_onPublished
(
ex
);
}
}
template
<
typename
FUN
>
inline
void
addOnResultCB
(
const
FUN
&
fun
)
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnResultCB
);
m_mapOnResultCB
.
emplace
(
m
_iReqID
,
fun
);
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnResultCB
);
_mapOnResultCB
.
emplace
(
_iReqID
,
fun
);
}
template
<
typename
FUN
>
inline
void
addOnStatusCB
(
const
FUN
&
fun
)
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtxOnStatusCB
);
m
_dqOnStatusCB
.
emplace_back
(
fun
);
lock_guard
<
recursive_mutex
>
lck
(
_mtxOnStatusCB
);
_dqOnStatusCB
.
emplace_back
(
fun
);
}
void
onCmd_result
(
AMFDecoder
&
dec
);
...
...
@@ -100,27 +100,27 @@ private:
inline
void
send_publish
();
inline
void
send_metaData
();
string
m
_strApp
;
string
m
_strStream
;
string
m
_strTcUrl
;
string
_strApp
;
string
_strStream
;
string
_strTcUrl
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
m
_mapOnResultCB
;
recursive_mutex
m
_mtxOnResultCB
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
m
_dqOnStatusCB
;
recursive_mutex
m
_mtxOnStatusCB
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
_mapOnResultCB
;
recursive_mutex
_mtxOnResultCB
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
_dqOnStatusCB
;
recursive_mutex
_mtxOnStatusCB
;
typedef
void
(
RtmpPusher
::*
rtmpCMDHandle
)(
AMFDecoder
&
dec
);
static
unordered_map
<
string
,
rtmpCMDHandle
>
g_mapCmd
;
//超时功能实现
std
::
shared_ptr
<
Timer
>
m
_pPublishTimer
;
std
::
shared_ptr
<
Timer
>
_pPublishTimer
;
//源
std
::
weak_ptr
<
RtmpMediaSource
>
m
_pMediaSrc
;
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
m
_pRtmpReader
;
std
::
weak_ptr
<
RtmpMediaSource
>
_pMediaSrc
;
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_pRtmpReader
;
//事件监听
Event
m
_onShutdown
;
Event
m
_onPublished
;
Event
_onShutdown
;
Event
_onPublished
;
};
}
/* namespace Rtmp */
...
...
src/Rtmp/RtmpSession.cpp
查看文件 @
39baaebc
...
...
@@ -45,9 +45,9 @@ RtmpSession::RtmpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::P
RtmpSession
::~
RtmpSession
()
{
DebugL
<<
get_peer_ip
();
if
(
m
_delayTask
){
m
_delayTask
();
m
_delayTask
=
nullptr
;
if
(
_delayTask
){
_delayTask
();
_delayTask
=
nullptr
;
}
}
...
...
@@ -57,41 +57,41 @@ void RtmpSession::onError(const SockException& err) {
//流量统计事件广播
GET_CONFIG_AND_REGISTER
(
uint32_t
,
iFlowThreshold
,
Broadcast
::
kFlowThreshold
);
if
(
m
_ui64TotalBytes
>
iFlowThreshold
*
1024
){
if
(
_ui64TotalBytes
>
iFlowThreshold
*
1024
){
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastFlowReport
,
m
_mediaInfo
,
m
_ui64TotalBytes
,
m
_ticker
.
createdTime
()
/
1000
,
_mediaInfo
,
_ui64TotalBytes
,
_ticker
.
createdTime
()
/
1000
,
*
this
);
}
}
void
RtmpSession
::
onManager
()
{
if
(
m
_ticker
.
createdTime
()
>
15
*
1000
)
{
if
(
!
m_pRingReader
&&
!
m
_pPublisherSrc
)
{
if
(
_ticker
.
createdTime
()
>
15
*
1000
)
{
if
(
!
_pRingReader
&&
!
_pPublisherSrc
)
{
WarnL
<<
"非法链接:"
<<
get_peer_ip
();
shutdown
();
}
}
if
(
m
_pPublisherSrc
)
{
if
(
_pPublisherSrc
)
{
//publisher
if
(
m
_ticker
.
elapsedTime
()
>
15
*
1000
)
{
if
(
_ticker
.
elapsedTime
()
>
15
*
1000
)
{
WarnL
<<
"数据接收超时:"
<<
get_peer_ip
();
shutdown
();
}
}
if
(
m
_delayTask
){
if
(
time
(
NULL
)
>
m
_iTaskTimeLine
){
m
_delayTask
();
m
_delayTask
=
nullptr
;
if
(
_delayTask
){
if
(
time
(
NULL
)
>
_iTaskTimeLine
){
_delayTask
();
_delayTask
=
nullptr
;
}
}
}
void
RtmpSession
::
onRecv
(
const
Buffer
::
Ptr
&
pBuf
)
{
m
_ticker
.
resetTime
();
_ticker
.
resetTime
();
try
{
m
_ui64TotalBytes
+=
pBuf
->
size
();
_ui64TotalBytes
+=
pBuf
->
size
();
onParseRtmp
(
pBuf
->
data
(),
pBuf
->
size
());
}
catch
(
exception
&
e
)
{
WarnL
<<
e
.
what
();
...
...
@@ -113,11 +113,11 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
///////////set peerBandwidth////////////////
sendPeerBandwidth
(
5000000
);
m_mediaInfo
.
m
_app
=
params
[
"app"
].
as_string
();
m
_strTcUrl
=
params
[
"tcUrl"
].
as_string
();
if
(
m
_strTcUrl
.
empty
()){
_mediaInfo
.
_app
=
params
[
"app"
].
as_string
();
_strTcUrl
=
params
[
"tcUrl"
].
as_string
();
if
(
_strTcUrl
.
empty
()){
//defaultVhost:默认vhost
m_strTcUrl
=
string
(
RTMP_SCHEMA
)
+
"://"
+
DEFAULT_VHOST
+
"/"
+
m_mediaInfo
.
m
_app
;
_strTcUrl
=
string
(
RTMP_SCHEMA
)
+
"://"
+
DEFAULT_VHOST
+
"/"
+
_mediaInfo
.
_app
;
}
bool
ok
=
true
;
//(app == APP_NAME);
AMFValue
version
(
AMF_OBJECT
);
...
...
@@ -130,7 +130,7 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
status
.
set
(
"objectEncoding"
,
amfVer
);
sendReply
(
ok
?
"_result"
:
"_error"
,
version
,
status
);
if
(
!
ok
)
{
throw
std
::
runtime_error
(
"Unsupported application: "
+
m_mediaInfo
.
m
_app
);
throw
std
::
runtime_error
(
"Unsupported application: "
+
_mediaInfo
.
_app
);
}
AMFEncoder
invoke
;
...
...
@@ -148,16 +148,16 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
DebugL
<<
"publish 回复时间:"
<<
pTicker
->
elapsedTime
()
<<
"ms"
;
}));
dec
.
load
<
AMFValue
>
();
/* NULL */
m_mediaInfo
.
parse
(
m
_strTcUrl
+
"/"
+
dec
.
load
<
std
::
string
>
());
_mediaInfo
.
parse
(
_strTcUrl
+
"/"
+
dec
.
load
<
std
::
string
>
());
auto
onRes
=
[
this
,
pToken
](
const
string
&
err
){
auto
src
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
MediaSource
::
find
(
RTMP_SCHEMA
,
m_mediaInfo
.
m
_vhost
,
m_mediaInfo
.
m
_app
,
m_mediaInfo
.
m
_streamid
,
_mediaInfo
.
_vhost
,
_mediaInfo
.
_app
,
_mediaInfo
.
_streamid
,
false
));
bool
authSuccess
=
err
.
empty
();
bool
ok
=
(
!
src
&&
!
m
_pPublisherSrc
&&
authSuccess
);
bool
ok
=
(
!
src
&&
!
_pPublisherSrc
&&
authSuccess
);
AMFValue
status
(
AMF_OBJECT
);
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"code"
,
ok
?
"NetStream.Publish.Start"
:
(
authSuccess
?
"NetStream.Publish.BadName"
:
"NetStream.Publish.BadAuth"
));
...
...
@@ -167,14 +167,14 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
if
(
!
ok
)
{
WarnL
<<
"onPublish:"
<<
(
authSuccess
?
"Already publishing:"
:
err
.
data
())
<<
" "
<<
m_mediaInfo
.
m
_vhost
<<
" "
<<
m_mediaInfo
.
m
_app
<<
" "
<<
m_mediaInfo
.
m
_streamid
<<
endl
;
<<
_mediaInfo
.
_vhost
<<
" "
<<
_mediaInfo
.
_app
<<
" "
<<
_mediaInfo
.
_streamid
<<
endl
;
shutdown
();
return
;
}
m_pPublisherSrc
.
reset
(
new
RtmpToRtspMediaSource
(
m_mediaInfo
.
m_vhost
,
m_mediaInfo
.
m_app
,
m_mediaInfo
.
m
_streamid
));
m
_pPublisherSrc
->
setListener
(
dynamic_pointer_cast
<
MediaSourceEvent
>
(
shared_from_this
()));
_pPublisherSrc
.
reset
(
new
RtmpToRtspMediaSource
(
_mediaInfo
.
_vhost
,
_mediaInfo
.
_app
,
_mediaInfo
.
_streamid
));
_pPublisherSrc
->
setListener
(
dynamic_pointer_cast
<
MediaSourceEvent
>
(
shared_from_this
()));
};
weak_ptr
<
RtmpSession
>
weakSelf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
...
...
@@ -192,7 +192,7 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
});
};
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Config
::
Broadcast
::
kBroadcastRtmpPublish
,
m
_mediaInfo
,
_mediaInfo
,
invoker
,
*
this
);
if
(
!
flag
){
...
...
@@ -213,9 +213,9 @@ void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) {
void
RtmpSession
::
doPlayResponse
(
const
string
&
err
,
bool
tryDelay
,
const
std
::
shared_ptr
<
onceToken
>
&
pToken
)
{
//获取流对象
auto
src
=
dynamic_pointer_cast
<
RtmpMediaSource
>
(
MediaSource
::
find
(
RTMP_SCHEMA
,
m_mediaInfo
.
m
_vhost
,
m_mediaInfo
.
m
_app
,
m_mediaInfo
.
m
_streamid
,
_mediaInfo
.
_vhost
,
_mediaInfo
.
_app
,
_mediaInfo
.
_streamid
,
true
));
//是否鉴权成功
bool
authSuccess
=
err
.
empty
();
...
...
@@ -223,17 +223,17 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
//校验成功,但是流不存在而导致的不能播放
//所以我们注册rtmp注册事件,等rtmp推流端推流成功后再告知播放器开始播放
auto
task_id
=
this
;
auto
media_info
=
m
_mediaInfo
;
auto
media_info
=
_mediaInfo
;
weak_ptr
<
RtmpSession
>
weakSelf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
NoticeCenter
::
Instance
().
addListener
(
task_id
,
Broadcast
::
kBroadcastMediaChanged
,
[
task_id
,
weakSelf
,
media_info
,
pToken
](
BroadcastMediaChangedArgs
){
if
(
bRegist
&&
schema
==
media_info
.
m
_schema
&&
vhost
==
media_info
.
m
_vhost
&&
app
==
media_info
.
m
_app
&&
stream
==
media_info
.
m
_streamid
){
schema
==
media_info
.
_schema
&&
vhost
==
media_info
.
_vhost
&&
app
==
media_info
.
_app
&&
stream
==
media_info
.
_streamid
){
//播发器请求的rtmp流终于注册上了
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
...
...
@@ -249,7 +249,7 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
if
(
!
strongSelf
)
{
return
;
}
DebugL
<<
"收到rtmp注册事件,回复播放器:"
<<
media_info
.
m_schema
<<
"/"
<<
media_info
.
m_vhost
<<
"/"
<<
media_info
.
m_app
<<
"/"
<<
media_info
.
m
_streamid
;
DebugL
<<
"收到rtmp注册事件,回复播放器:"
<<
media_info
.
_schema
<<
"/"
<<
media_info
.
_vhost
<<
"/"
<<
media_info
.
_app
<<
"/"
<<
media_info
.
_streamid
;
//回复播放器
strongSelf
->
doPlayResponse
(
""
,
false
,
pToken
);
//取消延时任务,防止多次回复
...
...
@@ -291,15 +291,15 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
status
.
set
(
"level"
,
ok
?
"status"
:
"error"
);
status
.
set
(
"code"
,
ok
?
"NetStream.Play.Reset"
:
(
authSuccess
?
"NetStream.Play.StreamNotFound"
:
"NetStream.Play.BadAuth"
));
status
.
set
(
"description"
,
ok
?
"Resetting and playing."
:
(
authSuccess
?
"No such stream."
:
err
.
data
()));
status
.
set
(
"details"
,
m_mediaInfo
.
m
_streamid
);
status
.
set
(
"details"
,
_mediaInfo
.
_streamid
);
status
.
set
(
"clientid"
,
"0"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
if
(
!
ok
)
{
WarnL
<<
"onPlayed:"
<<
(
authSuccess
?
"No such stream:"
:
err
.
data
())
<<
" "
<<
m_mediaInfo
.
m
_vhost
<<
" "
<<
m_mediaInfo
.
m
_app
<<
" "
<<
m_mediaInfo
.
m
_streamid
<<
_mediaInfo
.
_vhost
<<
" "
<<
_mediaInfo
.
_app
<<
" "
<<
_mediaInfo
.
_streamid
<<
endl
;
shutdown
();
return
;
...
...
@@ -310,7 +310,7 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
status
.
set
(
"level"
,
"status"
);
status
.
set
(
"code"
,
"NetStream.Play.Start"
);
status
.
set
(
"description"
,
"Started playing."
);
status
.
set
(
"details"
,
m_mediaInfo
.
m
_streamid
);
status
.
set
(
"details"
,
_mediaInfo
.
_streamid
);
status
.
set
(
"clientid"
,
"0"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
...
...
@@ -331,7 +331,7 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
status
.
set
(
"level"
,
"status"
);
status
.
set
(
"code"
,
"NetStream.Play.PublishNotify"
);
status
.
set
(
"description"
,
"Now published."
);
status
.
set
(
"details"
,
m_mediaInfo
.
m
_streamid
);
status
.
set
(
"details"
,
_mediaInfo
.
_streamid
);
status
.
set
(
"clientid"
,
"0"
);
sendReply
(
"onStatus"
,
nullptr
,
status
);
...
...
@@ -345,10 +345,10 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
onSendMedia
(
pkt
);
});
m
_pRingReader
=
src
->
getRing
()
->
attach
();
_pRingReader
=
src
->
getRing
()
->
attach
();
weak_ptr
<
RtmpSession
>
weakSelf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
SockUtil
::
setNoDelay
(
_sock
->
rawFD
(),
false
);
m
_pRingReader
->
setReadCB
([
weakSelf
](
const
RtmpPacket
::
Ptr
&
pkt
)
{
_pRingReader
->
setReadCB
([
weakSelf
](
const
RtmpPacket
::
Ptr
&
pkt
)
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
...
...
@@ -361,14 +361,14 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
strongSelf
->
onSendMedia
(
pkt
);
});
});
m
_pRingReader
->
setDetachCB
([
weakSelf
]()
{
_pRingReader
->
setDetachCB
([
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
}
strongSelf
->
safeShutdown
();
});
m
_pPlayerSrc
=
src
;
_pPlayerSrc
=
src
;
if
(
src
->
getRing
()
->
readerCount
()
==
1
)
{
src
->
seekTo
(
0
);
}
...
...
@@ -397,7 +397,7 @@ void RtmpSession::doPlay(AMFDecoder &dec){
strongSelf
->
doPlayResponse
(
err
,
true
,
pToken
);
});
};
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
m
_mediaInfo
,
invoker
,
*
this
);
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
_mediaInfo
,
invoker
,
*
this
);
if
(
!
flag
){
//该事件无人监听,默认不鉴权
doPlayResponse
(
""
,
true
,
pToken
);
...
...
@@ -408,7 +408,7 @@ void RtmpSession::onCmd_play2(AMFDecoder &dec) {
}
void
RtmpSession
::
onCmd_play
(
AMFDecoder
&
dec
)
{
dec
.
load
<
AMFValue
>
();
/* NULL */
m_mediaInfo
.
parse
(
m
_strTcUrl
+
"/"
+
dec
.
load
<
std
::
string
>
());
_mediaInfo
.
parse
(
_strTcUrl
+
"/"
+
dec
.
load
<
std
::
string
>
());
doPlay
(
dec
);
}
...
...
@@ -424,14 +424,14 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
//streamBegin
sendUserControl
(
paused
?
CONTROL_STREAM_EOF
:
CONTROL_STREAM_BEGIN
,
STREAM_MEDIA
);
if
(
!
m
_pRingReader
)
{
if
(
!
_pRingReader
)
{
throw
std
::
runtime_error
(
"Rtmp not started yet!"
);
}
if
(
paused
)
{
m
_pRingReader
->
setReadCB
(
nullptr
);
_pRingReader
->
setReadCB
(
nullptr
);
}
else
{
weak_ptr
<
RtmpSession
>
weakSelf
=
dynamic_pointer_cast
<
RtmpSession
>
(
shared_from_this
());
m
_pRingReader
->
setReadCB
([
weakSelf
](
const
RtmpPacket
::
Ptr
&
pkt
)
{
_pRingReader
->
setReadCB
([
weakSelf
](
const
RtmpPacket
::
Ptr
&
pkt
)
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
...
...
@@ -448,14 +448,14 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
}
void
RtmpSession
::
setMetaData
(
AMFDecoder
&
dec
)
{
if
(
!
m
_pPublisherSrc
)
{
if
(
!
_pPublisherSrc
)
{
throw
std
::
runtime_error
(
"not a publisher"
);
}
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
if
(
type
!=
"onMetaData"
)
{
throw
std
::
runtime_error
(
"can only set metadata"
);
}
m
_pPublisherSrc
->
onGetMetaData
(
dec
.
load
<
AMFValue
>
());
_pPublisherSrc
->
onGetMetaData
(
dec
.
load
<
AMFValue
>
());
}
void
RtmpSession
::
onProcessCmd
(
AMFDecoder
&
dec
)
{
...
...
@@ -477,7 +477,7 @@ void RtmpSession::onProcessCmd(AMFDecoder &dec) {
TraceL
<<
"can not support cmd:"
<<
method
;
return
;
}
m
_dNowReqID
=
dec
.
load
<
double
>
();
_dNowReqID
=
dec
.
load
<
double
>
();
auto
fun
=
it
->
second
;
(
this
->*
fun
)(
dec
);
}
...
...
@@ -503,14 +503,14 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) {
break
;
case
MSG_AUDIO
:
case
MSG_VIDEO
:
{
if
(
!
m
_pPublisherSrc
)
{
if
(
!
_pPublisherSrc
)
{
throw
std
::
runtime_error
(
"Not a rtmp publisher!"
);
}
GET_CONFIG_AND_REGISTER
(
bool
,
rtmp_modify_stamp
,
Config
::
Rtmp
::
kModifyStamp
);
if
(
rtmp_modify_stamp
){
chunkData
.
timeStamp
=
m
_stampTicker
[
chunkData
.
typeId
%
2
].
elapsedTime
();
chunkData
.
timeStamp
=
_stampTicker
[
chunkData
.
typeId
%
2
].
elapsedTime
();
}
m
_pPublisherSrc
->
onGetMedia
(
std
::
make_shared
<
RtmpPacket
>
(
chunkData
));
_pPublisherSrc
->
onGetMedia
(
std
::
make_shared
<
RtmpPacket
>
(
chunkData
));
}
break
;
default
:
...
...
@@ -523,7 +523,7 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
dec
.
load
<
AMFValue
>
();
/* NULL */
auto
milliSeconds
=
dec
.
load
<
AMFValue
>
().
as_number
();
InfoL
<<
"rtmp seekTo:"
<<
milliSeconds
/
1000.0
;
auto
stongSrc
=
m
_pPlayerSrc
.
lock
();
auto
stongSrc
=
_pPlayerSrc
.
lock
();
if
(
stongSrc
)
{
stongSrc
->
seekTo
(
milliSeconds
);
}
...
...
@@ -537,7 +537,7 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
void
RtmpSession
::
onSendMedia
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
auto
modifiedStamp
=
pkt
->
timeStamp
;
auto
&
firstStamp
=
m
_aui32FirstStamp
[
pkt
->
typeId
%
2
];
auto
&
firstStamp
=
_aui32FirstStamp
[
pkt
->
typeId
%
2
];
if
(
!
firstStamp
){
firstStamp
=
modifiedStamp
;
}
...
...
@@ -546,22 +546,22 @@ void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) {
modifiedStamp
-=
firstStamp
;
}
else
{
//发生回环,重新计算时间戳增量
CLEAR_ARR
(
m
_aui32FirstStamp
);
CLEAR_ARR
(
_aui32FirstStamp
);
modifiedStamp
=
0
;
}
sendRtmp
(
pkt
->
typeId
,
pkt
->
streamId
,
pkt
->
strBuf
,
modifiedStamp
,
pkt
->
chunkId
);
}
void
RtmpSession
::
doDelay
(
int
delaySec
,
const
std
::
function
<
void
()
>
&
fun
)
{
if
(
m
_delayTask
){
m
_delayTask
();
if
(
_delayTask
){
_delayTask
();
}
m
_delayTask
=
fun
;
m
_iTaskTimeLine
=
time
(
NULL
)
+
delaySec
;
_delayTask
=
fun
;
_iTaskTimeLine
=
time
(
NULL
)
+
delaySec
;
}
void
RtmpSession
::
cancelDelyaTask
(){
m
_delayTask
=
nullptr
;
_delayTask
=
nullptr
;
}
...
...
src/Rtmp/RtmpSession.h
查看文件 @
39baaebc
...
...
@@ -70,7 +70,7 @@ private:
void
onSendMedia
(
const
RtmpPacket
::
Ptr
&
pkt
);
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
override
{
m
_ui64TotalBytes
+=
buffer
->
size
();
_ui64TotalBytes
+=
buffer
->
size
();
send
(
buffer
);
}
void
onRtmpChunk
(
RtmpPacket
&
chunkData
)
override
;
...
...
@@ -78,12 +78,12 @@ private:
template
<
typename
first
,
typename
second
>
inline
void
sendReply
(
const
char
*
str
,
const
first
&
reply
,
const
second
&
status
)
{
AMFEncoder
invoke
;
invoke
<<
str
<<
m
_dNowReqID
<<
reply
<<
status
;
invoke
<<
str
<<
_dNowReqID
<<
reply
<<
status
;
sendResponse
(
MSG_CMD
,
invoke
.
data
());
}
bool
shutDown
()
override
{
InfoL
<<
"kick out:"
<<
m_mediaInfo
.
m_vhost
<<
" "
<<
m_mediaInfo
.
m_app
<<
" "
<<
m_mediaInfo
.
m
_streamid
;
InfoL
<<
"kick out:"
<<
_mediaInfo
.
_vhost
<<
" "
<<
_mediaInfo
.
_app
<<
" "
<<
_mediaInfo
.
_streamid
;
safeShutdown
();
return
true
;
}
...
...
@@ -91,19 +91,19 @@ private:
void
doDelay
(
int
delaySec
,
const
std
::
function
<
void
()
>
&
fun
);
void
cancelDelyaTask
();
private
:
std
::
string
m
_strTcUrl
;
MediaInfo
m
_mediaInfo
;
double
m
_dNowReqID
=
0
;
Ticker
m
_ticker
;
//数据接收时间
SmoothTicker
m
_stampTicker
[
2
];
//时间戳生产器
RingBuffer
<
RtmpPacket
::
Ptr
>::
RingReader
::
Ptr
m
_pRingReader
;
std
::
shared_ptr
<
RtmpMediaSource
>
m
_pPublisherSrc
;
std
::
weak_ptr
<
RtmpMediaSource
>
m
_pPlayerSrc
;
uint32_t
m
_aui32FirstStamp
[
2
]
=
{
0
};
std
::
string
_strTcUrl
;
MediaInfo
_mediaInfo
;
double
_dNowReqID
=
0
;
Ticker
_ticker
;
//数据接收时间
SmoothTicker
_stampTicker
[
2
];
//时间戳生产器
RingBuffer
<
RtmpPacket
::
Ptr
>::
RingReader
::
Ptr
_pRingReader
;
std
::
shared_ptr
<
RtmpMediaSource
>
_pPublisherSrc
;
std
::
weak_ptr
<
RtmpMediaSource
>
_pPlayerSrc
;
uint32_t
_aui32FirstStamp
[
2
]
=
{
0
};
//消耗的总流量
uint64_t
m
_ui64TotalBytes
=
0
;
std
::
function
<
void
()
>
m
_delayTask
;
uint32_t
m
_iTaskTimeLine
=
0
;
uint64_t
_ui64TotalBytes
=
0
;
std
::
function
<
void
()
>
_delayTask
;
uint32_t
_iTaskTimeLine
=
0
;
};
...
...
src/Rtmp/RtmpToRtspMediaSource.cpp
查看文件 @
39baaebc
...
...
@@ -41,27 +41,27 @@ RtmpToRtspMediaSource::RtmpToRtspMediaSource(const string &vhost,
const
string
&
id
,
bool
bEnableHls
,
bool
bEnableMp4
)
:
RtmpMediaSource
(
vhost
,
app
,
id
),
m_bEnableHls
(
bEnableHls
),
m
_bEnableMp4
(
bEnableMp4
)
{
RtmpMediaSource
(
vhost
,
app
,
id
),
_bEnableHls
(
bEnableHls
),
_bEnableMp4
(
bEnableMp4
)
{
}
RtmpToRtspMediaSource
::~
RtmpToRtspMediaSource
()
{}
void
RtmpToRtspMediaSource
::
onGetH264
(
const
H264Frame
&
frame
)
{
if
(
m
_pRecorder
){
m
_pRecorder
->
inputH264
((
char
*
)
frame
.
data
(),
frame
.
size
(),
frame
.
timeStamp
,
frame
.
type
);
if
(
_pRecorder
){
_pRecorder
->
inputH264
((
char
*
)
frame
.
data
(),
frame
.
size
(),
frame
.
timeStamp
,
frame
.
type
);
}
if
(
m
_pRtpMaker_h264
){
m
_pRtpMaker_h264
->
makeRtp
(
frame
.
data
()
+
4
,
frame
.
size
()
-
4
,
frame
.
timeStamp
);
if
(
_pRtpMaker_h264
){
_pRtpMaker_h264
->
makeRtp
(
frame
.
data
()
+
4
,
frame
.
size
()
-
4
,
frame
.
timeStamp
);
}
}
inline
void
RtmpToRtspMediaSource
::
onGetAAC
(
const
AACFrame
&
frame
)
{
if
(
m
_pRecorder
){
m
_pRecorder
->
inputAAC
((
char
*
)
frame
.
buffer
,
frame
.
aac_frame_length
,
frame
.
timeStamp
);
if
(
_pRecorder
){
_pRecorder
->
inputAAC
((
char
*
)
frame
.
buffer
,
frame
.
aac_frame_length
,
frame
.
timeStamp
);
}
if
(
m
_pRtpMaker_aac
)
{
m
_pRtpMaker_aac
->
makeRtp
((
char
*
)
frame
.
buffer
+
7
,
frame
.
aac_frame_length
-
7
,
frame
.
timeStamp
);
if
(
_pRtpMaker_aac
)
{
_pRtpMaker_aac
->
makeRtp
((
char
*
)
frame
.
buffer
+
7
,
frame
.
aac_frame_length
-
7
,
frame
.
timeStamp
);
}
}
...
...
@@ -73,40 +73,40 @@ void RtmpToRtspMediaSource::makeSDP() {
strSDP
+=
"i=ZL Live Stream
\r\n
"
;
strSDP
+=
"c=IN IP4 0.0.0.0
\r\n
"
;
strSDP
+=
"t=0 0
\r\n
"
;
if
(
m
_pParser
->
getDuration
()
<=
0
){
if
(
_pParser
->
getDuration
()
<=
0
){
strSDP
+=
"a=range:npt=0-
\r\n
"
;
}
else
{
strSDP
+=
StrPrinter
<<
"0-"
<<
m
_pParser
->
getDuration
()
<<
"
\r\n
"
<<
endl
;
strSDP
+=
StrPrinter
<<
"0-"
<<
_pParser
->
getDuration
()
<<
"
\r\n
"
<<
endl
;
}
strSDP
+=
"a=control:*
\r\n
"
;
//todo(xzl) 修复此处
// if (
m
_pParser->containVideo()) {
// if (_pParser->containVideo()) {
// uint32_t ssrc0;
// memcpy(&ssrc0, makeRandStr(4, false).data(), 4);
// auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
//
m
_pRtspSrc->onGetRTP(pkt,bKeyPos);
// _pRtspSrc->onGetRTP(pkt,bKeyPos);
// };
//
// GET_CONFIG_AND_REGISTER(uint32_t,videoMtu,Config::Rtp::kVideoMtuSize);
//
m
_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ssrc0,videoMtu));
// _pRtpMaker_h264.reset(new RtpMaker_H264(lam, ssrc0,videoMtu));
//
// char strTemp[100];
// int profile_level_id = 0;
// string strSPS =
m
_pParser->getSps().substr(4);
// string strPPS =
m
_pParser->getPps().substr(4);
// string strSPS =_pParser->getSps().substr(4);
// string strPPS =_pParser->getPps().substr(4);
// if (strSPS.length() >= 4) { // sanity check
// profile_level_id = (strSPS[1] << 16) | (strSPS[2] << 8) | strSPS[3]; // profile_idc|constraint_setN_flag|level_idc
// }
//
// //视频通道
// strSDP += StrPrinter << "m=video 0 RTP/AVP " <<
m
_pRtpMaker_h264->getPlayloadType()
// strSDP += StrPrinter << "m=video 0 RTP/AVP " << _pRtpMaker_h264->getPlayloadType()
// << "\r\n" << endl;
// strSDP += "b=AS:5100\r\n";
// strSDP += StrPrinter << "a=rtpmap:" <<
m
_pRtpMaker_h264->getPlayloadType()
// << " H264/" <<
m
_pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
// strSDP += StrPrinter << "a=fmtp:" <<
m
_pRtpMaker_h264->getPlayloadType()
// strSDP += StrPrinter << "a=rtpmap:" << _pRtpMaker_h264->getPlayloadType()
// << " H264/" << _pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
// strSDP += StrPrinter << "a=fmtp:" << _pRtpMaker_h264->getPlayloadType()
// << " packetization-mode=1;profile-level-id=" << endl;
//
// memset(strTemp, 0, 100);
...
...
@@ -121,41 +121,41 @@ void RtmpToRtspMediaSource::makeSDP() {
// av_base64_encode(strTemp, 100, (uint8_t *) strPPS.data(), strPPS.size());
// strSDP += strTemp;
// strSDP += "\r\n";
// strSDP += StrPrinter << "a=control:trackID=" <<
m
_pRtpMaker_h264->getInterleaved() / 2
// strSDP += StrPrinter << "a=control:trackID=" << _pRtpMaker_h264->getInterleaved() / 2
// << "\r\n" << endl;
// }
//
// if (
m
_pParser->containAudio()) {
// if (_pParser->containAudio()) {
// uint32_t ssrc1;
// memcpy(&ssrc1, makeRandStr(8, false).data() + 4, 4);
// auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
//
m
_pRtspSrc->onGetRTP(pkt,bKeyPos);
// _pRtspSrc->onGetRTP(pkt,bKeyPos);
// };
// GET_CONFIG_AND_REGISTER(uint32_t,audioMtu,Config::Rtp::kAudioMtuSize);
//
m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc1, audioMtu,m
_pParser->getAudioSampleRate()));
//
_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc1, audioMtu,
_pParser->getAudioSampleRate()));
//
// char configStr[32];
// const string & strAacCfg =
m
_pParser->getAudioCfg();
// const string & strAacCfg = _pParser->getAudioCfg();
// snprintf(configStr, sizeof(configStr), "%02X%02x", strAacCfg[0], strAacCfg[1]);
// strSDP += StrPrinter << "m=audio 0 RTP/AVP " <<
m
_pRtpMaker_aac->getPlayloadType()
// strSDP += StrPrinter << "m=audio 0 RTP/AVP " << _pRtpMaker_aac->getPlayloadType()
// << "\r\n" << endl;
// strSDP += "b=AS:96\r\n";
// strSDP += StrPrinter << "a=rtpmap:" <<
m
_pRtpMaker_aac->getPlayloadType()
// << " MPEG4-GENERIC/" <<
m
_pRtpMaker_aac->getSampleRate() << "\r\n"
// strSDP += StrPrinter << "a=rtpmap:" << _pRtpMaker_aac->getPlayloadType()
// << " MPEG4-GENERIC/" << _pRtpMaker_aac->getSampleRate() << "\r\n"
// << endl;
// strSDP += StrPrinter << "a=fmtp:" <<
m
_pRtpMaker_aac->getPlayloadType()
// strSDP += StrPrinter << "a=fmtp:" << _pRtpMaker_aac->getPlayloadType()
// << " streamtype=5;profile-level-id=1;mode=AAC-hbr;"
// << "sizelength=13;indexlength=3;indexdeltalength=3;config="
// << endl;
// strSDP.append(configStr, 4);
// strSDP += "\r\n";
// strSDP += StrPrinter << "a=control:trackID=" <<
m
_pRtpMaker_aac->getInterleaved() / 2
// strSDP += StrPrinter << "a=control:trackID=" << _pRtpMaker_aac->getInterleaved() / 2
// << "\r\n" << endl;
// }
m
_pRtspSrc
.
reset
(
new
RtspMediaSource
(
getVhost
(),
getApp
(),
getId
()));
m_pRtspSrc
->
setListener
(
m
_listener
);
m
_pRtspSrc
->
onGetSDP
(
strSDP
);
_pRtspSrc
.
reset
(
new
RtspMediaSource
(
getVhost
(),
getApp
(),
getId
()));
_pRtspSrc
->
setListener
(
_listener
);
_pRtspSrc
->
onGetSDP
(
strSDP
);
}
...
...
src/Rtmp/RtmpToRtspMediaSource.h
查看文件 @
39baaebc
...
...
@@ -65,12 +65,12 @@ public:
void
onGetMetaData
(
const
AMFValue
&
_metadata
)
override
{
try
{
m
_pParser
.
reset
(
new
RtmpParser
(
_metadata
));
m_pRecorder
.
reset
(
new
MediaRecorder
(
getVhost
(),
getApp
(),
getId
(),
m_pParser
,
m_bEnableHls
,
m
_bEnableMp4
));
_pParser
.
reset
(
new
RtmpParser
(
_metadata
));
_pRecorder
.
reset
(
new
MediaRecorder
(
getVhost
(),
getApp
(),
getId
(),
_pParser
,
_bEnableHls
,
_bEnableMp4
));
//todo(xzl) 修复此处
//
m
_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1));
//
m
_pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1));
// _pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1));
// _pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1));
}
catch
(
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
}
...
...
@@ -78,23 +78,23 @@ public:
}
void
onGetMedia
(
const
RtmpPacket
::
Ptr
&
pkt
)
override
{
if
(
m
_pParser
)
{
if
(
!
m_pRtspSrc
&&
m
_pParser
->
isInited
())
{
if
(
_pParser
)
{
if
(
!
_pRtspSrc
&&
_pParser
->
isInited
())
{
makeSDP
();
}
m
_pParser
->
inputRtmp
(
pkt
);
_pParser
->
inputRtmp
(
pkt
);
}
RtmpMediaSource
::
onGetMedia
(
pkt
);
}
private
:
RtmpParser
::
Ptr
m
_pParser
;
RtspMediaSource
::
Ptr
m
_pRtspSrc
;
RtpMaker_AAC
::
Ptr
m
_pRtpMaker_aac
;
RtpMaker_H264
::
Ptr
m
_pRtpMaker_h264
;
MediaRecorder
::
Ptr
m
_pRecorder
;
bool
m
_bEnableHls
;
bool
m
_bEnableMp4
;
RtmpParser
::
Ptr
_pParser
;
RtspMediaSource
::
Ptr
_pRtspSrc
;
RtpMaker_AAC
::
Ptr
_pRtpMaker_aac
;
RtpMaker_H264
::
Ptr
_pRtpMaker_h264
;
MediaRecorder
::
Ptr
_pRecorder
;
bool
_bEnableHls
;
bool
_bEnableMp4
;
void
onGetH264
(
const
H264Frame
&
frame
);
void
onGetAAC
(
const
AACFrame
&
frame
);
void
makeSDP
();
...
...
src/Rtmp/amf.cpp
查看文件 @
39baaebc
...
...
@@ -36,24 +36,24 @@ using namespace ZL::Network;
/////////////////////AMFValue/////////////////////////////
inline
void
AMFValue
::
destroy
()
{
switch
(
m
_type
)
{
switch
(
_type
)
{
case
AMF_STRING
:
if
(
m
_value
.
string
)
{
delete
m
_value
.
string
;
m
_value
.
string
=
nullptr
;
if
(
_value
.
string
)
{
delete
_value
.
string
;
_value
.
string
=
nullptr
;
}
break
;
case
AMF_OBJECT
:
case
AMF_ECMA_ARRAY
:
if
(
m
_value
.
object
)
{
delete
m
_value
.
object
;
m
_value
.
object
=
nullptr
;
if
(
_value
.
object
)
{
delete
_value
.
object
;
_value
.
object
=
nullptr
;
}
break
;
case
AMF_STRICT_ARRAY
:
if
(
m
_value
.
array
)
{
delete
m
_value
.
array
;
m
_value
.
array
=
nullptr
;
if
(
_value
.
array
)
{
delete
_value
.
array
;
_value
.
array
=
nullptr
;
}
break
;
default
:
...
...
@@ -61,16 +61,16 @@ inline void AMFValue::destroy() {
}
}
inline
void
AMFValue
::
init
()
{
switch
(
m
_type
)
{
switch
(
_type
)
{
case
AMF_OBJECT
:
case
AMF_ECMA_ARRAY
:
m
_value
.
object
=
new
mapType
;
_value
.
object
=
new
mapType
;
break
;
case
AMF_STRING
:
m
_value
.
string
=
new
std
::
string
;
_value
.
string
=
new
std
::
string
;
break
;
case
AMF_STRICT_ARRAY
:
m
_value
.
array
=
new
arrayType
;
_value
.
array
=
new
arrayType
;
break
;
default
:
...
...
@@ -79,7 +79,7 @@ inline void AMFValue::init() {
}
AMFValue
::
AMFValue
(
AMFType
type
)
:
m
_type
(
type
)
{
_type
(
type
)
{
init
();
}
...
...
@@ -89,38 +89,38 @@ AMFValue::~AMFValue() {
}
AMFValue
::
AMFValue
(
const
char
*
s
)
:
m
_type
(
AMF_STRING
)
{
_type
(
AMF_STRING
)
{
init
();
*
m
_value
.
string
=
s
;
*
_value
.
string
=
s
;
}
AMFValue
::
AMFValue
(
const
std
::
string
&
s
)
:
m
_type
(
AMF_STRING
)
{
_type
(
AMF_STRING
)
{
init
();
*
m
_value
.
string
=
s
;
*
_value
.
string
=
s
;
}
AMFValue
::
AMFValue
(
double
n
)
:
m
_type
(
AMF_NUMBER
)
{
_type
(
AMF_NUMBER
)
{
init
();
m
_value
.
number
=
n
;
_value
.
number
=
n
;
}
AMFValue
::
AMFValue
(
int
i
)
:
m
_type
(
AMF_INTEGER
)
{
_type
(
AMF_INTEGER
)
{
init
();
m
_value
.
integer
=
i
;
_value
.
integer
=
i
;
}
AMFValue
::
AMFValue
(
bool
b
)
:
m
_type
(
AMF_BOOLEAN
)
{
_type
(
AMF_BOOLEAN
)
{
init
();
m
_value
.
boolean
=
b
;
_value
.
boolean
=
b
;
}
AMFValue
::
AMFValue
(
const
AMFValue
&
from
)
:
m
_type
(
AMF_NULL
)
{
_type
(
AMF_NULL
)
{
*
this
=
from
;
}
...
...
@@ -134,27 +134,27 @@ AMFValue& AMFValue::operator =(const AMFValue &from) {
}
AMFValue
&
AMFValue
::
operator
=
(
AMFValue
&&
from
)
{
destroy
();
m_type
=
from
.
m
_type
;
_type
=
from
.
_type
;
init
();
switch
(
m
_type
)
{
switch
(
_type
)
{
case
AMF_STRING
:
*
m_value
.
string
=
(
*
from
.
m
_value
.
string
);
*
_value
.
string
=
(
*
from
.
_value
.
string
);
break
;
case
AMF_OBJECT
:
case
AMF_ECMA_ARRAY
:
*
m_value
.
object
=
(
*
from
.
m
_value
.
object
);
*
_value
.
object
=
(
*
from
.
_value
.
object
);
break
;
case
AMF_STRICT_ARRAY
:
*
m_value
.
array
=
(
*
from
.
m
_value
.
array
);
*
_value
.
array
=
(
*
from
.
_value
.
array
);
break
;
case
AMF_NUMBER
:
m_value
.
number
=
from
.
m
_value
.
number
;
_value
.
number
=
from
.
_value
.
number
;
break
;
case
AMF_INTEGER
:
m_value
.
integer
=
from
.
m
_value
.
integer
;
_value
.
integer
=
from
.
_value
.
integer
;
break
;
case
AMF_BOOLEAN
:
m_value
.
boolean
=
from
.
m
_value
.
boolean
;
_value
.
boolean
=
from
.
_value
.
boolean
;
break
;
default
:
break
;
...
...
src/Rtmp/amf.h
查看文件 @
39baaebc
...
...
@@ -61,13 +61,13 @@ public:
~
AMFValue
();
void
clear
()
{
switch
(
m
_type
)
{
switch
(
_type
)
{
case
AMF_STRING
:
m
_value
.
string
->
clear
();
_value
.
string
->
clear
();
break
;
case
AMF_OBJECT
:
case
AMF_ECMA_ARRAY
:
m
_value
.
object
->
clear
();
_value
.
object
->
clear
();
break
;
default:
break
;
...
...
@@ -75,23 +75,23 @@ public:
}
AMFType
type
()
const
{
return
m
_type
;
return
_type
;
}
const
std
::
string
&
as_string
()
const
{
if
(
m
_type
!=
AMF_STRING
){
if
(
_type
!=
AMF_STRING
){
throw
std
::
runtime_error
(
"AMF not a string"
);
}
return
*
m
_value
.
string
;
return
*
_value
.
string
;
}
double
as_number
()
const
{
switch
(
m
_type
)
{
switch
(
_type
)
{
case
AMF_NUMBER
:
return
m
_value
.
number
;
return
_value
.
number
;
case
AMF_INTEGER
:
return
m
_value
.
integer
;
return
_value
.
integer
;
case
AMF_BOOLEAN
:
return
m
_value
.
boolean
;
return
_value
.
boolean
;
break
;
default
:
throw
std
::
runtime_error
(
"AMF not a number"
);
...
...
@@ -99,13 +99,13 @@ public:
}
}
int
as_integer
()
const
{
switch
(
m
_type
)
{
switch
(
_type
)
{
case
AMF_NUMBER
:
return
m
_value
.
number
;
return
_value
.
number
;
case
AMF_INTEGER
:
return
m
_value
.
integer
;
return
_value
.
integer
;
case
AMF_BOOLEAN
:
return
m
_value
.
boolean
;
return
_value
.
boolean
;
break
;
default
:
throw
std
::
runtime_error
(
"AMF not a integer"
);
...
...
@@ -113,13 +113,13 @@ public:
}
}
bool
as_boolean
()
const
{
switch
(
m
_type
)
{
switch
(
_type
)
{
case
AMF_NUMBER
:
return
m
_value
.
number
;
return
_value
.
number
;
case
AMF_INTEGER
:
return
m
_value
.
integer
;
return
_value
.
integer
;
case
AMF_BOOLEAN
:
return
m
_value
.
boolean
;
return
_value
.
boolean
;
break
;
default
:
throw
std
::
runtime_error
(
"AMF not a boolean"
);
...
...
@@ -128,11 +128,11 @@ public:
}
const
AMFValue
&
operator
[](
const
char
*
str
)
const
{
if
(
m_type
!=
AMF_OBJECT
&&
m
_type
!=
AMF_ECMA_ARRAY
)
{
if
(
_type
!=
AMF_OBJECT
&&
_type
!=
AMF_ECMA_ARRAY
)
{
throw
std
::
runtime_error
(
"AMF not a object"
);
}
auto
i
=
m
_value
.
object
->
find
(
str
);
if
(
i
==
m
_value
.
object
->
end
())
{
auto
i
=
_value
.
object
->
find
(
str
);
if
(
i
==
_value
.
object
->
end
())
{
static
AMFValue
val
(
AMF_NULL
);
return
val
;
}
...
...
@@ -140,36 +140,36 @@ public:
}
template
<
typename
FUN
>
void
object_for_each
(
const
FUN
&
fun
)
const
{
if
(
m_type
!=
AMF_OBJECT
&&
m
_type
!=
AMF_ECMA_ARRAY
)
{
if
(
_type
!=
AMF_OBJECT
&&
_type
!=
AMF_ECMA_ARRAY
)
{
throw
std
::
runtime_error
(
"AMF not a object"
);
}
for
(
auto
&
pr
:
*
(
m
_value
.
object
))
{
for
(
auto
&
pr
:
*
(
_value
.
object
))
{
fun
(
pr
.
first
,
pr
.
second
);
}
}
operator
bool
()
const
{
return
m
_type
!=
AMF_NULL
;
return
_type
!=
AMF_NULL
;
}
void
set
(
const
std
::
string
&
s
,
const
AMFValue
&
val
)
{
if
(
m_type
!=
AMF_OBJECT
&&
m
_type
!=
AMF_ECMA_ARRAY
)
{
if
(
_type
!=
AMF_OBJECT
&&
_type
!=
AMF_ECMA_ARRAY
)
{
throw
std
::
runtime_error
(
"AMF not a object"
);
}
m
_value
.
object
->
emplace
(
s
,
val
);
_value
.
object
->
emplace
(
s
,
val
);
}
void
add
(
const
AMFValue
&
val
)
{
if
(
m
_type
!=
AMF_STRICT_ARRAY
)
{
if
(
_type
!=
AMF_STRICT_ARRAY
)
{
throw
std
::
runtime_error
(
"AMF not a array"
);
}
assert
(
m
_type
==
AMF_STRICT_ARRAY
);
m
_value
.
array
->
push_back
(
val
);
assert
(
_type
==
AMF_STRICT_ARRAY
);
_value
.
array
->
push_back
(
val
);
}
private
:
typedef
std
::
map
<
std
::
string
,
AMFValue
>
mapType
;
typedef
std
::
vector
<
AMFValue
>
arrayType
;
AMFType
m
_type
;
AMFType
_type
;
union
{
std
::
string
*
string
;
double
number
;
...
...
@@ -177,20 +177,20 @@ private:
bool
boolean
;
mapType
*
object
;
arrayType
*
array
;
}
m
_value
;
}
_value
;
friend
class
AMFEncoder
;
const
mapType
&
getMap
()
const
{
if
(
m_type
!=
AMF_OBJECT
&&
m
_type
!=
AMF_ECMA_ARRAY
)
{
if
(
_type
!=
AMF_OBJECT
&&
_type
!=
AMF_ECMA_ARRAY
)
{
throw
std
::
runtime_error
(
"AMF not a object"
);
}
return
*
m
_value
.
object
;
return
*
_value
.
object
;
}
const
arrayType
&
getArr
()
const
{
if
(
m
_type
!=
AMF_STRICT_ARRAY
)
{
if
(
_type
!=
AMF_STRICT_ARRAY
)
{
throw
std
::
runtime_error
(
"AMF not a array"
);
}
return
*
m
_value
.
array
;
return
*
_value
.
array
;
}
inline
void
destroy
();
inline
void
init
();
...
...
src/RtmpCodec/AACRtmpCodec.cpp
查看文件 @
39baaebc
...
...
@@ -67,7 +67,7 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
//////////header
uint8_t
is_config
=
false
;
rtmpPkt
->
strBuf
.
push_back
(
m
_ui8AudioFlags
);
rtmpPkt
->
strBuf
.
push_back
(
_ui8AudioFlags
);
rtmpPkt
->
strBuf
.
push_back
(
!
is_config
);
rtmpPkt
->
strBuf
.
append
(
frame
->
data
()
+
frame
->
prefixSize
(),
frame
->
size
()
-
frame
->
prefixSize
());
...
...
@@ -108,12 +108,12 @@ void AACRtmpEncoder::makeAudioConfigPkt() {
uint8_t
flvSampleBit
=
iSampleBit
==
16
;
uint8_t
flvAudioType
=
10
;
//aac
m
_ui8AudioFlags
=
(
flvAudioType
<<
4
)
|
(
flvSampleRate
<<
2
)
|
(
flvSampleBit
<<
1
)
|
flvStereoOrMono
;
_ui8AudioFlags
=
(
flvAudioType
<<
4
)
|
(
flvSampleRate
<<
2
)
|
(
flvSampleBit
<<
1
)
|
flvStereoOrMono
;
RtmpPacket
::
Ptr
rtmpPkt
=
ResourcePoolHelper
<
RtmpPacket
>::
obtainObj
();
//////////header
uint8_t
is_config
=
true
;
rtmpPkt
->
strBuf
.
push_back
(
m
_ui8AudioFlags
);
rtmpPkt
->
strBuf
.
push_back
(
_ui8AudioFlags
);
rtmpPkt
->
strBuf
.
push_back
(
!
is_config
);
rtmpPkt
->
strBuf
.
append
(
_aac_cfg
);
...
...
src/RtmpCodec/AACRtmpCodec.h
查看文件 @
39baaebc
...
...
@@ -61,7 +61,7 @@ public:
private
:
void
makeAudioConfigPkt
();
uint8_t
m
_ui8AudioFlags
;
uint8_t
_ui8AudioFlags
;
};
}
//namespace Rtmp
...
...
src/RtmpCodec/H264RtmpCodec.cpp
查看文件 @
39baaebc
...
...
@@ -6,7 +6,7 @@
H264RtmpDecoder
::
H264RtmpDecoder
()
{
m
_h264frame
=
obtainFrame
();
_h264frame
=
obtainFrame
();
}
H264Frame
::
Ptr
H264RtmpDecoder
::
obtainFrame
()
{
...
...
@@ -26,12 +26,12 @@ bool H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) {
bool
H264RtmpDecoder
::
decodeRtmp
(
const
RtmpPacket
::
Ptr
&
pkt
)
{
if
(
pkt
->
isCfgFrame
())
{
//缓存sps pps,后续插入到I帧之前
m
_sps
=
pkt
->
getH264SPS
();
m
_pps
=
pkt
->
getH264PPS
();
_sps
=
pkt
->
getH264SPS
();
_pps
=
pkt
->
getH264PPS
();
return
false
;
}
if
(
m
_sps
.
size
())
{
if
(
_sps
.
size
())
{
uint32_t
iTotalLen
=
pkt
->
strBuf
.
size
();
uint32_t
iOffset
=
5
;
while
(
iOffset
+
4
<
iTotalLen
){
...
...
@@ -54,8 +54,8 @@ inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t
switch
(
pcData
[
0
]
&
0x1F
)
{
case
5
:
{
//I frame
onGetH264
(
m_sps
.
data
(),
m
_sps
.
length
(),
ui32TimeStamp
);
onGetH264
(
m_pps
.
data
(),
m
_pps
.
length
(),
ui32TimeStamp
);
onGetH264
(
_sps
.
data
(),
_sps
.
length
(),
ui32TimeStamp
);
onGetH264
(
_pps
.
data
(),
_pps
.
length
(),
ui32TimeStamp
);
}
case
1
:
{
//I or P or B frame
...
...
@@ -68,14 +68,14 @@ inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t
}
}
inline
void
H264RtmpDecoder
::
onGetH264
(
const
char
*
pcData
,
int
iLen
,
uint32_t
ui32TimeStamp
)
{
m
_h264frame
->
type
=
pcData
[
0
]
&
0x1F
;
m
_h264frame
->
timeStamp
=
ui32TimeStamp
;
m
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
//添加264头
m
_h264frame
->
buffer
.
append
(
pcData
,
iLen
);
_h264frame
->
type
=
pcData
[
0
]
&
0x1F
;
_h264frame
->
timeStamp
=
ui32TimeStamp
;
_h264frame
->
buffer
.
assign
(
"\x0\x0\x0\x1"
,
4
);
//添加264头
_h264frame
->
buffer
.
append
(
pcData
,
iLen
);
//写入环形缓存
RtmpCodec
::
inputFrame
(
m
_h264frame
);
m
_h264frame
=
obtainFrame
();
RtmpCodec
::
inputFrame
(
_h264frame
);
_h264frame
=
obtainFrame
();
}
...
...
@@ -95,9 +95,9 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
switch
(
type
){
case
7
:{
//sps
if
(
m
_sps
.
empty
()){
m
_sps
=
string
(
pcData
,
iLen
);
if
(
!
m
_pps
.
empty
()){
if
(
_sps
.
empty
()){
_sps
=
string
(
pcData
,
iLen
);
if
(
!
_pps
.
empty
()){
makeVideoConfigPkt
();
}
}
...
...
@@ -105,9 +105,9 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
break
;
case
8
:{
//pps
if
(
m
_pps
.
empty
()){
m
_pps
=
string
(
pcData
,
iLen
);
if
(
!
m
_sps
.
empty
()){
if
(
_pps
.
empty
()){
_pps
=
string
(
pcData
,
iLen
);
if
(
!
_sps
.
empty
()){
makeVideoConfigPkt
();
}
}
...
...
@@ -158,23 +158,23 @@ void H264RtmpEncoder::makeVideoConfigPkt() {
////////////sps
rtmpPkt
->
strBuf
.
push_back
(
1
);
// version
//DebugL<<hexdump(
m_sps.data(), m
_sps.size());
rtmpPkt
->
strBuf
.
push_back
(
m
_sps
[
1
]);
// profile
rtmpPkt
->
strBuf
.
push_back
(
m
_sps
[
2
]);
// compat
rtmpPkt
->
strBuf
.
push_back
(
m
_sps
[
3
]);
// level
//DebugL<<hexdump(
_sps.data(),
_sps.size());
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
1
]);
// profile
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
2
]);
// compat
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
3
]);
// level
rtmpPkt
->
strBuf
.
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)
uint16_t
size
=
m
_sps
.
size
();
uint16_t
size
=
_sps
.
size
();
size
=
htons
(
size
);
rtmpPkt
->
strBuf
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
strBuf
.
append
(
m
_sps
);
rtmpPkt
->
strBuf
.
append
(
_sps
);
/////////////pps
rtmpPkt
->
strBuf
.
push_back
(
1
);
// version
size
=
m
_pps
.
size
();
size
=
_pps
.
size
();
size
=
htons
(
size
);
rtmpPkt
->
strBuf
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
strBuf
.
append
(
m
_pps
);
rtmpPkt
->
strBuf
.
append
(
_pps
);
rtmpPkt
->
bodySize
=
rtmpPkt
->
strBuf
.
size
();
rtmpPkt
->
chunkId
=
CHUNK_VIDEO
;
...
...
src/RtmpCodec/H264RtmpCodec.h
查看文件 @
39baaebc
...
...
@@ -40,9 +40,9 @@ protected:
void
onGetH264
(
const
char
*
pcData
,
int
iLen
,
uint32_t
ui32TimeStamp
);
H264Frame
::
Ptr
obtainFrame
();
protected
:
H264Frame
::
Ptr
m
_h264frame
;
string
m
_sps
;
string
m
_pps
;
H264Frame
::
Ptr
_h264frame
;
string
_sps
;
string
_pps
;
};
/**
...
...
src/Rtsp/RtpBroadCaster.cpp
查看文件 @
39baaebc
...
...
@@ -50,17 +50,17 @@ static uint32_t addressToInt(const string &ip){
}
std
::
shared_ptr
<
uint32_t
>
MultiCastAddressMaker
::
obtain
(
uint32_t
iTry
)
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtx
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
GET_CONFIG_AND_REGISTER
(
string
,
addrMinStr
,
Config
::
MultiCast
::
kAddrMin
);
GET_CONFIG_AND_REGISTER
(
string
,
addrMaxStr
,
Config
::
MultiCast
::
kAddrMax
);
uint32_t
addrMin
=
addressToInt
(
addrMinStr
);
uint32_t
addrMax
=
addressToInt
(
addrMaxStr
);
if
(
m_iAddr
>
addrMax
||
m
_iAddr
==
0
){
m
_iAddr
=
addrMin
;
if
(
_iAddr
>
addrMax
||
_iAddr
==
0
){
_iAddr
=
addrMin
;
}
auto
iGotAddr
=
m
_iAddr
++
;
if
(
m_setBadAddr
.
find
(
iGotAddr
)
!=
m
_setBadAddr
.
end
()){
auto
iGotAddr
=
_iAddr
++
;
if
(
_setBadAddr
.
find
(
iGotAddr
)
!=
_setBadAddr
.
end
()){
//已经分配过了
if
(
iTry
){
return
obtain
(
--
iTry
);
...
...
@@ -69,7 +69,7 @@ std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
ErrorL
;
return
nullptr
;
}
m
_setBadAddr
.
emplace
(
iGotAddr
);
_setBadAddr
.
emplace
(
iGotAddr
);
std
::
shared_ptr
<
uint32_t
>
ret
(
new
uint32_t
(
iGotAddr
),[](
uint32_t
*
ptr
){
MultiCastAddressMaker
::
Instance
().
release
(
*
ptr
);
delete
ptr
;
...
...
@@ -77,8 +77,8 @@ std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
return
ret
;
}
void
MultiCastAddressMaker
::
release
(
uint32_t
iAddr
){
lock_guard
<
recursive_mutex
>
lck
(
m
_mtx
);
m
_setBadAddr
.
erase
(
iAddr
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
_setBadAddr
.
erase
(
iAddr
);
}
...
...
@@ -86,16 +86,16 @@ recursive_mutex RtpBroadCaster::g_mtx;
unordered_map
<
string
,
weak_ptr
<
RtpBroadCaster
>
>
RtpBroadCaster
::
g_mapBroadCaster
;
void
RtpBroadCaster
::
setDetachCB
(
void
*
listener
,
const
onDetach
&
cb
)
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtx
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
if
(
cb
){
m
_mapDetach
.
emplace
(
listener
,
cb
);
_mapDetach
.
emplace
(
listener
,
cb
);
}
else
{
m
_mapDetach
.
erase
(
listener
);
_mapDetach
.
erase
(
listener
);
}
}
RtpBroadCaster
::~
RtpBroadCaster
()
{
m
_pReader
->
setReadCB
(
nullptr
);
m
_pReader
->
setDetachCB
(
nullptr
);
_pReader
->
setReadCB
(
nullptr
);
_pReader
->
setDetachCB
(
nullptr
);
DebugL
;
}
RtpBroadCaster
::
RtpBroadCaster
(
const
string
&
strLocalIp
,
const
string
&
strVhost
,
const
string
&
strApp
,
const
string
&
strStream
)
{
...
...
@@ -104,55 +104,55 @@ RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strVhost,c
auto
strErr
=
StrPrinter
<<
"未找到媒体源:"
<<
strVhost
<<
" "
<<
strApp
<<
" "
<<
strStream
<<
endl
;
throw
std
::
runtime_error
(
strErr
);
}
m
_multiAddr
=
MultiCastAddressMaker
::
Instance
().
obtain
();
_multiAddr
=
MultiCastAddressMaker
::
Instance
().
obtain
();
for
(
auto
i
=
0
;
i
<
2
;
i
++
){
m
_apUdpSock
[
i
].
reset
(
new
Socket
());
if
(
!
m
_apUdpSock
[
i
]
->
bindUdpSock
(
0
,
strLocalIp
.
data
())){
_apUdpSock
[
i
].
reset
(
new
Socket
());
if
(
!
_apUdpSock
[
i
]
->
bindUdpSock
(
0
,
strLocalIp
.
data
())){
auto
strErr
=
StrPrinter
<<
"绑定UDP端口失败:"
<<
strLocalIp
<<
endl
;
throw
std
::
runtime_error
(
strErr
);
}
auto
fd
=
m
_apUdpSock
[
i
]
->
rawFD
();
auto
fd
=
_apUdpSock
[
i
]
->
rawFD
();
GET_CONFIG_AND_REGISTER
(
uint32_t
,
udpTTL
,
Config
::
MultiCast
::
kUdpTTL
);
SockUtil
::
setMultiTTL
(
fd
,
udpTTL
);
SockUtil
::
setMultiLOOP
(
fd
,
false
);
SockUtil
::
setMultiIF
(
fd
,
strLocalIp
.
data
());
struct
sockaddr_in
&
peerAddr
=
m
_aPeerUdpAddr
[
i
];
struct
sockaddr_in
&
peerAddr
=
_aPeerUdpAddr
[
i
];
peerAddr
.
sin_family
=
AF_INET
;
peerAddr
.
sin_port
=
htons
(
m
_apUdpSock
[
i
]
->
get_local_port
());
peerAddr
.
sin_addr
.
s_addr
=
htonl
(
*
m
_multiAddr
);
peerAddr
.
sin_port
=
htons
(
_apUdpSock
[
i
]
->
get_local_port
());
peerAddr
.
sin_addr
.
s_addr
=
htonl
(
*
_multiAddr
);
bzero
(
&
(
peerAddr
.
sin_zero
),
sizeof
peerAddr
.
sin_zero
);
}
m
_pReader
=
src
->
getRing
()
->
attach
();
m
_pReader
->
setReadCB
([
this
](
const
RtpPacket
::
Ptr
&
pkt
){
_pReader
=
src
->
getRing
()
->
attach
();
_pReader
->
setReadCB
([
this
](
const
RtpPacket
::
Ptr
&
pkt
){
int
i
=
(
int
)(
pkt
->
type
);
auto
&
pSock
=
m
_apUdpSock
[
i
];
auto
&
peerAddr
=
m
_aPeerUdpAddr
[
i
];
auto
&
pSock
=
_apUdpSock
[
i
];
auto
&
peerAddr
=
_aPeerUdpAddr
[
i
];
BufferRtp
::
Ptr
buffer
(
new
BufferRtp
(
pkt
,
4
));
pSock
->
send
(
buffer
,
SOCKET_DEFAULE_FLAGS
|
FLAG_MORE
,(
struct
sockaddr
*
)(
&
peerAddr
));
});
m
_pReader
->
setDetachCB
([
this
](){
unordered_map
<
void
*
,
onDetach
>
m
_mapDetach_copy
;
_pReader
->
setDetachCB
([
this
](){
unordered_map
<
void
*
,
onDetach
>
_mapDetach_copy
;
{
lock_guard
<
recursive_mutex
>
lck
(
m
_mtx
);
m_mapDetach_copy
=
std
::
move
(
m
_mapDetach
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
);
_mapDetach_copy
=
std
::
move
(
_mapDetach
);
}
for
(
auto
&
pr
:
m
_mapDetach_copy
){
for
(
auto
&
pr
:
_mapDetach_copy
){
pr
.
second
();
}
});
DebugL
<<
MultiCastAddressMaker
::
toString
(
*
m
_multiAddr
)
<<
" "
<<
m
_apUdpSock
[
0
]
->
get_local_port
()
<<
" "
<<
m
_apUdpSock
[
1
]
->
get_local_port
()
<<
" "
DebugL
<<
MultiCastAddressMaker
::
toString
(
*
_multiAddr
)
<<
" "
<<
_apUdpSock
[
0
]
->
get_local_port
()
<<
" "
<<
_apUdpSock
[
1
]
->
get_local_port
()
<<
" "
<<
strVhost
<<
" "
<<
strApp
<<
" "
<<
strStream
;
}
uint16_t
RtpBroadCaster
::
getPort
(
TrackType
trackType
){
return
m
_apUdpSock
[
trackType
]
->
get_local_port
();
return
_apUdpSock
[
trackType
]
->
get_local_port
();
}
string
RtpBroadCaster
::
getIP
(){
return
inet_ntoa
(
m
_aPeerUdpAddr
[
0
].
sin_addr
);
return
inet_ntoa
(
_aPeerUdpAddr
[
0
].
sin_addr
);
}
RtpBroadCaster
::
Ptr
RtpBroadCaster
::
make
(
const
string
&
strLocalIp
,
const
string
&
strVhost
,
const
string
&
strApp
,
const
string
&
strStream
){
try
{
...
...
src/Rtsp/RtpBroadCaster.h
查看文件 @
39baaebc
...
...
@@ -64,9 +64,9 @@ public:
private
:
MultiCastAddressMaker
(){};
void
release
(
uint32_t
iAddr
);
uint32_t
m
_iAddr
=
0
;
recursive_mutex
m
_mtx
;
unordered_set
<
uint32_t
>
m
_setBadAddr
;
uint32_t
_iAddr
=
0
;
recursive_mutex
_mtx
;
unordered_set
<
uint32_t
>
_setBadAddr
;
};
class
RtpBroadCaster
{
public
:
...
...
@@ -82,12 +82,12 @@ private:
static
unordered_map
<
string
,
weak_ptr
<
RtpBroadCaster
>
>
g_mapBroadCaster
;
static
Ptr
make
(
const
string
&
strLocalIp
,
const
string
&
strVhost
,
const
string
&
strApp
,
const
string
&
strStream
);
std
::
shared_ptr
<
uint32_t
>
m
_multiAddr
;
recursive_mutex
m
_mtx
;
unordered_map
<
void
*
,
onDetach
>
m
_mapDetach
;
RtspMediaSource
::
RingType
::
RingReader
::
Ptr
m
_pReader
;
Socket
::
Ptr
m
_apUdpSock
[
2
];
struct
sockaddr_in
m
_aPeerUdpAddr
[
2
];
std
::
shared_ptr
<
uint32_t
>
_multiAddr
;
recursive_mutex
_mtx
;
unordered_map
<
void
*
,
onDetach
>
_mapDetach
;
RtspMediaSource
::
RingType
::
RingReader
::
Ptr
_pReader
;
Socket
::
Ptr
_apUdpSock
[
2
];
struct
sockaddr_in
_aPeerUdpAddr
[
2
];
RtpBroadCaster
(
const
string
&
strLocalIp
,
const
string
&
strVhost
,
const
string
&
strApp
,
const
string
&
strStream
);
...
...
src/Rtsp/RtpParser.cpp
查看文件 @
39baaebc
...
...
@@ -68,7 +68,7 @@ RtpParser::RtpParser(const string& sdp) {
break
;
}
}
m
_fDuration
=
getTimeInSDP
(
sdp
);
_fDuration
=
getTimeInSDP
(
sdp
);
}
bool
RtpParser
::
inputRtp
(
const
RtpPacket
::
Ptr
&
rtp
)
{
...
...
src/Rtsp/RtpParser.h
查看文件 @
39baaebc
...
...
@@ -51,7 +51,7 @@ public:
bool
inputRtp
(
const
RtpPacket
::
Ptr
&
rtp
);
float
getDuration
()
const
override
{
return
m
_fDuration
;
return
_fDuration
;
}
/**
...
...
@@ -76,7 +76,7 @@ private:
inline
void
onGetAudioTrack
(
const
RtspTrack
&
audio
);
inline
void
onGetVideoTrack
(
const
RtspTrack
&
video
);
private
:
float
m
_fDuration
=
0
;
float
_fDuration
=
0
;
AudioTrack
::
Ptr
_audioTrack
;
VideoTrack
::
Ptr
_videoTrack
;
RtpCodec
::
Ptr
_audioRtpDecoder
;
...
...
src/Rtsp/Rtsp.h
查看文件 @
39baaebc
...
...
@@ -83,79 +83,79 @@ public:
break
;
}
if
(
start
==
buf
)
{
m
_strMethod
=
FindField
(
line
.
c_str
(),
NULL
,
" "
);
m
_strFullUrl
=
FindField
(
line
.
c_str
(),
" "
,
" "
);
auto
args_pos
=
m
_strFullUrl
.
find
(
'?'
);
_strMethod
=
FindField
(
line
.
c_str
(),
NULL
,
" "
);
_strFullUrl
=
FindField
(
line
.
c_str
(),
" "
,
" "
);
auto
args_pos
=
_strFullUrl
.
find
(
'?'
);
if
(
args_pos
!=
string
::
npos
){
m_strUrl
=
m
_strFullUrl
.
substr
(
0
,
args_pos
);
m_mapUrlArgs
=
parseArgs
(
m
_strFullUrl
.
substr
(
args_pos
+
1
));
_strUrl
=
_strFullUrl
.
substr
(
0
,
args_pos
);
_mapUrlArgs
=
parseArgs
(
_strFullUrl
.
substr
(
args_pos
+
1
));
}
else
{
m_strUrl
=
m
_strFullUrl
;
_strUrl
=
_strFullUrl
;
}
m_strTail
=
FindField
(
line
.
c_str
(),
(
m
_strFullUrl
+
" "
).
c_str
(),
NULL
);
_strTail
=
FindField
(
line
.
c_str
(),
(
_strFullUrl
+
" "
).
c_str
(),
NULL
);
}
else
{
auto
field
=
FindField
(
line
.
c_str
(),
NULL
,
": "
);
auto
value
=
FindField
(
line
.
c_str
(),
": "
,
NULL
);
if
(
field
.
size
()
!=
0
)
{
m
_mapHeaders
[
field
]
=
value
;
_mapHeaders
[
field
]
=
value
;
}
}
start
=
start
+
line
.
size
()
+
2
;
if
(
strncmp
(
start
,
"
\r\n
"
,
2
)
==
0
)
{
//协议解析完毕
m
_strContent
=
FindField
(
start
,
"
\r\n
"
,
NULL
);
_strContent
=
FindField
(
start
,
"
\r\n
"
,
NULL
);
break
;
}
}
}
const
string
&
Method
()
const
{
//rtsp方法
return
m
_strMethod
;
return
_strMethod
;
}
const
string
&
Url
()
const
{
//rtsp url
return
m
_strUrl
;
return
_strUrl
;
}
const
string
&
FullUrl
()
const
{
//rtsp url with args
return
m
_strFullUrl
;
return
_strFullUrl
;
}
const
string
&
Tail
()
const
{
//RTSP/1.0
return
m
_strTail
;
return
_strTail
;
}
const
string
&
operator
[](
const
char
*
name
)
const
{
//rtsp field
auto
it
=
m
_mapHeaders
.
find
(
name
);
if
(
it
==
m
_mapHeaders
.
end
())
{
return
m
_strNull
;
auto
it
=
_mapHeaders
.
find
(
name
);
if
(
it
==
_mapHeaders
.
end
())
{
return
_strNull
;
}
return
it
->
second
;
}
const
string
&
Content
()
const
{
return
m
_strContent
;
return
_strContent
;
}
void
Clear
()
{
m
_strMethod
.
clear
();
m
_strUrl
.
clear
();
m
_strFullUrl
.
clear
();
m
_strTail
.
clear
();
m
_strContent
.
clear
();
m
_mapHeaders
.
clear
();
m
_mapUrlArgs
.
clear
();
_strMethod
.
clear
();
_strUrl
.
clear
();
_strFullUrl
.
clear
();
_strTail
.
clear
();
_strContent
.
clear
();
_mapHeaders
.
clear
();
_mapUrlArgs
.
clear
();
}
void
setUrl
(
const
string
&
url
)
{
this
->
m
_strUrl
=
url
;
this
->
_strUrl
=
url
;
}
void
setContent
(
const
string
&
content
)
{
this
->
m
_strContent
=
content
;
this
->
_strContent
=
content
;
}
StrCaseMap
&
getValues
()
const
{
return
m
_mapHeaders
;
return
_mapHeaders
;
}
StrCaseMap
&
getUrlArgs
()
const
{
return
m
_mapUrlArgs
;
return
_mapUrlArgs
;
}
static
StrCaseMap
parseArgs
(
const
string
&
str
,
const
char
*
pair_delim
=
"&"
,
const
char
*
key_delim
=
"="
){
...
...
@@ -170,14 +170,14 @@ public:
}
private
:
string
m
_strMethod
;
string
m
_strUrl
;
string
m
_strTail
;
string
m
_strContent
;
string
m
_strNull
;
string
m
_strFullUrl
;
mutable
StrCaseMap
m
_mapHeaders
;
mutable
StrCaseMap
m
_mapUrlArgs
;
string
_strMethod
;
string
_strUrl
;
string
_strTail
;
string
_strContent
;
string
_strNull
;
string
_strFullUrl
;
mutable
StrCaseMap
_mapHeaders
;
mutable
StrCaseMap
_mapUrlArgs
;
};
typedef
struct
{
...
...
src/Rtsp/RtspMediaSource.h
查看文件 @
39baaebc
...
...
@@ -60,46 +60,46 @@ public:
RtspMediaSource
(
const
string
&
strVhost
,
const
string
&
strApp
,
const
string
&
strId
)
:
MediaSource
(
RTSP_SCHEMA
,
strVhost
,
strApp
,
strId
),
m
_pRing
(
new
RingBuffer
<
RtpPacket
::
Ptr
>
())
{
_pRing
(
new
RingBuffer
<
RtpPacket
::
Ptr
>
())
{
}
virtual
~
RtspMediaSource
()
{}
const
RingType
::
Ptr
&
getRing
()
const
{
//获取媒体源的rtp环形缓冲
return
m
_pRing
;
return
_pRing
;
}
const
string
&
getSdp
()
const
{
//获取该源的媒体描述信息
return
m
_strSdp
;
return
_strSdp
;
}
virtual
uint32_t
getSsrc
(
TrackType
trackType
)
{
return
m
_mapTracks
[
trackType
].
ssrc
;
return
_mapTracks
[
trackType
].
ssrc
;
}
virtual
uint16_t
getSeqence
(
TrackType
trackType
)
{
return
m
_mapTracks
[
trackType
].
seq
;
return
_mapTracks
[
trackType
].
seq
;
}
virtual
uint32_t
getTimestamp
(
TrackType
trackType
)
{
return
m
_mapTracks
[
trackType
].
timeStamp
;
return
_mapTracks
[
trackType
].
timeStamp
;
}
virtual
void
onGetSDP
(
const
string
&
sdp
)
{
//派生类设置该媒体源媒体描述信息
m
_strSdp
=
sdp
;
_strSdp
=
sdp
;
regist
();
}
virtual
void
onGetRTP
(
const
RtpPacket
::
Ptr
&
rtppt
,
bool
keyPos
)
{
auto
&
trackRef
=
m
_mapTracks
[
rtppt
->
type
];
auto
&
trackRef
=
_mapTracks
[
rtppt
->
type
];
trackRef
.
seq
=
rtppt
->
sequence
;
trackRef
.
timeStamp
=
rtppt
->
timeStamp
;
trackRef
.
ssrc
=
rtppt
->
ssrc
;
trackRef
.
type
=
rtppt
->
type
;
m
_pRing
->
write
(
rtppt
,
keyPos
);
_pRing
->
write
(
rtppt
,
keyPos
);
}
protected
:
unordered_map
<
int
,
RtspTrack
>
m
_mapTracks
;
string
m
_strSdp
;
//媒体描述信息
RingType
::
Ptr
m
_pRing
;
//rtp环形缓冲
unordered_map
<
int
,
RtspTrack
>
_mapTracks
;
string
_strSdp
;
//媒体描述信息
RingType
::
Ptr
_pRing
;
//rtp环形缓冲
};
}
/* namespace Rtsp */
...
...
src/Rtsp/RtspPlayer.cpp
查看文件 @
39baaebc
...
...
@@ -44,9 +44,9 @@ namespace ZL {
namespace
Rtsp
{
#define POP_HEAD(trackidx) \
auto it =
m
_amapRtpSort[trackidx].begin(); \
auto it = _amapRtpSort[trackidx].begin(); \
onRecvRTP_l(it->second, trackidx); \
m
_amapRtpSort[trackidx].erase(it);
_amapRtpSort[trackidx].erase(it);
#define RTP_BUF_SIZE (4 * 1024)
...
...
@@ -54,48 +54,48 @@ const char kRtspMd5Nonce[] = "rtsp_md5_nonce";
const
char
kRtspRealm
[]
=
"rtsp_realm"
;
RtspPlayer
::
RtspPlayer
(
void
){
m
_pktPool
.
setSize
(
64
);
_pktPool
.
setSize
(
64
);
}
RtspPlayer
::~
RtspPlayer
(
void
)
{
teardown
();
if
(
m
_pucRtpBuf
)
{
delete
[]
m
_pucRtpBuf
;
m
_pucRtpBuf
=
nullptr
;
if
(
_pucRtpBuf
)
{
delete
[]
_pucRtpBuf
;
_pucRtpBuf
=
nullptr
;
}
DebugL
<<
endl
;
}
void
RtspPlayer
::
teardown
(){
if
(
alive
())
{
sendRtspRequest
(
"TEARDOWN"
,
m
_strContentBase
);
sendRtspRequest
(
"TEARDOWN"
,
_strContentBase
);
shutdown
();
}
erase
(
kRtspMd5Nonce
);
erase
(
kRtspRealm
);
m
_uiTrackCnt
=
0
;
m
_onHandshake
=
nullptr
;
m
_uiRtpBufLen
=
0
;
m
_strSession
.
clear
();
m
_uiCseq
=
1
;
m
_strContentBase
.
clear
();
CLEAR_ARR
(
m
_apUdpSock
);
CLEAR_ARR
(
m
_aui16LastSeq
)
CLEAR_ARR
(
m
_aui16FirstSeq
)
CLEAR_ARR
(
m
_aui32SsrcErrorCnt
)
CLEAR_ARR
(
m
_aui64RtpRecv
)
CLEAR_ARR
(
m
_aui64SeqOkCnt
)
CLEAR_ARR
(
m
_abSortStarted
)
CLEAR_ARR
(
m
_aui64RtpRecv
)
CLEAR_ARR
(
m
_aui16NowSeq
)
m
_amapRtpSort
[
0
].
clear
();
m
_amapRtpSort
[
1
].
clear
();
m
_pBeatTimer
.
reset
();
m
_pPlayTimer
.
reset
();
m
_pRtpTimer
.
reset
();
m
_fSeekTo
=
0
;
CLEAR_ARR
(
m
_adFistStamp
);
CLEAR_ARR
(
m
_adNowStamp
);
_uiTrackCnt
=
0
;
_onHandshake
=
nullptr
;
_uiRtpBufLen
=
0
;
_strSession
.
clear
();
_uiCseq
=
1
;
_strContentBase
.
clear
();
CLEAR_ARR
(
_apUdpSock
);
CLEAR_ARR
(
_aui16LastSeq
)
CLEAR_ARR
(
_aui16FirstSeq
)
CLEAR_ARR
(
_aui32SsrcErrorCnt
)
CLEAR_ARR
(
_aui64RtpRecv
)
CLEAR_ARR
(
_aui64SeqOkCnt
)
CLEAR_ARR
(
_abSortStarted
)
CLEAR_ARR
(
_aui64RtpRecv
)
CLEAR_ARR
(
_aui16NowSeq
)
_amapRtpSort
[
0
].
clear
();
_amapRtpSort
[
1
].
clear
();
_pBeatTimer
.
reset
();
_pPlayTimer
.
reset
();
_pRtpTimer
.
reset
();
_fSeekTo
=
0
;
CLEAR_ARR
(
_adFistStamp
);
CLEAR_ARR
(
_adNowStamp
);
}
void
RtspPlayer
::
play
(
const
char
*
strUrl
){
...
...
@@ -131,9 +131,9 @@ void RtspPlayer::play(const char* strUrl, const char *strUser, const char *strPw
(
*
this
)[
kRtspPwdIsMD5
]
=
false
;
}
m
_eType
=
eType
;
if
(
m_eType
==
RTP_TCP
&&
!
m
_pucRtpBuf
)
{
m
_pucRtpBuf
=
new
uint8_t
[
RTP_BUF_SIZE
];
_eType
=
eType
;
if
(
_eType
==
RTP_TCP
&&
!
_pucRtpBuf
)
{
_pucRtpBuf
=
new
uint8_t
[
RTP_BUF_SIZE
];
}
auto
ip
=
FindField
(
strUrl
,
"://"
,
"/"
);
if
(
!
ip
.
size
())
{
...
...
@@ -148,7 +148,7 @@ void RtspPlayer::play(const char* strUrl, const char *strUser, const char *strPw
ip
=
FindField
(
ip
.
c_str
(),
NULL
,
":"
);
}
m
_strUrl
=
strUrl
;
_strUrl
=
strUrl
;
if
(
!
(
*
this
)[
PlayerBase
::
kNetAdapter
].
empty
()){
setNetAdapter
((
*
this
)[
PlayerBase
::
kNetAdapter
]);
}
...
...
@@ -164,7 +164,7 @@ void RtspPlayer::onConnect(const SockException &err){
sendDescribe
();
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
m
_pPlayTimer
.
reset
(
new
Timer
(
10
,
[
weakSelf
]()
{
_pPlayTimer
.
reset
(
new
Timer
(
10
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
...
...
@@ -178,7 +178,7 @@ void RtspPlayer::onConnect(const SockException &err){
void
RtspPlayer
::
onRecv
(
const
Buffer
::
Ptr
&
pBuf
)
{
const
char
*
buf
=
pBuf
->
data
();
int
size
=
pBuf
->
size
();
if
(
m
_onHandshake
)
{
if
(
_onHandshake
)
{
//rtsp回复
int
offset
=
0
;
while
(
offset
<
size
-
4
){
...
...
@@ -203,16 +203,16 @@ void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) {
}
}
if
(
m_eType
==
RTP_TCP
&&
m
_pucRtpBuf
)
{
if
(
_eType
==
RTP_TCP
&&
_pucRtpBuf
)
{
//RTP data
while
(
size
>
0
)
{
int
added
=
RTP_BUF_SIZE
-
m
_uiRtpBufLen
;
int
added
=
RTP_BUF_SIZE
-
_uiRtpBufLen
;
added
=
(
added
>
size
?
size
:
added
);
memcpy
(
m_pucRtpBuf
+
m
_uiRtpBufLen
,
buf
,
added
);
m
_uiRtpBufLen
+=
added
;
memcpy
(
_pucRtpBuf
+
_uiRtpBufLen
,
buf
,
added
);
_uiRtpBufLen
+=
added
;
size
-=
added
;
buf
+=
added
;
splitRtp
(
m_pucRtpBuf
,
m
_uiRtpBufLen
);
splitRtp
(
_pucRtpBuf
,
_uiRtpBufLen
);
}
}
}
...
...
@@ -263,13 +263,13 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
StrPrinter
<<
"DESCRIBE:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
()
<<
endl
);
}
auto
strSdp
=
parser
.
Content
();
m
_strContentBase
=
parser
[
"Content-Base"
];
_strContentBase
=
parser
[
"Content-Base"
];
if
(
m
_strContentBase
.
empty
()){
m_strContentBase
=
m
_strUrl
;
if
(
_strContentBase
.
empty
()){
_strContentBase
=
_strUrl
;
}
if
(
m
_strContentBase
.
back
()
==
'/'
)
{
m
_strContentBase
.
pop_back
();
if
(
_strContentBase
.
back
()
==
'/'
)
{
_strContentBase
.
pop_back
();
}
auto
iLen
=
atoi
(
parser
[
"Content-Length"
].
data
());
...
...
@@ -278,26 +278,26 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
}
//解析sdp
m_uiTrackCnt
=
parserSDP
(
strSdp
,
m
_aTrackInfo
);
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
m
_aTrackInfo
[
i
].
ssrc
=
0
;
m
_aui32SsrcErrorCnt
[
i
]
=
0
;
_uiTrackCnt
=
parserSDP
(
strSdp
,
_aTrackInfo
);
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
_aTrackInfo
[
i
].
ssrc
=
0
;
_aui32SsrcErrorCnt
[
i
]
=
0
;
}
if
(
!
m
_uiTrackCnt
)
{
if
(
!
_uiTrackCnt
)
{
throw
std
::
runtime_error
(
"解析SDP失败"
);
}
if
(
!
onCheckSDP
(
strSdp
,
m_aTrackInfo
,
m
_uiTrackCnt
))
{
if
(
!
onCheckSDP
(
strSdp
,
_aTrackInfo
,
_uiTrackCnt
))
{
throw
std
::
runtime_error
(
"onCheckSDP faied"
);
}
sendSetup
(
0
);
}
//发送SETUP命令
bool
RtspPlayer
::
sendSetup
(
unsigned
int
trackIndex
)
{
m
_onHandshake
=
std
::
bind
(
&
RtspPlayer
::
handleResSETUP
,
this
,
placeholders
::
_1
,
trackIndex
);
_onHandshake
=
std
::
bind
(
&
RtspPlayer
::
handleResSETUP
,
this
,
placeholders
::
_1
,
trackIndex
);
auto
&
track
=
m
_aTrackInfo
[
trackIndex
];
auto
baseUrl
=
m
_strContentBase
+
"/"
+
track
.
controlSuffix
;
switch
(
m
_eType
)
{
auto
&
track
=
_aTrackInfo
[
trackIndex
];
auto
baseUrl
=
_strContentBase
+
"/"
+
track
.
controlSuffix
;
switch
(
_eType
)
{
case
RTP_TCP
:
{
StrCaseMap
header
;
header
[
"Transport"
]
=
StrPrinter
<<
"RTP/AVP/TCP;unicast;interleaved="
<<
track
.
type
*
2
<<
"-"
<<
track
.
type
*
2
+
1
;
...
...
@@ -311,12 +311,12 @@ bool RtspPlayer::sendSetup(unsigned int trackIndex) {
}
break
;
case
RTP_UDP
:
{
m
_apUdpSock
[
trackIndex
].
reset
(
new
Socket
());
if
(
!
m
_apUdpSock
[
trackIndex
]
->
bindUdpSock
(
0
,
get_local_ip
().
data
()))
{
m
_apUdpSock
[
trackIndex
].
reset
();
_apUdpSock
[
trackIndex
].
reset
(
new
Socket
());
if
(
!
_apUdpSock
[
trackIndex
]
->
bindUdpSock
(
0
,
get_local_ip
().
data
()))
{
_apUdpSock
[
trackIndex
].
reset
();
throw
std
::
runtime_error
(
"open udp sock err"
);
}
int
port
=
m
_apUdpSock
[
trackIndex
]
->
get_local_port
();
int
port
=
_apUdpSock
[
trackIndex
]
->
get_local_port
();
StrCaseMap
header
;
header
[
"Transport"
]
=
StrPrinter
<<
"RTP/AVP;unicast;client_port="
<<
port
<<
"-"
<<
port
+
1
;
return
sendRtspRequest
(
"SETUP"
,
baseUrl
,
header
);
...
...
@@ -334,33 +334,33 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
StrPrinter
<<
"SETUP:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
()
<<
endl
);
}
if
(
uiTrackIndex
==
0
)
{
m
_strSession
=
parser
[
"Session"
];
m
_strSession
.
append
(
";"
);
m_strSession
=
FindField
(
m
_strSession
.
data
(),
nullptr
,
";"
);
_strSession
=
parser
[
"Session"
];
_strSession
.
append
(
";"
);
_strSession
=
FindField
(
_strSession
.
data
(),
nullptr
,
";"
);
}
auto
strTransport
=
parser
[
"Transport"
];
if
(
strTransport
.
find
(
"TCP"
)
!=
string
::
npos
){
m
_eType
=
RTP_TCP
;
_eType
=
RTP_TCP
;
}
else
if
(
strTransport
.
find
(
"multicast"
)
!=
string
::
npos
){
m
_eType
=
RTP_MULTICAST
;
_eType
=
RTP_MULTICAST
;
}
else
{
m
_eType
=
RTP_UDP
;
_eType
=
RTP_UDP
;
}
if
(
m
_eType
==
RTP_TCP
)
{
if
(
_eType
==
RTP_TCP
)
{
string
interleaved
=
FindField
(
FindField
((
strTransport
+
";"
).
c_str
(),
"interleaved="
,
";"
).
c_str
(),
NULL
,
"-"
);
m
_aTrackInfo
[
uiTrackIndex
].
interleaved
=
atoi
(
interleaved
.
c_str
());
_aTrackInfo
[
uiTrackIndex
].
interleaved
=
atoi
(
interleaved
.
c_str
());
}
else
{
const
char
*
strPos
=
(
m
_eType
==
RTP_MULTICAST
?
"port="
:
"server_port="
)
;
const
char
*
strPos
=
(
_eType
==
RTP_MULTICAST
?
"port="
:
"server_port="
)
;
auto
port_str
=
FindField
((
strTransport
+
";"
).
c_str
(),
strPos
,
";"
);
uint16_t
port
=
atoi
(
FindField
(
port_str
.
c_str
(),
NULL
,
"-"
).
c_str
());
auto
&
pUdpSockRef
=
m
_apUdpSock
[
uiTrackIndex
];
auto
&
pUdpSockRef
=
_apUdpSock
[
uiTrackIndex
];
if
(
!
pUdpSockRef
){
pUdpSockRef
.
reset
(
new
Socket
());
}
if
(
m
_eType
==
RTP_MULTICAST
)
{
if
(
_eType
==
RTP_MULTICAST
)
{
auto
multiAddr
=
FindField
((
strTransport
+
";"
).
c_str
(),
"destination="
,
";"
);
if
(
!
pUdpSockRef
->
bindUdpSock
(
port
,
"0.0.0.0"
))
{
pUdpSockRef
.
reset
();
...
...
@@ -379,14 +379,14 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
}
}
if
(
uiTrackIndex
<
m
_uiTrackCnt
-
1
)
{
if
(
uiTrackIndex
<
_uiTrackCnt
-
1
)
{
//需要继续发送SETUP命令
sendSetup
(
uiTrackIndex
+
1
);
return
;
}
for
(
unsigned
int
i
=
0
;
i
<
m_uiTrackCnt
&&
m
_eType
!=
RTP_TCP
;
i
++
)
{
auto
&
pUdpSockRef
=
m
_apUdpSock
[
i
];
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
&&
_eType
!=
RTP_TCP
;
i
++
)
{
auto
&
pUdpSockRef
=
_apUdpSock
[
i
];
if
(
!
pUdpSockRef
){
continue
;
}
...
...
@@ -406,7 +406,7 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
}
/////////////////////////心跳/////////////////////////////////
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
m
_pBeatTimer
.
reset
(
new
Timer
(
5
,
[
weakSelf
](){
_pBeatTimer
.
reset
(
new
Timer
(
5
,
[
weakSelf
](){
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
){
return
false
;
...
...
@@ -417,47 +417,47 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
}
bool
RtspPlayer
::
sendOptions
()
{
m
_onHandshake
=
[](
const
Parser
&
parser
){
_onHandshake
=
[](
const
Parser
&
parser
){
return
true
;
};
return
sendRtspRequest
(
"OPTIONS"
,
m
_strContentBase
);
return
sendRtspRequest
(
"OPTIONS"
,
_strContentBase
);
}
bool
RtspPlayer
::
sendDescribe
()
{
//发送DESCRIBE命令后处理函数:handleResDESCRIBE
m
_onHandshake
=
std
::
bind
(
&
RtspPlayer
::
handleResDESCRIBE
,
this
,
placeholders
::
_1
);
_onHandshake
=
std
::
bind
(
&
RtspPlayer
::
handleResDESCRIBE
,
this
,
placeholders
::
_1
);
StrCaseMap
header
;
header
[
"Accept"
]
=
"application/sdp"
;
return
sendRtspRequest
(
"DESCRIBE"
,
m
_strUrl
,
header
);
return
sendRtspRequest
(
"DESCRIBE"
,
_strUrl
,
header
);
}
bool
RtspPlayer
::
sendPause
(
bool
bPause
,
float
fTime
){
if
(
!
bPause
){
//修改时间轴
m
_aNowStampTicker
[
0
].
resetTime
();
m
_aNowStampTicker
[
1
].
resetTime
();
_aNowStampTicker
[
0
].
resetTime
();
_aNowStampTicker
[
1
].
resetTime
();
float
iTimeInc
=
fTime
-
getProgressTime
();
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
){
if
(
m
_aTrackInfo
[
i
].
type
==
TrackVideo
)
{
m_adFistStamp
[
i
]
=
m
_adNowStamp
[
i
]
+
iTimeInc
*
90000.0
;
}
else
if
(
m
_aTrackInfo
[
i
].
type
==
TrackAudio
){
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
){
if
(
_aTrackInfo
[
i
].
type
==
TrackVideo
)
{
_adFistStamp
[
i
]
=
_adNowStamp
[
i
]
+
iTimeInc
*
90000.0
;
}
else
if
(
_aTrackInfo
[
i
].
type
==
TrackAudio
){
//todo(xzl) 修复此处
//
m_adFistStamp[i] = m
_adNowStamp[i] + iTimeInc * getAudioSampleRate();
//
_adFistStamp[i] =
_adNowStamp[i] + iTimeInc * getAudioSampleRate();
}
m_adNowStamp
[
i
]
=
m
_adFistStamp
[
i
];
_adNowStamp
[
i
]
=
_adFistStamp
[
i
];
}
m
_fSeekTo
=
fTime
;
_fSeekTo
=
fTime
;
}
//开启或暂停rtsp
m
_onHandshake
=
std
::
bind
(
&
RtspPlayer
::
handleResPAUSE
,
this
,
placeholders
::
_1
,
bPause
);
_onHandshake
=
std
::
bind
(
&
RtspPlayer
::
handleResPAUSE
,
this
,
placeholders
::
_1
,
bPause
);
StrCaseMap
header
;
char
buf
[
8
];
sprintf
(
buf
,
"%.2f"
,
fTime
);
header
[
"Range"
]
=
StrPrinter
<<
"npt="
<<
buf
<<
"-"
;
return
sendRtspRequest
(
bPause
?
"PAUSE"
:
"PLAY"
,
m
_strContentBase
,
header
);
return
sendRtspRequest
(
bPause
?
"PAUSE"
:
"PLAY"
,
_strContentBase
,
header
);
}
void
RtspPlayer
::
pause
(
bool
bPause
)
{
sendPause
(
bPause
,
getProgressTime
());
...
...
@@ -470,16 +470,16 @@ void RtspPlayer::handleResPAUSE(const Parser& parser, bool bPause) {
}
if
(
!
bPause
)
{
//修正时间轴
m
_aNowStampTicker
[
0
].
resetTime
();
m
_aNowStampTicker
[
1
].
resetTime
();
_aNowStampTicker
[
0
].
resetTime
();
_aNowStampTicker
[
1
].
resetTime
();
auto
strRange
=
parser
[
"Range"
];
if
(
strRange
.
size
())
{
auto
strStart
=
FindField
(
strRange
.
data
(),
"npt="
,
"-"
);
if
(
strStart
==
"now"
)
{
strStart
=
"0"
;
}
m
_fSeekTo
=
atof
(
strStart
.
data
());
DebugL
<<
"Range:"
<<
m
_fSeekTo
<<
" "
<<
strStart
;
_fSeekTo
=
atof
(
strStart
.
data
());
DebugL
<<
"Range:"
<<
_fSeekTo
<<
" "
<<
strStart
;
}
auto
strRtpInfo
=
parser
[
"RTP-Info"
];
if
(
strRtpInfo
.
size
())
{
...
...
@@ -490,14 +490,14 @@ void RtspPlayer::handleResPAUSE(const Parser& parser, bool bPause) {
auto
strControlSuffix
=
strTrack
.
substr
(
1
+
strTrack
.
rfind
(
'/'
),
strTrack
.
find
(
';'
)
-
strTrack
.
rfind
(
'/'
)
-
1
);
auto
strRtpTime
=
FindField
(
strTrack
.
data
(),
"rtptime="
,
";"
);
auto
iIdx
=
getTrackIndexByControlSuffix
(
strControlSuffix
);
m
_adFistStamp
[
iIdx
]
=
atoll
(
strRtpTime
.
data
());
m_adNowStamp
[
iIdx
]
=
m
_adFistStamp
[
iIdx
];
_adFistStamp
[
iIdx
]
=
atoll
(
strRtpTime
.
data
());
_adNowStamp
[
iIdx
]
=
_adFistStamp
[
iIdx
];
DebugL
<<
"rtptime:"
<<
strControlSuffix
<<
" "
<<
strRtpTime
;
}
}
onPlayResult_l
(
SockException
(
Err_success
,
"rtsp play success"
));
}
else
{
m
_pRtpTimer
.
reset
();
_pRtpTimer
.
reset
();
}
}
...
...
@@ -518,8 +518,8 @@ int RtspPlayer::onProcess(const char* pcBuf) {
parser
.
setContent
(
strContent
);
}
}
auto
fun
=
m
_onHandshake
;
m
_onHandshake
=
nullptr
;
auto
fun
=
_onHandshake
;
_onHandshake
=
nullptr
;
if
(
fun
){
fun
(
parser
);
}
...
...
@@ -576,7 +576,7 @@ void RtspPlayer::splitRtp(unsigned char* pucRtp, unsigned int uiLen) {
uiLen
-=
(
pos
-
rtp_ptr
);
rtp_ptr
=
pos
;
}
m
_uiRtpBufLen
=
uiLen
;
_uiRtpBufLen
=
uiLen
;
if
(
rtp_ptr
!=
pucRtp
)
{
memmove
(
pucRtp
,
rtp_ptr
,
uiLen
);
}
...
...
@@ -589,8 +589,8 @@ void RtspPlayer::splitRtp(unsigned char* pucRtp, unsigned int uiLen) {
bool
RtspPlayer
::
handleOneRtp
(
int
iTrackidx
,
unsigned
char
*
pucData
,
unsigned
int
uiLen
)
{
auto
&
track
=
m
_aTrackInfo
[
iTrackidx
];
auto
pt_ptr
=
m
_pktPool
.
obtain
();
auto
&
track
=
_aTrackInfo
[
iTrackidx
];
auto
pt_ptr
=
_pktPool
.
obtain
();
auto
&
rtppt
=*
pt_ptr
;
rtppt
.
interleaved
=
track
.
interleaved
;
rtppt
.
length
=
uiLen
+
4
;
...
...
@@ -613,13 +613,13 @@ bool RtspPlayer::handleOneRtp(int iTrackidx, unsigned char *pucData, unsigned in
}
else
if
(
track
.
ssrc
!=
rtppt
.
ssrc
)
{
//ssrc错误
WarnL
<<
"ssrc错误"
;
if
(
m
_aui32SsrcErrorCnt
[
iTrackidx
]
++
>
10
)
{
if
(
_aui32SsrcErrorCnt
[
iTrackidx
]
++
>
10
)
{
track
.
ssrc
=
rtppt
.
ssrc
;
WarnL
<<
"ssrc更换!"
;
}
return
false
;
}
m
_aui32SsrcErrorCnt
[
iTrackidx
]
=
0
;
_aui32SsrcErrorCnt
[
iTrackidx
]
=
0
;
rtppt
.
payload
[
0
]
=
'$'
;
rtppt
.
payload
[
1
]
=
rtppt
.
interleaved
;
...
...
@@ -642,30 +642,30 @@ bool RtspPlayer::handleOneRtp(int iTrackidx, unsigned char *pucData, unsigned in
memcpy
(
rtppt
.
payload
+
4
,
pucData
,
uiLen
);
/////////////////////////////////RTP排序逻辑///////////////////////////////////
if
(
rtppt
.
sequence
!=
(
uint16_t
)(
m_aui16LastSeq
[
iTrackidx
]
+
1
)
&&
m
_aui16LastSeq
[
iTrackidx
]
!=
0
){
if
(
rtppt
.
sequence
!=
(
uint16_t
)(
_aui16LastSeq
[
iTrackidx
]
+
1
)
&&
_aui16LastSeq
[
iTrackidx
]
!=
0
){
//包乱序或丢包
m
_aui64SeqOkCnt
[
iTrackidx
]
=
0
;
m
_abSortStarted
[
iTrackidx
]
=
true
;
//WarnL << "包乱序或丢包:" << trackidx <<" " << rtppt.sequence << " " <<
m
_aui16LastSeq[trackidx];
_aui64SeqOkCnt
[
iTrackidx
]
=
0
;
_abSortStarted
[
iTrackidx
]
=
true
;
//WarnL << "包乱序或丢包:" << trackidx <<" " << rtppt.sequence << " " << _aui16LastSeq[trackidx];
}
else
{
//正确序列的包
m
_aui64SeqOkCnt
[
iTrackidx
]
++
;
_aui64SeqOkCnt
[
iTrackidx
]
++
;
}
m
_aui16LastSeq
[
iTrackidx
]
=
rtppt
.
sequence
;
_aui16LastSeq
[
iTrackidx
]
=
rtppt
.
sequence
;
//开始排序缓存
if
(
m
_abSortStarted
[
iTrackidx
])
{
m
_amapRtpSort
[
iTrackidx
].
emplace
(
rtppt
.
sequence
,
pt_ptr
);
if
(
_abSortStarted
[
iTrackidx
])
{
_amapRtpSort
[
iTrackidx
].
emplace
(
rtppt
.
sequence
,
pt_ptr
);
GET_CONFIG_AND_REGISTER
(
uint32_t
,
clearCount
,
Config
::
Rtp
::
kClearCount
);
GET_CONFIG_AND_REGISTER
(
uint32_t
,
maxRtpCount
,
Config
::
Rtp
::
kMaxRtpCount
);
if
(
m
_aui64SeqOkCnt
[
iTrackidx
]
>=
clearCount
)
{
if
(
_aui64SeqOkCnt
[
iTrackidx
]
>=
clearCount
)
{
//网络环境改善,需要清空排序缓存
m
_aui64SeqOkCnt
[
iTrackidx
]
=
0
;
m
_abSortStarted
[
iTrackidx
]
=
false
;
while
(
m
_amapRtpSort
[
iTrackidx
].
size
())
{
_aui64SeqOkCnt
[
iTrackidx
]
=
0
;
_abSortStarted
[
iTrackidx
]
=
false
;
while
(
_amapRtpSort
[
iTrackidx
].
size
())
{
POP_HEAD
(
iTrackidx
)
}
}
else
if
(
m
_amapRtpSort
[
iTrackidx
].
size
()
>=
maxRtpCount
)
{
}
else
if
(
_amapRtpSort
[
iTrackidx
].
size
()
>=
maxRtpCount
)
{
//排序缓存溢出
POP_HEAD
(
iTrackidx
)
}
...
...
@@ -678,27 +678,27 @@ bool RtspPlayer::handleOneRtp(int iTrackidx, unsigned char *pucData, unsigned in
}
void
RtspPlayer
::
onRecvRTP_l
(
const
RtpPacket
::
Ptr
&
rtppt
,
int
trackidx
){
//统计丢包率
if
(
m_aui16FirstSeq
[
trackidx
]
==
0
||
rtppt
->
sequence
<
m
_aui16FirstSeq
[
trackidx
])
{
m
_aui16FirstSeq
[
trackidx
]
=
rtppt
->
sequence
;
m
_aui64RtpRecv
[
trackidx
]
=
0
;
if
(
_aui16FirstSeq
[
trackidx
]
==
0
||
rtppt
->
sequence
<
_aui16FirstSeq
[
trackidx
])
{
_aui16FirstSeq
[
trackidx
]
=
rtppt
->
sequence
;
_aui64RtpRecv
[
trackidx
]
=
0
;
}
m
_aui64RtpRecv
[
trackidx
]
++
;
m
_aui16NowSeq
[
trackidx
]
=
rtppt
->
sequence
;
_aui64RtpRecv
[
trackidx
]
++
;
_aui16NowSeq
[
trackidx
]
=
rtppt
->
sequence
;
if
(
m
_aNowStampTicker
[
trackidx
].
elapsedTime
()
>
500
)
{
m
_adNowStamp
[
trackidx
]
=
rtppt
->
timeStamp
;
if
(
_aNowStampTicker
[
trackidx
].
elapsedTime
()
>
500
)
{
_adNowStamp
[
trackidx
]
=
rtppt
->
timeStamp
;
}
onRecvRTP_l
(
rtppt
,
m
_aTrackInfo
[
trackidx
]);
onRecvRTP_l
(
rtppt
,
_aTrackInfo
[
trackidx
]);
}
float
RtspPlayer
::
getRtpLossRate
(
int
iTrackType
)
const
{
int
iTrackIdx
=
getTrackIndexByTrackType
((
TrackType
)
iTrackType
);
if
(
iTrackIdx
==
-
1
){
uint64_t
totalRecv
=
0
;
uint64_t
totalSend
=
0
;
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
totalRecv
+=
m
_aui64RtpRecv
[
i
];
totalSend
+=
(
m_aui16NowSeq
[
i
]
-
m
_aui16FirstSeq
[
i
]
+
1
);
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
totalRecv
+=
_aui64RtpRecv
[
i
];
totalSend
+=
(
_aui16NowSeq
[
i
]
-
_aui16FirstSeq
[
i
]
+
1
);
}
if
(
totalSend
==
0
){
return
0
;
...
...
@@ -707,25 +707,25 @@ float RtspPlayer::getRtpLossRate(int iTrackType) const{
}
if
(
m_aui16NowSeq
[
iTrackIdx
]
-
m
_aui16FirstSeq
[
iTrackIdx
]
+
1
==
0
){
if
(
_aui16NowSeq
[
iTrackIdx
]
-
_aui16FirstSeq
[
iTrackIdx
]
+
1
==
0
){
return
0
;
}
return
1.0
-
(
double
)
m_aui64RtpRecv
[
iTrackIdx
]
/
(
m_aui16NowSeq
[
iTrackIdx
]
-
m
_aui16FirstSeq
[
iTrackIdx
]
+
1
);
return
1.0
-
(
double
)
_aui64RtpRecv
[
iTrackIdx
]
/
(
_aui16NowSeq
[
iTrackIdx
]
-
_aui16FirstSeq
[
iTrackIdx
]
+
1
);
}
float
RtspPlayer
::
getProgressTime
()
const
{
double
iTime
[
2
]
=
{
0
,
0
};
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
){
if
(
m
_aTrackInfo
[
i
].
type
==
TrackVideo
)
{
iTime
[
i
]
=
(
m_adNowStamp
[
i
]
-
m
_adFistStamp
[
i
])
/
90000.0
;
}
else
if
(
m
_aTrackInfo
[
i
].
type
==
TrackAudio
){
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
){
if
(
_aTrackInfo
[
i
].
type
==
TrackVideo
)
{
iTime
[
i
]
=
(
_adNowStamp
[
i
]
-
_adFistStamp
[
i
])
/
90000.0
;
}
else
if
(
_aTrackInfo
[
i
].
type
==
TrackAudio
){
//todo(xzl) 修复此处
#if 0
iTime[i] = (
m_adNowStamp[i] - m
_adFistStamp[i]) / getAudioSampleRate();
iTime[i] = (
_adNowStamp[i] -
_adFistStamp[i]) / getAudioSampleRate();
#endif
}
}
return
m
_fSeekTo
+
MAX
(
iTime
[
0
],
iTime
[
1
]);
return
_fSeekTo
+
MAX
(
iTime
[
0
],
iTime
[
1
]);
}
void
RtspPlayer
::
seekToTime
(
float
fTime
)
{
sendPause
(
false
,
fTime
);
...
...
@@ -733,9 +733,9 @@ void RtspPlayer::seekToTime(float fTime) {
bool
RtspPlayer
::
sendRtspRequest
(
const
string
&
cmd
,
const
string
&
url
,
const
StrCaseMap
&
header_const
)
{
auto
header
=
header_const
;
header
.
emplace
(
"CSeq"
,
StrPrinter
<<
m
_uiCseq
++
);
if
(
!
m
_strSession
.
empty
()){
header
.
emplace
(
"Session"
,
m
_strSession
);
header
.
emplace
(
"CSeq"
,
StrPrinter
<<
_uiCseq
++
);
if
(
!
_strSession
.
empty
()){
header
.
emplace
(
"Session"
,
_strSession
);
}
if
(
!
(
*
this
)[
kRtspRealm
].
empty
()
&&
!
(
*
this
)[
PlayerBase
::
kRtspUser
].
empty
()){
...
...
@@ -782,28 +782,28 @@ bool RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
void
RtspPlayer
::
onShutdown_l
(
const
SockException
&
ex
)
{
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
m
_pPlayTimer
.
reset
();
m
_pRtpTimer
.
reset
();
m
_pBeatTimer
.
reset
();
_pPlayTimer
.
reset
();
_pRtpTimer
.
reset
();
_pBeatTimer
.
reset
();
onShutdown
(
ex
);
}
void
RtspPlayer
::
onRecvRTP_l
(
const
RtpPacket
::
Ptr
&
pRtppt
,
const
RtspTrack
&
track
)
{
m
_rtpTicker
.
resetTime
();
_rtpTicker
.
resetTime
();
onRecvRTP
(
pRtppt
,
track
);
}
void
RtspPlayer
::
onPlayResult_l
(
const
SockException
&
ex
)
{
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
m
_pPlayTimer
.
reset
();
m
_pRtpTimer
.
reset
();
_pPlayTimer
.
reset
();
_pRtpTimer
.
reset
();
if
(
!
ex
)
{
m
_rtpTicker
.
resetTime
();
_rtpTicker
.
resetTime
();
weak_ptr
<
RtspPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtspPlayer
>
(
shared_from_this
());
m
_pRtpTimer
.
reset
(
new
Timer
(
5
,
[
weakSelf
]()
{
_pRtpTimer
.
reset
(
new
Timer
(
5
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
if
(
strongSelf
->
m
_rtpTicker
.
elapsedTime
()
>
10000
)
{
if
(
strongSelf
->
_rtpTicker
.
elapsedTime
()
>
10000
)
{
//recv rtp timeout!
strongSelf
->
onShutdown_l
(
SockException
(
Err_timeout
,
"recv rtp timeout"
));
strongSelf
->
teardown
();
...
...
@@ -816,16 +816,16 @@ void RtspPlayer::onPlayResult_l(const SockException &ex) {
}
int
RtspPlayer
::
getTrackIndexByControlSuffix
(
const
string
&
controlSuffix
)
const
{
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
if
(
m
_aTrackInfo
[
i
].
controlSuffix
==
controlSuffix
)
{
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
if
(
_aTrackInfo
[
i
].
controlSuffix
==
controlSuffix
)
{
return
i
;
}
}
return
-
1
;
}
int
RtspPlayer
::
getTrackIndexByInterleaved
(
int
interleaved
)
const
{
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
if
(
m
_aTrackInfo
[
i
].
interleaved
==
interleaved
)
{
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
if
(
_aTrackInfo
[
i
].
interleaved
==
interleaved
)
{
return
i
;
}
}
...
...
@@ -833,8 +833,8 @@ int RtspPlayer::getTrackIndexByInterleaved(int interleaved) const{
}
int
RtspPlayer
::
getTrackIndexByTrackType
(
TrackType
trackType
)
const
{
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
if
(
m
_aTrackInfo
[
i
].
type
==
trackType
)
{
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
if
(
_aTrackInfo
[
i
].
type
==
trackType
)
{
return
i
;
}
}
...
...
src/Rtsp/RtspPlayer.h
查看文件 @
39baaebc
...
...
@@ -101,45 +101,45 @@ private:
bool
sendDescribe
();
bool
sendRtspRequest
(
const
string
&
cmd
,
const
string
&
url
,
const
StrCaseMap
&
header
=
StrCaseMap
());
private
:
string
m
_strUrl
;
unsigned
int
m
_uiTrackCnt
=
0
;
RtspTrack
m
_aTrackInfo
[
2
];
string
_strUrl
;
unsigned
int
_uiTrackCnt
=
0
;
RtspTrack
_aTrackInfo
[
2
];
function
<
void
(
const
Parser
&
)
>
m
_onHandshake
;
RtspMediaSource
::
PoolType
m
_pktPool
;
function
<
void
(
const
Parser
&
)
>
_onHandshake
;
RtspMediaSource
::
PoolType
_pktPool
;
uint8_t
*
m
_pucRtpBuf
=
nullptr
;
unsigned
int
m
_uiRtpBufLen
=
0
;
Socket
::
Ptr
m
_apUdpSock
[
2
];
uint8_t
*
_pucRtpBuf
=
nullptr
;
unsigned
int
_uiRtpBufLen
=
0
;
Socket
::
Ptr
_apUdpSock
[
2
];
//rtsp info
string
m
_strSession
;
unsigned
int
m
_uiCseq
=
1
;
uint32_t
m
_aui32SsrcErrorCnt
[
2
]
=
{
0
,
0
};
string
m
_strContentBase
;
eRtpType
m
_eType
=
RTP_TCP
;
string
_strSession
;
unsigned
int
_uiCseq
=
1
;
uint32_t
_aui32SsrcErrorCnt
[
2
]
=
{
0
,
0
};
string
_strContentBase
;
eRtpType
_eType
=
RTP_TCP
;
/* RTP包排序所用参数 */
uint16_t
m
_aui16LastSeq
[
2
]
=
{
0
,
0
};
uint64_t
m
_aui64SeqOkCnt
[
2
]
=
{
0
,
0
};
bool
m
_abSortStarted
[
2
]
=
{
0
,
0
};
map
<
uint32_t
,
RtpPacket
::
Ptr
>
m
_amapRtpSort
[
2
];
uint16_t
_aui16LastSeq
[
2
]
=
{
0
,
0
};
uint64_t
_aui64SeqOkCnt
[
2
]
=
{
0
,
0
};
bool
_abSortStarted
[
2
]
=
{
0
,
0
};
map
<
uint32_t
,
RtpPacket
::
Ptr
>
_amapRtpSort
[
2
];
/* 丢包率统计需要用到的参数 */
uint16_t
m
_aui16FirstSeq
[
2
]
=
{
0
,
0
};
uint16_t
m
_aui16NowSeq
[
2
]
=
{
0
,
0
};
uint64_t
m
_aui64RtpRecv
[
2
]
=
{
0
,
0
};
uint16_t
_aui16FirstSeq
[
2
]
=
{
0
,
0
};
uint16_t
_aui16NowSeq
[
2
]
=
{
0
,
0
};
uint64_t
_aui64RtpRecv
[
2
]
=
{
0
,
0
};
//超时功能实现
Ticker
m
_rtpTicker
;
std
::
shared_ptr
<
Timer
>
m
_pPlayTimer
;
std
::
shared_ptr
<
Timer
>
m
_pRtpTimer
;
Ticker
_rtpTicker
;
std
::
shared_ptr
<
Timer
>
_pPlayTimer
;
std
::
shared_ptr
<
Timer
>
_pRtpTimer
;
//心跳定时器
std
::
shared_ptr
<
Timer
>
m
_pBeatTimer
;
std
::
shared_ptr
<
Timer
>
_pBeatTimer
;
//播放进度控制
float
m
_fSeekTo
=
0
;
double
m
_adFistStamp
[
2
]
=
{
0
,
0
};
double
m
_adNowStamp
[
2
]
=
{
0
,
0
};
Ticker
m
_aNowStampTicker
[
2
];
float
_fSeekTo
=
0
;
double
_adFistStamp
[
2
]
=
{
0
,
0
};
double
_adNowStamp
[
2
]
=
{
0
,
0
};
Ticker
_aNowStampTicker
[
2
];
};
}
/* namespace Rtsp */
...
...
src/Rtsp/RtspPlayerImp.h
查看文件 @
39baaebc
...
...
@@ -65,33 +65,33 @@ public:
private
:
//派生类回调函数
bool
onCheckSDP
(
const
string
&
sdp
,
const
RtspTrack
*
track
,
int
trackCnt
)
override
{
m_pRtspMediaSrc
=
dynamic_pointer_cast
<
RtspMediaSource
>
(
m
_pMediaSrc
);
if
(
m
_pRtspMediaSrc
){
m
_pRtspMediaSrc
->
onGetSDP
(
sdp
);
_pRtspMediaSrc
=
dynamic_pointer_cast
<
RtspMediaSource
>
(
_pMediaSrc
);
if
(
_pRtspMediaSrc
){
_pRtspMediaSrc
->
onGetSDP
(
sdp
);
}
try
{
m
_parser
.
reset
(
new
RtpParser
(
sdp
));
_parser
.
reset
(
new
RtpParser
(
sdp
));
//todo(xzl) 修复此处
//
m_parser->setOnVideoCB(m
_onGetVideoCB);
//
m_parser->setOnAudioCB(m
_onGetAudioCB);
//
_parser->setOnVideoCB(
_onGetVideoCB);
//
_parser->setOnAudioCB(
_onGetAudioCB);
return
true
;
}
catch
(
std
::
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
return
m
_pRtspMediaSrc
?
true
:
false
;
return
_pRtspMediaSrc
?
true
:
false
;
}
}
void
onRecvRTP
(
const
RtpPacket
::
Ptr
&
rtppt
,
const
RtspTrack
&
track
)
override
{
if
(
m
_parser
){
m
_parser
->
inputRtp
(
rtppt
);
if
(
_parser
){
_parser
->
inputRtp
(
rtppt
);
}
if
(
m
_pRtspMediaSrc
){
m
_pRtspMediaSrc
->
onGetRTP
(
rtppt
,
true
);
if
(
_pRtspMediaSrc
){
_pRtspMediaSrc
->
onGetRTP
(
rtppt
,
true
);
}
}
private
:
RtspMediaSource
::
Ptr
m
_pRtspMediaSrc
;
RtspMediaSource
::
Ptr
_pRtspMediaSrc
;
};
...
...
src/Rtsp/RtspSession.cpp
查看文件 @
39baaebc
...
...
@@ -57,7 +57,7 @@ unordered_map<void *, std::shared_ptr<RtspSession> > RtspSession::g_mapPostter;
recursive_mutex
RtspSession
::
g_mtxGetter
;
//对quicktime上锁保护
recursive_mutex
RtspSession
::
g_mtxPostter
;
//对quicktime上锁保护
RtspSession
::
RtspSession
(
const
std
::
shared_ptr
<
ThreadPool
>
&
pTh
,
const
Socket
::
Ptr
&
pSock
)
:
TcpSession
(
pTh
,
pSock
),
m
_pSender
(
pSock
)
{
TcpSession
(
pTh
,
pSock
),
_pSender
(
pSock
)
{
//设置10秒发送缓存
pSock
->
setSendBufSecond
(
10
);
//设置15秒发送超时时间
...
...
@@ -67,8 +67,8 @@ RtspSession::RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::P
}
RtspSession
::~
RtspSession
()
{
if
(
m
_onDestory
)
{
m
_onDestory
();
if
(
_onDestory
)
{
_onDestory
();
}
DebugL
<<
get_peer_ip
();
}
...
...
@@ -80,34 +80,34 @@ void RtspSession::shutdown_l(bool close){
if
(
_sock
)
{
_sock
->
emitErr
(
SockException
(
Err_other
,
"self shutdown"
),
close
);
}
if
(
m
_bBase64need
&&
!
_sock
)
{
if
(
_bBase64need
&&
!
_sock
)
{
//quickTime http postter,and self is detached from tcpServer
lock_guard
<
recursive_mutex
>
lock
(
g_mtxPostter
);
g_mapPostter
.
erase
(
this
);
}
if
(
m
_pBrdcaster
)
{
m
_pBrdcaster
->
setDetachCB
(
this
,
nullptr
);
m
_pBrdcaster
.
reset
();
if
(
_pBrdcaster
)
{
_pBrdcaster
->
setDetachCB
(
this
,
nullptr
);
_pBrdcaster
.
reset
();
}
if
(
m
_pRtpReader
)
{
m
_pRtpReader
.
reset
();
if
(
_pRtpReader
)
{
_pRtpReader
.
reset
();
}
}
void
RtspSession
::
onError
(
const
SockException
&
err
)
{
TraceL
<<
err
.
getErrCode
()
<<
" "
<<
err
.
what
();
if
(
m
_bListenPeerUdpData
)
{
if
(
_bListenPeerUdpData
)
{
//取消UDP端口监听
UDPServer
::
Instance
().
stopListenPeer
(
get_peer_ip
().
data
(),
this
);
m
_bListenPeerUdpData
=
false
;
_bListenPeerUdpData
=
false
;
}
if
(
!
m_bBase64need
&&
m
_strSessionCookie
.
size
()
!=
0
)
{
if
(
!
_bBase64need
&&
_strSessionCookie
.
size
()
!=
0
)
{
//quickTime http getter
lock_guard
<
recursive_mutex
>
lock
(
g_mtxGetter
);
g_mapGetter
.
erase
(
m
_strSessionCookie
);
g_mapGetter
.
erase
(
_strSessionCookie
);
}
if
(
m
_bBase64need
&&
err
.
getErrCode
()
==
Err_eof
)
{
if
(
_bBase64need
&&
err
.
getErrCode
()
==
Err_eof
)
{
//quickTime http postter,正在发送rtp; QuickTime只是断开了请求连接,请继续发送rtp
_sock
=
nullptr
;
lock_guard
<
recursive_mutex
>
lock
(
g_mtxPostter
);
...
...
@@ -121,24 +121,24 @@ void RtspSession::onError(const SockException& err) {
//流量统计事件广播
GET_CONFIG_AND_REGISTER
(
uint32_t
,
iFlowThreshold
,
Broadcast
::
kFlowThreshold
);
if
(
m
_ui64TotalBytes
>
iFlowThreshold
*
1024
){
if
(
_ui64TotalBytes
>
iFlowThreshold
*
1024
){
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastFlowReport
,
m
_mediaInfo
,
m
_ui64TotalBytes
,
m
_ticker
.
createdTime
()
/
1000
,
_mediaInfo
,
_ui64TotalBytes
,
_ticker
.
createdTime
()
/
1000
,
*
this
);
}
}
void
RtspSession
::
onManager
()
{
if
(
m
_ticker
.
createdTime
()
>
15
*
1000
)
{
if
(
m
_strSession
.
size
()
==
0
)
{
if
(
_ticker
.
createdTime
()
>
15
*
1000
)
{
if
(
_strSession
.
size
()
==
0
)
{
WarnL
<<
"非法链接:"
<<
get_peer_ip
();
shutdown
();
return
;
}
}
if
(
m_rtpType
!=
PlayerBase
::
RTP_TCP
&&
m
_ticker
.
elapsedTime
()
>
15
*
1000
)
{
if
(
_rtpType
!=
PlayerBase
::
RTP_TCP
&&
_ticker
.
elapsedTime
()
>
15
*
1000
)
{
WarnL
<<
"RTSP会话超时:"
<<
get_peer_ip
();
shutdown
();
return
;
...
...
@@ -148,11 +148,11 @@ void RtspSession::onManager() {
int64_t
RtspSession
::
onRecvHeader
(
const
char
*
header
,
uint64_t
len
)
{
char
tmp
[
2
*
1024
];
m
_pcBuf
=
tmp
;
_pcBuf
=
tmp
;
m
_parser
.
Parse
(
header
);
//rtsp请求解析
string
strCmd
=
m
_parser
.
Method
();
//提取出请求命令字
m_iCseq
=
atoi
(
m
_parser
[
"CSeq"
].
data
());
_parser
.
Parse
(
header
);
//rtsp请求解析
string
strCmd
=
_parser
.
Method
();
//提取出请求命令字
_iCseq
=
atoi
(
_parser
[
"CSeq"
].
data
());
typedef
bool
(
RtspSession
::*
rtspCMDHandle
)();
static
unordered_map
<
string
,
rtspCMDHandle
>
g_mapCmd
;
...
...
@@ -180,15 +180,15 @@ int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) {
WarnL
<<
"cmd="
<<
strCmd
;
}
m
_parser
.
Clear
();
_parser
.
Clear
();
return
0
;
}
void
RtspSession
::
onRecv
(
const
Buffer
::
Ptr
&
pBuf
)
{
m
_ticker
.
resetTime
();
m
_ui64TotalBytes
+=
pBuf
->
size
();
if
(
m
_bBase64need
)
{
_ticker
.
resetTime
();
_ui64TotalBytes
+=
pBuf
->
size
();
if
(
_bBase64need
)
{
//quicktime 加密后的rtsp请求,需要解密
auto
str
=
decodeBase64
(
string
(
pBuf
->
data
(),
pBuf
->
size
()));
inputRtspOrRtcp
(
str
.
data
(),
str
.
size
());
...
...
@@ -198,7 +198,7 @@ void RtspSession::onRecv(const Buffer::Ptr &pBuf) {
}
void
RtspSession
::
inputRtspOrRtcp
(
const
char
*
data
,
uint64_t
len
)
{
if
(
data
[
0
]
==
'$'
&&
m
_rtpType
==
PlayerBase
::
RTP_TCP
){
if
(
data
[
0
]
==
'$'
&&
_rtpType
==
PlayerBase
::
RTP_TCP
){
//这是rtcp
return
;
}
...
...
@@ -207,24 +207,24 @@ void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) {
bool
RtspSession
::
handleReq_Options
()
{
//支持这些命令
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY,"
" PAUSE, SET_PARAMETER, GET_PARAMETER
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
SocketHelper
::
send
(
_pcBuf
,
n
);
return
true
;
}
bool
RtspSession
::
handleReq_Describe
()
{
{
//解析url获取媒体名称
m_strUrl
=
m
_parser
.
Url
();
m_mediaInfo
.
parse
(
m
_parser
.
FullUrl
());
_strUrl
=
_parser
.
Url
();
_mediaInfo
.
parse
(
_parser
.
FullUrl
());
}
if
(
!
findStream
())
{
...
...
@@ -235,7 +235,7 @@ bool RtspSession::handleReq_Describe() {
weak_ptr
<
RtspSession
>
weakSelf
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
//该请求中的认证信息
auto
authorization
=
m
_parser
[
"Authorization"
];
auto
authorization
=
_parser
[
"Authorization"
];
onGetRealm
invoker
=
[
weakSelf
,
authorization
](
const
string
&
realm
){
if
(
realm
.
empty
()){
//无需认证,回复sdp
...
...
@@ -248,7 +248,7 @@ bool RtspSession::handleReq_Describe() {
//广播是否需要认证事件
if
(
!
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastOnGetRtspRealm
,
m
_mediaInfo
,
_mediaInfo
,
invoker
,
*
this
)){
//无人监听此事件,说明无需认证
...
...
@@ -279,10 +279,10 @@ void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) {
"Content-Base: %s/
\r\n
"
"Content-Type: application/sdp
\r\n
"
"Content-Length: %d
\r\n\r\n
%s"
,
strongSelf
->
m
_iCseq
,
SERVER_NAME
,
strongSelf
->
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
strongSelf
->
m
_strUrl
.
data
(),
(
int
)
strongSelf
->
m_strSdp
.
length
(),
strongSelf
->
m
_strSdp
.
data
());
dateHeader
().
data
(),
strongSelf
->
_strUrl
.
data
(),
(
int
)
strongSelf
->
_strSdp
.
length
(),
strongSelf
->
_strSdp
.
data
());
strongSelf
->
SocketHelper
::
send
(
response
,
n
);
});
}
...
...
@@ -304,16 +304,16 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin
GET_CONFIG_AND_REGISTER
(
bool
,
authBasic
,
Config
::
Rtsp
::
kAuthBasic
);
if
(
!
authBasic
)
{
//我们需要客户端优先以md5方式认证
strongSelf
->
m
_strNonce
=
makeRandStr
(
32
);
strongSelf
->
_strNonce
=
makeRandStr
(
32
);
n
=
sprintf
(
response
,
"RTSP/1.0 401 Unauthorized
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"WWW-Authenticate: Digest realm=
\"
%s
\"
,nonce=
\"
%s
\"\r\n\r\n
"
,
strongSelf
->
m
_iCseq
,
SERVER_NAME
,
strongSelf
->
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
realm
.
data
(),
strongSelf
->
m
_strNonce
.
data
());
dateHeader
().
data
(),
realm
.
data
(),
strongSelf
->
_strNonce
.
data
());
}
else
{
//当然我们也支持base64认证,但是我们不建议这样做
n
=
sprintf
(
response
,
...
...
@@ -322,7 +322,7 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"WWW-Authenticate: Basic realm=
\"
%s
\"\r\n\r\n
"
,
strongSelf
->
m
_iCseq
,
SERVER_NAME
,
strongSelf
->
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
realm
.
data
());
}
...
...
@@ -359,7 +359,7 @@ void RtspSession::onAuthBasic(const weak_ptr<RtspSession> &weakSelf,const string
}
//此时必须提供明文密码
if
(
!
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastOnRtspAuth
,
strongSelf
->
m
_mediaInfo
,
user
,
true
,
invoker
,
*
strongSelf
)){
if
(
!
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastOnRtspAuth
,
strongSelf
->
_mediaInfo
,
user
,
true
,
invoker
,
*
strongSelf
)){
//表明该流需要认证却没监听请求密码事件,这一般是大意的程序所为,警告之
WarnL
<<
"请监听kBroadcastOnRtspAuth事件!"
;
//但是我们还是忽略认证以便完成播放
...
...
@@ -388,8 +388,8 @@ void RtspSession::onAuthDigest(const weak_ptr<RtspSession> &weakSelf,const strin
}
//check nonce
auto
nonce
=
map
[
"nonce"
];
if
(
strongSelf
->
m
_strNonce
!=
nonce
){
TraceL
<<
"nonce not mached:"
<<
nonce
<<
","
<<
strongSelf
->
m
_strNonce
;
if
(
strongSelf
->
_strNonce
!=
nonce
){
TraceL
<<
"nonce not mached:"
<<
nonce
<<
","
<<
strongSelf
->
_strNonce
;
onAuthFailed
(
weakSelf
,
realm
);
return
;
}
...
...
@@ -440,7 +440,7 @@ void RtspSession::onAuthDigest(const weak_ptr<RtspSession> &weakSelf,const strin
};
//此时可以提供明文或md5加密的密码
if
(
!
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastOnRtspAuth
,
strongSelf
->
m
_mediaInfo
,
username
,
false
,
invoker
,
*
strongSelf
)){
if
(
!
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastOnRtspAuth
,
strongSelf
->
_mediaInfo
,
username
,
false
,
invoker
,
*
strongSelf
)){
//表明该流需要认证却没监听请求密码事件,这一般是大意的程序所为,警告之
WarnL
<<
"请监听kBroadcastOnRtspAuth事件!"
;
//但是我们还是忽略认证以便完成播放
...
...
@@ -469,80 +469,80 @@ void RtspSession::onAuthUser(const weak_ptr<RtspSession> &weakSelf,const string
}
}
inline
void
RtspSession
::
send_StreamNotFound
()
{
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 404 Stream Not Found
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 404 Stream Not Found
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Connection: Close
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
SocketHelper
::
send
(
_pcBuf
,
n
);
}
inline
void
RtspSession
::
send_UnsupportedTransport
()
{
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 461 Unsupported Transport
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 461 Unsupported Transport
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Connection: Close
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
SocketHelper
::
send
(
_pcBuf
,
n
);
}
inline
void
RtspSession
::
send_SessionNotFound
()
{
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 454 Session Not Found
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 454 Session Not Found
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Connection: Close
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
SocketHelper
::
send
(
_pcBuf
,
n
);
/*40 Method Not Allowed*/
}
bool
RtspSession
::
handleReq_Setup
()
{
//处理setup命令,该函数可能进入多次
auto
controlSuffix
=
m_parser
.
FullUrl
().
substr
(
1
+
m
_parser
.
FullUrl
().
rfind
(
'/'
));
auto
controlSuffix
=
_parser
.
FullUrl
().
substr
(
1
+
_parser
.
FullUrl
().
rfind
(
'/'
));
int
trackIdx
=
getTrackIndexByControlSuffix
(
controlSuffix
);
if
(
trackIdx
==
-
1
)
{
//未找到相应track
return
false
;
}
RtspTrack
&
trackRef
=
m
_aTrackInfo
[
trackIdx
];
RtspTrack
&
trackRef
=
_aTrackInfo
[
trackIdx
];
if
(
trackRef
.
inited
)
{
//已经初始化过该Track
return
false
;
}
trackRef
.
inited
=
true
;
//现在初始化
auto
strongRing
=
m
_pWeakRing
.
lock
();
auto
strongRing
=
_pWeakRing
.
lock
();
if
(
!
strongRing
)
{
//the media source is released!
send_NotAcceptable
();
return
false
;
}
if
(
!
m
_bSetUped
){
m
_bSetUped
=
true
;
auto
strTransport
=
m
_parser
[
"Transport"
];
if
(
!
_bSetUped
){
_bSetUped
=
true
;
auto
strTransport
=
_parser
[
"Transport"
];
if
(
strTransport
.
find
(
"TCP"
)
!=
string
::
npos
){
m
_rtpType
=
PlayerBase
::
RTP_TCP
;
_rtpType
=
PlayerBase
::
RTP_TCP
;
}
else
if
(
strTransport
.
find
(
"multicast"
)
!=
string
::
npos
){
m
_rtpType
=
PlayerBase
::
RTP_MULTICAST
;
_rtpType
=
PlayerBase
::
RTP_MULTICAST
;
}
else
{
m
_rtpType
=
PlayerBase
::
RTP_UDP
;
_rtpType
=
PlayerBase
::
RTP_UDP
;
}
}
if
(
!
m_pRtpReader
&&
m
_rtpType
!=
PlayerBase
::
RTP_MULTICAST
)
{
m
_pRtpReader
=
strongRing
->
attach
();
if
(
!
_pRtpReader
&&
_rtpType
!=
PlayerBase
::
RTP_MULTICAST
)
{
_pRtpReader
=
strongRing
->
attach
();
weak_ptr
<
RtspSession
>
weakSelf
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
m
_pRtpReader
->
setDetachCB
([
weakSelf
]()
{
_pRtpReader
->
setDetachCB
([
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
...
...
@@ -551,9 +551,9 @@ bool RtspSession::handleReq_Setup() {
});
}
switch
(
m
_rtpType
)
{
switch
(
_rtpType
)
{
case
PlayerBase
:
:
RTP_TCP
:
{
int
iLen
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
int
iLen
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
...
...
@@ -562,13 +562,13 @@ bool RtspSession::handleReq_Setup() {
"Session: %s
\r\n
"
"x-Transport-Options: late-tolerance=1.400000
\r\n
"
"x-Dynamic-Rate: 1
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
trackRef
.
type
*
2
,
trackRef
.
type
*
2
+
1
,
printSSRC
(
trackRef
.
ssrc
).
data
(),
m
_strSession
.
data
());
SocketHelper
::
send
(
m
_pcBuf
,
iLen
);
_strSession
.
data
());
SocketHelper
::
send
(
_pcBuf
,
iLen
);
}
break
;
case
PlayerBase
:
:
RTP_UDP
:
{
...
...
@@ -587,44 +587,44 @@ bool RtspSession::handleReq_Setup() {
send_NotAcceptable
();
return
false
;
}
m
_apUdpSock
[
trackIdx
]
=
pSockRtp
;
_apUdpSock
[
trackIdx
]
=
pSockRtp
;
//设置客户端内网端口信息
string
strClientPort
=
FindField
(
m
_parser
[
"Transport"
].
data
(),
"client_port="
,
NULL
);
string
strClientPort
=
FindField
(
_parser
[
"Transport"
].
data
(),
"client_port="
,
NULL
);
uint16_t
ui16PeerPort
=
atoi
(
FindField
(
strClientPort
.
data
(),
NULL
,
"-"
).
data
());
struct
sockaddr_in
peerAddr
;
peerAddr
.
sin_family
=
AF_INET
;
peerAddr
.
sin_port
=
htons
(
ui16PeerPort
);
peerAddr
.
sin_addr
.
s_addr
=
inet_addr
(
get_peer_ip
().
data
());
bzero
(
&
(
peerAddr
.
sin_zero
),
sizeof
peerAddr
.
sin_zero
);
m
_apPeerUdpAddr
[
trackIdx
].
reset
((
struct
sockaddr
*
)
(
new
struct
sockaddr_in
(
peerAddr
)));
_apPeerUdpAddr
[
trackIdx
].
reset
((
struct
sockaddr
*
)
(
new
struct
sockaddr_in
(
peerAddr
)));
//尝试获取客户端nat映射地址
startListenPeerUdpData
();
//InfoL << "分配端口:" << srv_port;
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Transport: RTP/AVP/UDP;unicast;"
"client_port=%s;server_port=%d-%d;ssrc=%s;mode=play
\r\n
"
"Session: %s
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
strClientPort
.
data
(),
pSockRtp
->
get_local_port
(),
pSockRtcp
->
get_local_port
(),
printSSRC
(
trackRef
.
ssrc
).
data
(),
m
_strSession
.
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
_strSession
.
data
());
SocketHelper
::
send
(
_pcBuf
,
n
);
}
break
;
case
PlayerBase
:
:
RTP_MULTICAST
:
{
if
(
!
m
_pBrdcaster
){
m_pBrdcaster
=
RtpBroadCaster
::
get
(
get_local_ip
(),
m_mediaInfo
.
m_vhost
,
m_mediaInfo
.
m_app
,
m_mediaInfo
.
m
_streamid
);
if
(
!
m
_pBrdcaster
)
{
if
(
!
_pBrdcaster
){
_pBrdcaster
=
RtpBroadCaster
::
get
(
get_local_ip
(),
_mediaInfo
.
_vhost
,
_mediaInfo
.
_app
,
_mediaInfo
.
_streamid
);
if
(
!
_pBrdcaster
)
{
send_NotAcceptable
();
return
false
;
}
weak_ptr
<
RtspSession
>
weakSelf
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
m
_pBrdcaster
->
setDetachCB
(
this
,
[
weakSelf
]()
{
_pBrdcaster
->
setDetachCB
(
this
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
...
...
@@ -632,7 +632,7 @@ bool RtspSession::handleReq_Setup() {
strongSelf
->
safeShutdown
();
});
}
int
iSrvPort
=
m
_pBrdcaster
->
getPort
(
trackRef
.
type
);
int
iSrvPort
=
_pBrdcaster
->
getPort
(
trackRef
.
type
);
//我们用trackIdx区分rtp和rtcp包
auto
pSockRtcp
=
UDPServer
::
Instance
().
getSock
(
get_local_ip
().
data
(),
2
*
trackIdx
+
1
,
iSrvPort
+
1
);
if
(
!
pSockRtcp
)
{
...
...
@@ -643,20 +643,20 @@ bool RtspSession::handleReq_Setup() {
}
startListenPeerUdpData
();
GET_CONFIG_AND_REGISTER
(
uint32_t
,
udpTTL
,
MultiCast
::
kUdpTTL
);
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Transport: RTP/AVP;multicast;destination=%s;"
"source=%s;port=%d-%d;ttl=%d;ssrc=%s
\r\n
"
"Session: %s
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
m
_pBrdcaster
->
getIP
().
data
(),
dateHeader
().
data
(),
_pBrdcaster
->
getIP
().
data
(),
get_local_ip
().
data
(),
iSrvPort
,
pSockRtcp
->
get_local_port
(),
udpTTL
,
printSSRC
(
trackRef
.
ssrc
).
data
(),
m
_strSession
.
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
_strSession
.
data
());
SocketHelper
::
send
(
_pcBuf
,
n
);
}
break
;
default
:
...
...
@@ -666,39 +666,39 @@ bool RtspSession::handleReq_Setup() {
}
bool
RtspSession
::
handleReq_Play
()
{
if
(
m
_uiTrackCnt
==
0
)
{
if
(
_uiTrackCnt
==
0
)
{
//还没有Describe
return
false
;
}
if
(
m_parser
[
"Session"
]
!=
m
_strSession
)
{
if
(
_parser
[
"Session"
]
!=
_strSession
)
{
send_SessionNotFound
();
return
false
;
}
auto
strRange
=
m
_parser
[
"Range"
];
auto
strRange
=
_parser
[
"Range"
];
auto
onRes
=
[
this
,
strRange
](
const
string
&
err
){
bool
authSuccess
=
err
.
empty
();
char
response
[
2
*
1024
];
m
_pcBuf
=
response
;
if
(
!
authSuccess
&&
m
_bFirstPlay
){
_pcBuf
=
response
;
if
(
!
authSuccess
&&
_bFirstPlay
){
//第一次play是播放,否则是恢复播放。只对播放鉴权
int
n
=
sprintf
(
m
_pcBuf
,
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 401 Unauthorized
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Content-Type: text/plain
\r\n
"
"Content-Length: %d
\r\n\r\n
%s"
,
m
_iCseq
,
SERVER_NAME
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),(
int
)
err
.
size
(),
err
.
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
SocketHelper
::
send
(
_pcBuf
,
n
);
shutdown
();
return
;
}
if
(
m
_pRtpReader
){
if
(
_pRtpReader
){
weak_ptr
<
RtspSession
>
weakSelf
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
SockUtil
::
setNoDelay
(
m
_pSender
->
rawFD
(),
false
);
m
_pRtpReader
->
setReadCB
([
weakSelf
](
const
RtpPacket
::
Ptr
&
pack
)
{
SockUtil
::
setNoDelay
(
_pSender
->
rawFD
(),
false
);
_pRtpReader
->
setReadCB
([
weakSelf
](
const
RtpPacket
::
Ptr
&
pack
)
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
...
...
@@ -714,10 +714,10 @@ bool RtspSession::handleReq_Play() {
});
}
auto
pMediaSrc
=
m
_pMediaSrc
.
lock
();
auto
pMediaSrc
=
_pMediaSrc
.
lock
();
uint32_t
iStamp
=
0
;
if
(
pMediaSrc
){
if
(
strRange
.
size
()
&&
!
m
_bFirstPlay
)
{
if
(
strRange
.
size
()
&&
!
_bFirstPlay
)
{
auto
strStart
=
FindField
(
strRange
.
data
(),
"npt="
,
"-"
);
if
(
strStart
==
"now"
)
{
strStart
=
"0"
;
...
...
@@ -733,41 +733,41 @@ bool RtspSession::handleReq_Play() {
}
else
{
iStamp
=
pMediaSrc
->
getStamp
();
}
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
m
_aTrackInfo
[
i
];
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
_aTrackInfo
[
i
];
track
.
ssrc
=
pMediaSrc
->
getSsrc
(
track
.
type
);
track
.
seq
=
pMediaSrc
->
getSeqence
(
track
.
type
);
track
.
timeStamp
=
pMediaSrc
->
getTimestamp
(
track
.
type
);
}
}
m
_bFirstPlay
=
false
;
int
iLen
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
_bFirstPlay
=
false
;
int
iLen
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Session: %s
\r\n
"
"Range: npt=%.2f-
\r\n
"
"RTP-Info: "
,
m
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
m
_strSession
.
data
(),
iStamp
/
1000.0
);
"RTP-Info: "
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
_strSession
.
data
(),
iStamp
/
1000.0
);
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
m
_aTrackInfo
[
i
];
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
_aTrackInfo
[
i
];
if
(
track
.
inited
==
false
)
{
//还有track没有setup
shutdown
();
return
;
}
iLen
+=
sprintf
(
m
_pcBuf
+
iLen
,
"url=%s/%s;seq=%d;rtptime=%u,"
,
m
_strUrl
.
data
(),
track
.
controlSuffix
.
data
(),
track
.
seq
,
track
.
timeStamp
);
iLen
+=
sprintf
(
_pcBuf
+
iLen
,
"url=%s/%s;seq=%d;rtptime=%u,"
,
_strUrl
.
data
(),
track
.
controlSuffix
.
data
(),
track
.
seq
,
track
.
timeStamp
);
}
iLen
-=
1
;
(
m
_pcBuf
)[
iLen
]
=
'\0'
;
iLen
+=
sprintf
(
m
_pcBuf
+
iLen
,
"
\r\n\r\n
"
);
SocketHelper
::
send
(
m
_pcBuf
,
iLen
);
(
_pcBuf
)[
iLen
]
=
'\0'
;
iLen
+=
sprintf
(
_pcBuf
+
iLen
,
"
\r\n\r\n
"
);
SocketHelper
::
send
(
_pcBuf
,
iLen
);
//提高发送性能
(
*
this
)
<<
SocketFlags
(
kSockFlags
);
SockUtil
::
setNoDelay
(
m
_pSender
->
rawFD
(),
false
);
SockUtil
::
setNoDelay
(
_pSender
->
rawFD
(),
false
);
};
weak_ptr
<
RtspSession
>
weakSelf
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
...
...
@@ -784,7 +784,7 @@ bool RtspSession::handleReq_Play() {
onRes
(
err
);
});
};
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
m
_mediaInfo
,
invoker
,
*
this
);
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastMediaPlayed
,
_mediaInfo
,
invoker
,
*
this
);
if
(
!
flag
){
//该事件无人监听,默认不鉴权
onRes
(
""
);
...
...
@@ -793,40 +793,40 @@ bool RtspSession::handleReq_Play() {
}
bool
RtspSession
::
handleReq_Pause
()
{
if
(
m_parser
[
"Session"
]
!=
m
_strSession
)
{
if
(
_parser
[
"Session"
]
!=
_strSession
)
{
send_SessionNotFound
();
return
false
;
}
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Session: %s
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
m
_strSession
.
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
if
(
m
_pRtpReader
){
m
_pRtpReader
->
setReadCB
(
nullptr
);
"Session: %s
\r\n\r\n
"
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
_strSession
.
data
());
SocketHelper
::
send
(
_pcBuf
,
n
);
if
(
_pRtpReader
){
_pRtpReader
->
setReadCB
(
nullptr
);
}
return
true
;
}
bool
RtspSession
::
handleReq_Teardown
()
{
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Session: %s
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
m
_strSession
.
data
());
"Session: %s
\r\n\r\n
"
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
_strSession
.
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
SocketHelper
::
send
(
_pcBuf
,
n
);
TraceL
<<
"播放器断开连接!"
;
return
false
;
}
bool
RtspSession
::
handleReq_Get
()
{
m_strSessionCookie
=
m
_parser
[
"x-sessioncookie"
];
int
n
=
sprintf
(
m
_pcBuf
,
"HTTP/1.0 200 OK
\r\n
"
_strSessionCookie
=
_parser
[
"x-sessioncookie"
];
int
n
=
sprintf
(
_pcBuf
,
"HTTP/1.0 200 OK
\r\n
"
"%s"
"Connection: close
\r\n
"
"Cache-Control: no-store
\r\n
"
...
...
@@ -835,23 +835,23 @@ bool RtspSession::handleReq_Get() {
dateHeader
().
data
());
//注册GET
lock_guard
<
recursive_mutex
>
lock
(
g_mtxGetter
);
g_mapGetter
[
m
_strSessionCookie
]
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
//InfoL <<
m
_strSessionCookie;
SocketHelper
::
send
(
m
_pcBuf
,
n
);
g_mapGetter
[
_strSessionCookie
]
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
//InfoL << _strSessionCookie;
SocketHelper
::
send
(
_pcBuf
,
n
);
return
true
;
}
bool
RtspSession
::
handleReq_Post
()
{
lock_guard
<
recursive_mutex
>
lock
(
g_mtxGetter
);
string
sessioncookie
=
m
_parser
[
"x-sessioncookie"
];
string
sessioncookie
=
_parser
[
"x-sessioncookie"
];
//Poster 找到 Getter
auto
it
=
g_mapGetter
.
find
(
sessioncookie
);
if
(
it
==
g_mapGetter
.
end
())
{
//WarnL << sessioncookie;
return
false
;
}
m
_bBase64need
=
true
;
_bBase64need
=
true
;
//Poster 找到Getter的SOCK
auto
strongSession
=
it
->
second
.
lock
();
g_mapGetter
.
erase
(
sessioncookie
);
...
...
@@ -866,46 +866,46 @@ bool RtspSession::handleReq_Post() {
bool
RtspSession
::
handleReq_SET_PARAMETER
()
{
//TraceL<<endl;
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 200 OK
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Session: %s
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
m
_strSession
.
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
"Session: %s
\r\n\r\n
"
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
(),
_strSession
.
data
());
SocketHelper
::
send
(
_pcBuf
,
n
);
return
true
;
}
inline
void
RtspSession
::
send_NotAcceptable
()
{
int
n
=
sprintf
(
m
_pcBuf
,
"RTSP/1.0 406 Not Acceptable
\r\n
"
int
n
=
sprintf
(
_pcBuf
,
"RTSP/1.0 406 Not Acceptable
\r\n
"
"CSeq: %d
\r\n
"
"Server: %s-%0.2f(build in %s)
\r\n
"
"%s"
"Connection: Close
\r\n\r\n
"
,
m
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
"Connection: Close
\r\n\r\n
"
,
_iCseq
,
SERVER_NAME
,
RTSP_VERSION
,
RTSP_BUILDTIME
,
dateHeader
().
data
());
SocketHelper
::
send
(
m
_pcBuf
,
n
);
SocketHelper
::
send
(
_pcBuf
,
n
);
}
inline
bool
RtspSession
::
findStream
()
{
RtspMediaSource
::
Ptr
pMediaSrc
=
dynamic_pointer_cast
<
RtspMediaSource
>
(
MediaSource
::
find
(
RTSP_SCHEMA
,
m_mediaInfo
.
m_vhost
,
m_mediaInfo
.
m_app
,
m_mediaInfo
.
m
_streamid
)
);
dynamic_pointer_cast
<
RtspMediaSource
>
(
MediaSource
::
find
(
RTSP_SCHEMA
,
_mediaInfo
.
_vhost
,
_mediaInfo
.
_app
,
_mediaInfo
.
_streamid
)
);
if
(
!
pMediaSrc
)
{
WarnL
<<
"No such stream:"
<<
m_mediaInfo
.
m_vhost
<<
" "
<<
m_mediaInfo
.
m_app
<<
" "
<<
m_mediaInfo
.
m
_streamid
;
WarnL
<<
"No such stream:"
<<
_mediaInfo
.
_vhost
<<
" "
<<
_mediaInfo
.
_app
<<
" "
<<
_mediaInfo
.
_streamid
;
return
false
;
}
m
_strSdp
=
pMediaSrc
->
getSdp
();
m
_pWeakRing
=
pMediaSrc
->
getRing
();
_strSdp
=
pMediaSrc
->
getSdp
();
_pWeakRing
=
pMediaSrc
->
getRing
();
m_uiTrackCnt
=
parserSDP
(
m_strSdp
,
m
_aTrackInfo
);
if
(
m_uiTrackCnt
==
0
||
m
_uiTrackCnt
>
2
)
{
_uiTrackCnt
=
parserSDP
(
_strSdp
,
_aTrackInfo
);
if
(
_uiTrackCnt
==
0
||
_uiTrackCnt
>
2
)
{
return
false
;
}
m
_strSession
=
makeRandStr
(
12
);
m
_pMediaSrc
=
pMediaSrc
;
_strSession
=
makeRandStr
(
12
);
_pMediaSrc
=
pMediaSrc
;
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
m
_aTrackInfo
[
i
];
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
_aTrackInfo
[
i
];
track
.
ssrc
=
pMediaSrc
->
getSsrc
(
track
.
type
);
track
.
seq
=
pMediaSrc
->
getSeqence
(
track
.
type
);
track
.
timeStamp
=
pMediaSrc
->
getTimestamp
(
track
.
type
);
...
...
@@ -917,19 +917,19 @@ inline bool RtspSession::findStream() {
inline
void
RtspSession
::
sendRtpPacket
(
const
RtpPacket
::
Ptr
&
pkt
)
{
//InfoL<<(int)pkt.Interleaved;
switch
(
m
_rtpType
)
{
switch
(
_rtpType
)
{
case
PlayerBase
:
:
RTP_TCP
:
{
BufferRtp
::
Ptr
buffer
(
new
BufferRtp
(
pkt
));
send
(
buffer
);
#ifdef RTSP_SEND_RTCP
int
iTrackIndex
=
getTrackIndexByTrackId
(
pkt
.
interleaved
/
2
);
RtcpCounter
&
counter
=
m
_aRtcpCnt
[
iTrackIndex
];
RtcpCounter
&
counter
=
_aRtcpCnt
[
iTrackIndex
];
counter
.
pktCnt
+=
1
;
counter
.
octCount
+=
(
pkt
.
length
-
12
);
auto
&
m_ticker
=
m
_aRtcpTicker
[
iTrackIndex
];
if
(
m
_ticker
.
elapsedTime
()
>
5
*
1000
)
{
auto
&
_ticker
=
_aRtcpTicker
[
iTrackIndex
];
if
(
_ticker
.
elapsedTime
()
>
5
*
1000
)
{
//send rtcp every 5 second
m
_ticker
.
resetTime
();
_ticker
.
resetTime
();
counter
.
timeStamp
=
pkt
.
timeStamp
;
sendRTCP
();
}
...
...
@@ -938,17 +938,17 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
break
;
case
PlayerBase
:
:
RTP_UDP
:
{
int
iTrackIndex
=
getTrackIndexByTrackType
(
pkt
->
type
);
auto
pSock
=
m
_apUdpSock
[
iTrackIndex
].
lock
();
auto
pSock
=
_apUdpSock
[
iTrackIndex
].
lock
();
if
(
!
pSock
)
{
shutdown
();
return
;
}
auto
peerAddr
=
m
_apPeerUdpAddr
[
iTrackIndex
];
auto
peerAddr
=
_apPeerUdpAddr
[
iTrackIndex
];
if
(
!
peerAddr
)
{
return
;
}
BufferRtp
::
Ptr
buffer
(
new
BufferRtp
(
pkt
,
4
));
m
_ui64TotalBytes
+=
buffer
->
size
();
_ui64TotalBytes
+=
buffer
->
size
();
pSock
->
send
(
buffer
,
kSockFlags
,
peerAddr
.
get
());
}
break
;
...
...
@@ -960,35 +960,35 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
inline
void
RtspSession
::
onRcvPeerUdpData
(
int
iTrackIdx
,
const
Buffer
::
Ptr
&
pBuf
,
const
struct
sockaddr
&
addr
)
{
if
(
iTrackIdx
%
2
==
0
){
//这是rtp探测包
if
(
!
m
_bGotAllPeerUdp
){
if
(
!
_bGotAllPeerUdp
){
//还没有获取完整的rtp探测包
if
(
SockUtil
::
in_same_lan
(
get_local_ip
().
data
(),
get_peer_ip
().
data
())){
//在内网中,客户端上报的端口号是真实的,所以我们忽略udp打洞包
m
_bGotAllPeerUdp
=
true
;
_bGotAllPeerUdp
=
true
;
return
;
}
//设置真实的客户端nat映射端口号
m
_apPeerUdpAddr
[
iTrackIdx
/
2
].
reset
(
new
struct
sockaddr
(
addr
));
m
_abGotPeerUdp
[
iTrackIdx
/
2
]
=
true
;
m
_bGotAllPeerUdp
=
true
;
//先假设获取到完整的rtp探测包
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
if
(
!
m
_abGotPeerUdp
[
i
])
{
_apPeerUdpAddr
[
iTrackIdx
/
2
].
reset
(
new
struct
sockaddr
(
addr
));
_abGotPeerUdp
[
iTrackIdx
/
2
]
=
true
;
_bGotAllPeerUdp
=
true
;
//先假设获取到完整的rtp探测包
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
if
(
!
_abGotPeerUdp
[
i
])
{
//还有track没获取到rtp探测包
m
_bGotAllPeerUdp
=
false
;
_bGotAllPeerUdp
=
false
;
break
;
}
}
}
}
else
{
//这是rtcp心跳包,说明播放器还存活
m
_ticker
.
resetTime
();
_ticker
.
resetTime
();
//TraceL << "rtcp:" << (iTrackIdx-1)/2 ;
}
}
inline
void
RtspSession
::
startListenPeerUdpData
()
{
m
_bListenPeerUdpData
=
true
;
_bListenPeerUdpData
=
true
;
weak_ptr
<
RtspSession
>
weakSelf
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
UDPServer
::
Instance
().
listenPeer
(
get_peer_ip
().
data
(),
this
,
[
weakSelf
](
int
iTrackIdx
,
const
Buffer
::
Ptr
&
pBuf
,
struct
sockaddr
*
pPeerAddr
)
->
bool
{
...
...
@@ -1009,15 +1009,15 @@ inline void RtspSession::startListenPeerUdpData() {
}
inline
void
RtspSession
::
initSender
(
const
std
::
shared_ptr
<
RtspSession
>&
session
)
{
m
_pSender
=
session
->
_sock
;
_pSender
=
session
->
_sock
;
weak_ptr
<
RtspSession
>
weakSelf
=
dynamic_pointer_cast
<
RtspSession
>
(
shared_from_this
());
session
->
m
_onDestory
=
[
weakSelf
]()
{
session
->
_onDestory
=
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
}
//DebugL;
strongSelf
->
m
_pSender
->
setOnErr
([
weakSelf
](
const
SockException
&
err
)
{
strongSelf
->
_pSender
->
setOnErr
([
weakSelf
](
const
SockException
&
err
)
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
;
...
...
@@ -1033,9 +1033,9 @@ inline void RtspSession::sendRTCP() {
//DebugL;
uint8_t
aui8Rtcp
[
60
]
=
{
0
};
uint8_t
*
pui8Rtcp_SR
=
aui8Rtcp
+
4
,
*
pui8Rtcp_SDES
=
pui8Rtcp_SR
+
28
;
for
(
uint8_t
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
m
_aTrackInfo
[
i
];
auto
&
counter
=
m
_aRtcpCnt
[
i
];
for
(
uint8_t
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
auto
&
track
=
_aTrackInfo
[
i
];
auto
&
counter
=
_aRtcpCnt
[
i
];
aui8Rtcp
[
0
]
=
'$'
;
aui8Rtcp
[
1
]
=
track
.
trackId
*
2
+
1
;
...
...
src/Rtsp/RtspSession.h
查看文件 @
39baaebc
...
...
@@ -90,8 +90,8 @@ protected:
private
:
void
inputRtspOrRtcp
(
const
char
*
data
,
uint64_t
len
);
int
send
(
const
Buffer
::
Ptr
&
pkt
)
override
{
m
_ui64TotalBytes
+=
pkt
->
size
();
return
m
_pSender
->
send
(
pkt
,
_flags
);
_ui64TotalBytes
+=
pkt
->
size
();
return
_pSender
->
send
(
pkt
,
_flags
);
}
void
shutdown
()
override
;
void
shutdown_l
(
bool
close
);
...
...
@@ -123,16 +123,16 @@ private:
return
tmp
;
}
inline
int
getTrackIndexByTrackType
(
TrackType
type
)
{
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
if
(
type
==
m
_aTrackInfo
[
i
].
type
)
{
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
if
(
type
==
_aTrackInfo
[
i
].
type
)
{
return
i
;
}
}
return
-
1
;
}
inline
int
getTrackIndexByControlSuffix
(
const
string
&
controlSuffix
)
{
for
(
unsigned
int
i
=
0
;
i
<
m
_uiTrackCnt
;
i
++
)
{
if
(
controlSuffix
==
m
_aTrackInfo
[
i
].
controlSuffix
)
{
for
(
unsigned
int
i
=
0
;
i
<
_uiTrackCnt
;
i
++
)
{
if
(
controlSuffix
==
_aTrackInfo
[
i
].
controlSuffix
)
{
return
i
;
}
}
...
...
@@ -150,53 +150,53 @@ private:
static
void
onAuthDigest
(
const
weak_ptr
<
RtspSession
>
&
weakSelf
,
const
string
&
realm
,
const
string
&
strMd5
);
private
:
char
*
m
_pcBuf
=
nullptr
;
Ticker
m
_ticker
;
Parser
m
_parser
;
//rtsp解析类
string
m
_strUrl
;
string
m
_strSdp
;
string
m
_strSession
;
bool
m
_bFirstPlay
=
true
;
MediaInfo
m
_mediaInfo
;
std
::
weak_ptr
<
RtspMediaSource
>
m
_pMediaSrc
;
char
*
_pcBuf
=
nullptr
;
Ticker
_ticker
;
Parser
_parser
;
//rtsp解析类
string
_strUrl
;
string
_strSdp
;
string
_strSession
;
bool
_bFirstPlay
=
true
;
MediaInfo
_mediaInfo
;
std
::
weak_ptr
<
RtspMediaSource
>
_pMediaSrc
;
//RTP缓冲
weak_ptr
<
RingBuffer
<
RtpPacket
::
Ptr
>
>
m
_pWeakRing
;
RingBuffer
<
RtpPacket
::
Ptr
>::
RingReader
::
Ptr
m
_pRtpReader
;
weak_ptr
<
RingBuffer
<
RtpPacket
::
Ptr
>
>
_pWeakRing
;
RingBuffer
<
RtpPacket
::
Ptr
>::
RingReader
::
Ptr
_pRtpReader
;
PlayerBase
::
eRtpType
m
_rtpType
=
PlayerBase
::
RTP_UDP
;
bool
m
_bSetUped
=
false
;
int
m
_iCseq
=
0
;
unsigned
int
m
_uiTrackCnt
=
0
;
//媒体track个数
RtspTrack
m
_aTrackInfo
[
2
];
//媒体track信息,trackid idx 为数组下标
bool
m
_bGotAllPeerUdp
=
false
;
PlayerBase
::
eRtpType
_rtpType
=
PlayerBase
::
RTP_UDP
;
bool
_bSetUped
=
false
;
int
_iCseq
=
0
;
unsigned
int
_uiTrackCnt
=
0
;
//媒体track个数
RtspTrack
_aTrackInfo
[
2
];
//媒体track信息,trackid idx 为数组下标
bool
_bGotAllPeerUdp
=
false
;
#ifdef RTSP_SEND_RTCP
RtcpCounter
m
_aRtcpCnt
[
2
];
//rtcp统计,trackid idx 为数组下标
Ticker
m
_aRtcpTicker
[
2
];
//rtcp发送时间,trackid idx 为数组下标
RtcpCounter
_aRtcpCnt
[
2
];
//rtcp统计,trackid idx 为数组下标
Ticker
_aRtcpTicker
[
2
];
//rtcp发送时间,trackid idx 为数组下标
inline
void
sendRTCP
();
#endif
//RTP over UDP
bool
m
_abGotPeerUdp
[
2
]
=
{
false
,
false
};
//获取客户端udp端口计数
weak_ptr
<
Socket
>
m
_apUdpSock
[
2
];
//发送RTP的UDP端口,trackid idx 为数组下标
std
::
shared_ptr
<
struct
sockaddr
>
m
_apPeerUdpAddr
[
2
];
//播放器接收RTP的地址,trackid idx 为数组下标
bool
m
_bListenPeerUdpData
=
false
;
RtpBroadCaster
::
Ptr
m
_pBrdcaster
;
bool
_abGotPeerUdp
[
2
]
=
{
false
,
false
};
//获取客户端udp端口计数
weak_ptr
<
Socket
>
_apUdpSock
[
2
];
//发送RTP的UDP端口,trackid idx 为数组下标
std
::
shared_ptr
<
struct
sockaddr
>
_apPeerUdpAddr
[
2
];
//播放器接收RTP的地址,trackid idx 为数组下标
bool
_bListenPeerUdpData
=
false
;
RtpBroadCaster
::
Ptr
_pBrdcaster
;
//登录认证
string
m
_strNonce
;
string
_strNonce
;
//RTSP over HTTP
function
<
void
(
void
)
>
m
_onDestory
;
bool
m
_bBase64need
=
false
;
//是否需要base64解码
Socket
::
Ptr
m
_pSender
;
//回复rtsp时走的tcp通道,供quicktime用
function
<
void
(
void
)
>
_onDestory
;
bool
_bBase64need
=
false
;
//是否需要base64解码
Socket
::
Ptr
_pSender
;
//回复rtsp时走的tcp通道,供quicktime用
//quicktime 请求rtsp会产生两次tcp连接,
//一次发送 get 一次发送post,需要通过sessioncookie关联起来
string
m
_strSessionCookie
;
string
_strSessionCookie
;
//消耗的总流量
uint64_t
m
_ui64TotalBytes
=
0
;
uint64_t
_ui64TotalBytes
=
0
;
static
recursive_mutex
g_mtxGetter
;
//对quicktime上锁保护
static
recursive_mutex
g_mtxPostter
;
//对quicktime上锁保护
...
...
src/Rtsp/RtspToRtmpMediaSource.cpp
查看文件 @
39baaebc
...
...
@@ -43,7 +43,7 @@ RtspToRtmpMediaSource::RtspToRtmpMediaSource(const string &vhost,
const
string
&
id
,
bool
bEnableHls
,
bool
bEnableMp4
)
:
RtspMediaSource
(
vhost
,
app
,
id
),
m_bEnableHls
(
bEnableHls
),
m
_bEnableMp4
(
bEnableMp4
)
{
RtspMediaSource
(
vhost
,
app
,
id
),
_bEnableHls
(
bEnableHls
),
_bEnableMp4
(
bEnableMp4
)
{
}
RtspToRtmpMediaSource
::~
RtspToRtmpMediaSource
()
{
...
...
@@ -65,36 +65,36 @@ void RtspToRtmpMediaSource::makeVideoConfigPkt() {
rtmpPkt
->
strBuf
.
push_back
(
1
);
// version
//todo(xzl) 修复此处
string
m_sps
;
//= m
_pParser->getSps().substr(4);
string
m_pps
;
//= m
_pParser->getPps().substr(4);
//DebugL<<hexdump(
m_sps.data(), m
_sps.size());
rtmpPkt
->
strBuf
.
push_back
(
m
_sps
[
1
]);
// profile
rtmpPkt
->
strBuf
.
push_back
(
m
_sps
[
2
]);
// compat
rtmpPkt
->
strBuf
.
push_back
(
m
_sps
[
3
]);
// level
string
_sps
;
//=
_pParser->getSps().substr(4);
string
_pps
;
//=
_pParser->getPps().substr(4);
//DebugL<<hexdump(
_sps.data(),
_sps.size());
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
1
]);
// profile
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
2
]);
// compat
rtmpPkt
->
strBuf
.
push_back
(
_sps
[
3
]);
// level
rtmpPkt
->
strBuf
.
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)
uint16_t
size
=
m
_sps
.
size
();
uint16_t
size
=
_sps
.
size
();
size
=
htons
(
size
);
rtmpPkt
->
strBuf
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
strBuf
.
append
(
m
_sps
);
rtmpPkt
->
strBuf
.
append
(
_sps
);
/////////////pps
rtmpPkt
->
strBuf
.
push_back
(
1
);
// version
size
=
m
_pps
.
size
();
size
=
_pps
.
size
();
size
=
htons
(
size
);
rtmpPkt
->
strBuf
.
append
((
char
*
)
&
size
,
2
);
rtmpPkt
->
strBuf
.
append
(
m
_pps
);
rtmpPkt
->
strBuf
.
append
(
_pps
);
rtmpPkt
->
bodySize
=
rtmpPkt
->
strBuf
.
size
();
rtmpPkt
->
chunkId
=
CHUNK_VIDEO
;
rtmpPkt
->
streamId
=
STREAM_MEDIA
;
rtmpPkt
->
timeStamp
=
0
;
rtmpPkt
->
typeId
=
MSG_VIDEO
;
m
_pRtmpSrc
->
onGetMedia
(
rtmpPkt
);
_pRtmpSrc
->
onGetMedia
(
rtmpPkt
);
}
void
RtspToRtmpMediaSource
::
onGetH264
(
const
H264Frame
&
frame
)
{
if
(
m
_pRecorder
){
m
_pRecorder
->
inputH264
((
char
*
)
frame
.
data
(),
frame
.
size
(),
frame
.
timeStamp
,
frame
.
type
);
if
(
_pRecorder
){
_pRecorder
->
inputH264
((
char
*
)
frame
.
data
(),
frame
.
size
(),
frame
.
timeStamp
,
frame
.
type
);
}
uint8_t
nal_type
=
frame
.
data
()[
4
]
&
0x1F
;
int8_t
flags
=
7
;
//h.264
...
...
@@ -124,17 +124,17 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) {
rtmpPkt
->
streamId
=
STREAM_MEDIA
;
rtmpPkt
->
timeStamp
=
frame
.
timeStamp
;
rtmpPkt
->
typeId
=
MSG_VIDEO
;
m
_pRtmpSrc
->
onGetMedia
(
rtmpPkt
);
_pRtmpSrc
->
onGetMedia
(
rtmpPkt
);
}
void
RtspToRtmpMediaSource
::
onGetAAC
(
const
AACFrame
&
frame
)
{
if
(
m
_pRecorder
){
m
_pRecorder
->
inputAAC
((
char
*
)
frame
.
buffer
,
frame
.
aac_frame_length
,
frame
.
timeStamp
);
if
(
_pRecorder
){
_pRecorder
->
inputAAC
((
char
*
)
frame
.
buffer
,
frame
.
aac_frame_length
,
frame
.
timeStamp
);
}
RtmpPacket
::
Ptr
rtmpPkt
(
new
RtmpPacket
);
//////////header
uint8_t
is_config
=
false
;
rtmpPkt
->
strBuf
.
push_back
(
m
_ui8AudioFlags
);
rtmpPkt
->
strBuf
.
push_back
(
_ui8AudioFlags
);
rtmpPkt
->
strBuf
.
push_back
(
!
is_config
);
rtmpPkt
->
strBuf
.
append
((
char
*
)
frame
.
buffer
+
7
,
frame
.
aac_frame_length
-
7
);
...
...
@@ -143,15 +143,15 @@ void RtspToRtmpMediaSource::onGetAAC(const AACFrame& frame) {
rtmpPkt
->
streamId
=
STREAM_MEDIA
;
rtmpPkt
->
timeStamp
=
frame
.
timeStamp
;
rtmpPkt
->
typeId
=
MSG_AUDIO
;
m
_pRtmpSrc
->
onGetMedia
(
rtmpPkt
);
_pRtmpSrc
->
onGetMedia
(
rtmpPkt
);
}
void
RtspToRtmpMediaSource
::
makeAudioConfigPkt
()
{
//todo(xzl) 修复此处
#if 0
uint8_t flvStereoOrMono = (
m
_pParser->getAudioChannel() > 1);
uint8_t flvStereoOrMono = (_pParser->getAudioChannel() > 1);
uint8_t flvSampleRate;
switch (
m
_pParser->getAudioSampleRate()) {
switch (_pParser->getAudioSampleRate()) {
case 48000:
case 44100:
flvSampleRate = 3;
...
...
@@ -168,57 +168,57 @@ void RtspToRtmpMediaSource::makeAudioConfigPkt() {
flvSampleRate = 0;
break;
}
uint8_t flvSampleBit =
m
_pParser->getAudioSampleBit() == 16;
uint8_t flvSampleBit = _pParser->getAudioSampleBit() == 16;
uint8_t flvAudioType = 10; //aac
m
_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
RtmpPacket::Ptr rtmpPkt(new RtmpPacket);
//////////header
uint8_t is_config = true;
rtmpPkt->strBuf.push_back(
m
_ui8AudioFlags);
rtmpPkt->strBuf.push_back(_ui8AudioFlags);
rtmpPkt->strBuf.push_back(!is_config);
rtmpPkt->strBuf.append(
m
_pParser->getAudioCfg());
rtmpPkt->strBuf.append(_pParser->getAudioCfg());
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_AUDIO;
rtmpPkt->streamId = STREAM_MEDIA;
rtmpPkt->timeStamp = 0;
rtmpPkt->typeId = MSG_AUDIO;
m
_pRtmpSrc->onGetMedia(rtmpPkt);
_pRtmpSrc->onGetMedia(rtmpPkt);
#endif
}
void
RtspToRtmpMediaSource
::
makeMetaData
()
{
m
_pRtmpSrc
.
reset
(
new
RtmpMediaSource
(
getVhost
(),
getApp
(),
getId
()));
m_pRtmpSrc
->
setListener
(
m
_listener
);
_pRtmpSrc
.
reset
(
new
RtmpMediaSource
(
getVhost
(),
getApp
(),
getId
()));
_pRtmpSrc
->
setListener
(
_listener
);
AMFValue
metaData
(
AMF_OBJECT
);
metaData
.
set
(
"duration"
,
m
_pParser
->
getDuration
());
metaData
.
set
(
"duration"
,
_pParser
->
getDuration
());
metaData
.
set
(
"fileSize"
,
0
);
//todo(xzl) 修复此处
#if 0
if (
m
_pParser->containVideo()) {
metaData.set("width",
m
_pParser->getVideoWidth());
metaData.set("height",
m
_pParser->getVideoHeight());
if (_pParser->containVideo()) {
metaData.set("width", _pParser->getVideoWidth());
metaData.set("height", _pParser->getVideoHeight());
metaData.set("videocodecid", "avc1"); //h.264
metaData.set("videodatarate", 5000);
metaData.set("framerate",
m
_pParser->getVideoFps());
metaData.set("framerate", _pParser->getVideoFps());
makeVideoConfigPkt();
}
if (
m
_pParser->containAudio()) {
if (_pParser->containAudio()) {
metaData.set("audiocodecid", "mp4a"); //aac
metaData.set("audiodatarate", 160);
metaData.set("audiosamplerate",
m
_pParser->getAudioSampleRate());
metaData.set("audiosamplesize",
m
_pParser->getAudioSampleBit());
metaData.set("audiochannels",
m
_pParser->getAudioChannel());
metaData.set("stereo",
m
_pParser->getAudioChannel() > 1);
metaData.set("audiosamplerate", _pParser->getAudioSampleRate());
metaData.set("audiosamplesize", _pParser->getAudioSampleBit());
metaData.set("audiochannels", _pParser->getAudioChannel());
metaData.set("stereo", _pParser->getAudioChannel() > 1);
makeAudioConfigPkt();
}
#endif
m
_pRtmpSrc
->
onGetMetaData
(
metaData
);
_pRtmpSrc
->
onGetMetaData
(
metaData
);
}
}
/* namespace Rtsp */
}
/* namespace ZL */
src/Rtsp/RtspToRtmpMediaSource.h
查看文件 @
39baaebc
...
...
@@ -52,11 +52,11 @@ public:
virtual
void
onGetSDP
(
const
string
&
strSdp
)
override
{
try
{
m
_pParser
.
reset
(
new
RtpParser
(
strSdp
));
m_pRecorder
.
reset
(
new
MediaRecorder
(
getVhost
(),
getApp
(),
getId
(),
m_pParser
,
m_bEnableHls
,
m
_bEnableMp4
));
_pParser
.
reset
(
new
RtpParser
(
strSdp
));
_pRecorder
.
reset
(
new
MediaRecorder
(
getVhost
(),
getApp
(),
getId
(),
_pParser
,
_bEnableHls
,
_bEnableMp4
));
//todo(xzl) 修复此处
//
m
_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1));
//
m
_pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
// _pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1));
// _pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
makeMetaData
();
}
catch
(
exception
&
ex
)
{
WarnL
<<
ex
.
what
();
...
...
@@ -64,22 +64,22 @@ public:
RtspMediaSource
::
onGetSDP
(
strSdp
);
}
virtual
void
onGetRTP
(
const
RtpPacket
::
Ptr
&
pRtppkt
,
bool
bKeyPos
)
override
{
if
(
m
_pParser
)
{
bKeyPos
=
m
_pParser
->
inputRtp
(
pRtppkt
);
if
(
_pParser
)
{
bKeyPos
=
_pParser
->
inputRtp
(
pRtppkt
);
}
RtspMediaSource
::
onGetRTP
(
pRtppkt
,
bKeyPos
);
}
int
readerCount
(){
return
getRing
()
->
readerCount
()
+
(
m_pRtmpSrc
?
m
_pRtmpSrc
->
getRing
()
->
readerCount
()
:
0
);
return
getRing
()
->
readerCount
()
+
(
_pRtmpSrc
?
_pRtmpSrc
->
getRing
()
->
readerCount
()
:
0
);
}
void
updateTimeStamp
(
uint32_t
uiStamp
)
{
for
(
auto
&
pr
:
m
_mapTracks
)
{
for
(
auto
&
pr
:
_mapTracks
)
{
switch
(
pr
.
second
.
type
)
{
case
TrackAudio
:
{
//todo(xzl) 修复此处
// pr.second.timeStamp = uiStamp * (
m
_pParser->getAudioSampleRate() / 1000.0);
// pr.second.timeStamp = uiStamp * (_pParser->getAudioSampleRate() / 1000.0);
}
break
;
case
TrackVideo
:
{
...
...
@@ -100,12 +100,12 @@ private:
void
makeAudioConfigPkt
();
void
makeMetaData
();
private
:
RtpParser
::
Ptr
m
_pParser
;
RtmpMediaSource
::
Ptr
m
_pRtmpSrc
;
uint8_t
m
_ui8AudioFlags
=
0
;
MediaRecorder
::
Ptr
m
_pRecorder
;
bool
m
_bEnableHls
;
bool
m
_bEnableMp4
;
RtpParser
::
Ptr
_pParser
;
RtmpMediaSource
::
Ptr
_pRtmpSrc
;
uint8_t
_ui8AudioFlags
=
0
;
MediaRecorder
::
Ptr
_pRecorder
;
bool
_bEnableHls
;
bool
_bEnableMp4
;
};
...
...
src/Rtsp/UDPServer.cpp
查看文件 @
39baaebc
...
...
@@ -48,10 +48,10 @@ UDPServer::~UDPServer() {
}
Socket
::
Ptr
UDPServer
::
getSock
(
const
char
*
strLocalIp
,
int
iTrackIndex
,
uint16_t
iLocalPort
)
{
lock_guard
<
mutex
>
lck
(
m
_mtxUpdSock
);
lock_guard
<
mutex
>
lck
(
_mtxUpdSock
);
string
strKey
=
StrPrinter
<<
strLocalIp
<<
":"
<<
iTrackIndex
<<
endl
;
auto
it
=
m
_mapUpdSock
.
find
(
strKey
);
if
(
it
==
m
_mapUpdSock
.
end
())
{
auto
it
=
_mapUpdSock
.
find
(
strKey
);
if
(
it
==
_mapUpdSock
.
end
())
{
Socket
::
Ptr
pSock
(
new
Socket
());
//InfoL<<localIp;
if
(
!
pSock
->
bindUdpSock
(
iLocalPort
,
strLocalIp
))
{
...
...
@@ -61,7 +61,7 @@ Socket::Ptr UDPServer::getSock(const char* strLocalIp, int iTrackIndex,uint16_t
pSock
->
setOnRead
(
bind
(
&
UDPServer
::
onRcvData
,
this
,
iTrackIndex
,
placeholders
::
_1
,
placeholders
::
_2
));
pSock
->
setOnErr
(
bind
(
&
UDPServer
::
onErr
,
this
,
strKey
,
placeholders
::
_1
));
m
_mapUpdSock
[
strKey
]
=
pSock
;
_mapUpdSock
[
strKey
]
=
pSock
;
DebugL
<<
strLocalIp
<<
" "
<<
pSock
->
get_local_port
()
<<
" "
<<
iTrackIndex
;
return
pSock
;
}
...
...
@@ -69,15 +69,15 @@ Socket::Ptr UDPServer::getSock(const char* strLocalIp, int iTrackIndex,uint16_t
}
void
UDPServer
::
listenPeer
(
const
char
*
strPeerIp
,
void
*
pSelf
,
const
onRecvData
&
cb
)
{
lock_guard
<
mutex
>
lck
(
m
_mtxDataHandler
);
auto
&
mapRef
=
m
_mapDataHandler
[
strPeerIp
];
lock_guard
<
mutex
>
lck
(
_mtxDataHandler
);
auto
&
mapRef
=
_mapDataHandler
[
strPeerIp
];
mapRef
.
emplace
(
pSelf
,
cb
);
}
void
UDPServer
::
stopListenPeer
(
const
char
*
strPeerIp
,
void
*
pSelf
)
{
lock_guard
<
mutex
>
lck
(
m
_mtxDataHandler
);
auto
it0
=
m
_mapDataHandler
.
find
(
strPeerIp
);
if
(
it0
==
m
_mapDataHandler
.
end
())
{
lock_guard
<
mutex
>
lck
(
_mtxDataHandler
);
auto
it0
=
_mapDataHandler
.
find
(
strPeerIp
);
if
(
it0
==
_mapDataHandler
.
end
())
{
return
;
}
auto
&
mapRef
=
it0
->
second
;
...
...
@@ -86,22 +86,22 @@ void UDPServer::stopListenPeer(const char* strPeerIp, void* pSelf) {
mapRef
.
erase
(
it1
);
}
if
(
mapRef
.
size
()
==
0
)
{
m
_mapDataHandler
.
erase
(
it0
);
_mapDataHandler
.
erase
(
it0
);
}
}
void
UDPServer
::
onErr
(
const
string
&
strKey
,
const
SockException
&
err
)
{
WarnL
<<
err
.
what
();
lock_guard
<
mutex
>
lck
(
m
_mtxUpdSock
);
m
_mapUpdSock
.
erase
(
strKey
);
lock_guard
<
mutex
>
lck
(
_mtxUpdSock
);
_mapUpdSock
.
erase
(
strKey
);
}
void
UDPServer
::
onRcvData
(
int
iTrackIndex
,
const
Buffer
::
Ptr
&
pBuf
,
struct
sockaddr
*
pPeerAddr
)
{
//TraceL << trackIndex;
struct
sockaddr_in
*
in
=
(
struct
sockaddr_in
*
)
pPeerAddr
;
string
peerIp
=
inet_ntoa
(
in
->
sin_addr
);
lock_guard
<
mutex
>
lck
(
m
_mtxDataHandler
);
auto
it0
=
m
_mapDataHandler
.
find
(
peerIp
);
if
(
it0
==
m
_mapDataHandler
.
end
())
{
lock_guard
<
mutex
>
lck
(
_mtxDataHandler
);
auto
it0
=
_mapDataHandler
.
find
(
peerIp
);
if
(
it0
==
_mapDataHandler
.
end
())
{
return
;
}
auto
&
mapRef
=
it0
->
second
;
...
...
@@ -112,7 +112,7 @@ void UDPServer::onRcvData(int iTrackIndex, const Buffer::Ptr &pBuf, struct socka
}
}
if
(
mapRef
.
size
()
==
0
)
{
m
_mapDataHandler
.
erase
(
it0
);
_mapDataHandler
.
erase
(
it0
);
}
}
...
...
src/Rtsp/UDPServer.h
查看文件 @
39baaebc
...
...
@@ -56,11 +56,11 @@ public:
private
:
void
onRcvData
(
int
iTrackId
,
const
Buffer
::
Ptr
&
pBuf
,
struct
sockaddr
*
pPeerAddr
);
void
onErr
(
const
string
&
strKey
,
const
SockException
&
err
);
unordered_map
<
string
,
Socket
::
Ptr
>
m
_mapUpdSock
;
mutex
m
_mtxUpdSock
;
unordered_map
<
string
,
Socket
::
Ptr
>
_mapUpdSock
;
mutex
_mtxUpdSock
;
unordered_map
<
string
,
unordered_map
<
void
*
,
onRecvData
>
>
m
_mapDataHandler
;
mutex
m
_mtxDataHandler
;
unordered_map
<
string
,
unordered_map
<
void
*
,
onRecvData
>
>
_mapDataHandler
;
mutex
_mtxDataHandler
;
};
}
/* namespace Rtsp */
...
...
src/Shell/ShellSession.cpp
查看文件 @
39baaebc
...
...
@@ -48,14 +48,14 @@ ShellSession::~ShellSession() {
void
ShellSession
::
onRecv
(
const
Buffer
::
Ptr
&
buf
)
{
//DebugL << hexdump(buf->data(), buf->size());
GET_CONFIG_AND_REGISTER
(
uint32_t
,
maxReqSize
,
Config
::
Shell
::
kMaxReqSize
);
if
(
m
_strRecvBuf
.
size
()
+
buf
->
size
()
>=
maxReqSize
)
{
if
(
_strRecvBuf
.
size
()
+
buf
->
size
()
>=
maxReqSize
)
{
WarnL
<<
"接收缓冲区溢出!"
;
shutdown
();
return
;
}
m
_beatTicker
.
resetTime
();
m
_strRecvBuf
.
append
(
buf
->
data
(),
buf
->
size
());
if
(
m
_strRecvBuf
.
find
(
"
\xff\xf4\xff\0
xfd
\x06
"
)
!=
std
::
string
::
npos
)
{
_beatTicker
.
resetTime
();
_strRecvBuf
.
append
(
buf
->
data
(),
buf
->
size
());
if
(
_strRecvBuf
.
find
(
"
\xff\xf4\xff\0
xfd
\x06
"
)
!=
std
::
string
::
npos
)
{
WarnL
<<
"收到Ctrl+C."
;
send
(
"
\033
[0m
\r\n
Bye bye!
\r\n
"
);
shutdown
();
...
...
@@ -63,9 +63,9 @@ void ShellSession::onRecv(const Buffer::Ptr&buf) {
}
size_t
index
;
string
line
;
while
((
index
=
m
_strRecvBuf
.
find
(
"
\r\n
"
))
!=
std
::
string
::
npos
)
{
line
=
m
_strRecvBuf
.
substr
(
0
,
index
);
m
_strRecvBuf
.
erase
(
0
,
index
+
2
);
while
((
index
=
_strRecvBuf
.
find
(
"
\r\n
"
))
!=
std
::
string
::
npos
)
{
line
=
_strRecvBuf
.
substr
(
0
,
index
);
_strRecvBuf
.
erase
(
0
,
index
+
2
);
if
(
!
onCommandLine
(
line
))
{
shutdown
();
return
;
...
...
@@ -74,7 +74,7 @@ void ShellSession::onRecv(const Buffer::Ptr&buf) {
}
void
ShellSession
::
onManager
()
{
if
(
m
_beatTicker
.
elapsedTime
()
>
1000
*
60
*
5
)
{
if
(
_beatTicker
.
elapsedTime
()
>
1000
*
60
*
5
)
{
//5 miniutes for alive
shutdown
();
return
;
...
...
@@ -82,7 +82,7 @@ void ShellSession::onManager() {
}
inline
bool
ShellSession
::
onCommandLine
(
const
string
&
line
)
{
auto
loginInterceptor
=
m
_loginInterceptor
;
auto
loginInterceptor
=
_loginInterceptor
;
if
(
loginInterceptor
)
{
bool
ret
=
loginInterceptor
(
line
);
return
ret
;
...
...
@@ -104,15 +104,15 @@ inline bool ShellSession::onCommandLine(const string& line) {
inline
void
ShellSession
::
pleaseInputUser
()
{
send
(
"
\033
[0m"
);
send
(
StrPrinter
<<
SERVER_NAME
<<
" login: "
<<
endl
);
m
_loginInterceptor
=
[
this
](
const
string
&
user_name
)
{
m
_strUserName
=
user_name
;
_loginInterceptor
=
[
this
](
const
string
&
user_name
)
{
_strUserName
=
user_name
;
pleaseInputPasswd
();
return
true
;
};
}
inline
void
ShellSession
::
pleaseInputPasswd
()
{
send
(
"Password:
\033
[8m"
);
m
_loginInterceptor
=
[
this
](
const
string
&
passwd
)
{
_loginInterceptor
=
[
this
](
const
string
&
passwd
)
{
auto
onAuth
=
[
this
](
const
string
&
errMessage
){
if
(
!
errMessage
.
empty
()){
//鉴权失败
...
...
@@ -120,7 +120,7 @@ inline void ShellSession::pleaseInputPasswd() {
<<
"
\033
[0mAuth failed("
<<
errMessage
<<
"), please try again.
\r\n
"
<<
m
_strUserName
<<
"@"
<<
SERVER_NAME
<<
_strUserName
<<
"@"
<<
SERVER_NAME
<<
"'s password:
\033
[8m"
<<
endl
);
return
;
...
...
@@ -130,7 +130,7 @@ inline void ShellSession::pleaseInputPasswd() {
send
(
StrPrinter
<<
"欢迎来到"
<<
SERVER_NAME
<<
", 你可输入
\"
help
\"
查看帮助.
\r\n
"
<<
endl
);
send
(
"-----------------------------------------
\r\n
"
);
printShellPrefix
();
m
_loginInterceptor
=
nullptr
;
_loginInterceptor
=
nullptr
;
};
weak_ptr
<
ShellSession
>
weakSelf
=
dynamic_pointer_cast
<
ShellSession
>
(
shared_from_this
());
...
...
@@ -148,7 +148,7 @@ inline void ShellSession::pleaseInputPasswd() {
});
};
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastShellLogin
,
m
_strUserName
,
passwd
,
invoker
,
*
this
);
auto
flag
=
NoticeCenter
::
Instance
().
emitEvent
(
Broadcast
::
kBroadcastShellLogin
,
_strUserName
,
passwd
,
invoker
,
*
this
);
if
(
!
flag
){
//如果无人监听shell登录事件,那么默认shell无法登录
onAuth
(
"please listen kBroadcastShellLogin event"
);
...
...
@@ -158,7 +158,7 @@ inline void ShellSession::pleaseInputPasswd() {
}
inline
void
ShellSession
::
printShellPrefix
()
{
send
(
StrPrinter
<<
m
_strUserName
<<
"@"
<<
SERVER_NAME
<<
"# "
<<
endl
);
send
(
StrPrinter
<<
_strUserName
<<
"@"
<<
SERVER_NAME
<<
"# "
<<
endl
);
}
}
/* namespace Shell */
...
...
src/Shell/ShellSession.h
查看文件 @
39baaebc
...
...
@@ -54,10 +54,10 @@ private:
inline
void
pleaseInputPasswd
();
inline
void
printShellPrefix
();
function
<
bool
(
const
string
&
)
>
m
_loginInterceptor
;
string
m
_strRecvBuf
;
Ticker
m
_beatTicker
;
string
m
_strUserName
;
function
<
bool
(
const
string
&
)
>
_loginInterceptor
;
string
_strRecvBuf
;
Ticker
_beatTicker
;
string
_strUserName
;
};
}
/* namespace Shell */
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论