for rtp server can config pt

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

View File

@ -265,6 +265,28 @@ timeoutSec=15
#该范围同时限制rtsp服务器udp端口范围
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

View File

@ -8,31 +8,31 @@
* may be found in the AUTHORS file in the root of the source tree.
*/
#include <stdio.h>
#include <assert.h>
#include "Common/config.h"
#include "Util/util.h"
#include "Util/NoticeCenter.h"
#include "Util/logger.h"
#include "Util/onceToken.h"
#include "Util/NoticeCenter.h"
#include "Util/util.h"
#include <assert.h>
#include <stdio.h>
using namespace std;
using namespace toolkit;
namespace mediakit {
bool loadIniConfig(const char *ini_path){
bool loadIniConfig(const char *ini_path) {
string ini;
if(ini_path && ini_path[0] != '\0'){
if (ini_path && ini_path[0] != '\0') {
ini = ini_path;
}else{
} else {
ini = exePath() + ".ini";
}
try{
try {
mINI::Instance().parseFile(ini);
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastReloadConfig);
return true;
}catch (std::exception &) {
} catch (std::exception &) {
InfoL << "dump ini file to:" << ini;
mINI::Instance().dumpFile(ini);
return false;
@ -55,36 +55,36 @@ const string kBroadcastShellLogin = "kBroadcastShellLogin";
const string kBroadcastNotFoundStream = "kBroadcastNotFoundStream";
const string kBroadcastStreamNoneReader = "kBroadcastStreamNoneReader";
const string kBroadcastHttpBeforeAccess = "kBroadcastHttpBeforeAccess";
} //namespace Broadcast
} // namespace Broadcast
//通用配置项目
namespace General{
// 通用配置项目
namespace General {
#define GENERAL_FIELD "general."
const string kMediaServerId = GENERAL_FIELD"mediaServerId";
const string kFlowThreshold = GENERAL_FIELD"flowThreshold";
const string kStreamNoneReaderDelayMS = GENERAL_FIELD"streamNoneReaderDelayMS";
const string kMaxStreamWaitTimeMS = GENERAL_FIELD"maxStreamWaitMS";
const string kEnableVhost = GENERAL_FIELD"enableVhost";
const string kAddMuteAudio = GENERAL_FIELD"addMuteAudio";
const string kResetWhenRePlay = GENERAL_FIELD"resetWhenRePlay";
const string kPublishToHls = GENERAL_FIELD"publishToHls";
const string kPublishToMP4 = GENERAL_FIELD"publishToMP4";
const string kMergeWriteMS = GENERAL_FIELD"mergeWriteMS";
const string kModifyStamp = GENERAL_FIELD"modifyStamp";
const string kHlsDemand = GENERAL_FIELD"hls_demand";
const string kRtspDemand = GENERAL_FIELD"rtsp_demand";
const string kRtmpDemand = GENERAL_FIELD"rtmp_demand";
const string kTSDemand = GENERAL_FIELD"ts_demand";
const string kFMP4Demand = GENERAL_FIELD"fmp4_demand";
const string kEnableAudio = GENERAL_FIELD"enable_audio";
const string kCheckNvidiaDev = GENERAL_FIELD"check_nvidia_dev";
const string kEnableFFmpegLog = GENERAL_FIELD"enable_ffmpeg_log";
const string kWaitTrackReadyMS = GENERAL_FIELD"wait_track_ready_ms";
const string kWaitAddTrackMS = GENERAL_FIELD"wait_add_track_ms";
const string kUnreadyFrameCache = GENERAL_FIELD"unready_frame_cache";
const string kContinuePushMS = GENERAL_FIELD"continue_push_ms";
const string kMediaServerId = GENERAL_FIELD "mediaServerId";
const string kFlowThreshold = GENERAL_FIELD "flowThreshold";
const string kStreamNoneReaderDelayMS = GENERAL_FIELD "streamNoneReaderDelayMS";
const string kMaxStreamWaitTimeMS = GENERAL_FIELD "maxStreamWaitMS";
const string kEnableVhost = GENERAL_FIELD "enableVhost";
const string kAddMuteAudio = GENERAL_FIELD "addMuteAudio";
const string kResetWhenRePlay = GENERAL_FIELD "resetWhenRePlay";
const string kPublishToHls = GENERAL_FIELD "publishToHls";
const string kPublishToMP4 = GENERAL_FIELD "publishToMP4";
const string kMergeWriteMS = GENERAL_FIELD "mergeWriteMS";
const string kModifyStamp = GENERAL_FIELD "modifyStamp";
const string kHlsDemand = GENERAL_FIELD "hls_demand";
const string kRtspDemand = GENERAL_FIELD "rtsp_demand";
const string kRtmpDemand = GENERAL_FIELD "rtmp_demand";
const string kTSDemand = GENERAL_FIELD "ts_demand";
const string kFMP4Demand = GENERAL_FIELD "fmp4_demand";
const string kEnableAudio = GENERAL_FIELD "enable_audio";
const string kCheckNvidiaDev = GENERAL_FIELD "check_nvidia_dev";
const string kEnableFFmpegLog = GENERAL_FIELD "enable_ffmpeg_log";
const string kWaitTrackReadyMS = GENERAL_FIELD "wait_track_ready_ms";
const string kWaitAddTrackMS = GENERAL_FIELD "wait_add_track_ms";
const string kUnreadyFrameCache = GENERAL_FIELD "unready_frame_cache";
const string kContinuePushMS = GENERAL_FIELD "continue_push_ms";
static onceToken token([](){
static onceToken token([]() {
mINI::Instance()[kFlowThreshold] = 1024;
mINI::Instance()[kStreamNoneReaderDelayMS] = 20 * 1000;
mINI::Instance()[kMaxStreamWaitTimeMS] = 15 * 1000;
@ -110,22 +110,22 @@ static onceToken token([](){
mINI::Instance()[kContinuePushMS] = 15 * 1000;
});
}//namespace General
} // namespace General
////////////HTTP配置///////////
namespace Http {
#define HTTP_FIELD "http."
const string kSendBufSize = HTTP_FIELD"sendBufSize";
const string kMaxReqSize = HTTP_FIELD"maxReqSize";
const string kKeepAliveSecond = HTTP_FIELD"keepAliveSecond";
const string kCharSet = HTTP_FIELD"charSet";
const string kRootPath = HTTP_FIELD"rootPath";
const string kSendBufSize = HTTP_FIELD "sendBufSize";
const string kMaxReqSize = HTTP_FIELD "maxReqSize";
const string kKeepAliveSecond = HTTP_FIELD "keepAliveSecond";
const string kCharSet = HTTP_FIELD "charSet";
const string kRootPath = HTTP_FIELD "rootPath";
const string kVirtualPath = HTTP_FIELD "virtualPath";
const string kNotFound = HTTP_FIELD"notFound";
const string kDirMenu = HTTP_FIELD"dirMenu";
const string kForbidCacheSuffix = HTTP_FIELD"forbidCacheSuffix";
const string kNotFound = HTTP_FIELD "notFound";
const string kDirMenu = HTTP_FIELD "dirMenu";
const string kForbidCacheSuffix = HTTP_FIELD "forbidCacheSuffix";
static onceToken token([](){
static onceToken token([]() {
mINI::Instance()[kSendBufSize] = 64 * 1024;
mINI::Instance()[kMaxReqSize] = 4 * 10240;
mINI::Instance()[kKeepAliveSecond] = 15;
@ -135,7 +135,7 @@ static onceToken token([](){
#if defined(_WIN32)
mINI::Instance()[kCharSet] = "gb2312";
#else
mINI::Instance()[kCharSet] ="utf-8";
mINI::Instance()[kCharSet] = "utf-8";
#endif
mINI::Instance()[kRootPath] = "./www";
@ -152,118 +152,115 @@ static onceToken token([](){
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
#ifdef ENABLE_MEM_DEBUG
extern "C" {
extern void *__real_malloc(size_t);
extern void __real_free(void *);
extern void *__real_realloc(void *ptr, size_t c);
void *__wrap_malloc(size_t c);
void __wrap_free(void *ptr);
void *__wrap_calloc(size_t __nmemb, size_t __size);
void *__wrap_realloc(void *ptr, size_t c);
extern void *__real_malloc(size_t);
extern void __real_free(void *);
extern void *__real_realloc(void *ptr, size_t c);
void *__wrap_malloc(size_t c);
void __wrap_free(void *ptr);
void *__wrap_calloc(size_t __nmemb, size_t __size);
void *__wrap_realloc(void *ptr, size_t c);
}
#define BLOCK_TYPES 16
@ -344,8 +353,8 @@ std::vector<size_t> getBlockTypeSize() {
class MemThreadInfo {
public:
using Ptr = std::shared_ptr<MemThreadInfo>;
atomic<uint64_t> mem_usage{0};
atomic<uint64_t> mem_block{0};
atomic<uint64_t> mem_usage { 0 };
atomic<uint64_t> mem_block { 0 };
atomic<uint64_t> mem_block_map[BLOCK_TYPES];
static MemThreadInfo *Instance(bool is_thread_local) {
@ -358,25 +367,21 @@ public:
}
~MemThreadInfo() {
//printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
// printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
}
MemThreadInfo(bool is_thread_local) {
_is_thread_local = is_thread_local;
if (_is_thread_local) {
//确保所有线程退出后才能释放全局内存统计器
// 确保所有线程退出后才能释放全局内存统计器
total_mem = Instance(false);
}
//printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
// printf("%s %d\r\n", __FUNCTION__, (int) _is_thread_local);
}
void *operator new(size_t sz) {
return __real_malloc(sz);
}
void *operator new(size_t sz) { return __real_malloc(sz); }
void operator delete(void *ptr) {
__real_free(ptr);
}
void operator delete(void *ptr) { __real_free(ptr); }
void addBlock(size_t c) {
if (total_mem) {
@ -410,19 +415,15 @@ public:
ptr->addBlock(1);
}
~MemThreadInfoLocal() {
ptr->delBlock(1);
}
~MemThreadInfoLocal() { ptr->delBlock(1); }
MemThreadInfo *get() const {
return ptr;
}
MemThreadInfo *get() const { return ptr; }
private:
MemThreadInfo *ptr;
};
//该变量主要确保线程退出后才能释放MemThreadInfo变量
// 该变量主要确保线程退出后才能释放MemThreadInfo变量
static thread_local MemThreadInfoLocal s_thread_mem_info;
uint64_t getTotalMemUsage() {
@ -456,7 +457,7 @@ public:
static constexpr uint32_t kMagic = 0xFEFDFCFB;
uint32_t magic;
uint32_t size;
MemThreadInfo* alloc_info;
MemThreadInfo *alloc_info;
char ptr;
};
@ -465,10 +466,10 @@ public:
#if (defined(__linux__) && !defined(ANDROID)) || defined(__MACH__)
#define MAX_STACK_FRAMES 128
#define MEM_WARING
#include <execinfo.h>
#include <limits.h>
#include <sys/resource.h>
#include <sys/wait.h>
#include <execinfo.h>
static void print_mem_waring(size_t c) {
void *array[MAX_STACK_FRAMES];
@ -503,7 +504,7 @@ static void un_init_cookie(MemCookie *cookie) {
void *__wrap_malloc(size_t c) {
c += MEM_OFFSET;
auto cookie = (MemCookie *) __real_malloc(c);
auto cookie = (MemCookie *)__real_malloc(c);
if (cookie) {
init_cookie(cookie, c);
return &cookie->ptr;
@ -515,7 +516,7 @@ void __wrap_free(void *ptr) {
if (!ptr) {
return;
}
auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET);
auto cookie = (MemCookie *)((char *)ptr - MEM_OFFSET);
if (cookie->magic != MemCookie::kMagic) {
__real_free(ptr);
return;
@ -538,14 +539,14 @@ void *__wrap_realloc(void *ptr, size_t c) {
return malloc(c);
}
auto cookie = (MemCookie *) ((char *) ptr - MEM_OFFSET);
auto cookie = (MemCookie *)((char *)ptr - MEM_OFFSET);
if (cookie->magic != MemCookie::kMagic) {
return __real_realloc(ptr, c);
}
un_init_cookie(cookie);
c += MEM_OFFSET;
cookie = (MemCookie *) __real_realloc(cookie, c);
cookie = (MemCookie *)__real_realloc(cookie, c);
if (cookie) {
init_cookie(cookie, c);
return &cookie->ptr;

View File

@ -8,35 +8,34 @@
* may be found in the AUTHORS file in the root of the source tree.
*/
#ifndef COMMON_CONFIG_H
#define COMMON_CONFIG_H
#include <functional>
#include "Util/NoticeCenter.h"
#include "Util/mini.h"
#include "Util/onceToken.h"
#include "Util/NoticeCenter.h"
#include "macros.h"
#include <functional>
namespace mediakit {
class ProtocolOption;
//加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件
//加载配置文件成功后会触发kBroadcastUpdateConfig广播
//如果指定的文件名(ini_path)为空,那么会加载默认配置文件
//默认配置文件名为 /path/to/your/exe.ini
//加载配置文件成功后返回true否则返回false
// 加载配置文件,如果配置文件不存在,那么会导出默认配置并生成配置文件
// 加载配置文件成功后会触发kBroadcastUpdateConfig广播
// 如果指定的文件名(ini_path)为空,那么会加载默认配置文件
// 默认配置文件名为 /path/to/your/exe.ini
// 加载配置文件成功后返回true否则返回false
bool loadIniConfig(const char *ini_path = nullptr);
////////////广播名称///////////
namespace Broadcast {
//注册或反注册MediaSource事件广播
// 注册或反注册MediaSource事件广播
extern const std::string kBroadcastMediaChanged;
#define BroadcastMediaChangedArgs const bool &bRegist, MediaSource &sender
//录制mp4文件成功后广播
// 录制mp4文件成功后广播
extern const std::string kBroadcastRecordMP4;
#define BroadcastRecordMP4Args const RecordInfo &info
@ -44,66 +43,75 @@ extern const std::string kBroadcastRecordMP4;
extern const std::string kBroadcastRecordTs;
#define BroadcastRecordTsArgs const RecordInfo &info
//收到http api请求广播
// 收到http api请求广播
extern const std::string kBroadcastHttpRequest;
#define BroadcastHttpRequestArgs const Parser &parser,const HttpSession::HttpResponseInvoker &invoker,bool &consumed,SockInfo &sender
#define BroadcastHttpRequestArgs \
const Parser &parser, const HttpSession::HttpResponseInvoker &invoker, bool &consumed, SockInfo &sender
//在http文件服务器中,收到http访问文件或目录的广播,通过该事件控制访问http目录的权限
// 在http文件服务器中,收到http访问文件或目录的广播,通过该事件控制访问http目录的权限
extern const std::string kBroadcastHttpAccess;
#define BroadcastHttpAccessArgs const Parser &parser,const std::string &path,const bool &is_dir,const HttpSession::HttpAccessPathInvoker &invoker,SockInfo &sender
#define BroadcastHttpAccessArgs \
const Parser &parser, const std::string &path, const bool &is_dir, \
const HttpSession::HttpAccessPathInvoker &invoker, SockInfo &sender
//在http文件服务器中,收到http访问文件或目录前的广播,通过该事件可以控制http url到文件路径的映射
//在该事件中通过自行覆盖path参数可以做到譬如根据虚拟主机或者app选择不同http根目录的目的
// 在http文件服务器中,收到http访问文件或目录前的广播,通过该事件可以控制http url到文件路径的映射
// 在该事件中通过自行覆盖path参数可以做到譬如根据虚拟主机或者app选择不同http根目录的目的
extern const std::string kBroadcastHttpBeforeAccess;
#define BroadcastHttpBeforeAccessArgs const Parser &parser, std::string &path, SockInfo &sender
//该流是否需要认证是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证
// 该流是否需要认证是的话调用invoker并传入realm,否则传入空的realm.如果该事件不监听则不认证
extern const std::string kBroadcastOnGetRtspRealm;
#define BroadcastOnGetRtspRealmArgs const MediaInfo &args,const RtspSession::onGetRealm &invoker,SockInfo &sender
#define BroadcastOnGetRtspRealmArgs const MediaInfo &args, const RtspSession::onGetRealm &invoker, SockInfo &sender
//请求认证用户密码事件user_name为用户名must_no_encrypt如果为true则必须提供明文密码(因为此时是base64认证方式),否则会导致认证失败
//获取到密码后请调用invoker并输入对应类型的密码和密码类型invoker执行时会匹配密码
// 请求认证用户密码事件user_name为用户名must_no_encrypt如果为true则必须提供明文密码(因为此时是base64认证方式),否则会导致认证失败
// 获取到密码后请调用invoker并输入对应类型的密码和密码类型invoker执行时会匹配密码
extern const std::string kBroadcastOnRtspAuth;
#define BroadcastOnRtspAuthArgs const MediaInfo &args,const std::string &realm,const std::string &user_name,const bool &must_no_encrypt,const RtspSession::onAuth &invoker,SockInfo &sender
#define BroadcastOnRtspAuthArgs \
const MediaInfo &args, const std::string &realm, const std::string &user_name, const bool &must_no_encrypt, \
const RtspSession::onAuth &invoker, SockInfo &sender
//推流鉴权结果回调对象
//如果err为空则代表鉴权成功
// 推流鉴权结果回调对象
// 如果err为空则代表鉴权成功
using PublishAuthInvoker = std::function<void(const std::string &err, const ProtocolOption &option)>;
//收到rtsp/rtmp推流事件广播通过该事件控制推流鉴权
// 收到rtsp/rtmp推流事件广播通过该事件控制推流鉴权
extern const std::string kBroadcastMediaPublish;
#define BroadcastMediaPublishArgs const MediaOriginType &type, const MediaInfo &args, const Broadcast::PublishAuthInvoker &invoker,SockInfo &sender
#define BroadcastMediaPublishArgs \
const MediaOriginType &type, const MediaInfo &args, const Broadcast::PublishAuthInvoker &invoker, SockInfo &sender
//播放鉴权结果回调对象
//如果err为空则代表鉴权成功
// 播放鉴权结果回调对象
// 如果err为空则代表鉴权成功
using AuthInvoker = std::function<void(const std::string &err)>;
//播放rtsp/rtmp/http-flv事件广播通过该事件控制播放鉴权
// 播放rtsp/rtmp/http-flv事件广播通过该事件控制播放鉴权
extern const std::string kBroadcastMediaPlayed;
#define BroadcastMediaPlayedArgs const MediaInfo &args,const Broadcast::AuthInvoker &invoker,SockInfo &sender
#define BroadcastMediaPlayedArgs const MediaInfo &args, const Broadcast::AuthInvoker &invoker, SockInfo &sender
//shell登录鉴权
// shell登录鉴权
extern const std::string kBroadcastShellLogin;
#define BroadcastShellLoginArgs const std::string &user_name,const std::string &passwd,const Broadcast::AuthInvoker &invoker,SockInfo &sender
#define BroadcastShellLoginArgs \
const std::string &user_name, const std::string &passwd, const Broadcast::AuthInvoker &invoker, SockInfo &sender
//停止rtsp/rtmp/http-flv会话后流量汇报事件广播
// 停止rtsp/rtmp/http-flv会话后流量汇报事件广播
extern const std::string kBroadcastFlowReport;
#define BroadcastFlowReportArgs const MediaInfo &args,const uint64_t &totalBytes,const uint64_t &totalDuration,const bool &isPlayer, SockInfo &sender
#define BroadcastFlowReportArgs \
const MediaInfo &args, const uint64_t &totalBytes, const uint64_t &totalDuration, const bool &isPlayer, \
SockInfo &sender
//未找到流后会广播该事件,请在监听该事件后去拉流或其他方式产生流,这样就能按需拉流了
// 未找到流后会广播该事件,请在监听该事件后去拉流或其他方式产生流,这样就能按需拉流了
extern const std::string kBroadcastNotFoundStream;
#define BroadcastNotFoundStreamArgs const MediaInfo &args, SockInfo &sender, const std::function<void()> &closePlayer
//某个流无人消费时触发,目的为了实现无人观看时主动断开拉流等业务逻辑
// 某个流无人消费时触发,目的为了实现无人观看时主动断开拉流等业务逻辑
extern const std::string kBroadcastStreamNoneReader;
#define BroadcastStreamNoneReaderArgs MediaSource &sender
//更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播
// 更新配置文件事件广播,执行loadIniConfig函数加载配置文件成功后会触发该广播
extern const std::string kBroadcastReloadConfig;
#define BroadcastReloadConfigArgs void
#define ReloadConfigTag ((void *)(0xFF))
#define RELOAD_KEY(arg,key) \
#define RELOAD_KEY(arg, key) \
do { \
decltype(arg) arg##_tmp = ::toolkit::mINI::Instance()[key]; \
if (arg == arg##_tmp) { \
@ -111,30 +119,26 @@ extern const std::string kBroadcastReloadConfig;
} \
arg = arg##_tmp; \
InfoL << "reload config:" << key << "=" << arg; \
} while(0)
} 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__; \
static ::toolkit::onceToken s_token_listen([]() { \
::toolkit::NoticeCenter::Instance().addListener( \
ReloadConfigTag, Broadcast::kBroadcastReloadConfig, [](BroadcastReloadConfigArgs) { __VA_ARGS__; }); \
}); \
}); \
} while(0)
} while (0)
#define GET_CONFIG(type, arg, key) \
static type arg = ::toolkit::mINI::Instance()[key]; \
LISTEN_RELOAD_KEY(arg, key, { \
RELOAD_KEY(arg, 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 ::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, { \
@ -142,187 +146,199 @@ extern const std::string kBroadcastReloadConfig;
arg = lam(arg##_str); \
}); \
}); \
} while(0)
} while (0)
} //namespace Broadcast
} // namespace Broadcast
////////////通用配置///////////
namespace General{
//每个流媒体服务器的IDGUID
namespace General {
// 每个流媒体服务器的IDGUID
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;
//是否默认推流时转换成hlshook接口(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进行时间戳覆盖
// 是否默认推流时转换成hlshook接口(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 Client
} // namespace mediakit
#endif /* COMMON_CONFIG_H */

View File

@ -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,76 +66,61 @@ void GB28181Process::onRtpSorted(RtpPacket::Ptr rtp) {
}
bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
RtpHeader *header = (RtpHeader *) data;
GET_CONFIG(uint32_t, h264_pt, RtpProxy::KH264PT);
GET_CONFIG(uint32_t, h265_pt, RtpProxy::KH265PT);
GET_CONFIG(uint32_t, ps_pt, RtpProxy::KPSPT);
GET_CONFIG(uint32_t, ts_pt, RtpProxy::KTSPT);
GET_CONFIG(uint32_t, opus_pt, RtpProxy::KOpusPT);
GET_CONFIG(uint32_t, g711u_pt, RtpProxy::KG711UPT);
GET_CONFIG(uint32_t, g711a_pt, RtpProxy::KG711APT);
RtpHeader *header = (RtpHeader *)data;
auto pt = header->pt;
auto &ref = _rtp_receiver[pt];
if (!ref) {
if (_rtp_receiver.size() > 2) {
//防止pt类型太多导致内存溢出
// 防止pt类型太多导致内存溢出
throw std::invalid_argument("rtp pt类型不得超过2种!");
}
switch (pt) {
case 100: {
//opus负载
ref = std::make_shared<RtpReceiverImp>(48000,[this](RtpPacket::Ptr rtp) {
onRtpSorted(std::move(rtp));
});
if (pt == opus_pt) {
// opus负载
ref = std::make_shared<RtpReceiverImp>(48000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<OpusTrack>();
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
break;
}
case 99: {
//H265负载
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
onRtpSorted(std::move(rtp));
});
} else if (pt == h265_pt) {
// H265负载
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<H265Track>();
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
break;
}
case 98: {
//H264负载
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
onRtpSorted(std::move(rtp));
});
} else if (pt == h264_pt) {
// H264负载
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<H264Track>();
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
break;
}
case 0:
//CodecG711U
case 8: {
//CodecG711A
ref = std::make_shared<RtpReceiverImp>(8000,[this](RtpPacket::Ptr rtp) {
onRtpSorted(std::move(rtp));
});
} else if (pt == g711u_pt || pt == g711a_pt) {
// CodecG711U
// CodecG711A
ref = std::make_shared<RtpReceiverImp>(8000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
auto track = std::make_shared<G711Track>(pt == 0 ? CodecG711U : CodecG711A, 8000, 1, 16);
_interface->addTrack(track);
_rtp_decoder[pt] = Factory::getRtpDecoderByTrack(track);
break;
} else {
if (pt != ts_pt && pt != ps_pt) {
WarnL << "rtp payload type未识别(" << (int)pt << "),已按ts或ps负载处理";
}
default: {
if (pt != 33 && pt != 96) {
WarnL << "rtp payload type未识别(" << (int) pt << "),已按ts或ps负载处理";
}
ref = std::make_shared<RtpReceiverImp>(90000, [this](RtpPacket::Ptr rtp) { onRtpSorted(std::move(rtp)); });
ref = std::make_shared<RtpReceiverImp>(90000,[this](RtpPacket::Ptr rtp) {
onRtpSorted(std::move(rtp));
});
//ts或ps负载
// ts或ps负载
_rtp_decoder[pt] = std::make_shared<CommonRtpDecoder>(CodecInvalid, 32 * 1024);
//设置dump目录
// 设置dump目录
GET_CONFIG(string, dump_dir, RtpProxy::kDumpDir);
if (!dump_dir.empty()) {
auto save_path = File::absolutePath(_media_info._streamid + ".mp2", dump_dir);
@ -145,40 +130,37 @@ bool GB28181Process::inputRtp(bool, const char *data, size_t data_len) {
}
});
}
break;
}
}
//设置frame回调
// 设置frame回调
_rtp_decoder[pt]->addDelegate(std::make_shared<FrameWriterInterfaceHelper>([this](const Frame::Ptr &frame) {
onRtpDecode(frame);
return true;
}));
}
return ref->inputRtp(TrackVideo, (unsigned char *) data, data_len);
return ref->inputRtp(TrackVideo, (unsigned char *)data, data_len);
}
void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
if (frame->getCodecId() != CodecInvalid) {
//这里不是ps或ts
// 这里不是ps或ts
_interface->inputFrame(frame);
return;
}
//这是TS或PS
// 这是TS或PS
if (_save_file_ps) {
fwrite(frame->data(), frame->size(), 1, _save_file_ps.get());
}
if (!_decoder) {
//创建解码器
if (checkTS((uint8_t *) frame->data(), frame->size())) {
//猜测是ts负载
// 创建解码器
if (checkTS((uint8_t *)frame->data(), frame->size())) {
// 猜测是ts负载
InfoL << _media_info._streamid << " judged to be TS";
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ts, _interface);
} else {
//猜测是ps负载
// 猜测是ps负载
InfoL << _media_info._streamid << " judged to be PS";
_decoder = DecoderImp::createDecoder(DecoderImp::decoder_ps, _interface);
}
@ -189,5 +171,5 @@ void GB28181Process::onRtpDecode(const Frame::Ptr &frame) {
}
}
}//namespace mediakit
#endif//defined(ENABLE_RTPPROXY)
} // namespace mediakit
#endif // defined(ENABLE_RTPPROXY)