mirror of
https://github.com/ZLMediaKit/ZLMediaKit.git
synced 2024-11-22 19:00:01 +08:00
for rtp server can config pt
This commit is contained in:
parent
559b4d3fe7
commit
6a337adc91
@ -265,6 +265,28 @@ timeoutSec=15
|
||||
#该范围同时限制rtsp服务器udp端口范围
|
||||
port_range=30000-35000
|
||||
|
||||
#rtp h264 负载的pt
|
||||
h264_pt=98
|
||||
|
||||
#rtp h265 负载的pt
|
||||
h265_pt=99
|
||||
|
||||
#rtp ps 负载的pt
|
||||
ps_pt=96
|
||||
|
||||
#rtp ts 负载的pt
|
||||
ts_pt=33
|
||||
|
||||
#rtp opus 负载的pt
|
||||
opus_pt=100
|
||||
|
||||
#rtp g711u 负载的pt
|
||||
g711u_pt=0
|
||||
|
||||
#rtp g711a 负载的pt
|
||||
g711a_pt=8
|
||||
|
||||
|
||||
[rtc]
|
||||
#rtc播放推流、播放超时时间
|
||||
timeoutSec=15
|
||||
|
@ -8,31 +8,31 @@
|
||||
* may be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <assert.h>
|
||||
#include "Common/config.h"
|
||||
#include "Util/util.h"
|
||||
#include "Util/NoticeCenter.h"
|
||||
#include "Util/logger.h"
|
||||
#include "Util/onceToken.h"
|
||||
#include "Util/NoticeCenter.h"
|
||||
#include "Util/util.h"
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
bool loadIniConfig(const char *ini_path){
|
||||
bool loadIniConfig(const char *ini_path) {
|
||||
string ini;
|
||||
if(ini_path && ini_path[0] != '\0'){
|
||||
if (ini_path && ini_path[0] != '\0') {
|
||||
ini = ini_path;
|
||||
}else{
|
||||
} else {
|
||||
ini = exePath() + ".ini";
|
||||
}
|
||||
try{
|
||||
try {
|
||||
mINI::Instance().parseFile(ini);
|
||||
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
|
||||
return true;
|
||||
}catch (std::exception &) {
|
||||
} catch (std::exception &) {
|
||||
InfoL << "dump ini file to:" << ini;
|
||||
mINI::Instance().dumpFile(ini);
|
||||
return false;
|
||||
@ -55,36 +55,36 @@ const string kBroadcastShellLogin = "kBroadcastShellLogin";
|
||||
const string kBroadcastNotFoundStream = "kBroadcastNotFoundStream";
|
||||
const string kBroadcastStreamNoneReader = "kBroadcastStreamNoneReader";
|
||||
const string kBroadcastHttpBeforeAccess = "kBroadcastHttpBeforeAccess";
|
||||
} //namespace Broadcast
|
||||
} // namespace Broadcast
|
||||
|
||||
//通用配置项目
|
||||
namespace General{
|
||||
// 通用配置项目
|
||||
namespace General {
|
||||
#define GENERAL_FIELD "general."
|
||||
const string kMediaServerId = GENERAL_FIELD"mediaServerId";
|
||||
const string kFlowThreshold = GENERAL_FIELD"flowThreshold";
|
||||
const string kStreamNoneReaderDelayMS = GENERAL_FIELD"streamNoneReaderDelayMS";
|
||||
const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS";
|
||||
const string kEnableVhost = GENERAL_FIELD"enableVhost";
|
||||
const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio";
|
||||
const string kResetWhenRePlay = GENERAL_FIELD"resetWhenRePlay";
|
||||
const string kPublishToHls = GENERAL_FIELD"publishToHls";
|
||||
const string kPublishToMP4 = GENERAL_FIELD"publishToMP4";
|
||||
const string kMergeWriteMS = GENERAL_FIELD"mergeWriteMS";
|
||||
const string kModifyStamp = GENERAL_FIELD"modifyStamp";
|
||||
const string kHlsDemand = GENERAL_FIELD"hls_demand";
|
||||
const string kRtspDemand = GENERAL_FIELD"rtsp_demand";
|
||||
const string kRtmpDemand = GENERAL_FIELD"rtmp_demand";
|
||||
const string kTSDemand = GENERAL_FIELD"ts_demand";
|
||||
const string kFMP4Demand = GENERAL_FIELD"fmp4_demand";
|
||||
const string kEnableAudio = GENERAL_FIELD"enable_audio";
|
||||
const string kCheckNvidiaDev = GENERAL_FIELD"check_nvidia_dev";
|
||||
const string kEnableFFmpegLog = GENERAL_FIELD"enable_ffmpeg_log";
|
||||
const string kWaitTrackReadyMS = GENERAL_FIELD"wait_track_ready_ms";
|
||||
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";
|
||||
const string kMediaServerId = GENERAL_FIELD "mediaServerId";
|
||||
const string kFlowThreshold = GENERAL_FIELD "flowThreshold";
|
||||
const string kStreamNoneReaderDelayMS = GENERAL_FIELD "streamNoneReaderDelayMS";
|
||||
const string kMaxStreamWaitTimeMS = GENERAL_FIELD "maxStreamWaitMS";
|
||||
const string kEnableVhost = GENERAL_FIELD "enableVhost";
|
||||
const string kAddMuteAudio = GENERAL_FIELD "addMuteAudio";
|
||||
const string kResetWhenRePlay = GENERAL_FIELD "resetWhenRePlay";
|
||||
const string kPublishToHls = GENERAL_FIELD "publishToHls";
|
||||
const string kPublishToMP4 = GENERAL_FIELD "publishToMP4";
|
||||
const string kMergeWriteMS = GENERAL_FIELD "mergeWriteMS";
|
||||
const string kModifyStamp = GENERAL_FIELD "modifyStamp";
|
||||
const string kHlsDemand = GENERAL_FIELD "hls_demand";
|
||||
const string kRtspDemand = GENERAL_FIELD "rtsp_demand";
|
||||
const string kRtmpDemand = GENERAL_FIELD "rtmp_demand";
|
||||
const string kTSDemand = GENERAL_FIELD "ts_demand";
|
||||
const string kFMP4Demand = GENERAL_FIELD "fmp4_demand";
|
||||
const string kEnableAudio = GENERAL_FIELD "enable_audio";
|
||||
const string kCheckNvidiaDev = GENERAL_FIELD "check_nvidia_dev";
|
||||
const string kEnableFFmpegLog = GENERAL_FIELD "enable_ffmpeg_log";
|
||||
const string kWaitTrackReadyMS = GENERAL_FIELD "wait_track_ready_ms";
|
||||
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";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kFlowThreshold] = 1024;
|
||||
mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000;
|
||||
mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000;
|
||||
@ -110,22 +110,22 @@ static onceToken token([](){
|
||||
mINI::Instance()[kContinuePushMS] = 15 * 1000;
|
||||
});
|
||||
|
||||
}//namespace General
|
||||
} // namespace General
|
||||
|
||||
////////////HTTP配置///////////
|
||||
namespace Http {
|
||||
#define HTTP_FIELD "http."
|
||||
const string kSendBufSize = HTTP_FIELD"sendBufSize";
|
||||
const string kMaxReqSize = HTTP_FIELD"maxReqSize";
|
||||
const string kKeepAliveSecond = HTTP_FIELD"keepAliveSecond";
|
||||
const string kCharSet = HTTP_FIELD"charSet";
|
||||
const string kRootPath = HTTP_FIELD"rootPath";
|
||||
const string kSendBufSize = HTTP_FIELD "sendBufSize";
|
||||
const string kMaxReqSize = HTTP_FIELD "maxReqSize";
|
||||
const string kKeepAliveSecond = HTTP_FIELD "keepAliveSecond";
|
||||
const string kCharSet = HTTP_FIELD "charSet";
|
||||
const string kRootPath = HTTP_FIELD "rootPath";
|
||||
const string kVirtualPath = HTTP_FIELD "virtualPath";
|
||||
const string kNotFound = HTTP_FIELD"notFound";
|
||||
const string kDirMenu = HTTP_FIELD"dirMenu";
|
||||
const string kForbidCacheSuffix = HTTP_FIELD"forbidCacheSuffix";
|
||||
const string kNotFound = HTTP_FIELD "notFound";
|
||||
const string kDirMenu = HTTP_FIELD "dirMenu";
|
||||
const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kSendBufSize] = 64 * 1024;
|
||||
mINI::Instance()[kMaxReqSize] = 4 * 10240;
|
||||
mINI::Instance()[kKeepAliveSecond] = 15;
|
||||
@ -135,7 +135,7 @@ static onceToken token([](){
|
||||
#if defined(_WIN32)
|
||||
mINI::Instance()[kCharSet] = "gb2312";
|
||||
#else
|
||||
mINI::Instance()[kCharSet] ="utf-8";
|
||||
mINI::Instance()[kCharSet] = "utf-8";
|
||||
#endif
|
||||
|
||||
mINI::Instance()[kRootPath] = "./www";
|
||||
@ -149,121 +149,118 @@ static onceToken token([](){
|
||||
"</body>"
|
||||
"</html>"
|
||||
<< endl;
|
||||
mINI::Instance()[kForbidCacheSuffix] = "";
|
||||
mINI::Instance()[kForbidCacheSuffix] = "";
|
||||
});
|
||||
|
||||
}//namespace Http
|
||||
} // namespace Http
|
||||
|
||||
////////////SHELL配置///////////
|
||||
namespace Shell {
|
||||
#define SHELL_FIELD "shell."
|
||||
const string kMaxReqSize = SHELL_FIELD"maxReqSize";
|
||||
const string kMaxReqSize = SHELL_FIELD "maxReqSize";
|
||||
|
||||
static onceToken token([](){
|
||||
mINI::Instance()[kMaxReqSize] = 1024;
|
||||
});
|
||||
} //namespace Shell
|
||||
static onceToken token([]() { mINI::Instance()[kMaxReqSize] = 1024; });
|
||||
} // namespace Shell
|
||||
|
||||
////////////RTSP服务器配置///////////
|
||||
namespace Rtsp {
|
||||
#define RTSP_FIELD "rtsp."
|
||||
const string kAuthBasic = RTSP_FIELD"authBasic";
|
||||
const string kHandshakeSecond = RTSP_FIELD"handshakeSecond";
|
||||
const string kKeepAliveSecond = RTSP_FIELD"keepAliveSecond";
|
||||
const string kDirectProxy = RTSP_FIELD"directProxy";
|
||||
const string kAuthBasic = RTSP_FIELD "authBasic";
|
||||
const string kHandshakeSecond = RTSP_FIELD "handshakeSecond";
|
||||
const string kKeepAliveSecond = RTSP_FIELD "keepAliveSecond";
|
||||
const string kDirectProxy = RTSP_FIELD "directProxy";
|
||||
|
||||
static onceToken token([](){
|
||||
//默认Md5方式认证
|
||||
static onceToken token([]() {
|
||||
// 默认Md5方式认证
|
||||
mINI::Instance()[kAuthBasic] = 0;
|
||||
mINI::Instance()[kHandshakeSecond] = 15;
|
||||
mINI::Instance()[kKeepAliveSecond] = 15;
|
||||
mINI::Instance()[kDirectProxy] = 1;
|
||||
});
|
||||
} //namespace Rtsp
|
||||
} // namespace Rtsp
|
||||
|
||||
////////////RTMP服务器配置///////////
|
||||
namespace Rtmp {
|
||||
#define RTMP_FIELD "rtmp."
|
||||
const string kModifyStamp = RTMP_FIELD"modifyStamp";
|
||||
const string kHandshakeSecond = RTMP_FIELD"handshakeSecond";
|
||||
const string kKeepAliveSecond = RTMP_FIELD"keepAliveSecond";
|
||||
const string kModifyStamp = RTMP_FIELD "modifyStamp";
|
||||
const string kHandshakeSecond = RTMP_FIELD "handshakeSecond";
|
||||
const string kKeepAliveSecond = RTMP_FIELD "keepAliveSecond";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kModifyStamp] = false;
|
||||
mINI::Instance()[kHandshakeSecond] = 15;
|
||||
mINI::Instance()[kKeepAliveSecond] = 15;
|
||||
});
|
||||
} //namespace RTMP
|
||||
|
||||
} // namespace Rtmp
|
||||
|
||||
////////////RTP配置///////////
|
||||
namespace Rtp {
|
||||
#define RTP_FIELD "rtp."
|
||||
//RTP打包最大MTU,公网情况下更小
|
||||
const string kVideoMtuSize = RTP_FIELD"videoMtuSize";
|
||||
const string kAudioMtuSize = RTP_FIELD"audioMtuSize";
|
||||
//rtp包最大长度限制,单位是KB
|
||||
const string kRtpMaxSize = RTP_FIELD"rtpMaxSize";
|
||||
// RTP打包最大MTU,公网情况下更小
|
||||
const string kVideoMtuSize = RTP_FIELD "videoMtuSize";
|
||||
const string kAudioMtuSize = RTP_FIELD "audioMtuSize";
|
||||
// rtp包最大长度限制,单位是KB
|
||||
const string kRtpMaxSize = RTP_FIELD "rtpMaxSize";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kVideoMtuSize] = 1400;
|
||||
mINI::Instance()[kAudioMtuSize] = 600;
|
||||
mINI::Instance()[kRtpMaxSize] = 10;
|
||||
});
|
||||
} //namespace Rtsp
|
||||
} // namespace Rtp
|
||||
|
||||
////////////组播配置///////////
|
||||
namespace MultiCast {
|
||||
#define MULTI_FIELD "multicast."
|
||||
//组播分配起始地址
|
||||
const string kAddrMin = MULTI_FIELD"addrMin";
|
||||
//组播分配截止地址
|
||||
const string kAddrMax = MULTI_FIELD"addrMax";
|
||||
//组播TTL
|
||||
const string kUdpTTL = MULTI_FIELD"udpTTL";
|
||||
// 组播分配起始地址
|
||||
const string kAddrMin = MULTI_FIELD "addrMin";
|
||||
// 组播分配截止地址
|
||||
const string kAddrMax = MULTI_FIELD "addrMax";
|
||||
// 组播TTL
|
||||
const string kUdpTTL = MULTI_FIELD "udpTTL";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kAddrMin] = "239.0.0.0";
|
||||
mINI::Instance()[kAddrMax] = "239.255.255.255";
|
||||
mINI::Instance()[kUdpTTL] = 64;
|
||||
});
|
||||
} //namespace MultiCast
|
||||
} // namespace MultiCast
|
||||
|
||||
////////////录像配置///////////
|
||||
namespace Record {
|
||||
#define RECORD_FIELD "record."
|
||||
const string kAppName = RECORD_FIELD"appName";
|
||||
const string kSampleMS = RECORD_FIELD"sampleMS";
|
||||
const string kFileSecond = RECORD_FIELD"fileSecond";
|
||||
const string kFilePath = RECORD_FIELD"filePath";
|
||||
const string kFileBufSize = RECORD_FIELD"fileBufSize";
|
||||
const string kFastStart = RECORD_FIELD"fastStart";
|
||||
const string kFileRepeat = RECORD_FIELD"fileRepeat";
|
||||
const string kAppName = RECORD_FIELD "appName";
|
||||
const string kSampleMS = RECORD_FIELD "sampleMS";
|
||||
const string kFileSecond = RECORD_FIELD "fileSecond";
|
||||
const string kFilePath = RECORD_FIELD "filePath";
|
||||
const string kFileBufSize = RECORD_FIELD "fileBufSize";
|
||||
const string kFastStart = RECORD_FIELD "fastStart";
|
||||
const string kFileRepeat = RECORD_FIELD "fileRepeat";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kAppName] = "record";
|
||||
mINI::Instance()[kSampleMS] = 500;
|
||||
mINI::Instance()[kFileSecond] = 60*60;
|
||||
mINI::Instance()[kFileSecond] = 60 * 60;
|
||||
mINI::Instance()[kFilePath] = "./www";
|
||||
mINI::Instance()[kFileBufSize] = 64 * 1024;
|
||||
mINI::Instance()[kFastStart] = false;
|
||||
mINI::Instance()[kFileRepeat] = false;
|
||||
});
|
||||
} //namespace Record
|
||||
} // namespace Record
|
||||
|
||||
////////////HLS相关配置///////////
|
||||
namespace Hls {
|
||||
#define HLS_FIELD "hls."
|
||||
const string kSegmentDuration = HLS_FIELD"segDur";
|
||||
const string kSegmentNum = HLS_FIELD"segNum";
|
||||
const string kSegmentKeep = HLS_FIELD"segKeep";
|
||||
const string kSegmentRetain = HLS_FIELD"segRetain";
|
||||
const string kFileBufSize = HLS_FIELD"fileBufSize";
|
||||
const string kFilePath = HLS_FIELD"filePath";
|
||||
const string kBroadcastRecordTs = HLS_FIELD"broadcastRecordTs";
|
||||
const string kDeleteDelaySec = HLS_FIELD"deleteDelaySec";
|
||||
const string kSegmentDuration = HLS_FIELD "segDur";
|
||||
const string kSegmentNum = HLS_FIELD "segNum";
|
||||
const string kSegmentKeep = HLS_FIELD "segKeep";
|
||||
const string kSegmentRetain = HLS_FIELD "segRetain";
|
||||
const string kFileBufSize = HLS_FIELD "fileBufSize";
|
||||
const string kFilePath = HLS_FIELD "filePath";
|
||||
const string kBroadcastRecordTs = HLS_FIELD "broadcastRecordTs";
|
||||
const string kDeleteDelaySec = HLS_FIELD "deleteDelaySec";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kSegmentDuration] = 2;
|
||||
mINI::Instance()[kSegmentNum] = 3;
|
||||
mINI::Instance()[kSegmentKeep] = false;
|
||||
@ -273,28 +270,40 @@ static onceToken token([](){
|
||||
mINI::Instance()[kBroadcastRecordTs] = false;
|
||||
mINI::Instance()[kDeleteDelaySec] = 0;
|
||||
});
|
||||
} //namespace Hls
|
||||
|
||||
} // namespace Hls
|
||||
|
||||
////////////Rtp代理相关配置///////////
|
||||
namespace RtpProxy {
|
||||
#define RTP_PROXY_FIELD "rtp_proxy."
|
||||
const string kDumpDir = RTP_PROXY_FIELD"dumpDir";
|
||||
const string kTimeoutSec = RTP_PROXY_FIELD"timeoutSec";
|
||||
const string kDumpDir = RTP_PROXY_FIELD "dumpDir";
|
||||
const string kTimeoutSec = RTP_PROXY_FIELD "timeoutSec";
|
||||
const string kPortRange = RTP_PROXY_FIELD "port_range";
|
||||
const string KH264PT = RTP_PROXY_FIELD "h264_pt";
|
||||
const string KH265PT = RTP_PROXY_FIELD "h265_pt";
|
||||
const string KPSPT = RTP_PROXY_FIELD "ps_pt";
|
||||
const string KTSPT = RTP_PROXY_FIELD "ts_pt";
|
||||
const string KOpusPT = RTP_PROXY_FIELD "opus_pt";
|
||||
const string KG711UPT = RTP_PROXY_FIELD "g711u_pt";
|
||||
const string KG711APT = RTP_PROXY_FIELD "g711a_pt";
|
||||
|
||||
static onceToken token([](){
|
||||
static onceToken token([]() {
|
||||
mINI::Instance()[kDumpDir] = "";
|
||||
mINI::Instance()[kTimeoutSec] = 15;
|
||||
mINI::Instance()[kPortRange] = "30000-35000";
|
||||
mINI::Instance()[KH264PT] = 98;
|
||||
mINI::Instance()[KH265PT] = 99;
|
||||
mINI::Instance()[KPSPT] = 96;
|
||||
mINI::Instance()[KTSPT] = 33;
|
||||
mINI::Instance()[KOpusPT] = 100;
|
||||
mINI::Instance()[KG711UPT] = 0;
|
||||
mINI::Instance()[KG711APT] = 8;
|
||||
});
|
||||
} //namespace RtpProxy
|
||||
|
||||
} // namespace RtpProxy
|
||||
|
||||
namespace Client {
|
||||
const string kNetAdapter = "net_adapter";
|
||||
const string kRtpType = "rtp_type";
|
||||
const string kRtspUser = "rtsp_user" ;
|
||||
const string kRtspUser = "rtsp_user";
|
||||
const string kRtspPwd = "rtsp_pwd";
|
||||
const string kRtspPwdIsMD5 = "rtsp_pwd_md5";
|
||||
const string kTimeoutMS = "protocol_timeout_ms";
|
||||
@ -302,20 +311,20 @@ const string kMediaTimeoutMS = "media_timeout_ms";
|
||||
const string kBeatIntervalMS = "beat_interval_ms";
|
||||
const string kBenchmarkMode = "benchmark_mode";
|
||||
const string kWaitTrackReady = "wait_track_ready";
|
||||
}
|
||||
} // namespace Client
|
||||
|
||||
} // namespace mediakit
|
||||
} // namespace mediakit
|
||||
|
||||
#ifdef ENABLE_MEM_DEBUG
|
||||
|
||||
extern "C" {
|
||||
extern void *__real_malloc(size_t);
|
||||
extern void __real_free(void *);
|
||||
extern void *__real_realloc(void *ptr, size_t c);
|
||||
void *__wrap_malloc(size_t c);
|
||||
void __wrap_free(void *ptr);
|
||||
void *__wrap_calloc(size_t __nmemb, size_t __size);
|
||||
void *__wrap_realloc(void *ptr, size_t c);
|
||||
extern void *__real_malloc(size_t);
|
||||
extern void __real_free(void *);
|
||||
extern void *__real_realloc(void *ptr, size_t c);
|
||||
void *__wrap_malloc(size_t c);
|
||||
void __wrap_free(void *ptr);
|
||||
void *__wrap_calloc(size_t __nmemb, size_t __size);
|
||||
void *__wrap_realloc(void *ptr, size_t c);
|
||||
}
|
||||
|
||||
#define BLOCK_TYPES 16
|
||||
@ -344,8 +353,8 @@ std::vector<size_t> getBlockTypeSize() {
|
||||
class MemThreadInfo {
|
||||
public:
|
||||
using Ptr = std::shared_ptr<MemThreadInfo>;
|
||||
atomic<uint64_t> mem_usage{0};
|
||||
atomic<uint64_t> mem_block{0};
|
||||
atomic<uint64_t> mem_usage { 0 };
|
||||
atomic<uint64_t> mem_block { 0 };
|
||||
atomic<uint64_t> mem_block_map[BLOCK_TYPES];
|
||||
|
||||
static MemThreadInfo *Instance(bool is_thread_local) {
|
||||
@ -358,25 +367,21 @@ public:
|
||||
}
|
||||
|
||||
~MemThreadInfo() {
|
||||
//printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
|
||||
// printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
|
||||
}
|
||||
|
||||
MemThreadInfo(bool is_thread_local) {
|
||||
_is_thread_local = is_thread_local;
|
||||
if (_is_thread_local) {
|
||||
//确保所有线程退出后才能释放全局内存统计器
|
||||
// 确保所有线程退出后才能释放全局内存统计器
|
||||
total_mem = Instance(false);
|
||||
}
|
||||
//printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
|
||||
// printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
|
||||
}
|
||||
|
||||
void *operator new(size_t sz) {
|
||||
return __real_malloc(sz);
|
||||
}
|
||||
void *operator new(size_t sz) { return __real_malloc(sz); }
|
||||
|
||||
void operator delete(void *ptr) {
|
||||
__real_free(ptr);
|
||||
}
|
||||
void operator delete(void *ptr) { __real_free(ptr); }
|
||||
|
||||
void addBlock(size_t c) {
|
||||
if (total_mem) {
|
||||
@ -410,19 +415,15 @@ public:
|
||||
ptr->addBlock(1);
|
||||
}
|
||||
|
||||
~MemThreadInfoLocal() {
|
||||
ptr->delBlock(1);
|
||||
}
|
||||
~MemThreadInfoLocal() { ptr->delBlock(1); }
|
||||
|
||||
MemThreadInfo *get() const {
|
||||
return ptr;
|
||||
}
|
||||
MemThreadInfo *get() const { return ptr; }
|
||||
|
||||
private:
|
||||
MemThreadInfo *ptr;
|
||||
};
|
||||
|
||||
//该变量主要确保线程退出后才能释放MemThreadInfo变量
|
||||
// 该变量主要确保线程退出后才能释放MemThreadInfo变量
|
||||
static thread_local MemThreadInfoLocal s_thread_mem_info;
|
||||
|
||||
uint64_t getTotalMemUsage() {
|
||||
@ -456,7 +457,7 @@ public:
|
||||
static constexpr uint32_t kMagic = 0xFEFDFCFB;
|
||||
uint32_t magic;
|
||||
uint32_t size;
|
||||
MemThreadInfo* alloc_info;
|
||||
MemThreadInfo *alloc_info;
|
||||
char ptr;
|
||||
};
|
||||
|
||||
@ -465,10 +466,10 @@ public:
|
||||
#if (defined(__linux__) && !defined(ANDROID)) || defined(__MACH__)
|
||||
#define MAX_STACK_FRAMES 128
|
||||
#define MEM_WARING
|
||||
#include <execinfo.h>
|
||||
#include <limits.h>
|
||||
#include <sys/resource.h>
|
||||
#include <sys/wait.h>
|
||||
#include <execinfo.h>
|
||||
|
||||
static void print_mem_waring(size_t c) {
|
||||
void *array[MAX_STACK_FRAMES];
|
||||
@ -503,7 +504,7 @@ static void un_init_cookie(MemCookie *cookie) {
|
||||
|
||||
void *__wrap_malloc(size_t c) {
|
||||
c += MEM_OFFSET;
|
||||
auto cookie = (MemCookie *) __real_malloc(c);
|
||||
auto cookie = (MemCookie *)__real_malloc(c);
|
||||
if (cookie) {
|
||||
init_cookie(cookie, c);
|
||||
return &cookie->ptr;
|
||||
@ -515,7 +516,7 @@ void __wrap_free(void *ptr) {
|
||||
if (!ptr) {
|
||||
return;
|
||||
}
|
||||
auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET);
|
||||
auto cookie = (MemCookie *)((char *)ptr - MEM_OFFSET);
|
||||
if (cookie->magic != MemCookie::kMagic) {
|
||||
__real_free(ptr);
|
||||
return;
|
||||
@ -538,14 +539,14 @@ void *__wrap_realloc(void *ptr, size_t c) {
|
||||
return malloc(c);
|
||||
}
|
||||
|
||||
auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET);
|
||||
auto cookie = (MemCookie *)((char *)ptr - MEM_OFFSET);
|
||||
if (cookie->magic != MemCookie::kMagic) {
|
||||
return __real_realloc(ptr, c);
|
||||
}
|
||||
|
||||
un_init_cookie(cookie);
|
||||
c += MEM_OFFSET;
|
||||
cookie = (MemCookie *) __real_realloc(cookie, c);
|
||||
cookie = (MemCookie *)__real_realloc(cookie, c);
|
||||
if (cookie) {
|
||||
init_cookie(cookie, c);
|
||||
return &cookie->ptr;
|
||||
|
@ -8,35 +8,34 @@
|
||||
* may be found in the AUTHORS file in the root of the source tree.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef COMMON_CONFIG_H
|
||||
#define COMMON_CONFIG_H
|
||||
|
||||
#include <functional>
|
||||
#include "Util/NoticeCenter.h"
|
||||
#include "Util/mini.h"
|
||||
#include "Util/onceToken.h"
|
||||
#include "Util/NoticeCenter.h"
|
||||
#include "macros.h"
|
||||
#include <functional>
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
class ProtocolOption;
|
||||
|
||||
//加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件
|
||||
//加载配置文件成功后会触发kBroadcastUpdateConfig广播
|
||||
//如果指定的文件名(ini_path)为空,那么会加载默认配置文件
|
||||
//默认配置文件名为 /path/to/your/exe.ini
|
||||
//加载配置文件成功后返回true,否则返回false
|
||||
// 加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件
|
||||
// 加载配置文件成功后会触发kBroadcastUpdateConfig广播
|
||||
// 如果指定的文件名(ini_path)为空,那么会加载默认配置文件
|
||||
// 默认配置文件名为 /path/to/your/exe.ini
|
||||
// 加载配置文件成功后返回true,否则返回false
|
||||
bool loadIniConfig(const char *ini_path = nullptr);
|
||||
|
||||
////////////广播名称///////////
|
||||
namespace Broadcast {
|
||||
|
||||
//注册或反注册MediaSource事件广播
|
||||
// 注册或反注册MediaSource事件广播
|
||||
extern const std::string kBroadcastMediaChanged;
|
||||
#define BroadcastMediaChangedArgs const bool &bRegist, MediaSource &sender
|
||||
|
||||
//录制mp4文件成功后广播
|
||||
// 录制mp4文件成功后广播
|
||||
extern const std::string kBroadcastRecordMP4;
|
||||
#define BroadcastRecordMP4Args const RecordInfo &info
|
||||
|
||||
@ -44,285 +43,302 @@ extern const std::string kBroadcastRecordMP4;
|
||||
extern const std::string kBroadcastRecordTs;
|
||||
#define BroadcastRecordTsArgs const RecordInfo &info
|
||||
|
||||
//收到http api请求广播
|
||||
// 收到http api请求广播
|
||||
extern const std::string kBroadcastHttpRequest;
|
||||
#define BroadcastHttpRequestArgs const Parser &parser,const HttpSession::HttpResponseInvoker &invoker,bool &consumed,SockInfo &sender
|
||||
#define BroadcastHttpRequestArgs \
|
||||
const Parser &parser, const HttpSession::HttpResponseInvoker &invoker, bool &consumed, SockInfo &sender
|
||||
|
||||
//在http文件服务器中,收到http访问文件或目录的广播,通过该事件控制访问http目录的权限
|
||||
// 在http文件服务器中,收到http访问文件或目录的广播,通过该事件控制访问http目录的权限
|
||||
extern const std::string kBroadcastHttpAccess;
|
||||
#define BroadcastHttpAccessArgs const Parser &parser,const std::string &path,const bool &is_dir,const HttpSession::HttpAccessPathInvoker &invoker,SockInfo &sender
|
||||
#define BroadcastHttpAccessArgs \
|
||||
const Parser &parser, const std::string &path, const bool &is_dir, \
|
||||
const HttpSession::HttpAccessPathInvoker &invoker, SockInfo &sender
|
||||
|
||||
//在http文件服务器中,收到http访问文件或目录前的广播,通过该事件可以控制http url到文件路径的映射
|
||||
//在该事件中通过自行覆盖path参数,可以做到譬如根据虚拟主机或者app选择不同http根目录的目的
|
||||
// 在http文件服务器中,收到http访问文件或目录前的广播,通过该事件可以控制http url到文件路径的映射
|
||||
// 在该事件中通过自行覆盖path参数,可以做到譬如根据虚拟主机或者app选择不同http根目录的目的
|
||||
extern const std::string kBroadcastHttpBeforeAccess;
|
||||
#define BroadcastHttpBeforeAccessArgs const Parser &parser, std::string &path, SockInfo &sender
|
||||
|
||||
//该流是否需要认证?是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证
|
||||
// 该流是否需要认证?是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证
|
||||
extern const std::string kBroadcastOnGetRtspRealm;
|
||||
#define BroadcastOnGetRtspRealmArgs const MediaInfo &args,const RtspSession::onGetRealm &invoker,SockInfo &sender
|
||||
#define BroadcastOnGetRtspRealmArgs const MediaInfo &args, const RtspSession::onGetRealm &invoker, SockInfo &sender
|
||||
|
||||
//请求认证用户密码事件,user_name为用户名,must_no_encrypt如果为true,则必须提供明文密码(因为此时是base64认证方式),否则会导致认证失败
|
||||
//获取到密码后请调用invoker并输入对应类型的密码和密码类型,invoker执行时会匹配密码
|
||||
// 请求认证用户密码事件,user_name为用户名,must_no_encrypt如果为true,则必须提供明文密码(因为此时是base64认证方式),否则会导致认证失败
|
||||
// 获取到密码后请调用invoker并输入对应类型的密码和密码类型,invoker执行时会匹配密码
|
||||
extern const std::string kBroadcastOnRtspAuth;
|
||||
#define BroadcastOnRtspAuthArgs const MediaInfo &args,const std::string &realm,const std::string &user_name,const bool &must_no_encrypt,const RtspSession::onAuth &invoker,SockInfo &sender
|
||||
#define BroadcastOnRtspAuthArgs \
|
||||
const MediaInfo &args, const std::string &realm, const std::string &user_name, const bool &must_no_encrypt, \
|
||||
const RtspSession::onAuth &invoker, SockInfo &sender
|
||||
|
||||
//推流鉴权结果回调对象
|
||||
//如果err为空则代表鉴权成功
|
||||
// 推流鉴权结果回调对象
|
||||
// 如果err为空则代表鉴权成功
|
||||
using PublishAuthInvoker = std::function<void(const std::string &err, const ProtocolOption &option)>;
|
||||
|
||||
//收到rtsp/rtmp推流事件广播,通过该事件控制推流鉴权
|
||||
// 收到rtsp/rtmp推流事件广播,通过该事件控制推流鉴权
|
||||
extern const std::string kBroadcastMediaPublish;
|
||||
#define BroadcastMediaPublishArgs const MediaOriginType &type, const MediaInfo &args, const Broadcast::PublishAuthInvoker &invoker,SockInfo &sender
|
||||
#define BroadcastMediaPublishArgs \
|
||||
const MediaOriginType &type, const MediaInfo &args, const Broadcast::PublishAuthInvoker &invoker, SockInfo &sender
|
||||
|
||||
//播放鉴权结果回调对象
|
||||
//如果err为空则代表鉴权成功
|
||||
// 播放鉴权结果回调对象
|
||||
// 如果err为空则代表鉴权成功
|
||||
using AuthInvoker = std::function<void(const std::string &err)>;
|
||||
|
||||
//播放rtsp/rtmp/http-flv事件广播,通过该事件控制播放鉴权
|
||||
// 播放rtsp/rtmp/http-flv事件广播,通过该事件控制播放鉴权
|
||||
extern const std::string kBroadcastMediaPlayed;
|
||||
#define BroadcastMediaPlayedArgs const MediaInfo &args,const Broadcast::AuthInvoker &invoker,SockInfo &sender
|
||||
#define BroadcastMediaPlayedArgs const MediaInfo &args, const Broadcast::AuthInvoker &invoker, SockInfo &sender
|
||||
|
||||
//shell登录鉴权
|
||||
// shell登录鉴权
|
||||
extern const std::string kBroadcastShellLogin;
|
||||
#define BroadcastShellLoginArgs const std::string &user_name,const std::string &passwd,const Broadcast::AuthInvoker &invoker,SockInfo &sender
|
||||
#define BroadcastShellLoginArgs \
|
||||
const std::string &user_name, const std::string &passwd, const Broadcast::AuthInvoker &invoker, SockInfo &sender
|
||||
|
||||
//停止rtsp/rtmp/http-flv会话后流量汇报事件广播
|
||||
// 停止rtsp/rtmp/http-flv会话后流量汇报事件广播
|
||||
extern const std::string kBroadcastFlowReport;
|
||||
#define BroadcastFlowReportArgs const MediaInfo &args,const uint64_t &totalBytes,const uint64_t &totalDuration,const bool &isPlayer, SockInfo &sender
|
||||
#define BroadcastFlowReportArgs \
|
||||
const MediaInfo &args, const uint64_t &totalBytes, const uint64_t &totalDuration, const bool &isPlayer, \
|
||||
SockInfo &sender
|
||||
|
||||
//未找到流后会广播该事件,请在监听该事件后去拉流或其他方式产生流,这样就能按需拉流了
|
||||
// 未找到流后会广播该事件,请在监听该事件后去拉流或其他方式产生流,这样就能按需拉流了
|
||||
extern const std::string kBroadcastNotFoundStream;
|
||||
#define BroadcastNotFoundStreamArgs const MediaInfo &args, SockInfo &sender, const std::function<void()> &closePlayer
|
||||
|
||||
//某个流无人消费时触发,目的为了实现无人观看时主动断开拉流等业务逻辑
|
||||
// 某个流无人消费时触发,目的为了实现无人观看时主动断开拉流等业务逻辑
|
||||
extern const std::string kBroadcastStreamNoneReader;
|
||||
#define BroadcastStreamNoneReaderArgs MediaSource &sender
|
||||
|
||||
//更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播
|
||||
// 更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播
|
||||
extern const std::string kBroadcastReloadConfig;
|
||||
#define BroadcastReloadConfigArgs void
|
||||
|
||||
#define ReloadConfigTag ((void *)(0xFF))
|
||||
#define RELOAD_KEY(arg,key) \
|
||||
do { \
|
||||
decltype(arg) arg##_tmp = ::toolkit::mINI::Instance()[key]; \
|
||||
if (arg == arg##_tmp) { \
|
||||
return; \
|
||||
} \
|
||||
arg = arg##_tmp; \
|
||||
InfoL << "reload config:" << key << "=" << arg; \
|
||||
} while(0)
|
||||
#define ReloadConfigTag ((void *)(0xFF))
|
||||
#define RELOAD_KEY(arg, key) \
|
||||
do { \
|
||||
decltype(arg) arg##_tmp = ::toolkit::mINI::Instance()[key]; \
|
||||
if (arg == arg##_tmp) { \
|
||||
return; \
|
||||
} \
|
||||
arg = arg##_tmp; \
|
||||
InfoL << "reload config:" << key << "=" << arg; \
|
||||
} while (0)
|
||||
|
||||
//监听某个配置发送变更
|
||||
#define LISTEN_RELOAD_KEY(arg, key, ...) \
|
||||
do { \
|
||||
static ::toolkit::onceToken s_token_listen([](){ \
|
||||
::toolkit::NoticeCenter::Instance().addListener(ReloadConfigTag, \
|
||||
Broadcast::kBroadcastReloadConfig,[](BroadcastReloadConfigArgs) { \
|
||||
__VA_ARGS__; \
|
||||
}); \
|
||||
}); \
|
||||
} while(0)
|
||||
// 监听某个配置发送变更
|
||||
#define LISTEN_RELOAD_KEY(arg, key, ...) \
|
||||
do { \
|
||||
static ::toolkit::onceToken s_token_listen([]() { \
|
||||
::toolkit::NoticeCenter::Instance().addListener( \
|
||||
ReloadConfigTag, Broadcast::kBroadcastReloadConfig, [](BroadcastReloadConfigArgs) { __VA_ARGS__; }); \
|
||||
}); \
|
||||
} while (0)
|
||||
|
||||
#define GET_CONFIG(type, arg, key) \
|
||||
static type arg = ::toolkit::mINI::Instance()[key]; \
|
||||
LISTEN_RELOAD_KEY(arg, key, { \
|
||||
RELOAD_KEY(arg, key); \
|
||||
});
|
||||
#define GET_CONFIG(type, arg, key) \
|
||||
static type arg = ::toolkit::mINI::Instance()[key]; \
|
||||
LISTEN_RELOAD_KEY(arg, key, { RELOAD_KEY(arg, key); });
|
||||
|
||||
#define GET_CONFIG_FUNC(type, arg, key, ...) \
|
||||
static type arg; \
|
||||
do { \
|
||||
static ::toolkit::onceToken s_token_set([](){ \
|
||||
static auto lam = __VA_ARGS__ ; \
|
||||
static auto arg##_str = ::toolkit::mINI::Instance()[key]; \
|
||||
arg = lam(arg##_str); \
|
||||
LISTEN_RELOAD_KEY(arg, key, { \
|
||||
RELOAD_KEY(arg##_str, key); \
|
||||
arg = lam(arg##_str); \
|
||||
}); \
|
||||
}); \
|
||||
} while(0)
|
||||
#define GET_CONFIG_FUNC(type, arg, key, ...) \
|
||||
static type arg; \
|
||||
do { \
|
||||
static ::toolkit::onceToken s_token_set([]() { \
|
||||
static auto lam = __VA_ARGS__; \
|
||||
static auto arg##_str = ::toolkit::mINI::Instance()[key]; \
|
||||
arg = lam(arg##_str); \
|
||||
LISTEN_RELOAD_KEY(arg, key, { \
|
||||
RELOAD_KEY(arg##_str, key); \
|
||||
arg = lam(arg##_str); \
|
||||
}); \
|
||||
}); \
|
||||
} while (0)
|
||||
|
||||
} //namespace Broadcast
|
||||
} // namespace Broadcast
|
||||
|
||||
////////////通用配置///////////
|
||||
namespace General{
|
||||
//每个流媒体服务器的ID(GUID)
|
||||
namespace General {
|
||||
// 每个流媒体服务器的ID(GUID)
|
||||
extern const std::string kMediaServerId;
|
||||
//流量汇报事件流量阈值,单位KB,默认1MB
|
||||
// 流量汇报事件流量阈值,单位KB,默认1MB
|
||||
extern const std::string kFlowThreshold;
|
||||
//流无人观看并且超过若干时间后才触发kBroadcastStreamNoneReader事件
|
||||
//默认连续5秒无人观看然后触发kBroadcastStreamNoneReader事件
|
||||
// 流无人观看并且超过若干时间后才触发kBroadcastStreamNoneReader事件
|
||||
// 默认连续5秒无人观看然后触发kBroadcastStreamNoneReader事件
|
||||
extern const std::string kStreamNoneReaderDelayMS;
|
||||
//等待流注册超时时间,收到播放器后请求后,如果未找到相关流,服务器会等待一定时间,
|
||||
//如果在这个时间内,相关流注册上了,那么服务器会立即响应播放器播放成功,
|
||||
//否则会最多等待kMaxStreamWaitTimeMS毫秒,然后响应播放器播放失败
|
||||
// 等待流注册超时时间,收到播放器后请求后,如果未找到相关流,服务器会等待一定时间,
|
||||
// 如果在这个时间内,相关流注册上了,那么服务器会立即响应播放器播放成功,
|
||||
// 否则会最多等待kMaxStreamWaitTimeMS毫秒,然后响应播放器播放失败
|
||||
extern const std::string kMaxStreamWaitTimeMS;
|
||||
//是否启动虚拟主机
|
||||
// 是否启动虚拟主机
|
||||
extern const std::string kEnableVhost;
|
||||
//拉流代理时是否添加静音音频
|
||||
// 拉流代理时是否添加静音音频
|
||||
extern const std::string kAddMuteAudio;
|
||||
//拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
|
||||
//如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
|
||||
// 拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
|
||||
// 如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
|
||||
extern const std::string kResetWhenRePlay;
|
||||
//是否默认推流时转换成hls,hook接口(on_publish)中可以覆盖该设置
|
||||
extern const std::string kPublishToHls ;
|
||||
//是否默认推流时mp4录像,hook接口(on_publish)中可以覆盖该设置
|
||||
extern const std::string kPublishToMP4 ;
|
||||
//合并写缓存大小(单位毫秒),合并写指服务器缓存一定的数据后才会一次性写入socket,这样能提高性能,但是会提高延时
|
||||
//开启后会同时关闭TCP_NODELAY并开启MSG_MORE
|
||||
extern const std::string kMergeWriteMS ;
|
||||
//全局的时间戳覆盖开关,在转协议时,对frame进行时间戳覆盖
|
||||
// 是否默认推流时转换成hls,hook接口(on_publish)中可以覆盖该设置
|
||||
extern const std::string kPublishToHls;
|
||||
// 是否默认推流时mp4录像,hook接口(on_publish)中可以覆盖该设置
|
||||
extern const std::string kPublishToMP4;
|
||||
// 合并写缓存大小(单位毫秒),合并写指服务器缓存一定的数据后才会一次性写入socket,这样能提高性能,但是会提高延时
|
||||
// 开启后会同时关闭TCP_NODELAY并开启MSG_MORE
|
||||
extern const std::string kMergeWriteMS;
|
||||
// 全局的时间戳覆盖开关,在转协议时,对frame进行时间戳覆盖
|
||||
extern const std::string kModifyStamp;
|
||||
//按需转协议的开关
|
||||
// 按需转协议的开关
|
||||
extern const std::string kHlsDemand;
|
||||
extern const std::string kRtspDemand;
|
||||
extern const std::string kRtmpDemand;
|
||||
extern const std::string kTSDemand;
|
||||
extern const std::string kFMP4Demand;
|
||||
//转协议是否全局开启或忽略音频
|
||||
// 转协议是否全局开启或忽略音频
|
||||
extern const std::string kEnableAudio;
|
||||
//在docker环境下,不能通过英伟达驱动是否存在来判断是否支持硬件转码
|
||||
// 在docker环境下,不能通过英伟达驱动是否存在来判断是否支持硬件转码
|
||||
extern const std::string kCheckNvidiaDev;
|
||||
//是否开启ffmpeg日志
|
||||
// 是否开启ffmpeg日志
|
||||
extern const std::string kEnableFFmpegLog;
|
||||
//最多等待未初始化的Track 10秒,超时之后会忽略未初始化的Track
|
||||
// 最多等待未初始化的Track 10秒,超时之后会忽略未初始化的Track
|
||||
extern const std::string kWaitTrackReadyMS;
|
||||
//如果直播流只有单Track,最多等待3秒,超时后未收到其他Track的数据,则认为是单Track
|
||||
//如果协议元数据有声明特定track数,那么无此等待时间
|
||||
// 如果直播流只有单Track,最多等待3秒,超时后未收到其他Track的数据,则认为是单Track
|
||||
// 如果协议元数据有声明特定track数,那么无此等待时间
|
||||
extern const std::string kWaitAddTrackMS;
|
||||
//如果track未就绪,我们先缓存帧数据,但是有最大个数限制(100帧时大约4秒),防止内存溢出
|
||||
// 如果track未就绪,我们先缓存帧数据,但是有最大个数限制(100帧时大约4秒),防止内存溢出
|
||||
extern const std::string kUnreadyFrameCache;
|
||||
//推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。
|
||||
//置0关闭此特性(推流断开会导致立即断开播放器)
|
||||
// 推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。
|
||||
// 置0关闭此特性(推流断开会导致立即断开播放器)
|
||||
extern const std::string kContinuePushMS;
|
||||
}//namespace General
|
||||
|
||||
} // namespace General
|
||||
|
||||
////////////HTTP配置///////////
|
||||
namespace Http {
|
||||
//http 文件发送缓存大小
|
||||
// http 文件发送缓存大小
|
||||
extern const std::string kSendBufSize;
|
||||
//http 最大请求字节数
|
||||
// http 最大请求字节数
|
||||
extern const std::string kMaxReqSize;
|
||||
//http keep-alive秒数
|
||||
// http keep-alive秒数
|
||||
extern const std::string kKeepAliveSecond;
|
||||
//http 字符编码
|
||||
// http 字符编码
|
||||
extern const std::string kCharSet;
|
||||
//http 服务器根目录
|
||||
// http 服务器根目录
|
||||
extern const std::string kRootPath;
|
||||
//http 服务器虚拟目录 虚拟目录名和文件路径使用","隔开,多个配置路径间用";"隔开,例如 path_d,d:/record;path_e,e:/record
|
||||
// http 服务器虚拟目录 虚拟目录名和文件路径使用","隔开,多个配置路径间用";"隔开,例如 path_d,d:/record;path_e,e:/record
|
||||
extern const std::string kVirtualPath;
|
||||
//http 404错误提示内容
|
||||
// http 404错误提示内容
|
||||
extern const std::string kNotFound;
|
||||
//是否显示文件夹菜单
|
||||
// 是否显示文件夹菜单
|
||||
extern const std::string kDirMenu;
|
||||
//禁止缓存文件的后缀
|
||||
// 禁止缓存文件的后缀
|
||||
extern const std::string kForbidCacheSuffix;
|
||||
}//namespace Http
|
||||
} // namespace Http
|
||||
|
||||
////////////SHELL配置///////////
|
||||
namespace Shell {
|
||||
extern const std::string kMaxReqSize;
|
||||
} //namespace Shell
|
||||
} // namespace Shell
|
||||
|
||||
////////////RTSP服务器配置///////////
|
||||
namespace Rtsp {
|
||||
//是否优先base64方式认证?默认Md5方式认证
|
||||
// 是否优先base64方式认证?默认Md5方式认证
|
||||
extern const std::string kAuthBasic;
|
||||
//握手超时时间,默认15秒
|
||||
// 握手超时时间,默认15秒
|
||||
extern const std::string kHandshakeSecond;
|
||||
//维持链接超时时间,默认15秒
|
||||
// 维持链接超时时间,默认15秒
|
||||
extern const std::string kKeepAliveSecond;
|
||||
|
||||
//rtsp拉流代理是否直接代理
|
||||
//直接代理后支持任意编码格式,但是会导致GOP缓存无法定位到I帧,可能会导致开播花屏
|
||||
//并且如果是tcp方式拉流,如果rtp大于mtu会导致无法使用udp方式代理
|
||||
//假定您的拉流源地址不是264或265或AAC,那么你可以使用直接代理的方式来支持rtsp代理
|
||||
//默认开启rtsp直接代理,rtmp由于没有这些问题,是强制开启直接代理的
|
||||
// rtsp拉流代理是否直接代理
|
||||
// 直接代理后支持任意编码格式,但是会导致GOP缓存无法定位到I帧,可能会导致开播花屏
|
||||
// 并且如果是tcp方式拉流,如果rtp大于mtu会导致无法使用udp方式代理
|
||||
// 假定您的拉流源地址不是264或265或AAC,那么你可以使用直接代理的方式来支持rtsp代理
|
||||
// 默认开启rtsp直接代理,rtmp由于没有这些问题,是强制开启直接代理的
|
||||
extern const std::string kDirectProxy;
|
||||
} //namespace Rtsp
|
||||
} // namespace Rtsp
|
||||
|
||||
////////////RTMP服务器配置///////////
|
||||
namespace Rtmp {
|
||||
//rtmp推流时间戳覆盖开关
|
||||
// rtmp推流时间戳覆盖开关
|
||||
extern const std::string kModifyStamp;
|
||||
//握手超时时间,默认15秒
|
||||
// 握手超时时间,默认15秒
|
||||
extern const std::string kHandshakeSecond;
|
||||
//维持链接超时时间,默认15秒
|
||||
// 维持链接超时时间,默认15秒
|
||||
extern const std::string kKeepAliveSecond;
|
||||
} //namespace RTMP
|
||||
|
||||
} // namespace Rtmp
|
||||
|
||||
////////////RTP配置///////////
|
||||
namespace Rtp {
|
||||
//RTP打包最大MTU,公网情况下更小
|
||||
// RTP打包最大MTU,公网情况下更小
|
||||
extern const std::string kVideoMtuSize;
|
||||
//RTP打包最大MTU,公网情况下更小
|
||||
// RTP打包最大MTU,公网情况下更小
|
||||
extern const std::string kAudioMtuSize;
|
||||
//rtp包最大长度限制, 单位KB
|
||||
// rtp包最大长度限制, 单位KB
|
||||
extern const std::string kRtpMaxSize;
|
||||
} //namespace Rtsp
|
||||
} // namespace Rtp
|
||||
|
||||
////////////组播配置///////////
|
||||
namespace MultiCast {
|
||||
//组播分配起始地址
|
||||
// 组播分配起始地址
|
||||
extern const std::string kAddrMin;
|
||||
//组播分配截止地址
|
||||
// 组播分配截止地址
|
||||
extern const std::string kAddrMax;
|
||||
//组播TTL
|
||||
// 组播TTL
|
||||
extern const std::string kUdpTTL;
|
||||
} //namespace MultiCast
|
||||
} // namespace MultiCast
|
||||
|
||||
////////////录像配置///////////
|
||||
namespace Record {
|
||||
//查看录像的应用名称
|
||||
// 查看录像的应用名称
|
||||
extern const std::string kAppName;
|
||||
//每次流化MP4文件的时长,单位毫秒
|
||||
// 每次流化MP4文件的时长,单位毫秒
|
||||
extern const std::string kSampleMS;
|
||||
//MP4文件录制大小,默认一个小时
|
||||
// MP4文件录制大小,默认一个小时
|
||||
extern const std::string kFileSecond;
|
||||
//录制文件路径
|
||||
// 录制文件路径
|
||||
extern const std::string kFilePath;
|
||||
//mp4文件写缓存大小
|
||||
// mp4文件写缓存大小
|
||||
extern const std::string kFileBufSize;
|
||||
//mp4录制完成后是否进行二次关键帧索引写入头部
|
||||
// mp4录制完成后是否进行二次关键帧索引写入头部
|
||||
extern const std::string kFastStart;
|
||||
//mp4文件是否重头循环读取
|
||||
// mp4文件是否重头循环读取
|
||||
extern const std::string kFileRepeat;
|
||||
} //namespace Record
|
||||
} // namespace Record
|
||||
|
||||
////////////HLS相关配置///////////
|
||||
namespace Hls {
|
||||
//HLS切片时长,单位秒
|
||||
// HLS切片时长,单位秒
|
||||
extern const std::string kSegmentDuration;
|
||||
//m3u8文件中HLS切片个数,如果设置为0,则不删除切片,而是保存为点播
|
||||
// m3u8文件中HLS切片个数,如果设置为0,则不删除切片,而是保存为点播
|
||||
extern const std::string kSegmentNum;
|
||||
//如果设置为0,则不保留切片,设置为1则一直保留切片
|
||||
// 如果设置为0,则不保留切片,设置为1则一直保留切片
|
||||
extern const std::string kSegmentKeep;
|
||||
//HLS切片从m3u8文件中移除后,继续保留在磁盘上的个数
|
||||
// HLS切片从m3u8文件中移除后,继续保留在磁盘上的个数
|
||||
extern const std::string kSegmentRetain;
|
||||
//HLS文件写缓存大小
|
||||
// HLS文件写缓存大小
|
||||
extern const std::string kFileBufSize;
|
||||
//录制文件路径
|
||||
// 录制文件路径
|
||||
extern const std::string kFilePath;
|
||||
// 是否广播 ts 切片完成通知
|
||||
extern const std::string kBroadcastRecordTs;
|
||||
//hls直播文件删除延时,单位秒
|
||||
// hls直播文件删除延时,单位秒
|
||||
extern const std::string kDeleteDelaySec;
|
||||
} //namespace Hls
|
||||
} // namespace Hls
|
||||
|
||||
////////////Rtp代理相关配置///////////
|
||||
namespace RtpProxy {
|
||||
//rtp调试数据保存目录,置空则不生成
|
||||
// rtp调试数据保存目录,置空则不生成
|
||||
extern const std::string kDumpDir;
|
||||
//rtp接收超时时间
|
||||
// rtp接收超时时间
|
||||
extern const std::string kTimeoutSec;
|
||||
//随机端口范围,最少确保36个端口
|
||||
//该范围同时限制rtsp服务器udp端口范围
|
||||
// 随机端口范围,最少确保36个端口
|
||||
// 该范围同时限制rtsp服务器udp端口范围
|
||||
extern const std::string kPortRange;
|
||||
} //namespace RtpProxy
|
||||
// rtp server h264的pt
|
||||
extern const std::string KH264PT;
|
||||
// rtp server h265的pt
|
||||
extern const std::string KH265PT;
|
||||
// rtp server ps 的pt
|
||||
extern const std::string KPSPT;
|
||||
// rtp server ts 的pt
|
||||
extern const std::string KTSPT;
|
||||
// rtp server opus 的pt
|
||||
extern const std::string KOpusPT;
|
||||
// rtp server g711u 的pt
|
||||
extern const std::string KG711UPT;
|
||||
// rtp server g711a 的pt
|
||||
extern const std::string KG711APT;
|
||||
} // namespace RtpProxy
|
||||
|
||||
/**
|
||||
* rtsp/rtmp播放器、推流器相关设置名,
|
||||
@ -330,28 +346,28 @@ extern const std::string kPortRange;
|
||||
* 只用于设置某个播放器或推流器实例用
|
||||
*/
|
||||
namespace Client {
|
||||
//指定网卡ip
|
||||
// 指定网卡ip
|
||||
extern const std::string kNetAdapter;
|
||||
//设置rtp传输类型,可选项有0(tcp,默认)、1(udp)、2(组播)
|
||||
//设置方法:player[PlayerBase::kRtpType] = 0/1/2;
|
||||
// 设置rtp传输类型,可选项有0(tcp,默认)、1(udp)、2(组播)
|
||||
// 设置方法:player[PlayerBase::kRtpType] = 0/1/2;
|
||||
extern const std::string kRtpType;
|
||||
//rtsp认证用户名
|
||||
// rtsp认证用户名
|
||||
extern const std::string kRtspUser;
|
||||
//rtsp认证用用户密码,可以是明文也可以是md5,md5密码生成方式 md5(username:realm:password)
|
||||
// rtsp认证用用户密码,可以是明文也可以是md5,md5密码生成方式 md5(username:realm:password)
|
||||
extern const std::string kRtspPwd;
|
||||
//rtsp认证用用户密码是否为md5类型
|
||||
// rtsp认证用用户密码是否为md5类型
|
||||
extern const std::string kRtspPwdIsMD5;
|
||||
//握手超时时间,默认10,000 毫秒
|
||||
// 握手超时时间,默认10,000 毫秒
|
||||
extern const std::string kTimeoutMS;
|
||||
//rtp/rtmp包接收超时时间,默认5000秒
|
||||
// rtp/rtmp包接收超时时间,默认5000秒
|
||||
extern const std::string kMediaTimeoutMS;
|
||||
//rtsp/rtmp心跳时间,默认5000毫秒
|
||||
// rtsp/rtmp心跳时间,默认5000毫秒
|
||||
extern const std::string kBeatIntervalMS;
|
||||
//是否为性能测试模式,性能测试模式开启后不会解析rtp或rtmp包
|
||||
// 是否为性能测试模式,性能测试模式开启后不会解析rtp或rtmp包
|
||||
extern const std::string kBenchmarkMode;
|
||||
//播放器在触发播放成功事件时,是否等待所有track ready时再回调
|
||||
// 播放器在触发播放成功事件时,是否等待所有track ready时再回调
|
||||
extern const std::string kWaitTrackReady;
|
||||
}
|
||||
} // namespace mediakit
|
||||
} // namespace Client
|
||||
} // namespace mediakit
|
||||
|
||||
#endif /* COMMON_CONFIG_H */
|
||||
|
@ -10,21 +10,21 @@
|
||||
|
||||
#if defined(ENABLE_RTPPROXY)
|
||||
#include "GB28181Process.h"
|
||||
#include "Util/File.h"
|
||||
#include "Http/HttpTSPlayer.h"
|
||||
#include "Extension/CommonRtp.h"
|
||||
#include "Extension/H264Rtp.h"
|
||||
#include "Extension/Factory.h"
|
||||
#include "Extension/Opus.h"
|
||||
#include "Extension/G711.h"
|
||||
#include "Extension/H264Rtp.h"
|
||||
#include "Extension/H265.h"
|
||||
#include "Extension/Opus.h"
|
||||
#include "Http/HttpTSPlayer.h"
|
||||
#include "Util/File.h"
|
||||
|
||||
using namespace std;
|
||||
using namespace toolkit;
|
||||
|
||||
namespace mediakit {
|
||||
|
||||
//判断是否为ts负载
|
||||
// 判断是否为ts负载
|
||||
static inline bool checkTS(const uint8_t *packet, size_t bytes) {
|
||||
return bytes % TS_PACKET_SIZE == 0 && packet[0] == TS_SYNC_BYTE;
|
||||
}
|
||||
@ -37,13 +37,13 @@ public:
|
||||
_sample_rate = sample_rate;
|
||||
setOnSorted(std::move(cb));
|
||||
setBeforeSorted(std::move(cb_before));
|
||||
//GB28181推流不支持ntp时间戳
|
||||
// GB28181推流不支持ntp时间戳
|
||||
setNtpStamp(0, 0);
|
||||
}
|
||||
|
||||
~RtpReceiverImp() override = default;
|
||||
|
||||
bool inputRtp(TrackType type, uint8_t *ptr, size_t len){
|
||||
bool inputRtp(TrackType type, uint8_t *ptr, size_t len) {
|
||||
return RtpTrack::inputRtp(type, _sample_rate, ptr, len).operator bool();
|
||||
}
|
||||
|
||||
@ -66,119 +66,101 @@ void GB28181Process::onRtpSorted(RtpPacket::Ptr rtp) {
|
||||
}
|
||||
|
||||
bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
|
||||
RtpHeader *header = (RtpHeader *) data;
|
||||
GET_CONFIG(uint32_t, h264_pt, RtpProxy::KH264PT);
|
||||
GET_CONFIG(uint32_t, h265_pt, RtpProxy::KH265PT);
|
||||
GET_CONFIG(uint32_t, ps_pt, RtpProxy::KPSPT);
|
||||
GET_CONFIG(uint32_t, ts_pt, RtpProxy::KTSPT);
|
||||
GET_CONFIG(uint32_t, opus_pt, RtpProxy::KOpusPT);
|
||||
GET_CONFIG(uint32_t, g711u_pt, RtpProxy::KG711UPT);
|
||||
GET_CONFIG(uint32_t, g711a_pt, RtpProxy::KG711APT);
|
||||
|
||||
RtpHeader *header = (RtpHeader *)data;
|
||||
auto pt = header->pt;
|
||||
auto &ref = _rtp_receiver[pt];
|
||||
if (!ref) {
|
||||
if (_rtp_receiver.size() > 2) {
|
||||
//防止pt类型太多导致内存溢出
|
||||
// 防止pt类型太多导致内存溢出
|
||||
throw std::invalid_argument("rtp pt类型不得超过2种!");
|
||||
}
|
||||
switch (pt) {
|
||||
case 100: {
|
||||
//opus负载
|
||||
ref = std::make_shared<RtpReceiverImp>(48000,[this](RtpPacket::Ptr rtp) {
|
||||
onRtpSorted(std::move(rtp));
|
||||
});
|
||||
if (pt == opus_pt) {
|
||||
// opus负载
|
||||
ref = std::make_shared<RtpReceiverImp>(48000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
|
||||
auto track = std::make_shared<OpusTrack>();
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
break;
|
||||
auto track = std::make_shared<OpusTrack>();
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
} else if (pt == h265_pt) {
|
||||
// H265负载
|
||||
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
|
||||
auto track = std::make_shared<H265Track>();
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
} else if (pt == h264_pt) {
|
||||
// H264负载
|
||||
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
|
||||
auto track = std::make_shared<H264Track>();
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
} else if (pt == g711u_pt || pt == g711a_pt) {
|
||||
// CodecG711U
|
||||
// CodecG711A
|
||||
ref = std::make_shared<RtpReceiverImp>(8000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
|
||||
auto track = std::make_shared<G711Track>(pt == 0 ? CodecG711U : CodecG711A, 8000, 1, 16);
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
} else {
|
||||
if (pt != ts_pt && pt != ps_pt) {
|
||||
WarnL << "rtp payload type未识别(" << (int)pt << "),已按ts或ps负载处理";
|
||||
}
|
||||
|
||||
case 99: {
|
||||
//H265负载
|
||||
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
|
||||
onRtpSorted(std::move(rtp));
|
||||
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
|
||||
|
||||
// ts或ps负载
|
||||
_rtp_decoder[pt] = std::make_shared<CommonRtpDecoder>(CodecInvalid, 32 * 1024);
|
||||
// 设置dump目录
|
||||
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
|
||||
if (!dump_dir.empty()) {
|
||||
auto save_path = File::absolutePath(_media_info._streamid + ".mp2", dump_dir);
|
||||
_save_file_ps.reset(File::create_file(save_path.data(), "wb"), [](FILE *fp) {
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
});
|
||||
|
||||
auto track = std::make_shared<H265Track>();
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
break;
|
||||
}
|
||||
case 98: {
|
||||
//H264负载
|
||||
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
|
||||
onRtpSorted(std::move(rtp));
|
||||
});
|
||||
|
||||
auto track = std::make_shared<H264Track>();
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
break;
|
||||
}
|
||||
|
||||
case 0:
|
||||
//CodecG711U
|
||||
case 8: {
|
||||
//CodecG711A
|
||||
ref = std::make_shared<RtpReceiverImp>(8000,[this](RtpPacket::Ptr rtp) {
|
||||
onRtpSorted(std::move(rtp));
|
||||
});
|
||||
|
||||
auto track = std::make_shared<G711Track>(pt == 0 ? CodecG711U : CodecG711A, 8000, 1, 16);
|
||||
_interface->addTrack(track);
|
||||
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
|
||||
break;
|
||||
}
|
||||
|
||||
default: {
|
||||
if (pt != 33 && pt != 96) {
|
||||
WarnL << "rtp payload type未识别(" << (int) pt << "),已按ts或ps负载处理";
|
||||
}
|
||||
|
||||
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
|
||||
onRtpSorted(std::move(rtp));
|
||||
});
|
||||
|
||||
//ts或ps负载
|
||||
_rtp_decoder[pt] = std::make_shared<CommonRtpDecoder>(CodecInvalid, 32 * 1024);
|
||||
//设置dump目录
|
||||
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
|
||||
if (!dump_dir.empty()) {
|
||||
auto save_path = File::absolutePath(_media_info._streamid + ".mp2", dump_dir);
|
||||
_save_file_ps.reset(File::create_file(save_path.data(), "wb"), [](FILE *fp) {
|
||||
if (fp) {
|
||||
fclose(fp);
|
||||
}
|
||||
});
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//设置frame回调
|
||||
// 设置frame回调
|
||||
_rtp_decoder[pt]->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([this](const Frame::Ptr &frame) {
|
||||
onRtpDecode(frame);
|
||||
return true;
|
||||
}));
|
||||
}
|
||||
|
||||
return ref->inputRtp(TrackVideo, (unsigned char *) data, data_len);
|
||||
return ref->inputRtp(TrackVideo, (unsigned char *)data, data_len);
|
||||
}
|
||||
|
||||
void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
|
||||
if (frame->getCodecId() != CodecInvalid) {
|
||||
//这里不是ps或ts
|
||||
// 这里不是ps或ts
|
||||
_interface->inputFrame(frame);
|
||||
return;
|
||||
}
|
||||
|
||||
//这是TS或PS
|
||||
// 这是TS或PS
|
||||
if (_save_file_ps) {
|
||||
fwrite(frame->data(), frame->size(), 1, _save_file_ps.get());
|
||||
}
|
||||
|
||||
if (!_decoder) {
|
||||
//创建解码器
|
||||
if (checkTS((uint8_t *) frame->data(), frame->size())) {
|
||||
//猜测是ts负载
|
||||
// 创建解码器
|
||||
if (checkTS((uint8_t *)frame->data(), frame->size())) {
|
||||
// 猜测是ts负载
|
||||
InfoL << _media_info._streamid << " judged to be TS";
|
||||
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
|
||||
} else {
|
||||
//猜测是ps负载
|
||||
// 猜测是ps负载
|
||||
InfoL << _media_info._streamid << " judged to be PS";
|
||||
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
|
||||
}
|
||||
@ -189,5 +171,5 @@ void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
|
||||
}
|
||||
}
|
||||
|
||||
}//namespace mediakit
|
||||
#endif//defined(ENABLE_RTPPROXY)
|
||||
} // namespace mediakit
|
||||
#endif // defined(ENABLE_RTPPROXY)
|
||||
|
Loading…
Reference in New Issue
Block a user