Commit 70bb1a65 by xiongziliang

添加配置文件热加载功能

parent 551b9a43
...@@ -43,7 +43,7 @@ bool loadIniConfig(const char *ini_path){ ...@@ -43,7 +43,7 @@ bool loadIniConfig(const char *ini_path){
} }
try{ try{
mINI::Instance().parseFile(ini); mINI::Instance().parseFile(ini);
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastUpdateConfig); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
return true; return true;
}catch (std::exception &ex) { }catch (std::exception &ex) {
mINI::Instance().dumpFile(ini); mINI::Instance().dumpFile(ini);
...@@ -60,7 +60,7 @@ const char kBroadcastOnRtspAuth[] = "kBroadcastOnRtspAuth"; ...@@ -60,7 +60,7 @@ const char kBroadcastOnRtspAuth[] = "kBroadcastOnRtspAuth";
const char kBroadcastMediaPlayed[] = "kBroadcastMediaPlayed"; const char kBroadcastMediaPlayed[] = "kBroadcastMediaPlayed";
const char kBroadcastRtmpPublish[] = "kBroadcastRtmpPublish"; const char kBroadcastRtmpPublish[] = "kBroadcastRtmpPublish";
const char kBroadcastFlowReport[] = "kBroadcastFlowReport"; const char kBroadcastFlowReport[] = "kBroadcastFlowReport";
const char kBroadcastUpdateConfig[] = "kBroadcastUpdateConfig"; const char kBroadcastReloadConfig[] = "kBroadcastReloadConfig";
const char kBroadcastShellLogin[] = "kBroadcastShellLogin"; const char kBroadcastShellLogin[] = "kBroadcastShellLogin";
const char kFlowThreshold[] = "broadcast.flowThreshold"; const char kFlowThreshold[] = "broadcast.flowThreshold";
......
...@@ -28,9 +28,11 @@ ...@@ -28,9 +28,11 @@
#ifndef COMMON_CONFIG_H #ifndef COMMON_CONFIG_H
#define COMMON_CONFIG_H #define COMMON_CONFIG_H
#include <functional>
#include "Util/mini.h" #include "Util/mini.h"
#include "Util/onceToken.h" #include "Util/onceToken.h"
#include <functional> #include "Util/NoticeCenter.h"
using namespace std; using namespace std;
using namespace ZL::Util; using namespace ZL::Util;
...@@ -114,10 +116,33 @@ extern const char kBroadcastFlowReport[]; ...@@ -114,10 +116,33 @@ extern const char kBroadcastFlowReport[];
extern const char kFlowThreshold[]; extern const char kFlowThreshold[];
//更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播 //更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播
extern const char kBroadcastUpdateConfig[]; extern const char kBroadcastReloadConfig[];
#define BroadcastUpdateConfigArgs void #define BroadcastReloadConfigArgs void
#define ReloadConfigTag ((void *)(0xFF)) #define ReloadConfigTag ((void *)(0xFF))
#define RELOAD_KEY(arg,key) \
do{ \
decltype(arg) arg##tmp = mINI::Instance()[key]; \
if(arg != arg##tmp ) { \
arg = arg##tmp; \
InfoL << "reload config:" << key << "=" << arg; \
} \
}while(0);
//监听某个配置发送变更
#define RELOAD_KEY_REGISTER(arg,key) \
do{ \
static onceToken s_token([](){ \
NoticeCenter::Instance().addListener(ReloadConfigTag,Config::Broadcast::kBroadcastReloadConfig,[](BroadcastReloadConfigArgs){ \
RELOAD_KEY(arg,key); \
}); \
}); \
}while(0);
#define GET_CONFIG_AND_REGISTER(type,arg,key) \
static type arg = mINI::Instance()[key]; \
RELOAD_KEY_REGISTER(arg,key);
} //namespace Broadcast } //namespace Broadcast
////////////HTTP配置/////////// ////////////HTTP配置///////////
......
...@@ -107,7 +107,7 @@ void DevChannel::inputH264(char* pcData, int iDataLen, uint32_t uiStamp) { ...@@ -107,7 +107,7 @@ void DevChannel::inputH264(char* pcData, int iDataLen, uint32_t uiStamp) {
auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) { auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
onGetRTP(pkt,bKeyPos); onGetRTP(pkt,bKeyPos);
}; };
static uint32_t videoMtu = mINI::Instance()[Config::Rtp::kVideoMtuSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,videoMtu,Config::Rtp::kVideoMtuSize);
m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu)); m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu));
} }
if (!m_bSdp_gotH264 && m_video) { if (!m_bSdp_gotH264 && m_video) {
...@@ -130,7 +130,7 @@ void DevChannel::inputAAC(char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp ...@@ -130,7 +130,7 @@ void DevChannel::inputAAC(char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp
auto lam = [this](const RtpPacket::Ptr &pkt, bool keyPos) { auto lam = [this](const RtpPacket::Ptr &pkt, bool keyPos) {
onGetRTP(pkt,keyPos); onGetRTP(pkt,keyPos);
}; };
static uint32_t audioMtu = mINI::Instance()[Config::Rtp::kAudioMtuSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,audioMtu,Config::Rtp::kAudioMtuSize);
m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,m_audio->iSampleRate)); m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,m_audio->iSampleRate));
} }
if (!m_bSdp_gotAAC && m_audio && pcAdtsHeader) { if (!m_bSdp_gotAAC && m_audio && pcAdtsHeader) {
......
...@@ -102,7 +102,8 @@ get_mime_type(const char* name) { ...@@ -102,7 +102,8 @@ get_mime_type(const char* name) {
HttpSession::HttpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) : HttpSession::HttpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) :
TcpLimitedSession(pTh, pSock) { TcpLimitedSession(pTh, pSock) {
static string rootPath = mINI::Instance()[Config::Http::kRootPath]; GET_CONFIG_AND_REGISTER(string,rootPath,Config::Http::kRootPath);
m_strPath = rootPath; m_strPath = rootPath;
static onceToken token([]() { static onceToken token([]() {
g_mapCmdIndex.emplace("GET",&HttpSession::Handle_Req_GET); g_mapCmdIndex.emplace("GET",&HttpSession::Handle_Req_GET);
...@@ -118,7 +119,8 @@ void HttpSession::onRecv(const Socket::Buffer::Ptr &pBuf) { ...@@ -118,7 +119,8 @@ void HttpSession::onRecv(const Socket::Buffer::Ptr &pBuf) {
onRecv(pBuf->data(),pBuf->size()); onRecv(pBuf->data(),pBuf->size());
} }
void HttpSession::onRecv(const char *data,int size){ void HttpSession::onRecv(const char *data,int size){
static uint32_t reqSize = mINI::Instance()[Config::Http::kMaxReqSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,reqSize,Config::Http::kMaxReqSize);
m_ticker.resetTime(); m_ticker.resetTime();
if (m_strRcvBuf.size() + size >= reqSize) { if (m_strRcvBuf.size() + size >= reqSize) {
WarnL << "接收缓冲区溢出:" << m_strRcvBuf.size() + size << "," << reqSize; WarnL << "接收缓冲区溢出:" << m_strRcvBuf.size() + size << "," << reqSize;
...@@ -163,7 +165,8 @@ inline HttpSession::HttpCode HttpSession::parserHttpReq(const string &str) { ...@@ -163,7 +165,8 @@ inline HttpSession::HttpCode HttpSession::parserHttpReq(const string &str) {
} }
void HttpSession::onError(const SockException& err) { void HttpSession::onError(const SockException& err) {
//WarnL << err.what(); //WarnL << err.what();
static uint64_t iFlowThreshold = mINI::Instance()[Broadcast::kFlowThreshold]; GET_CONFIG_AND_REGISTER(uint32_t,iFlowThreshold,Broadcast::kFlowThreshold);
if(m_previousTagSize > iFlowThreshold * 1024){ if(m_previousTagSize > iFlowThreshold * 1024){
uint64_t totalBytes = m_previousTagSize; uint64_t totalBytes = m_previousTagSize;
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,m_mediaInfo,totalBytes); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,m_mediaInfo,totalBytes);
...@@ -171,7 +174,8 @@ void HttpSession::onError(const SockException& err) { ...@@ -171,7 +174,8 @@ void HttpSession::onError(const SockException& err) {
} }
void HttpSession::onManager() { void HttpSession::onManager() {
static uint32_t keepAliveSec = mINI::Instance()[Config::Http::kKeepAliveSecond].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,keepAliveSec,Config::Http::kKeepAliveSecond);
if(m_ticker.elapsedTime() > keepAliveSec * 1000){ if(m_ticker.elapsedTime() > keepAliveSec * 1000){
//1分钟超时 //1分钟超时
WarnL<<"HttpSession timeouted!"; WarnL<<"HttpSession timeouted!";
...@@ -318,7 +322,8 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() { ...@@ -318,7 +322,8 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() {
string strFile = m_strPath + "/" + m_mediaInfo.m_vhost + m_parser.Url(); string strFile = m_strPath + "/" + m_mediaInfo.m_vhost + m_parser.Url();
/////////////HTTP连接是否需要被关闭//////////////// /////////////HTTP连接是否需要被关闭////////////////
static uint32_t reqCnt = mINI::Instance()[Config::Http::kMaxReqCount].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,reqCnt,Config::Http::kMaxReqCount);
bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) && ( ++m_iReqCnt < reqCnt); bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) && ( ++m_iReqCnt < reqCnt);
HttpCode eHttpCode = bClose ? Http_failed : Http_success; HttpCode eHttpCode = bClose ? Http_failed : Http_success;
//访问的是文件夹 //访问的是文件夹
...@@ -384,7 +389,8 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() { ...@@ -384,7 +389,8 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() {
std::shared_ptr<FILE> pFilePtr(pFile, [](FILE *pFp) { std::shared_ptr<FILE> pFilePtr(pFile, [](FILE *pFp) {
fclose(pFp); fclose(pFp);
}); });
static uint32_t sendBufSize = mINI::Instance()[Config::Http::kSendBufSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,sendBufSize,Config::Http::kSendBufSize);
//不允许主动丢包 //不允许主动丢包
sock->setShouldDropPacket(false); sock->setShouldDropPacket(false);
//缓存大小为两个包,太大可能导致发送时间太长从而超时 //缓存大小为两个包,太大可能导致发送时间太长从而超时
...@@ -545,9 +551,9 @@ inline void HttpSession::sendResponse(const char* pcStatus, const KeyValue& head ...@@ -545,9 +551,9 @@ inline void HttpSession::sendResponse(const char* pcStatus, const KeyValue& head
} }
inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iContentSize,const char* pcContentType) { inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iContentSize,const char* pcContentType) {
KeyValue headerOut; KeyValue headerOut;
static string charSet = mINI::Instance()[Config::Http::kCharSet]; GET_CONFIG_AND_REGISTER(string,charSet,Config::Http::kCharSet);
static uint32_t keepAliveSec = mINI::Instance()[Config::Http::kKeepAliveSecond].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,keepAliveSec,Config::Http::kKeepAliveSecond);
static uint32_t reqCnt = mINI::Instance()[Config::Http::kMaxReqCount].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,reqCnt,Config::Http::kMaxReqCount);
headerOut.emplace("Date", dateStr()); headerOut.emplace("Date", dateStr());
headerOut.emplace("Server", SERVER_NAME); headerOut.emplace("Server", SERVER_NAME);
...@@ -568,7 +574,8 @@ inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iC ...@@ -568,7 +574,8 @@ inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iC
string HttpSession::urlDecode(const string &str){ string HttpSession::urlDecode(const string &str){
auto ret = strCoding::UrlUTF8Decode(str); auto ret = strCoding::UrlUTF8Decode(str);
#ifdef _WIN32 #ifdef _WIN32
static bool isGb2312 = !strcasecmp(mINI::Instance()[Config::Http::kCharSet].data(), "gb2312"); GET_CONFIG_AND_REGISTER(string,charSet,Config::Http::kCharSet);
bool isGb2312 = !strcasecmp(charSet.data(), "gb2312");
if (isGb2312) { if (isGb2312) {
ret = strCoding::UTF8ToGB2312(ret); ret = strCoding::UTF8ToGB2312(ret);
} }
...@@ -585,7 +592,8 @@ inline void HttpSession::urlDecode(Parser &parser){ ...@@ -585,7 +592,8 @@ inline void HttpSession::urlDecode(Parser &parser){
inline bool HttpSession::emitHttpEvent(bool doInvoke){ inline bool HttpSession::emitHttpEvent(bool doInvoke){
///////////////////是否断开本链接/////////////////////// ///////////////////是否断开本链接///////////////////////
static uint32_t reqCnt = mINI::Instance()[Config::Http::kMaxReqCount].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,reqCnt,Config::Http::kMaxReqCount);
bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) && ( ++m_iReqCnt < reqCnt); bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) && ( ++m_iReqCnt < reqCnt);
auto Origin = m_parser["Origin"]; auto Origin = m_parser["Origin"];
/////////////////////异步回复Invoker/////////////////////////////// /////////////////////异步回复Invoker///////////////////////////////
...@@ -643,7 +651,8 @@ void HttpSession::responseDelay(const string &Origin,bool bClose, ...@@ -643,7 +651,8 @@ void HttpSession::responseDelay(const string &Origin,bool bClose,
sendResponse(codeOut.data(), headerOut, contentOut); sendResponse(codeOut.data(), headerOut, contentOut);
} }
inline void HttpSession::sendNotFound(bool bClose) { inline void HttpSession::sendNotFound(bool bClose) {
static string notFound = mINI::Instance()[Config::Http::kNotFound]; GET_CONFIG_AND_REGISTER(string,notFound,Config::Http::kNotFound);
sendResponse("404 Not Found", makeHttpHeader(bClose, notFound.size()), notFound); sendResponse("404 Not Found", makeHttpHeader(bClose, notFound.size()), notFound);
} }
......
...@@ -37,7 +37,8 @@ namespace MediaFile { ...@@ -37,7 +37,8 @@ namespace MediaFile {
#ifdef ENABLE_MP4V2 #ifdef ENABLE_MP4V2
MediaReader::MediaReader(const string &strVhost,const string &strApp, const string &strId) { MediaReader::MediaReader(const string &strVhost,const string &strApp, const string &strId) {
static string recordPath = mINI::Instance()[Config::Record::kFilePath]; GET_CONFIG_AND_REGISTER(string,recordPath,Config::Record::kFilePath);
auto strFileName = recordPath + "/" + strVhost + "/" + strApp + "/" + strId; auto strFileName = recordPath + "/" + strVhost + "/" + strApp + "/" + strId;
m_hMP4File = MP4Read(strFileName.data()); m_hMP4File = MP4Read(strFileName.data());
...@@ -168,7 +169,8 @@ MediaReader::~MediaReader() { ...@@ -168,7 +169,8 @@ MediaReader::~MediaReader() {
void MediaReader::startReadMP4() { void MediaReader::startReadMP4() {
auto strongSelf = shared_from_this(); auto strongSelf = shared_from_this();
static uint32_t sampleMS = mINI::Instance()[Config::Record::kSampleMS].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,sampleMS,Config::Record::kSampleMS);
AsyncTaskThread::Instance().DoTaskDelay(reinterpret_cast<uint64_t>(this), sampleMS, [strongSelf](){ AsyncTaskThread::Instance().DoTaskDelay(reinterpret_cast<uint64_t>(this), sampleMS, [strongSelf](){
return strongSelf->readSample(); return strongSelf->readSample();
}); });
...@@ -321,7 +323,8 @@ void MediaReader::seek(int iSeekTime,bool bReStart){ ...@@ -321,7 +323,8 @@ void MediaReader::seek(int iSeekTime,bool bReStart){
MediaSource::Ptr MediaReader::onMakeMediaSource(const string &strSchema,const string &strVhost,const string &strApp, const string &strId){ MediaSource::Ptr MediaReader::onMakeMediaSource(const string &strSchema,const string &strVhost,const string &strApp, const string &strId){
#ifdef ENABLE_MP4V2 #ifdef ENABLE_MP4V2
static string appName = mINI::Instance()[Config::Record::kAppName]; GET_CONFIG_AND_REGISTER(string,appName,Config::Record::kAppName);
if (strApp != appName) { if (strApp != appName) {
return nullptr; return nullptr;
} }
......
...@@ -44,12 +44,12 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp, ...@@ -44,12 +44,12 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp,
bool enableHls, bool enableHls,
bool enableMp4) { bool enableMp4) {
static string hlsPrefix = mINI::Instance()[Config::Hls::kHttpPrefix]; GET_CONFIG_AND_REGISTER(string,hlsPrefix,Config::Hls::kHttpPrefix);
static string hlsPrefixDefaultVhost = mINI::Instance()[Config::Hls::kHttpPrefixDefaultVhost]; GET_CONFIG_AND_REGISTER(string,hlsPrefixDefaultVhost,Config::Hls::kHttpPrefixDefaultVhost);
static string hlsPath = mINI::Instance()[Config::Hls::kFilePath]; GET_CONFIG_AND_REGISTER(string,hlsPath,Config::Hls::kFilePath);
static uint32_t hlsBufSize = mINI::Instance()[Config::Hls::kFileBufSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,hlsBufSize,Config::Hls::kFileBufSize);
static uint32_t hlsDuration = mINI::Instance()[Config::Hls::kSegmentDuration].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,hlsDuration,Config::Hls::kSegmentDuration);
static uint32_t hlsNum = mINI::Instance()[Config::Hls::kSegmentNum].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,hlsNum,Config::Hls::kSegmentNum);
string strVhost = strVhost_tmp; string strVhost = strVhost_tmp;
if(trim(strVhost).empty()){ if(trim(strVhost).empty()){
...@@ -80,8 +80,9 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp, ...@@ -80,8 +80,9 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp,
hlsBufSize, hlsDuration, hlsNum)); hlsBufSize, hlsDuration, hlsNum));
} }
#ifdef ENABLE_MP4V2 #ifdef ENABLE_MP4V2
static string recordPath = mINI::Instance()[Config::Record::kFilePath]; GET_CONFIG_AND_REGISTER(string,recordPath,Config::Record::kFilePath);
static string recordAppName = mINI::Instance()[Config::Record::kAppName]; GET_CONFIG_AND_REGISTER(string,recordAppName,Config::Record::kAppName);
if(enableMp4){ if(enableMp4){
m_mp4Maker.reset(new Mp4Maker(recordPath + "/" + strVhost + "/" + recordAppName + "/" + strApp + "/" + strId + "/", m_mp4Maker.reset(new Mp4Maker(recordPath + "/" + strVhost + "/" + recordAppName + "/" + strApp + "/" + strId + "/",
strVhost,strApp,strId,pPlayer)); strVhost,strApp,strId,pPlayer));
......
...@@ -119,8 +119,9 @@ void Mp4Maker::inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp ...@@ -119,8 +119,9 @@ void Mp4Maker::inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp
} }
void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duration, int iType) { void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duration, int iType) {
static uint32_t recordMS = 1000 * mINI::Instance()[Config::Record::kFileSecond].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,recordSec,Config::Record::kFileSecond);
if(iType == 5 && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordMS)){
if(iType == 5 && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordSec * 1000)){
//在I帧率处新建MP4文件 //在I帧率处新建MP4文件
//如果文件未创建或者文件超过10分钟则创建新文件 //如果文件未创建或者文件超过10分钟则创建新文件
createFile(); createFile();
...@@ -131,8 +132,9 @@ void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duratio ...@@ -131,8 +132,9 @@ void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duratio
} }
void Mp4Maker::_inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32Duration) { void Mp4Maker::_inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32Duration) {
static uint32_t recordMS = 1000 * mINI::Instance()[Config::Record::kFileSecond].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,recordSec,Config::Record::kFileSecond);
if (!m_pPlayer->containVideo() && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordMS)) {
if (!m_pPlayer->containVideo() && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordSec * 1000)) {
//在I帧率处新建MP4文件 //在I帧率处新建MP4文件
//如果文件未创建或者文件超过10分钟则创建新文件 //如果文件未创建或者文件超过10分钟则创建新文件
createFile(); createFile();
...@@ -158,7 +160,9 @@ void Mp4Maker::createFile() { ...@@ -158,7 +160,9 @@ void Mp4Maker::createFile() {
m_info.ui64StartedTime = ::time(NULL); m_info.ui64StartedTime = ::time(NULL);
m_info.strFileName = strTime + ".mp4"; m_info.strFileName = strTime + ".mp4";
m_info.strFilePath = strFile; m_info.strFilePath = strFile;
static string appName = mINI::Instance()[Config::Record::kAppName];
GET_CONFIG_AND_REGISTER(string,appName,Config::Record::kAppName);
m_info.strUrl = m_info.strVhost + "/" m_info.strUrl = m_info.strVhost + "/"
+ appName + "/" + appName + "/"
+ m_info.strAppName + "/" + m_info.strAppName + "/"
......
...@@ -36,7 +36,8 @@ namespace ZL { ...@@ -36,7 +36,8 @@ namespace ZL {
namespace Rtsp { namespace Rtsp {
void RtpMaker_AAC::makeRtp(const char *pcData, int iLen, uint32_t uiStamp) { void RtpMaker_AAC::makeRtp(const char *pcData, int iLen, uint32_t uiStamp) {
static uint32_t cycleMS = mINI::Instance()[Config::Rtp::kCycleMS].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Config::Rtp::kCycleMS);
uiStamp %= cycleMS; uiStamp %= cycleMS;
char *ptr = (char *) pcData; char *ptr = (char *) pcData;
int iSize = iLen; int iSize = iLen;
......
...@@ -36,7 +36,8 @@ namespace ZL { ...@@ -36,7 +36,8 @@ namespace ZL {
namespace Rtsp { namespace Rtsp {
void RtpMaker_H264::makeRtp(const char* pcData, int iLen, uint32_t uiStamp) { void RtpMaker_H264::makeRtp(const char* pcData, int iLen, uint32_t uiStamp) {
static uint32_t cycleMS = mINI::Instance()[Config::Rtp::kCycleMS].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Config::Rtp::kCycleMS);
uiStamp %= cycleMS; uiStamp %= cycleMS;
int iSize = m_iMtuSize - 2; int iSize = m_iMtuSize - 2;
if (iLen > iSize) { //超过MTU if (iLen > iSize) { //超过MTU
......
...@@ -54,7 +54,8 @@ void RtmpSession::onError(const SockException& err) { ...@@ -54,7 +54,8 @@ void RtmpSession::onError(const SockException& err) {
DebugL << err.what(); DebugL << err.what();
//流量统计事件广播 //流量统计事件广播
static uint64_t iFlowThreshold = mINI::Instance()[Broadcast::kFlowThreshold]; GET_CONFIG_AND_REGISTER(uint32_t,iFlowThreshold,Broadcast::kFlowThreshold);
if(m_ui64TotalBytes > iFlowThreshold * 1024){ if(m_ui64TotalBytes > iFlowThreshold * 1024){
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,m_mediaInfo,m_ui64TotalBytes); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,m_mediaInfo,m_ui64TotalBytes);
} }
......
...@@ -98,7 +98,8 @@ void RtmpToRtspMediaSource::makeSDP() { ...@@ -98,7 +98,8 @@ void RtmpToRtspMediaSource::makeSDP() {
auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) { auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
m_pRtspSrc->onGetRTP(pkt,bKeyPos); m_pRtspSrc->onGetRTP(pkt,bKeyPos);
}; };
static uint32_t videoMtu = mINI::Instance()[Config::Rtp::kVideoMtuSize].as<uint32_t>();
GET_CONFIG_AND_REGISTER(uint32_t,videoMtu,Config::Rtp::kVideoMtuSize);
m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ssrc0,videoMtu)); m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ssrc0,videoMtu));
char strTemp[100]; char strTemp[100];
...@@ -140,7 +141,7 @@ void RtmpToRtspMediaSource::makeSDP() { ...@@ -140,7 +141,7 @@ void RtmpToRtspMediaSource::makeSDP() {
auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) { auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
m_pRtspSrc->onGetRTP(pkt,bKeyPos); m_pRtspSrc->onGetRTP(pkt,bKeyPos);
}; };
static uint32_t audioMtu = mINI::Instance()[Config::Rtp::kAudioMtuSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,audioMtu,Config::Rtp::kAudioMtuSize);
m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc1, audioMtu,m_pParser->getAudioSampleRate())); m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc1, audioMtu,m_pParser->getAudioSampleRate()));
char configStr[32]; char configStr[32];
......
...@@ -47,8 +47,10 @@ static uint32_t addressToInt(const string &ip){ ...@@ -47,8 +47,10 @@ static uint32_t addressToInt(const string &ip){
std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) { std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
lock_guard<recursive_mutex> lck(m_mtx); lock_guard<recursive_mutex> lck(m_mtx);
static uint32_t addrMin = addressToInt(mINI::Instance()[Config::MultiCast::kAddrMin]); GET_CONFIG_AND_REGISTER(string,addrMinStr,Config::MultiCast::kAddrMin);
static uint32_t addrMax = addressToInt(mINI::Instance()[Config::MultiCast::kAddrMax]); GET_CONFIG_AND_REGISTER(string,addrMaxStr,Config::MultiCast::kAddrMax);
uint32_t addrMin = addressToInt(addrMinStr);
uint32_t addrMax = addressToInt(addrMaxStr);
if(m_iAddr > addrMax || m_iAddr == 0){ if(m_iAddr > addrMax || m_iAddr == 0){
m_iAddr = addrMin; m_iAddr = addrMin;
...@@ -106,7 +108,8 @@ RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strVhost,c ...@@ -106,7 +108,8 @@ RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strVhost,c
throw std::runtime_error(strErr); throw std::runtime_error(strErr);
} }
auto fd = m_apUdpSock[i]->rawFD(); auto fd = m_apUdpSock[i]->rawFD();
static uint32_t udpTTL = mINI::Instance()[Config::MultiCast::kUdpTTL].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,Config::MultiCast::kUdpTTL);
SockUtil::setMultiTTL(fd, udpTTL); SockUtil::setMultiTTL(fd, udpTTL);
SockUtil::setMultiLOOP(fd, false); SockUtil::setMultiLOOP(fd, false);
SockUtil::setMultiIF(fd, strLocalIp.data()); SockUtil::setMultiIF(fd, strLocalIp.data());
......
...@@ -127,7 +127,7 @@ void RtspPlayer::play(const char* strUrl, const char *strUser, const char *strPw ...@@ -127,7 +127,7 @@ void RtspPlayer::play(const char* strUrl, const char *strUser, const char *strPw
} }
m_eType = eType; m_eType = eType;
if (m_eType == RTP_TCP && !m_pucRtpBuf) { if (m_eType == RTP_TCP && !m_pucRtpBuf) {
static uint32_t rtpSize = mINI::Instance()[Config::Rtp::kUdpBufSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,rtpSize,Config::Rtp::kUdpBufSize);
m_pucRtpBuf = new uint8_t[rtpSize]; m_pucRtpBuf = new uint8_t[rtpSize];
} }
auto ip = FindField(strUrl, "://", "/"); auto ip = FindField(strUrl, "://", "/");
...@@ -203,7 +203,7 @@ void RtspPlayer::onRecv(const Socket::Buffer::Ptr& pBuf) { ...@@ -203,7 +203,7 @@ void RtspPlayer::onRecv(const Socket::Buffer::Ptr& pBuf) {
if (m_eType == RTP_TCP && m_pucRtpBuf) { if (m_eType == RTP_TCP && m_pucRtpBuf) {
//RTP data //RTP data
while (size > 0) { while (size > 0) {
static uint32_t rtpSize = mINI::Instance()[Config::Rtp::kUdpBufSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,rtpSize,Config::Rtp::kUdpBufSize);
int added = rtpSize - m_uiRtpBufLen; int added = rtpSize - m_uiRtpBufLen;
added = (added > size ? size : added); added = (added > size ? size : added);
memcpy(m_pucRtpBuf + m_uiRtpBufLen, buf, added); memcpy(m_pucRtpBuf + m_uiRtpBufLen, buf, added);
...@@ -607,8 +607,8 @@ inline bool RtspPlayer::HandleOneRtp(int iTrackidx, unsigned char *pucData, unsi ...@@ -607,8 +607,8 @@ inline bool RtspPlayer::HandleOneRtp(int iTrackidx, unsigned char *pucData, unsi
//开始排序缓存 //开始排序缓存
if (m_abSortStarted[iTrackidx]) { if (m_abSortStarted[iTrackidx]) {
m_amapRtpSort[iTrackidx].emplace(rtppt.sequence, pt_ptr); m_amapRtpSort[iTrackidx].emplace(rtppt.sequence, pt_ptr);
static uint32_t clearCount = mINI::Instance()[Config::Rtp::kClearCount].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,clearCount,Config::Rtp::kClearCount);
static uint32_t maxRtpCount = mINI::Instance()[Config::Rtp::kMaxRtpCount].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,maxRtpCount,Config::Rtp::kMaxRtpCount);
if (m_aui64SeqOkCnt[iTrackidx] >= clearCount) { if (m_aui64SeqOkCnt[iTrackidx] >= clearCount) {
//网络环境改善,需要清空排序缓存 //网络环境改善,需要清空排序缓存
m_aui64SeqOkCnt[iTrackidx] = 0; m_aui64SeqOkCnt[iTrackidx] = 0;
......
...@@ -127,7 +127,7 @@ void RtspSession::onError(const SockException& err) { ...@@ -127,7 +127,7 @@ void RtspSession::onError(const SockException& err) {
} }
//流量统计事件广播 //流量统计事件广播
static uint64_t iFlowThreshold = mINI::Instance()[Broadcast::kFlowThreshold]; GET_CONFIG_AND_REGISTER(uint32_t,iFlowThreshold,Broadcast::kFlowThreshold);
if(m_ui64TotalBytes > iFlowThreshold * 1024){ if(m_ui64TotalBytes > iFlowThreshold * 1024){
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,m_mediaInfo,m_ui64TotalBytes); NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,m_mediaInfo,m_ui64TotalBytes);
} }
...@@ -278,7 +278,7 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin ...@@ -278,7 +278,7 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin
int n; int n;
char response[2 * 1024]; char response[2 * 1024];
static bool authBasic = mINI::Instance()[Config::Rtsp::kAuthBasic]; GET_CONFIG_AND_REGISTER(bool,authBasic,Config::Rtsp::kAuthBasic);
if (!authBasic) { if (!authBasic) {
//我们需要客户端优先以md5方式认证 //我们需要客户端优先以md5方式认证
strongSelf->m_strNonce = makeRandStr(32); strongSelf->m_strNonce = makeRandStr(32);
...@@ -617,7 +617,7 @@ bool RtspSession::handleReq_Setup() { ...@@ -617,7 +617,7 @@ bool RtspSession::handleReq_Setup() {
return false; return false;
} }
startListenPeerUdpData(); startListenPeerUdpData();
static uint32_t udpTTL = mINI::Instance()[MultiCast::kUdpTTL].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL);
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n" int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n" "CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n" "Server: %s-%0.2f(build in %s)\r\n"
......
...@@ -47,7 +47,7 @@ ShellSession::~ShellSession() { ...@@ -47,7 +47,7 @@ ShellSession::~ShellSession() {
void ShellSession::onRecv(const Socket::Buffer::Ptr&buf) { void ShellSession::onRecv(const Socket::Buffer::Ptr&buf) {
//DebugL << hexdump(buf->data(), buf->size()); //DebugL << hexdump(buf->data(), buf->size());
static uint32_t maxReqSize = mINI::Instance()[Config::Shell::kMaxReqSize].as<uint32_t>(); GET_CONFIG_AND_REGISTER(uint32_t,maxReqSize,Config::Shell::kMaxReqSize);
if (m_strRecvBuf.size() + buf->size() >= maxReqSize) { if (m_strRecvBuf.size() + buf->size() >= maxReqSize) {
WarnL << "接收缓冲区溢出!"; WarnL << "接收缓冲区溢出!";
shutdown(); shutdown();
......
...@@ -135,25 +135,27 @@ static onceToken s_token([](){ ...@@ -135,25 +135,27 @@ static onceToken s_token([](){
}, nullptr); }, nullptr);
int main(int argc,char *argv[]){ int main(int argc,char *argv[]) {
//设置退出信号处理函数 //设置退出信号处理函数
signal(SIGINT, [](int){EventPoller::Instance().shutdown();}); signal(SIGINT, [](int) { EventPoller::Instance().shutdown(); });
signal(SIGHUP, [](int){Config::loadIniConfig();}); signal(SIGHUP, [](int) { Config::loadIniConfig(); });
//设置日志 //设置日志
Logger::Instance().add(std::make_shared<ConsoleChannel>("stdout", LTrace)); Logger::Instance().add(std::make_shared<ConsoleChannel>("stdout", LTrace));
Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>()); Logger::Instance().setWriter(std::make_shared<AsyncLogWriter>());
//加载配置文件,如果配置文件不存在就创建一个 //加载配置文件,如果配置文件不存在就创建一个
Config::loadIniConfig(); Config::loadIniConfig();
{
//这里是拉流地址,支持rtmp/rtsp协议,负载必须是H264+AAC //这里是拉流地址,支持rtmp/rtsp协议,负载必须是H264+AAC
//如果是其他不识别的音视频将会被忽略(譬如说h264+adpcm转发后会去除音频) //如果是其他不识别的音视频将会被忽略(譬如说h264+adpcm转发后会去除音频)
auto urlList = {"rtmp://live.hkstv.hk.lxdns.com/live/hks", auto urlList = {"rtmp://live.hkstv.hk.lxdns.com/live/hks",
"rtmp://live.hkstv.hk.lxdns.com/live/hks" "rtmp://live.hkstv.hk.lxdns.com/live/hks"
//rtsp链接支持输入用户名密码 //rtsp链接支持输入用户名密码
/*"rtsp://admin:jzan123456@192.168.0.122/"*/}; /*"rtsp://admin:jzan123456@192.168.0.122/"*/};
map<string , PlayerProxy::Ptr> proxyMap; map<string, PlayerProxy::Ptr> proxyMap;
int i=0; int i = 0;
for(auto &url : urlList){ for (auto &url : urlList) {
//PlayerProxy构造函数前两个参数分别为应用名(app),流id(streamId) //PlayerProxy构造函数前两个参数分别为应用名(app),流id(streamId)
//比如说应用为live,流id为0,那么直播地址为: //比如说应用为live,流id为0,那么直播地址为:
//http://127.0.0.1/live/0/hls.m3u8 //http://127.0.0.1/live/0/hls.m3u8
...@@ -163,58 +165,85 @@ int main(int argc,char *argv[]){ ...@@ -163,58 +165,85 @@ int main(int argc,char *argv[]){
//http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
//rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
//rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4
PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST,"live",to_string(i).data())); PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST, "live", to_string(i).data()));
//指定RTP over TCP(播放rtsp时有效) //指定RTP over TCP(播放rtsp时有效)
(*player)[RtspPlayer::kRtpType] = PlayerBase::RTP_TCP; (*player)[RtspPlayer::kRtpType] = PlayerBase::RTP_TCP;
//开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试 //开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试
player->play(url); player->play(url);
//需要保存PlayerProxy,否则作用域结束就会销毁该对象 //需要保存PlayerProxy,否则作用域结束就会销毁该对象
proxyMap.emplace(to_string(i),player); proxyMap.emplace(to_string(i), player);
++i; ++i;
} }
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
//请把证书"test_server.pem"放置在本程序可执行程序同目录下 //请把证书"test_server.pem"放置在本程序可执行程序同目录下
try{ try {
//加载证书,证书包含公钥和私钥 //加载证书,证书包含公钥和私钥
SSL_Initor::Instance().loadServerPem((exePath() + ".pem").data()); SSL_Initor::Instance().loadServerPem((exePath() + ".pem").data());
}catch(...){ } catch (...) {
FatalL << "请把证书:" << (exeName() + ".pem") << "放置在本程序可执行程序同目录下:" << exeDir() << endl; FatalL << "请把证书:" << (exeName() + ".pem") << "放置在本程序可执行程序同目录下:" << exeDir() << endl;
proxyMap.clear(); proxyMap.clear();
return 0; return 0;
} }
#endif //ENABLE_OPENSSL #endif //ENABLE_OPENSSL
uint16_t shellPort = mINI::Instance()[Config::Shell::kPort];
uint16_t rtspPort = mINI::Instance()[Config::Rtsp::kPort];
uint16_t rtmpPort = mINI::Instance()[Config::Rtmp::kPort];
uint16_t httpPort = mINI::Instance()[Config::Http::kPort];
uint16_t httpsPort = mINI::Instance()[Config::Http::kSSLPort];
//简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象 //简单的telnet服务器,可用于服务器调试,但是不能使用23端口,否则telnet上了莫名其妙的现象
//测试方法:telnet 127.0.0.1 9000 //测试方法:telnet 127.0.0.1 9000
TcpServer<ShellSession>::Ptr shellSrv(new TcpServer<ShellSession>()); TcpServer<ShellSession>::Ptr shellSrv(new TcpServer<ShellSession>());
shellSrv->start(mINI::Instance()[Config::Shell::kPort]);
//开启rtsp/rtmp/http服务器
TcpServer<RtspSession>::Ptr rtspSrv(new TcpServer<RtspSession>()); TcpServer<RtspSession>::Ptr rtspSrv(new TcpServer<RtspSession>());
TcpServer<RtmpSession>::Ptr rtmpSrv(new TcpServer<RtmpSession>()); TcpServer<RtmpSession>::Ptr rtmpSrv(new TcpServer<RtmpSession>());
TcpServer<HttpSession>::Ptr httpSrv(new TcpServer<HttpSession>()); TcpServer<HttpSession>::Ptr httpSrv(new TcpServer<HttpSession>());
rtspSrv->start(mINI::Instance()[Config::Rtsp::kPort]);//默认554 shellSrv->start(shellPort);
rtmpSrv->start(mINI::Instance()[Config::Rtmp::kPort]);//默认1935 rtspSrv->start(rtspPort);//默认554
httpSrv->start(mINI::Instance()[Config::Http::kPort]);//默认80 rtmpSrv->start(rtmpPort);//默认1935
httpSrv->start(httpPort);//默认80
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
//如果支持ssl,还可以开启https服务器 //如果支持ssl,还可以开启https服务器
TcpServer<HttpsSession>::Ptr httpsSrv(new TcpServer<HttpsSession>()); TcpServer<HttpsSession>::Ptr httpsSrv(new TcpServer<HttpsSession>());
httpsSrv->start(mINI::Instance()[Config::Http::kSSLPort]);//默认443 httpsSrv->start(httpsPort);//默认443
#endif //ENABLE_OPENSSL #endif //ENABLE_OPENSSL
EventPoller::Instance().runLoop(); NoticeCenter::Instance().addListener(ReloadConfigTag,Config::Broadcast::kBroadcastReloadConfig,[&](BroadcastReloadConfigArgs){
//销毁拉流客户端 //重新创建服务器
proxyMap.clear(); if(shellPort != mINI::Instance()[Config::Shell::kPort].as<uint16_t>()){
//销毁服务器 shellPort = mINI::Instance()[Config::Shell::kPort];
shellSrv.reset(); shellSrv->start(shellPort);
rtspSrv.reset(); InfoL << "重启shell服务器:" << shellPort;
rtmpSrv.reset(); }
httpSrv.reset(); if(rtspPort != mINI::Instance()[Config::Rtsp::kPort].as<uint16_t>()){
rtspPort = mINI::Instance()[Config::Rtsp::kPort];
rtspSrv->start(rtspPort);
InfoL << "重启rtsp服务器" << rtspPort;
}
if(rtmpPort != mINI::Instance()[Config::Rtmp::kPort].as<uint16_t>()){
rtmpPort = mINI::Instance()[Config::Rtmp::kPort];
rtmpSrv->start(rtmpPort);
InfoL << "重启rtmp服务器" << rtmpPort;
}
if(httpPort != mINI::Instance()[Config::Http::kPort].as<uint16_t>()){
httpPort = mINI::Instance()[Config::Http::kPort];
httpSrv->start(httpPort);
InfoL << "重启http服务器" << httpPort;
}
#ifdef ENABLE_OPENSSL #ifdef ENABLE_OPENSSL
httpsSrv.reset(); if(httpsPort != mINI::Instance()[Config::Http::kSSLPort].as<uint16_t>()){
httpsPort = mINI::Instance()[Config::Http::kSSLPort];
httpsSrv->start(httpsPort);
InfoL << "重启https服务器" << httpsPort;
}
#endif //ENABLE_OPENSSL #endif //ENABLE_OPENSSL
});
EventPoller::Instance().runLoop();
}//设置作用域,作用域结束后会销毁临时变量;省去手动注销服务器
//rtsp服务器用到udp端口分配器了 //rtsp服务器用到udp端口分配器了
UDPServer::Destory(); UDPServer::Destory();
......
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论