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
a7e99b9d
Commit
a7e99b9d
authored
Aug 30, 2020
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
整理代码
parent
fbd711a6
显示空白字符变更
内嵌
并排
正在显示
10 个修改的文件
包含
433 行增加
和
414 行删除
+433
-414
src/Rtmp/RtmpPlayer.cpp
+24
-24
src/Rtmp/RtmpPlayer.h
+14
-14
src/Rtmp/RtmpProtocol.cpp
+5
-5
src/Rtmp/RtmpPusher.cpp
+114
-105
src/Rtmp/RtmpPusher.h
+31
-28
src/Rtsp/RtspPlayer.cpp
+2
-2
src/Rtsp/RtspPlayer.h
+1
-1
src/Rtsp/RtspPlayerImp.h
+31
-25
src/Rtsp/RtspPusher.cpp
+180
-176
src/Rtsp/RtspPusher.h
+31
-34
没有找到文件。
src/Rtmp/RtmpPlayer.cpp
查看文件 @
a7e99b9d
...
...
@@ -91,14 +91,14 @@ void RtmpPlayer::onErr(const SockException &ex){
onPlayResult_l
(
ex
,
!
_play_timer
);
}
void
RtmpPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
Completed
)
{
void
RtmpPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
_done
)
{
if
(
ex
.
getErrCode
()
==
Err_shutdown
)
{
//主动shutdown的,不触发回调
return
;
}
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
if
(
!
handshake
Completed
)
{
if
(
!
handshake
_done
)
{
//开始播放阶段
_play_timer
.
reset
();
//是否为性能测试模式
...
...
@@ -152,14 +152,14 @@ void RtmpPlayer::onConnect(const SockException &err){
});
}
void
RtmpPlayer
::
onRecv
(
const
Buffer
::
Ptr
&
pB
uf
){
void
RtmpPlayer
::
onRecv
(
const
Buffer
::
Ptr
&
b
uf
){
try
{
if
(
_benchmark_mode
&&
!
_play_timer
)
{
//在性能测试模式下,如果rtmp握手完毕后,不再解析rtmp包
_rtmp_recv_ticker
.
resetTime
();
return
;
}
onParseRtmp
(
pBuf
->
data
(),
pB
uf
->
size
());
onParseRtmp
(
buf
->
data
(),
b
uf
->
size
());
}
catch
(
exception
&
e
)
{
SockException
ex
(
Err_other
,
e
.
what
());
//定时器_pPlayTimer为空后表明握手结束了
...
...
@@ -226,21 +226,21 @@ inline void RtmpPlayer::send_play() {
addOnStatusCB
(
fun
);
}
inline
void
RtmpPlayer
::
send_pause
(
bool
bP
ause
)
{
inline
void
RtmpPlayer
::
send_pause
(
bool
p
ause
)
{
AMFEncoder
enc
;
enc
<<
"pause"
<<
++
_send_req_id
<<
nullptr
<<
bP
ause
;
enc
<<
"pause"
<<
++
_send_req_id
<<
nullptr
<<
p
ause
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
auto
fun
=
[
this
,
bP
ause
](
AMFValue
&
val
)
{
auto
fun
=
[
this
,
p
ause
](
AMFValue
&
val
)
{
//TraceL << "pause onStatus";
auto
level
=
val
[
"level"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
!=
"status"
)
{
if
(
!
bP
ause
)
{
if
(
!
p
ause
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"pause 恢复播放失败:"
<<
level
<<
" "
<<
code
<<
endl
);
}
}
else
{
_paused
=
bP
ause
;
if
(
!
bP
ause
)
{
_paused
=
p
ause
;
if
(
!
p
ause
)
{
onPlayResult_l
(
SockException
(
Err_success
,
"resum rtmp success"
),
true
);
}
else
{
//暂停播放
...
...
@@ -251,7 +251,7 @@ inline void RtmpPlayer::send_pause(bool bPause) {
addOnStatusCB
(
fun
);
_beat_timer
.
reset
();
if
(
bP
ause
)
{
if
(
p
ause
)
{
weak_ptr
<
RtmpPlayer
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPlayer
>
(
shared_from_this
());
_beat_timer
.
reset
(
new
Timer
((
*
this
)[
kBeatIntervalMS
].
as
<
int
>
()
/
1000.0
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
...
...
@@ -314,32 +314,32 @@ void RtmpPlayer::onCmd_onMetaData(AMFDecoder &dec) {
_metadata_got
=
true
;
}
void
RtmpPlayer
::
onStreamDry
(
uint32_t
stream_i
d
)
{
//TraceL << stream_i
d
;
void
RtmpPlayer
::
onStreamDry
(
uint32_t
stream_i
ndex
)
{
//TraceL << stream_i
ndex
;
onPlayResult_l
(
SockException
(
Err_other
,
"rtmp stream dry"
),
true
);
}
void
RtmpPlayer
::
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
packet
)
{
void
RtmpPlayer
::
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
chunk_data
)
{
_rtmp_recv_ticker
.
resetTime
();
if
(
!
_play_timer
)
{
//已经触发了onPlayResult事件,直接触发onMediaData事件
onMediaData
(
packet
);
onMediaData
(
chunk_data
);
return
;
}
if
(
packet
->
isCfgFrame
())
{
if
(
chunk_data
->
isCfgFrame
())
{
//输入配置帧以便初始化完成各个track
onMediaData
(
packet
);
onMediaData
(
chunk_data
);
}
else
{
//先触发onPlayResult事件,这个时候解码器才能初始化完毕
onPlayResult_l
(
SockException
(
Err_success
,
"play rtmp success"
),
false
);
//触发onPlayResult事件后,再把帧数据输入到解码器
onMediaData
(
packet
);
onMediaData
(
chunk_data
);
}
}
void
RtmpPlayer
::
onRtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
{
void
RtmpPlayer
::
onRtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
{
typedef
void
(
RtmpPlayer
::*
rtmp_func_ptr
)(
AMFDecoder
&
dec
);
static
unordered_map
<
string
,
rtmp_func_ptr
>
s_func_map
;
static
onceToken
token
([]()
{
...
...
@@ -349,12 +349,12 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
s_func_map
.
emplace
(
"onMetaData"
,
&
RtmpPlayer
::
onCmd_onMetaData
);
});
switch
(
chunk
D
ata
.
type_id
)
{
switch
(
chunk
_d
ata
.
type_id
)
{
case
MSG_CMD
:
case
MSG_CMD3
:
case
MSG_DATA
:
case
MSG_DATA3
:
{
AMFDecoder
dec
(
chunk
D
ata
.
buffer
,
0
);
AMFDecoder
dec
(
chunk
_d
ata
.
buffer
,
0
);
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
auto
it
=
s_func_map
.
find
(
type
);
if
(
it
!=
s_func_map
.
end
())
{
...
...
@@ -368,10 +368,10 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
case
MSG_AUDIO
:
case
MSG_VIDEO
:
{
auto
idx
=
chunk
D
ata
.
type_id
%
2
;
auto
idx
=
chunk
_d
ata
.
type_id
%
2
;
if
(
_now_stamp_ticker
[
idx
].
elapsedTime
()
>
500
)
{
//计算播放进度时间轴用
_now_stamp
[
idx
]
=
chunk
D
ata
.
time_stamp
;
_now_stamp
[
idx
]
=
chunk
_d
ata
.
time_stamp
;
}
if
(
!
_metadata_got
)
{
if
(
!
onCheckMeta
(
TitleMeta
().
getMetadata
()))
{
...
...
@@ -379,7 +379,7 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
}
_metadata_got
=
true
;
}
onMediaData_l
(
std
::
make_shared
<
RtmpPacket
>
(
std
::
move
(
chunk
D
ata
)));
onMediaData_l
(
std
::
make_shared
<
RtmpPacket
>
(
std
::
move
(
chunk
_d
ata
)));
break
;
}
...
...
src/Rtmp/RtmpPlayer.h
查看文件 @
a7e99b9d
...
...
@@ -41,34 +41,34 @@ public:
void
teardown
()
override
;
protected
:
virtual
bool
onCheckMeta
(
const
AMFValue
&
val
)
=
0
;
virtual
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunk
Data
)
=
0
;
virtual
bool
onCheckMeta
(
const
AMFValue
&
val
)
=
0
;
virtual
void
onMediaData
(
const
RtmpPacket
::
Ptr
&
chunk
_data
)
=
0
;
uint32_t
getProgressMilliSecond
()
const
;
void
seekToMilliSecond
(
uint32_t
ms
);
protected
:
void
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
chunk
D
ata
);
void
onMediaData_l
(
const
RtmpPacket
::
Ptr
&
chunk
_d
ata
);
//在获取config帧后才触发onPlayResult_l(而不是收到play命令回复),所以此时所有track都初始化完毕了
void
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
Completed
);
void
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
_done
);
//form Tcpclient
void
onRecv
(
const
Buffer
::
Ptr
&
pB
uf
)
override
;
void
onRecv
(
const
Buffer
::
Ptr
&
b
uf
)
override
;
void
onConnect
(
const
SockException
&
err
)
override
;
void
onErr
(
const
SockException
&
ex
)
override
;
//from RtmpProtocol
void
onRtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
override
;
void
onStreamDry
(
uint32_t
ui32StreamId
)
override
;
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
override
{
void
onRtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
override
;
void
onStreamDry
(
uint32_t
stream_index
)
override
;
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
override
{
send
(
buffer
);
}
template
<
typename
FUNC
>
inline
void
addOnResultCB
(
const
FUNC
&
func
)
{
void
addOnResultCB
(
const
FUNC
&
func
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx_on_result
);
_map_on_result
.
emplace
(
_send_req_id
,
func
);
}
template
<
typename
FUNC
>
inline
void
addOnStatusCB
(
const
FUNC
&
func
)
{
void
addOnStatusCB
(
const
FUNC
&
func
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx_on_status
);
_deque_on_status
.
emplace_back
(
func
);
}
...
...
@@ -77,10 +77,10 @@ protected:
void
onCmd_onStatus
(
AMFDecoder
&
dec
);
void
onCmd_onMetaData
(
AMFDecoder
&
dec
);
inline
void
send_connect
();
inline
void
send_createStream
();
inline
void
send_play
();
inline
void
send_pause
(
bool
bP
ause
);
void
send_connect
();
void
send_createStream
();
void
send_play
();
void
send_pause
(
bool
p
ause
);
private
:
string
_app
;
...
...
src/Rtmp/RtmpProtocol.cpp
查看文件 @
a7e99b9d
...
...
@@ -15,11 +15,6 @@
#include "Thread/ThreadPool.h"
using
namespace
toolkit
;
#ifdef ENABLE_OPENSSL
#include "Util/SSLBox.h"
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
#define C1_DIGEST_SIZE 32
#define C1_KEY_SIZE 128
#define C1_SCHEMA_SIZE 764
...
...
@@ -29,6 +24,11 @@ using namespace toolkit;
#define S2_FMS_KEY_SIZE 68
#define C1_OFFSET_SIZE 4
#ifdef ENABLE_OPENSSL
#include "Util/SSLBox.h"
#include <openssl/hmac.h>
#include <openssl/opensslv.h>
static
string
openssl_HMACsha256
(
const
void
*
key
,
unsigned
int
key_len
,
const
void
*
data
,
unsigned
int
data_len
){
std
::
shared_ptr
<
char
>
out
(
new
char
[
32
],
[](
char
*
ptr
)
{
delete
[]
ptr
;
});
unsigned
int
out_len
;
...
...
src/Rtmp/RtmpPusher.cpp
查看文件 @
a7e99b9d
...
...
@@ -18,141 +18,147 @@ using namespace mediakit::Client;
namespace
mediakit
{
RtmpPusher
::
RtmpPusher
(
const
EventPoller
::
Ptr
&
poller
,
const
RtmpMediaSource
::
Ptr
&
src
)
:
TcpClient
(
poller
){
_p
MediaSrc
=
src
;
RtmpPusher
::
RtmpPusher
(
const
EventPoller
::
Ptr
&
poller
,
const
RtmpMediaSource
::
Ptr
&
src
)
:
TcpClient
(
poller
){
_p
ublish_src
=
src
;
}
RtmpPusher
::~
RtmpPusher
()
{
teardown
();
DebugL
<<
endl
;
}
void
RtmpPusher
::
teardown
()
{
if
(
alive
())
{
_
strA
pp
.
clear
();
_str
Stream
.
clear
();
_
strTcU
rl
.
clear
();
_
a
pp
.
clear
();
_str
eam_id
.
clear
();
_
tc_u
rl
.
clear
();
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnResultCB
);
_map
OnResultCB
.
clear
();
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_result
);
_map
_on_result
.
clear
();
}
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnStatusCB
);
_d
qOnStatusCB
.
clear
();
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_status
);
_d
eque_on_status
.
clear
();
}
_p
PublishT
imer
.
reset
();
_p
ublish_t
imer
.
reset
();
reset
();
shutdown
(
SockException
(
Err_shutdown
,
"teardown"
));
shutdown
(
SockException
(
Err_shutdown
,
"teardown"
));
}
}
void
RtmpPusher
::
onPublishResult
(
const
SockException
&
ex
,
bool
handshakeCompleted
)
{
if
(
!
handshakeCompleted
){
void
RtmpPusher
::
onPublishResult
(
const
SockException
&
ex
,
bool
handshake_done
)
{
if
(
ex
.
getErrCode
()
==
Err_shutdown
)
{
//主动shutdown的,不触发回调
return
;
}
if
(
!
handshake_done
)
{
//播放结果回调
_p
PublishT
imer
.
reset
();
if
(
_onPublished
)
{
_on
P
ublished
(
ex
);
_p
ublish_t
imer
.
reset
();
if
(
_on_published
)
{
_on
_p
ublished
(
ex
);
}
}
else
{
//播放成功后异常断开回调
if
(
_onShutdown
)
{
_on
S
hutdown
(
ex
);
if
(
_on_shutdown
)
{
_on
_s
hutdown
(
ex
);
}
}
if
(
ex
)
{
if
(
ex
)
{
teardown
();
}
}
void
RtmpPusher
::
publish
(
const
string
&
strU
rl
)
{
void
RtmpPusher
::
publish
(
const
string
&
u
rl
)
{
teardown
();
string
strHost
=
FindField
(
strU
rl
.
data
(),
"://"
,
"/"
);
_
strApp
=
FindField
(
strUrl
.
data
(),
(
strHost
+
"/"
).
data
(),
"/"
);
_str
Stream
=
FindField
(
strUrl
.
data
(),
(
strHost
+
"/"
+
_strA
pp
+
"/"
).
data
(),
NULL
);
_
strTcUrl
=
string
(
"rtmp://"
)
+
strHost
+
"/"
+
_strA
pp
;
string
host_url
=
FindField
(
u
rl
.
data
(),
"://"
,
"/"
);
_
app
=
FindField
(
url
.
data
(),
(
host_url
+
"/"
).
data
(),
"/"
);
_str
eam_id
=
FindField
(
url
.
data
(),
(
host_url
+
"/"
+
_a
pp
+
"/"
).
data
(),
NULL
);
_
tc_url
=
string
(
"rtmp://"
)
+
host_url
+
"/"
+
_a
pp
;
if
(
!
_
strApp
.
size
()
||
!
_strStream
.
size
())
{
onPublishResult
(
SockException
(
Err_other
,
"rtmp url非法"
),
false
);
if
(
!
_
app
.
size
()
||
!
_stream_id
.
size
())
{
onPublishResult
(
SockException
(
Err_other
,
"rtmp url非法"
),
false
);
return
;
}
DebugL
<<
strHost
<<
" "
<<
_strApp
<<
" "
<<
_strStream
;
DebugL
<<
host_url
<<
" "
<<
_app
<<
" "
<<
_stream_id
;
auto
iPort
=
atoi
(
FindField
(
strHost
.
data
(),
":"
,
NULL
).
data
());
auto
iPort
=
atoi
(
FindField
(
host_url
.
data
(),
":"
,
NULL
).
data
());
if
(
iPort
<=
0
)
{
//rtmp 默认端口1935
iPort
=
1935
;
}
else
{
//服务器域名
strHost
=
FindField
(
strHost
.
data
(),
NULL
,
":"
);
host_url
=
FindField
(
host_url
.
data
(),
NULL
,
":"
);
}
weak_ptr
<
RtmpPusher
>
weakSelf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
float
publishTimeOutSec
=
(
*
this
)[
kTimeoutMS
].
as
<
int
>
()
/
1000.0
;
_p
PublishTimer
.
reset
(
new
Timer
(
publishTimeOutSec
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
_p
ublish_timer
.
reset
(
new
Timer
(
publishTimeOutSec
,
[
weakSelf
]()
{
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
)
{
return
false
;
}
strongSelf
->
onPublishResult
(
SockException
(
Err_timeout
,
"publish rtmp timeout"
),
false
);
strongSelf
->
onPublishResult
(
SockException
(
Err_timeout
,
"publish rtmp timeout"
),
false
);
return
false
;
},
getPoller
()));
},
getPoller
()));
if
(
!
(
*
this
)[
kNetAdapter
].
empty
())
{
if
(
!
(
*
this
)[
kNetAdapter
].
empty
())
{
setNetAdapter
((
*
this
)[
kNetAdapter
]);
}
startConnect
(
strHost
,
iPort
);
startConnect
(
host_url
,
iPort
);
}
void
RtmpPusher
::
onErr
(
const
SockException
&
ex
){
//定时器_pPublishTimer为空后表明握手结束了
onPublishResult
(
ex
,
!
_pPublishT
imer
);
onPublishResult
(
ex
,
!
_publish_t
imer
);
}
void
RtmpPusher
::
onConnect
(
const
SockException
&
err
){
if
(
err
)
{
onPublishResult
(
err
,
false
);
if
(
err
)
{
onPublishResult
(
err
,
false
);
return
;
}
//推流器不需要多大的接收缓存,节省内存占用
_sock
->
setReadBuffer
(
std
::
make_shared
<
BufferRaw
>
(
1
*
1024
));
weak_ptr
<
RtmpPusher
>
weak
S
elf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
startClientSession
([
weak
Self
]()
{
auto
strong
Self
=
weakS
elf
.
lock
();
if
(
!
strongS
elf
)
{
weak_ptr
<
RtmpPusher
>
weak
_s
elf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
startClientSession
([
weak
_self
]()
{
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
!
strong_s
elf
)
{
return
;
}
strong
S
elf
->
sendChunkSize
(
60000
);
strong
S
elf
->
send_connect
();
strong
_s
elf
->
sendChunkSize
(
60000
);
strong
_s
elf
->
send_connect
();
});
}
void
RtmpPusher
::
onRecv
(
const
Buffer
::
Ptr
&
pBuf
){
void
RtmpPusher
::
onRecv
(
const
Buffer
::
Ptr
&
buf
){
try
{
onParseRtmp
(
pBuf
->
data
(),
pB
uf
->
size
());
onParseRtmp
(
buf
->
data
(),
b
uf
->
size
());
}
catch
(
exception
&
e
)
{
SockException
ex
(
Err_other
,
e
.
what
());
//定时器_pPublishTimer为空后表明握手结束了
onPublishResult
(
ex
,
!
_pPublishT
imer
);
onPublishResult
(
ex
,
!
_publish_t
imer
);
}
}
inline
void
RtmpPusher
::
send_connect
()
{
AMFValue
obj
(
AMF_OBJECT
);
obj
.
set
(
"app"
,
_
strA
pp
);
obj
.
set
(
"app"
,
_
a
pp
);
obj
.
set
(
"type"
,
"nonprivate"
);
obj
.
set
(
"tcUrl"
,
_
strTcU
rl
);
obj
.
set
(
"swfUrl"
,
_
strTcU
rl
);
obj
.
set
(
"tcUrl"
,
_
tc_u
rl
);
obj
.
set
(
"swfUrl"
,
_
tc_u
rl
);
sendInvoke
(
"connect"
,
obj
);
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
addOnResultCB
([
this
](
AMFDecoder
&
dec
)
{
//TraceL << "connect result";
dec
.
load
<
AMFValue
>
();
auto
val
=
dec
.
load
<
AMFValue
>
();
auto
level
=
val
[
"level"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"connect 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
if
(
level
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"connect 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
}
send_createStream
();
});
...
...
@@ -161,23 +167,24 @@ inline void RtmpPusher::send_connect() {
inline
void
RtmpPusher
::
send_createStream
()
{
AMFValue
obj
(
AMF_NULL
);
sendInvoke
(
"createStream"
,
obj
);
addOnResultCB
([
this
](
AMFDecoder
&
dec
){
addOnResultCB
([
this
](
AMFDecoder
&
dec
)
{
//TraceL << "createStream result";
dec
.
load
<
AMFValue
>
();
_stream_index
=
dec
.
load
<
int
>
();
send_publish
();
});
}
inline
void
RtmpPusher
::
send_publish
()
{
AMFEncoder
enc
;
enc
<<
"publish"
<<
++
_send_req_id
<<
nullptr
<<
_str
Stream
<<
_strApp
;
enc
<<
"publish"
<<
++
_send_req_id
<<
nullptr
<<
_str
eam_id
<<
_app
;
sendRequest
(
MSG_CMD
,
enc
.
data
());
addOnStatusCB
([
this
](
AMFValue
&
val
)
{
auto
level
=
val
[
"level"
].
as_string
();
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"publish 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
if
(
level
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"publish 失败:"
<<
level
<<
" "
<<
code
<<
endl
);
}
//start send media
send_metaData
();
...
...
@@ -185,7 +192,7 @@ inline void RtmpPusher::send_publish() {
}
inline
void
RtmpPusher
::
send_metaData
(){
auto
src
=
_p
MediaS
rc
.
lock
();
auto
src
=
_p
ublish_s
rc
.
lock
();
if
(
!
src
)
{
throw
std
::
runtime_error
(
"the media source was released"
);
}
...
...
@@ -194,42 +201,42 @@ inline void RtmpPusher::send_metaData(){
enc
<<
"@setDataFrame"
<<
"onMetaData"
<<
src
->
getMetaData
();
sendRequest
(
MSG_DATA
,
enc
.
data
());
src
->
getConfigFrame
([
&
](
const
RtmpPacket
::
Ptr
&
pkt
){
sendRtmp
(
pkt
->
type_id
,
_stream_index
,
pkt
,
pkt
->
time_stamp
,
pkt
->
chunk_id
);
src
->
getConfigFrame
([
&
](
const
RtmpPacket
::
Ptr
&
pkt
)
{
sendRtmp
(
pkt
->
type_id
,
_stream_index
,
pkt
,
pkt
->
time_stamp
,
pkt
->
chunk_id
);
});
_
pRtmpR
eader
=
src
->
getRing
()
->
attach
(
getPoller
());
weak_ptr
<
RtmpPusher
>
weak
S
elf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
_
pRtmpReader
->
setReadCB
([
weakSelf
](
const
RtmpMediaSource
::
RingDataType
&
pkt
)
{
auto
strong
Self
=
weakS
elf
.
lock
();
if
(
!
strongS
elf
)
{
_
rtmp_r
eader
=
src
->
getRing
()
->
attach
(
getPoller
());
weak_ptr
<
RtmpPusher
>
weak
_s
elf
=
dynamic_pointer_cast
<
RtmpPusher
>
(
shared_from_this
());
_
rtmp_reader
->
setReadCB
([
weak_self
](
const
RtmpMediaSource
::
RingDataType
&
pkt
)
{
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
!
strong_s
elf
)
{
return
;
}
int
i
=
0
;
int
size
=
pkt
->
size
();
strong
S
elf
->
setSendFlushFlag
(
false
);
pkt
->
for_each
([
&
](
const
RtmpPacket
::
Ptr
&
rtmp
){
if
(
++
i
==
size
)
{
strong
S
elf
->
setSendFlushFlag
(
true
);
strong
_s
elf
->
setSendFlushFlag
(
false
);
pkt
->
for_each
([
&
](
const
RtmpPacket
::
Ptr
&
rtmp
)
{
if
(
++
i
==
size
)
{
strong
_s
elf
->
setSendFlushFlag
(
true
);
}
strong
Self
->
sendRtmp
(
rtmp
->
type_id
,
strongS
elf
->
_stream_index
,
rtmp
,
rtmp
->
time_stamp
,
rtmp
->
chunk_id
);
strong
_self
->
sendRtmp
(
rtmp
->
type_id
,
strong_s
elf
->
_stream_index
,
rtmp
,
rtmp
->
time_stamp
,
rtmp
->
chunk_id
);
});
});
_
pRtmpReader
->
setDetachCB
([
weakSelf
]()
{
auto
strong
Self
=
weakS
elf
.
lock
();
if
(
strongSelf
)
{
strong
Self
->
onPublishResult
(
SockException
(
Err_other
,
"媒体源被释放"
),
!
strongSelf
->
_pPublishT
imer
);
_
rtmp_reader
->
setDetachCB
([
weak_self
]()
{
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
strong_self
)
{
strong
_self
->
onPublishResult
(
SockException
(
Err_other
,
"媒体源被释放"
),
!
strong_self
->
_publish_t
imer
);
}
});
onPublishResult
(
SockException
(
Err_success
,
"success"
),
false
);
onPublishResult
(
SockException
(
Err_success
,
"success"
),
false
);
//提升发送性能
setSocketFlags
();
}
void
RtmpPusher
::
setSocketFlags
(){
GET_CONFIG
(
int
,
mergeWriteMS
,
General
::
kMergeWriteMS
);
if
(
mergeWriteMS
>
0
)
{
if
(
mergeWriteMS
>
0
)
{
//提高发送性能
setSendFlags
(
SOCKET_DEFAULE_FLAGS
|
FLAG_MORE
);
SockUtil
::
setNoDelay
(
_sock
->
rawFD
(),
false
);
...
...
@@ -237,68 +244,70 @@ void RtmpPusher::setSocketFlags(){
}
void
RtmpPusher
::
onCmd_result
(
AMFDecoder
&
dec
){
auto
iReqI
d
=
dec
.
load
<
int
>
();
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnResultCB
);
auto
it
=
_map
OnResultCB
.
find
(
iReqI
d
);
if
(
it
!=
_mapOnResultCB
.
end
())
{
auto
req_i
d
=
dec
.
load
<
int
>
();
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_result
);
auto
it
=
_map
_on_result
.
find
(
req_i
d
);
if
(
it
!=
_map_on_result
.
end
())
{
it
->
second
(
dec
);
_map
OnResultCB
.
erase
(
it
);
}
else
{
_map
_on_result
.
erase
(
it
);
}
else
{
WarnL
<<
"unhandled _result"
;
}
}
void
RtmpPusher
::
onCmd_onStatus
(
AMFDecoder
&
dec
)
{
AMFValue
val
;
while
(
true
)
{
while
(
true
)
{
val
=
dec
.
load
<
AMFValue
>
();
if
(
val
.
type
()
==
AMF_OBJECT
)
{
if
(
val
.
type
()
==
AMF_OBJECT
)
{
break
;
}
}
if
(
val
.
type
()
!=
AMF_OBJECT
)
{
if
(
val
.
type
()
!=
AMF_OBJECT
)
{
throw
std
::
runtime_error
(
"onStatus:the result object was not found"
);
}
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnStatusCB
);
if
(
_dqOnStatusCB
.
size
())
{
_d
qOnStatusCB
.
front
()(
val
);
_d
qOnStatusCB
.
pop_front
();
}
else
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_status
);
if
(
_deque_on_status
.
size
())
{
_d
eque_on_status
.
front
()(
val
);
_d
eque_on_status
.
pop_front
();
}
else
{
auto
level
=
val
[
"level"
];
auto
code
=
val
[
"code"
].
as_string
();
if
(
level
.
type
()
==
AMF_STRING
)
{
if
(
level
.
as_string
()
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"onStatus 失败:"
<<
level
.
as_string
()
<<
" "
<<
code
<<
endl
);
if
(
level
.
type
()
==
AMF_STRING
)
{
if
(
level
.
as_string
()
!=
"status"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"onStatus 失败:"
<<
level
.
as_string
()
<<
" "
<<
code
<<
endl
);
}
}
}
}
void
RtmpPusher
::
onRtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
{
switch
(
chunk
D
ata
.
type_id
)
{
void
RtmpPusher
::
onRtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
{
switch
(
chunk
_d
ata
.
type_id
)
{
case
MSG_CMD
:
case
MSG_CMD3
:
{
typedef
void
(
RtmpPusher
::*
rtmpCMDHandle
)(
AMFDecoder
&
dec
);
static
unordered_map
<
string
,
rtmpCMDHandle
>
g_mapCmd
;
static
onceToken
token
([]()
{
g_mapCmd
.
emplace
(
"_error"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"_result"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"onStatus"
,
&
RtmpPusher
::
onCmd_onStatus
);
g_mapCmd
.
emplace
(
"_error"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"_result"
,
&
RtmpPusher
::
onCmd_result
);
g_mapCmd
.
emplace
(
"onStatus"
,
&
RtmpPusher
::
onCmd_onStatus
);
});
AMFDecoder
dec
(
chunk
D
ata
.
buffer
,
0
);
AMFDecoder
dec
(
chunk
_d
ata
.
buffer
,
0
);
std
::
string
type
=
dec
.
load
<
std
::
string
>
();
auto
it
=
g_mapCmd
.
find
(
type
);
if
(
it
!=
g_mapCmd
.
end
())
{
if
(
it
!=
g_mapCmd
.
end
())
{
auto
fun
=
it
->
second
;
(
this
->*
fun
)(
dec
);
}
else
{
}
else
{
WarnL
<<
"can not support cmd:"
<<
type
;
}
}
break
;
}
default
:
//WarnL << "unhandled message:" << (int) chunk
Data.type_id << hexdump(chunkData.buffer.data(), chunkD
ata.buffer.size());
//WarnL << "unhandled message:" << (int) chunk
_data.type_id << hexdump(chunk_data.buffer.data(), chunk_d
ata.buffer.size());
break
;
}
}
...
...
src/Rtmp/RtmpPusher.h
查看文件 @
a7e99b9d
...
...
@@ -18,46 +18,47 @@
namespace
mediakit
{
class
RtmpPusher
:
public
RtmpProtocol
,
public
TcpClient
,
public
PusherBase
{
class
RtmpPusher
:
public
RtmpProtocol
,
public
TcpClient
,
public
PusherBase
{
public
:
typedef
std
::
shared_ptr
<
RtmpPusher
>
Ptr
;
RtmpPusher
(
const
EventPoller
::
Ptr
&
poller
,
const
RtmpMediaSource
::
Ptr
&
src
);
virtual
~
RtmpPusher
();
void
publish
(
const
string
&
strUrl
)
override
;
~
RtmpPusher
()
override
;
void
publish
(
const
string
&
url
)
override
;
void
teardown
()
override
;
void
setOnPublished
(
const
Event
&
cb
)
override
{
_on
P
ublished
=
cb
;
_on
_p
ublished
=
cb
;
}
void
setOnShutdown
(
const
Event
&
cb
)
override
{
_on
S
hutdown
=
cb
;
_on
_s
hutdown
=
cb
;
}
protected
:
//for Tcpclient override
void
onRecv
(
const
Buffer
::
Ptr
&
pB
uf
)
override
;
void
onRecv
(
const
Buffer
::
Ptr
&
b
uf
)
override
;
void
onConnect
(
const
SockException
&
err
)
override
;
void
onErr
(
const
SockException
&
ex
)
override
;
//for RtmpProtocol override
void
onRtmpChunk
(
RtmpPacket
&
chunk
D
ata
)
override
;
void
onRtmpChunk
(
RtmpPacket
&
chunk
_d
ata
)
override
;
void
onSendRawData
(
const
Buffer
::
Ptr
&
buffer
)
override
{
send
(
buffer
);
}
private
:
void
onPublishResult
(
const
SockException
&
ex
,
bool
handshakeCompleted
);
void
onPublishResult
(
const
SockException
&
ex
,
bool
handshake_done
);
template
<
typename
FUN
>
inline
void
addOnResultCB
(
const
FUN
&
fun
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnResultCB
);
_map
OnResultCB
.
emplace
(
_send_req_id
,
fun
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_result
);
_map
_on_result
.
emplace
(
_send_req_id
,
fun
);
}
template
<
typename
FUN
>
inline
void
addOnStatusCB
(
const
FUN
&
fun
)
{
lock_guard
<
recursive_mutex
>
lck
(
_mtx
OnStatusCB
);
_d
qOnStatusCB
.
emplace_back
(
fun
);
lock_guard
<
recursive_mutex
>
lck
(
_mtx
_on_status
);
_d
eque_on_status
.
emplace_back
(
fun
);
}
void
onCmd_result
(
AMFDecoder
&
dec
);
...
...
@@ -69,23 +70,25 @@ private:
inline
void
send_publish
();
inline
void
send_metaData
();
void
setSocketFlags
();
private
:
string
_strApp
;
string
_strStream
;
string
_strTcUrl
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
_mapOnResultCB
;
recursive_mutex
_mtxOnResultCB
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
_dqOnStatusCB
;
recursive_mutex
_mtxOnStatusCB
;
//超时功能实现
std
::
shared_ptr
<
Timer
>
_pPublishTimer
;
//源
std
::
weak_ptr
<
RtmpMediaSource
>
_pMediaSrc
;
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_pRtmpReader
;
string
_app
;
string
_stream_id
;
string
_tc_url
;
recursive_mutex
_mtx_on_result
;
recursive_mutex
_mtx_on_status
;
deque
<
function
<
void
(
AMFValue
&
dec
)
>
>
_deque_on_status
;
unordered_map
<
int
,
function
<
void
(
AMFDecoder
&
dec
)
>
>
_map_on_result
;
//事件监听
Event
_onShutdown
;
Event
_onPublished
;
Event
_on_shutdown
;
Event
_on_published
;
//推流超时定时器
std
::
shared_ptr
<
Timer
>
_publish_timer
;
std
::
weak_ptr
<
RtmpMediaSource
>
_publish_src
;
RtmpMediaSource
::
RingType
::
RingReader
::
Ptr
_rtmp_reader
;
};
}
/* namespace mediakit */
...
...
src/Rtsp/RtspPlayer.cpp
查看文件 @
a7e99b9d
...
...
@@ -732,14 +732,14 @@ void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &rtp, const SdpTrack::Ptr &tra
}
}
void
RtspPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
Completed
)
{
void
RtspPlayer
::
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
_done
)
{
if
(
ex
.
getErrCode
()
==
Err_shutdown
)
{
//主动shutdown的,不触发回调
return
;
}
WarnL
<<
ex
.
getErrCode
()
<<
" "
<<
ex
.
what
();
if
(
!
handshake
Completed
)
{
if
(
!
handshake
_done
)
{
//开始播放阶段
_play_check_timer
.
reset
();
onPlayResult
(
ex
);
...
...
src/Rtsp/RtspPlayer.h
查看文件 @
a7e99b9d
...
...
@@ -87,7 +87,7 @@ protected:
private
:
void
onRecvRTP_l
(
const
RtpPacket
::
Ptr
&
rtp
,
const
SdpTrack
::
Ptr
&
track
);
void
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
Completed
);
void
onPlayResult_l
(
const
SockException
&
ex
,
bool
handshake
_done
);
int
getTrackIndexByInterleaved
(
int
interleaved
)
const
;
int
getTrackIndexByTrackType
(
TrackType
track_type
)
const
;
...
...
src/Rtsp/RtspPlayerImp.h
查看文件 @
a7e99b9d
...
...
@@ -25,46 +25,51 @@ using namespace toolkit;
namespace
mediakit
{
class
RtspPlayerImp
:
public
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>
{
class
RtspPlayerImp
:
public
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>
{
public
:
typedef
std
::
shared_ptr
<
RtspPlayerImp
>
Ptr
;
RtspPlayerImp
(
const
EventPoller
::
Ptr
&
poller
)
:
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>
(
poller
){}
virtual
~
RtspPlayerImp
(){
DebugL
<<
endl
;
};
float
getProgress
()
const
override
{
if
(
getDuration
()
>
0
){
RtspPlayerImp
(
const
EventPoller
::
Ptr
&
poller
)
:
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>
(
poller
)
{}
~
RtspPlayerImp
()
override
{
DebugL
<<
endl
;
}
float
getProgress
()
const
override
{
if
(
getDuration
()
>
0
)
{
return
getProgressMilliSecond
()
/
(
getDuration
()
*
1000
);
}
return
PlayerBase
::
getProgress
();
};
void
seekTo
(
float
fProgress
)
override
{
fProgress
=
MAX
(
float
(
0
),
MIN
(
fProgress
,
float
(
1
.
0
)));
}
void
seekTo
(
float
fProgress
)
override
{
fProgress
=
MAX
(
float
(
0
),
MIN
(
fProgress
,
float
(
1
.
0
)));
seekToMilliSecond
(
fProgress
*
getDuration
()
*
1000
);
};
}
private
:
//派生类回调函数
bool
onCheckSDP
(
const
string
&
sdp
)
override
{
_
pRtspMediaS
rc
=
dynamic_pointer_cast
<
RtspMediaSource
>
(
_pMediaSrc
);
if
(
_pRtspMediaSrc
)
{
_
pRtspMediaS
rc
->
setSdp
(
sdp
);
_
rtsp_media_s
rc
=
dynamic_pointer_cast
<
RtspMediaSource
>
(
_pMediaSrc
);
if
(
_rtsp_media_src
)
{
_
rtsp_media_s
rc
->
setSdp
(
sdp
);
}
_delegate
.
reset
(
new
RtspDemuxer
);
_delegate
->
loadSdp
(
sdp
);
return
true
;
}
void
onRecvRTP
(
const
RtpPacket
::
Ptr
&
rtp
,
const
SdpTrack
::
Ptr
&
track
)
override
{
if
(
_pRtspMediaSrc
)
{
if
(
_rtsp_media_src
)
{
// rtsp直接代理是无法判断该rtp是否是I帧,所以GOP缓存基本是无效的
// 为了减少内存使用,那么我们设置为一直关键帧以便清空GOP缓存
_
pRtspMediaSrc
->
onWrite
(
rtp
,
true
);
_
rtsp_media_src
->
onWrite
(
rtp
,
true
);
}
_delegate
->
inputRtp
(
rtp
);
if
(
_maxAnalysisMS
&&
_delegate
->
isInited
(
_maxAnalysisMS
))
{
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>::
onPlayResult
(
SockException
(
Err_success
,
"play rtsp success"
));
_max
AnalysisMS
=
0
;
if
(
_max_analysis_ms
&&
_delegate
->
isInited
(
_max_analysis_ms
))
{
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>::
onPlayResult
(
SockException
(
Err_success
,
"play rtsp success"
));
_max
_analysis_ms
=
0
;
}
}
...
...
@@ -74,17 +79,18 @@ private:
//如果超过这个时间还未获取成功,那么会强制触发onPlayResult事件(虽然此时有些track还未初始化成功)
void
onPlayResult
(
const
SockException
&
ex
)
override
{
//isInited判断条件:无超时
if
(
ex
||
_delegate
->
isInited
(
0
))
{
if
(
ex
||
_delegate
->
isInited
(
0
))
{
//已经初始化成功,说明sdp里面有完善的信息
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>::
onPlayResult
(
ex
);
}
else
{
PlayerImp
<
RtspPlayer
,
RtspDemuxer
>::
onPlayResult
(
ex
);
}
else
{
//还没初始化成功,说明sdp里面信息不完善,还有一些track未初始化成功
_max
AnalysisMS
=
(
*
this
)[
Client
::
kMaxAnalysisMS
];
_max
_analysis_ms
=
(
*
this
)[
Client
::
kMaxAnalysisMS
];
}
}
private
:
RtspMediaSource
::
Ptr
_pRtspMediaSrc
;
int
_maxAnalysisMS
=
0
;
int
_max_analysis_ms
=
0
;
RtspMediaSource
::
Ptr
_rtsp_media_src
;
};
}
/* namespace mediakit */
...
...
src/Rtsp/RtspPusher.cpp
查看文件 @
a7e99b9d
...
...
@@ -17,8 +17,8 @@ using namespace mediakit::Client;
namespace
mediakit
{
RtspPusher
::
RtspPusher
(
const
EventPoller
::
Ptr
&
poller
,
const
RtspMediaSource
::
Ptr
&
src
)
:
TcpClient
(
poller
)
{
_p
MediaS
rc
=
src
;
RtspPusher
::
RtspPusher
(
const
EventPoller
::
Ptr
&
poller
,
const
RtspMediaSource
::
Ptr
&
src
)
:
TcpClient
(
poller
)
{
_p
ush_s
rc
=
src
;
}
RtspPusher
::~
RtspPusher
()
{
...
...
@@ -28,30 +28,30 @@ RtspPusher::~RtspPusher() {
void
RtspPusher
::
teardown
()
{
if
(
alive
())
{
sendRtspRequest
(
"TEARDOWN"
,
_strContentB
ase
);
shutdown
(
SockException
(
Err_shutdown
,
"teardown"
));
sendRtspRequest
(
"TEARDOWN"
,
_content_b
ase
);
shutdown
(
SockException
(
Err_shutdown
,
"teardown"
));
}
reset
();
CLEAR_ARR
(
_
apUdpSock
);
_
rtspMd5N
once
.
clear
();
_r
tspR
ealm
.
clear
();
_
aTrackInfo
.
clear
();
_s
trSession
.
clear
();
_
strContentB
ase
.
clear
();
_s
trSession
.
clear
();
_
uiC
seq
=
1
;
_p
PublishT
imer
.
reset
();
_
pBeatT
imer
.
reset
();
_
pRtspR
eader
.
reset
();
_
aTrackInfo
.
clear
();
_on
Handshake
=
nullptr
;
CLEAR_ARR
(
_
udp_socks
);
_
n
once
.
clear
();
_realm
.
clear
();
_
track_vec
.
clear
();
_s
ession_id
.
clear
();
_
content_b
ase
.
clear
();
_s
ession_id
.
clear
();
_
c
seq
=
1
;
_p
ublish_t
imer
.
reset
();
_
beat_t
imer
.
reset
();
_
rtsp_r
eader
.
reset
();
_
track_vec
.
clear
();
_on
_res_func
=
nullptr
;
}
void
RtspPusher
::
publish
(
const
string
&
strUrl
)
{
void
RtspPusher
::
publish
(
const
string
&
url_str
)
{
RtspUrl
url
;
if
(
!
url
.
parse
(
strUrl
))
{
onPublishResult
(
SockException
(
Err_other
,
StrPrinter
<<
"illegal rtsp url:"
<<
strUrl
),
false
);
if
(
!
url
.
parse
(
url_str
))
{
onPublishResult
(
SockException
(
Err_other
,
StrPrinter
<<
"illegal rtsp url:"
<<
url_str
),
false
);
return
;
}
...
...
@@ -65,55 +65,60 @@ void RtspPusher::publish(const string &strUrl) {
(
*
this
)[
kRtspPwdIsMD5
]
=
false
;
}
_strUrl
=
strUrl
;
_eType
=
(
Rtsp
::
eRtpType
)(
int
)(
*
this
)[
kRtpType
];
DebugL
<<
url
.
_url
<<
" "
<<
(
url
.
_user
.
size
()
?
url
.
_user
:
"null"
)
<<
" "
<<
(
url
.
_passwd
.
size
()
?
url
.
_passwd
:
"null"
)
<<
" "
<<
_eType
;
_url
=
url_str
;
_rtp_type
=
(
Rtsp
::
eRtpType
)
(
int
)
(
*
this
)[
kRtpType
];
DebugL
<<
url
.
_url
<<
" "
<<
(
url
.
_user
.
size
()
?
url
.
_user
:
"null"
)
<<
" "
<<
(
url
.
_passwd
.
size
()
?
url
.
_passwd
:
"null"
)
<<
" "
<<
_rtp_type
;
weak_ptr
<
RtspPusher
>
weak
S
elf
=
dynamic_pointer_cast
<
RtspPusher
>
(
shared_from_this
());
float
publish
TimeOutS
ec
=
(
*
this
)[
kTimeoutMS
].
as
<
int
>
()
/
1000.0
;
_p
PublishTimer
.
reset
(
new
Timer
(
publishTimeOutSec
,
[
weakS
elf
]()
{
auto
strong
Self
=
weakS
elf
.
lock
();
if
(
!
strongS
elf
)
{
weak_ptr
<
RtspPusher
>
weak
_s
elf
=
dynamic_pointer_cast
<
RtspPusher
>
(
shared_from_this
());
float
publish
_timeout_s
ec
=
(
*
this
)[
kTimeoutMS
].
as
<
int
>
()
/
1000.0
;
_p
ublish_timer
.
reset
(
new
Timer
(
publish_timeout_sec
,
[
weak_s
elf
]()
{
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
!
strong_s
elf
)
{
return
false
;
}
strong
Self
->
onPublishResult
(
SockException
(
Err_timeout
,
"publish rtsp timeout"
),
false
);
strong
_self
->
onPublishResult
(
SockException
(
Err_timeout
,
"publish rtsp timeout"
),
false
);
return
false
;
},
getPoller
()));
},
getPoller
()));
if
(
!
(
*
this
)[
kNetAdapter
].
empty
())
{
if
(
!
(
*
this
)[
kNetAdapter
].
empty
())
{
setNetAdapter
((
*
this
)[
kNetAdapter
]);
}
startConnect
(
url
.
_host
,
url
.
_port
,
publish
TimeOutS
ec
);
startConnect
(
url
.
_host
,
url
.
_port
,
publish
_timeout_s
ec
);
}
void
RtspPusher
::
onPublishResult
(
const
SockException
&
ex
,
bool
handshakeCompleted
)
{
if
(
!
handshakeCompleted
){
void
RtspPusher
::
onPublishResult
(
const
SockException
&
ex
,
bool
handshake_done
)
{
if
(
ex
.
getErrCode
()
==
Err_shutdown
)
{
//主动shutdown的,不触发回调
return
;
}
if
(
!
handshake_done
)
{
//播放结果回调
_p
PublishT
imer
.
reset
();
if
(
_onPublished
)
{
_on
P
ublished
(
ex
);
_p
ublish_t
imer
.
reset
();
if
(
_on_published
)
{
_on
_p
ublished
(
ex
);
}
}
else
{
//播放成功后异常断开回调
if
(
_onShutdown
)
{
_on
S
hutdown
(
ex
);
if
(
_on_shutdown
)
{
_on
_s
hutdown
(
ex
);
}
}
if
(
ex
)
{
if
(
ex
)
{
teardown
();
}
}
void
RtspPusher
::
onErr
(
const
SockException
&
ex
)
{
//定时器_pPublishTimer为空后表明握手结束了
onPublishResult
(
ex
,
!
_pPublishT
imer
);
onPublishResult
(
ex
,
!
_publish_t
imer
);
}
void
RtspPusher
::
onConnect
(
const
SockException
&
err
)
{
if
(
err
)
{
onPublishResult
(
err
,
false
);
if
(
err
)
{
onPublishResult
(
err
,
false
);
return
;
}
//推流器不需要多大的接收缓存,节省内存占用
...
...
@@ -121,41 +126,40 @@ void RtspPusher::onConnect(const SockException &err) {
sendAnnounce
();
}
void
RtspPusher
::
onRecv
(
const
Buffer
::
Ptr
&
pB
uf
){
void
RtspPusher
::
onRecv
(
const
Buffer
::
Ptr
&
b
uf
){
try
{
input
(
pBuf
->
data
(),
pB
uf
->
size
());
input
(
buf
->
data
(),
b
uf
->
size
());
}
catch
(
exception
&
e
)
{
SockException
ex
(
Err_other
,
e
.
what
());
//定时器_pPublishTimer为空后表明握手结束了
onPublishResult
(
ex
,
!
_pPublishT
imer
);
onPublishResult
(
ex
,
!
_publish_t
imer
);
}
}
void
RtspPusher
::
onWholeRtspPacket
(
Parser
&
parser
)
{
decltype
(
_on
Handshake
)
fun
;
_on
Handshake
.
swap
(
fun
);
if
(
fun
)
{
fun
(
parser
);
decltype
(
_on
_res_func
)
func
;
_on
_res_func
.
swap
(
func
);
if
(
func
)
{
fun
c
(
parser
);
}
parser
.
Clear
();
}
void
RtspPusher
::
sendAnnounce
()
{
auto
src
=
_p
MediaS
rc
.
lock
();
auto
src
=
_p
ush_s
rc
.
lock
();
if
(
!
src
)
{
throw
std
::
runtime_error
(
"the media source was released"
);
}
//解析sdp
_sdp
P
arser
.
load
(
src
->
getSdp
());
_
aTrackInfo
=
_sdpP
arser
.
getAvailableTrack
();
_sdp
_p
arser
.
load
(
src
->
getSdp
());
_
track_vec
=
_sdp_p
arser
.
getAvailableTrack
();
if
(
_
aTrackInfo
.
empty
())
{
if
(
_
track_vec
.
empty
())
{
throw
std
::
runtime_error
(
"无有效的Sdp Track"
);
}
_on
Handshake
=
std
::
bind
(
&
RtspPusher
::
handleResAnnounce
,
this
,
placeholders
::
_1
);
sendRtspRequest
(
"ANNOUNCE"
,
_strUrl
,{},
src
->
getSdp
());
_on
_res_func
=
std
::
bind
(
&
RtspPusher
::
handleResAnnounce
,
this
,
placeholders
::
_1
);
sendRtspRequest
(
"ANNOUNCE"
,
_url
,
{},
src
->
getSdp
());
}
void
RtspPusher
::
handleResAnnounce
(
const
Parser
&
parser
)
{
...
...
@@ -165,9 +169,9 @@ void RtspPusher::handleResAnnounce(const Parser &parser) {
sendAnnounce
();
return
;
}
if
(
parser
.
Url
()
==
"302"
)
{
if
(
parser
.
Url
()
==
"302"
)
{
auto
newUrl
=
parser
[
"Location"
];
if
(
newUrl
.
empty
())
{
if
(
newUrl
.
empty
())
{
throw
std
::
runtime_error
(
"未找到Location字段(跳转url)"
);
}
publish
(
newUrl
);
...
...
@@ -176,45 +180,45 @@ void RtspPusher::handleResAnnounce(const Parser &parser) {
if
(
parser
.
Url
()
!=
"200"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"ANNOUNCE:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
());
}
_
strContentB
ase
=
parser
[
"Content-Base"
];
_
content_b
ase
=
parser
[
"Content-Base"
];
if
(
_strContentBase
.
empty
())
{
_
strContentBase
=
_strU
rl
;
if
(
_content_base
.
empty
())
{
_
content_base
=
_u
rl
;
}
if
(
_
strContentB
ase
.
back
()
==
'/'
)
{
_
strContentB
ase
.
pop_back
();
if
(
_
content_b
ase
.
back
()
==
'/'
)
{
_
content_b
ase
.
pop_back
();
}
sendSetup
(
0
);
}
bool
RtspPusher
::
handleAuthenticationFailure
(
const
string
&
params
S
tr
)
{
if
(
!
_rtspRealm
.
empty
())
{
bool
RtspPusher
::
handleAuthenticationFailure
(
const
string
&
params
_s
tr
)
{
if
(
!
_realm
.
empty
())
{
//已经认证过了
return
false
;
}
char
*
realm
=
new
char
[
params
S
tr
.
size
()];
char
*
nonce
=
new
char
[
params
S
tr
.
size
()];
char
*
stale
=
new
char
[
params
S
tr
.
size
()];
onceToken
token
(
nullptr
,
[
&
]()
{
char
*
realm
=
new
char
[
params
_s
tr
.
size
()];
char
*
nonce
=
new
char
[
params
_s
tr
.
size
()];
char
*
stale
=
new
char
[
params
_s
tr
.
size
()];
onceToken
token
(
nullptr
,
[
&
]()
{
delete
[]
realm
;
delete
[]
nonce
;
delete
[]
stale
;
});
if
(
sscanf
(
params
S
tr
.
data
(),
"Digest realm=
\"
%[^
\"
]
\"
, nonce=
\"
%[^
\"
]
\"
, stale=%[a-zA-Z]"
,
realm
,
nonce
,
stale
)
==
3
)
{
_r
tspRealm
=
(
const
char
*
)
realm
;
_
rtspMd5Nonce
=
(
const
char
*
)
nonce
;
if
(
sscanf
(
params
_s
tr
.
data
(),
"Digest realm=
\"
%[^
\"
]
\"
, nonce=
\"
%[^
\"
]
\"
, stale=%[a-zA-Z]"
,
realm
,
nonce
,
stale
)
==
3
)
{
_r
ealm
=
(
const
char
*
)
realm
;
_
nonce
=
(
const
char
*
)
nonce
;
return
true
;
}
if
(
sscanf
(
params
S
tr
.
data
(),
"Digest realm=
\"
%[^
\"
]
\"
, nonce=
\"
%[^
\"
]
\"
"
,
realm
,
nonce
)
==
2
)
{
_r
tspRealm
=
(
const
char
*
)
realm
;
_
rtspMd5Nonce
=
(
const
char
*
)
nonce
;
if
(
sscanf
(
params
_s
tr
.
data
(),
"Digest realm=
\"
%[^
\"
]
\"
, nonce=
\"
%[^
\"
]
\"
"
,
realm
,
nonce
)
==
2
)
{
_r
ealm
=
(
const
char
*
)
realm
;
_
nonce
=
(
const
char
*
)
nonce
;
return
true
;
}
if
(
sscanf
(
params
S
tr
.
data
(),
"Basic realm=
\"
%[^
\"
]
\"
"
,
realm
)
==
1
)
{
_r
tspRealm
=
(
const
char
*
)
realm
;
if
(
sscanf
(
params
_s
tr
.
data
(),
"Basic realm=
\"
%[^
\"
]
\"
"
,
realm
)
==
1
)
{
_r
ealm
=
(
const
char
*
)
realm
;
return
true
;
}
return
false
;
...
...
@@ -222,30 +226,33 @@ bool RtspPusher::handleAuthenticationFailure(const string ¶msStr) {
//有必要的情况下创建udp端口
void
RtspPusher
::
createUdpSockIfNecessary
(
int
track_idx
){
auto
&
rtp
SockRef
=
_apUdpSock
[
track_idx
];
if
(
!
rtpSockRef
)
{
rtp
SockRef
.
reset
(
new
Socket
(
getPoller
()));
auto
&
rtp
_sock
=
_udp_socks
[
track_idx
];
if
(
!
rtp_sock
)
{
rtp
_sock
.
reset
(
new
Socket
(
getPoller
()));
//rtp随机端口
if
(
!
rtp
SockRef
->
bindUdpSock
(
0
,
get_local_ip
().
data
()))
{
rtp
SockRef
.
reset
();
if
(
!
rtp
_sock
->
bindUdpSock
(
0
,
get_local_ip
().
data
()))
{
rtp
_sock
.
reset
();
throw
std
::
runtime_error
(
"open rtp sock failed"
);
}
}
}
void
RtspPusher
::
sendSetup
(
unsigned
int
track
Inde
x
)
{
_on
Handshake
=
std
::
bind
(
&
RtspPusher
::
handleResSetup
,
this
,
placeholders
::
_1
,
trackInde
x
);
auto
&
track
=
_
aTrackInfo
[
trackInde
x
];
auto
base
Url
=
_strContentB
ase
+
"/"
+
track
->
_control_surffix
;
switch
(
_
eT
ype
)
{
void
RtspPusher
::
sendSetup
(
unsigned
int
track
_id
x
)
{
_on
_res_func
=
std
::
bind
(
&
RtspPusher
::
handleResSetup
,
this
,
placeholders
::
_1
,
track_id
x
);
auto
&
track
=
_
track_vec
[
track_id
x
];
auto
base
_url
=
_content_b
ase
+
"/"
+
track
->
_control_surffix
;
switch
(
_
rtp_t
ype
)
{
case
Rtsp
:
:
RTP_TCP
:
{
sendRtspRequest
(
"SETUP"
,
baseUrl
,{
"Transport"
,
StrPrinter
<<
"RTP/AVP/TCP;unicast;interleaved="
<<
track
->
_type
*
2
<<
"-"
<<
track
->
_type
*
2
+
1
});
sendRtspRequest
(
"SETUP"
,
base_url
,
{
"Transport"
,
StrPrinter
<<
"RTP/AVP/TCP;unicast;interleaved="
<<
track
->
_type
*
2
<<
"-"
<<
track
->
_type
*
2
+
1
});
}
break
;
case
Rtsp
:
:
RTP_UDP
:
{
createUdpSockIfNecessary
(
trackIndex
);
int
port
=
_apUdpSock
[
trackIndex
]
->
get_local_port
();
sendRtspRequest
(
"SETUP"
,
baseUrl
,{
"Transport"
,
StrPrinter
<<
"RTP/AVP;unicast;client_port="
<<
port
<<
"-"
<<
port
+
1
});
createUdpSockIfNecessary
(
track_idx
);
int
port
=
_udp_socks
[
track_idx
]
->
get_local_port
();
sendRtspRequest
(
"SETUP"
,
base_url
,
{
"Transport"
,
StrPrinter
<<
"RTP/AVP;unicast;client_port="
<<
port
<<
"-"
<<
port
+
1
});
}
break
;
default
:
...
...
@@ -254,42 +261,41 @@ void RtspPusher::sendSetup(unsigned int trackIndex) {
}
void
RtspPusher
::
handleResSetup
(
const
Parser
&
parser
,
unsigned
int
uiTrackInde
x
)
{
void
RtspPusher
::
handleResSetup
(
const
Parser
&
parser
,
unsigned
int
track_id
x
)
{
if
(
parser
.
Url
()
!=
"200"
)
{
throw
std
::
runtime_error
(
StrPrinter
<<
"SETUP:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
()
<<
endl
);
throw
std
::
runtime_error
(
StrPrinter
<<
"SETUP:"
<<
parser
.
Url
()
<<
" "
<<
parser
.
Tail
()
<<
endl
);
}
if
(
uiTrackInde
x
==
0
)
{
_s
trSession
=
parser
[
"Session"
];
_s
trSession
.
append
(
";"
);
_s
trSession
=
FindField
(
_strSession
.
data
(),
nullptr
,
";"
);
if
(
track_id
x
==
0
)
{
_s
ession_id
=
parser
[
"Session"
];
_s
ession_id
.
append
(
";"
);
_s
ession_id
=
FindField
(
_session_id
.
data
(),
nullptr
,
";"
);
}
auto
strT
ransport
=
parser
[
"Transport"
];
if
(
strTransport
.
find
(
"TCP"
)
!=
string
::
npos
||
strTransport
.
find
(
"interleaved"
)
!=
string
::
npos
)
{
_
eT
ype
=
Rtsp
::
RTP_TCP
;
string
interleaved
=
FindField
(
FindField
((
strT
ransport
+
";"
).
data
(),
"interleaved="
,
";"
).
data
(),
NULL
,
"-"
);
_
aTrackInfo
[
uiTrackInde
x
]
->
_interleaved
=
atoi
(
interleaved
.
data
());
}
else
if
(
strTransport
.
find
(
"multicast"
)
!=
string
::
npos
)
{
auto
t
ransport
=
parser
[
"Transport"
];
if
(
transport
.
find
(
"TCP"
)
!=
string
::
npos
||
transport
.
find
(
"interleaved"
)
!=
string
::
npos
)
{
_
rtp_t
ype
=
Rtsp
::
RTP_TCP
;
string
interleaved
=
FindField
(
FindField
((
t
ransport
+
";"
).
data
(),
"interleaved="
,
";"
).
data
(),
NULL
,
"-"
);
_
track_vec
[
track_id
x
]
->
_interleaved
=
atoi
(
interleaved
.
data
());
}
else
if
(
transport
.
find
(
"multicast"
)
!=
string
::
npos
)
{
throw
std
::
runtime_error
(
"SETUP rtsp pusher can not support multicast!"
);
}
else
{
_
eT
ype
=
Rtsp
::
RTP_UDP
;
createUdpSockIfNecessary
(
uiTrackInde
x
);
const
char
*
strPos
=
"server_port="
;
auto
port_str
=
FindField
((
strT
ransport
+
";"
).
data
(),
strPos
,
";"
);
}
else
{
_
rtp_t
ype
=
Rtsp
::
RTP_UDP
;
createUdpSockIfNecessary
(
track_id
x
);
const
char
*
strPos
=
"server_port="
;
auto
port_str
=
FindField
((
t
ransport
+
";"
).
data
(),
strPos
,
";"
);
uint16_t
port
=
atoi
(
FindField
(
port_str
.
data
(),
NULL
,
"-"
).
data
());
struct
sockaddr_in
rtpto
;
rtpto
.
sin_port
=
ntohs
(
port
);
rtpto
.
sin_family
=
AF_INET
;
rtpto
.
sin_addr
.
s_addr
=
inet_addr
(
get_peer_ip
().
data
());
_
apUdpSock
[
uiTrackIndex
]
->
setSendPeerAddr
((
struct
sockaddr
*
)
&
(
rtpto
));
_
udp_socks
[
track_idx
]
->
setSendPeerAddr
((
struct
sockaddr
*
)
&
(
rtpto
));
}
RtspSplitter
::
enableRecvRtp
(
_
eT
ype
==
Rtsp
::
RTP_TCP
);
RtspSplitter
::
enableRecvRtp
(
_
rtp_t
ype
==
Rtsp
::
RTP_TCP
);
if
(
uiTrackIndex
<
_aTrackInfo
.
size
()
-
1
)
{
if
(
track_idx
<
_track_vec
.
size
()
-
1
)
{
//需要继续发送SETUP命令
sendSetup
(
uiTrackInde
x
+
1
);
sendSetup
(
track_id
x
+
1
);
return
;
}
...
...
@@ -297,13 +303,12 @@ void RtspPusher::handleResSetup(const Parser &parser, unsigned int uiTrackIndex)
}
void
RtspPusher
::
sendOptions
()
{
_on
Handshake
=
[
this
](
const
Parser
&
parser
)
{};
sendRtspRequest
(
"OPTIONS"
,
_strContentB
ase
);
_on
_res_func
=
[
this
](
const
Parser
&
parser
)
{};
sendRtspRequest
(
"OPTIONS"
,
_content_b
ase
);
}
inline
void
RtspPusher
::
sendRtpPacket
(
const
RtspMediaSource
::
RingDataType
&
pkt
)
{
//InfoL<<(int)pkt.Interleaved;
switch
(
_eType
)
{
switch
(
_rtp_type
)
{
case
Rtsp
:
:
RTP_TCP
:
{
int
i
=
0
;
int
size
=
pkt
->
size
();
...
...
@@ -315,85 +320,84 @@ inline void RtspPusher::sendRtpPacket(const RtspMediaSource::RingDataType &pkt)
BufferRtp
::
Ptr
buffer
(
new
BufferRtp
(
rtp
));
send
(
buffer
);
});
}
break
;
}
case
Rtsp
:
:
RTP_UDP
:
{
int
i
=
0
;
int
size
=
pkt
->
size
();
pkt
->
for_each
([
&
](
const
RtpPacket
::
Ptr
&
rtp
)
{
int
iTrackIndex
=
getTrackIndexByTrackType
(
rtp
->
type
);
auto
&
pSock
=
_
apUdpSock
[
iTrackIndex
];
auto
&
pSock
=
_
udp_socks
[
iTrackIndex
];
if
(
!
pSock
)
{
shutdown
(
SockException
(
Err_shutdown
,
"udp sock not opened yet"
));
shutdown
(
SockException
(
Err_shutdown
,
"udp sock not opened yet"
));
return
;
}
BufferRtp
::
Ptr
buffer
(
new
BufferRtp
(
rtp
,
4
));
BufferRtp
::
Ptr
buffer
(
new
BufferRtp
(
rtp
,
4
));
pSock
->
send
(
buffer
,
nullptr
,
0
,
++
i
==
size
);
});
}
break
;
default
:
break
;
}
default
:
break
;
}
}
inline
int
RtspPusher
::
getTrackIndexByTrackType
(
TrackType
type
)
{
for
(
unsigned
int
i
=
0
;
i
<
_
aTrackInfo
.
size
();
i
++
)
{
if
(
type
==
_
aTrackInfo
[
i
]
->
_type
)
{
for
(
unsigned
int
i
=
0
;
i
<
_
track_vec
.
size
();
i
++
)
{
if
(
type
==
_
track_vec
[
i
]
->
_type
)
{
return
i
;
}
}
if
(
_aTrackInfo
.
size
()
==
1
)
{
if
(
_track_vec
.
size
()
==
1
)
{
return
0
;
}
throw
SockException
(
Err_shutdown
,
StrPrinter
<<
"no such track with type:"
<<
(
int
)
type
);
}
void
RtspPusher
::
sendRecord
()
{
_on
Handshake
=
[
this
](
const
Parser
&
parser
)
{
auto
src
=
_p
MediaS
rc
.
lock
();
_on
_res_func
=
[
this
](
const
Parser
&
parser
)
{
auto
src
=
_p
ush_s
rc
.
lock
();
if
(
!
src
)
{
throw
std
::
runtime_error
(
"the media source was released"
);
}
_
pRtspR
eader
=
src
->
getRing
()
->
attach
(
getPoller
());
weak_ptr
<
RtspPusher
>
weak
S
elf
=
dynamic_pointer_cast
<
RtspPusher
>
(
shared_from_this
());
_
pRtspReader
->
setReadCB
([
weakSelf
](
const
RtspMediaSource
::
RingDataType
&
pkt
)
{
auto
strong
Self
=
weakS
elf
.
lock
();
if
(
!
strongS
elf
)
{
_
rtsp_r
eader
=
src
->
getRing
()
->
attach
(
getPoller
());
weak_ptr
<
RtspPusher
>
weak
_s
elf
=
dynamic_pointer_cast
<
RtspPusher
>
(
shared_from_this
());
_
rtsp_reader
->
setReadCB
([
weak_self
](
const
RtspMediaSource
::
RingDataType
&
pkt
)
{
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
!
strong_s
elf
)
{
return
;
}
strong
S
elf
->
sendRtpPacket
(
pkt
);
strong
_s
elf
->
sendRtpPacket
(
pkt
);
});
_
pRtspReader
->
setDetachCB
([
weakSelf
]()
{
auto
strong
Self
=
weakS
elf
.
lock
();
if
(
strongSelf
)
{
strong
Self
->
onPublishResult
(
SockException
(
Err_other
,
"媒体源被释放"
),
!
strongSelf
->
_pPublishT
imer
);
_
rtsp_reader
->
setDetachCB
([
weak_self
]()
{
auto
strong
_self
=
weak_s
elf
.
lock
();
if
(
strong_self
)
{
strong
_self
->
onPublishResult
(
SockException
(
Err_other
,
"媒体源被释放"
),
!
strong_self
->
_publish_t
imer
);
}
});
if
(
_eType
!=
Rtsp
::
RTP_TCP
)
{
if
(
_rtp_type
!=
Rtsp
::
RTP_TCP
)
{
/////////////////////////心跳/////////////////////////////////
weak_ptr
<
RtspPusher
>
weakSelf
=
dynamic_pointer_cast
<
RtspPusher
>
(
shared_from_this
());
_pBeatTimer
.
reset
(
new
Timer
((
*
this
)[
kBeatIntervalMS
].
as
<
int
>
()
/
1000.0
,
[
weakSelf
](){
auto
strongSelf
=
weakSelf
.
lock
();
if
(
!
strongSelf
){
_beat_timer
.
reset
(
new
Timer
((
*
this
)[
kBeatIntervalMS
].
as
<
int
>
()
/
1000.0
,
[
weak_self
]()
{
auto
strong_self
=
weak_self
.
lock
();
if
(
!
strong_self
)
{
return
false
;
}
strong
S
elf
->
sendOptions
();
strong
_s
elf
->
sendOptions
();
return
true
;
},
getPoller
()));
},
getPoller
()));
}
onPublishResult
(
SockException
(
Err_success
,
"success"
),
false
);
onPublishResult
(
SockException
(
Err_success
,
"success"
),
false
);
//提升发送性能
setSocketFlags
();
};
sendRtspRequest
(
"RECORD"
,
_strContentBase
,{
"Range"
,
"npt=0.000-"
});
sendRtspRequest
(
"RECORD"
,
_content_base
,
{
"Range"
,
"npt=0.000-"
});
}
void
RtspPusher
::
setSocketFlags
(){
GET_CONFIG
(
int
,
merge
WriteMS
,
General
::
kMergeWriteMS
);
if
(
mergeWriteMS
>
0
)
{
GET_CONFIG
(
int
,
merge
_write_ms
,
General
::
kMergeWriteMS
);
if
(
merge_write_ms
>
0
)
{
//提高发送性能
setSendFlags
(
SOCKET_DEFAULE_FLAGS
|
FLAG_MORE
);
SockUtil
::
setNoDelay
(
_sock
->
rawFD
(),
false
);
...
...
@@ -404,26 +408,26 @@ void RtspPusher::sendRtspRequest(const string &cmd, const string &url, const std
string
key
;
StrCaseMap
header_map
;
int
i
=
0
;
for
(
auto
&
val
:
header
)
{
if
(
++
i
%
2
==
0
)
{
header_map
.
emplace
(
key
,
val
);
}
else
{
for
(
auto
&
val
:
header
)
{
if
(
++
i
%
2
==
0
)
{
header_map
.
emplace
(
key
,
val
);
}
else
{
key
=
val
;
}
}
sendRtspRequest
(
cmd
,
url
,
header_map
,
sdp
);
sendRtspRequest
(
cmd
,
url
,
header_map
,
sdp
);
}
void
RtspPusher
::
sendRtspRequest
(
const
string
&
cmd
,
const
string
&
url
,
const
StrCaseMap
&
header_const
,
const
string
&
sdp
)
{
auto
header
=
header_const
;
header
.
emplace
(
"CSeq"
,
StrPrinter
<<
_uiC
seq
++
);
header
.
emplace
(
"User-Agent"
,
SERVER_NAME
);
header
.
emplace
(
"CSeq"
,
StrPrinter
<<
_c
seq
++
);
header
.
emplace
(
"User-Agent"
,
SERVER_NAME
);
if
(
!
_strSession
.
empty
())
{
header
.
emplace
(
"Session"
,
_strSession
);
if
(
!
_session_id
.
empty
())
{
header
.
emplace
(
"Session"
,
_session_id
);
}
if
(
!
_rtspRealm
.
empty
()
&&
!
(
*
this
)[
kRtspUser
].
empty
())
{
if
(
!
_rtspMd5Nonce
.
empty
())
{
if
(
!
_realm
.
empty
()
&&
!
(
*
this
)[
kRtspUser
].
empty
())
{
if
(
!
_nonce
.
empty
())
{
//MD5认证
/*
response计算方法如下:
...
...
@@ -434,41 +438,41 @@ void RtspPusher::sendRtspRequest(const string &cmd, const string &url,const StrC
response= md5( md5(username:realm:password):nonce:md5(public_method:url) );
*/
string
encrypted_pwd
=
(
*
this
)[
kRtspPwd
];
if
(
!
(
*
this
)[
kRtspPwdIsMD5
].
as
<
bool
>
())
{
encrypted_pwd
=
MD5
((
*
this
)[
kRtspUser
]
+
":"
+
_rtspR
ealm
+
":"
+
encrypted_pwd
).
hexdigest
();
if
(
!
(
*
this
)[
kRtspPwdIsMD5
].
as
<
bool
>
())
{
encrypted_pwd
=
MD5
((
*
this
)[
kRtspUser
]
+
":"
+
_r
ealm
+
":"
+
encrypted_pwd
).
hexdigest
();
}
auto
response
=
MD5
(
encrypted_pwd
+
":"
+
_rtspMd5Nonce
+
":"
+
MD5
(
cmd
+
":"
+
url
).
hexdigest
()).
hexdigest
();
auto
response
=
MD5
(
encrypted_pwd
+
":"
+
_nonce
+
":"
+
MD5
(
cmd
+
":"
+
url
).
hexdigest
()).
hexdigest
();
_StrPrinter
printer
;
printer
<<
"Digest "
;
printer
<<
"username=
\"
"
<<
(
*
this
)[
kRtspUser
]
<<
"
\"
, "
;
printer
<<
"realm=
\"
"
<<
_r
tspR
ealm
<<
"
\"
, "
;
printer
<<
"nonce=
\"
"
<<
_
rtspMd5N
once
<<
"
\"
, "
;
printer
<<
"realm=
\"
"
<<
_realm
<<
"
\"
, "
;
printer
<<
"nonce=
\"
"
<<
_
n
once
<<
"
\"
, "
;
printer
<<
"uri=
\"
"
<<
url
<<
"
\"
, "
;
printer
<<
"response=
\"
"
<<
response
<<
"
\"
"
;
header
.
emplace
(
"Authorization"
,
printer
);
}
else
if
(
!
(
*
this
)[
kRtspPwdIsMD5
].
as
<
bool
>
())
{
header
.
emplace
(
"Authorization"
,
printer
);
}
else
if
(
!
(
*
this
)[
kRtspPwdIsMD5
].
as
<
bool
>
())
{
//base64认证
string
authStr
=
StrPrinter
<<
(
*
this
)[
kRtspUser
]
<<
":"
<<
(
*
this
)[
kRtspPwd
];
char
authStrBase64
[
1024
]
=
{
0
};
av_base64_encode
(
authStrBase64
,
sizeof
(
authStrBase64
),(
uint8_t
*
)
authStr
.
data
(),
authStr
.
size
());
header
.
emplace
(
"Authorization"
,
StrPrinter
<<
"Basic "
<<
authStrBase64
);
av_base64_encode
(
authStrBase64
,
sizeof
(
authStrBase64
),
(
uint8_t
*
)
authStr
.
data
(),
authStr
.
size
());
header
.
emplace
(
"Authorization"
,
StrPrinter
<<
"Basic "
<<
authStrBase64
);
}
}
if
(
!
sdp
.
empty
())
{
header
.
emplace
(
"Content-Length"
,
StrPrinter
<<
sdp
.
size
());
header
.
emplace
(
"Content-Type"
,
"application/sdp"
);
if
(
!
sdp
.
empty
())
{
header
.
emplace
(
"Content-Length"
,
StrPrinter
<<
sdp
.
size
());
header
.
emplace
(
"Content-Type"
,
"application/sdp"
);
}
_StrPrinter
printer
;
printer
<<
cmd
<<
" "
<<
url
<<
" RTSP/1.0
\r\n
"
;
for
(
auto
&
pr
:
header
){
for
(
auto
&
pr
:
header
)
{
printer
<<
pr
.
first
<<
": "
<<
pr
.
second
<<
"
\r\n
"
;
}
printer
<<
"
\r\n
"
;
if
(
!
sdp
.
empty
())
{
if
(
!
sdp
.
empty
())
{
printer
<<
sdp
;
}
SockSender
::
send
(
printer
);
...
...
src/Rtsp/RtspPusher.h
查看文件 @
a7e99b9d
...
...
@@ -31,39 +31,39 @@ class RtspPusher : public TcpClient, public RtspSplitter, public PusherBase {
public
:
typedef
std
::
shared_ptr
<
RtspPusher
>
Ptr
;
RtspPusher
(
const
EventPoller
::
Ptr
&
poller
,
const
RtspMediaSource
::
Ptr
&
src
);
virtual
~
RtspPusher
();
void
publish
(
const
string
&
strUrl
)
override
;
~
RtspPusher
()
override
;
void
publish
(
const
string
&
url
)
override
;
void
teardown
()
override
;
void
setOnPublished
(
const
Event
&
cb
)
override
{
_on
P
ublished
=
cb
;
_on
_p
ublished
=
cb
;
}
void
setOnShutdown
(
const
Event
&
cb
)
override
{
_on
S
hutdown
=
cb
;
_on
_s
hutdown
=
cb
;
}
protected
:
//for Tcpclient override
void
onRecv
(
const
Buffer
::
Ptr
&
pB
uf
)
override
;
void
onRecv
(
const
Buffer
::
Ptr
&
b
uf
)
override
;
void
onConnect
(
const
SockException
&
err
)
override
;
void
onErr
(
const
SockException
&
ex
)
override
;
//RtspSplitter override
void
onWholeRtspPacket
(
Parser
&
parser
)
override
;
void
onRtpPacket
(
const
char
*
data
,
uint64_t
len
)
override
{};
private
:
void
onPublishResult
(
const
SockException
&
ex
,
bool
handshake
Completed
);
void
onPublishResult
(
const
SockException
&
ex
,
bool
handshake
_done
);
void
sendAnnounce
();
void
sendSetup
(
unsigned
int
uiTrackInde
x
);
void
sendSetup
(
unsigned
int
track_id
x
);
void
sendRecord
();
void
sendOptions
();
void
handleResAnnounce
(
const
Parser
&
parser
);
void
handleResSetup
(
const
Parser
&
parser
,
unsigned
int
uiTrackInde
x
);
bool
handleAuthenticationFailure
(
const
string
&
params
S
tr
);
void
handleResSetup
(
const
Parser
&
parser
,
unsigned
int
track_id
x
);
bool
handleAuthenticationFailure
(
const
string
&
params
_s
tr
);
inline
int
getTrackIndexByTrackType
(
TrackType
type
);
...
...
@@ -73,33 +73,30 @@ private:
void
createUdpSockIfNecessary
(
int
track_idx
);
void
setSocketFlags
();
private
:
//rtsp鉴权相关
string
_rtspMd5Nonce
;
string
_rtspRealm
;
unsigned
int
_cseq
=
1
;
Rtsp
::
eRtpType
_rtp_type
=
Rtsp
::
RTP_TCP
;
//rtsp鉴权相关
string
_nonce
;
string
_realm
;
string
_url
;
string
_session_id
;
string
_content_base
;
SdpParser
_sdp_parser
;
vector
<
SdpTrack
::
Ptr
>
_track_vec
;
Socket
::
Ptr
_udp_socks
[
2
];
//超时功能实现
std
::
shared_ptr
<
Timer
>
_pPublishTimer
;
//源
std
::
weak_ptr
<
RtspMediaSource
>
_pMediaSrc
;
RtspMediaSource
::
RingType
::
RingReader
::
Ptr
_pRtspReader
;
//事件监听
Event
_onShutdown
;
Event
_onPublished
;
string
_strUrl
;
SdpParser
_sdpParser
;
vector
<
SdpTrack
::
Ptr
>
_aTrackInfo
;
string
_strSession
;
unsigned
int
_uiCseq
=
1
;
string
_strContentBase
;
Rtsp
::
eRtpType
_eType
=
Rtsp
::
RTP_TCP
;
Socket
::
Ptr
_apUdpSock
[
2
];
function
<
void
(
const
Parser
&
)
>
_onHandshake
;
std
::
shared_ptr
<
Timer
>
_publish_timer
;
//心跳定时器
std
::
shared_ptr
<
Timer
>
_pBeatTimer
;
std
::
shared_ptr
<
Timer
>
_beat_timer
;
std
::
weak_ptr
<
RtspMediaSource
>
_push_src
;
RtspMediaSource
::
RingType
::
RingReader
::
Ptr
_rtsp_reader
;
//事件监听
Event
_on_shutdown
;
Event
_on_published
;
function
<
void
(
const
Parser
&
)
>
_on_res_func
;
};
}
/* namespace mediakit */
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论