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