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
b127d8c2
Commit
b127d8c2
authored
Mar 13, 2022
by
xiongziliang
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
rtsp/GB28181随机端口,支持端口范围设置
parent
43140065
隐藏空白字符变更
内嵌
并排
正在显示
4 个修改的文件
包含
108 行增加
和
64 行删除
+108
-64
conf/config.ini
+3
-0
src/Common/config.cpp
+22
-45
src/Common/config.h
+3
-0
src/Rtsp/Rtsp.cpp
+80
-19
没有找到文件。
conf/config.ini
查看文件 @
b127d8c2
...
...
@@ -254,6 +254,9 @@ dumpDir=
port
=
10000
#rtp超时时间,单位秒
timeoutSec
=
15
#随机端口范围,最少确保36个端口
#该范围同时限制rtsp服务器udp端口范围
port_range
=
30000-35000
[rtc]
#rtc播放推流、播放超时时间
...
...
src/Common/config.cpp
查看文件 @
b127d8c2
...
...
@@ -82,7 +82,7 @@ const string kWaitAddTrackMS = GENERAL_FIELD"wait_add_track_ms";
const
string
kUnreadyFrameCache
=
GENERAL_FIELD
"unready_frame_cache"
;
const
string
kContinuePushMS
=
GENERAL_FIELD
"continue_push_ms"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kFlowThreshold
]
=
1024
;
mINI
::
Instance
()[
kStreamNoneReaderDelayMS
]
=
20
*
1000
;
mINI
::
Instance
()[
kMaxStreamWaitTimeMS
]
=
15
*
1000
;
...
...
@@ -104,33 +104,24 @@ onceToken token([](){
mINI
::
Instance
()[
kWaitAddTrackMS
]
=
3000
;
mINI
::
Instance
()[
kUnreadyFrameCache
]
=
100
;
mINI
::
Instance
()[
kContinuePushMS
]
=
15
*
1000
;
}
,
nullptr
);
});
}
//namespace General
////////////HTTP配置///////////
namespace
Http
{
#define HTTP_FIELD "http."
//http 文件发送缓存大小
const
string
kSendBufSize
=
HTTP_FIELD
"sendBufSize"
;
//http 最大请求字节数
const
string
kMaxReqSize
=
HTTP_FIELD
"maxReqSize"
;
//http keep-alive秒数
const
string
kKeepAliveSecond
=
HTTP_FIELD
"keepAliveSecond"
;
//http 字符编码
const
string
kCharSet
=
HTTP_FIELD
"charSet"
;
//http 服务器根目录
const
string
kRootPath
=
HTTP_FIELD
"rootPath"
;
//http 服务器虚拟目录
const
string
kVirtualPath
=
HTTP_FIELD
"virtualPath"
;
//http 404错误提示内容
const
string
kNotFound
=
HTTP_FIELD
"notFound"
;
//是否显示文件夹菜单
const
string
kDirMenu
=
HTTP_FIELD
"dirMenu"
;
const
string
kForbidCacheSuffix
=
HTTP_FIELD
"forbidCacheSuffix"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kSendBufSize
]
=
64
*
1024
;
mINI
::
Instance
()[
kMaxReqSize
]
=
4
*
10240
;
mINI
::
Instance
()[
kKeepAliveSecond
]
=
15
;
...
...
@@ -155,7 +146,7 @@ onceToken token([](){
"</html>"
<<
endl
;
mINI
::
Instance
()[
kForbidCacheSuffix
]
=
""
;
}
,
nullptr
);
});
}
//namespace Http
...
...
@@ -164,9 +155,9 @@ namespace Shell {
#define SHELL_FIELD "shell."
const
string
kMaxReqSize
=
SHELL_FIELD
"maxReqSize"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kMaxReqSize
]
=
1024
;
}
,
nullptr
);
});
}
//namespace Shell
////////////RTSP服务器配置///////////
...
...
@@ -177,13 +168,13 @@ const string kHandshakeSecond = RTSP_FIELD"handshakeSecond";
const
string
kKeepAliveSecond
=
RTSP_FIELD
"keepAliveSecond"
;
const
string
kDirectProxy
=
RTSP_FIELD
"directProxy"
;
onceToken
token
([](){
static
onceToken
token
([](){
//默认Md5方式认证
mINI
::
Instance
()[
kAuthBasic
]
=
0
;
mINI
::
Instance
()[
kHandshakeSecond
]
=
15
;
mINI
::
Instance
()[
kKeepAliveSecond
]
=
15
;
mINI
::
Instance
()[
kDirectProxy
]
=
1
;
}
,
nullptr
);
});
}
//namespace Rtsp
////////////RTMP服务器配置///////////
...
...
@@ -193,11 +184,11 @@ const string kModifyStamp = RTMP_FIELD"modifyStamp";
const
string
kHandshakeSecond
=
RTMP_FIELD
"handshakeSecond"
;
const
string
kKeepAliveSecond
=
RTMP_FIELD
"keepAliveSecond"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kModifyStamp
]
=
false
;
mINI
::
Instance
()[
kHandshakeSecond
]
=
15
;
mINI
::
Instance
()[
kKeepAliveSecond
]
=
15
;
}
,
nullptr
);
});
}
//namespace RTMP
...
...
@@ -210,11 +201,11 @@ const string kAudioMtuSize = RTP_FIELD"audioMtuSize";
//rtp包最大长度限制,单位是KB
const
string
kRtpMaxSize
=
RTP_FIELD
"rtpMaxSize"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kVideoMtuSize
]
=
1400
;
mINI
::
Instance
()[
kAudioMtuSize
]
=
600
;
mINI
::
Instance
()[
kRtpMaxSize
]
=
10
;
}
,
nullptr
);
});
}
//namespace Rtsp
////////////组播配置///////////
...
...
@@ -227,32 +218,25 @@ const string kAddrMax = MULTI_FIELD"addrMax";
//组播TTL
const
string
kUdpTTL
=
MULTI_FIELD
"udpTTL"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kAddrMin
]
=
"239.0.0.0"
;
mINI
::
Instance
()[
kAddrMax
]
=
"239.255.255.255"
;
mINI
::
Instance
()[
kUdpTTL
]
=
64
;
}
,
nullptr
);
});
}
//namespace MultiCast
////////////录像配置///////////
namespace
Record
{
#define RECORD_FIELD "record."
//查看录像的应用名称
const
string
kAppName
=
RECORD_FIELD
"appName"
;
//每次流化MP4文件的时长,单位毫秒
const
string
kSampleMS
=
RECORD_FIELD
"sampleMS"
;
//MP4文件录制大小,默认一个小时
const
string
kFileSecond
=
RECORD_FIELD
"fileSecond"
;
//录制文件路径
const
string
kFilePath
=
RECORD_FIELD
"filePath"
;
//mp4文件写缓存大小
const
string
kFileBufSize
=
RECORD_FIELD
"fileBufSize"
;
//mp4录制完成后是否进行二次关键帧索引写入头部
const
string
kFastStart
=
RECORD_FIELD
"fastStart"
;
//mp4文件是否重头循环读取
const
string
kFileRepeat
=
RECORD_FIELD
"fileRepeat"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kAppName
]
=
"record"
;
mINI
::
Instance
()[
kSampleMS
]
=
500
;
mINI
::
Instance
()[
kFileSecond
]
=
60
*
60
;
...
...
@@ -260,28 +244,21 @@ onceToken token([](){
mINI
::
Instance
()[
kFileBufSize
]
=
64
*
1024
;
mINI
::
Instance
()[
kFastStart
]
=
false
;
mINI
::
Instance
()[
kFileRepeat
]
=
false
;
}
,
nullptr
);
});
}
//namespace Record
////////////HLS相关配置///////////
namespace
Hls
{
#define HLS_FIELD "hls."
//HLS切片时长,单位秒
const
string
kSegmentDuration
=
HLS_FIELD
"segDur"
;
//HLS切片个数
const
string
kSegmentNum
=
HLS_FIELD
"segNum"
;
//HLS切片从m3u8文件中移除后,继续保留在磁盘上的个数
const
string
kSegmentRetain
=
HLS_FIELD
"segRetain"
;
//HLS文件写缓存大小
const
string
kFileBufSize
=
HLS_FIELD
"fileBufSize"
;
//录制文件路径
const
string
kFilePath
=
HLS_FIELD
"filePath"
;
// 是否广播 ts 切片完成通知
const
string
kBroadcastRecordTs
=
HLS_FIELD
"broadcastRecordTs"
;
//hls直播文件删除延时,单位秒
const
string
kDeleteDelaySec
=
HLS_FIELD
"deleteDelaySec"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kSegmentDuration
]
=
2
;
mINI
::
Instance
()[
kSegmentNum
]
=
3
;
mINI
::
Instance
()[
kSegmentRetain
]
=
5
;
...
...
@@ -289,22 +266,22 @@ onceToken token([](){
mINI
::
Instance
()[
kFilePath
]
=
"./www"
;
mINI
::
Instance
()[
kBroadcastRecordTs
]
=
false
;
mINI
::
Instance
()[
kDeleteDelaySec
]
=
0
;
}
,
nullptr
);
});
}
//namespace Hls
////////////Rtp代理相关配置///////////
namespace
RtpProxy
{
#define RTP_PROXY_FIELD "rtp_proxy."
//rtp调试数据保存目录
const
string
kDumpDir
=
RTP_PROXY_FIELD
"dumpDir"
;
//rtp接收超时时间
const
string
kTimeoutSec
=
RTP_PROXY_FIELD
"timeoutSec"
;
const
string
kPortRange
=
RTP_PROXY_FIELD
"port_range"
;
onceToken
token
([](){
static
onceToken
token
([](){
mINI
::
Instance
()[
kDumpDir
]
=
""
;
mINI
::
Instance
()[
kTimeoutSec
]
=
15
;
},
nullptr
);
mINI
::
Instance
()[
kPortRange
]
=
"30000-35000"
;
});
}
//namespace RtpProxy
...
...
src/Common/config.h
查看文件 @
b127d8c2
...
...
@@ -313,6 +313,9 @@ namespace RtpProxy {
extern
const
std
::
string
kDumpDir
;
//rtp接收超时时间
extern
const
std
::
string
kTimeoutSec
;
//随机端口范围,最少确保36个端口
//该范围同时限制rtsp服务器udp端口范围
extern
const
std
::
string
kPortRange
;
}
//namespace RtpProxy
/**
...
...
src/Rtsp/Rtsp.cpp
查看文件 @
b127d8c2
...
...
@@ -8,7 +8,8 @@
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <stdlib.h>
#include <cstdlib>
#include <cinttypes>
#include "Rtsp.h"
#include "Common/Parser.h"
...
...
@@ -364,28 +365,88 @@ bool RtspUrl::setup(bool isSSL, const string &strUrl, const string &strUser, con
return
true
;
}
static
void
makeSockPair_l
(
std
::
pair
<
Socket
::
Ptr
,
Socket
::
Ptr
>
&
pair
,
const
string
&
local_ip
)
{
auto
&
pSockRtp
=
pair
.
first
;
auto
&
pSockRtcp
=
pair
.
second
;
class
PortManager
:
public
std
::
enable_shared_from_this
<
PortManager
>
{
public
:
PortManager
()
{
static
auto
func
=
[](
const
string
&
str
,
int
index
)
{
uint16_t
port
[]
=
{
30000
,
35000
};
sscanf
(
str
.
data
(),
"%"
SCNu16
"-%"
SCNu16
,
port
,
port
+
1
);
return
port
[
index
];
};
GET_CONFIG_FUNC
(
uint16_t
,
s_min_port
,
RtpProxy
::
kPortRange
,
[](
const
string
&
str
)
{
return
func
(
str
,
0
);
});
GET_CONFIG_FUNC
(
uint16_t
,
s_max_port
,
RtpProxy
::
kPortRange
,
[](
const
string
&
str
)
{
return
func
(
str
,
1
);
});
assert
(
s_max_port
>
s_min_port
+
36
);
setRange
((
s_min_port
+
1
)
/
2
,
s_max_port
/
2
);
}
static
PortManager
&
Instance
()
{
static
auto
instance
=
std
::
make_shared
<
PortManager
>
();
return
*
instance
;
}
void
bindUdpSock
(
std
::
pair
<
Socket
::
Ptr
,
Socket
::
Ptr
>
&
pair
,
const
string
&
local_ip
)
{
auto
&
sock0
=
pair
.
first
;
auto
&
sock1
=
pair
.
second
;
auto
sock_pair
=
getPortPair
();
if
(
!
sock_pair
)
{
throw
runtime_error
(
"none reserved udp port in pool"
);
}
if
(
!
sock0
->
bindUdpSock
(
2
*
*
sock_pair
,
local_ip
.
data
(),
false
))
{
//分配端口失败
throw
runtime_error
(
"open udp socket[0] failed"
);
}
if
(
!
pSockRtp
->
bindUdpSock
(
0
,
local_ip
.
data
()))
{
//分配端口失败
throw
runtime_error
(
"open udp socket failed"
);
if
(
!
sock1
->
bindUdpSock
(
2
*
*
sock_pair
+
1
,
local_ip
.
data
(),
false
))
{
//分配端口失败
throw
runtime_error
(
"open udp socket[1] failed"
);
}
auto
on_cycle
=
[
sock_pair
](
Socket
::
Ptr
&
,
std
::
shared_ptr
<
void
>
&
)
{};
// udp socket没onAccept事件,设置该回调,目的是为了在销毁socket时,回收对象
sock0
->
setOnAccept
(
on_cycle
);
sock1
->
setOnAccept
(
on_cycle
);
}
//是否是偶数
bool
even_numbers
=
pSockRtp
->
get_local_port
()
%
2
==
0
;
if
(
!
pSockRtcp
->
bindUdpSock
(
pSockRtp
->
get_local_port
()
+
(
even_numbers
?
1
:
-
1
),
local_ip
.
data
()))
{
//分配端口失败
throw
runtime_error
(
"open udp socket failed"
);
private
:
void
setRange
(
uint16_t
start_pos
,
uint16_t
end_pos
)
{
lock_guard
<
recursive_mutex
>
lck
(
_pool_mtx
);
while
(
start_pos
<
end_pos
)
{
_port_pair_pool
.
emplace_back
(
start_pos
++
);
}
}
if
(
!
even_numbers
)
{
//如果rtp端口不是偶数,那么与rtcp端口互换,目的是兼容一些要求严格的播放器或服务器
Socket
::
Ptr
tmp
=
pSockRtp
;
pSockRtp
=
pSockRtcp
;
pSockRtcp
=
tmp
;
std
::
shared_ptr
<
uint16_t
>
getPortPair
()
{
lock_guard
<
recursive_mutex
>
lck
(
_pool_mtx
);
if
(
_port_pair_pool
.
empty
())
{
return
nullptr
;
}
auto
pos
=
_port_pair_pool
.
front
();
_port_pair_pool
.
pop_front
();
InfoL
<<
"got port from pool:"
<<
2
*
pos
<<
"-"
<<
2
*
pos
+
1
;
weak_ptr
<
PortManager
>
weak_self
=
shared_from_this
();
std
::
shared_ptr
<
uint16_t
>
ret
(
new
uint16_t
(
pos
),
[
weak_self
,
pos
](
uint16_t
*
ptr
)
{
delete
ptr
;
auto
strong_self
=
weak_self
.
lock
();
if
(
!
strong_self
)
{
return
;
}
InfoL
<<
"return port to pool:"
<<
2
*
pos
<<
"-"
<<
2
*
pos
+
1
;
//回收端口号
lock_guard
<
recursive_mutex
>
lck
(
strong_self
->
_pool_mtx
);
strong_self
->
_port_pair_pool
.
emplace_back
(
pos
);
});
return
ret
;
}
private
:
recursive_mutex
_pool_mtx
;
deque
<
uint16_t
>
_port_pair_pool
;
};
static
void
makeSockPair_l
(
std
::
pair
<
Socket
::
Ptr
,
Socket
::
Ptr
>
&
pair
,
const
string
&
local_ip
)
{
PortManager
::
Instance
().
bindUdpSock
(
pair
,
local_ip
);
}
void
makeSockPair
(
std
::
pair
<
Socket
::
Ptr
,
Socket
::
Ptr
>
&
pair
,
const
string
&
local_ip
)
{
...
...
@@ -397,11 +458,11 @@ void makeSockPair(std::pair<Socket::Ptr, Socket::Ptr> &pair, const string &local
try
{
makeSockPair_l
(
pair
,
local_ip
);
break
;
}
catch
(
...
)
{
}
catch
(
exception
&
ex
)
{
if
(
++
try_count
==
3
)
{
throw
;
}
WarnL
<<
"open udp socket failed, retry: "
<<
try_count
;
WarnL
<<
"open udp socket failed
:"
<<
ex
.
what
()
<<
"
, retry: "
<<
try_count
;
}
}
}
...
...
编写
预览
Markdown
格式
0%
重试
或
添加新文件
添加附件
取消
您添加了
0
人
到此讨论。请谨慎行事。
请先完成此评论的编辑!
取消
请
注册
或者
登录
后发表评论