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