for rtp server can config pt

This commit is contained in:
xiongguangjie 2022-06-15 00:20:53 +08:00
parent 559b4d3fe7
commit 6a337adc91
4 changed files with 425 additions and 404 deletions

View File

@ -265,6 +265,28 @@ timeoutSec=15
#该范围同时限制rtsp服务器udp端口范围 #该范围同时限制rtsp服务器udp端口范围
port_range=30000-35000 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]
#rtc播放推流、播放超时时间 #rtc播放推流、播放超时时间
timeoutSec=15 timeoutSec=15

View File

@ -8,31 +8,31 @@
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#include <stdio.h>
#include <assert.h>
#include "Common/config.h" #include "Common/config.h"
#include "Util/util.h" #include "Util/NoticeCenter.h"
#include "Util/logger.h" #include "Util/logger.h"
#include "Util/onceToken.h" #include "Util/onceToken.h"
#include "Util/NoticeCenter.h" #include "Util/util.h"
#include <assert.h>
#include <stdio.h>
using namespace std; using namespace std;
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {
bool loadIniConfig(const char *ini_path){ bool loadIniConfig(const char *ini_path) {
string ini; string ini;
if(ini_path && ini_path[0] != '\0'){ if (ini_path && ini_path[0] != '\0') {
ini = ini_path; ini = ini_path;
}else{ } else {
ini = exePath() + ".ini"; ini = exePath() + ".ini";
} }
try{ try {
mINI::Instance().parseFile(ini); mINI::Instance().parseFile(ini);
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
return true; return true;
}catch (std::exception &) { } catch (std::exception &) {
InfoL << "dump ini file to:" << ini; InfoL << "dump ini file to:" << ini;
mINI::Instance().dumpFile(ini); mINI::Instance().dumpFile(ini);
return false; return false;
@ -55,36 +55,36 @@ const string kBroadcastShellLogin = "kBroadcastShellLogin";
const string kBroadcastNotFoundStream = "kBroadcastNotFoundStream"; const string kBroadcastNotFoundStream = "kBroadcastNotFoundStream";
const string kBroadcastStreamNoneReader = "kBroadcastStreamNoneReader"; const string kBroadcastStreamNoneReader = "kBroadcastStreamNoneReader";
const string kBroadcastHttpBeforeAccess = "kBroadcastHttpBeforeAccess"; const string kBroadcastHttpBeforeAccess = "kBroadcastHttpBeforeAccess";
} //namespace Broadcast } // namespace Broadcast
//通用配置项目 // 通用配置项目
namespace General{ namespace General {
#define GENERAL_FIELD "general." #define GENERAL_FIELD "general."
const string kMediaServerId = GENERAL_FIELD"mediaServerId"; const string kMediaServerId = GENERAL_FIELD "mediaServerId";
const string kFlowThreshold = GENERAL_FIELD"flowThreshold"; const string kFlowThreshold = GENERAL_FIELD "flowThreshold";
const string kStreamNoneReaderDelayMS = GENERAL_FIELD"streamNoneReaderDelayMS"; const string kStreamNoneReaderDelayMS = GENERAL_FIELD "streamNoneReaderDelayMS";
const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS"; const string kMaxStreamWaitTimeMS = GENERAL_FIELD "maxStreamWaitMS";
const string kEnableVhost = GENERAL_FIELD"enableVhost"; const string kEnableVhost = GENERAL_FIELD "enableVhost";
const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio"; const string kAddMuteAudio = GENERAL_FIELD "addMuteAudio";
const string kResetWhenRePlay = GENERAL_FIELD"resetWhenRePlay"; const string kResetWhenRePlay = GENERAL_FIELD "resetWhenRePlay";
const string kPublishToHls = GENERAL_FIELD"publishToHls"; const string kPublishToHls = GENERAL_FIELD "publishToHls";
const string kPublishToMP4 = GENERAL_FIELD"publishToMP4"; const string kPublishToMP4 = GENERAL_FIELD "publishToMP4";
const string kMergeWriteMS = GENERAL_FIELD"mergeWriteMS"; const string kMergeWriteMS = GENERAL_FIELD "mergeWriteMS";
const string kModifyStamp = GENERAL_FIELD"modifyStamp"; const string kModifyStamp = GENERAL_FIELD "modifyStamp";
const string kHlsDemand = GENERAL_FIELD"hls_demand"; const string kHlsDemand = GENERAL_FIELD "hls_demand";
const string kRtspDemand = GENERAL_FIELD"rtsp_demand"; const string kRtspDemand = GENERAL_FIELD "rtsp_demand";
const string kRtmpDemand = GENERAL_FIELD"rtmp_demand"; const string kRtmpDemand = GENERAL_FIELD "rtmp_demand";
const string kTSDemand = GENERAL_FIELD"ts_demand"; const string kTSDemand = GENERAL_FIELD "ts_demand";
const string kFMP4Demand = GENERAL_FIELD"fmp4_demand"; const string kFMP4Demand = GENERAL_FIELD "fmp4_demand";
const string kEnableAudio = GENERAL_FIELD"enable_audio"; const string kEnableAudio = GENERAL_FIELD "enable_audio";
const string kCheckNvidiaDev = GENERAL_FIELD"check_nvidia_dev"; const string kCheckNvidiaDev = GENERAL_FIELD "check_nvidia_dev";
const string kEnableFFmpegLog = GENERAL_FIELD"enable_ffmpeg_log"; const string kEnableFFmpegLog = GENERAL_FIELD "enable_ffmpeg_log";
const string kWaitTrackReadyMS = GENERAL_FIELD"wait_track_ready_ms"; const string kWaitTrackReadyMS = GENERAL_FIELD "wait_track_ready_ms";
const string kWaitAddTrackMS = GENERAL_FIELD"wait_add_track_ms"; const string kWaitAddTrackMS = GENERAL_FIELD "wait_add_track_ms";
const string kUnreadyFrameCache = GENERAL_FIELD"unready_frame_cache"; const string kUnreadyFrameCache = GENERAL_FIELD "unready_frame_cache";
const string kContinuePushMS = GENERAL_FIELD"continue_push_ms"; const string kContinuePushMS = GENERAL_FIELD "continue_push_ms";
static onceToken token([](){ static onceToken token([]() {
mINI::Instance()[kFlowThreshold] = 1024; mINI::Instance()[kFlowThreshold] = 1024;
mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000; mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000;
mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000; mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000;
@ -110,22 +110,22 @@ static onceToken token([](){
mINI::Instance()[kContinuePushMS] = 15 * 1000; mINI::Instance()[kContinuePushMS] = 15 * 1000;
}); });
}//namespace General } // namespace General
////////////HTTP配置/////////// ////////////HTTP配置///////////
namespace Http { namespace Http {
#define HTTP_FIELD "http." #define HTTP_FIELD "http."
const string kSendBufSize = HTTP_FIELD"sendBufSize"; const string kSendBufSize = HTTP_FIELD "sendBufSize";
const string kMaxReqSize = HTTP_FIELD"maxReqSize"; const string kMaxReqSize = HTTP_FIELD "maxReqSize";
const string kKeepAliveSecond = HTTP_FIELD"keepAliveSecond"; const string kKeepAliveSecond = HTTP_FIELD "keepAliveSecond";
const string kCharSet = HTTP_FIELD"charSet"; const string kCharSet = HTTP_FIELD "charSet";
const string kRootPath = HTTP_FIELD"rootPath"; const string kRootPath = HTTP_FIELD "rootPath";
const string kVirtualPath = HTTP_FIELD "virtualPath"; const string kVirtualPath = HTTP_FIELD "virtualPath";
const string kNotFound = HTTP_FIELD"notFound"; const string kNotFound = HTTP_FIELD "notFound";
const string kDirMenu = HTTP_FIELD"dirMenu"; const string kDirMenu = HTTP_FIELD "dirMenu";
const string kForbidCacheSuffix = HTTP_FIELD"forbidCacheSuffix"; const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix";
static onceToken token([](){ static onceToken token([]() {
mINI::Instance()[kSendBufSize] = 64 * 1024; mINI::Instance()[kSendBufSize] = 64 * 1024;
mINI::Instance()[kMaxReqSize] = 4 * 10240; mINI::Instance()[kMaxReqSize] = 4 * 10240;
mINI::Instance()[kKeepAliveSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15;
@ -135,7 +135,7 @@ static onceToken token([](){
#if defined(_WIN32) #if defined(_WIN32)
mINI::Instance()[kCharSet] = "gb2312"; mINI::Instance()[kCharSet] = "gb2312";
#else #else
mINI::Instance()[kCharSet] ="utf-8"; mINI::Instance()[kCharSet] = "utf-8";
#endif #endif
mINI::Instance()[kRootPath] = "./www"; mINI::Instance()[kRootPath] = "./www";
@ -149,121 +149,118 @@ static onceToken token([](){
"</body>" "</body>"
"</html>" "</html>"
<< endl; << endl;
mINI::Instance()[kForbidCacheSuffix] = ""; mINI::Instance()[kForbidCacheSuffix] = "";
}); });
}//namespace Http } // namespace Http
////////////SHELL配置/////////// ////////////SHELL配置///////////
namespace Shell { namespace Shell {
#define SHELL_FIELD "shell." #define SHELL_FIELD "shell."
const string kMaxReqSize = SHELL_FIELD"maxReqSize"; const string kMaxReqSize = SHELL_FIELD "maxReqSize";
static onceToken token([](){ static onceToken token([]() { mINI::Instance()[kMaxReqSize] = 1024; });
mINI::Instance()[kMaxReqSize] = 1024; } // namespace Shell
});
} //namespace Shell
////////////RTSP服务器配置/////////// ////////////RTSP服务器配置///////////
namespace Rtsp { namespace Rtsp {
#define RTSP_FIELD "rtsp." #define RTSP_FIELD "rtsp."
const string kAuthBasic = RTSP_FIELD"authBasic"; const string kAuthBasic = RTSP_FIELD "authBasic";
const string kHandshakeSecond = RTSP_FIELD"handshakeSecond"; const string kHandshakeSecond = RTSP_FIELD "handshakeSecond";
const string kKeepAliveSecond = RTSP_FIELD"keepAliveSecond"; const string kKeepAliveSecond = RTSP_FIELD "keepAliveSecond";
const string kDirectProxy = RTSP_FIELD"directProxy"; const string kDirectProxy = RTSP_FIELD "directProxy";
static onceToken token([](){ static onceToken token([]() {
//默认Md5方式认证 // 默认Md5方式认证
mINI::Instance()[kAuthBasic] = 0; mINI::Instance()[kAuthBasic] = 0;
mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kHandshakeSecond] = 15;
mINI::Instance()[kKeepAliveSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15;
mINI::Instance()[kDirectProxy] = 1; mINI::Instance()[kDirectProxy] = 1;
}); });
} //namespace Rtsp } // namespace Rtsp
////////////RTMP服务器配置/////////// ////////////RTMP服务器配置///////////
namespace Rtmp { namespace Rtmp {
#define RTMP_FIELD "rtmp." #define RTMP_FIELD "rtmp."
const string kModifyStamp = RTMP_FIELD"modifyStamp"; const string kModifyStamp = RTMP_FIELD "modifyStamp";
const string kHandshakeSecond = RTMP_FIELD"handshakeSecond"; const string kHandshakeSecond = RTMP_FIELD "handshakeSecond";
const string kKeepAliveSecond = RTMP_FIELD"keepAliveSecond"; const string kKeepAliveSecond = RTMP_FIELD "keepAliveSecond";
static onceToken token([](){ static onceToken token([]() {
mINI::Instance()[kModifyStamp] = false; mINI::Instance()[kModifyStamp] = false;
mINI::Instance()[kHandshakeSecond] = 15; mINI::Instance()[kHandshakeSecond] = 15;
mINI::Instance()[kKeepAliveSecond] = 15; mINI::Instance()[kKeepAliveSecond] = 15;
}); });
} //namespace RTMP } // namespace Rtmp
////////////RTP配置/////////// ////////////RTP配置///////////
namespace Rtp { namespace Rtp {
#define RTP_FIELD "rtp." #define RTP_FIELD "rtp."
//RTP打包最大MTU,公网情况下更小 // RTP打包最大MTU,公网情况下更小
const string kVideoMtuSize = RTP_FIELD"videoMtuSize"; const string kVideoMtuSize = RTP_FIELD "videoMtuSize";
const string kAudioMtuSize = RTP_FIELD"audioMtuSize"; const string kAudioMtuSize = RTP_FIELD "audioMtuSize";
//rtp包最大长度限制单位是KB // rtp包最大长度限制单位是KB
const string kRtpMaxSize = RTP_FIELD"rtpMaxSize"; const string kRtpMaxSize = RTP_FIELD "rtpMaxSize";
static onceToken token([](){ static onceToken token([]() {
mINI::Instance()[kVideoMtuSize] = 1400; mINI::Instance()[kVideoMtuSize] = 1400;
mINI::Instance()[kAudioMtuSize] = 600; mINI::Instance()[kAudioMtuSize] = 600;
mINI::Instance()[kRtpMaxSize] = 10; mINI::Instance()[kRtpMaxSize] = 10;
}); });
} //namespace Rtsp } // namespace Rtp
////////////组播配置/////////// ////////////组播配置///////////
namespace MultiCast { namespace MultiCast {
#define MULTI_FIELD "multicast." #define MULTI_FIELD "multicast."
//组播分配起始地址 // 组播分配起始地址
const string kAddrMin = MULTI_FIELD"addrMin"; const string kAddrMin = MULTI_FIELD "addrMin";
//组播分配截止地址 // 组播分配截止地址
const string kAddrMax = MULTI_FIELD"addrMax"; const string kAddrMax = MULTI_FIELD "addrMax";
//组播TTL // 组播TTL
const string kUdpTTL = MULTI_FIELD"udpTTL"; const string kUdpTTL = MULTI_FIELD "udpTTL";
static onceToken token([](){ static onceToken token([]() {
mINI::Instance()[kAddrMin] = "239.0.0.0"; mINI::Instance()[kAddrMin] = "239.0.0.0";
mINI::Instance()[kAddrMax] = "239.255.255.255"; mINI::Instance()[kAddrMax] = "239.255.255.255";
mINI::Instance()[kUdpTTL] = 64; mINI::Instance()[kUdpTTL] = 64;
}); });
} //namespace MultiCast } // namespace MultiCast
////////////录像配置/////////// ////////////录像配置///////////
namespace Record { namespace Record {
#define RECORD_FIELD "record." #define RECORD_FIELD "record."
const string kAppName = RECORD_FIELD"appName"; const string kAppName = RECORD_FIELD "appName";
const string kSampleMS = RECORD_FIELD"sampleMS"; const string kSampleMS = RECORD_FIELD "sampleMS";
const string kFileSecond = RECORD_FIELD"fileSecond"; const string kFileSecond = RECORD_FIELD "fileSecond";
const string kFilePath = RECORD_FIELD"filePath"; const string kFilePath = RECORD_FIELD "filePath";
const string kFileBufSize = RECORD_FIELD"fileBufSize"; const string kFileBufSize = RECORD_FIELD "fileBufSize";
const string kFastStart = RECORD_FIELD"fastStart"; const string kFastStart = RECORD_FIELD "fastStart";
const string kFileRepeat = RECORD_FIELD"fileRepeat"; const string kFileRepeat = RECORD_FIELD "fileRepeat";
static onceToken token([](){ static onceToken token([]() {
mINI::Instance()[kAppName] = "record"; mINI::Instance()[kAppName] = "record";
mINI::Instance()[kSampleMS] = 500; mINI::Instance()[kSampleMS] = 500;
mINI::Instance()[kFileSecond] = 60*60; mINI::Instance()[kFileSecond] = 60 * 60;
mINI::Instance()[kFilePath] = "./www"; mINI::Instance()[kFilePath] = "./www";
mINI::Instance()[kFileBufSize] = 64 * 1024; mINI::Instance()[kFileBufSize] = 64 * 1024;
mINI::Instance()[kFastStart] = false; mINI::Instance()[kFastStart] = false;
mINI::Instance()[kFileRepeat] = false; mINI::Instance()[kFileRepeat] = false;
}); });
} //namespace Record } // namespace Record
////////////HLS相关配置/////////// ////////////HLS相关配置///////////
namespace Hls { namespace Hls {
#define HLS_FIELD "hls." #define HLS_FIELD "hls."
const string kSegmentDuration = HLS_FIELD"segDur"; const string kSegmentDuration = HLS_FIELD "segDur";
const string kSegmentNum = HLS_FIELD"segNum"; const string kSegmentNum = HLS_FIELD "segNum";
const string kSegmentKeep = HLS_FIELD"segKeep"; const string kSegmentKeep = HLS_FIELD "segKeep";
const string kSegmentRetain = HLS_FIELD"segRetain"; const string kSegmentRetain = HLS_FIELD "segRetain";
const string kFileBufSize = HLS_FIELD"fileBufSize"; const string kFileBufSize = HLS_FIELD "fileBufSize";
const string kFilePath = HLS_FIELD"filePath"; const string kFilePath = HLS_FIELD "filePath";
const string kBroadcastRecordTs = HLS_FIELD"broadcastRecordTs"; const string kBroadcastRecordTs = HLS_FIELD "broadcastRecordTs";
const string kDeleteDelaySec = HLS_FIELD"deleteDelaySec"; const string kDeleteDelaySec = HLS_FIELD "deleteDelaySec";
static onceToken token([](){ static onceToken token([]() {
mINI::Instance()[kSegmentDuration] = 2; mINI::Instance()[kSegmentDuration] = 2;
mINI::Instance()[kSegmentNum] = 3; mINI::Instance()[kSegmentNum] = 3;
mINI::Instance()[kSegmentKeep] = false; mINI::Instance()[kSegmentKeep] = false;
@ -273,28 +270,40 @@ static onceToken token([](){
mINI::Instance()[kBroadcastRecordTs] = false; mINI::Instance()[kBroadcastRecordTs] = false;
mINI::Instance()[kDeleteDelaySec] = 0; mINI::Instance()[kDeleteDelaySec] = 0;
}); });
} //namespace Hls } // namespace Hls
////////////Rtp代理相关配置/////////// ////////////Rtp代理相关配置///////////
namespace RtpProxy { namespace RtpProxy {
#define RTP_PROXY_FIELD "rtp_proxy." #define RTP_PROXY_FIELD "rtp_proxy."
const string kDumpDir = RTP_PROXY_FIELD"dumpDir"; const string kDumpDir = RTP_PROXY_FIELD "dumpDir";
const string kTimeoutSec = RTP_PROXY_FIELD"timeoutSec"; const string kTimeoutSec = RTP_PROXY_FIELD "timeoutSec";
const string kPortRange = RTP_PROXY_FIELD "port_range"; 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()[kDumpDir] = "";
mINI::Instance()[kTimeoutSec] = 15; mINI::Instance()[kTimeoutSec] = 15;
mINI::Instance()[kPortRange] = "30000-35000"; 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 { namespace Client {
const string kNetAdapter = "net_adapter"; const string kNetAdapter = "net_adapter";
const string kRtpType = "rtp_type"; const string kRtpType = "rtp_type";
const string kRtspUser = "rtsp_user" ; const string kRtspUser = "rtsp_user";
const string kRtspPwd = "rtsp_pwd"; const string kRtspPwd = "rtsp_pwd";
const string kRtspPwdIsMD5 = "rtsp_pwd_md5"; const string kRtspPwdIsMD5 = "rtsp_pwd_md5";
const string kTimeoutMS = "protocol_timeout_ms"; const string kTimeoutMS = "protocol_timeout_ms";
@ -302,20 +311,20 @@ const string kMediaTimeoutMS = "media_timeout_ms";
const string kBeatIntervalMS = "beat_interval_ms"; const string kBeatIntervalMS = "beat_interval_ms";
const string kBenchmarkMode = "benchmark_mode"; const string kBenchmarkMode = "benchmark_mode";
const string kWaitTrackReady = "wait_track_ready"; const string kWaitTrackReady = "wait_track_ready";
} } // namespace Client
} // namespace mediakit } // namespace mediakit
#ifdef ENABLE_MEM_DEBUG #ifdef ENABLE_MEM_DEBUG
extern "C" { extern "C" {
extern void *__real_malloc(size_t); extern void *__real_malloc(size_t);
extern void __real_free(void *); extern void __real_free(void *);
extern void *__real_realloc(void *ptr, size_t c); extern void *__real_realloc(void *ptr, size_t c);
void *__wrap_malloc(size_t c); void *__wrap_malloc(size_t c);
void __wrap_free(void *ptr); void __wrap_free(void *ptr);
void *__wrap_calloc(size_t __nmemb, size_t __size); void *__wrap_calloc(size_t __nmemb, size_t __size);
void *__wrap_realloc(void *ptr, size_t c); void *__wrap_realloc(void *ptr, size_t c);
} }
#define BLOCK_TYPES 16 #define BLOCK_TYPES 16
@ -344,8 +353,8 @@ std::vector<size_t> getBlockTypeSize() {
class MemThreadInfo { class MemThreadInfo {
public: public:
using Ptr = std::shared_ptr<MemThreadInfo>; using Ptr = std::shared_ptr<MemThreadInfo>;
atomic<uint64_t> mem_usage{0}; atomic<uint64_t> mem_usage { 0 };
atomic<uint64_t> mem_block{0}; atomic<uint64_t> mem_block { 0 };
atomic<uint64_t> mem_block_map[BLOCK_TYPES]; atomic<uint64_t> mem_block_map[BLOCK_TYPES];
static MemThreadInfo *Instance(bool is_thread_local) { static MemThreadInfo *Instance(bool is_thread_local) {
@ -358,25 +367,21 @@ public:
} }
~MemThreadInfo() { ~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) { MemThreadInfo(bool is_thread_local) {
_is_thread_local = is_thread_local; _is_thread_local = is_thread_local;
if (_is_thread_local) { if (_is_thread_local) {
//确保所有线程退出后才能释放全局内存统计器 // 确保所有线程退出后才能释放全局内存统计器
total_mem = Instance(false); 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) { void *operator new(size_t sz) { return __real_malloc(sz); }
return __real_malloc(sz);
}
void operator delete(void *ptr) { void operator delete(void *ptr) { __real_free(ptr); }
__real_free(ptr);
}
void addBlock(size_t c) { void addBlock(size_t c) {
if (total_mem) { if (total_mem) {
@ -410,19 +415,15 @@ public:
ptr->addBlock(1); ptr->addBlock(1);
} }
~MemThreadInfoLocal() { ~MemThreadInfoLocal() { ptr->delBlock(1); }
ptr->delBlock(1);
}
MemThreadInfo *get() const { MemThreadInfo *get() const { return ptr; }
return ptr;
}
private: private:
MemThreadInfo *ptr; MemThreadInfo *ptr;
}; };
//该变量主要确保线程退出后才能释放MemThreadInfo变量 // 该变量主要确保线程退出后才能释放MemThreadInfo变量
static thread_local MemThreadInfoLocal s_thread_mem_info; static thread_local MemThreadInfoLocal s_thread_mem_info;
uint64_t getTotalMemUsage() { uint64_t getTotalMemUsage() {
@ -456,7 +457,7 @@ public:
static constexpr uint32_t kMagic = 0xFEFDFCFB; static constexpr uint32_t kMagic = 0xFEFDFCFB;
uint32_t magic; uint32_t magic;
uint32_t size; uint32_t size;
MemThreadInfo* alloc_info; MemThreadInfo *alloc_info;
char ptr; char ptr;
}; };
@ -465,10 +466,10 @@ public:
#if (defined(__linux__) && !defined(ANDROID)) || defined(__MACH__) #if (defined(__linux__) && !defined(ANDROID)) || defined(__MACH__)
#define MAX_STACK_FRAMES 128 #define MAX_STACK_FRAMES 128
#define MEM_WARING #define MEM_WARING
#include <execinfo.h>
#include <limits.h> #include <limits.h>
#include <sys/resource.h> #include <sys/resource.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <execinfo.h>
static void print_mem_waring(size_t c) { static void print_mem_waring(size_t c) {
void *array[MAX_STACK_FRAMES]; void *array[MAX_STACK_FRAMES];
@ -503,7 +504,7 @@ static void un_init_cookie(MemCookie *cookie) {
void *__wrap_malloc(size_t c) { void *__wrap_malloc(size_t c) {
c += MEM_OFFSET; c += MEM_OFFSET;
auto cookie = (MemCookie *) __real_malloc(c); auto cookie = (MemCookie *)__real_malloc(c);
if (cookie) { if (cookie) {
init_cookie(cookie, c); init_cookie(cookie, c);
return &cookie->ptr; return &cookie->ptr;
@ -515,7 +516,7 @@ void __wrap_free(void *ptr) {
if (!ptr) { if (!ptr) {
return; return;
} }
auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET); auto cookie = (MemCookie *)((char *)ptr - MEM_OFFSET);
if (cookie->magic != MemCookie::kMagic) { if (cookie->magic != MemCookie::kMagic) {
__real_free(ptr); __real_free(ptr);
return; return;
@ -538,14 +539,14 @@ void *__wrap_realloc(void *ptr, size_t c) {
return malloc(c); return malloc(c);
} }
auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET); auto cookie = (MemCookie *)((char *)ptr - MEM_OFFSET);
if (cookie->magic != MemCookie::kMagic) { if (cookie->magic != MemCookie::kMagic) {
return __real_realloc(ptr, c); return __real_realloc(ptr, c);
} }
un_init_cookie(cookie); un_init_cookie(cookie);
c += MEM_OFFSET; c += MEM_OFFSET;
cookie = (MemCookie *) __real_realloc(cookie, c); cookie = (MemCookie *)__real_realloc(cookie, c);
if (cookie) { if (cookie) {
init_cookie(cookie, c); init_cookie(cookie, c);
return &cookie->ptr; return &cookie->ptr;

View File

@ -8,35 +8,34 @@
* may be found in the AUTHORS file in the root of the source tree. * may be found in the AUTHORS file in the root of the source tree.
*/ */
#ifndef COMMON_CONFIG_H #ifndef COMMON_CONFIG_H
#define COMMON_CONFIG_H #define COMMON_CONFIG_H
#include <functional> #include "Util/NoticeCenter.h"
#include "Util/mini.h" #include "Util/mini.h"
#include "Util/onceToken.h" #include "Util/onceToken.h"
#include "Util/NoticeCenter.h"
#include "macros.h" #include "macros.h"
#include <functional>
namespace mediakit { namespace mediakit {
class ProtocolOption; class ProtocolOption;
//加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件 // 加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件
//加载配置文件成功后会触发kBroadcastUpdateConfig广播 // 加载配置文件成功后会触发kBroadcastUpdateConfig广播
//如果指定的文件名(ini_path)为空,那么会加载默认配置文件 // 如果指定的文件名(ini_path)为空,那么会加载默认配置文件
//默认配置文件名为 /path/to/your/exe.ini // 默认配置文件名为 /path/to/your/exe.ini
//加载配置文件成功后返回true否则返回false // 加载配置文件成功后返回true否则返回false
bool loadIniConfig(const char *ini_path = nullptr); bool loadIniConfig(const char *ini_path = nullptr);
////////////广播名称/////////// ////////////广播名称///////////
namespace Broadcast { namespace Broadcast {
//注册或反注册MediaSource事件广播 // 注册或反注册MediaSource事件广播
extern const std::string kBroadcastMediaChanged; extern const std::string kBroadcastMediaChanged;
#define BroadcastMediaChangedArgs const bool &bRegist, MediaSource &sender #define BroadcastMediaChangedArgs const bool &bRegist, MediaSource &sender
//录制mp4文件成功后广播 // 录制mp4文件成功后广播
extern const std::string kBroadcastRecordMP4; extern const std::string kBroadcastRecordMP4;
#define BroadcastRecordMP4Args const RecordInfo &info #define BroadcastRecordMP4Args const RecordInfo &info
@ -44,285 +43,302 @@ extern const std::string kBroadcastRecordMP4;
extern const std::string kBroadcastRecordTs; extern const std::string kBroadcastRecordTs;
#define BroadcastRecordTsArgs const RecordInfo &info #define BroadcastRecordTsArgs const RecordInfo &info
//收到http api请求广播 // 收到http api请求广播
extern const std::string kBroadcastHttpRequest; 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; 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到文件路径的映射 // 在http文件服务器中,收到http访问文件或目录前的广播,通过该事件可以控制http url到文件路径的映射
//在该事件中通过自行覆盖path参数可以做到譬如根据虚拟主机或者app选择不同http根目录的目的 // 在该事件中通过自行覆盖path参数可以做到譬如根据虚拟主机或者app选择不同http根目录的目的
extern const std::string kBroadcastHttpBeforeAccess; extern const std::string kBroadcastHttpBeforeAccess;
#define BroadcastHttpBeforeAccessArgs const Parser &parser, std::string &path, SockInfo &sender #define BroadcastHttpBeforeAccessArgs const Parser &parser, std::string &path, SockInfo &sender
//该流是否需要认证是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证 // 该流是否需要认证是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证
extern const std::string kBroadcastOnGetRtspRealm; 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认证方式),否则会导致认证失败 // 请求认证用户密码事件user_name为用户名must_no_encrypt如果为true则必须提供明文密码(因为此时是base64认证方式),否则会导致认证失败
//获取到密码后请调用invoker并输入对应类型的密码和密码类型invoker执行时会匹配密码 // 获取到密码后请调用invoker并输入对应类型的密码和密码类型invoker执行时会匹配密码
extern const std::string kBroadcastOnRtspAuth; 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)>; using PublishAuthInvoker = std::function<void(const std::string &err, const ProtocolOption &option)>;
//收到rtsp/rtmp推流事件广播通过该事件控制推流鉴权 // 收到rtsp/rtmp推流事件广播通过该事件控制推流鉴权
extern const std::string kBroadcastMediaPublish; 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)>; using AuthInvoker = std::function<void(const std::string &err)>;
//播放rtsp/rtmp/http-flv事件广播通过该事件控制播放鉴权 // 播放rtsp/rtmp/http-flv事件广播通过该事件控制播放鉴权
extern const std::string kBroadcastMediaPlayed; 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; 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; 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; extern const std::string kBroadcastNotFoundStream;
#define BroadcastNotFoundStreamArgs const MediaInfo &args, SockInfo &sender, const std::function<void()> &closePlayer #define BroadcastNotFoundStreamArgs const MediaInfo &args, SockInfo &sender, const std::function<void()> &closePlayer
//某个流无人消费时触发,目的为了实现无人观看时主动断开拉流等业务逻辑 // 某个流无人消费时触发,目的为了实现无人观看时主动断开拉流等业务逻辑
extern const std::string kBroadcastStreamNoneReader; extern const std::string kBroadcastStreamNoneReader;
#define BroadcastStreamNoneReaderArgs MediaSource &sender #define BroadcastStreamNoneReaderArgs MediaSource &sender
//更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播 // 更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播
extern const std::string kBroadcastReloadConfig; extern const std::string kBroadcastReloadConfig;
#define BroadcastReloadConfigArgs void #define BroadcastReloadConfigArgs void
#define ReloadConfigTag ((void *)(0xFF)) #define ReloadConfigTag ((void *)(0xFF))
#define RELOAD_KEY(arg,key) \ #define RELOAD_KEY(arg, key) \
do { \ do { \
decltype(arg) arg##_tmp = ::toolkit::mINI::Instance()[key]; \ decltype(arg) arg##_tmp = ::toolkit::mINI::Instance()[key]; \
if (arg == arg##_tmp) { \ if (arg == arg##_tmp) { \
return; \ return; \
} \ } \
arg = arg##_tmp; \ arg = arg##_tmp; \
InfoL << "reload config:" << key << "=" << arg; \ InfoL << "reload config:" << key << "=" << arg; \
} while(0) } while (0)
//监听某个配置发送变更 // 监听某个配置发送变更
#define LISTEN_RELOAD_KEY(arg, key, ...) \ #define LISTEN_RELOAD_KEY(arg, key, ...) \
do { \ do { \
static ::toolkit::onceToken s_token_listen([](){ \ static ::toolkit::onceToken s_token_listen([]() { \
::toolkit::NoticeCenter::Instance().addListener(ReloadConfigTag, \ ::toolkit::NoticeCenter::Instance().addListener( \
Broadcast::kBroadcastReloadConfig,[](BroadcastReloadConfigArgs) { \ ReloadConfigTag, Broadcast::kBroadcastReloadConfig, [](BroadcastReloadConfigArgs) { __VA_ARGS__; }); \
__VA_ARGS__; \ }); \
}); \ } while (0)
}); \
} while(0)
#define GET_CONFIG(type, arg, key) \ #define GET_CONFIG(type, arg, key) \
static type arg = ::toolkit::mINI::Instance()[key]; \ static type arg = ::toolkit::mINI::Instance()[key]; \
LISTEN_RELOAD_KEY(arg, key, { \ LISTEN_RELOAD_KEY(arg, key, { RELOAD_KEY(arg, key); });
RELOAD_KEY(arg, key); \
});
#define GET_CONFIG_FUNC(type, arg, key, ...) \ #define GET_CONFIG_FUNC(type, arg, key, ...) \
static type arg; \ static type arg; \
do { \ do { \
static ::toolkit::onceToken s_token_set([](){ \ static ::toolkit::onceToken s_token_set([]() { \
static auto lam = __VA_ARGS__ ; \ static auto lam = __VA_ARGS__; \
static auto arg##_str = ::toolkit::mINI::Instance()[key]; \ static auto arg##_str = ::toolkit::mINI::Instance()[key]; \
arg = lam(arg##_str); \ arg = lam(arg##_str); \
LISTEN_RELOAD_KEY(arg, key, { \ LISTEN_RELOAD_KEY(arg, key, { \
RELOAD_KEY(arg##_str, key); \ RELOAD_KEY(arg##_str, key); \
arg = lam(arg##_str); \ arg = lam(arg##_str); \
}); \ }); \
}); \ }); \
} while(0) } while (0)
} //namespace Broadcast } // namespace Broadcast
////////////通用配置/////////// ////////////通用配置///////////
namespace General{ namespace General {
//每个流媒体服务器的IDGUID // 每个流媒体服务器的IDGUID
extern const std::string kMediaServerId; extern const std::string kMediaServerId;
//流量汇报事件流量阈值,单位KB默认1MB // 流量汇报事件流量阈值,单位KB默认1MB
extern const std::string kFlowThreshold; extern const std::string kFlowThreshold;
//流无人观看并且超过若干时间后才触发kBroadcastStreamNoneReader事件 // 流无人观看并且超过若干时间后才触发kBroadcastStreamNoneReader事件
//默认连续5秒无人观看然后触发kBroadcastStreamNoneReader事件 // 默认连续5秒无人观看然后触发kBroadcastStreamNoneReader事件
extern const std::string kStreamNoneReaderDelayMS; extern const std::string kStreamNoneReaderDelayMS;
//等待流注册超时时间,收到播放器后请求后,如果未找到相关流,服务器会等待一定时间, // 等待流注册超时时间,收到播放器后请求后,如果未找到相关流,服务器会等待一定时间,
//如果在这个时间内,相关流注册上了,那么服务器会立即响应播放器播放成功, // 如果在这个时间内,相关流注册上了,那么服务器会立即响应播放器播放成功,
//否则会最多等待kMaxStreamWaitTimeMS毫秒然后响应播放器播放失败 // 否则会最多等待kMaxStreamWaitTimeMS毫秒然后响应播放器播放失败
extern const std::string kMaxStreamWaitTimeMS; extern const std::string kMaxStreamWaitTimeMS;
//是否启动虚拟主机 // 是否启动虚拟主机
extern const std::string kEnableVhost; extern const std::string kEnableVhost;
//拉流代理时是否添加静音音频 // 拉流代理时是否添加静音音频
extern const std::string kAddMuteAudio; extern const std::string kAddMuteAudio;
//拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始, // 拉流代理时如果断流再重连成功是否删除前一次的媒体流数据,如果删除将重新开始,
//如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写) // 如果不删除将会接着上一次的数据继续写(录制hls/mp4时会继续在前一个文件后面写)
extern const std::string kResetWhenRePlay; extern const std::string kResetWhenRePlay;
//是否默认推流时转换成hlshook接口(on_publish)中可以覆盖该设置 // 是否默认推流时转换成hlshook接口(on_publish)中可以覆盖该设置
extern const std::string kPublishToHls ; extern const std::string kPublishToHls;
//是否默认推流时mp4录像hook接口(on_publish)中可以覆盖该设置 // 是否默认推流时mp4录像hook接口(on_publish)中可以覆盖该设置
extern const std::string kPublishToMP4 ; extern const std::string kPublishToMP4;
//合并写缓存大小(单位毫秒)合并写指服务器缓存一定的数据后才会一次性写入socket这样能提高性能但是会提高延时 // 合并写缓存大小(单位毫秒)合并写指服务器缓存一定的数据后才会一次性写入socket这样能提高性能但是会提高延时
//开启后会同时关闭TCP_NODELAY并开启MSG_MORE // 开启后会同时关闭TCP_NODELAY并开启MSG_MORE
extern const std::string kMergeWriteMS ; extern const std::string kMergeWriteMS;
//全局的时间戳覆盖开关在转协议时对frame进行时间戳覆盖 // 全局的时间戳覆盖开关在转协议时对frame进行时间戳覆盖
extern const std::string kModifyStamp; extern const std::string kModifyStamp;
//按需转协议的开关 // 按需转协议的开关
extern const std::string kHlsDemand; extern const std::string kHlsDemand;
extern const std::string kRtspDemand; extern const std::string kRtspDemand;
extern const std::string kRtmpDemand; extern const std::string kRtmpDemand;
extern const std::string kTSDemand; extern const std::string kTSDemand;
extern const std::string kFMP4Demand; extern const std::string kFMP4Demand;
//转协议是否全局开启或忽略音频 // 转协议是否全局开启或忽略音频
extern const std::string kEnableAudio; extern const std::string kEnableAudio;
//在docker环境下不能通过英伟达驱动是否存在来判断是否支持硬件转码 // 在docker环境下不能通过英伟达驱动是否存在来判断是否支持硬件转码
extern const std::string kCheckNvidiaDev; extern const std::string kCheckNvidiaDev;
//是否开启ffmpeg日志 // 是否开启ffmpeg日志
extern const std::string kEnableFFmpegLog; extern const std::string kEnableFFmpegLog;
//最多等待未初始化的Track 10秒超时之后会忽略未初始化的Track // 最多等待未初始化的Track 10秒超时之后会忽略未初始化的Track
extern const std::string kWaitTrackReadyMS; extern const std::string kWaitTrackReadyMS;
//如果直播流只有单Track最多等待3秒超时后未收到其他Track的数据则认为是单Track // 如果直播流只有单Track最多等待3秒超时后未收到其他Track的数据则认为是单Track
//如果协议元数据有声明特定track数那么无此等待时间 // 如果协议元数据有声明特定track数那么无此等待时间
extern const std::string kWaitAddTrackMS; extern const std::string kWaitAddTrackMS;
//如果track未就绪我们先缓存帧数据但是有最大个数限制(100帧时大约4秒),防止内存溢出 // 如果track未就绪我们先缓存帧数据但是有最大个数限制(100帧时大约4秒),防止内存溢出
extern const std::string kUnreadyFrameCache; extern const std::string kUnreadyFrameCache;
//推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。 // 推流断开后可以在超时时间内重新连接上继续推流,这样播放器会接着播放。
//置0关闭此特性(推流断开会导致立即断开播放器) // 置0关闭此特性(推流断开会导致立即断开播放器)
extern const std::string kContinuePushMS; extern const std::string kContinuePushMS;
}//namespace General } // namespace General
////////////HTTP配置/////////// ////////////HTTP配置///////////
namespace Http { namespace Http {
//http 文件发送缓存大小 // http 文件发送缓存大小
extern const std::string kSendBufSize; extern const std::string kSendBufSize;
//http 最大请求字节数 // http 最大请求字节数
extern const std::string kMaxReqSize; extern const std::string kMaxReqSize;
//http keep-alive秒数 // http keep-alive秒数
extern const std::string kKeepAliveSecond; extern const std::string kKeepAliveSecond;
//http 字符编码 // http 字符编码
extern const std::string kCharSet; extern const std::string kCharSet;
//http 服务器根目录 // http 服务器根目录
extern const std::string kRootPath; 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; extern const std::string kVirtualPath;
//http 404错误提示内容 // http 404错误提示内容
extern const std::string kNotFound; extern const std::string kNotFound;
//是否显示文件夹菜单 // 是否显示文件夹菜单
extern const std::string kDirMenu; extern const std::string kDirMenu;
//禁止缓存文件的后缀 // 禁止缓存文件的后缀
extern const std::string kForbidCacheSuffix; extern const std::string kForbidCacheSuffix;
}//namespace Http } // namespace Http
////////////SHELL配置/////////// ////////////SHELL配置///////////
namespace Shell { namespace Shell {
extern const std::string kMaxReqSize; extern const std::string kMaxReqSize;
} //namespace Shell } // namespace Shell
////////////RTSP服务器配置/////////// ////////////RTSP服务器配置///////////
namespace Rtsp { namespace Rtsp {
//是否优先base64方式认证默认Md5方式认证 // 是否优先base64方式认证默认Md5方式认证
extern const std::string kAuthBasic; extern const std::string kAuthBasic;
//握手超时时间默认15秒 // 握手超时时间默认15秒
extern const std::string kHandshakeSecond; extern const std::string kHandshakeSecond;
//维持链接超时时间默认15秒 // 维持链接超时时间默认15秒
extern const std::string kKeepAliveSecond; extern const std::string kKeepAliveSecond;
//rtsp拉流代理是否直接代理 // rtsp拉流代理是否直接代理
//直接代理后支持任意编码格式但是会导致GOP缓存无法定位到I帧可能会导致开播花屏 // 直接代理后支持任意编码格式但是会导致GOP缓存无法定位到I帧可能会导致开播花屏
//并且如果是tcp方式拉流如果rtp大于mtu会导致无法使用udp方式代理 // 并且如果是tcp方式拉流如果rtp大于mtu会导致无法使用udp方式代理
//假定您的拉流源地址不是264或265或AAC那么你可以使用直接代理的方式来支持rtsp代理 // 假定您的拉流源地址不是264或265或AAC那么你可以使用直接代理的方式来支持rtsp代理
//默认开启rtsp直接代理rtmp由于没有这些问题是强制开启直接代理的 // 默认开启rtsp直接代理rtmp由于没有这些问题是强制开启直接代理的
extern const std::string kDirectProxy; extern const std::string kDirectProxy;
} //namespace Rtsp } // namespace Rtsp
////////////RTMP服务器配置/////////// ////////////RTMP服务器配置///////////
namespace Rtmp { namespace Rtmp {
//rtmp推流时间戳覆盖开关 // rtmp推流时间戳覆盖开关
extern const std::string kModifyStamp; extern const std::string kModifyStamp;
//握手超时时间默认15秒 // 握手超时时间默认15秒
extern const std::string kHandshakeSecond; extern const std::string kHandshakeSecond;
//维持链接超时时间默认15秒 // 维持链接超时时间默认15秒
extern const std::string kKeepAliveSecond; extern const std::string kKeepAliveSecond;
} //namespace RTMP } // namespace Rtmp
////////////RTP配置/////////// ////////////RTP配置///////////
namespace Rtp { namespace Rtp {
//RTP打包最大MTU,公网情况下更小 // RTP打包最大MTU,公网情况下更小
extern const std::string kVideoMtuSize; extern const std::string kVideoMtuSize;
//RTP打包最大MTU,公网情况下更小 // RTP打包最大MTU,公网情况下更小
extern const std::string kAudioMtuSize; extern const std::string kAudioMtuSize;
//rtp包最大长度限制, 单位KB // rtp包最大长度限制, 单位KB
extern const std::string kRtpMaxSize; extern const std::string kRtpMaxSize;
} //namespace Rtsp } // namespace Rtp
////////////组播配置/////////// ////////////组播配置///////////
namespace MultiCast { namespace MultiCast {
//组播分配起始地址 // 组播分配起始地址
extern const std::string kAddrMin; extern const std::string kAddrMin;
//组播分配截止地址 // 组播分配截止地址
extern const std::string kAddrMax; extern const std::string kAddrMax;
//组播TTL // 组播TTL
extern const std::string kUdpTTL; extern const std::string kUdpTTL;
} //namespace MultiCast } // namespace MultiCast
////////////录像配置/////////// ////////////录像配置///////////
namespace Record { namespace Record {
//查看录像的应用名称 // 查看录像的应用名称
extern const std::string kAppName; extern const std::string kAppName;
//每次流化MP4文件的时长,单位毫秒 // 每次流化MP4文件的时长,单位毫秒
extern const std::string kSampleMS; extern const std::string kSampleMS;
//MP4文件录制大小,默认一个小时 // MP4文件录制大小,默认一个小时
extern const std::string kFileSecond; extern const std::string kFileSecond;
//录制文件路径 // 录制文件路径
extern const std::string kFilePath; extern const std::string kFilePath;
//mp4文件写缓存大小 // mp4文件写缓存大小
extern const std::string kFileBufSize; extern const std::string kFileBufSize;
//mp4录制完成后是否进行二次关键帧索引写入头部 // mp4录制完成后是否进行二次关键帧索引写入头部
extern const std::string kFastStart; extern const std::string kFastStart;
//mp4文件是否重头循环读取 // mp4文件是否重头循环读取
extern const std::string kFileRepeat; extern const std::string kFileRepeat;
} //namespace Record } // namespace Record
////////////HLS相关配置/////////// ////////////HLS相关配置///////////
namespace Hls { namespace Hls {
//HLS切片时长,单位秒 // HLS切片时长,单位秒
extern const std::string kSegmentDuration; extern const std::string kSegmentDuration;
//m3u8文件中HLS切片个数如果设置为0则不删除切片而是保存为点播 // m3u8文件中HLS切片个数如果设置为0则不删除切片而是保存为点播
extern const std::string kSegmentNum; extern const std::string kSegmentNum;
//如果设置为0则不保留切片设置为1则一直保留切片 // 如果设置为0则不保留切片设置为1则一直保留切片
extern const std::string kSegmentKeep; extern const std::string kSegmentKeep;
//HLS切片从m3u8文件中移除后继续保留在磁盘上的个数 // HLS切片从m3u8文件中移除后继续保留在磁盘上的个数
extern const std::string kSegmentRetain; extern const std::string kSegmentRetain;
//HLS文件写缓存大小 // HLS文件写缓存大小
extern const std::string kFileBufSize; extern const std::string kFileBufSize;
//录制文件路径 // 录制文件路径
extern const std::string kFilePath; extern const std::string kFilePath;
// 是否广播 ts 切片完成通知 // 是否广播 ts 切片完成通知
extern const std::string kBroadcastRecordTs; extern const std::string kBroadcastRecordTs;
//hls直播文件删除延时单位秒 // hls直播文件删除延时单位秒
extern const std::string kDeleteDelaySec; extern const std::string kDeleteDelaySec;
} //namespace Hls } // namespace Hls
////////////Rtp代理相关配置/////////// ////////////Rtp代理相关配置///////////
namespace RtpProxy { namespace RtpProxy {
//rtp调试数据保存目录,置空则不生成 // rtp调试数据保存目录,置空则不生成
extern const std::string kDumpDir; extern const std::string kDumpDir;
//rtp接收超时时间 // rtp接收超时时间
extern const std::string kTimeoutSec; extern const std::string kTimeoutSec;
//随机端口范围最少确保36个端口 // 随机端口范围最少确保36个端口
//该范围同时限制rtsp服务器udp端口范围 // 该范围同时限制rtsp服务器udp端口范围
extern const std::string kPortRange; 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播放器 * rtsp/rtmp播放器
@ -330,28 +346,28 @@ extern const std::string kPortRange;
* *
*/ */
namespace Client { namespace Client {
//指定网卡ip // 指定网卡ip
extern const std::string kNetAdapter; extern const std::string kNetAdapter;
//设置rtp传输类型可选项有0(tcp默认)、1(udp)、2(组播) // 设置rtp传输类型可选项有0(tcp默认)、1(udp)、2(组播)
//设置方法:player[PlayerBase::kRtpType] = 0/1/2; // 设置方法:player[PlayerBase::kRtpType] = 0/1/2;
extern const std::string kRtpType; extern const std::string kRtpType;
//rtsp认证用户名 // rtsp认证用户名
extern const std::string kRtspUser; extern const std::string kRtspUser;
//rtsp认证用用户密码可以是明文也可以是md5,md5密码生成方式 md5(username:realm:password) // rtsp认证用用户密码可以是明文也可以是md5,md5密码生成方式 md5(username:realm:password)
extern const std::string kRtspPwd; extern const std::string kRtspPwd;
//rtsp认证用用户密码是否为md5类型 // rtsp认证用用户密码是否为md5类型
extern const std::string kRtspPwdIsMD5; extern const std::string kRtspPwdIsMD5;
//握手超时时间默认10,000 毫秒 // 握手超时时间默认10,000 毫秒
extern const std::string kTimeoutMS; extern const std::string kTimeoutMS;
//rtp/rtmp包接收超时时间默认5000秒 // rtp/rtmp包接收超时时间默认5000秒
extern const std::string kMediaTimeoutMS; extern const std::string kMediaTimeoutMS;
//rtsp/rtmp心跳时间,默认5000毫秒 // rtsp/rtmp心跳时间,默认5000毫秒
extern const std::string kBeatIntervalMS; extern const std::string kBeatIntervalMS;
//是否为性能测试模式性能测试模式开启后不会解析rtp或rtmp包 // 是否为性能测试模式性能测试模式开启后不会解析rtp或rtmp包
extern const std::string kBenchmarkMode; extern const std::string kBenchmarkMode;
//播放器在触发播放成功事件时是否等待所有track ready时再回调 // 播放器在触发播放成功事件时是否等待所有track ready时再回调
extern const std::string kWaitTrackReady; extern const std::string kWaitTrackReady;
} } // namespace Client
} // namespace mediakit } // namespace mediakit
#endif /* COMMON_CONFIG_H */ #endif /* COMMON_CONFIG_H */

View File

@ -10,21 +10,21 @@
#if defined(ENABLE_RTPPROXY) #if defined(ENABLE_RTPPROXY)
#include "GB28181Process.h" #include "GB28181Process.h"
#include "Util/File.h"
#include "Http/HttpTSPlayer.h"
#include "Extension/CommonRtp.h" #include "Extension/CommonRtp.h"
#include "Extension/H264Rtp.h"
#include "Extension/Factory.h" #include "Extension/Factory.h"
#include "Extension/Opus.h"
#include "Extension/G711.h" #include "Extension/G711.h"
#include "Extension/H264Rtp.h"
#include "Extension/H265.h" #include "Extension/H265.h"
#include "Extension/Opus.h"
#include "Http/HttpTSPlayer.h"
#include "Util/File.h"
using namespace std; using namespace std;
using namespace toolkit; using namespace toolkit;
namespace mediakit { namespace mediakit {
//判断是否为ts负载 // 判断是否为ts负载
static inline bool checkTS(const uint8_t *packet, size_t bytes) { static inline bool checkTS(const uint8_t *packet, size_t bytes) {
return bytes % TS_PACKET_SIZE == 0 && packet[0] == TS_SYNC_BYTE; return bytes % TS_PACKET_SIZE == 0 && packet[0] == TS_SYNC_BYTE;
} }
@ -37,13 +37,13 @@ public:
_sample_rate = sample_rate; _sample_rate = sample_rate;
setOnSorted(std::move(cb)); setOnSorted(std::move(cb));
setBeforeSorted(std::move(cb_before)); setBeforeSorted(std::move(cb_before));
//GB28181推流不支持ntp时间戳 // GB28181推流不支持ntp时间戳
setNtpStamp(0, 0); setNtpStamp(0, 0);
} }
~RtpReceiverImp() override = default; ~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(); 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) { 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 pt = header->pt;
auto &ref = _rtp_receiver[pt]; auto &ref = _rtp_receiver[pt];
if (!ref) { if (!ref) {
if (_rtp_receiver.size() > 2) { if (_rtp_receiver.size() > 2) {
//防止pt类型太多导致内存溢出 // 防止pt类型太多导致内存溢出
throw std::invalid_argument("rtp pt类型不得超过2种!"); throw std::invalid_argument("rtp pt类型不得超过2种!");
} }
switch (pt) { if (pt == opus_pt) {
case 100: { // opus负载
//opus负载 ref = std::make_shared<RtpReceiverImp>(48000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
ref = std::make_shared<RtpReceiverImp>(48000,[this](RtpPacket::Ptr rtp) {
onRtpSorted(std::move(rtp));
});
auto track = std::make_shared<OpusTrack>(); auto track = std::make_shared<OpusTrack>();
_interface->addTrack(track); _interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track); _rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
break; } 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: { ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
//H265负载
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) { // ts或ps负载
onRtpSorted(std::move(rtp)); _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) { _rtp_decoder[pt]->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([this](const Frame::Ptr &frame) {
onRtpDecode(frame); onRtpDecode(frame);
return true; 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) { void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
if (frame->getCodecId() != CodecInvalid) { if (frame->getCodecId() != CodecInvalid) {
//这里不是ps或ts // 这里不是ps或ts
_interface->inputFrame(frame); _interface->inputFrame(frame);
return; return;
} }
//这是TS或PS // 这是TS或PS
if (_save_file_ps) { if (_save_file_ps) {
fwrite(frame->data(), frame->size(), 1, _save_file_ps.get()); fwrite(frame->data(), frame->size(), 1, _save_file_ps.get());
} }
if (!_decoder) { if (!_decoder) {
//创建解码器 // 创建解码器
if (checkTS((uint8_t *) frame->data(), frame->size())) { if (checkTS((uint8_t *)frame->data(), frame->size())) {
//猜测是ts负载 // 猜测是ts负载
InfoL << _media_info._streamid << " judged to be TS"; InfoL << _media_info._streamid << " judged to be TS";
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface); _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
} else { } else {
//猜测是ps负载 // 猜测是ps负载
InfoL << _media_info._streamid << " judged to be PS"; InfoL << _media_info._streamid << " judged to be PS";
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface); _decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
} }
@ -189,5 +171,5 @@ void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
} }
} }
}//namespace mediakit } // namespace mediakit
#endif//defined(ENABLE_RTPPROXY) #endif // defined(ENABLE_RTPPROXY)