统一成员变量命名风格

This commit is contained in:
xiongziliang 2018-10-24 15:43:52 +08:00
parent 97567ec36d
commit 39baaebc55
74 changed files with 2048 additions and 2048 deletions

View File

@ -48,17 +48,17 @@ AACEncoder::AACEncoder() {
}
AACEncoder::~AACEncoder() {
if (m_hEncoder != nullptr) {
faacEncClose(m_hEncoder);
m_hEncoder = nullptr;
if (_hEncoder != nullptr) {
faacEncClose(_hEncoder);
_hEncoder = nullptr;
}
if (m_pucAacBuf != nullptr) {
delete[] m_pucAacBuf;
m_pucAacBuf = nullptr;
if (_pucAacBuf != nullptr) {
delete[] _pucAacBuf;
_pucAacBuf = nullptr;
}
if (m_pucPcmBuf != nullptr) {
delete[] m_pucPcmBuf;
m_pucPcmBuf = nullptr;
if (_pucPcmBuf != nullptr) {
delete[] _pucPcmBuf;
_pucPcmBuf = nullptr;
}
}
@ -67,19 +67,19 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
return false;
}
// (1) Open FAAC engine
m_hEncoder = faacEncOpen(iSampleRate, iChannels, &m_ulInputSamples,
&m_ulMaxOutputBytes);
if (m_hEncoder == NULL) {
_hEncoder = faacEncOpen(iSampleRate, iChannels, &_ulInputSamples,
&_ulMaxOutputBytes);
if (_hEncoder == NULL) {
return false;
}
m_pucAacBuf = new unsigned char[m_ulMaxOutputBytes];
m_ulMaxInputBytes = m_ulInputSamples * iSampleBit / 8;
m_pucPcmBuf = new unsigned char[m_ulMaxInputBytes * 4];
_pucAacBuf = new unsigned char[_ulMaxOutputBytes];
_ulMaxInputBytes = _ulInputSamples * iSampleBit / 8;
_pucPcmBuf = new unsigned char[_ulMaxInputBytes * 4];
// (2.1) Get current encoding configuration
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(m_hEncoder);
faacEncConfigurationPtr pConfiguration = faacEncGetCurrentConfiguration(_hEncoder);
if (pConfiguration == NULL) {
faacEncClose(m_hEncoder);
faacEncClose(_hEncoder);
return false;
}
pConfiguration->aacObjectType =LOW;
@ -95,25 +95,25 @@ bool AACEncoder::init(int iSampleRate, int iChannels, int iSampleBit) {
pConfiguration->inputFormat = FAAC_INPUT_16BIT;
// (2.2) Set encoding configuration
if(!faacEncSetConfiguration(m_hEncoder, pConfiguration)){
if(!faacEncSetConfiguration(_hEncoder, pConfiguration)){
ErrorL << "faacEncSetConfiguration failed";
faacEncClose(m_hEncoder);
faacEncClose(_hEncoder);
return false;
}
return true;
}
int AACEncoder::inputData(char *pcPcmBufr, int iLen, unsigned char **ppucOutBuffer) {
memcpy(m_pucPcmBuf + m_uiPcmLen, pcPcmBufr, iLen);
m_uiPcmLen += iLen;
if (m_uiPcmLen < m_ulMaxInputBytes) {
memcpy(_pucPcmBuf + _uiPcmLen, pcPcmBufr, iLen);
_uiPcmLen += iLen;
if (_uiPcmLen < _ulMaxInputBytes) {
return 0;
}
int nRet = faacEncEncode(m_hEncoder, (int32_t *) (m_pucPcmBuf), m_ulInputSamples, m_pucAacBuf, m_ulMaxOutputBytes);
m_uiPcmLen -= m_ulMaxInputBytes;
memmove(m_pucPcmBuf, m_pucPcmBuf + m_ulMaxInputBytes, m_uiPcmLen);
*ppucOutBuffer = m_pucAacBuf;
int nRet = faacEncEncode(_hEncoder, (int32_t *) (_pucPcmBuf), _ulInputSamples, _pucAacBuf, _ulMaxOutputBytes);
_uiPcmLen -= _ulMaxInputBytes;
memmove(_pucPcmBuf, _pucPcmBuf + _ulMaxInputBytes, _uiPcmLen);
*ppucOutBuffer = _pucAacBuf;
return nRet;
}

View File

@ -39,15 +39,15 @@ public:
int inputData(char *pcData, int iLen, unsigned char **ppucOutBuffer);
private:
unsigned char *m_pucPcmBuf = nullptr;
unsigned int m_uiPcmLen = 0;
unsigned char *_pucPcmBuf = nullptr;
unsigned int _uiPcmLen = 0;
unsigned char *m_pucAacBuf = nullptr;
void *m_hEncoder = nullptr;
unsigned char *_pucAacBuf = nullptr;
void *_hEncoder = nullptr;
unsigned long m_ulInputSamples = 0;
unsigned long m_ulMaxInputBytes = 0;
unsigned long m_ulMaxOutputBytes = 0;
unsigned long _ulInputSamples = 0;
unsigned long _ulMaxInputBytes = 0;
unsigned long _ulMaxOutputBytes = 0;
};

View File

@ -39,19 +39,19 @@ H264Encoder::H264Encoder() {
H264Encoder::~H264Encoder() {
//* 清除图像区域
if (m_pPicIn) {
delete m_pPicIn;
m_pPicIn = nullptr;
if (_pPicIn) {
delete _pPicIn;
_pPicIn = nullptr;
}
if (m_pPicOut) {
delete m_pPicOut;
m_pPicOut = nullptr;
if (_pPicOut) {
delete _pPicOut;
_pPicOut = nullptr;
}
//* 关闭编码器句柄
if (m_pX264Handle) {
x264_encoder_close(m_pX264Handle);
m_pX264Handle = nullptr;
if (_pX264Handle) {
x264_encoder_close(_pX264Handle);
_pX264Handle = nullptr;
}
}
@ -229,7 +229,7 @@ Value的值就是fps。
} x264_param_t;*/
bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
if (m_pX264Handle) {
if (_pX264Handle) {
return true;
}
x264_param_t X264Param, *pX264Param = &X264Param;
@ -307,43 +307,43 @@ bool H264Encoder::init(int iWidth, int iHeight, int iFps) {
//* 打开编码器句柄,通过x264_encoder_parameters得到设置给X264
//* 的参数.通过x264_encoder_reconfig更新X264的参数
m_pX264Handle = x264_encoder_open(pX264Param);
if (!m_pX264Handle) {
_pX264Handle = x264_encoder_open(pX264Param);
if (!_pX264Handle) {
return false;
}
m_pPicIn = new x264_picture_t;
m_pPicOut = new x264_picture_t;
x264_picture_init(m_pPicIn);
x264_picture_init(m_pPicOut);
m_pPicIn->img.i_csp = X264_CSP_I420;
m_pPicIn->img.i_plane = 3;
_pPicIn = new x264_picture_t;
_pPicOut = new x264_picture_t;
x264_picture_init(_pPicIn);
x264_picture_init(_pPicOut);
_pPicIn->img.i_csp = X264_CSP_I420;
_pPicIn->img.i_plane = 3;
return true;
}
int H264Encoder::inputData(char* apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame** ppFrame) {
//TimeTicker1(5);
m_pPicIn->img.i_stride[0] = aiYuvLen[0];
m_pPicIn->img.i_stride[1] = aiYuvLen[1];
m_pPicIn->img.i_stride[2] = aiYuvLen[2];
m_pPicIn->img.plane[0] = (uint8_t *) apcYuv[0];
m_pPicIn->img.plane[1] = (uint8_t *) apcYuv[1];
m_pPicIn->img.plane[2] = (uint8_t *) apcYuv[2];
m_pPicIn->i_pts = i64Pts;
_pPicIn->img.i_stride[0] = aiYuvLen[0];
_pPicIn->img.i_stride[1] = aiYuvLen[1];
_pPicIn->img.i_stride[2] = aiYuvLen[2];
_pPicIn->img.plane[0] = (uint8_t *) apcYuv[0];
_pPicIn->img.plane[1] = (uint8_t *) apcYuv[1];
_pPicIn->img.plane[2] = (uint8_t *) apcYuv[2];
_pPicIn->i_pts = i64Pts;
int iNal;
x264_nal_t* pNals;
int iResult = x264_encoder_encode(m_pX264Handle, &pNals, &iNal, m_pPicIn,
m_pPicOut);
int iResult = x264_encoder_encode(_pX264Handle, &pNals, &iNal, _pPicIn,
_pPicOut);
if (iResult <= 0) {
return 0;
}
for (int i = 0; i < iNal; i++) {
x264_nal_t pNal = pNals[i];
m_aFrames[i].iType = pNal.i_type;
m_aFrames[i].iLength = pNal.i_payload;
m_aFrames[i].pucData = pNal.p_payload;
_aFrames[i].iType = pNal.i_type;
_aFrames[i].iLength = pNal.i_payload;
_aFrames[i].pucData = pNal.p_payload;
}
*ppFrame = m_aFrames;
*ppFrame = _aFrames;
return iNal;
}

View File

@ -54,10 +54,10 @@ public:
bool init(int iWidth, int iHeight, int iFps);
int inputData(char *apcYuv[3], int aiYuvLen[3], int64_t i64Pts, H264Frame **ppFrame);
private:
x264_t* m_pX264Handle = nullptr;
x264_picture_t* m_pPicIn = nullptr;
x264_picture_t* m_pPicOut = nullptr;
H264Frame m_aFrames[10];
x264_t* _pX264Handle = nullptr;
x264_picture_t* _pPicIn = nullptr;
x264_picture_t* _pPicOut = nullptr;
H264Frame _aFrames[10];
};
} /* namespace Codec */

View File

@ -77,16 +77,16 @@ MediaSource::Ptr MediaSource::find(
bool MediaSource::regist() {
//注册该源,注册后服务器才能找到该源
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
auto pr = g_mapMediaSrc[m_strSchema][m_strVhost][m_strApp].emplace(m_strId,shared_from_this());
auto pr = g_mapMediaSrc[_strSchema][_strVhost][_strApp].emplace(_strId,shared_from_this());
auto success = pr.second;
if(success){
InfoL << m_strSchema << " " << m_strVhost << " " << m_strApp << " " << m_strId;
InfoL << _strSchema << " " << _strVhost << " " << _strApp << " " << _strId;
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaChanged,
true,
m_strSchema,
m_strVhost,
m_strApp,
m_strId,
_strSchema,
_strVhost,
_strApp,
_strId,
*this);
}
return success;
@ -94,7 +94,7 @@ bool MediaSource::regist() {
bool MediaSource::unregist() {
//反注册该源
lock_guard<recursive_mutex> lock(g_mtxMediaSrc);
return searchMedia(m_strSchema, m_strVhost, m_strApp, m_strId, [&](SchemaVhostAppStreamMap::iterator &it0 ,
return searchMedia(_strSchema, _strVhost, _strApp, _strId, [&](SchemaVhostAppStreamMap::iterator &it0 ,
VhostAppStreamMap::iterator &it1,
AppStreamMap::iterator &it2,
StreamMap::iterator &it3){
@ -110,13 +110,13 @@ bool MediaSource::unregist() {
});
}
void MediaSource::unregisted(){
InfoL << "" << m_strSchema << " " << m_strVhost << " " << m_strApp << " " << m_strId;
InfoL << "" << _strSchema << " " << _strVhost << " " << _strApp << " " << _strId;
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaChanged,
false,
m_strSchema,
m_strVhost,
m_strApp,
m_strId,
_strSchema,
_strVhost,
_strApp,
_strId,
*this);
}
@ -124,7 +124,7 @@ void MediaInfo::parse(const string &url){
//string url = "rtsp://127.0.0.1:8554/live/id?key=val&a=1&&b=2&vhost=vhost.com";
auto schema_pos = url.find("://");
if(schema_pos != string::npos){
m_schema = url.substr(0,schema_pos);
_schema = url.substr(0,schema_pos);
}else{
schema_pos = -3;
}
@ -133,14 +133,14 @@ void MediaInfo::parse(const string &url){
auto vhost = split_vec[0];
auto pos = vhost.find(":");
if(pos != string::npos){
m_host = m_vhost = vhost.substr(0,pos);
m_port = vhost.substr(pos + 1);
_host = _vhost = vhost.substr(0,pos);
_port = vhost.substr(pos + 1);
} else{
m_host = m_vhost = vhost;
_host = _vhost = vhost;
}
}
if(split_vec.size() > 1){
m_app = split_vec[1];
_app = split_vec[1];
}
if(split_vec.size() > 2){
string steamid;
@ -152,23 +152,23 @@ void MediaInfo::parse(const string &url){
}
auto pos = steamid.find("?");
if(pos != string::npos){
m_streamid = steamid.substr(0,pos);
m_param_strs = steamid.substr(pos + 1);
m_params = Parser::parseArgs(m_param_strs);
if(m_params.find(VHOST_KEY) != m_params.end()){
m_vhost = m_params[VHOST_KEY];
_streamid = steamid.substr(0,pos);
_para_strs = steamid.substr(pos + 1);
_params = Parser::parseArgs(_para_strs);
if(_params.find(VHOST_KEY) != _params.end()){
_vhost = _params[VHOST_KEY];
}
} else{
m_streamid = steamid;
_streamid = steamid;
}
}
if(m_vhost.empty()){
if(_vhost.empty()){
//无效vhost
m_vhost = DEFAULT_VHOST;
_vhost = DEFAULT_VHOST;
}else{
if(INADDR_NONE != inet_addr(m_vhost.data())){
if(INADDR_NONE != inet_addr(_vhost.data())){
//这是ip,未指定vhost;使用默认vhost
m_vhost = DEFAULT_VHOST;
_vhost = DEFAULT_VHOST;
}
}
}

View File

@ -77,17 +77,17 @@ public:
void parse(const string &url);
string &operator[](const string &key){
return m_params[key];
return _params[key];
}
public:
string m_schema;
string m_host;
string m_port;
string m_vhost;
string m_app;
string m_streamid;
StrCaseMap m_params;
string m_param_strs;
string _schema;
string _host;
string _port;
string _vhost;
string _app;
string _streamid;
StrCaseMap _params;
string _para_strs;
};
@ -104,13 +104,13 @@ public:
const string &strVhost,
const string &strApp,
const string &strId) :
m_strSchema(strSchema),
m_strApp(strApp),
m_strId(strId) {
_strSchema(strSchema),
_strApp(strApp),
_strId(strId) {
if(strVhost.empty()){
m_strVhost = DEFAULT_VHOST;
_strVhost = DEFAULT_VHOST;
}else{
m_strVhost = strVhost;
_strVhost = strVhost;
}
}
virtual ~MediaSource() {
@ -124,21 +124,21 @@ public:
bool bMake = true) ;
const string& getSchema() const {
return m_strSchema;
return _strSchema;
}
const string& getVhost() const {
return m_strVhost;
return _strVhost;
}
const string& getApp() const {
//获取该源的id
return m_strApp;
return _strApp;
}
const string& getId() const {
return m_strId;
return _strId;
}
bool seekTo(uint32_t ui32Stamp) {
auto listener = m_listener.lock();
auto listener = _listener.lock();
if(!listener){
return false;
}
@ -146,21 +146,21 @@ public:
}
uint32_t getStamp() {
auto listener = m_listener.lock();
auto listener = _listener.lock();
if(!listener){
return 0;
}
return listener->getStamp();
}
bool shutDown() {
auto listener = m_listener.lock();
auto listener = _listener.lock();
if(!listener){
return false;
}
return listener->shutDown();
}
void setListener(const std::weak_ptr<MediaSourceEvent> &listener){
m_listener = listener;
_listener = listener;
}
template <typename FUN>
@ -224,12 +224,12 @@ private:
void unregisted();
protected:
std::weak_ptr<MediaSourceEvent> m_listener;
std::weak_ptr<MediaSourceEvent> _listener;
private:
string m_strSchema;//协议类型
string m_strVhost; //vhost
string m_strApp; //媒体app
string m_strId; //媒体id
string _strSchema;//协议类型
string _strVhost; //vhost
string _strApp; //媒体app
string _strId; //媒体id
static SchemaVhostAppStreamMap g_mapMediaSrc; //静态的媒体源表
static recursive_mutex g_mtxMediaSrc; //访问静态的媒体源表的互斥锁
};

View File

@ -44,19 +44,19 @@ DevChannel::DevChannel(const char *strVhost,
bool bEnableMp4 ) :
RtspToRtmpMediaSource(strVhost,strApp,strId,bEanbleHls,bEnableMp4) {
m_strSdp = "v=0\r\n";
m_strSdp += "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n";
m_strSdp += "s=RTSP Session, streamed by the ZL\r\n";
m_strSdp += "i=ZL Live Stream\r\n";
m_strSdp += "c=IN IP4 0.0.0.0\r\n";
m_strSdp += "t=0 0\r\n";
_strSdp = "v=0\r\n";
_strSdp += "o=- 1383190487994921 1 IN IP4 0.0.0.0\r\n";
_strSdp += "s=RTSP Session, streamed by the ZL\r\n";
_strSdp += "i=ZL Live Stream\r\n";
_strSdp += "c=IN IP4 0.0.0.0\r\n";
_strSdp += "t=0 0\r\n";
//直播,时间长度永远
if(fDuration <= 0){
m_strSdp += "a=range:npt=0-\r\n";
_strSdp += "a=range:npt=0-\r\n";
}else{
m_strSdp += StrPrinter <<"a=range:npt=0-" << fDuration << "\r\n" << endl;
_strSdp += StrPrinter <<"a=range:npt=0-" << fDuration << "\r\n" << endl;
}
m_strSdp += "a=control:*\r\n";
_strSdp += "a=control:*\r\n";
}
DevChannel::~DevChannel() {
}
@ -64,16 +64,16 @@ DevChannel::~DevChannel() {
#ifdef ENABLE_X264
void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) {
//TimeTicker1(50);
if (!m_pH264Enc) {
m_pH264Enc.reset(new H264Encoder());
if (!m_pH264Enc->init(m_video->iWidth, m_video->iHeight, m_video->iFrameRate)) {
m_pH264Enc.reset();
if (!_pH264Enc) {
_pH264Enc.reset(new H264Encoder());
if (!_pH264Enc->init(_video->iWidth, _video->iHeight, _video->iFrameRate)) {
_pH264Enc.reset();
WarnL << "H264Encoder init failed!";
}
}
if (m_pH264Enc) {
if (_pH264Enc) {
H264Encoder::H264Frame *pOut;
int iFrames = m_pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut);
int iFrames = _pH264Enc->inputData(apcYuv, aiYuvLen, uiStamp, &pOut);
for (int i = 0; i < iFrames; i++) {
inputH264((char *) pOut[i].pucData, pOut[i].iLength, uiStamp);
}
@ -83,16 +83,16 @@ void DevChannel::inputYUV(char* apcYuv[3], int aiYuvLen[3], uint32_t uiStamp) {
#ifdef ENABLE_FAAC
void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
if (!m_pAacEnc) {
m_pAacEnc.reset(new AACEncoder());
if (!m_pAacEnc->init(m_audio->iSampleRate, m_audio->iChannel, m_audio->iSampleBit)) {
m_pAacEnc.reset();
if (!_pAacEnc) {
_pAacEnc.reset(new AACEncoder());
if (!_pAacEnc->init(_audio->iSampleRate, _audio->iChannel, _audio->iSampleBit)) {
_pAacEnc.reset();
WarnL << "AACEncoder init failed!";
}
}
if (m_pAacEnc) {
if (_pAacEnc) {
unsigned char *pucOut;
int iRet = m_pAacEnc->inputData(pcData, iDataLen, &pucOut);
int iRet = _pAacEnc->inputData(pcData, iDataLen, &pucOut);
if (iRet > 0) {
inputAAC((char *) pucOut, iRet, uiStamp);
}
@ -101,16 +101,16 @@ void DevChannel::inputPCM(char* pcData, int iDataLen, uint32_t uiStamp) {
#endif //ENABLE_FAAC
void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t uiStamp) {
if (!m_pRtpMaker_h264) {
if (!_pRtpMaker_h264) {
uint32_t ui32Ssrc;
memcpy(&ui32Ssrc, makeRandStr(4, false).data(), 4);
auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
onGetRTP(pkt,bKeyPos);
};
GET_CONFIG_AND_REGISTER(uint32_t,videoMtu,Config::Rtp::kVideoMtuSize);
m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu));
_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu));
}
if (!m_bSdp_gotH264 && m_video) {
if (!_bSdp_gotH264 && _video) {
makeSDP_264((unsigned char*) pcData, iDataLen);
}
int iOffset = 4;
@ -118,38 +118,38 @@ void DevChannel::inputH264(const char* pcData, int iDataLen, uint32_t uiStamp) {
iOffset = 3;
}
if(uiStamp == 0){
uiStamp = (uint32_t)m_aTicker[0].elapsedTime();
uiStamp = (uint32_t)_aTicker[0].elapsedTime();
}
m_pRtpMaker_h264->makeRtp(pcData + iOffset, iDataLen - iOffset, uiStamp);
_pRtpMaker_h264->makeRtp(pcData + iOffset, iDataLen - iOffset, uiStamp);
}
void DevChannel::inputAAC(const char* pcData, int iDataLen, uint32_t uiStamp,bool withAdtsHeader) {
if(withAdtsHeader){
inputAAC(pcData+7,iDataLen-7,uiStamp,pcData);
} else if(m_pAdtsHeader){
m_pAdtsHeader->aac_frame_length = iDataLen;
writeAdtsHeader(*m_pAdtsHeader,(uint8_t *)m_pAdtsHeader->buffer);
inputAAC(pcData,iDataLen,uiStamp,(const char *)m_pAdtsHeader->buffer);
} else if(_pAdtsHeader){
_pAdtsHeader->aac_frame_length = iDataLen;
writeAdtsHeader(*_pAdtsHeader,(uint8_t *)_pAdtsHeader->buffer);
inputAAC(pcData,iDataLen,uiStamp,(const char *)_pAdtsHeader->buffer);
}
}
void DevChannel::inputAAC(const char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,const char *pcAdtsHeader){
if (!m_pRtpMaker_aac) {
if (!_pRtpMaker_aac) {
uint32_t ssrc;
memcpy(&ssrc, makeRandStr(8, false).data() + 4, 4);
auto lam = [this](const RtpPacket::Ptr &pkt, bool keyPos) {
onGetRTP(pkt,keyPos);
};
GET_CONFIG_AND_REGISTER(uint32_t,audioMtu,Config::Rtp::kAudioMtuSize);
m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,m_audio->iSampleRate));
_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,_audio->iSampleRate));
}
if (!m_bSdp_gotAAC && m_audio && pcAdtsHeader) {
if (!_bSdp_gotAAC && _audio && pcAdtsHeader) {
makeSDP_AAC((unsigned char*) pcAdtsHeader);
}
if(uiStamp == 0){
uiStamp = (uint32_t)m_aTicker[1].elapsedTime();
uiStamp = (uint32_t)_aTicker[1].elapsedTime();
}
if(pcDataWithoutAdts && iDataLen){
m_pRtpMaker_aac->makeRtp(pcDataWithoutAdts, iDataLen, uiStamp);
_pRtpMaker_aac->makeRtp(pcDataWithoutAdts, iDataLen, uiStamp);
}
}
@ -161,77 +161,77 @@ inline void DevChannel::makeSDP_264(unsigned char *pcData, int iDataLen) {
switch (pcData[offset] & 0x1F) {
case 7:/*SPS frame*/
{
if (m_uiSPSLen != 0) {
if (_uiSPSLen != 0) {
break;
}
memcpy(m_aucSPS, pcData + offset, iDataLen - offset);
m_uiSPSLen = iDataLen - offset;
memcpy(_aucSPS, pcData + offset, iDataLen - offset);
_uiSPSLen = iDataLen - offset;
}
break;
case 8:/*PPS frame*/
{
if (m_uiPPSLen != 0) {
if (_uiPPSLen != 0) {
break;
}
memcpy(m_aucPPS, pcData + offset, iDataLen - offset);
m_uiPPSLen = iDataLen - offset;
memcpy(_aucPPS, pcData + offset, iDataLen - offset);
_uiPPSLen = iDataLen - offset;
}
break;
default:
break;
}
if (!m_uiSPSLen || !m_uiPPSLen) {
if (!_uiSPSLen || !_uiPPSLen) {
return;
}
char acTmp[256];
int profile_level_id = 0;
if (m_uiSPSLen >= 4) { // sanity check
profile_level_id = (m_aucSPS[1] << 16) | (m_aucSPS[2] << 8) | m_aucSPS[3]; // profile_idc|constraint_setN_flag|level_idc
if (_uiSPSLen >= 4) { // sanity check
profile_level_id = (_aucSPS[1] << 16) | (_aucSPS[2] << 8) | _aucSPS[3]; // profile_idc|constraint_setN_flag|level_idc
}
//视频通道
m_strSdp += StrPrinter << "m=video 0 RTP/AVP "
<< m_pRtpMaker_h264->getPlayloadType() << "\r\n" << endl;
m_strSdp += "b=AS:5100\r\n";
m_strSdp += StrPrinter << "a=rtpmap:" << m_pRtpMaker_h264->getPlayloadType()
<< " H264/" << m_pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
m_strSdp += StrPrinter << "a=fmtp:" << m_pRtpMaker_h264->getPlayloadType()
_strSdp += StrPrinter << "m=video 0 RTP/AVP "
<< _pRtpMaker_h264->getPlayloadType() << "\r\n" << endl;
_strSdp += "b=AS:5100\r\n";
_strSdp += StrPrinter << "a=rtpmap:" << _pRtpMaker_h264->getPlayloadType()
<< " H264/" << _pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
_strSdp += StrPrinter << "a=fmtp:" << _pRtpMaker_h264->getPlayloadType()
<< " packetization-mode=1;profile-level-id=" << endl;
memset(acTmp, 0, sizeof(acTmp));
sprintf(acTmp, "%06X", profile_level_id);
m_strSdp += acTmp;
m_strSdp += ";sprop-parameter-sets=";
_strSdp += acTmp;
_strSdp += ";sprop-parameter-sets=";
memset(acTmp, 0, sizeof(acTmp));
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) m_aucSPS, m_uiSPSLen);
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) _aucSPS, _uiSPSLen);
//WarnL<<"SPS base64:"<<strTemp;
//WarnL<<"SPS hexdump:"<<hexdump(SPS_BUF, SPS_LEN);
m_strSdp += acTmp;
m_strSdp += ",";
_strSdp += acTmp;
_strSdp += ",";
memset(acTmp, 0, sizeof(acTmp));
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) m_aucPPS, m_uiPPSLen);
m_strSdp += acTmp;
m_strSdp += "\r\n";
if (m_video->iFrameRate > 0 && m_video->iHeight > 0 && m_video->iWidth > 0) {
m_strSdp += "a=framerate:";
m_strSdp += StrPrinter << m_video->iFrameRate << endl;
m_strSdp += StrPrinter << "\r\na=framesize:"
<< m_pRtpMaker_h264->getPlayloadType() << " " << endl;
m_strSdp += StrPrinter << m_video->iWidth << endl;
m_strSdp += "-";
m_strSdp += StrPrinter << m_video->iHeight << endl;
m_strSdp += "\r\n";
av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) _aucPPS, _uiPPSLen);
_strSdp += acTmp;
_strSdp += "\r\n";
if (_video->iFrameRate > 0 && _video->iHeight > 0 && _video->iWidth > 0) {
_strSdp += "a=framerate:";
_strSdp += StrPrinter << _video->iFrameRate << endl;
_strSdp += StrPrinter << "\r\na=framesize:"
<< _pRtpMaker_h264->getPlayloadType() << " " << endl;
_strSdp += StrPrinter << _video->iWidth << endl;
_strSdp += "-";
_strSdp += StrPrinter << _video->iHeight << endl;
_strSdp += "\r\n";
}
m_strSdp += StrPrinter << "a=control:trackID="
<< m_pRtpMaker_h264->getInterleaved() / 2 << "\r\n" << endl;
m_bSdp_gotH264 = true;
if (m_audio) {
if (m_bSdp_gotAAC) {
makeSDP(m_strSdp);
_strSdp += StrPrinter << "a=control:trackID="
<< _pRtpMaker_h264->getInterleaved() / 2 << "\r\n" << endl;
_bSdp_gotH264 = true;
if (_audio) {
if (_bSdp_gotAAC) {
makeSDP(_strSdp);
}
} else {
makeSDP(m_strSdp);
makeSDP(_strSdp);
}
}
@ -244,27 +244,27 @@ inline void DevChannel::makeSDP_AAC(unsigned char *fixedHeader) {
char fConfigStr[5] = { 0 };
sprintf(fConfigStr, "%02X%02x", (uint8_t)audioSpecificConfig[0],(uint8_t)audioSpecificConfig[1]);
m_strSdp += StrPrinter << "m=audio 0 RTP/AVP "
<< m_pRtpMaker_aac->getPlayloadType() << "\r\n" << endl;
m_strSdp += "b=AS:96\r\n";
m_strSdp += StrPrinter << "a=rtpmap:" << m_pRtpMaker_aac->getPlayloadType()
<< " MPEG4-GENERIC/" << m_pRtpMaker_aac->getSampleRate() << "\r\n"
_strSdp += StrPrinter << "m=audio 0 RTP/AVP "
<< _pRtpMaker_aac->getPlayloadType() << "\r\n" << endl;
_strSdp += "b=AS:96\r\n";
_strSdp += StrPrinter << "a=rtpmap:" << _pRtpMaker_aac->getPlayloadType()
<< " MPEG4-GENERIC/" << _pRtpMaker_aac->getSampleRate() << "\r\n"
<< endl;
m_strSdp += StrPrinter << "a=fmtp:" << m_pRtpMaker_aac->getPlayloadType()
_strSdp += StrPrinter << "a=fmtp:" << _pRtpMaker_aac->getPlayloadType()
<< " streamtype=5;profile-level-id=1;mode=AAC-hbr;sizelength=13;indexlength=3;indexdeltalength=3;config="
<< endl;
m_strSdp += fConfigStr;
m_strSdp += "\r\n";
m_strSdp += StrPrinter << "a=control:trackID="
<< m_pRtpMaker_aac->getInterleaved() / 2 << "\r\n" << endl;
_strSdp += fConfigStr;
_strSdp += "\r\n";
_strSdp += StrPrinter << "a=control:trackID="
<< _pRtpMaker_aac->getInterleaved() / 2 << "\r\n" << endl;
m_bSdp_gotAAC = true;
if (m_video) {
if (m_bSdp_gotH264) {
makeSDP(m_strSdp);
_bSdp_gotAAC = true;
if (_video) {
if (_bSdp_gotH264) {
makeSDP(_strSdp);
}
} else {
makeSDP(m_strSdp);
makeSDP(_strSdp);
}
}
@ -273,35 +273,35 @@ void DevChannel::makeSDP(const string& strSdp) {
}
void DevChannel::initVideo(const VideoInfo& info) {
m_video.reset(new VideoInfo(info));
_video.reset(new VideoInfo(info));
}
void DevChannel::initAudio(const AudioInfo& info) {
m_audio.reset(new AudioInfo(info));
m_pAdtsHeader = std::make_shared<AACFrame>();
_audio.reset(new AudioInfo(info));
_pAdtsHeader = std::make_shared<AACFrame>();
m_pAdtsHeader->syncword = 0x0FFF;
m_pAdtsHeader->id = 0;
m_pAdtsHeader->layer = 0;
m_pAdtsHeader->protection_absent = 1;
m_pAdtsHeader->profile = info.iProfile;//audioObjectType - 1;
_pAdtsHeader->syncword = 0x0FFF;
_pAdtsHeader->id = 0;
_pAdtsHeader->layer = 0;
_pAdtsHeader->protection_absent = 1;
_pAdtsHeader->profile = info.iProfile;//audioObjectType - 1;
int i = 0;
for(auto rate : samplingFrequencyTable){
if(rate == info.iSampleRate){
m_pAdtsHeader->sf_index = i;
_pAdtsHeader->sf_index = i;
};
++i;
}
m_pAdtsHeader->private_bit = 0;
m_pAdtsHeader->channel_configuration = info.iChannel;
m_pAdtsHeader->original = 0;
m_pAdtsHeader->home = 0;
m_pAdtsHeader->copyright_identification_bit = 0;
m_pAdtsHeader->copyright_identification_start = 0;
m_pAdtsHeader->aac_frame_length = 7;
m_pAdtsHeader->adts_buffer_fullness = 2047;
m_pAdtsHeader->no_raw_data_blocks_in_frame = 0;
_pAdtsHeader->private_bit = 0;
_pAdtsHeader->channel_configuration = info.iChannel;
_pAdtsHeader->original = 0;
_pAdtsHeader->home = 0;
_pAdtsHeader->copyright_identification_bit = 0;
_pAdtsHeader->copyright_identification_start = 0;
_pAdtsHeader->aac_frame_length = 7;
_pAdtsHeader->adts_buffer_fullness = 2047;
_pAdtsHeader->no_raw_data_blocks_in_frame = 0;
}
} /* namespace DEV */

View File

@ -102,25 +102,25 @@ private:
inline void makeSDP_AAC(unsigned char *pucData);
inline void makeSDP(const string& strSdp);
#ifdef ENABLE_X264
std::shared_ptr<H264Encoder> m_pH264Enc;
std::shared_ptr<H264Encoder> _pH264Enc;
#endif //ENABLE_X264
#ifdef ENABLE_FAAC
std::shared_ptr<AACEncoder> m_pAacEnc;
std::shared_ptr<AACEncoder> _pAacEnc;
#endif //ENABLE_FAAC
RtpMaker_AAC::Ptr m_pRtpMaker_aac;
RtpMaker_H264::Ptr m_pRtpMaker_h264;
bool m_bSdp_gotH264 = false;
bool m_bSdp_gotAAC = false;
RtpMaker_AAC::Ptr _pRtpMaker_aac;
RtpMaker_H264::Ptr _pRtpMaker_h264;
bool _bSdp_gotH264 = false;
bool _bSdp_gotAAC = false;
unsigned char m_aucSPS[256];
unsigned int m_uiSPSLen = 0;
unsigned char m_aucPPS[256];
unsigned int m_uiPPSLen = 0;
std::shared_ptr<VideoInfo> m_video;
std::shared_ptr<AudioInfo> m_audio;
SmoothTicker m_aTicker[2];
std::shared_ptr<AACFrame> m_pAdtsHeader;
unsigned char _aucSPS[256];
unsigned int _uiSPSLen = 0;
unsigned char _aucPPS[256];
unsigned int _uiPPSLen = 0;
std::shared_ptr<VideoInfo> _video;
std::shared_ptr<AudioInfo> _audio;
SmoothTicker _aTicker[2];
std::shared_ptr<AACFrame> _pAdtsHeader;
};

View File

@ -74,12 +74,12 @@ PlayerProxy::PlayerProxy(const char *strVhost,
bool bEnableHls,
bool bEnableMp4,
int iRetryCount){
m_strVhost = strVhost;
m_strApp = strApp;
m_strSrc = strSrc;
m_bEnableHls = bEnableHls;
m_bEnableMp4 = bEnableMp4;
m_iRetryCount = iRetryCount;
_strVhost = strVhost;
_strApp = strApp;
_strSrc = strSrc;
_bEnableHls = bEnableHls;
_bEnableMp4 = bEnableMp4;
_iRetryCount = iRetryCount;
}
void PlayerProxy::play(const char* strUrl) {
weak_ptr<PlayerProxy> weakSelf = shared_from_this();
@ -90,9 +90,9 @@ void PlayerProxy::play(const char* strUrl) {
// if(!strongSelf){
// return;
// }
// if(strongSelf->m_pChn){
// strongSelf->m_pChn->inputH264((char *)data.data(), data.size(), data.timeStamp);
// if(!strongSelf->m_haveAudio){
// if(strongSelf->_pChn){
// strongSelf->_pChn->inputH264((char *)data.data(), data.size(), data.timeStamp);
// if(!strongSelf->_haveAudio){
// strongSelf->makeMuteAudio(data.timeStamp);
// }
// }else{
@ -104,8 +104,8 @@ void PlayerProxy::play(const char* strUrl) {
// if(!strongSelf){
// return;
// }
// if(strongSelf->m_pChn){
// strongSelf->m_pChn->inputAAC((char *)data.data(), data.size(), data.timeStamp);
// if(strongSelf->_pChn){
// strongSelf->_pChn->inputAAC((char *)data.data(), data.size(), data.timeStamp);
// }else{
// strongSelf->initMedia();
// }
@ -121,7 +121,7 @@ void PlayerProxy::play(const char* strUrl) {
if(!err) {
// 播放成功
*piFailedCnt = 0;//连续播放失败次数清0
}else if(*piFailedCnt < strongSelf->m_iRetryCount || strongSelf->m_iRetryCount < 0) {
}else if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) {
// 播放失败,延时重试播放
strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
}
@ -131,11 +131,11 @@ void PlayerProxy::play(const char* strUrl) {
if(!strongSelf) {
return;
}
if(strongSelf->m_pChn) {
strongSelf->m_pChn.reset();
if(strongSelf->_pChn) {
strongSelf->_pChn.reset();
}
//播放异常中断,延时重试播放
if(*piFailedCnt < strongSelf->m_iRetryCount || strongSelf->m_iRetryCount < 0) {
if(*piFailedCnt < strongSelf->_iRetryCount || strongSelf->_iRetryCount < 0) {
strongSelf->rePlay(strUrlTmp,(*piFailedCnt)++);
}
});
@ -166,8 +166,8 @@ void PlayerProxy::initMedia() {
if (!isInited()) {
return;
}
m_pChn.reset(new DevChannel(m_strVhost.data(),m_strApp.data(),m_strSrc.data(),getDuration(),m_bEnableHls,m_bEnableMp4));
m_pChn->setListener(shared_from_this());
_pChn.reset(new DevChannel(_strVhost.data(),_strApp.data(),_strSrc.data(),getDuration(),_bEnableHls,_bEnableMp4));
_pChn->setListener(shared_from_this());
//todo(xzl) 修复此处
@ -176,22 +176,22 @@ void PlayerProxy::initMedia() {
// info.iFrameRate = getVideoFps();
// info.iWidth = getVideoWidth();
// info.iHeight = getVideoHeight();
// m_pChn->initVideo(info);
// _pChn->initVideo(info);
// }
//
// m_haveAudio = containAudio();
// _haveAudio = containAudio();
// if (containAudio()) {
// AudioInfo info;
// info.iSampleRate = getAudioSampleRate();
// info.iChannel = getAudioChannel();
// info.iSampleBit = getAudioSampleBit();
// m_pChn->initAudio(info);
// _pChn->initAudio(info);
// }else{
// AudioInfo info;
// info.iSampleRate = MUTE_ADTS_SAMPLE_RATE;
// info.iChannel = MUTE_ADTS_CHN_CNT;
// info.iSampleBit = MUTE_ADTS_SAMPLE_BIT;
// m_pChn->initAudio(info);
// _pChn->initAudio(info);
// }
}
bool PlayerProxy::shutDown() {
@ -202,7 +202,7 @@ bool PlayerProxy::shutDown() {
executor->async_first([weakSlef]() {
auto stronSelf = weakSlef.lock();
if (stronSelf) {
stronSelf->m_pChn.reset();
stronSelf->_pChn.reset();
stronSelf->teardown();
}
});
@ -212,10 +212,10 @@ bool PlayerProxy::shutDown() {
void PlayerProxy::makeMuteAudio(uint32_t stamp) {
auto iAudioIndex = stamp / MUTE_ADTS_DATA_MS;
if(m_iAudioIndex != iAudioIndex){
m_iAudioIndex = iAudioIndex;
m_pChn->inputAAC((char *)MUTE_ADTS_DATA,MUTE_ADTS_DATA_LEN, m_iAudioIndex * MUTE_ADTS_DATA_MS);
//DebugL << m_iAudioIndex * MUTE_ADTS_DATA_MS << " " << stamp;
if(_iAudioIndex != iAudioIndex){
_iAudioIndex = iAudioIndex;
_pChn->inputAAC((char *)MUTE_ADTS_DATA,MUTE_ADTS_DATA_LEN, _iAudioIndex * MUTE_ADTS_DATA_MS);
//DebugL << _iAudioIndex * MUTE_ADTS_DATA_MS << " " << stamp;
}
}

View File

@ -60,15 +60,15 @@ private:
void rePlay(const string &strUrl,int iFailedCnt);
void makeMuteAudio(uint32_t stamp);
private:
bool m_bEnableHls;
bool m_bEnableMp4;
int m_iRetryCount;
DevChannel::Ptr m_pChn;
string m_strVhost;
string m_strApp;
string m_strSrc;
bool m_haveAudio = false;
int m_iAudioIndex = 0;
bool _bEnableHls;
bool _bEnableMp4;
int _iRetryCount;
DevChannel::Ptr _pChn;
string _strVhost;
string _strApp;
string _strSrc;
bool _haveAudio = false;
int _iAudioIndex = 0;
};
} /* namespace Player */

View File

@ -37,19 +37,19 @@ H264Parser::~H264Parser(){
}
void H264Parser::inputH264(const string &h264,uint32_t dts){
m_parser.SetStream((const uint8_t *)h264.data(), h264.size());
_parser.SetStream((const uint8_t *)h264.data(), h264.size());
while (true) {
if(media::H264Parser::kOk != m_parser.AdvanceToNextNALU(&m_nalu)){
if(media::H264Parser::kOk != _parser.AdvanceToNextNALU(&_nalu)){
break;
}
switch (m_nalu.nal_unit_type) {
switch (_nalu.nal_unit_type) {
case media::H264NALU::kNonIDRSlice:
case media::H264NALU::kIDRSlice:{
if(media::H264Parser::kOk == m_parser.ParseSliceHeader(m_nalu, &m_shdr)){
const media::H264SPS *pPps = m_parser.GetSPS(m_shdr.pic_parameter_set_id);
if(media::H264Parser::kOk == _parser.ParseSliceHeader(_nalu, &_shdr)){
const media::H264SPS *pPps = _parser.GetSPS(_shdr.pic_parameter_set_id);
if (pPps) {
m_poc.ComputePicOrderCnt(pPps, m_shdr, &m_iNowPOC);
_poc.ComputePicOrderCnt(pPps, _shdr, &_iNowPOC);
computePts(dts);
}
}
@ -57,12 +57,12 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
break;
case media::H264NALU::kSPS:{
int sps_id;
m_parser.ParseSPS(&sps_id);
_parser.ParseSPS(&sps_id);
}
break;
case media::H264NALU::kPPS:{
int pps_id;
m_parser.ParsePPS(&pps_id);
_parser.ParsePPS(&pps_id);
}
break;
default:
@ -72,33 +72,33 @@ void H264Parser::inputH264(const string &h264,uint32_t dts){
}
void H264Parser::computePts(uint32_t iNowDTS) {
auto iPOCInc = m_iNowPOC - m_iLastPOC;
if (m_shdr.slice_type % 5 == 1) {
auto iPOCInc = _iNowPOC - _iLastPOC;
if (_shdr.slice_type % 5 == 1) {
//这是B帧
m_iNowPTS = m_iLastPTS + m_iMsPerPOC * (iPOCInc);
_iNowPTS = _iLastPTS + _iMsPerPOC * (iPOCInc);
} else {
//这是I帧或者P帧
m_iNowPTS = iNowDTS;
_iNowPTS = iNowDTS;
//计算每一POC的时间
if(iPOCInc == 0){
WarnL << "iPOCInc = 0," << m_iNowPOC << " " << m_iLastPOC;
WarnL << "iPOCInc = 0," << _iNowPOC << " " << _iLastPOC;
}else{
m_iMsPerPOC = (m_iNowPTS - m_iLastPTS) / iPOCInc;
_iMsPerPOC = (_iNowPTS - _iLastPTS) / iPOCInc;
}
m_iLastPTS = m_iNowPTS;
m_iLastPOC = m_iNowPOC;
_iLastPTS = _iNowPTS;
_iLastPOC = _iNowPOC;
}
// DebugL << m_shdr.slice_type
// DebugL << _shdr.slice_type
// <<"\r\nNOW:"
// << m_iNowPOC << " "
// << m_iNowPTS << " "
// << _iNowPOC << " "
// << _iNowPTS << " "
// << iNowDTS << " "
// << "\r\nLST:"
// << m_iLastPOC << " "
// << m_iLastPTS << " "
// << m_iMsPerPOC << endl;
// << _iLastPOC << " "
// << _iLastPTS << " "
// << _iMsPerPOC << endl;
}

View File

@ -44,29 +44,29 @@ public:
void inputH264(const string &h264,uint32_t dts);
int32_t getPOC() const{
return m_iNowPOC;
return _iNowPOC;
}
int getSliceType() const{
return m_shdr.slice_type;
return _shdr.slice_type;
}
int getNaluType() const{
return m_nalu.nal_unit_type;
return _nalu.nal_unit_type;
}
uint32_t getPts() const{
return m_iNowPTS;
return _iNowPTS;
}
private:
media::H264Parser m_parser;
media::H264POC m_poc;
media::H264NALU m_nalu;
media::H264SliceHeader m_shdr;
media::H264Parser _parser;
media::H264POC _poc;
media::H264NALU _nalu;
media::H264SliceHeader _shdr;
int32_t m_iNowPOC = INT32_MAX;
int32_t m_iLastPOC = INT32_MAX;
int32_t _iNowPOC = INT32_MAX;
int32_t _iLastPOC = INT32_MAX;
uint32_t m_iNowPTS = INT32_MAX;
uint32_t m_iLastPTS = INT32_MAX;
int32_t m_iMsPerPOC = 30;
uint32_t _iNowPTS = INT32_MAX;
uint32_t _iLastPTS = INT32_MAX;
int32_t _iMsPerPOC = 30;
void computePts(uint32_t dts);

View File

@ -110,7 +110,7 @@ HttpSession::HttpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::P
pSock->setSendTimeOutSecond(15);
GET_CONFIG_AND_REGISTER(string,rootPath,Config::Http::kRootPath);
m_strPath = rootPath;
_strPath = rootPath;
}
HttpSession::~HttpSession() {
@ -125,9 +125,9 @@ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
g_mapCmdIndex.emplace("POST",&HttpSession::Handle_Req_POST);
}, nullptr);
m_parser.Parse(header);
urlDecode(m_parser);
string cmd = m_parser.Method();
_parser.Parse(header);
urlDecode(_parser);
string cmd = _parser.Method();
auto it = g_mapCmdIndex.find(cmd);
if (it == g_mapCmdIndex.end()) {
WarnL << cmd;
@ -143,15 +143,15 @@ int64_t HttpSession::onRecvHeader(const char *header,uint64_t len) {
shutdown();
}
//清空解析器节省内存
m_parser.Clear();
_parser.Clear();
//返回content长度
return content_len;
}
void HttpSession::onRecvContent(const char *data,uint64_t len) {
if(m_contentCallBack){
if(!m_contentCallBack(data,len)){
m_contentCallBack = nullptr;
if(_contentCallBack){
if(!_contentCallBack(data,len)){
_contentCallBack = nullptr;
}
}
}
@ -160,7 +160,7 @@ void HttpSession::onRecv(const Buffer::Ptr &pBuf) {
onRecv(pBuf->data(),pBuf->size());
}
void HttpSession::onRecv(const char *data,int size){
m_ticker.resetTime();
_ticker.resetTime();
input(data,size);
}
@ -168,11 +168,11 @@ void HttpSession::onError(const SockException& err) {
//WarnL << err.what();
GET_CONFIG_AND_REGISTER(uint32_t,iFlowThreshold,Broadcast::kFlowThreshold);
if(m_ui64TotalBytes > iFlowThreshold * 1024){
if(_ui64TotalBytes > iFlowThreshold * 1024){
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,
m_mediaInfo,
m_ui64TotalBytes,
m_ticker.createdTime()/1000,
_mediaInfo,
_ui64TotalBytes,
_ticker.createdTime()/1000,
*this);
}
}
@ -180,7 +180,7 @@ void HttpSession::onError(const SockException& err) {
void HttpSession::onManager() {
GET_CONFIG_AND_REGISTER(uint32_t,keepAliveSec,Config::Http::kKeepAliveSecond);
if(m_ticker.elapsedTime() > keepAliveSec * 1000){
if(_ticker.elapsedTime() > keepAliveSec * 1000){
//1分钟超时
WarnL<<"HttpSession timeouted!";
shutdown();
@ -189,7 +189,7 @@ void HttpSession::onManager() {
inline bool HttpSession::checkWebSocket(){
auto Sec_WebSocket_Key = m_parser["Sec-WebSocket-Key"];
auto Sec_WebSocket_Key = _parser["Sec-WebSocket-Key"];
if(Sec_WebSocket_Key.empty()){
return false;
}
@ -205,7 +205,7 @@ inline bool HttpSession::checkWebSocket(){
//http-flv 链接格式:http://vhost-url:port/app/streamid.flv?key1=value1&key2=value2
//如果url(除去?以及后面的参数)后缀是.flv,那么表明该url是一个http-flv直播。
inline bool HttpSession::checkLiveFlvStream(){
auto pos = strrchr(m_parser.Url().data(),'.');
auto pos = strrchr(_parser.Url().data(),'.');
if(!pos){
//未找到".flv"后缀
return false;
@ -215,11 +215,11 @@ inline bool HttpSession::checkLiveFlvStream(){
return false;
}
//拼接成完整url
auto fullUrl = string(HTTP_SCHEMA) + "://" + m_parser["Host"] + m_parser.FullUrl();
m_mediaInfo.parse(fullUrl);
m_mediaInfo.m_streamid.erase(m_mediaInfo.m_streamid.size() - 4);//去除.flv后缀
auto fullUrl = string(HTTP_SCHEMA) + "://" + _parser["Host"] + _parser.FullUrl();
_mediaInfo.parse(fullUrl);
_mediaInfo._streamid.erase(_mediaInfo._streamid.size() - 4);//去除.flv后缀
auto mediaSrc = dynamic_pointer_cast<RtmpMediaSource>(MediaSource::find(RTMP_SCHEMA,m_mediaInfo.m_vhost,m_mediaInfo.m_app,m_mediaInfo.m_streamid));
auto mediaSrc = dynamic_pointer_cast<RtmpMediaSource>(MediaSource::find(RTMP_SCHEMA,_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid));
if(!mediaSrc){
//该rtmp源不存在
return false;
@ -262,7 +262,7 @@ inline bool HttpSession::checkLiveFlvStream(){
onRes(err);
});
};
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed,m_mediaInfo,invoker,*this);
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed,_mediaInfo,invoker,*this);
if(!flag){
//该事件无人监听,默认不鉴权
onRes("");
@ -273,10 +273,10 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
//先看看是否为WebSocket请求
if(checkWebSocket()){
content_len = -1;
auto parserCopy = m_parser;
m_contentCallBack = [this,parserCopy](const char *data,uint64_t len){
auto parserCopy = _parser;
_contentCallBack = [this,parserCopy](const char *data,uint64_t len){
onRecvWebSocketData(parserCopy,data,len);
//m_contentCallBack是可持续的后面还要处理后续数据
//_contentCallBack是可持续的后面还要处理后续数据
return true;
};
return true;
@ -293,19 +293,19 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
}
//事件未被拦截则认为是http下载请求
auto fullUrl = string(HTTP_SCHEMA) + "://" + m_parser["Host"] + m_parser.FullUrl();
m_mediaInfo.parse(fullUrl);
auto fullUrl = string(HTTP_SCHEMA) + "://" + _parser["Host"] + _parser.FullUrl();
_mediaInfo.parse(fullUrl);
string strFile = m_strPath + "/" + m_mediaInfo.m_vhost + m_parser.Url();
string strFile = _strPath + "/" + _mediaInfo._vhost + _parser.Url();
/////////////HTTP连接是否需要被关闭////////////////
GET_CONFIG_AND_REGISTER(uint32_t,reqCnt,Config::Http::kMaxReqCount);
bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) || ( ++m_iReqCnt > reqCnt);
bool bClose = (strcasecmp(_parser["Connection"].data(),"close") == 0) || ( ++_iReqCnt > reqCnt);
//访问的是文件夹
if (strFile.back() == '/') {
//生成文件夹菜单索引
string strMeun;
if (!makeMeun(strFile,m_mediaInfo.m_vhost, strMeun)) {
if (!makeMeun(strFile,_mediaInfo._vhost, strMeun)) {
//文件夹不存在
sendNotFound(bClose);
return !bClose;
@ -334,7 +334,7 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
}
//判断是不是分节下载
auto &strRange = m_parser["Range"];
auto &strRange = _parser["Range"];
int64_t iRangeStart = 0, iRangeEnd = 0;
iRangeStart = atoll(FindField(strRange.data(), "bytes=", "-").data());
iRangeEnd = atoll(FindField(strRange.data(), "-", "\r\n").data());
@ -355,7 +355,7 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
//分节下载返回Content-Range头
httpHeader.emplace("Content-Range",StrPrinter<<"bytes " << iRangeStart << "-" << iRangeEnd << "/" << tFileStat.st_size<< endl);
}
auto Origin = m_parser["Origin"];
auto Origin = _parser["Origin"];
if(!Origin.empty()){
httpHeader["Access-Control-Allow-Origin"] = Origin;
httpHeader["Access-Control-Allow-Credentials"] = "true";
@ -377,7 +377,7 @@ inline bool HttpSession::Handle_Req_GET(int64_t &content_len) {
auto strongSelf = weakSelf.lock();
while(*piLeft && strongSelf){
//更新超时定时器
strongSelf->m_ticker.resetTime();
strongSelf->_ticker.resetTime();
//从循环池获取一个内存片
auto sendBuf = strongSelf->obtainBuffer();
sendBuf->setCapacity(sendBufSize);
@ -449,7 +449,7 @@ inline bool HttpSession::makeMeun(const string &strFullPath,const string &vhost,
"<h1>文件索引:";
string strPath = strFullPath;
strPath = strPath.substr(m_strPath.length() + vhost.length() + 1);
strPath = strPath.substr(_strPath.length() + vhost.length() + 1);
strRet += strPath;
strRet += "</h1>\r\n";
if (strPath != "/") {
@ -525,7 +525,7 @@ inline void HttpSession::sendResponse(const char* pcStatus, const KeyValue& head
auto strSend = printer << endl;
//DebugL << strSend;
send(strSend);
m_ticker.resetTime();
_ticker.resetTime();
}
inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iContentSize,const char* pcContentType) {
KeyValue headerOut;
@ -563,7 +563,7 @@ string HttpSession::urlDecode(const string &str){
inline void HttpSession::urlDecode(Parser &parser){
parser.setUrl(urlDecode(parser.Url()));
for(auto &pr : m_parser.getUrlArgs()){
for(auto &pr : _parser.getUrlArgs()){
const_cast<string &>(pr.second) = urlDecode(pr.second);
}
}
@ -572,8 +572,8 @@ inline bool HttpSession::emitHttpEvent(bool doInvoke){
///////////////////是否断开本链接///////////////////////
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"];
bool bClose = (strcasecmp(_parser["Connection"].data(),"close") == 0) || ( ++_iReqCnt > reqCnt);
auto Origin = _parser["Origin"];
/////////////////////异步回复Invoker///////////////////////////////
weak_ptr<HttpSession> weakSelf = dynamic_pointer_cast<HttpSession>(shared_from_this());
HttpResponseInvoker invoker = [weakSelf,bClose,Origin](const string &codeOut, const KeyValue &headerOut, const string &contentOut){
@ -594,7 +594,7 @@ inline bool HttpSession::emitHttpEvent(bool doInvoke){
};
///////////////////广播HTTP事件///////////////////////////
bool consumed = false;//该事件是否被消费
NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastHttpRequest,m_parser,invoker,consumed,*this);
NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastHttpRequest,_parser,invoker,consumed,*this);
if(!consumed && doInvoke){
//该事件无人消费所以返回404
invoker("404 Not Found",KeyValue(),"");
@ -609,7 +609,7 @@ inline bool HttpSession::Handle_Req_POST(int64_t &content_len) {
GET_CONFIG_AND_REGISTER(uint64_t,maxReqSize,Config::Http::kMaxReqSize);
GET_CONFIG_AND_REGISTER(int,maxReqCnt,Config::Http::kMaxReqCount);
int64_t totalContentLen = m_parser["Content-Length"].empty() ? -1 : atoll(m_parser["Content-Length"].data());
int64_t totalContentLen = _parser["Content-Length"].empty() ? -1 : atoll(_parser["Content-Length"].data());
if(totalContentLen == 0){
//content为空
@ -621,34 +621,34 @@ inline bool HttpSession::Handle_Req_POST(int64_t &content_len) {
if(totalContentLen > 0 && totalContentLen < maxReqSize ){
//返回固定长度的content
content_len = totalContentLen;
auto parserCopy = m_parser;
m_contentCallBack = [this,parserCopy](const char *data,uint64_t len){
auto parserCopy = _parser;
_contentCallBack = [this,parserCopy](const char *data,uint64_t len){
//恢复http头
m_parser = parserCopy;
_parser = parserCopy;
//设置content
m_parser.setContent(string(data,len));
_parser.setContent(string(data,len));
//触发http事件emitHttpEvent内部会选择是否关闭连接
emitHttpEvent(true);
//清空数据,节省内存
m_parser.Clear();
_parser.Clear();
//content已经接收完毕
return false;
};
}else{
//返回不固定长度的content
content_len = -1;
auto parserCopy = m_parser;
auto parserCopy = _parser;
std::shared_ptr<uint64_t> recvedContentLen = std::make_shared<uint64_t>(0);
bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) || ( ++m_iReqCnt > maxReqCnt);
bool bClose = (strcasecmp(_parser["Connection"].data(),"close") == 0) || ( ++_iReqCnt > maxReqCnt);
m_contentCallBack = [this,parserCopy,totalContentLen,recvedContentLen,bClose](const char *data,uint64_t len){
_contentCallBack = [this,parserCopy,totalContentLen,recvedContentLen,bClose](const char *data,uint64_t len){
*(recvedContentLen) += len;
onRecvUnlimitedContent(parserCopy,data,len,totalContentLen,*(recvedContentLen));
if(*(recvedContentLen) < totalContentLen){
//数据还没接收完毕
//m_contentCallBack是可持续的后面还要处理后续content数据
//_contentCallBack是可持续的后面还要处理后续content数据
return true;
}
@ -698,8 +698,8 @@ void HttpSession::onWrite(const Buffer::Ptr &buffer) {
if(!strongSelf) {
return;
}
strongSelf->m_ticker.resetTime();
strongSelf->m_ui64TotalBytes += buffer->size();
strongSelf->_ticker.resetTime();
strongSelf->_ui64TotalBytes += buffer->size();
strongSelf->send(buffer);
});
}
@ -714,8 +714,8 @@ void HttpSession::onWrite(const char *data, int len) {
if(!strongSelf) {
return;
}
strongSelf->m_ticker.resetTime();
strongSelf->m_ui64TotalBytes += buffer->size();
strongSelf->_ticker.resetTime();
strongSelf->_ui64TotalBytes += buffer->size();
strongSelf->send(buffer);
});
}

View File

@ -101,16 +101,16 @@ protected:
WebSocketSplitter::decode((uint8_t *)data,len);
}
private:
Parser m_parser;
string m_strPath;
Ticker m_ticker;
uint32_t m_iReqCnt = 0;
Parser _parser;
string _strPath;
Ticker _ticker;
uint32_t _iReqCnt = 0;
//消耗的总流量
uint64_t m_ui64TotalBytes = 0;
uint64_t _ui64TotalBytes = 0;
//flv over http
MediaInfo m_mediaInfo;
MediaInfo _mediaInfo;
//处理content数据的callback
function<bool (const char *data,uint64_t len) > m_contentCallBack;
function<bool (const char *data,uint64_t len) > _contentCallBack;
private:
inline bool Handle_Req_GET(int64_t &content_len);
inline bool Handle_Req_POST(int64_t &content_len);

View File

@ -40,14 +40,14 @@ class HttpsSession: public HttpSession {
public:
HttpsSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock):
HttpSession(pTh,pSock){
m_sslBox.setOnEncData([&](const char *data, uint32_t len){
_sslBox.setOnEncData([&](const char *data, uint32_t len){
#if defined(__GNUC__) && (__GNUC__ < 5)
public_send(data,len);
#else//defined(__GNUC__) && (__GNUC__ < 5)
HttpSession::send(obtainBuffer(data,len));
#endif//defined(__GNUC__) && (__GNUC__ < 5)
});
m_sslBox.setOnDecData([&](const char *data, uint32_t len){
_sslBox.setOnDecData([&](const char *data, uint32_t len){
#if defined(__GNUC__) && (__GNUC__ < 5)
public_onRecv(data,len);
#else//defined(__GNUC__) && (__GNUC__ < 5)
@ -56,11 +56,11 @@ public:
});
}
virtual ~HttpsSession(){
//m_sslBox.shutdown();
//_sslBox.shutdown();
}
void onRecv(const Buffer::Ptr &pBuf) override{
TimeTicker();
m_sslBox.onRecv(pBuf->data(), pBuf->size());
_sslBox.onRecv(pBuf->data(), pBuf->size());
}
#if defined(__GNUC__) && (__GNUC__ < 5)
int public_send(const char *data, uint32_t len){
@ -73,10 +73,10 @@ public:
protected:
virtual int send(const Buffer::Ptr &buf) override{
TimeTicker();
m_sslBox.onSend(buf->data(), buf->size());
_sslBox.onSend(buf->data(), buf->size());
return buf->size();
}
SSL_Box m_sslBox;
SSL_Box _sslBox;
};

View File

@ -43,35 +43,35 @@ HLSMaker::HLSMaker(const string& strM3u8File,
if(ui32Num < 1){
ui32Num = 1;
}
m_ui32BufSize = ui32BufSize;
m_ui64TsCnt = 0;
m_strM3u8File = strM3u8File;
m_ui32NumSegments = ui32Num;
m_ui32SegmentDuration = ui32Duration;
m_ui32LastStamp = 0;
_ui32BufSize = ui32BufSize;
_ui64TsCnt = 0;
_strM3u8File = strM3u8File;
_ui32NumSegments = ui32Num;
_ui32SegmentDuration = ui32Duration;
_ui32LastStamp = 0;
m_strOutputPrefix = strM3u8File.substr(0, strM3u8File.rfind('.'));
m_strFileName = m_strOutputPrefix.substr(m_strOutputPrefix.rfind('/') + 1);
m_ts.init(m_strOutputPrefix + "-0.ts", m_ui32BufSize);
_strOutputPrefix = strM3u8File.substr(0, strM3u8File.rfind('.'));
_strFileName = _strOutputPrefix.substr(_strOutputPrefix.rfind('/') + 1);
_ts.init(_strOutputPrefix + "-0.ts", _ui32BufSize);
}
HLSMaker::~HLSMaker() {
m_ts.clear();
string strDir = m_strOutputPrefix.substr(0,m_strOutputPrefix.rfind('/'));
_ts.clear();
string strDir = _strOutputPrefix.substr(0,_strOutputPrefix.rfind('/'));
File::delete_file(strDir.data());
}
bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, int iEnd) {
char acWriteBuf[1024];
std::shared_ptr<FILE> pM3u8File(File::createfile_file(m_strM3u8File.data(), "w"),[](FILE *fp){
std::shared_ptr<FILE> pM3u8File(File::createfile_file(_strM3u8File.data(), "w"),[](FILE *fp){
if(fp){
fflush(fp);
fclose(fp);
}
});
if (!pM3u8File) {
WarnL << "Could not open temporary m3u8 index file (" << m_strM3u8File << "), no index file will be created";
WarnL << "Could not open temporary m3u8 index file (" << _strM3u8File << "), no index file will be created";
return false;
}
if (iFirstSegment < 0) {
@ -80,13 +80,13 @@ bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, i
//最少1秒
int maxSegmentDuration = 0;
for (auto dur : m_iDurations) {
for (auto dur : _iDurations) {
dur /=1000;
if(dur > maxSegmentDuration){
maxSegmentDuration = dur;
}
}
if (m_ui32NumSegments) {
if (_ui32NumSegments) {
snprintf(acWriteBuf,
sizeof(acWriteBuf),
"#EXTM3U\r\n"
@ -114,8 +114,8 @@ bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, i
snprintf(acWriteBuf,
sizeof(acWriteBuf),
"#EXTINF:%.3f,\r\n%s-%u.ts\r\n",
m_iDurations[i-iFirstSegment]/1000.0,
m_strFileName.c_str(),
_iDurations[i-iFirstSegment]/1000.0,
_strFileName.c_str(),
i);
if (fwrite(acWriteBuf, strlen(acWriteBuf), 1, pM3u8File.get()) != 1) {
WarnL << "Could not write to m3u8 index file, will not continue writing to index file";
@ -134,36 +134,36 @@ bool HLSMaker::write_index_file(int iFirstSegment, unsigned int uiLastSegment, i
}
void HLSMaker::inputH264(void *data, uint32_t length, uint32_t timeStamp, int type) {
if(m_ui32LastStamp == 0){
m_ui32LastStamp = timeStamp;
if(_ui32LastStamp == 0){
_ui32LastStamp = timeStamp;
}
int stampInc = timeStamp - m_ui32LastStamp;
int stampInc = timeStamp - _ui32LastStamp;
switch (type) {
case 7: //SPS
if (stampInc >= m_ui32SegmentDuration * 1000) {
m_ui32LastStamp = timeStamp;
if (stampInc >= _ui32SegmentDuration * 1000) {
_ui32LastStamp = timeStamp;
//关闭文件
m_ts.clear();
auto strTmpFileName = StrPrinter << m_strOutputPrefix << '-' << (++m_ui64TsCnt) << ".ts" << endl;
if (!m_ts.init(strTmpFileName, m_ui32BufSize)) {
_ts.clear();
auto strTmpFileName = StrPrinter << _strOutputPrefix << '-' << (++_ui64TsCnt) << ".ts" << endl;
if (!_ts.init(strTmpFileName, _ui32BufSize)) {
//创建文件失败
return;
}
//记录切片时间
m_iDurations.push_back(stampInc);
_iDurations.push_back(stampInc);
if(removets()){
//删除老的时间戳
m_iDurations.pop_front();
_iDurations.pop_front();
}
write_index_file(m_ui64TsCnt - m_ui32NumSegments, m_ui64TsCnt, 0);
write_index_file(_ui64TsCnt - _ui32NumSegments, _ui64TsCnt, 0);
}
case 1: //P
//insert aud frame before p and SPS frame
m_ts.inputH264("\x0\x0\x0\x1\x9\xf0", 6, timeStamp * 90);
_ts.inputH264("\x0\x0\x0\x1\x9\xf0", 6, timeStamp * 90);
case 5: //IDR
case 8: //PPS
m_ts.inputH264((char *) data, length, timeStamp * 90);
_ts.inputH264((char *) data, length, timeStamp * 90);
break;
default:
break;
@ -171,15 +171,15 @@ void HLSMaker::inputH264(void *data, uint32_t length, uint32_t timeStamp, int ty
}
void HLSMaker::inputAAC(void *data, uint32_t length, uint32_t timeStamp) {
m_ts.inputAAC((char *) data, length, timeStamp * 90);
_ts.inputAAC((char *) data, length, timeStamp * 90);
}
bool HLSMaker::removets() {
if (m_ui64TsCnt < m_ui32NumSegments + 2) {
if (_ui64TsCnt < _ui32NumSegments + 2) {
return false;
}
File::delete_file((StrPrinter << m_strOutputPrefix << "-"
<< m_ui64TsCnt - m_ui32NumSegments - 2
File::delete_file((StrPrinter << _strOutputPrefix << "-"
<< _ui64TsCnt - _ui32NumSegments - 2
<< ".ts" << endl).data());
return true;
}

View File

@ -60,16 +60,16 @@ public:
uint32_t ui32Length,
uint32_t ui32TimeStamp);
private:
TSMaker m_ts;
string m_strM3u8File;
string m_strFileName;
string m_strOutputPrefix;
uint32_t m_ui32SegmentDuration;
uint32_t m_ui32NumSegments;
uint64_t m_ui64TsCnt;
uint32_t m_ui32BufSize;
uint32_t m_ui32LastStamp;
std::deque<int> m_iDurations;
TSMaker _ts;
string _strM3u8File;
string _strFileName;
string _strOutputPrefix;
uint32_t _ui32SegmentDuration;
uint32_t _ui32NumSegments;
uint64_t _ui64TsCnt;
uint32_t _ui32BufSize;
uint32_t _ui32LastStamp;
std::deque<int> _iDurations;
bool write_index_file(int iFirstSegment, unsigned int uiLastSegment, int iEnd);
bool removets();

View File

@ -41,21 +41,21 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri
auto strFileName = recordPath + "/" + strVhost + "/" + strApp + "/" + strId;
m_hMP4File = MP4Read(strFileName.data());
if(m_hMP4File == MP4_INVALID_FILE_HANDLE){
_hMP4File = MP4Read(strFileName.data());
if(_hMP4File == MP4_INVALID_FILE_HANDLE){
throw runtime_error(StrPrinter << "打开MP4文件失败:" << strFileName << endl);
}
m_video_trId = MP4FindTrackId(m_hMP4File, 0, MP4_VIDEO_TRACK_TYPE, 0);
if(m_video_trId != MP4_INVALID_TRACK_ID){
if(strcmp(MP4GetTrackMediaDataName(m_hMP4File, m_video_trId),"avc1") ==0){
auto m_video_timescale = MP4GetTrackTimeScale(m_hMP4File, m_video_trId);
auto m_video_duration = MP4GetTrackDuration(m_hMP4File, m_video_trId);
m_video_num_samples = MP4GetTrackNumberOfSamples(m_hMP4File, m_video_trId);
m_video_sample_max_size = MP4GetTrackMaxSampleSize(m_hMP4File, m_video_trId);
m_video_width = MP4GetTrackVideoWidth(m_hMP4File, m_video_trId);
m_video_height = MP4GetTrackVideoHeight(m_hMP4File, m_video_trId);
m_video_framerate = MP4GetTrackVideoFrameRate(m_hMP4File, m_video_trId);
m_pcVideoSample = std::shared_ptr<uint8_t> (new uint8_t[m_video_sample_max_size],[](uint8_t *ptr){
_video_trId = MP4FindTrackId(_hMP4File, 0, MP4_VIDEO_TRACK_TYPE, 0);
if(_video_trId != MP4_INVALID_TRACK_ID){
if(strcmp(MP4GetTrackMediaDataName(_hMP4File, _video_trId),"avc1") ==0){
auto _video_timescale = MP4GetTrackTimeScale(_hMP4File, _video_trId);
auto _video_duration = MP4GetTrackDuration(_hMP4File, _video_trId);
_video_num_samples = MP4GetTrackNumberOfSamples(_hMP4File, _video_trId);
_video_sample_max_size = MP4GetTrackMaxSampleSize(_hMP4File, _video_trId);
_video_width = MP4GetTrackVideoWidth(_hMP4File, _video_trId);
_video_height = MP4GetTrackVideoHeight(_hMP4File, _video_trId);
_video_framerate = MP4GetTrackVideoFrameRate(_hMP4File, _video_trId);
_pcVideoSample = std::shared_ptr<uint8_t> (new uint8_t[_video_sample_max_size],[](uint8_t *ptr){
delete [] ptr;
});
uint8_t **seqheader;
@ -63,106 +63,106 @@ MediaReader::MediaReader(const string &strVhost,const string &strApp, const stri
uint32_t *pictheadersize;
uint32_t *seqheadersize;
uint32_t ix;
if(MP4GetTrackH264SeqPictHeaders(m_hMP4File, m_video_trId, &seqheader, &seqheadersize, &pictheader, &pictheadersize)){
if(MP4GetTrackH264SeqPictHeaders(_hMP4File, _video_trId, &seqheader, &seqheadersize, &pictheader, &pictheadersize)){
for (ix = 0; seqheadersize[ix] != 0; ix++) {
m_strSps.assign((char *)(seqheader[ix]), seqheadersize[ix]);
_strSps.assign((char *)(seqheader[ix]), seqheadersize[ix]);
float framerate;
getAVCInfo(m_strSps, (int &)m_video_width, (int &)m_video_height, framerate);
m_video_framerate = framerate;
m_strSps = string("\x0\x0\x0\x1",4) + m_strSps;
getAVCInfo(_strSps, (int &)_video_width, (int &)_video_height, framerate);
_video_framerate = framerate;
_strSps = string("\x0\x0\x0\x1",4) + _strSps;
MP4Free(seqheader[ix]);
}
MP4Free(seqheader);
MP4Free(seqheadersize);
for (ix = 0; pictheadersize[ix] != 0; ix++) {
m_strPps.assign("\x0\x0\x0\x1",4);
m_strPps.append((char *)(pictheader[ix]), pictheadersize[ix]);
_strPps.assign("\x0\x0\x0\x1",4);
_strPps.append((char *)(pictheader[ix]), pictheadersize[ix]);
MP4Free(pictheader[ix]);
}
MP4Free(pictheader);
MP4Free(pictheadersize);
}
m_video_ms = 1000.0 * m_video_duration / m_video_timescale;
_video_ms = 1000.0 * _video_duration / _video_timescale;
/*InfoL << "\r\n"
<< m_video_ms << "\r\n"
<< m_video_num_samples << "\r\n"
<< m_video_framerate << "\r\n"
<< m_video_width << "\r\n"
<< m_video_height << "\r\n";*/
<< _video_ms << "\r\n"
<< _video_num_samples << "\r\n"
<< _video_framerate << "\r\n"
<< _video_width << "\r\n"
<< _video_height << "\r\n";*/
} else {
//如果不是h264则忽略
m_video_trId = MP4_INVALID_TRACK_ID;
_video_trId = MP4_INVALID_TRACK_ID;
}
}
m_audio_trId = MP4FindTrackId(m_hMP4File, 0, MP4_AUDIO_TRACK_TYPE, 0);
if (m_audio_trId != MP4_INVALID_TRACK_ID) {
if (strcmp(MP4GetTrackMediaDataName(m_hMP4File, m_audio_trId), "mp4a") == 0) {
m_audio_sample_rate = MP4GetTrackTimeScale(m_hMP4File, m_audio_trId);
auto m_audio_duration = MP4GetTrackDuration(m_hMP4File, m_audio_trId);
m_audio_num_samples = MP4GetTrackNumberOfSamples(m_hMP4File,m_audio_trId);
m_audio_num_channels = MP4GetTrackAudioChannels(m_hMP4File, m_audio_trId);
m_audio_sample_max_size = MP4GetTrackMaxSampleSize(m_hMP4File,m_audio_trId);
_audio_trId = MP4FindTrackId(_hMP4File, 0, MP4_AUDIO_TRACK_TYPE, 0);
if (_audio_trId != MP4_INVALID_TRACK_ID) {
if (strcmp(MP4GetTrackMediaDataName(_hMP4File, _audio_trId), "mp4a") == 0) {
_audio_sample_rate = MP4GetTrackTimeScale(_hMP4File, _audio_trId);
auto _audio_duration = MP4GetTrackDuration(_hMP4File, _audio_trId);
_audio_num_samples = MP4GetTrackNumberOfSamples(_hMP4File,_audio_trId);
_audio_num_channels = MP4GetTrackAudioChannels(_hMP4File, _audio_trId);
_audio_sample_max_size = MP4GetTrackMaxSampleSize(_hMP4File,_audio_trId);
uint8_t *ppConfig;
uint32_t pConfigSize;
if(MP4GetTrackESConfiguration(m_hMP4File,m_audio_trId,&ppConfig,&pConfigSize)){
m_strAacCfg.assign((char *)ppConfig, pConfigSize);
makeAdtsHeader(m_strAacCfg, m_adts);
writeAdtsHeader(m_adts,m_adts.buffer);
getAACInfo(m_adts, (int &)m_audio_sample_rate, (int &)m_audio_num_channels);
if(MP4GetTrackESConfiguration(_hMP4File,_audio_trId,&ppConfig,&pConfigSize)){
_strAacCfg.assign((char *)ppConfig, pConfigSize);
makeAdtsHeader(_strAacCfg, _adts);
writeAdtsHeader(_adts,_adts.buffer);
getAACInfo(_adts, (int &)_audio_sample_rate, (int &)_audio_num_channels);
MP4Free(ppConfig);
}
m_audio_ms = 1000.0 * m_audio_duration / m_audio_sample_rate;
_audio_ms = 1000.0 * _audio_duration / _audio_sample_rate;
/*InfoL << "\r\n"
<< m_audio_ms << "\r\n"
<< m_audio_num_samples << "\r\n"
<< m_audio_num_channels << "\r\n"
<< m_audio_sample_rate << "\r\n";*/
<< _audio_ms << "\r\n"
<< _audio_num_samples << "\r\n"
<< _audio_num_channels << "\r\n"
<< _audio_sample_rate << "\r\n";*/
}else{
m_audio_trId = MP4_INVALID_TRACK_ID;
_audio_trId = MP4_INVALID_TRACK_ID;
}
}
if(m_audio_trId == MP4_INVALID_TRACK_ID && m_video_trId == MP4_INVALID_TRACK_ID){
MP4Close(m_hMP4File);
m_hMP4File = MP4_INVALID_FILE_HANDLE;
if(_audio_trId == MP4_INVALID_TRACK_ID && _video_trId == MP4_INVALID_TRACK_ID){
MP4Close(_hMP4File);
_hMP4File = MP4_INVALID_FILE_HANDLE;
throw runtime_error(StrPrinter << "该MP4文件音视频格式不支持:" << strFileName << endl);
}
m_iDuration = MAX(m_video_ms,m_audio_ms);
m_pChn.reset(new DevChannel(strVhost.data(),strApp.data(),strId.data(),m_iDuration/1000.0,false, false));
if (m_audio_trId != MP4_INVALID_TRACK_ID) {
_iDuration = MAX(_video_ms,_audio_ms);
_pChn.reset(new DevChannel(strVhost.data(),strApp.data(),strId.data(),_iDuration/1000.0,false, false));
if (_audio_trId != MP4_INVALID_TRACK_ID) {
AudioInfo info;
info.iChannel = m_audio_num_channels;
info.iChannel = _audio_num_channels;
info.iSampleBit = 16;
info.iSampleRate = m_audio_sample_rate;
m_pChn->initAudio(info);
info.iSampleRate = _audio_sample_rate;
_pChn->initAudio(info);
}
if (m_video_trId != MP4_INVALID_TRACK_ID) {
if (_video_trId != MP4_INVALID_TRACK_ID) {
VideoInfo info;
info.iFrameRate = m_video_framerate;
info.iWidth = m_video_width;
info.iHeight = m_video_height;
m_pChn->initVideo(info);
info.iFrameRate = _video_framerate;
info.iWidth = _video_width;
info.iHeight = _video_height;
_pChn->initVideo(info);
}
if (m_audio_trId != MP4_INVALID_TRACK_ID) {
m_pChn->inputAAC((char *)m_adts.buffer, 7, 0);
if (_audio_trId != MP4_INVALID_TRACK_ID) {
_pChn->inputAAC((char *)_adts.buffer, 7, 0);
}
if (m_video_trId != MP4_INVALID_TRACK_ID) {
//m_pChn->initVideo(info);
m_pChn->inputH264((char *) m_strSps.data(), m_strSps.size(), 0);
m_pChn->inputH264((char *) m_strPps.data(), m_strPps.size(), 0);
if (_video_trId != MP4_INVALID_TRACK_ID) {
//_pChn->initVideo(info);
_pChn->inputH264((char *) _strSps.data(), _strSps.size(), 0);
_pChn->inputH264((char *) _strPps.data(), _strPps.size(), 0);
}
}
MediaReader::~MediaReader() {
if (m_hMP4File != MP4_INVALID_FILE_HANDLE) {
MP4Close(m_hMP4File);
m_hMP4File = MP4_INVALID_FILE_HANDLE;
if (_hMP4File != MP4_INVALID_FILE_HANDLE) {
MP4Close(_hMP4File);
_hMP4File = MP4_INVALID_FILE_HANDLE;
}
}
@ -174,14 +174,14 @@ void MediaReader::startReadMP4() {
AsyncTaskThread::Instance().DoTaskDelay(reinterpret_cast<uint64_t>(this), sampleMS, [strongSelf](){
return strongSelf->readSample();
});
m_pChn->setListener(strongSelf);
_pChn->setListener(strongSelf);
}
bool MediaReader::seekTo(uint32_t ui32Stamp){
seek(ui32Stamp);
return true;
}
uint32_t MediaReader::getStamp() {
return m_iSeekTime + m_ticker.elapsedTime();
return _iSeekTime + _ticker.elapsedTime();
}
bool MediaReader::shutDown(){
AsyncTaskThread::Instance().CancelTask(reinterpret_cast<uint64_t>(this));
@ -190,25 +190,25 @@ bool MediaReader::shutDown(){
bool MediaReader::readSample(int iTimeInc) {
TimeTicker();
lock_guard<recursive_mutex> lck(m_mtx);
lock_guard<recursive_mutex> lck(_mtx);
auto bFlag0 = readVideoSample(iTimeInc);//数据没读完
auto bFlag1 = readAudioSample(iTimeInc);//数据没读完
auto bFlag2 = m_pChn->readerCount() > 0;//读取者大于0
auto bFlag2 = _pChn->readerCount() > 0;//读取者大于0
if((bFlag0 || bFlag1) && bFlag2){
m_alive.resetTime();
_alive.resetTime();
}
//DebugL << "alive ...";
//3秒延时关闭
return m_alive.elapsedTime() < 3 * 1000;
return _alive.elapsedTime() < 3 * 1000;
}
inline bool MediaReader::readVideoSample(int iTimeInc) {
if (m_video_trId != MP4_INVALID_TRACK_ID) {
if (_video_trId != MP4_INVALID_TRACK_ID) {
auto iNextSample = getVideoSampleId(iTimeInc);
MP4SampleId iIdx = m_video_current;
for (iIdx = m_video_current; iIdx < iNextSample; iIdx++) {
uint8_t *pBytes = m_pcVideoSample.get();
uint32_t numBytes = m_video_sample_max_size;
if(MP4ReadSample(m_hMP4File, m_video_trId, iIdx + 1, &pBytes, &numBytes,NULL,NULL,NULL,&m_bSyncSample)){
MP4SampleId iIdx = _video_current;
for (iIdx = _video_current; iIdx < iNextSample; iIdx++) {
uint8_t *pBytes = _pcVideoSample.get();
uint32_t numBytes = _video_sample_max_size;
if(MP4ReadSample(_hMP4File, _video_trId, iIdx + 1, &pBytes, &numBytes,NULL,NULL,NULL,&_bSyncSample)){
if (!iTimeInc) {
uint32_t iOffset = 0;
while (iOffset < numBytes) {
@ -219,97 +219,97 @@ inline bool MediaReader::readVideoSample(int iTimeInc) {
break;
}
memcpy(pBytes + iOffset, "\x0\x0\x0\x1", 4);
writeH264(pBytes + iOffset, iFrameLen + 4, (double) m_video_ms * iIdx / m_video_num_samples);
writeH264(pBytes + iOffset, iFrameLen + 4, (double) _video_ms * iIdx / _video_num_samples);
iOffset += (iFrameLen + 4);
}
}else if(m_bSyncSample){
}else if(_bSyncSample){
break;
}
}else{
ErrorL << "读取视频失败:" << iIdx + 1;
}
}
m_video_current = iIdx;
return m_video_current < m_video_num_samples;
_video_current = iIdx;
return _video_current < _video_num_samples;
}
return false;
}
inline bool MediaReader::readAudioSample(int iTimeInc) {
if (m_audio_trId != MP4_INVALID_TRACK_ID) {
if (_audio_trId != MP4_INVALID_TRACK_ID) {
auto iNextSample = getAudioSampleId(iTimeInc);
for (auto i = m_audio_current; i < iNextSample; i++) {
uint32_t numBytes = m_audio_sample_max_size;
uint8_t *pBytes = m_adts.buffer + 7;
if(MP4ReadSample(m_hMP4File, m_audio_trId, i + 1, &pBytes, &numBytes)){
for (auto i = _audio_current; i < iNextSample; i++) {
uint32_t numBytes = _audio_sample_max_size;
uint8_t *pBytes = _adts.buffer + 7;
if(MP4ReadSample(_hMP4File, _audio_trId, i + 1, &pBytes, &numBytes)){
if (!iTimeInc) {
m_adts.aac_frame_length = 7 + numBytes;
writeAdtsHeader(m_adts, m_adts.buffer);
writeAAC(m_adts.buffer, m_adts.aac_frame_length, (double) m_audio_ms * i / m_audio_num_samples);
_adts.aac_frame_length = 7 + numBytes;
writeAdtsHeader(_adts, _adts.buffer);
writeAAC(_adts.buffer, _adts.aac_frame_length, (double) _audio_ms * i / _audio_num_samples);
}
}else{
ErrorL << "读取音频失败:" << i+ 1;
}
}
m_audio_current = iNextSample;
return m_audio_current < m_audio_num_samples;
_audio_current = iNextSample;
return _audio_current < _audio_num_samples;
}
return false;
}
inline void MediaReader::writeH264(uint8_t *pucData,int iLen,uint32_t uiStamp) {
m_pChn->inputH264((char *)pucData, iLen, uiStamp);
_pChn->inputH264((char *)pucData, iLen, uiStamp);
}
inline void MediaReader::writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp) {
m_pChn->inputAAC((char *)pucData, iLen, uiStamp);
_pChn->inputAAC((char *)pucData, iLen, uiStamp);
}
inline MP4SampleId MediaReader::getVideoSampleId(int iTimeInc ) {
MP4SampleId video_current = (double)m_video_num_samples * (m_iSeekTime + m_ticker.elapsedTime() + iTimeInc) / m_video_ms;
video_current = MAX(0,MIN(m_video_num_samples, video_current));
MP4SampleId video_current = (double)_video_num_samples * (_iSeekTime + _ticker.elapsedTime() + iTimeInc) / _video_ms;
video_current = MAX(0,MIN(_video_num_samples, video_current));
return video_current;
}
inline MP4SampleId MediaReader::getAudioSampleId(int iTimeInc) {
MP4SampleId audio_current = (double)m_audio_num_samples * (m_iSeekTime + m_ticker.elapsedTime() + iTimeInc) / m_audio_ms ;
audio_current = MAX(0,MIN(m_audio_num_samples,audio_current));
MP4SampleId audio_current = (double)_audio_num_samples * (_iSeekTime + _ticker.elapsedTime() + iTimeInc) / _audio_ms ;
audio_current = MAX(0,MIN(_audio_num_samples,audio_current));
return audio_current;
}
inline void MediaReader::setSeekTime(int iSeekTime){
m_iSeekTime = MAX(0, MIN(iSeekTime,m_iDuration));
m_ticker.resetTime();
if (m_audio_trId != MP4_INVALID_TRACK_ID) {
m_audio_current = getAudioSampleId();
_iSeekTime = MAX(0, MIN(iSeekTime,_iDuration));
_ticker.resetTime();
if (_audio_trId != MP4_INVALID_TRACK_ID) {
_audio_current = getAudioSampleId();
}
if (m_video_trId != MP4_INVALID_TRACK_ID) {
m_video_current = getVideoSampleId();
if (_video_trId != MP4_INVALID_TRACK_ID) {
_video_current = getVideoSampleId();
}
}
inline uint32_t MediaReader::getVideoCurrentTime(){
return (double)m_video_current * m_video_ms /m_video_num_samples;
return (double)_video_current * _video_ms /_video_num_samples;
}
void MediaReader::seek(int iSeekTime,bool bReStart){
lock_guard<recursive_mutex> lck(m_mtx);
if(iSeekTime == 0 || m_video_trId == MP4_INVALID_TRACK_ID){
lock_guard<recursive_mutex> lck(_mtx);
if(iSeekTime == 0 || _video_trId == MP4_INVALID_TRACK_ID){
setSeekTime(iSeekTime);
}else{
setSeekTime(iSeekTime - 5000);
//在之后的10秒查找关键帧
readVideoSample(10000);
if (m_bSyncSample) {
if (_bSyncSample) {
//找到关键帧
auto iIdr = m_video_current;
auto iIdr = _video_current;
setSeekTime(getVideoCurrentTime());
m_video_current = iIdr;
_video_current = iIdr;
}else{
//未找到关键帧
setSeekTime(iSeekTime);
}
}
m_pChn->updateTimeStamp(m_iSeekTime);
_pChn->updateTimeStamp(_iSeekTime);
if(bReStart){
AsyncTaskThread::Instance().CancelTask(reinterpret_cast<uint64_t>(this));

View File

@ -55,37 +55,37 @@ public:
private:
#ifdef ENABLE_MP4V2
MP4FileHandle m_hMP4File = MP4_INVALID_FILE_HANDLE;
MP4TrackId m_video_trId = MP4_INVALID_TRACK_ID;
uint32_t m_video_ms = 0;
uint32_t m_video_num_samples = 0;
uint32_t m_video_sample_max_size = 0;
uint32_t m_video_width = 0;
uint32_t m_video_height = 0;
uint32_t m_video_framerate = 0;
string m_strPps;
string m_strSps;
bool m_bSyncSample = false;
MP4FileHandle _hMP4File = MP4_INVALID_FILE_HANDLE;
MP4TrackId _video_trId = MP4_INVALID_TRACK_ID;
uint32_t _video_ms = 0;
uint32_t _video_num_samples = 0;
uint32_t _video_sample_max_size = 0;
uint32_t _video_width = 0;
uint32_t _video_height = 0;
uint32_t _video_framerate = 0;
string _strPps;
string _strSps;
bool _bSyncSample = false;
MP4TrackId m_audio_trId = MP4_INVALID_TRACK_ID;
uint32_t m_audio_ms = 0;
uint32_t m_audio_num_samples = 0;
uint32_t m_audio_sample_max_size = 0;
uint32_t m_audio_sample_rate = 0;
uint32_t m_audio_num_channels = 0;
string m_strAacCfg;
AACFrame m_adts;
MP4TrackId _audio_trId = MP4_INVALID_TRACK_ID;
uint32_t _audio_ms = 0;
uint32_t _audio_num_samples = 0;
uint32_t _audio_sample_max_size = 0;
uint32_t _audio_sample_rate = 0;
uint32_t _audio_num_channels = 0;
string _strAacCfg;
AACFrame _adts;
int m_iDuration = 0;
DevChannel::Ptr m_pChn;
MP4SampleId m_video_current = 0;
MP4SampleId m_audio_current = 0;
std::shared_ptr<uint8_t> m_pcVideoSample;
int _iDuration = 0;
DevChannel::Ptr _pChn;
MP4SampleId _video_current = 0;
MP4SampleId _audio_current = 0;
std::shared_ptr<uint8_t> _pcVideoSample;
int m_iSeekTime = 0 ;
Ticker m_ticker;
Ticker m_alive;
recursive_mutex m_mtx;
int _iSeekTime = 0 ;
Ticker _ticker;
Ticker _alive;
recursive_mutex _mtx;
void seek(int iSeekTime,bool bReStart = true);
inline void setSeekTime(int iSeekTime);

View File

@ -57,7 +57,7 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp,
if(enableHls) {
auto m3u8FilePath = hlsPath + "/" + strVhost + "/" + strApp + "/" + strId + "/hls.m3u8";
m_hlsMaker.reset(new HLSMaker(m3u8FilePath,hlsBufSize, hlsDuration, hlsNum));
_hlsMaker.reset(new HLSMaker(m3u8FilePath,hlsBufSize, hlsDuration, hlsNum));
}
#ifdef ENABLE_MP4V2
@ -66,7 +66,7 @@ MediaRecorder::MediaRecorder(const string &strVhost_tmp,
if(enableMp4){
auto mp4FilePath = recordPath + "/" + strVhost + "/" + recordAppName + "/" + strApp + "/" + strId + "/";
m_mp4Maker.reset(new Mp4Maker(mp4FilePath,strVhost,strApp,strId,pPlayer));
_mp4Maker.reset(new Mp4Maker(mp4FilePath,strVhost,strApp,strId,pPlayer));
}
#endif //ENABLE_MP4V2
}
@ -75,23 +75,23 @@ MediaRecorder::~MediaRecorder() {
}
void MediaRecorder::inputH264(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType) {
if(m_hlsMaker){
m_hlsMaker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
if(_hlsMaker){
_hlsMaker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
}
#ifdef ENABLE_MP4V2
if(m_mp4Maker){
m_mp4Maker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
if(_mp4Maker){
_mp4Maker->inputH264(pData, ui32Length, ui32TimeStamp, iType);
}
#endif //ENABLE_MP4V2
}
void MediaRecorder::inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp) {
if(m_hlsMaker){
m_hlsMaker->inputAAC(pData, ui32Length, ui32TimeStamp);
if(_hlsMaker){
_hlsMaker->inputAAC(pData, ui32Length, ui32TimeStamp);
}
#ifdef ENABLE_MP4V2
if(m_mp4Maker){
m_mp4Maker->inputAAC(pData, ui32Length, ui32TimeStamp);
if(_mp4Maker){
_mp4Maker->inputAAC(pData, ui32Length, ui32TimeStamp);
}
#endif //ENABLE_MP4V2
}

View File

@ -50,8 +50,8 @@ public:
const string &strApp,
const string &strId,
const std::shared_ptr<PlayerBase> &pPlayer,
bool m_enableHls = true,
bool m_enableMp4 = false);
bool enableHls = true,
bool enableMp4 = false);
virtual ~MediaRecorder();
void inputH264( void *pData,
@ -63,9 +63,9 @@ public:
uint32_t ui32Length,
uint32_t ui32TimeStamp);
private:
std::shared_ptr<HLSMaker> m_hlsMaker;
std::shared_ptr<HLSMaker> _hlsMaker;
#ifdef ENABLE_MP4V2
std::shared_ptr<Mp4Maker> m_mp4Maker;
std::shared_ptr<Mp4Maker> _mp4Maker;
#endif //ENABLE_MP4V2
};

View File

@ -62,14 +62,14 @@ Mp4Maker::Mp4Maker(const string& strPath,
const string &strStreamId,
const PlayerBase::Ptr &pPlayer) {
DebugL << strPath;
m_pPlayer = pPlayer;
m_strPath = strPath;
_pPlayer = pPlayer;
_strPath = strPath;
/////record 业务逻辑//////
m_info.strAppName = strApp;
m_info.strStreamId = strStreamId;
m_info.strVhost = strVhost;
m_info.strFolder = strPath;
_info.strAppName = strApp;
_info.strStreamId = strStreamId;
_info.strVhost = strVhost;
_info.strFolder = strPath;
//----record 业务逻辑----//
}
Mp4Maker::~Mp4Maker() {
@ -80,22 +80,22 @@ void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStam
switch (iType) {
case 1: //P
case 5: { //IDR
if (m_strLastVideo.size()) {
int64_t iTimeInc = (int64_t)ui32TimeStamp - (int64_t)m_ui32LastVideoTime;
if (_strLastVideo.size()) {
int64_t iTimeInc = (int64_t)ui32TimeStamp - (int64_t)_ui32LastVideoTime;
iTimeInc = MAX(0,MIN(iTimeInc,500));
if(iTimeInc == 0 || iTimeInc == 500){
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << m_ui32LastVideoTime;
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << _ui32LastVideoTime;
}
_inputH264((char *) m_strLastVideo.data(), m_strLastVideo.size(), iTimeInc, m_iLastVideoType);
_inputH264((char *) _strLastVideo.data(), _strLastVideo.size(), iTimeInc, _iLastVideoType);
}
//m_strLastVideo.assign(("\x0\x0\x0\x2\x9\xf0"), 6);
//_strLastVideo.assign(("\x0\x0\x0\x2\x9\xf0"), 6);
uint32_t *p = (uint32_t *) pData;
*p = htonl(ui32Length - 4);
m_strLastVideo.assign((char *) pData, ui32Length);
_strLastVideo.assign((char *) pData, ui32Length);
memcpy(pData, "\x00\x00\x00\x01", 4);
m_ui32LastVideoTime = ui32TimeStamp;
m_iLastVideoType = iType;
_ui32LastVideoTime = ui32TimeStamp;
_iLastVideoType = iType;
}
break;
default:
@ -103,28 +103,28 @@ void Mp4Maker::inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStam
}
}
void Mp4Maker::inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp){
if (m_strLastAudio.size()) {
int64_t iTimeInc = (int64_t)ui32TimeStamp - (int64_t)m_ui32LastAudioTime;
if (_strLastAudio.size()) {
int64_t iTimeInc = (int64_t)ui32TimeStamp - (int64_t)_ui32LastAudioTime;
iTimeInc = MAX(0,MIN(iTimeInc,500));
if(iTimeInc == 0 || iTimeInc == 500){
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << m_ui32LastAudioTime;
WarnL << "abnormal time stamp increment:" << ui32TimeStamp << " " << _ui32LastAudioTime;
}
_inputAAC((char *)m_strLastAudio.data(), m_strLastAudio.size(), iTimeInc);
_inputAAC((char *)_strLastAudio.data(), _strLastAudio.size(), iTimeInc);
}
m_strLastAudio.assign((char *)pData, ui32Length);
m_ui32LastAudioTime = ui32TimeStamp;
_strLastAudio.assign((char *)pData, ui32Length);
_ui32LastAudioTime = ui32TimeStamp;
}
void Mp4Maker::_inputH264(void* pData, uint32_t ui32Length, uint32_t ui32Duration, int iType) {
GET_CONFIG_AND_REGISTER(uint32_t,recordSec,Config::Record::kFileSecond);
if(iType == 5 && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordSec * 1000)){
if(iType == 5 && (_hMp4 == MP4_INVALID_FILE_HANDLE || _ticker.elapsedTime() > recordSec * 1000)){
//在I帧率处新建MP4文件
//如果文件未创建或者文件超过10分钟则创建新文件
createFile();
}
if (m_hVideo != MP4_INVALID_TRACK_ID) {
MP4WriteSample(m_hMp4, m_hVideo, (uint8_t *) pData, ui32Length,ui32Duration * 90,0,iType == 5);
if (_hVideo != MP4_INVALID_TRACK_ID) {
MP4WriteSample(_hMp4, _hVideo, (uint8_t *) pData, ui32Length,ui32Duration * 90,0,iType == 5);
}
}
@ -134,39 +134,39 @@ void Mp4Maker::_inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32Duration
//todo(xzl) 修复此处
//
// if (!m_pPlayer->containVideo() && (m_hMp4 == MP4_INVALID_FILE_HANDLE || m_ticker.elapsedTime() > recordSec * 1000)) {
// if (!_pPlayer->containVideo() && (_hMp4 == MP4_INVALID_FILE_HANDLE || _ticker.elapsedTime() > recordSec * 1000)) {
// //在I帧率处新建MP4文件
// //如果文件未创建或者文件超过10分钟则创建新文件
// createFile();
// }
// if (m_hAudio != MP4_INVALID_TRACK_ID) {
// auto duration = ui32Duration * m_pPlayer->getAudioSampleRate() /1000.0;
// MP4WriteSample(m_hMp4, m_hAudio, (uint8_t*)pData + 7, ui32Length - 7,duration,0,false);
// if (_hAudio != MP4_INVALID_TRACK_ID) {
// auto duration = ui32Duration * _pPlayer->getAudioSampleRate() /1000.0;
// MP4WriteSample(_hMp4, _hAudio, (uint8_t*)pData + 7, ui32Length - 7,duration,0,false);
// }
}
void Mp4Maker::createFile() {
if(!m_pPlayer->isInited()){
if(!_pPlayer->isInited()){
return;
}
closeFile();
auto strDate = timeStr("%Y-%m-%d");
auto strTime = timeStr("%H-%M-%S");
auto strFileTmp = m_strPath + strDate + "/." + strTime + ".mp4";
auto strFile = m_strPath + strDate + "/" + strTime + ".mp4";
auto strFileTmp = _strPath + strDate + "/." + strTime + ".mp4";
auto strFile = _strPath + strDate + "/" + strTime + ".mp4";
/////record 业务逻辑//////
m_info.ui64StartedTime = ::time(NULL);
m_info.strFileName = strTime + ".mp4";
m_info.strFilePath = strFile;
_info.ui64StartedTime = ::time(NULL);
_info.strFileName = strTime + ".mp4";
_info.strFilePath = strFile;
GET_CONFIG_AND_REGISTER(string,appName,Config::Record::kAppName);
m_info.strUrl = m_info.strVhost + "/"
_info.strUrl = _info.strVhost + "/"
+ appName + "/"
+ m_info.strAppName + "/"
+ m_info.strStreamId + "/"
+ _info.strAppName + "/"
+ _info.strStreamId + "/"
+ strDate + "/"
+ strTime + ".mp4";
//----record 业务逻辑----//
@ -176,36 +176,36 @@ void Mp4Maker::createFile() {
#else
File::createfile_path(strFileTmp.data(), 0);
#endif
m_hMp4 = MP4Create(strFileTmp.data());
if (m_hMp4 == MP4_INVALID_FILE_HANDLE) {
_hMp4 = MP4Create(strFileTmp.data());
if (_hMp4 == MP4_INVALID_FILE_HANDLE) {
WarnL << "创建MP4文件失败:" << strFileTmp;
return;
}
//MP4SetTimeScale(m_hMp4, 90000);
m_strFileTmp = strFileTmp;
m_strFile = strFile;
m_ticker.resetTime();
//MP4SetTimeScale(_hMp4, 90000);
_strFileTmp = strFileTmp;
_strFile = strFile;
_ticker.resetTime();
//todo(xzl) 修复此处
// if(m_pPlayer->containVideo()){
// auto &sps = m_pPlayer->getSps();
// auto &pps = m_pPlayer->getPps();
// m_hVideo = MP4AddH264VideoTrack(m_hMp4, 90000, MP4_INVALID_DURATION,
// m_pPlayer->getVideoWidth(), m_pPlayer->getVideoHeight(),
// if(_pPlayer->containVideo()){
// auto &sps = _pPlayer->getSps();
// auto &pps = _pPlayer->getPps();
// _hVideo = MP4AddH264VideoTrack(_hMp4, 90000, MP4_INVALID_DURATION,
// _pPlayer->getVideoWidth(), _pPlayer->getVideoHeight(),
// sps[5], sps[6], sps[7], 3);
// if(m_hVideo !=MP4_INVALID_TRACK_ID){
// MP4AddH264SequenceParameterSet(m_hMp4, m_hVideo, (uint8_t *)sps.data() + 4, sps.size() - 4);
// MP4AddH264PictureParameterSet(m_hMp4, m_hVideo, (uint8_t *)pps.data() + 4, pps.size() - 4);
// if(_hVideo !=MP4_INVALID_TRACK_ID){
// MP4AddH264SequenceParameterSet(_hMp4, _hVideo, (uint8_t *)sps.data() + 4, sps.size() - 4);
// MP4AddH264PictureParameterSet(_hMp4, _hVideo, (uint8_t *)pps.data() + 4, pps.size() - 4);
// }else{
// WarnL << "添加视频通道失败:" << strFileTmp;
// }
// }
// if(m_pPlayer->containAudio()){
// m_hAudio = MP4AddAudioTrack(m_hMp4, m_pPlayer->getAudioSampleRate(), MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
// if (m_hAudio != MP4_INVALID_TRACK_ID) {
// auto &cfg = m_pPlayer->getAudioCfg();
// MP4SetTrackESConfiguration(m_hMp4, m_hAudio,(uint8_t *)cfg.data(), cfg.size());
// if(_pPlayer->containAudio()){
// _hAudio = MP4AddAudioTrack(_hMp4, _pPlayer->getAudioSampleRate(), MP4_INVALID_DURATION, MP4_MPEG4_AUDIO_TYPE);
// if (_hAudio != MP4_INVALID_TRACK_ID) {
// auto &cfg = _pPlayer->getAudioCfg();
// MP4SetTrackESConfiguration(_hMp4, _hAudio,(uint8_t *)cfg.data(), cfg.size());
// }else{
// WarnL << "添加音频通道失败:" << strFileTmp;
// }
@ -213,24 +213,24 @@ void Mp4Maker::createFile() {
}
void Mp4Maker::closeFile() {
if (m_hMp4 != MP4_INVALID_FILE_HANDLE) {
if (_hMp4 != MP4_INVALID_FILE_HANDLE) {
{
TimeTicker();
MP4Close(m_hMp4,MP4_CLOSE_DO_NOT_COMPUTE_BITRATE);
MP4Close(_hMp4,MP4_CLOSE_DO_NOT_COMPUTE_BITRATE);
}
rename(m_strFileTmp.data(),m_strFile.data());
m_hMp4 = MP4_INVALID_FILE_HANDLE;
m_hVideo = MP4_INVALID_TRACK_ID;
m_hAudio = MP4_INVALID_TRACK_ID;
rename(_strFileTmp.data(),_strFile.data());
_hMp4 = MP4_INVALID_FILE_HANDLE;
_hVideo = MP4_INVALID_TRACK_ID;
_hAudio = MP4_INVALID_TRACK_ID;
/////record 业务逻辑//////
m_info.ui64TimeLen = ::time(NULL) - m_info.ui64StartedTime;
_info.ui64TimeLen = ::time(NULL) - _info.ui64StartedTime;
//获取文件大小
struct stat fileData;
stat(m_strFile.data(), &fileData);
m_info.ui64FileSize = fileData.st_size;
stat(_strFile.data(), &fileData);
_info.ui64FileSize = fileData.st_size;
//----record 业务逻辑----//
NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRecordMP4,m_info,*this);
NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRecordMP4,_info,*this);
}
}

View File

@ -73,29 +73,29 @@ public:
//时间戳参考频率1000
void inputAAC(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp);
private:
MP4FileHandle m_hMp4 = MP4_INVALID_FILE_HANDLE;
MP4TrackId m_hVideo = MP4_INVALID_TRACK_ID;
MP4TrackId m_hAudio = MP4_INVALID_TRACK_ID;
PlayerBase::Ptr m_pPlayer;
string m_strPath;
string m_strFile;
string m_strFileTmp;
Ticker m_ticker;
SmoothTicker m_mediaTicker[2];
MP4FileHandle _hMp4 = MP4_INVALID_FILE_HANDLE;
MP4TrackId _hVideo = MP4_INVALID_TRACK_ID;
MP4TrackId _hAudio = MP4_INVALID_TRACK_ID;
PlayerBase::Ptr _pPlayer;
string _strPath;
string _strFile;
string _strFileTmp;
Ticker _ticker;
SmoothTicker _mediaTicker[2];
void createFile();
void closeFile();
void _inputH264(void *pData, uint32_t ui32Length, uint32_t ui64Duration, int iType);
void _inputAAC(void *pData, uint32_t ui32Length, uint32_t ui64Duration);
string m_strLastVideo;
string m_strLastAudio;
string _strLastVideo;
string _strLastAudio;
uint32_t m_ui32LastVideoTime = 0;
uint32_t m_ui32LastAudioTime = 0;
int m_iLastVideoType = 0;
uint32_t _ui32LastVideoTime = 0;
uint32_t _ui32LastAudioTime = 0;
int _iLastVideoType = 0;
Mp4Info m_info;
Mp4Info _info;
};
} /* namespace MediaFile */

View File

@ -43,22 +43,22 @@ MediaPlayer::~MediaPlayer() {
}
void MediaPlayer::play(const char* strUrl) {
string strPrefix = FindField(strUrl, NULL, "://");
if ((strcasecmp(m_strPrefix.data(),strPrefix.data()) != 0) || strPrefix.empty()) {
if ((strcasecmp(_strPrefix.data(),strPrefix.data()) != 0) || strPrefix.empty()) {
//协议切换
m_strPrefix = strPrefix;
m_parser = PlayerBase::createPlayer(strUrl);
m_parser->setOnShutdown(m_shutdownCB);
_strPrefix = strPrefix;
_parser = PlayerBase::createPlayer(strUrl);
_parser->setOnShutdown(_shutdownCB);
//todo(xzl) 修复此处
// m_parser->setOnVideoCB(m_onGetVideoCB);
// m_parser->setOnAudioCB(m_onGetAudioCB);
// _parser->setOnVideoCB(_onGetVideoCB);
// _parser->setOnAudioCB(_onGetAudioCB);
}
m_parser->setOnPlayResult(m_playResultCB);
m_parser->mINI::operator=(*this);
m_parser->play(strUrl);
_parser->setOnPlayResult(_playResultCB);
_parser->mINI::operator=(*this);
_parser->play(strUrl);
}
TaskExecutor::Ptr MediaPlayer::getExecutor(){
auto parser = dynamic_pointer_cast<SocketHelper>(m_parser);
auto parser = dynamic_pointer_cast<SocketHelper>(_parser);
if(!parser){
return nullptr;
}
@ -66,14 +66,14 @@ TaskExecutor::Ptr MediaPlayer::getExecutor(){
}
void MediaPlayer::pause(bool bPause) {
if (m_parser) {
m_parser->pause(bPause);
if (_parser) {
_parser->pause(bPause);
}
}
void MediaPlayer::teardown() {
if (m_parser) {
m_parser->teardown();
if (_parser) {
_parser->teardown();
}
}

View File

@ -54,7 +54,7 @@ public:
void teardown() override;
TaskExecutor::Ptr getExecutor();
private:
string m_strPrefix;
string _strPrefix;
};

View File

@ -101,73 +101,73 @@ public:
PlayerImp(){}
virtual ~PlayerImp(){}
void setOnShutdown(const function<void(const SockException &)> &cb) override {
if (m_parser) {
m_parser->setOnShutdown(cb);
if (_parser) {
_parser->setOnShutdown(cb);
}
m_shutdownCB = cb;
_shutdownCB = cb;
}
void setOnPlayResult(const function<void(const SockException &ex)> &cb) override {
if (m_parser) {
m_parser->setOnPlayResult(cb);
if (_parser) {
_parser->setOnPlayResult(cb);
}
m_playResultCB = cb;
_playResultCB = cb;
}
bool isInited() const override{
if (m_parser) {
return m_parser->isInited();
if (_parser) {
return _parser->isInited();
}
return PlayerBase::isInited();
}
float getDuration() const override {
if (m_parser) {
return m_parser->getDuration();
if (_parser) {
return _parser->getDuration();
}
return PlayerBase::getDuration();
}
float getProgress() const override{
if (m_parser) {
return m_parser->getProgress();
if (_parser) {
return _parser->getProgress();
}
return PlayerBase::getProgress();
}
void seekTo(float fProgress) override{
if (m_parser) {
return m_parser->seekTo(fProgress);
if (_parser) {
return _parser->seekTo(fProgress);
}
return PlayerBase::seekTo(fProgress);
}
void setMediaSouce(const MediaSource::Ptr & src) override {
if (m_parser) {
return m_parser->setMediaSouce(src);
if (_parser) {
return _parser->setMediaSouce(src);
}
m_pMediaSrc = src;
_pMediaSrc = src;
}
vector<Track::Ptr> getTracks() const override{
if (m_parser) {
return m_parser->getTracks();
if (_parser) {
return _parser->getTracks();
}
return PlayerBase::getTracks();
}
protected:
void onShutdown(const SockException &ex) override {
if (m_shutdownCB) {
m_shutdownCB(ex);
if (_shutdownCB) {
_shutdownCB(ex);
}
}
void onPlayResult(const SockException &ex) override {
if (m_playResultCB) {
m_playResultCB(ex);
m_playResultCB = nullptr;
if (_playResultCB) {
_playResultCB(ex);
_playResultCB = nullptr;
}
}
protected:
function<void(const SockException &ex)> m_shutdownCB;
function<void(const SockException &ex)> m_playResultCB;
std::shared_ptr<Parser> m_parser;
MediaSource::Ptr m_pMediaSrc;
function<void(const SockException &ex)> _shutdownCB;
function<void(const SockException &ex)> _playResultCB;
std::shared_ptr<Parser> _parser;
MediaSource::Ptr _pMediaSrc;
};
} /* namespace Player */

View File

@ -29,41 +29,41 @@ void AACRtpEncoder::inputFrame(const Frame::Ptr &frame) {
char *ptr = (char *) pcData;
int iSize = iLen;
while (iSize > 0) {
if (iSize <= m_ui32MtuSize - 20) {
m_aucSectionBuf[0] = 0;
m_aucSectionBuf[1] = 16;
m_aucSectionBuf[2] = iLen >> 5;
m_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(m_aucSectionBuf + 4, ptr, iSize);
makeAACRtp(m_aucSectionBuf, iSize + 4, true, uiStamp);
if (iSize <= _ui32MtuSize - 20) {
_aucSectionBuf[0] = 0;
_aucSectionBuf[1] = 16;
_aucSectionBuf[2] = iLen >> 5;
_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(_aucSectionBuf + 4, ptr, iSize);
makeAACRtp(_aucSectionBuf, iSize + 4, true, uiStamp);
break;
}
m_aucSectionBuf[0] = 0;
m_aucSectionBuf[1] = 16;
m_aucSectionBuf[2] = (iLen) >> 5;
m_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(m_aucSectionBuf + 4, ptr, m_ui32MtuSize - 20);
makeAACRtp(m_aucSectionBuf, m_ui32MtuSize - 16, false, uiStamp);
ptr += (m_ui32MtuSize - 20);
iSize -= (m_ui32MtuSize - 20);
_aucSectionBuf[0] = 0;
_aucSectionBuf[1] = 16;
_aucSectionBuf[2] = (iLen) >> 5;
_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(_aucSectionBuf + 4, ptr, _ui32MtuSize - 20);
makeAACRtp(_aucSectionBuf, _ui32MtuSize - 16, false, uiStamp);
ptr += (_ui32MtuSize - 20);
iSize -= (_ui32MtuSize - 20);
}
}
void AACRtpEncoder::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp) {
uint16_t u16RtpLen = uiLen + 12;
m_ui32TimeStamp = (m_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(m_ui32TimeStamp);
uint16_t sq = htons(m_ui16Sequence);
uint32_t sc = htonl(m_ui32Ssrc);
_ui32TimeStamp = (_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(_ui32TimeStamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
auto pRtppkt = ResourcePoolHelper<RtpPacket>::obtainObj();
auto &rtppkt = *pRtppkt;
unsigned char *pucRtp = rtppkt.payload;
pucRtp[0] = '$';
pucRtp[1] = m_ui8Interleaved;
pucRtp[1] = _ui8Interleaved;
pucRtp[2] = u16RtpLen >> 8;
pucRtp[3] = u16RtpLen & 0x00FF;
pucRtp[4] = 0x80;
pucRtp[5] = (bMark << 7) | m_ui8PlayloadType;
pucRtp[5] = (bMark << 7) | _ui8PlayloadType;
memcpy(&pucRtp[6], &sq, 2);
memcpy(&pucRtp[8], &ts, 4);
//ssrc
@ -71,24 +71,24 @@ void AACRtpEncoder::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark
//playload
memcpy(&pucRtp[16], pData, uiLen);
rtppkt.PT = m_ui8PlayloadType;
rtppkt.interleaved = m_ui8Interleaved;
rtppkt.PT = _ui8PlayloadType;
rtppkt.interleaved = _ui8Interleaved;
rtppkt.mark = bMark;
rtppkt.length = uiLen + 16;
rtppkt.sequence = m_ui16Sequence;
rtppkt.timeStamp = m_ui32TimeStamp;
rtppkt.ssrc = m_ui32Ssrc;
rtppkt.sequence = _ui16Sequence;
rtppkt.timeStamp = _ui32TimeStamp;
rtppkt.ssrc = _ui32Ssrc;
rtppkt.type = TrackAudio;
rtppkt.offset = 16;
RtpCodec::inputRtp(pRtppkt, false);
m_ui16Sequence++;
_ui16Sequence++;
}
/////////////////////////////////////////////////////////////////////////////////////
AACRtpDecoder::AACRtpDecoder(uint32_t ui32SampleRate) {
m_adts = obtainFrame();
m_sampleRate = ui32SampleRate;
_adts = obtainFrame();
_sampleRate = ui32SampleRate;
}
AACFrame::Ptr AACRtpDecoder::obtainFrame() {
@ -103,18 +103,18 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
RtpCodec::inputRtp(rtppack, false);
int length = rtppack->length - rtppack->offset;
if (m_adts->aac_frame_length + length - 4 > sizeof(AACFrame::buffer)) {
m_adts->aac_frame_length = 7;
if (_adts->aac_frame_length + length - 4 > sizeof(AACFrame::buffer)) {
_adts->aac_frame_length = 7;
WarnL << "aac负载数据太长";
return false;
}
memcpy(m_adts->buffer + m_adts->aac_frame_length, rtppack->payload + rtppack->offset + 4, length - 4);
m_adts->aac_frame_length += (length - 4);
memcpy(_adts->buffer + _adts->aac_frame_length, rtppack->payload + rtppack->offset + 4, length - 4);
_adts->aac_frame_length += (length - 4);
if (rtppack->mark == true) {
m_adts->sequence = rtppack->sequence;
m_adts->timeStamp = rtppack->timeStamp * (1000.0 / m_sampleRate);
writeAdtsHeader(*m_adts, m_adts->buffer);
onGetAAC(m_adts);
_adts->sequence = rtppack->sequence;
_adts->timeStamp = rtppack->timeStamp * (1000.0 / _sampleRate);
writeAdtsHeader(*_adts, _adts->buffer);
onGetAAC(_adts);
}
return false;
}
@ -122,7 +122,7 @@ bool AACRtpDecoder::inputRtp(const RtpPacket::Ptr &rtppack, bool key_pos) {
void AACRtpDecoder::onGetAAC(const AACFrame::Ptr &frame) {
//写入环形缓存
RtpCodec::inputFrame(frame);
m_adts = obtainFrame();
_adts = obtainFrame();
}

View File

@ -38,8 +38,8 @@ private:
void onGetAAC(const AACFrame::Ptr &frame);
AACFrame::Ptr obtainFrame();
private:
AACFrame::Ptr m_adts;
uint32_t m_sampleRate;
AACFrame::Ptr _adts;
uint32_t _sampleRate;
};
@ -72,7 +72,7 @@ public:
private:
void makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
private:
unsigned char m_aucSectionBuf[1600];
unsigned char _aucSectionBuf[1600];
};

View File

@ -6,7 +6,7 @@
H264RtpDecoder::H264RtpDecoder() {
m_h264frame = obtainFrame();
_h264frame = obtainFrame();
}
H264Frame::Ptr H264RtpDecoder::obtainFrame() {
@ -40,13 +40,13 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if (nal.type >= 0 && nal.type < 24) {
//a full frame
m_h264frame->buffer.assign("\x0\x0\x0\x1", 4);
m_h264frame->buffer.append((char *)frame, length);
m_h264frame->type = nal.type;
m_h264frame->timeStamp = rtppack->timeStamp / 90;
m_h264frame->sequence = rtppack->sequence;
auto isIDR = m_h264frame->type == 5;
onGetH264(m_h264frame);
_h264frame->buffer.assign("\x0\x0\x0\x1", 4);
_h264frame->buffer.append((char *)frame, length);
_h264frame->type = nal.type;
_h264frame->timeStamp = rtppack->timeStamp / 90;
_h264frame->sequence = rtppack->sequence;
auto isIDR = _h264frame->type == 5;
onGetH264(_h264frame);
return (isIDR); //i frame
}
@ -57,31 +57,31 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
if (fu.S == 1) {
//FU-A start
char tmp = (nal.forbidden_zero_bit << 7 | nal.nal_ref_idc << 5 | fu.type);
m_h264frame->buffer.assign("\x0\x0\x0\x1", 4);
m_h264frame->buffer.push_back(tmp);
m_h264frame->buffer.append((char *)frame + 2, length - 2);
m_h264frame->type = fu.type;
m_h264frame->timeStamp = rtppack->timeStamp / 90;
m_h264frame->sequence = rtppack->sequence;
return (m_h264frame->type == 5); //i frame
_h264frame->buffer.assign("\x0\x0\x0\x1", 4);
_h264frame->buffer.push_back(tmp);
_h264frame->buffer.append((char *)frame + 2, length - 2);
_h264frame->type = fu.type;
_h264frame->timeStamp = rtppack->timeStamp / 90;
_h264frame->sequence = rtppack->sequence;
return (_h264frame->type == 5); //i frame
}
if (rtppack->sequence != (uint16_t)(m_h264frame->sequence + 1)) {
m_h264frame->buffer.clear();
WarnL << "丢包,帧废弃:" << rtppack->sequence << "," << m_h264frame->sequence;
if (rtppack->sequence != (uint16_t)(_h264frame->sequence + 1)) {
_h264frame->buffer.clear();
WarnL << "丢包,帧废弃:" << rtppack->sequence << "," << _h264frame->sequence;
return false;
}
m_h264frame->sequence = rtppack->sequence;
_h264frame->sequence = rtppack->sequence;
if (fu.E == 1) {
//FU-A end
m_h264frame->buffer.append((char *)frame + 2, length - 2);
m_h264frame->timeStamp = rtppack->timeStamp / 90;
auto isIDR = m_h264frame->type == 5;
onGetH264(m_h264frame);
_h264frame->buffer.append((char *)frame + 2, length - 2);
_h264frame->timeStamp = rtppack->timeStamp / 90;
auto isIDR = _h264frame->type == 5;
onGetH264(_h264frame);
return isIDR;
}
//FU-A mid
m_h264frame->buffer.append((char *)frame + 2, length - 2);
_h264frame->buffer.append((char *)frame + 2, length - 2);
return false;
}
@ -100,7 +100,7 @@ bool H264RtpDecoder::decodeRtp(const RtpPacket::Ptr &rtppack) {
void H264RtpDecoder::onGetH264(const H264Frame::Ptr &frame) {
//写入环形缓存
RtpCodec::inputFrame(frame);
m_h264frame = obtainFrame();
_h264frame = obtainFrame();
}
@ -127,7 +127,7 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
auto iLen = frame->size() - frame->prefixSize();
uiStamp %= cycleMS;
int iSize = m_ui32MtuSize - 2;
int iSize = _ui32MtuSize - 2;
if (iLen > iSize) { //超过MTU
const unsigned char s_e_r_Start = 0x80;
const unsigned char s_e_r_Mid = 0x00;
@ -156,11 +156,11 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
s_e_r_type = s_e_r_Mid + naluType;
}
}
memcpy(m_aucSectionBuf, &f_nri_type, 1);
memcpy(m_aucSectionBuf + 1, &s_e_r_type, 1);
memcpy(m_aucSectionBuf + 2, (unsigned char *) pcData + nOffset, iSize);
memcpy(_aucSectionBuf, &f_nri_type, 1);
memcpy(_aucSectionBuf + 1, &s_e_r_type, 1);
memcpy(_aucSectionBuf + 2, (unsigned char *) pcData + nOffset, iSize);
nOffset += iSize;
makeH264Rtp(m_aucSectionBuf, iSize + 2, mark, uiStamp);
makeH264Rtp(_aucSectionBuf, iSize + 2, mark, uiStamp);
}
} else {
makeH264Rtp(pcData, iLen, true, uiStamp);
@ -169,19 +169,19 @@ void H264RtpEncoder::inputFrame(const Frame::Ptr &frame) {
void H264RtpEncoder::makeH264Rtp(const void* data, unsigned int len, bool mark, uint32_t uiStamp) {
uint16_t ui16RtpLen = len + 12;
m_ui32TimeStamp = (m_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(m_ui32TimeStamp);
uint16_t sq = htons(m_ui16Sequence);
uint32_t sc = htonl(m_ui32Ssrc);
_ui32TimeStamp = (_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(_ui32TimeStamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
auto rtppkt = ResourcePoolHelper<RtpPacket>::obtainObj();
unsigned char *pucRtp = rtppkt->payload;
pucRtp[0] = '$';
pucRtp[1] = m_ui8Interleaved;
pucRtp[1] = _ui8Interleaved;
pucRtp[2] = ui16RtpLen >> 8;
pucRtp[3] = ui16RtpLen & 0x00FF;
pucRtp[4] = 0x80;
pucRtp[5] = (mark << 7) | m_ui8PlayloadType;
pucRtp[5] = (mark << 7) | _ui8PlayloadType;
memcpy(&pucRtp[6], &sq, 2);
memcpy(&pucRtp[8], &ts, 4);
//ssrc
@ -189,17 +189,17 @@ void H264RtpEncoder::makeH264Rtp(const void* data, unsigned int len, bool mark,
//playload
memcpy(&pucRtp[16], data, len);
rtppkt->PT = m_ui8PlayloadType;
rtppkt->interleaved = m_ui8Interleaved;
rtppkt->PT = _ui8PlayloadType;
rtppkt->interleaved = _ui8Interleaved;
rtppkt->mark = mark;
rtppkt->length = len + 16;
rtppkt->sequence = m_ui16Sequence;
rtppkt->timeStamp = m_ui32TimeStamp;
rtppkt->ssrc = m_ui32Ssrc;
rtppkt->sequence = _ui16Sequence;
rtppkt->timeStamp = _ui32TimeStamp;
rtppkt->ssrc = _ui32Ssrc;
rtppkt->type = TrackVideo;
rtppkt->offset = 16;
uint8_t type = ((uint8_t *) (data))[0] & 0x1F;
RtpCodec::inputRtp(rtppkt,type == 5);
m_ui16Sequence++;
_ui16Sequence++;
}

View File

@ -39,7 +39,7 @@ private:
void onGetH264(const H264Frame::Ptr &frame);
H264Frame::Ptr obtainFrame();
private:
H264Frame::Ptr m_h264frame;
H264Frame::Ptr _h264frame;
};
/**
@ -71,7 +71,7 @@ public:
private:
void makeH264Rtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
private:
unsigned char m_aucSectionBuf[1600];
unsigned char _aucSectionBuf[1600];
};

View File

@ -105,48 +105,48 @@ public:
if(ui32Ssrc == 0){
ui32Ssrc = ((uint64_t)this) & 0xFFFFFFFF;
}
m_ui32Ssrc = ui32Ssrc;
m_ui32SampleRate = ui32SampleRate;
m_ui32MtuSize = ui32MtuSize;
m_ui8PlayloadType = ui8PlayloadType;
m_ui8Interleaved = ui8Interleaved;
_ui32Ssrc = ui32Ssrc;
_ui32SampleRate = ui32SampleRate;
_ui32MtuSize = ui32MtuSize;
_ui8PlayloadType = ui8PlayloadType;
_ui8Interleaved = ui8Interleaved;
}
virtual ~RtpInfo(){}
int getInterleaved() const {
return m_ui8Interleaved;
return _ui8Interleaved;
}
int getPlayloadType() const {
return m_ui8PlayloadType;
return _ui8PlayloadType;
}
int getSampleRate() const {
return m_ui32SampleRate;
return _ui32SampleRate;
}
uint32_t getSsrc() const {
return m_ui32Ssrc;
return _ui32Ssrc;
}
uint16_t getSeqence() const {
return m_ui16Sequence;
return _ui16Sequence;
}
uint32_t getTimestamp() const {
return m_ui32TimeStamp;
return _ui32TimeStamp;
}
uint32_t getMtuSize() const {
return m_ui32MtuSize;
return _ui32MtuSize;
}
protected:
uint32_t m_ui32Ssrc;
uint32_t m_ui32SampleRate;
uint32_t m_ui32MtuSize;
uint8_t m_ui8PlayloadType;
uint8_t m_ui8Interleaved;
uint16_t m_ui16Sequence = 0;
uint32_t m_ui32TimeStamp = 0;
uint32_t _ui32Ssrc;
uint32_t _ui32SampleRate;
uint32_t _ui32MtuSize;
uint8_t _ui8PlayloadType;
uint8_t _ui8Interleaved;
uint16_t _ui16Sequence = 0;
uint32_t _ui32TimeStamp = 0;
};
class RtpCodec : public RtpRing, public FrameRingInterfaceDelegate , public CodecInfo , public ResourcePoolHelper<RtpPacket>{

View File

@ -49,12 +49,12 @@ public:
RtpMaker(const onGetRTP &cb, uint32_t ui32Ssrc, int iMtuSize,int iSampleRate,
uint8_t ui8PlayloadType, uint8_t ui8Interleaved) {
callBack = cb;
m_ui32Ssrc = ui32Ssrc;
m_ui32SampleRate = iSampleRate;
m_iMtuSize = iMtuSize;
m_ui8PlayloadType = ui8PlayloadType;
m_ui8Interleaved = ui8Interleaved;
m_pktPool.setSize(64);
_ui32Ssrc = ui32Ssrc;
_ui32SampleRate = iSampleRate;
_iMtuSize = iMtuSize;
_ui8PlayloadType = ui8PlayloadType;
_ui8Interleaved = ui8Interleaved;
_pktPool.setSize(64);
}
virtual ~RtpMaker() {
}
@ -62,43 +62,43 @@ public:
virtual void makeRtp(const char *pcData, int iDataLen, uint32_t uiStamp)=0;
int getInterleaved() const {
return m_ui8Interleaved;
return _ui8Interleaved;
}
int getPlayloadType() const {
return m_ui8PlayloadType;
return _ui8PlayloadType;
}
int getSampleRate() const {
return m_ui32SampleRate;
return _ui32SampleRate;
}
uint32_t getSsrc() const {
return m_ui32Ssrc;
return _ui32Ssrc;
}
uint16_t getSeqence() const {
return m_ui16Sequence;
return _ui16Sequence;
}
uint32_t getTimestamp() const {
return m_ui32TimeStamp;
return _ui32TimeStamp;
}
protected:
uint32_t m_ui32Ssrc;
uint32_t m_ui32SampleRate;
int m_iMtuSize;
uint8_t m_ui8PlayloadType;
uint8_t m_ui8Interleaved;
uint16_t m_ui16Sequence = 0;
uint32_t m_ui32TimeStamp = 0;
uint32_t _ui32Ssrc;
uint32_t _ui32SampleRate;
int _iMtuSize;
uint8_t _ui8PlayloadType;
uint8_t _ui8Interleaved;
uint16_t _ui16Sequence = 0;
uint32_t _ui32TimeStamp = 0;
virtual void onMakeRtp(const RtpPacket::Ptr &pkt, bool bKeyPos = true) {
callBack(pkt, bKeyPos);
}
inline RtpPacket::Ptr obtainPkt() {
return m_pktPool.obtain();
return _pktPool.obtain();
}
private:
RtspMediaSource::PoolType m_pktPool;
RtspMediaSource::PoolType _pktPool;
onGetRTP callBack;
};

View File

@ -42,42 +42,42 @@ void RtpMaker_AAC::makeRtp(const char *pcData, int iLen, uint32_t uiStamp) {
char *ptr = (char *) pcData;
int iSize = iLen;
while (iSize > 0 ) {
if (iSize <= m_iMtuSize - 20) {
m_aucSectionBuf[0] = 0;
m_aucSectionBuf[1] = 16;
m_aucSectionBuf[2] = iLen >> 5;
m_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(m_aucSectionBuf + 4, ptr, iSize);
makeAACRtp(m_aucSectionBuf, iSize + 4, true, uiStamp);
if (iSize <= _iMtuSize - 20) {
_aucSectionBuf[0] = 0;
_aucSectionBuf[1] = 16;
_aucSectionBuf[2] = iLen >> 5;
_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(_aucSectionBuf + 4, ptr, iSize);
makeAACRtp(_aucSectionBuf, iSize + 4, true, uiStamp);
break;
}
m_aucSectionBuf[0] = 0;
m_aucSectionBuf[1] = 16;
m_aucSectionBuf[2] = (iLen) >> 5;
m_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(m_aucSectionBuf + 4, ptr, m_iMtuSize - 20);
makeAACRtp(m_aucSectionBuf, m_iMtuSize - 16, false, uiStamp);
ptr += (m_iMtuSize - 20);
iSize -= (m_iMtuSize - 20);
_aucSectionBuf[0] = 0;
_aucSectionBuf[1] = 16;
_aucSectionBuf[2] = (iLen) >> 5;
_aucSectionBuf[3] = (iLen & 0x1F) << 3;
memcpy(_aucSectionBuf + 4, ptr, _iMtuSize - 20);
makeAACRtp(_aucSectionBuf, _iMtuSize - 16, false, uiStamp);
ptr += (_iMtuSize - 20);
iSize -= (_iMtuSize - 20);
}
}
inline void RtpMaker_AAC::makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp) {
uint16_t u16RtpLen = uiLen + 12;
m_ui32TimeStamp = (m_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(m_ui32TimeStamp);
uint16_t sq = htons(m_ui16Sequence);
uint32_t sc = htonl(m_ui32Ssrc);
_ui32TimeStamp = (_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(_ui32TimeStamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
auto pRtppkt = obtainPkt();
auto &rtppkt = *(pRtppkt.get());
unsigned char *pucRtp = rtppkt.payload;
pucRtp[0] = '$';
pucRtp[1] = m_ui8Interleaved;
pucRtp[1] = _ui8Interleaved;
pucRtp[2] = u16RtpLen >> 8;
pucRtp[3] = u16RtpLen & 0x00FF;
pucRtp[4] = 0x80;
pucRtp[5] = (bMark << 7) | m_ui8PlayloadType;
pucRtp[5] = (bMark << 7) | _ui8PlayloadType;
memcpy(&pucRtp[6], &sq, 2);
memcpy(&pucRtp[8], &ts, 4);
//ssrc
@ -85,18 +85,18 @@ inline void RtpMaker_AAC::makeAACRtp(const void *pData, unsigned int uiLen, bool
//playload
memcpy(&pucRtp[16], pData, uiLen);
rtppkt.PT = m_ui8PlayloadType;
rtppkt.interleaved = m_ui8Interleaved;
rtppkt.PT = _ui8PlayloadType;
rtppkt.interleaved = _ui8Interleaved;
rtppkt.mark = bMark;
rtppkt.length = uiLen + 16;
rtppkt.sequence = m_ui16Sequence;
rtppkt.timeStamp = m_ui32TimeStamp;
rtppkt.ssrc = m_ui32Ssrc;
rtppkt.sequence = _ui16Sequence;
rtppkt.timeStamp = _ui32TimeStamp;
rtppkt.ssrc = _ui32Ssrc;
rtppkt.type = TrackAudio;
rtppkt.offset = 16;
onMakeRtp(pRtppkt, false);
m_ui16Sequence++;
_ui16Sequence++;
}
} /* namespace RTP */

View File

@ -53,7 +53,7 @@ public:
void makeRtp(const char *pcData, int iDataLen, uint32_t uiStamp) override;
private:
inline void makeAACRtp(const void *pData, unsigned int uiLen, bool bMark, uint32_t uiStamp);
unsigned char m_aucSectionBuf[1600];
unsigned char _aucSectionBuf[1600];
};
} /* namespace RTP */

View File

@ -39,7 +39,7 @@ void RtpMaker_H264::makeRtp(const char* pcData, int iLen, uint32_t uiStamp) {
GET_CONFIG_AND_REGISTER(uint32_t,cycleMS,Config::Rtp::kCycleMS);
uiStamp %= cycleMS;
int iSize = m_iMtuSize - 2;
int iSize = _iMtuSize - 2;
if (iLen > iSize) { //超过MTU
const unsigned char s_e_r_Start = 0x80;
const unsigned char s_e_r_Mid = 0x00;
@ -81,20 +81,20 @@ void RtpMaker_H264::makeRtp(const char* pcData, int iLen, uint32_t uiStamp) {
inline void RtpMaker_H264::makeH264Rtp(const void* data, unsigned int len, bool mark, uint32_t uiStamp) {
uint16_t ui16RtpLen = len + 12;
m_ui32TimeStamp = (m_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(m_ui32TimeStamp);
uint16_t sq = htons(m_ui16Sequence);
uint32_t sc = htonl(m_ui32Ssrc);
_ui32TimeStamp = (_ui32SampleRate / 1000) * uiStamp;
uint32_t ts = htonl(_ui32TimeStamp);
uint16_t sq = htons(_ui16Sequence);
uint32_t sc = htonl(_ui32Ssrc);
auto pRtppkt = obtainPkt();
auto &rtppkt = *(pRtppkt.get());
unsigned char *pucRtp = rtppkt.payload;
pucRtp[0] = '$';
pucRtp[1] = m_ui8Interleaved;
pucRtp[1] = _ui8Interleaved;
pucRtp[2] = ui16RtpLen >> 8;
pucRtp[3] = ui16RtpLen & 0x00FF;
pucRtp[4] = 0x80;
pucRtp[5] = (mark << 7) | m_ui8PlayloadType;
pucRtp[5] = (mark << 7) | _ui8PlayloadType;
memcpy(&pucRtp[6], &sq, 2);
memcpy(&pucRtp[8], &ts, 4);
//ssrc
@ -102,19 +102,19 @@ inline void RtpMaker_H264::makeH264Rtp(const void* data, unsigned int len, bool
//playload
memcpy(&pucRtp[16], data, len);
rtppkt.PT = m_ui8PlayloadType;
rtppkt.interleaved = m_ui8Interleaved;
rtppkt.PT = _ui8PlayloadType;
rtppkt.interleaved = _ui8Interleaved;
rtppkt.mark = mark;
rtppkt.length = len + 16;
rtppkt.sequence = m_ui16Sequence;
rtppkt.timeStamp = m_ui32TimeStamp;
rtppkt.ssrc = m_ui32Ssrc;
rtppkt.sequence = _ui16Sequence;
rtppkt.timeStamp = _ui32TimeStamp;
rtppkt.ssrc = _ui32Ssrc;
rtppkt.type = TrackVideo;
rtppkt.offset = 16;
uint8_t type = ((uint8_t *) (data))[0] & 0x1F;
onMakeRtp(pRtppkt, type == 5);
m_ui16Sequence++;
_ui16Sequence++;
//InfoL<<timeStamp<<" "<<time<<" "<<sampleRate;
}

View File

@ -43,8 +43,8 @@ void FlvMuxer::start(const RtmpMediaSource::Ptr &media) {
}
void FlvMuxer::onWriteFlvHeader(const RtmpMediaSource::Ptr &mediaSrc) {
m_previousTagSize = 0;
CLEAR_ARR(m_aui32FirstStamp);
_previousTagSize = 0;
CLEAR_ARR(_aui32FirstStamp);
//发送flv文件头
char flv_file_header[] = "FLV\x1\x5\x0\x0\x0\x9"; // have audio and have video
@ -118,7 +118,7 @@ private:
void FlvMuxer::onWriteFlvTag(const RtmpPacket::Ptr &pkt, uint32_t ui32TimeStamp) {
auto size = htonl(m_previousTagSize);
auto size = htonl(_previousTagSize);
onWrite((char *)&size,4);//onWrite PreviousTagSize
RtmpTagHeader header;
header.type = pkt->typeId;
@ -127,11 +127,11 @@ void FlvMuxer::onWriteFlvTag(const RtmpPacket::Ptr &pkt, uint32_t ui32TimeStamp)
set_be24(header.timestamp,ui32TimeStamp & 0xFFFFFF);
onWrite((char *)&header, sizeof(header));//onWrite tag header
onWrite(std::make_shared<BufferRtmp>(pkt));//onWrite tag data
m_previousTagSize += (pkt->strBuf.size() + sizeof(header));
_previousTagSize += (pkt->strBuf.size() + sizeof(header));
}
void FlvMuxer::onWriteFlvTag(uint8_t ui8Type, const std::string &strBuf, uint32_t ui32TimeStamp) {
auto size = htonl(m_previousTagSize);
auto size = htonl(_previousTagSize);
onWrite((char *)&size,4);//onWrite PreviousTagSize
RtmpTagHeader header;
header.type = ui8Type;
@ -140,12 +140,12 @@ void FlvMuxer::onWriteFlvTag(uint8_t ui8Type, const std::string &strBuf, uint32_
set_be24(header.timestamp,ui32TimeStamp & 0xFFFFFF);
onWrite((char *)&header, sizeof(header));//onWrite tag header
onWrite(std::make_shared<BufferString>(strBuf));//onWrite tag data
m_previousTagSize += (strBuf.size() + sizeof(header));
_previousTagSize += (strBuf.size() + sizeof(header));
}
void FlvMuxer::onWriteRtmp(const RtmpPacket::Ptr &pkt) {
auto modifiedStamp = pkt->timeStamp;
auto &firstStamp = m_aui32FirstStamp[pkt->typeId % 2];
auto &firstStamp = _aui32FirstStamp[pkt->typeId % 2];
if(!firstStamp){
firstStamp = modifiedStamp;
}
@ -154,7 +154,7 @@ void FlvMuxer::onWriteRtmp(const RtmpPacket::Ptr &pkt) {
modifiedStamp -= firstStamp;
}else{
//发生回环,重新计算时间戳增量
CLEAR_ARR(m_aui32FirstStamp);
CLEAR_ARR(_aui32FirstStamp);
modifiedStamp = 0;
}
onWriteFlvTag(pkt, modifiedStamp);

View File

@ -33,8 +33,8 @@ private:
void onWriteFlvTag(uint8_t ui8Type, const std::string &strBuf, uint32_t ui32TimeStamp);
private:
RtmpMediaSource::RingType::RingReader::Ptr _ring_reader;
uint32_t m_aui32FirstStamp[2] = {0};
uint32_t m_previousTagSize = 0;
uint32_t _aui32FirstStamp[2] = {0};
uint32_t _previousTagSize = 0;
};
class FlvRecorder : public FlvMuxer , public std::enable_shared_from_this<FlvRecorder>{

View File

@ -60,66 +60,66 @@ public:
RtmpMediaSource(const string &vhost,const string &strApp, const string &strId) :
MediaSource(RTMP_SCHEMA,vhost,strApp,strId),
m_pRing(new RingBuffer<RtmpPacket::Ptr>()) {
_pRing(new RingBuffer<RtmpPacket::Ptr>()) {
}
virtual ~RtmpMediaSource() {}
const RingType::Ptr &getRing() const {
//获取媒体源的rtp环形缓冲
return m_pRing;
return _pRing;
}
const AMFValue &getMetaData() const {
lock_guard<recursive_mutex> lock(m_mtxMap);
return m_metadata;
lock_guard<recursive_mutex> lock(_mtxMap);
return _metadata;
}
template<typename FUN>
void getConfigFrame(const FUN &f) {
lock_guard<recursive_mutex> lock(m_mtxMap);
for (auto &pr : m_mapCfgFrame) {
lock_guard<recursive_mutex> lock(_mtxMap);
for (auto &pr : _mapCfgFrame) {
f(pr.second);
}
}
virtual void onGetMetaData(const AMFValue &_metadata) {
lock_guard<recursive_mutex> lock(m_mtxMap);
m_metadata = _metadata;
RtmpParser parser(_metadata);
m_iCfgFrameSize = parser.getTracks().size();
virtual void onGetMetaData(const AMFValue &metadata) {
lock_guard<recursive_mutex> lock(_mtxMap);
_metadata = metadata;
RtmpParser parser(metadata);
_iCfgFrameSize = parser.getTracks().size();
if(ready()){
MediaSource::regist();
m_bRegisted = true;
_bRegisted = true;
} else{
m_bAsyncRegist = true;
_bAsyncRegist = true;
}
}
virtual void onGetMedia(const RtmpPacket::Ptr &pkt) {
lock_guard<recursive_mutex> lock(m_mtxMap);
lock_guard<recursive_mutex> lock(_mtxMap);
if (pkt->isCfgFrame()) {
m_mapCfgFrame.emplace(pkt->typeId, pkt);
_mapCfgFrame.emplace(pkt->typeId, pkt);
if(m_bAsyncRegist && !m_bRegisted && m_mapCfgFrame.size() == m_iCfgFrameSize){
m_bAsyncRegist = false;
if(_bAsyncRegist && !_bRegisted && _mapCfgFrame.size() == _iCfgFrameSize){
_bAsyncRegist = false;
MediaSource::regist();
m_bRegisted = true;
_bRegisted = true;
}
}
m_pRing->write(pkt,pkt->isVideoKeyFrame());
_pRing->write(pkt,pkt->isVideoKeyFrame());
}
private:
bool ready(){
lock_guard<recursive_mutex> lock(m_mtxMap);
return m_iCfgFrameSize != -1 && m_iCfgFrameSize == m_mapCfgFrame.size();
lock_guard<recursive_mutex> lock(_mtxMap);
return _iCfgFrameSize != -1 && _iCfgFrameSize == _mapCfgFrame.size();
}
protected:
AMFValue m_metadata;
unordered_map<int, RtmpPacket::Ptr> m_mapCfgFrame;
mutable recursive_mutex m_mtxMap;
RingBuffer<RtmpPacket::Ptr>::Ptr m_pRing; //rtp环形缓冲
int m_iCfgFrameSize = -1;
bool m_bAsyncRegist = false;
bool m_bRegisted = false;
AMFValue _metadata;
unordered_map<int, RtmpPacket::Ptr> _mapCfgFrame;
mutable recursive_mutex _mtxMap;
RingBuffer<RtmpPacket::Ptr>::Ptr _pRing; //rtp环形缓冲
int _iCfgFrameSize = -1;
bool _bAsyncRegist = false;
bool _bRegisted = false;
};
} /* namespace Rtmp */

View File

@ -36,13 +36,13 @@ RtmpParser::RtmpParser(const AMFValue &val) {
if (videoCodec.type() == AMF_STRING) {
if (videoCodec.as_string() == "avc1") {
//h264
m_iVideoCodecID = H264_CODEC_ID;
_iVideoCodecID = H264_CODEC_ID;
} else {
InfoL << "不支持RTMP视频格式:" << videoCodec.as_string();
}
}else if (videoCodec.type() != AMF_NULL){
m_iVideoCodecID = videoCodec.as_integer();
if (m_iVideoCodecID != H264_CODEC_ID) {
_iVideoCodecID = videoCodec.as_integer();
if (_iVideoCodecID != H264_CODEC_ID) {
InfoL << "不支持RTMP视频格式:" << videoCodec.as_integer();
}
}
@ -50,13 +50,13 @@ RtmpParser::RtmpParser(const AMFValue &val) {
if (audioCodec.type() == AMF_STRING) {
if (audioCodec.as_string() == "mp4a") {
//aac
m_iAudioCodecID = AAC_CODEC_ID;
_iAudioCodecID = AAC_CODEC_ID;
} else {
InfoL << "不支持RTMP音频格式:" << audioCodec.as_string();
}
}else if (audioCodec.type() != AMF_NULL) {
m_iAudioCodecID = audioCodec.as_integer();
if (m_iAudioCodecID != AAC_CODEC_ID) {
_iAudioCodecID = audioCodec.as_integer();
if (_iAudioCodecID != AAC_CODEC_ID) {
InfoL << "不支持RTMP音频格式:" << audioCodec.as_integer();
}
}
@ -69,28 +69,28 @@ RtmpParser::~RtmpParser() {
bool RtmpParser::inputRtmp(const RtmpPacket::Ptr &pkt) {
switch (pkt->typeId) {
case MSG_VIDEO:{
if(m_iVideoCodecID == 0){
if(_iVideoCodecID == 0){
//未初始化视频
m_iVideoCodecID = pkt->getMediaType();
if(m_iVideoCodecID != H264_CODEC_ID){
InfoL << "不支持RTMP视频格式:" << m_iVideoCodecID;
_iVideoCodecID = pkt->getMediaType();
if(_iVideoCodecID != H264_CODEC_ID){
InfoL << "不支持RTMP视频格式:" << _iVideoCodecID;
}
}
if(m_iVideoCodecID == H264_CODEC_ID){
if(_iVideoCodecID == H264_CODEC_ID){
return inputVideo(pkt);
}
return false;
}
case MSG_AUDIO: {
if(m_iAudioCodecID == 0){
if(_iAudioCodecID == 0){
//未初始化音频
m_iAudioCodecID = pkt->getMediaType();
if(m_iAudioCodecID != AAC_CODEC_ID){
InfoL << "不支持RTMP音频格式:" << m_iAudioCodecID;
_iAudioCodecID = pkt->getMediaType();
if(_iAudioCodecID != AAC_CODEC_ID){
InfoL << "不支持RTMP音频格式:" << _iAudioCodecID;
}
}
if (m_iAudioCodecID == AAC_CODEC_ID) {
if (_iAudioCodecID == AAC_CODEC_ID) {
return inputAudio(pkt);
}
return false;
@ -104,20 +104,20 @@ bool RtmpParser::inputRtmp(const RtmpPacket::Ptr &pkt) {
inline bool RtmpParser::inputVideo(const RtmpPacket::Ptr &pkt) {
if (pkt->isCfgFrame()) {
//WarnL << " got h264 cfg";
if (m_strSPS.size()) {
if (_strSPS.size()) {
return false;
}
m_strSPS.assign("\x00\x00\x00\x01", 4);
m_strSPS.append(pkt->getH264SPS());
_strSPS.assign("\x00\x00\x00\x01", 4);
_strSPS.append(pkt->getH264SPS());
m_strPPS.assign("\x00\x00\x00\x01", 4);
m_strPPS.append(pkt->getH264PPS());
_strPPS.assign("\x00\x00\x00\x01", 4);
_strPPS.append(pkt->getH264PPS());
getAVCInfo(pkt->getH264SPS(), m_iVideoWidth, m_iVideoHeight, m_fVideoFps);
getAVCInfo(pkt->getH264SPS(), _iVideoWidth, _iVideoHeight, _fVideoFps);
return false;
}
if (m_strSPS.size()) {
if (_strSPS.size()) {
uint32_t iTotalLen = pkt->strBuf.size();
uint32_t iOffset = 5;
while(iOffset + 4 < iTotalLen){
@ -137,8 +137,8 @@ inline bool RtmpParser::inputVideo(const RtmpPacket::Ptr &pkt) {
inline void RtmpParser::_onGetH264(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
switch (pcData[0] & 0x1F) {
case 5: {
onGetH264(m_strSPS.data() + 4, m_strSPS.length() - 4, ui32TimeStamp);
onGetH264(m_strPPS.data() + 4, m_strPPS.length() - 4, ui32TimeStamp);
onGetH264(_strSPS.data() + 4, _strSPS.length() - 4, ui32TimeStamp);
onGetH264(_strPPS.data() + 4, _strPPS.length() - 4, ui32TimeStamp);
}
case 1: {
onGetH264(pcData, iLen, ui32TimeStamp);
@ -150,82 +150,82 @@ inline void RtmpParser::_onGetH264(const char* pcData, int iLen, uint32_t ui32Ti
}
}
inline void RtmpParser::onGetH264(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
m_h264frame.type = pcData[0] & 0x1F;
m_h264frame.timeStamp = ui32TimeStamp;
m_h264frame.buffer.assign("\x0\x0\x0\x1", 4); //添加264头
m_h264frame.buffer.append(pcData, iLen);
_h264frame.type = pcData[0] & 0x1F;
_h264frame.timeStamp = ui32TimeStamp;
_h264frame.buffer.assign("\x0\x0\x0\x1", 4); //添加264头
_h264frame.buffer.append(pcData, iLen);
{
lock_guard<recursive_mutex> lck(m_mtxCB);
lock_guard<recursive_mutex> lck(_mtxCB);
if (onVideo) {
onVideo(m_h264frame);
onVideo(_h264frame);
}
}
m_h264frame.buffer.clear();
_h264frame.buffer.clear();
}
inline bool RtmpParser::inputAudio(const RtmpPacket::Ptr &pkt) {
if (pkt->isCfgFrame()) {
if (m_strAudioCfg.size()) {
if (_strAudioCfg.size()) {
return false;
}
m_strAudioCfg = pkt->getAacCfg();
m_iSampleBit = pkt->getAudioSampleBit();
makeAdtsHeader(m_strAudioCfg,m_adts);
getAACInfo(m_adts, m_iSampleRate, m_iChannel);
_strAudioCfg = pkt->getAacCfg();
_iSampleBit = pkt->getAudioSampleBit();
makeAdtsHeader(_strAudioCfg,_adts);
getAACInfo(_adts, _iSampleRate, _iChannel);
return false;
}
if (m_strAudioCfg.size()) {
if (_strAudioCfg.size()) {
onGetAAC(pkt->strBuf.data() + 2, pkt->strBuf.size() - 2, pkt->timeStamp);
}
return false;
}
inline void RtmpParser::onGetAAC(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
if(iLen + 7 > sizeof(m_adts.buffer)){
if(iLen + 7 > sizeof(_adts.buffer)){
WarnL << "Illegal adts data, exceeding the length limit.";
return;
}
//添加adts头
memcpy(m_adts.buffer + 7, pcData, iLen);
m_adts.aac_frame_length = 7 + iLen;
m_adts.timeStamp = ui32TimeStamp;
writeAdtsHeader(m_adts, m_adts.buffer);
memcpy(_adts.buffer + 7, pcData, iLen);
_adts.aac_frame_length = 7 + iLen;
_adts.timeStamp = ui32TimeStamp;
writeAdtsHeader(_adts, _adts.buffer);
{
lock_guard<recursive_mutex> lck(m_mtxCB);
lock_guard<recursive_mutex> lck(_mtxCB);
if (onAudio) {
onAudio(m_adts);
onAudio(_adts);
}
}
m_adts.aac_frame_length = 7;
_adts.aac_frame_length = 7;
}
inline void RtmpParser::onCheckMedia(const AMFValue& obj) {
obj.object_for_each([&](const string &key ,const AMFValue& val) {
if(key == "duration") {
m_fDuration = val.as_number();
_fDuration = val.as_number();
return;
}
if(key == "width") {
m_iVideoWidth = val.as_number();
_iVideoWidth = val.as_number();
return;
}
if(key == "height") {
m_iVideoHeight = val.as_number();
_iVideoHeight = val.as_number();
return;
}
if(key == "framerate") {
m_fVideoFps = val.as_number();
_fVideoFps = val.as_number();
return;
}
if(key == "audiosamplerate") {
m_iSampleRate = val.as_number();
_iSampleRate = val.as_number();
return;
}
if(key == "audiosamplesize") {
m_iSampleBit = val.as_number();
_iSampleBit = val.as_number();
return;
}
if(key == "stereo") {
m_iChannel = val.as_boolean() ? 2 :1;
_iChannel = val.as_boolean() ? 2 :1;
return;
}
});

View File

@ -54,19 +54,19 @@ public:
bool inputRtmp(const RtmpPacket::Ptr &pkt);
bool isInited() const override{
if((m_iAudioCodecID | m_iVideoCodecID) == 0){
if((_iAudioCodecID | _iVideoCodecID) == 0){
//音视频codec_id都未获取到说明还未初始化成功
return false;
}
if((m_iAudioCodecID & m_iVideoCodecID) == 0 && m_ticker.elapsedTime() < 300){
if((_iAudioCodecID & _iVideoCodecID) == 0 && _ticker.elapsedTime() < 300){
//音视频codec_id有其一未获取到,且最少分析300ms才能断定没有音频或视频
return false;
}
if (m_iAudioCodecID && !m_strAudioCfg.size()) {
if (_iAudioCodecID && !_strAudioCfg.size()) {
//如果音频是aac但是还未获取aac config ,则未初始化成功
return false;
}
if (m_iVideoCodecID && !m_strSPS.size()) {
if (_iVideoCodecID && !_strSPS.size()) {
//如果视频是h264但是还未获取sps ,则未初始化成功
return false;
}
@ -74,7 +74,7 @@ public:
return true;
}
float getDuration() const override{
return m_fDuration;
return _fDuration;
}
private:
inline void onCheckMedia(const AMFValue &obj);
@ -86,28 +86,28 @@ private:
inline void onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
inline void onGetAAC(const char *pcData, int iLen, uint32_t ui32TimeStamp);
//video
H264Frame m_h264frame;
H264Frame _h264frame;
//aduio
AACFrame m_adts;
AACFrame _adts;
int m_iSampleRate = 44100;
int m_iSampleBit = 16;
int m_iChannel = 1;
int _iSampleRate = 44100;
int _iSampleBit = 16;
int _iChannel = 1;
string m_strSPS;
string m_strPPS;
string m_strAudioCfg;
int m_iVideoWidth = 0;
int m_iVideoHeight = 0;
float m_fVideoFps = 0;
string _strSPS;
string _strPPS;
string _strAudioCfg;
int _iVideoWidth = 0;
int _iVideoHeight = 0;
float _fVideoFps = 0;
//音视频codec_id初始为0代表尚未获取到
int m_iAudioCodecID = 0;
int m_iVideoCodecID = 0;
float m_fDuration = 0;
mutable Ticker m_ticker;
int _iAudioCodecID = 0;
int _iVideoCodecID = 0;
float _fDuration = 0;
mutable Ticker _ticker;
function<void(const H264Frame &frame)> onVideo;
function<void(const AACFrame &frame)> onAudio;
recursive_mutex m_mtxCB;
recursive_mutex _mtxCB;
};

View File

@ -53,24 +53,24 @@ RtmpPlayer::~RtmpPlayer() {
}
void RtmpPlayer::teardown() {
if (alive()) {
m_strApp.clear();
m_strStream.clear();
m_strTcUrl.clear();
_strApp.clear();
_strStream.clear();
_strTcUrl.clear();
{
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
m_mapOnResultCB.clear();
lock_guard<recursive_mutex> lck(_mtxOnResultCB);
_mapOnResultCB.clear();
}
{
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
m_dqOnStatusCB.clear();
lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
_dqOnStatusCB.clear();
}
m_pBeatTimer.reset();
m_pPlayTimer.reset();
m_pMediaTimer.reset();
m_fSeekTo = 0;
CLEAR_ARR(m_adFistStamp);
CLEAR_ARR(m_adNowStamp);
_pBeatTimer.reset();
_pPlayTimer.reset();
_pMediaTimer.reset();
_fSeekTo = 0;
CLEAR_ARR(_adFistStamp);
CLEAR_ARR(_adNowStamp);
reset();
shutdown();
}
@ -78,15 +78,15 @@ void RtmpPlayer::teardown() {
void RtmpPlayer::play(const char* strUrl) {
teardown();
string strHost = FindField(strUrl, "://", "/");
m_strApp = FindField(strUrl, (strHost + "/").data(), "/");
m_strStream = FindField(strUrl, (strHost + "/" + m_strApp + "/").data(), NULL);
m_strTcUrl = string("rtmp://") + strHost + "/" + m_strApp;
_strApp = FindField(strUrl, (strHost + "/").data(), "/");
_strStream = FindField(strUrl, (strHost + "/" + _strApp + "/").data(), NULL);
_strTcUrl = string("rtmp://") + strHost + "/" + _strApp;
if (!m_strApp.size() || !m_strStream.size()) {
if (!_strApp.size() || !_strStream.size()) {
_onPlayResult(SockException(Err_other,"rtmp url非法"));
return;
}
DebugL << strHost << " " << m_strApp << " " << m_strStream;
DebugL << strHost << " " << _strApp << " " << _strStream;
auto iPort = atoi(FindField(strHost.c_str(), ":", NULL).c_str());
if (iPort <= 0) {
@ -111,7 +111,7 @@ void RtmpPlayer::onConnect(const SockException &err){
}
weak_ptr<RtmpPlayer> weakSelf= dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
m_pPlayTimer.reset( new Timer(10, [weakSelf]() {
_pPlayTimer.reset( new Timer(10, [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return false;
@ -145,8 +145,8 @@ void RtmpPlayer::pause(bool bPause) {
inline void RtmpPlayer::send_connect() {
AMFValue obj(AMF_OBJECT);
obj.set("app", m_strApp);
obj.set("tcUrl", m_strTcUrl);
obj.set("app", _strApp);
obj.set("tcUrl", _strTcUrl);
//未使用代理
obj.set("fpad", false);
//参考librtmp,什么作用?
@ -177,14 +177,14 @@ inline void RtmpPlayer::send_createStream() {
addOnResultCB([this](AMFDecoder &dec){
//TraceL << "createStream result";
dec.load<AMFValue>();
m_ui32StreamId = dec.load<int>();
_ui32StreamId = dec.load<int>();
send_play();
});
}
inline void RtmpPlayer::send_play() {
AMFEncoder enc;
enc << "play" << ++m_iReqID << nullptr << m_strStream << (double)m_ui32StreamId;
enc << "play" << ++_iReqID << nullptr << _strStream << (double)_ui32StreamId;
sendRequest(MSG_CMD, enc.data());
auto fun = [this](AMFValue &val){
//TraceL << "play onStatus";
@ -200,7 +200,7 @@ inline void RtmpPlayer::send_play() {
inline void RtmpPlayer::send_pause(bool bPause) {
AMFEncoder enc;
enc << "pause" << ++m_iReqID << nullptr << bPause;
enc << "pause" << ++_iReqID << nullptr << bPause;
sendRequest(MSG_CMD, enc.data());
auto fun = [this,bPause](AMFValue &val){
//TraceL << "pause onStatus";
@ -211,21 +211,21 @@ inline void RtmpPlayer::send_pause(bool bPause) {
throw std::runtime_error(StrPrinter <<"pause 恢复播放失败:" << level << " " << code << endl);
}
}else{
m_bPaused = bPause;
_bPaused = bPause;
if(!bPause){
_onPlayResult(SockException(Err_success, "rtmp resum success"));
}else{
//暂停播放
m_pMediaTimer.reset();
_pMediaTimer.reset();
}
}
};
addOnStatusCB(fun);
m_pBeatTimer.reset();
_pBeatTimer.reset();
if(bPause){
weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
m_pBeatTimer.reset(new Timer(3,[weakSelf](){
_pBeatTimer.reset(new Timer(3,[weakSelf](){
auto strongSelf = weakSelf.lock();
if (!strongSelf){
return false;
@ -239,11 +239,11 @@ inline void RtmpPlayer::send_pause(bool bPause) {
void RtmpPlayer::onCmd_result(AMFDecoder &dec){
auto iReqId = dec.load<int>();
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
auto it = m_mapOnResultCB.find(iReqId);
if(it != m_mapOnResultCB.end()){
lock_guard<recursive_mutex> lck(_mtxOnResultCB);
auto it = _mapOnResultCB.find(iReqId);
if(it != _mapOnResultCB.end()){
it->second(dec);
m_mapOnResultCB.erase(it);
_mapOnResultCB.erase(it);
}else{
WarnL << "unhandled _result";
}
@ -260,10 +260,10 @@ void RtmpPlayer::onCmd_onStatus(AMFDecoder &dec) {
throw std::runtime_error("onStatus:the result object was not found");
}
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
if(m_dqOnStatusCB.size()){
m_dqOnStatusCB.front()(val);
m_dqOnStatusCB.pop_front();
lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
if(_dqOnStatusCB.size()){
_dqOnStatusCB.front()(val);
_dqOnStatusCB.pop_front();
}else{
auto level = val["level"];
auto code = val["code"].as_string();
@ -311,8 +311,8 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
case MSG_AUDIO:
case MSG_VIDEO: {
auto idx = chunkData.typeId%2;
if (m_aNowStampTicker[idx].elapsedTime() > 500) {
m_adNowStamp[idx] = chunkData.timeStamp;
if (_aNowStampTicker[idx].elapsedTime() > 500) {
_adNowStamp[idx] = chunkData.timeStamp;
}
_onMediaData(std::make_shared<RtmpPacket>(chunkData));
}
@ -326,27 +326,27 @@ void RtmpPlayer::onRtmpChunk(RtmpPacket &chunkData) {
float RtmpPlayer::getProgressTime() const{
double iTime[2] = {0,0};
for(auto i = 0 ;i < 2 ;i++){
iTime[i] = (m_adNowStamp[i] - m_adFistStamp[i]) / 1000.0;
iTime[i] = (_adNowStamp[i] - _adFistStamp[i]) / 1000.0;
}
return m_fSeekTo + MAX(iTime[0],iTime[1]);
return _fSeekTo + MAX(iTime[0],iTime[1]);
}
void RtmpPlayer::seekToTime(float fTime){
if (m_bPaused) {
if (_bPaused) {
pause(false);
}
AMFEncoder enc;
enc << "seek" << ++m_iReqID << nullptr << fTime * 1000.0;
enc << "seek" << ++_iReqID << nullptr << fTime * 1000.0;
sendRequest(MSG_CMD, enc.data());
addOnStatusCB([this,fTime](AMFValue &val) {
//TraceL << "seek result";
m_aNowStampTicker[0].resetTime();
m_aNowStampTicker[1].resetTime();
_aNowStampTicker[0].resetTime();
_aNowStampTicker[1].resetTime();
float iTimeInc = fTime - getProgressTime();
for(auto i = 0 ;i < 2 ;i++){
m_adFistStamp[i] = m_adNowStamp[i] + iTimeInc * 1000.0;
m_adNowStamp[i] = m_adFistStamp[i];
_adFistStamp[i] = _adNowStamp[i] + iTimeInc * 1000.0;
_adNowStamp[i] = _adFistStamp[i];
}
m_fSeekTo = fTime;
_fSeekTo = fTime;
});
}

View File

@ -65,28 +65,28 @@ protected:
private:
void _onShutdown(const SockException &ex) {
WarnL << ex.getErrCode() << " " << ex.what();
m_pPlayTimer.reset();
m_pMediaTimer.reset();
m_pBeatTimer.reset();
_pPlayTimer.reset();
_pMediaTimer.reset();
_pBeatTimer.reset();
onShutdown(ex);
}
void _onMediaData(const RtmpPacket::Ptr &chunkData) {
m_mediaTicker.resetTime();
_mediaTicker.resetTime();
onMediaData(chunkData);
}
void _onPlayResult(const SockException &ex) {
WarnL << ex.getErrCode() << " " << ex.what();
m_pPlayTimer.reset();
m_pMediaTimer.reset();
_pPlayTimer.reset();
_pMediaTimer.reset();
if (!ex) {
m_mediaTicker.resetTime();
_mediaTicker.resetTime();
weak_ptr<RtmpPlayer> weakSelf = dynamic_pointer_cast<RtmpPlayer>(shared_from_this());
m_pMediaTimer.reset( new Timer(5, [weakSelf]() {
_pMediaTimer.reset( new Timer(5, [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return false;
}
if(strongSelf->m_mediaTicker.elapsedTime()>10000) {
if(strongSelf->_mediaTicker.elapsedTime()>10000) {
//recv media timeout!
strongSelf->_onShutdown(SockException(Err_timeout,"recv rtmp timeout"));
strongSelf->teardown();
@ -111,13 +111,13 @@ private:
template<typename FUN>
inline void addOnResultCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
m_mapOnResultCB.emplace(m_iReqID, fun);
lock_guard<recursive_mutex> lck(_mtxOnResultCB);
_mapOnResultCB.emplace(_iReqID, fun);
}
template<typename FUN>
inline void addOnStatusCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
m_dqOnStatusCB.emplace_back(fun);
lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
_dqOnStatusCB.emplace_back(fun);
}
void onCmd_result(AMFDecoder &dec);
@ -129,31 +129,31 @@ private:
inline void send_play();
inline void send_pause(bool bPause);
string m_strApp;
string m_strStream;
string m_strTcUrl;
bool m_bPaused = false;
string _strApp;
string _strStream;
string _strTcUrl;
bool _bPaused = false;
unordered_map<int, function<void(AMFDecoder &dec)> > m_mapOnResultCB;
recursive_mutex m_mtxOnResultCB;
deque<function<void(AMFValue &dec)> > m_dqOnStatusCB;
recursive_mutex m_mtxOnStatusCB;
unordered_map<int, function<void(AMFDecoder &dec)> > _mapOnResultCB;
recursive_mutex _mtxOnResultCB;
deque<function<void(AMFValue &dec)> > _dqOnStatusCB;
recursive_mutex _mtxOnStatusCB;
typedef void (RtmpPlayer::*rtmpCMDHandle)(AMFDecoder &dec);
static unordered_map<string, rtmpCMDHandle> g_mapCmd;
//超时功能实现
Ticker m_mediaTicker;
std::shared_ptr<Timer> m_pMediaTimer;
std::shared_ptr<Timer> m_pPlayTimer;
Ticker _mediaTicker;
std::shared_ptr<Timer> _pMediaTimer;
std::shared_ptr<Timer> _pPlayTimer;
//心跳定时器
std::shared_ptr<Timer> m_pBeatTimer;
std::shared_ptr<Timer> _pBeatTimer;
//播放进度控制
float m_fSeekTo = 0;
double m_adFistStamp[2] = { 0, 0 };
double m_adNowStamp[2] = { 0, 0 };
Ticker m_aNowStampTicker[2];
float _fSeekTo = 0;
double _adFistStamp[2] = { 0, 0 };
double _adNowStamp[2] = { 0, 0 };
Ticker _aNowStampTicker[2];
};
} /* namespace Rtmp */

View File

@ -63,32 +63,32 @@ public:
private:
//派生类回调函数
bool onCheckMeta(AMFValue &val) override {
m_pRtmpMediaSrc = dynamic_pointer_cast<RtmpMediaSource>(m_pMediaSrc);
if(m_pRtmpMediaSrc){
m_pRtmpMediaSrc->onGetMetaData(val);
_pRtmpMediaSrc = dynamic_pointer_cast<RtmpMediaSource>(_pMediaSrc);
if(_pRtmpMediaSrc){
_pRtmpMediaSrc->onGetMetaData(val);
}
try {
m_parser.reset(new RtmpParser(val));
_parser.reset(new RtmpParser(val));
//todo(xzl) 修复此处
// m_parser->setOnVideoCB(m_onGetVideoCB);
// m_parser->setOnAudioCB(m_onGetAudioCB);
// _parser->setOnVideoCB(_onGetVideoCB);
// _parser->setOnAudioCB(_onGetAudioCB);
return true;
} catch (std::exception &ex) {
WarnL << ex.what();
return m_pRtmpMediaSrc ? true : false;
return _pRtmpMediaSrc ? true : false;
}
}
void onMediaData(const RtmpPacket::Ptr &chunkData) override {
if(m_parser){
m_parser->inputRtmp(chunkData);
if(_parser){
_parser->inputRtmp(chunkData);
}
if(m_pRtmpMediaSrc){
m_pRtmpMediaSrc->onGetMedia(chunkData);
if(_pRtmpMediaSrc){
_pRtmpMediaSrc->onGetMedia(chunkData);
}
}
private:
RtmpMediaSource::Ptr m_pRtmpMediaSrc;
RtmpMediaSource::Ptr _pRtmpMediaSrc;
};

View File

@ -76,7 +76,7 @@ namespace ZL {
namespace Rtmp {
RtmpProtocol::RtmpProtocol() {
m_nextHandle = [this](){
_nextHandle = [this](){
handle_C0C1();
};
}
@ -85,25 +85,25 @@ RtmpProtocol::~RtmpProtocol() {
}
void RtmpProtocol::reset() {
////////////ChunkSize////////////
m_iChunkLenIn = DEFAULT_CHUNK_LEN;
m_iChunkLenOut = DEFAULT_CHUNK_LEN;
_iChunkLenIn = DEFAULT_CHUNK_LEN;
_iChunkLenOut = DEFAULT_CHUNK_LEN;
////////////Acknowledgement////////////
m_ui32ByteSent = 0;
m_ui32LastSent = 0;
m_ui32WinSize = 0;
_ui32ByteSent = 0;
_ui32LastSent = 0;
_ui32WinSize = 0;
///////////PeerBandwidth///////////
m_ui32Bandwidth = 2500000;
m_ui8LimitType = 2;
_ui32Bandwidth = 2500000;
_ui8LimitType = 2;
////////////Chunk////////////
m_mapChunkData.clear();
m_iNowStreamID = 0;
m_iNowChunkID = 0;
_mapChunkData.clear();
_iNowStreamID = 0;
_iNowChunkID = 0;
//////////Invoke Request//////////
m_iReqID = 0;
_iReqID = 0;
//////////Rtmp parser//////////
m_strRcvBuf.clear();
m_ui32StreamId = STREAM_CONTROL;
m_nextHandle = [this]() {
_strRcvBuf.clear();
_ui32StreamId = STREAM_CONTROL;
_nextHandle = [this]() {
handle_C0C1();
};
}
@ -132,7 +132,7 @@ void RtmpProtocol::sendChunkSize(uint32_t ui32Size) {
uint32_t len = htonl(ui32Size);
std::string set_chunk((char *) &len, 4);
sendRequest(MSG_SET_CHUNK, set_chunk);
m_iChunkLenOut = ui32Size;
_iChunkLenOut = ui32Size;
}
void RtmpProtocol::sendPingRequest(uint32_t ui32TimeStamp) {
@ -173,20 +173,20 @@ void RtmpProtocol::sendUserControl(uint16_t ui16EventType,
}
void RtmpProtocol::sendResponse(int iType, const string& str) {
if(!m_bDataStarted && (iType == MSG_DATA)){
m_bDataStarted = true;
if(!_bDataStarted && (iType == MSG_DATA)){
_bDataStarted = true;
}
sendRtmp(iType, m_iNowStreamID, str, 0, m_bDataStarted ? CHUNK_CLIENT_REQUEST_AFTER : CHUNK_CLIENT_REQUEST_BEFORE);
sendRtmp(iType, _iNowStreamID, str, 0, _bDataStarted ? CHUNK_CLIENT_REQUEST_AFTER : CHUNK_CLIENT_REQUEST_BEFORE);
}
void RtmpProtocol::sendInvoke(const string& strCmd, const AMFValue& val) {
AMFEncoder enc;
enc << strCmd << ++m_iReqID << val;
enc << strCmd << ++_iReqID << val;
sendRequest(MSG_CMD, enc.data());
}
void RtmpProtocol::sendRequest(int iCmd, const string& str) {
sendRtmp(iCmd, m_ui32StreamId, str, 0, CHUNK_SERVER_REQUEST);
sendRtmp(iCmd, _ui32StreamId, str, 0, CHUNK_SERVER_REQUEST);
}
void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
@ -205,7 +205,7 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
set_le32(header.streamId, ui32StreamId);
//估算rtmp包数据大小
uint32_t capacity = ((bExtStamp ? 5 : 1) * (1 + (strBuf.size() / m_iChunkLenOut))) + strBuf.size() + sizeof(header);
uint32_t capacity = ((bExtStamp ? 5 : 1) * (1 + (strBuf.size() / _iChunkLenOut))) + strBuf.size() + sizeof(header);
uint32_t totalSize = 0;
BufferRaw::Ptr buffer = obtainBuffer();
buffer->setCapacity(capacity);
@ -229,23 +229,23 @@ void RtmpProtocol::sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId,
memcpy(buffer->data() + totalSize,acExtStamp, 4);
totalSize += 4;
}
size_t chunk = min(m_iChunkLenOut, strBuf.size() - pos);
size_t chunk = min(_iChunkLenOut, strBuf.size() - pos);
memcpy(buffer->data() + totalSize,strBuf.data() + pos, chunk);
totalSize += chunk;
pos += chunk;
}
buffer->setSize(totalSize);
onSendRawData(buffer);
m_ui32ByteSent += totalSize;
if (m_ui32WinSize > 0 && m_ui32ByteSent - m_ui32LastSent >= m_ui32WinSize) {
m_ui32LastSent = m_ui32ByteSent;
sendAcknowledgement(m_ui32ByteSent);
_ui32ByteSent += totalSize;
if (_ui32WinSize > 0 && _ui32ByteSent - _ui32LastSent >= _ui32WinSize) {
_ui32LastSent = _ui32ByteSent;
sendAcknowledgement(_ui32ByteSent);
}
}
void RtmpProtocol::onParseRtmp(const char *pcRawData, int iSize) {
m_strRcvBuf.append(pcRawData, iSize);
auto cb = m_nextHandle;
_strRcvBuf.append(pcRawData, iSize);
auto cb = _nextHandle;
cb();
}
@ -256,25 +256,25 @@ void RtmpProtocol::startClientSession(const function<void()> &callBack) {
onSendRawData(obtainBuffer(&handshake_head, 1));
RtmpHandshake c1(0);
onSendRawData(obtainBuffer((char *) (&c1), sizeof(c1)));
m_nextHandle = [this,callBack]() {
_nextHandle = [this,callBack]() {
//等待 S0+S1+S2
handle_S0S1S2(callBack);
};
}
void RtmpProtocol::handle_S0S1S2(const function<void()> &callBack) {
if (m_strRcvBuf.size() < 1 + 2 * C1_HANDSHARK_SIZE) {
if (_strRcvBuf.size() < 1 + 2 * C1_HANDSHARK_SIZE) {
//数据不够
return;
}
if (m_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) {
if (_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) {
throw std::runtime_error("only plaintext[0x03] handshake supported");
}
//发送 C2
const char *pcC2 = m_strRcvBuf.data() + 1;
const char *pcC2 = _strRcvBuf.data() + 1;
onSendRawData(obtainBuffer(pcC2, C1_HANDSHARK_SIZE));
m_strRcvBuf.erase(0, 1 + 2 * C1_HANDSHARK_SIZE);
_strRcvBuf.erase(0, 1 + 2 * C1_HANDSHARK_SIZE);
//握手结束
m_nextHandle = [this]() {
_nextHandle = [this]() {
//握手结束并且开始进入解析命令模式
handle_rtmp();
};
@ -282,14 +282,14 @@ void RtmpProtocol::handle_S0S1S2(const function<void()> &callBack) {
}
////for server ////
void RtmpProtocol::handle_C0C1() {
if (m_strRcvBuf.size() < 1 + C1_HANDSHARK_SIZE) {
if (_strRcvBuf.size() < 1 + C1_HANDSHARK_SIZE) {
//need more data!
return;
}
if (m_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) {
if (_strRcvBuf[0] != HANDSHAKE_PLAINTEXT) {
throw std::runtime_error("only plaintext[0x03] handshake supported");
}
if(memcmp(m_strRcvBuf.c_str() + 5,"\x00\x00\x00\x00",4) ==0 ){
if(memcmp(_strRcvBuf.c_str() + 5,"\x00\x00\x00\x00",4) ==0 ){
//simple handsharke
handle_C1_simple();
}else{
@ -301,7 +301,7 @@ void RtmpProtocol::handle_C0C1() {
handle_C1_simple();
#endif//ENABLE_OPENSSL
}
m_strRcvBuf.erase(0, 1 + C1_HANDSHARK_SIZE);
_strRcvBuf.erase(0, 1 + C1_HANDSHARK_SIZE);
}
void RtmpProtocol::handle_C1_simple(){
//发送S0
@ -311,9 +311,9 @@ void RtmpProtocol::handle_C1_simple(){
RtmpHandshake s1(0);
onSendRawData(obtainBuffer((char *) &s1, C1_HANDSHARK_SIZE));
//发送S2
onSendRawData(obtainBuffer(m_strRcvBuf.c_str() + 1, C1_HANDSHARK_SIZE));
onSendRawData(obtainBuffer(_strRcvBuf.c_str() + 1, C1_HANDSHARK_SIZE));
//等待C2
m_nextHandle = [this]() {
_nextHandle = [this]() {
handle_C2();
};
}
@ -321,7 +321,7 @@ void RtmpProtocol::handle_C1_simple(){
void RtmpProtocol::handle_C1_complex(){
//参考自:http://blog.csdn.net/win_lin/article/details/13006803
//skip c0,time,version
const char *c1_start = m_strRcvBuf.data() + 1;
const char *c1_start = _strRcvBuf.data() + 1;
const char *schema_start = c1_start + 8;
char *digest_start;
try{
@ -470,57 +470,57 @@ void RtmpProtocol::send_complex_S0S1S2(int schemeType,const string &digest){
memcpy((char *)&s2 + C1_HANDSHARK_SIZE - C1_DIGEST_SIZE,s2_digest.data(),C1_DIGEST_SIZE);
onSendRawData(obtainBuffer((char *)&s2, sizeof(s2)));
//等待C2
m_nextHandle = [this]() {
_nextHandle = [this]() {
handle_C2();
};
}
#endif //ENABLE_OPENSSL
void RtmpProtocol::handle_C2() {
if (m_strRcvBuf.size() < C1_HANDSHARK_SIZE) {
if (_strRcvBuf.size() < C1_HANDSHARK_SIZE) {
//need more data!
return;
}
m_strRcvBuf.erase(0, C1_HANDSHARK_SIZE);
_strRcvBuf.erase(0, C1_HANDSHARK_SIZE);
//握手结束,进入命令模式
if (!m_strRcvBuf.empty()) {
if (!_strRcvBuf.empty()) {
handle_rtmp();
}
m_nextHandle = [this]() {
_nextHandle = [this]() {
handle_rtmp();
};
}
void RtmpProtocol::handle_rtmp() {
while (!m_strRcvBuf.empty()) {
uint8_t flags = m_strRcvBuf[0];
while (!_strRcvBuf.empty()) {
uint8_t flags = _strRcvBuf[0];
int iOffset = 0;
static const size_t HEADER_LENGTH[] = { 12, 8, 4, 1 };
size_t iHeaderLen = HEADER_LENGTH[flags >> 6];
m_iNowChunkID = flags & 0x3f;
if(m_iNowChunkID >10){
_iNowChunkID = flags & 0x3f;
if(_iNowChunkID >10){
int i=0;
i++;
}
switch (m_iNowChunkID) {
switch (_iNowChunkID) {
case 0: {
//0 值表示二字节形式,并且 ID 范围 64 - 319
//(第二个字节 + 64)。
if (m_strRcvBuf.size() < 2) {
if (_strRcvBuf.size() < 2) {
//need more data
return;
}
m_iNowChunkID = 64 + (uint8_t) (m_strRcvBuf[1]);
_iNowChunkID = 64 + (uint8_t) (_strRcvBuf[1]);
iOffset = 1;
}
break;
case 1: {
//1 值表示三字节形式,并且 ID 范围为 64 - 65599
//((第三个字节) * 256 + 第二个字节 + 64)。
if (m_strRcvBuf.size() < 3) {
if (_strRcvBuf.size() < 3) {
//need more data
return;
}
m_iNowChunkID = 64 + ((uint8_t) (m_strRcvBuf[2]) << 8) + (uint8_t) (m_strRcvBuf[1]);
_iNowChunkID = 64 + ((uint8_t) (_strRcvBuf[2]) << 8) + (uint8_t) (_strRcvBuf[1]);
iOffset = 2;
}
break;
@ -529,13 +529,13 @@ void RtmpProtocol::handle_rtmp() {
break;
}
if (m_strRcvBuf.size() < iHeaderLen + iOffset) {
if (_strRcvBuf.size() < iHeaderLen + iOffset) {
//need more data
return;
}
RtmpHeader &header = *((RtmpHeader *) (m_strRcvBuf.data() + iOffset));
auto &chunkData = m_mapChunkData[m_iNowChunkID];
chunkData.chunkId = m_iNowChunkID;
RtmpHeader &header = *((RtmpHeader *) (_strRcvBuf.data() + iOffset));
auto &chunkData = _mapChunkData[_iNowChunkID];
chunkData.chunkId = _iNowChunkID;
switch (iHeaderLen) {
case 12:
chunkData.hasAbsStamp = true;
@ -549,11 +549,11 @@ void RtmpProtocol::handle_rtmp() {
}
if (chunkData.hasExtStamp) {
if (m_strRcvBuf.size() < iHeaderLen + iOffset + 4) {
if (_strRcvBuf.size() < iHeaderLen + iOffset + 4) {
//need more data
return;
}
chunkData.deltaStamp = load_be32(m_strRcvBuf.data() + iOffset + iHeaderLen);
chunkData.deltaStamp = load_be32(_strRcvBuf.data() + iOffset + iHeaderLen);
iOffset += 4;
}
@ -561,18 +561,18 @@ void RtmpProtocol::handle_rtmp() {
throw std::runtime_error("非法的bodySize");
}
auto iMore = min(m_iChunkLenIn, chunkData.bodySize - chunkData.strBuf.size());
if (m_strRcvBuf.size() < iHeaderLen + iOffset + iMore) {
auto iMore = min(_iChunkLenIn, chunkData.bodySize - chunkData.strBuf.size());
if (_strRcvBuf.size() < iHeaderLen + iOffset + iMore) {
//need more data
return;
}
chunkData.strBuf.append(m_strRcvBuf, iHeaderLen + iOffset, iMore);
m_strRcvBuf.erase(0, iHeaderLen + iOffset + iMore);
chunkData.strBuf.append(_strRcvBuf, iHeaderLen + iOffset, iMore);
_strRcvBuf.erase(0, iHeaderLen + iOffset + iMore);
if (chunkData.strBuf.size() == chunkData.bodySize) {
//frame is ready
m_iNowStreamID = chunkData.streamId;
_iNowStreamID = chunkData.streamId;
chunkData.timeStamp = chunkData.deltaStamp + (chunkData.hasAbsStamp ? 0 : chunkData.timeStamp);
if(chunkData.bodySize){
@ -600,8 +600,8 @@ void RtmpProtocol::handle_rtmpChunk(RtmpPacket& chunkData) {
if (chunkData.strBuf.size() < 4) {
throw std::runtime_error("MSG_SET_CHUNK :Not enough data");
}
m_iChunkLenIn = load_be32(&chunkData.strBuf[0]);
TraceL << "MSG_SET_CHUNK:" << m_iChunkLenIn;
_iChunkLenIn = load_be32(&chunkData.strBuf[0]);
TraceL << "MSG_SET_CHUNK:" << _iChunkLenIn;
}
break;
case MSG_USER_CONTROL: {
@ -668,14 +668,14 @@ void RtmpProtocol::handle_rtmpChunk(RtmpPacket& chunkData) {
break;
case MSG_WIN_SIZE: {
m_ui32WinSize = load_be32(&chunkData.strBuf[0]);
TraceL << "MSG_WIN_SIZE:" << m_ui32WinSize;
_ui32WinSize = load_be32(&chunkData.strBuf[0]);
TraceL << "MSG_WIN_SIZE:" << _ui32WinSize;
}
break;
case MSG_SET_PEER_BW: {
m_ui32Bandwidth = load_be32(&chunkData.strBuf[0]);
m_ui8LimitType = chunkData.strBuf[4];
TraceL << "MSG_SET_PEER_BW:" << m_ui32WinSize;
_ui32Bandwidth = load_be32(&chunkData.strBuf[0]);
_ui8LimitType = chunkData.strBuf[4];
TraceL << "MSG_SET_PEER_BW:" << _ui32WinSize;
}
break;
case MSG_AGGREGATE:

View File

@ -57,7 +57,7 @@ protected:
virtual void onSendRawData(const Buffer::Ptr &buffer) = 0;
virtual void onRtmpChunk(RtmpPacket &chunkData) = 0;
virtual void onStreamBegin(uint32_t ui32StreamId){
m_ui32StreamId = ui32StreamId;
_ui32StreamId = ui32StreamId;
}
virtual void onStreamEof(uint32_t ui32StreamId){};
virtual void onStreamDry(uint32_t ui32StreamId){};
@ -77,14 +77,14 @@ protected:
void sendResponse(int iType, const string &str);
void sendRtmp(uint8_t ui8Type, uint32_t ui32StreamId, const std::string &strBuf, uint32_t ui32TimeStamp, int iChunkID);
protected:
int m_iReqID = 0;
uint32_t m_ui32StreamId = STREAM_CONTROL;
int m_iNowStreamID = 0;
int m_iNowChunkID = 0;
bool m_bDataStarted = false;
int _iReqID = 0;
uint32_t _ui32StreamId = STREAM_CONTROL;
int _iNowStreamID = 0;
int _iNowChunkID = 0;
bool _bDataStarted = false;
inline BufferRaw::Ptr obtainBuffer();
inline BufferRaw::Ptr obtainBuffer(const void *data, int len);
//ResourcePool<BufferRaw,MAX_SEND_PKT> m_bufferPool;
//ResourcePool<BufferRaw,MAX_SEND_PKT> _bufferPool;
private:
void handle_S0S1S2(const function<void()> &cb);
void handle_C0C1();
@ -103,20 +103,20 @@ private:
private:
////////////ChunkSize////////////
size_t m_iChunkLenIn = DEFAULT_CHUNK_LEN;
size_t m_iChunkLenOut = DEFAULT_CHUNK_LEN;
size_t _iChunkLenIn = DEFAULT_CHUNK_LEN;
size_t _iChunkLenOut = DEFAULT_CHUNK_LEN;
////////////Acknowledgement////////////
uint32_t m_ui32ByteSent = 0;
uint32_t m_ui32LastSent = 0;
uint32_t m_ui32WinSize = 0;
uint32_t _ui32ByteSent = 0;
uint32_t _ui32LastSent = 0;
uint32_t _ui32WinSize = 0;
///////////PeerBandwidth///////////
uint32_t m_ui32Bandwidth = 2500000;
uint8_t m_ui8LimitType = 2;
uint32_t _ui32Bandwidth = 2500000;
uint8_t _ui8LimitType = 2;
////////////Chunk////////////
unordered_map<int, RtmpPacket> m_mapChunkData;
unordered_map<int, RtmpPacket> _mapChunkData;
//////////Rtmp parser//////////
string m_strRcvBuf;
function<void()> m_nextHandle;
string _strRcvBuf;
function<void()> _nextHandle;
};
} /* namespace Rtmp */

View File

@ -56,7 +56,7 @@ void RtmpPusher::init(const RtmpMediaSource::Ptr &src){
g_mapCmd.emplace("_result",&RtmpPusher::onCmd_result);
g_mapCmd.emplace("onStatus",&RtmpPusher::onCmd_onStatus);
}, []() {});
m_pMediaSrc=src;
_pMediaSrc=src;
}
RtmpPusher::~RtmpPusher() {
@ -65,18 +65,18 @@ RtmpPusher::~RtmpPusher() {
}
void RtmpPusher::teardown() {
if (alive()) {
m_strApp.clear();
m_strStream.clear();
m_strTcUrl.clear();
_strApp.clear();
_strStream.clear();
_strTcUrl.clear();
{
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
m_mapOnResultCB.clear();
lock_guard<recursive_mutex> lck(_mtxOnResultCB);
_mapOnResultCB.clear();
}
{
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
m_dqOnStatusCB.clear();
lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
_dqOnStatusCB.clear();
}
m_pPublishTimer.reset();
_pPublishTimer.reset();
reset();
shutdown();
}
@ -85,15 +85,15 @@ void RtmpPusher::teardown() {
void RtmpPusher::publish(const char* strUrl) {
teardown();
string strHost = FindField(strUrl, "://", "/");
m_strApp = FindField(strUrl, (strHost + "/").data(), "/");
m_strStream = FindField(strUrl, (strHost + "/" + m_strApp + "/").data(), NULL);
m_strTcUrl = string("rtmp://") + strHost + "/" + m_strApp;
_strApp = FindField(strUrl, (strHost + "/").data(), "/");
_strStream = FindField(strUrl, (strHost + "/" + _strApp + "/").data(), NULL);
_strTcUrl = string("rtmp://") + strHost + "/" + _strApp;
if (!m_strApp.size() || !m_strStream.size()) {
if (!_strApp.size() || !_strStream.size()) {
onPublishResult(SockException(Err_other,"rtmp url非法"));
return;
}
DebugL << strHost << " " << m_strApp << " " << m_strStream;
DebugL << strHost << " " << _strApp << " " << _strStream;
auto iPort = atoi(FindField(strHost.c_str(), ":", NULL).c_str());
if (iPort <= 0) {
@ -115,7 +115,7 @@ void RtmpPusher::onConnect(const SockException &err){
return;
}
weak_ptr<RtmpPusher> weakSelf = dynamic_pointer_cast<RtmpPusher>(shared_from_this());
m_pPublishTimer.reset( new Timer(10, [weakSelf]() {
_pPublishTimer.reset( new Timer(10, [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return false;
@ -147,10 +147,10 @@ void RtmpPusher::onRecv(const Buffer::Ptr &pBuf){
inline void RtmpPusher::send_connect() {
AMFValue obj(AMF_OBJECT);
obj.set("app", m_strApp);
obj.set("app", _strApp);
obj.set("type", "nonprivate");
obj.set("tcUrl", m_strTcUrl);
obj.set("swfUrl", m_strTcUrl);
obj.set("tcUrl", _strTcUrl);
obj.set("swfUrl", _strTcUrl);
sendInvoke("connect", obj);
addOnResultCB([this](AMFDecoder &dec){
//TraceL << "connect result";
@ -171,13 +171,13 @@ inline void RtmpPusher::send_createStream() {
addOnResultCB([this](AMFDecoder &dec){
//TraceL << "createStream result";
dec.load<AMFValue>();
m_ui32StreamId = dec.load<int>();
_ui32StreamId = dec.load<int>();
send_publish();
});
}
inline void RtmpPusher::send_publish() {
AMFEncoder enc;
enc << "publish" << ++m_iReqID << nullptr << m_strStream << m_strApp ;
enc << "publish" << ++_iReqID << nullptr << _strStream << _strApp ;
sendRequest(MSG_CMD, enc.data());
addOnStatusCB([this](AMFValue &val) {
@ -192,7 +192,7 @@ inline void RtmpPusher::send_publish() {
}
inline void RtmpPusher::send_metaData(){
auto src = m_pMediaSrc.lock();
auto src = _pMediaSrc.lock();
if (!src) {
throw std::runtime_error("the media source was released");
}
@ -202,19 +202,19 @@ inline void RtmpPusher::send_metaData(){
sendRequest(MSG_DATA, enc.data());
src->getConfigFrame([&](const RtmpPacket::Ptr &pkt){
sendRtmp(pkt->typeId, m_ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId );
sendRtmp(pkt->typeId, _ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId );
});
m_pRtmpReader = src->getRing()->attach();
_pRtmpReader = src->getRing()->attach();
weak_ptr<RtmpPusher> weakSelf = dynamic_pointer_cast<RtmpPusher>(shared_from_this());
m_pRtmpReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt){
_pRtmpReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt){
auto strongSelf = weakSelf.lock();
if(!strongSelf) {
return;
}
strongSelf->sendRtmp(pkt->typeId, strongSelf->m_ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId);
strongSelf->sendRtmp(pkt->typeId, strongSelf->_ui32StreamId, pkt->strBuf, pkt->timeStamp, pkt->chunkId);
});
m_pRtmpReader->setDetachCB([weakSelf](){
_pRtmpReader->setDetachCB([weakSelf](){
auto strongSelf = weakSelf.lock();
if(strongSelf){
strongSelf->onShutdown(SockException(Err_other,"媒体源被释放"));
@ -228,11 +228,11 @@ inline void RtmpPusher::send_metaData(){
}
void RtmpPusher::onCmd_result(AMFDecoder &dec){
auto iReqId = dec.load<int>();
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
auto it = m_mapOnResultCB.find(iReqId);
if(it != m_mapOnResultCB.end()){
lock_guard<recursive_mutex> lck(_mtxOnResultCB);
auto it = _mapOnResultCB.find(iReqId);
if(it != _mapOnResultCB.end()){
it->second(dec);
m_mapOnResultCB.erase(it);
_mapOnResultCB.erase(it);
}else{
WarnL << "unhandled _result";
}
@ -249,10 +249,10 @@ void RtmpPusher::onCmd_onStatus(AMFDecoder &dec) {
throw std::runtime_error("onStatus:the result object was not found");
}
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
if(m_dqOnStatusCB.size()){
m_dqOnStatusCB.front()(val);
m_dqOnStatusCB.pop_front();
lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
if(_dqOnStatusCB.size()){
_dqOnStatusCB.front()(val);
_dqOnStatusCB.pop_front();
}else{
auto level = val["level"];
auto code = val["code"].as_string();

View File

@ -46,11 +46,11 @@ public:
void teardown();
void setOnPublished(Event onPublished) {
m_onPublished = onPublished;
_onPublished = onPublished;
}
void setOnShutdown(Event onShutdown) {
m_onShutdown = onShutdown;
_onShutdown = onShutdown;
}
protected:
@ -67,28 +67,28 @@ protected:
private:
void init(const RtmpMediaSource::Ptr &src);
void onShutdown(const SockException &ex) {
m_pPublishTimer.reset();
if(m_onShutdown){
m_onShutdown(ex);
_pPublishTimer.reset();
if(_onShutdown){
_onShutdown(ex);
}
m_pRtmpReader.reset();
_pRtmpReader.reset();
}
void onPublishResult(const SockException &ex) {
m_pPublishTimer.reset();
if(m_onPublished){
m_onPublished(ex);
_pPublishTimer.reset();
if(_onPublished){
_onPublished(ex);
}
}
template<typename FUN>
inline void addOnResultCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(m_mtxOnResultCB);
m_mapOnResultCB.emplace(m_iReqID, fun);
lock_guard<recursive_mutex> lck(_mtxOnResultCB);
_mapOnResultCB.emplace(_iReqID, fun);
}
template<typename FUN>
inline void addOnStatusCB(const FUN &fun) {
lock_guard<recursive_mutex> lck(m_mtxOnStatusCB);
m_dqOnStatusCB.emplace_back(fun);
lock_guard<recursive_mutex> lck(_mtxOnStatusCB);
_dqOnStatusCB.emplace_back(fun);
}
void onCmd_result(AMFDecoder &dec);
@ -100,27 +100,27 @@ private:
inline void send_publish();
inline void send_metaData();
string m_strApp;
string m_strStream;
string m_strTcUrl;
string _strApp;
string _strStream;
string _strTcUrl;
unordered_map<int, function<void(AMFDecoder &dec)> > m_mapOnResultCB;
recursive_mutex m_mtxOnResultCB;
deque<function<void(AMFValue &dec)> > m_dqOnStatusCB;
recursive_mutex m_mtxOnStatusCB;
unordered_map<int, function<void(AMFDecoder &dec)> > _mapOnResultCB;
recursive_mutex _mtxOnResultCB;
deque<function<void(AMFValue &dec)> > _dqOnStatusCB;
recursive_mutex _mtxOnStatusCB;
typedef void (RtmpPusher::*rtmpCMDHandle)(AMFDecoder &dec);
static unordered_map<string, rtmpCMDHandle> g_mapCmd;
//超时功能实现
std::shared_ptr<Timer> m_pPublishTimer;
std::shared_ptr<Timer> _pPublishTimer;
//源
std::weak_ptr<RtmpMediaSource> m_pMediaSrc;
RtmpMediaSource::RingType::RingReader::Ptr m_pRtmpReader;
std::weak_ptr<RtmpMediaSource> _pMediaSrc;
RtmpMediaSource::RingType::RingReader::Ptr _pRtmpReader;
//事件监听
Event m_onShutdown;
Event m_onPublished;
Event _onShutdown;
Event _onPublished;
};
} /* namespace Rtmp */

View File

@ -45,9 +45,9 @@ RtmpSession::RtmpSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::P
RtmpSession::~RtmpSession() {
DebugL << get_peer_ip();
if(m_delayTask){
m_delayTask();
m_delayTask = nullptr;
if(_delayTask){
_delayTask();
_delayTask = nullptr;
}
}
@ -57,41 +57,41 @@ void RtmpSession::onError(const SockException& err) {
//流量统计事件广播
GET_CONFIG_AND_REGISTER(uint32_t,iFlowThreshold,Broadcast::kFlowThreshold);
if(m_ui64TotalBytes > iFlowThreshold * 1024){
if(_ui64TotalBytes > iFlowThreshold * 1024){
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,
m_mediaInfo,
m_ui64TotalBytes,
m_ticker.createdTime()/1000,
_mediaInfo,
_ui64TotalBytes,
_ticker.createdTime()/1000,
*this);
}
}
void RtmpSession::onManager() {
if (m_ticker.createdTime() > 15 * 1000) {
if (!m_pRingReader && !m_pPublisherSrc) {
if (_ticker.createdTime() > 15 * 1000) {
if (!_pRingReader && !_pPublisherSrc) {
WarnL << "非法链接:" << get_peer_ip();
shutdown();
}
}
if (m_pPublisherSrc) {
if (_pPublisherSrc) {
//publisher
if (m_ticker.elapsedTime() > 15 * 1000) {
if (_ticker.elapsedTime() > 15 * 1000) {
WarnL << "数据接收超时:" << get_peer_ip();
shutdown();
}
}
if(m_delayTask){
if(time(NULL) > m_iTaskTimeLine){
m_delayTask();
m_delayTask = nullptr;
if(_delayTask){
if(time(NULL) > _iTaskTimeLine){
_delayTask();
_delayTask = nullptr;
}
}
}
void RtmpSession::onRecv(const Buffer::Ptr &pBuf) {
m_ticker.resetTime();
_ticker.resetTime();
try {
m_ui64TotalBytes += pBuf->size();
_ui64TotalBytes += pBuf->size();
onParseRtmp(pBuf->data(), pBuf->size());
} catch (exception &e) {
WarnL << e.what();
@ -113,11 +113,11 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
///////////set peerBandwidth////////////////
sendPeerBandwidth(5000000);
m_mediaInfo.m_app = params["app"].as_string();
m_strTcUrl = params["tcUrl"].as_string();
if(m_strTcUrl.empty()){
_mediaInfo._app = params["app"].as_string();
_strTcUrl = params["tcUrl"].as_string();
if(_strTcUrl.empty()){
//defaultVhost:默认vhost
m_strTcUrl = string(RTMP_SCHEMA) + "://" + DEFAULT_VHOST + "/" + m_mediaInfo.m_app;
_strTcUrl = string(RTMP_SCHEMA) + "://" + DEFAULT_VHOST + "/" + _mediaInfo._app;
}
bool ok = true; //(app == APP_NAME);
AMFValue version(AMF_OBJECT);
@ -130,7 +130,7 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) {
status.set("objectEncoding", amfVer);
sendReply(ok ? "_result" : "_error", version, status);
if (!ok) {
throw std::runtime_error("Unsupported application: " + m_mediaInfo.m_app);
throw std::runtime_error("Unsupported application: " + _mediaInfo._app);
}
AMFEncoder invoke;
@ -148,16 +148,16 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
DebugL << "publish 回复时间:" << pTicker->elapsedTime() << "ms";
}));
dec.load<AMFValue>();/* NULL */
m_mediaInfo.parse(m_strTcUrl + "/" + dec.load<std::string>());
_mediaInfo.parse(_strTcUrl + "/" + dec.load<std::string>());
auto onRes = [this,pToken](const string &err){
auto src = dynamic_pointer_cast<RtmpMediaSource>(MediaSource::find(RTMP_SCHEMA,
m_mediaInfo.m_vhost,
m_mediaInfo.m_app,
m_mediaInfo.m_streamid,
_mediaInfo._vhost,
_mediaInfo._app,
_mediaInfo._streamid,
false));
bool authSuccess = err.empty();
bool ok = (!src && !m_pPublisherSrc && authSuccess);
bool ok = (!src && !_pPublisherSrc && authSuccess);
AMFValue status(AMF_OBJECT);
status.set("level", ok ? "status" : "error");
status.set("code", ok ? "NetStream.Publish.Start" : (authSuccess ? "NetStream.Publish.BadName" : "NetStream.Publish.BadAuth"));
@ -167,14 +167,14 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
if (!ok) {
WarnL << "onPublish:"
<< (authSuccess ? "Already publishing:" : err.data()) << " "
<< m_mediaInfo.m_vhost << " "
<< m_mediaInfo.m_app << " "
<< m_mediaInfo.m_streamid << endl;
<< _mediaInfo._vhost << " "
<< _mediaInfo._app << " "
<< _mediaInfo._streamid << endl;
shutdown();
return;
}
m_pPublisherSrc.reset(new RtmpToRtspMediaSource(m_mediaInfo.m_vhost,m_mediaInfo.m_app,m_mediaInfo.m_streamid));
m_pPublisherSrc->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));
_pPublisherSrc.reset(new RtmpToRtspMediaSource(_mediaInfo._vhost,_mediaInfo._app,_mediaInfo._streamid));
_pPublisherSrc->setListener(dynamic_pointer_cast<MediaSourceEvent>(shared_from_this()));
};
weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this());
@ -192,7 +192,7 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) {
});
};
auto flag = NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRtmpPublish,
m_mediaInfo,
_mediaInfo,
invoker,
*this);
if(!flag){
@ -213,9 +213,9 @@ void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) {
void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shared_ptr<onceToken> &pToken) {
//获取流对象
auto src = dynamic_pointer_cast<RtmpMediaSource>(MediaSource::find(RTMP_SCHEMA,
m_mediaInfo.m_vhost,
m_mediaInfo.m_app,
m_mediaInfo.m_streamid,
_mediaInfo._vhost,
_mediaInfo._app,
_mediaInfo._streamid,
true));
//是否鉴权成功
bool authSuccess = err.empty();
@ -223,17 +223,17 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
//校验成功,但是流不存在而导致的不能播放
//所以我们注册rtmp注册事件等rtmp推流端推流成功后再告知播放器开始播放
auto task_id = this;
auto media_info = m_mediaInfo;
auto media_info = _mediaInfo;
weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this());
NoticeCenter::Instance().addListener(task_id,Broadcast::kBroadcastMediaChanged,
[task_id,weakSelf,media_info,pToken](BroadcastMediaChangedArgs){
if(bRegist &&
schema == media_info.m_schema &&
vhost == media_info.m_vhost &&
app == media_info.m_app &&
stream == media_info.m_streamid){
schema == media_info._schema &&
vhost == media_info._vhost &&
app == media_info._app &&
stream == media_info._streamid){
//播发器请求的rtmp流终于注册上了
auto strongSelf = weakSelf.lock();
if(!strongSelf) {
@ -249,7 +249,7 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
if(!strongSelf) {
return;
}
DebugL << "收到rtmp注册事件,回复播放器:" << media_info.m_schema << "/" << media_info.m_vhost << "/" << media_info.m_app << "/" << media_info.m_streamid;
DebugL << "收到rtmp注册事件,回复播放器:" << media_info._schema << "/" << media_info._vhost << "/" << media_info._app << "/" << media_info._streamid;
//回复播放器
strongSelf->doPlayResponse("",false,pToken);
//取消延时任务,防止多次回复
@ -291,15 +291,15 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
status.set("level", ok ? "status" : "error");
status.set("code", ok ? "NetStream.Play.Reset" : (authSuccess ? "NetStream.Play.StreamNotFound" : "NetStream.Play.BadAuth"));
status.set("description", ok ? "Resetting and playing." : (authSuccess ? "No such stream." : err.data()));
status.set("details", m_mediaInfo.m_streamid);
status.set("details", _mediaInfo._streamid);
status.set("clientid", "0");
sendReply("onStatus", nullptr, status);
if (!ok) {
WarnL << "onPlayed:"
<< (authSuccess ? "No such stream:" : err.data()) << " "
<< m_mediaInfo.m_vhost << " "
<< m_mediaInfo.m_app << " "
<< m_mediaInfo.m_streamid
<< _mediaInfo._vhost << " "
<< _mediaInfo._app << " "
<< _mediaInfo._streamid
<< endl;
shutdown();
return;
@ -310,7 +310,7 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
status.set("level", "status");
status.set("code", "NetStream.Play.Start");
status.set("description", "Started playing.");
status.set("details", m_mediaInfo.m_streamid);
status.set("details", _mediaInfo._streamid);
status.set("clientid", "0");
sendReply("onStatus", nullptr, status);
@ -331,7 +331,7 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
status.set("level", "status");
status.set("code", "NetStream.Play.PublishNotify");
status.set("description", "Now published.");
status.set("details", m_mediaInfo.m_streamid);
status.set("details", _mediaInfo._streamid);
status.set("clientid", "0");
sendReply("onStatus", nullptr, status);
@ -345,10 +345,10 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
onSendMedia(pkt);
});
m_pRingReader = src->getRing()->attach();
_pRingReader = src->getRing()->attach();
weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this());
SockUtil::setNoDelay(_sock->rawFD(), false);
m_pRingReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt) {
_pRingReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt) {
auto strongSelf = weakSelf.lock();
if (!strongSelf) {
return;
@ -361,14 +361,14 @@ void RtmpSession::doPlayResponse(const string &err,bool tryDelay,const std::shar
strongSelf->onSendMedia(pkt);
});
});
m_pRingReader->setDetachCB([weakSelf]() {
_pRingReader->setDetachCB([weakSelf]() {
auto strongSelf = weakSelf.lock();
if (!strongSelf) {
return;
}
strongSelf->safeShutdown();
});
m_pPlayerSrc = src;
_pPlayerSrc = src;
if (src->getRing()->readerCount() == 1) {
src->seekTo(0);
}
@ -397,7 +397,7 @@ void RtmpSession::doPlay(AMFDecoder &dec){
strongSelf->doPlayResponse(err,true,pToken);
});
};
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed,m_mediaInfo,invoker,*this);
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed,_mediaInfo,invoker,*this);
if(!flag){
//该事件无人监听,默认不鉴权
doPlayResponse("",true,pToken);
@ -408,7 +408,7 @@ void RtmpSession::onCmd_play2(AMFDecoder &dec) {
}
void RtmpSession::onCmd_play(AMFDecoder &dec) {
dec.load<AMFValue>();/* NULL */
m_mediaInfo.parse(m_strTcUrl + "/" + dec.load<std::string>());
_mediaInfo.parse(_strTcUrl + "/" + dec.load<std::string>());
doPlay(dec);
}
@ -424,14 +424,14 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
//streamBegin
sendUserControl(paused ? CONTROL_STREAM_EOF : CONTROL_STREAM_BEGIN,
STREAM_MEDIA);
if (!m_pRingReader) {
if (!_pRingReader) {
throw std::runtime_error("Rtmp not started yet!");
}
if (paused) {
m_pRingReader->setReadCB(nullptr);
_pRingReader->setReadCB(nullptr);
} else {
weak_ptr<RtmpSession> weakSelf = dynamic_pointer_cast<RtmpSession>(shared_from_this());
m_pRingReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt) {
_pRingReader->setReadCB([weakSelf](const RtmpPacket::Ptr &pkt) {
auto strongSelf = weakSelf.lock();
if(!strongSelf) {
return;
@ -448,14 +448,14 @@ void RtmpSession::onCmd_pause(AMFDecoder &dec) {
}
void RtmpSession::setMetaData(AMFDecoder &dec) {
if (!m_pPublisherSrc) {
if (!_pPublisherSrc) {
throw std::runtime_error("not a publisher");
}
std::string type = dec.load<std::string>();
if (type != "onMetaData") {
throw std::runtime_error("can only set metadata");
}
m_pPublisherSrc->onGetMetaData(dec.load<AMFValue>());
_pPublisherSrc->onGetMetaData(dec.load<AMFValue>());
}
void RtmpSession::onProcessCmd(AMFDecoder &dec) {
@ -477,7 +477,7 @@ void RtmpSession::onProcessCmd(AMFDecoder &dec) {
TraceL << "can not support cmd:" << method;
return;
}
m_dNowReqID = dec.load<double>();
_dNowReqID = dec.load<double>();
auto fun = it->second;
(this->*fun)(dec);
}
@ -503,14 +503,14 @@ void RtmpSession::onRtmpChunk(RtmpPacket &chunkData) {
break;
case MSG_AUDIO:
case MSG_VIDEO: {
if (!m_pPublisherSrc) {
if (!_pPublisherSrc) {
throw std::runtime_error("Not a rtmp publisher!");
}
GET_CONFIG_AND_REGISTER(bool,rtmp_modify_stamp,Config::Rtmp::kModifyStamp);
if(rtmp_modify_stamp){
chunkData.timeStamp = m_stampTicker[chunkData.typeId % 2].elapsedTime();
chunkData.timeStamp = _stampTicker[chunkData.typeId % 2].elapsedTime();
}
m_pPublisherSrc->onGetMedia(std::make_shared<RtmpPacket>(chunkData));
_pPublisherSrc->onGetMedia(std::make_shared<RtmpPacket>(chunkData));
}
break;
default:
@ -523,7 +523,7 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
dec.load<AMFValue>();/* NULL */
auto milliSeconds = dec.load<AMFValue>().as_number();
InfoL << "rtmp seekTo:" << milliSeconds/1000.0;
auto stongSrc = m_pPlayerSrc.lock();
auto stongSrc = _pPlayerSrc.lock();
if (stongSrc) {
stongSrc->seekTo(milliSeconds);
}
@ -537,7 +537,7 @@ void RtmpSession::onCmd_seek(AMFDecoder &dec) {
void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) {
auto modifiedStamp = pkt->timeStamp;
auto &firstStamp = m_aui32FirstStamp[pkt->typeId % 2];
auto &firstStamp = _aui32FirstStamp[pkt->typeId % 2];
if(!firstStamp){
firstStamp = modifiedStamp;
}
@ -546,22 +546,22 @@ void RtmpSession::onSendMedia(const RtmpPacket::Ptr &pkt) {
modifiedStamp -= firstStamp;
}else{
//发生回环,重新计算时间戳增量
CLEAR_ARR(m_aui32FirstStamp);
CLEAR_ARR(_aui32FirstStamp);
modifiedStamp = 0;
}
sendRtmp(pkt->typeId, pkt->streamId, pkt->strBuf, modifiedStamp, pkt->chunkId);
}
void RtmpSession::doDelay(int delaySec, const std::function<void()> &fun) {
if(m_delayTask){
m_delayTask();
if(_delayTask){
_delayTask();
}
m_delayTask = fun;
m_iTaskTimeLine = time(NULL) + delaySec;
_delayTask = fun;
_iTaskTimeLine = time(NULL) + delaySec;
}
void RtmpSession::cancelDelyaTask(){
m_delayTask = nullptr;
_delayTask = nullptr;
}

View File

@ -70,7 +70,7 @@ private:
void onSendMedia(const RtmpPacket::Ptr &pkt);
void onSendRawData(const Buffer::Ptr &buffer) override{
m_ui64TotalBytes += buffer->size();
_ui64TotalBytes += buffer->size();
send(buffer);
}
void onRtmpChunk(RtmpPacket &chunkData) override;
@ -78,12 +78,12 @@ private:
template<typename first, typename second>
inline void sendReply(const char *str, const first &reply, const second &status) {
AMFEncoder invoke;
invoke << str << m_dNowReqID << reply << status;
invoke << str << _dNowReqID << reply << status;
sendResponse(MSG_CMD, invoke.data());
}
bool shutDown() override {
InfoL << "kick out:" << m_mediaInfo.m_vhost << " " << m_mediaInfo.m_app << " " << m_mediaInfo.m_streamid;
InfoL << "kick out:" << _mediaInfo._vhost << " " << _mediaInfo._app << " " << _mediaInfo._streamid;
safeShutdown();
return true;
}
@ -91,19 +91,19 @@ private:
void doDelay(int delaySec,const std::function<void()> &fun);
void cancelDelyaTask();
private:
std::string m_strTcUrl;
MediaInfo m_mediaInfo;
double m_dNowReqID = 0;
Ticker m_ticker;//数据接收时间
SmoothTicker m_stampTicker[2];//时间戳生产器
RingBuffer<RtmpPacket::Ptr>::RingReader::Ptr m_pRingReader;
std::shared_ptr<RtmpMediaSource> m_pPublisherSrc;
std::weak_ptr<RtmpMediaSource> m_pPlayerSrc;
uint32_t m_aui32FirstStamp[2] = {0};
std::string _strTcUrl;
MediaInfo _mediaInfo;
double _dNowReqID = 0;
Ticker _ticker;//数据接收时间
SmoothTicker _stampTicker[2];//时间戳生产器
RingBuffer<RtmpPacket::Ptr>::RingReader::Ptr _pRingReader;
std::shared_ptr<RtmpMediaSource> _pPublisherSrc;
std::weak_ptr<RtmpMediaSource> _pPlayerSrc;
uint32_t _aui32FirstStamp[2] = {0};
//消耗的总流量
uint64_t m_ui64TotalBytes = 0;
std::function<void()> m_delayTask;
uint32_t m_iTaskTimeLine = 0;
uint64_t _ui64TotalBytes = 0;
std::function<void()> _delayTask;
uint32_t _iTaskTimeLine = 0;
};

View File

@ -41,27 +41,27 @@ RtmpToRtspMediaSource::RtmpToRtspMediaSource(const string &vhost,
const string &id,
bool bEnableHls,
bool bEnableMp4) :
RtmpMediaSource(vhost,app,id),m_bEnableHls(bEnableHls),m_bEnableMp4(bEnableMp4) {
RtmpMediaSource(vhost,app,id),_bEnableHls(bEnableHls),_bEnableMp4(bEnableMp4) {
}
RtmpToRtspMediaSource::~RtmpToRtspMediaSource() {}
void RtmpToRtspMediaSource::onGetH264(const H264Frame &frame) {
if(m_pRecorder){
m_pRecorder->inputH264((char *) frame.data(), frame.size(), frame.timeStamp, frame.type);
if(_pRecorder){
_pRecorder->inputH264((char *) frame.data(), frame.size(), frame.timeStamp, frame.type);
}
if(m_pRtpMaker_h264){
m_pRtpMaker_h264->makeRtp(frame.data() + 4, frame.size() - 4, frame.timeStamp);
if(_pRtpMaker_h264){
_pRtpMaker_h264->makeRtp(frame.data() + 4, frame.size() - 4, frame.timeStamp);
}
}
inline void RtmpToRtspMediaSource::onGetAAC(const AACFrame &frame) {
if(m_pRecorder){
m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp);
if(_pRecorder){
_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp);
}
if (m_pRtpMaker_aac) {
m_pRtpMaker_aac->makeRtp((char *) frame.buffer + 7, frame.aac_frame_length - 7, frame.timeStamp);
if (_pRtpMaker_aac) {
_pRtpMaker_aac->makeRtp((char *) frame.buffer + 7, frame.aac_frame_length - 7, frame.timeStamp);
}
}
@ -73,40 +73,40 @@ void RtmpToRtspMediaSource::makeSDP() {
strSDP += "i=ZL Live Stream\r\n";
strSDP += "c=IN IP4 0.0.0.0\r\n";
strSDP += "t=0 0\r\n";
if(m_pParser->getDuration() <= 0){
if(_pParser->getDuration() <= 0){
strSDP += "a=range:npt=0-\r\n";
}else{
strSDP += StrPrinter << "0-"<< m_pParser->getDuration()<< "\r\n" << endl;
strSDP += StrPrinter << "0-"<< _pParser->getDuration()<< "\r\n" << endl;
}
strSDP += "a=control:*\r\n";
//todo(xzl) 修复此处
// if (m_pParser->containVideo()) {
// if (_pParser->containVideo()) {
// uint32_t ssrc0;
// memcpy(&ssrc0, makeRandStr(4, false).data(), 4);
// auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
// m_pRtspSrc->onGetRTP(pkt,bKeyPos);
// _pRtspSrc->onGetRTP(pkt,bKeyPos);
// };
//
// GET_CONFIG_AND_REGISTER(uint32_t,videoMtu,Config::Rtp::kVideoMtuSize);
// m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ssrc0,videoMtu));
// _pRtpMaker_h264.reset(new RtpMaker_H264(lam, ssrc0,videoMtu));
//
// char strTemp[100];
// int profile_level_id = 0;
// string strSPS =m_pParser->getSps().substr(4);
// string strPPS =m_pParser->getPps().substr(4);
// string strSPS =_pParser->getSps().substr(4);
// string strPPS =_pParser->getPps().substr(4);
// if (strSPS.length() >= 4) { // sanity check
// profile_level_id = (strSPS[1] << 16) | (strSPS[2] << 8) | strSPS[3]; // profile_idc|constraint_setN_flag|level_idc
// }
//
// //视频通道
// strSDP += StrPrinter << "m=video 0 RTP/AVP " << m_pRtpMaker_h264->getPlayloadType()
// strSDP += StrPrinter << "m=video 0 RTP/AVP " << _pRtpMaker_h264->getPlayloadType()
// << "\r\n" << endl;
// strSDP += "b=AS:5100\r\n";
// strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_h264->getPlayloadType()
// << " H264/" << m_pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
// strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_h264->getPlayloadType()
// strSDP += StrPrinter << "a=rtpmap:" << _pRtpMaker_h264->getPlayloadType()
// << " H264/" << _pRtpMaker_h264->getSampleRate() << "\r\n" << endl;
// strSDP += StrPrinter << "a=fmtp:" << _pRtpMaker_h264->getPlayloadType()
// << " packetization-mode=1;profile-level-id=" << endl;
//
// memset(strTemp, 0, 100);
@ -121,41 +121,41 @@ void RtmpToRtspMediaSource::makeSDP() {
// av_base64_encode(strTemp, 100, (uint8_t *) strPPS.data(), strPPS.size());
// strSDP += strTemp;
// strSDP += "\r\n";
// strSDP += StrPrinter << "a=control:trackID=" << m_pRtpMaker_h264->getInterleaved() / 2
// strSDP += StrPrinter << "a=control:trackID=" << _pRtpMaker_h264->getInterleaved() / 2
// << "\r\n" << endl;
// }
//
// if (m_pParser->containAudio()) {
// if (_pParser->containAudio()) {
// uint32_t ssrc1;
// memcpy(&ssrc1, makeRandStr(8, false).data() + 4, 4);
// auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) {
// m_pRtspSrc->onGetRTP(pkt,bKeyPos);
// _pRtspSrc->onGetRTP(pkt,bKeyPos);
// };
// GET_CONFIG_AND_REGISTER(uint32_t,audioMtu,Config::Rtp::kAudioMtuSize);
// m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc1, audioMtu,m_pParser->getAudioSampleRate()));
// _pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc1, audioMtu,_pParser->getAudioSampleRate()));
//
// char configStr[32];
// const string & strAacCfg = m_pParser->getAudioCfg();
// const string & strAacCfg = _pParser->getAudioCfg();
// snprintf(configStr, sizeof(configStr), "%02X%02x", strAacCfg[0], strAacCfg[1]);
// strSDP += StrPrinter << "m=audio 0 RTP/AVP " << m_pRtpMaker_aac->getPlayloadType()
// strSDP += StrPrinter << "m=audio 0 RTP/AVP " << _pRtpMaker_aac->getPlayloadType()
// << "\r\n" << endl;
// strSDP += "b=AS:96\r\n";
// strSDP += StrPrinter << "a=rtpmap:" << m_pRtpMaker_aac->getPlayloadType()
// << " MPEG4-GENERIC/" << m_pRtpMaker_aac->getSampleRate() << "\r\n"
// strSDP += StrPrinter << "a=rtpmap:" << _pRtpMaker_aac->getPlayloadType()
// << " MPEG4-GENERIC/" << _pRtpMaker_aac->getSampleRate() << "\r\n"
// << endl;
// strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_aac->getPlayloadType()
// strSDP += StrPrinter << "a=fmtp:" << _pRtpMaker_aac->getPlayloadType()
// << " streamtype=5;profile-level-id=1;mode=AAC-hbr;"
// << "sizelength=13;indexlength=3;indexdeltalength=3;config="
// << endl;
// strSDP.append(configStr, 4);
// strSDP += "\r\n";
// strSDP += StrPrinter << "a=control:trackID=" << m_pRtpMaker_aac->getInterleaved() / 2
// strSDP += StrPrinter << "a=control:trackID=" << _pRtpMaker_aac->getInterleaved() / 2
// << "\r\n" << endl;
// }
m_pRtspSrc.reset(new RtspMediaSource(getVhost(),getApp(),getId()));
m_pRtspSrc->setListener(m_listener);
m_pRtspSrc->onGetSDP(strSDP);
_pRtspSrc.reset(new RtspMediaSource(getVhost(),getApp(),getId()));
_pRtspSrc->setListener(_listener);
_pRtspSrc->onGetSDP(strSDP);
}

View File

@ -65,12 +65,12 @@ public:
void onGetMetaData(const AMFValue &_metadata) override {
try {
m_pParser.reset(new RtmpParser(_metadata));
m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser,m_bEnableHls,m_bEnableMp4));
_pParser.reset(new RtmpParser(_metadata));
_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),_pParser,_bEnableHls,_bEnableMp4));
//todo(xzl) 修复此处
// m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1));
// m_pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1));
// _pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAAC, this, placeholders::_1));
// _pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1));
} catch (exception &ex) {
WarnL << ex.what();
}
@ -78,23 +78,23 @@ public:
}
void onGetMedia(const RtmpPacket::Ptr &pkt) override {
if (m_pParser) {
if (!m_pRtspSrc && m_pParser->isInited()) {
if (_pParser) {
if (!_pRtspSrc && _pParser->isInited()) {
makeSDP();
}
m_pParser->inputRtmp(pkt);
_pParser->inputRtmp(pkt);
}
RtmpMediaSource::onGetMedia(pkt);
}
private:
RtmpParser::Ptr m_pParser;
RtspMediaSource::Ptr m_pRtspSrc;
RtpMaker_AAC::Ptr m_pRtpMaker_aac;
RtpMaker_H264::Ptr m_pRtpMaker_h264;
MediaRecorder::Ptr m_pRecorder;
bool m_bEnableHls;
bool m_bEnableMp4;
RtmpParser::Ptr _pParser;
RtspMediaSource::Ptr _pRtspSrc;
RtpMaker_AAC::Ptr _pRtpMaker_aac;
RtpMaker_H264::Ptr _pRtpMaker_h264;
MediaRecorder::Ptr _pRecorder;
bool _bEnableHls;
bool _bEnableMp4;
void onGetH264(const H264Frame &frame);
void onGetAAC(const AACFrame &frame);
void makeSDP();

View File

@ -36,24 +36,24 @@ using namespace ZL::Network;
/////////////////////AMFValue/////////////////////////////
inline void AMFValue::destroy() {
switch (m_type) {
switch (_type) {
case AMF_STRING:
if (m_value.string) {
delete m_value.string;
m_value.string = nullptr;
if (_value.string) {
delete _value.string;
_value.string = nullptr;
}
break;
case AMF_OBJECT:
case AMF_ECMA_ARRAY:
if (m_value.object) {
delete m_value.object;
m_value.object = nullptr;
if (_value.object) {
delete _value.object;
_value.object = nullptr;
}
break;
case AMF_STRICT_ARRAY:
if (m_value.array) {
delete m_value.array;
m_value.array = nullptr;
if (_value.array) {
delete _value.array;
_value.array = nullptr;
}
break;
default:
@ -61,16 +61,16 @@ inline void AMFValue::destroy() {
}
}
inline void AMFValue::init() {
switch (m_type) {
switch (_type) {
case AMF_OBJECT:
case AMF_ECMA_ARRAY:
m_value.object = new mapType;
_value.object = new mapType;
break;
case AMF_STRING:
m_value.string = new std::string;
_value.string = new std::string;
break;
case AMF_STRICT_ARRAY:
m_value.array = new arrayType;
_value.array = new arrayType;
break;
default:
@ -79,7 +79,7 @@ inline void AMFValue::init() {
}
AMFValue::AMFValue(AMFType type) :
m_type(type) {
_type(type) {
init();
}
@ -89,38 +89,38 @@ AMFValue::~AMFValue() {
}
AMFValue::AMFValue(const char *s) :
m_type(AMF_STRING) {
_type(AMF_STRING) {
init();
*m_value.string = s;
*_value.string = s;
}
AMFValue::AMFValue(const std::string &s) :
m_type(AMF_STRING) {
_type(AMF_STRING) {
init();
*m_value.string = s;
*_value.string = s;
}
AMFValue::AMFValue(double n) :
m_type(AMF_NUMBER) {
_type(AMF_NUMBER) {
init();
m_value.number = n;
_value.number = n;
}
AMFValue::AMFValue(int i) :
m_type(AMF_INTEGER) {
_type(AMF_INTEGER) {
init();
m_value.integer = i;
_value.integer = i;
}
AMFValue::AMFValue(bool b) :
m_type(AMF_BOOLEAN) {
_type(AMF_BOOLEAN) {
init();
m_value.boolean = b;
_value.boolean = b;
}
AMFValue::AMFValue(const AMFValue &from) :
m_type(AMF_NULL) {
_type(AMF_NULL) {
*this = from;
}
@ -134,27 +134,27 @@ AMFValue& AMFValue::operator =(const AMFValue &from) {
}
AMFValue& AMFValue::operator =(AMFValue &&from) {
destroy();
m_type = from.m_type;
_type = from._type;
init();
switch (m_type) {
switch (_type) {
case AMF_STRING:
*m_value.string = (*from.m_value.string);
*_value.string = (*from._value.string);
break;
case AMF_OBJECT:
case AMF_ECMA_ARRAY:
*m_value.object = (*from.m_value.object);
*_value.object = (*from._value.object);
break;
case AMF_STRICT_ARRAY:
*m_value.array = (*from.m_value.array);
*_value.array = (*from._value.array);
break;
case AMF_NUMBER:
m_value.number = from.m_value.number;
_value.number = from._value.number;
break;
case AMF_INTEGER:
m_value.integer = from.m_value.integer;
_value.integer = from._value.integer;
break;
case AMF_BOOLEAN:
m_value.boolean = from.m_value.boolean;
_value.boolean = from._value.boolean;
break;
default:
break;

View File

@ -61,13 +61,13 @@ public:
~AMFValue();
void clear() {
switch (m_type) {
switch (_type) {
case AMF_STRING:
m_value.string->clear();
_value.string->clear();
break;
case AMF_OBJECT:
case AMF_ECMA_ARRAY:
m_value.object->clear();
_value.object->clear();
break;
default:
break;
@ -75,23 +75,23 @@ public:
}
AMFType type() const {
return m_type;
return _type;
}
const std::string &as_string() const {
if(m_type != AMF_STRING){
if(_type != AMF_STRING){
throw std::runtime_error("AMF not a string");
}
return *m_value.string;
return *_value.string;
}
double as_number() const {
switch (m_type) {
switch (_type) {
case AMF_NUMBER:
return m_value.number;
return _value.number;
case AMF_INTEGER:
return m_value.integer;
return _value.integer;
case AMF_BOOLEAN:
return m_value.boolean;
return _value.boolean;
break;
default:
throw std::runtime_error("AMF not a number");
@ -99,13 +99,13 @@ public:
}
}
int as_integer() const {
switch (m_type) {
switch (_type) {
case AMF_NUMBER:
return m_value.number;
return _value.number;
case AMF_INTEGER:
return m_value.integer;
return _value.integer;
case AMF_BOOLEAN:
return m_value.boolean;
return _value.boolean;
break;
default:
throw std::runtime_error("AMF not a integer");
@ -113,13 +113,13 @@ public:
}
}
bool as_boolean() const {
switch (m_type) {
switch (_type) {
case AMF_NUMBER:
return m_value.number;
return _value.number;
case AMF_INTEGER:
return m_value.integer;
return _value.integer;
case AMF_BOOLEAN:
return m_value.boolean;
return _value.boolean;
break;
default:
throw std::runtime_error("AMF not a boolean");
@ -128,11 +128,11 @@ public:
}
const AMFValue &operator[](const char *str) const {
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
throw std::runtime_error("AMF not a object");
}
auto i = m_value.object->find(str);
if (i == m_value.object->end()) {
auto i = _value.object->find(str);
if (i == _value.object->end()) {
static AMFValue val(AMF_NULL);
return val;
}
@ -140,36 +140,36 @@ public:
}
template<typename FUN>
void object_for_each(const FUN &fun) const {
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
throw std::runtime_error("AMF not a object");
}
for (auto & pr : *(m_value.object)) {
for (auto & pr : *(_value.object)) {
fun(pr.first, pr.second);
}
}
operator bool() const{
return m_type != AMF_NULL;
return _type != AMF_NULL;
}
void set(const std::string &s, const AMFValue &val) {
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
throw std::runtime_error("AMF not a object");
}
m_value.object->emplace(s, val);
_value.object->emplace(s, val);
}
void add(const AMFValue &val) {
if (m_type != AMF_STRICT_ARRAY) {
if (_type != AMF_STRICT_ARRAY) {
throw std::runtime_error("AMF not a array");
}
assert(m_type == AMF_STRICT_ARRAY);
m_value.array->push_back(val);
assert(_type == AMF_STRICT_ARRAY);
_value.array->push_back(val);
}
private:
typedef std::map<std::string, AMFValue> mapType;
typedef std::vector<AMFValue> arrayType;
AMFType m_type;
AMFType _type;
union {
std::string *string;
double number;
@ -177,20 +177,20 @@ private:
bool boolean;
mapType *object;
arrayType *array;
} m_value;
} _value;
friend class AMFEncoder;
const mapType &getMap() const {
if (m_type != AMF_OBJECT && m_type != AMF_ECMA_ARRAY) {
if (_type != AMF_OBJECT && _type != AMF_ECMA_ARRAY) {
throw std::runtime_error("AMF not a object");
}
return *m_value.object;
return *_value.object;
}
const arrayType &getArr() const {
if (m_type != AMF_STRICT_ARRAY) {
if (_type != AMF_STRICT_ARRAY) {
throw std::runtime_error("AMF not a array");
}
return *m_value.array;
return *_value.array;
}
inline void destroy();
inline void init();

View File

@ -67,7 +67,7 @@ void AACRtmpEncoder::inputFrame(const Frame::Ptr &frame) {
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
//////////header
uint8_t is_config = false;
rtmpPkt->strBuf.push_back(m_ui8AudioFlags);
rtmpPkt->strBuf.push_back(_ui8AudioFlags);
rtmpPkt->strBuf.push_back(!is_config);
rtmpPkt->strBuf.append(frame->data() + frame->prefixSize(), frame->size() - frame->prefixSize());
@ -108,12 +108,12 @@ void AACRtmpEncoder::makeAudioConfigPkt() {
uint8_t flvSampleBit = iSampleBit == 16;
uint8_t flvAudioType = 10; //aac
m_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
RtmpPacket::Ptr rtmpPkt = ResourcePoolHelper<RtmpPacket>::obtainObj();
//////////header
uint8_t is_config = true;
rtmpPkt->strBuf.push_back(m_ui8AudioFlags);
rtmpPkt->strBuf.push_back(_ui8AudioFlags);
rtmpPkt->strBuf.push_back(!is_config);
rtmpPkt->strBuf.append(_aac_cfg);

View File

@ -61,7 +61,7 @@ public:
private:
void makeAudioConfigPkt();
uint8_t m_ui8AudioFlags;
uint8_t _ui8AudioFlags;
};
}//namespace Rtmp

View File

@ -6,7 +6,7 @@
H264RtmpDecoder::H264RtmpDecoder() {
m_h264frame = obtainFrame();
_h264frame = obtainFrame();
}
H264Frame::Ptr H264RtmpDecoder::obtainFrame() {
@ -26,12 +26,12 @@ bool H264RtmpDecoder::inputRtmp(const RtmpPacket::Ptr &rtmp, bool key_pos) {
bool H264RtmpDecoder::decodeRtmp(const RtmpPacket::Ptr &pkt) {
if (pkt->isCfgFrame()) {
//缓存sps pps后续插入到I帧之前
m_sps = pkt->getH264SPS();
m_pps = pkt->getH264PPS();
_sps = pkt->getH264SPS();
_pps = pkt->getH264PPS();
return false;
}
if (m_sps.size()) {
if (_sps.size()) {
uint32_t iTotalLen = pkt->strBuf.size();
uint32_t iOffset = 5;
while(iOffset + 4 < iTotalLen){
@ -54,8 +54,8 @@ inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t
switch (pcData[0] & 0x1F) {
case 5: {
//I frame
onGetH264(m_sps.data(), m_sps.length(), ui32TimeStamp);
onGetH264(m_pps.data(), m_pps.length(), ui32TimeStamp);
onGetH264(_sps.data(), _sps.length(), ui32TimeStamp);
onGetH264(_pps.data(), _pps.length(), ui32TimeStamp);
}
case 1: {
//I or P or B frame
@ -68,14 +68,14 @@ inline void H264RtmpDecoder::onGetH264_l(const char* pcData, int iLen, uint32_t
}
}
inline void H264RtmpDecoder::onGetH264(const char* pcData, int iLen, uint32_t ui32TimeStamp) {
m_h264frame->type = pcData[0] & 0x1F;
m_h264frame->timeStamp = ui32TimeStamp;
m_h264frame->buffer.assign("\x0\x0\x0\x1", 4); //添加264头
m_h264frame->buffer.append(pcData, iLen);
_h264frame->type = pcData[0] & 0x1F;
_h264frame->timeStamp = ui32TimeStamp;
_h264frame->buffer.assign("\x0\x0\x0\x1", 4); //添加264头
_h264frame->buffer.append(pcData, iLen);
//写入环形缓存
RtmpCodec::inputFrame(m_h264frame);
m_h264frame = obtainFrame();
RtmpCodec::inputFrame(_h264frame);
_h264frame = obtainFrame();
}
@ -95,9 +95,9 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
switch (type){
case 7:{
//sps
if(m_sps.empty()){
m_sps = string(pcData,iLen);
if(!m_pps.empty()){
if(_sps.empty()){
_sps = string(pcData,iLen);
if(!_pps.empty()){
makeVideoConfigPkt();
}
}
@ -105,9 +105,9 @@ void H264RtmpEncoder::inputFrame(const Frame::Ptr &frame) {
break;
case 8:{
//pps
if(m_pps.empty()){
m_pps = string(pcData,iLen);
if(!m_sps.empty()){
if(_pps.empty()){
_pps = string(pcData,iLen);
if(!_sps.empty()){
makeVideoConfigPkt();
}
}
@ -158,23 +158,23 @@ void H264RtmpEncoder::makeVideoConfigPkt() {
////////////sps
rtmpPkt->strBuf.push_back(1); // version
//DebugL<<hexdump(m_sps.data(), m_sps.size());
rtmpPkt->strBuf.push_back(m_sps[1]); // profile
rtmpPkt->strBuf.push_back(m_sps[2]); // compat
rtmpPkt->strBuf.push_back(m_sps[3]); // level
//DebugL<<hexdump(_sps.data(), _sps.size());
rtmpPkt->strBuf.push_back(_sps[1]); // profile
rtmpPkt->strBuf.push_back(_sps[2]); // compat
rtmpPkt->strBuf.push_back(_sps[3]); // level
rtmpPkt->strBuf.push_back(0xff); // 6 bits reserved + 2 bits nal size length - 1 (11)
rtmpPkt->strBuf.push_back(0xe1); // 3 bits reserved + 5 bits number of sps (00001)
uint16_t size = m_sps.size();
uint16_t size = _sps.size();
size = htons(size);
rtmpPkt->strBuf.append((char *) &size, 2);
rtmpPkt->strBuf.append(m_sps);
rtmpPkt->strBuf.append(_sps);
/////////////pps
rtmpPkt->strBuf.push_back(1); // version
size = m_pps.size();
size = _pps.size();
size = htons(size);
rtmpPkt->strBuf.append((char *) &size, 2);
rtmpPkt->strBuf.append(m_pps);
rtmpPkt->strBuf.append(_pps);
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_VIDEO;

View File

@ -40,9 +40,9 @@ protected:
void onGetH264(const char *pcData, int iLen, uint32_t ui32TimeStamp);
H264Frame::Ptr obtainFrame();
protected:
H264Frame::Ptr m_h264frame;
string m_sps;
string m_pps;
H264Frame::Ptr _h264frame;
string _sps;
string _pps;
};
/**

View File

@ -50,17 +50,17 @@ static uint32_t addressToInt(const string &ip){
}
std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
lock_guard<recursive_mutex> lck(m_mtx);
lock_guard<recursive_mutex> lck(_mtx);
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;
if(_iAddr > addrMax || _iAddr == 0){
_iAddr = addrMin;
}
auto iGotAddr = m_iAddr++;
if(m_setBadAddr.find(iGotAddr) != m_setBadAddr.end()){
auto iGotAddr = _iAddr++;
if(_setBadAddr.find(iGotAddr) != _setBadAddr.end()){
//已经分配过了
if(iTry){
return obtain(--iTry);
@ -69,7 +69,7 @@ std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
ErrorL;
return nullptr;
}
m_setBadAddr.emplace(iGotAddr);
_setBadAddr.emplace(iGotAddr);
std::shared_ptr<uint32_t> ret(new uint32_t(iGotAddr),[](uint32_t *ptr){
MultiCastAddressMaker::Instance().release(*ptr);
delete ptr;
@ -77,8 +77,8 @@ std::shared_ptr<uint32_t> MultiCastAddressMaker::obtain(uint32_t iTry) {
return ret;
}
void MultiCastAddressMaker::release(uint32_t iAddr){
lock_guard<recursive_mutex> lck(m_mtx);
m_setBadAddr.erase(iAddr);
lock_guard<recursive_mutex> lck(_mtx);
_setBadAddr.erase(iAddr);
}
@ -86,16 +86,16 @@ recursive_mutex RtpBroadCaster::g_mtx;
unordered_map<string, weak_ptr<RtpBroadCaster> > RtpBroadCaster::g_mapBroadCaster;
void RtpBroadCaster::setDetachCB(void* listener, const onDetach& cb) {
lock_guard<recursive_mutex> lck(m_mtx);
lock_guard<recursive_mutex> lck(_mtx);
if(cb){
m_mapDetach.emplace(listener,cb);
_mapDetach.emplace(listener,cb);
}else{
m_mapDetach.erase(listener);
_mapDetach.erase(listener);
}
}
RtpBroadCaster::~RtpBroadCaster() {
m_pReader->setReadCB(nullptr);
m_pReader->setDetachCB(nullptr);
_pReader->setReadCB(nullptr);
_pReader->setDetachCB(nullptr);
DebugL;
}
RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) {
@ -104,55 +104,55 @@ RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strVhost,c
auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl;
throw std::runtime_error(strErr);
}
m_multiAddr = MultiCastAddressMaker::Instance().obtain();
_multiAddr = MultiCastAddressMaker::Instance().obtain();
for(auto i = 0; i < 2; i++){
m_apUdpSock[i].reset(new Socket());
if(!m_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){
_apUdpSock[i].reset(new Socket());
if(!_apUdpSock[i]->bindUdpSock(0, strLocalIp.data())){
auto strErr = StrPrinter << "绑定UDP端口失败:" << strLocalIp << endl;
throw std::runtime_error(strErr);
}
auto fd = m_apUdpSock[i]->rawFD();
auto fd = _apUdpSock[i]->rawFD();
GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,Config::MultiCast::kUdpTTL);
SockUtil::setMultiTTL(fd, udpTTL);
SockUtil::setMultiLOOP(fd, false);
SockUtil::setMultiIF(fd, strLocalIp.data());
struct sockaddr_in &peerAddr = m_aPeerUdpAddr[i];
struct sockaddr_in &peerAddr = _aPeerUdpAddr[i];
peerAddr.sin_family = AF_INET;
peerAddr.sin_port = htons(m_apUdpSock[i]->get_local_port());
peerAddr.sin_addr.s_addr = htonl(*m_multiAddr);
peerAddr.sin_port = htons(_apUdpSock[i]->get_local_port());
peerAddr.sin_addr.s_addr = htonl(*_multiAddr);
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
}
m_pReader = src->getRing()->attach();
m_pReader->setReadCB([this](const RtpPacket::Ptr &pkt){
_pReader = src->getRing()->attach();
_pReader->setReadCB([this](const RtpPacket::Ptr &pkt){
int i = (int)(pkt->type);
auto &pSock = m_apUdpSock[i];
auto &peerAddr = m_aPeerUdpAddr[i];
auto &pSock = _apUdpSock[i];
auto &peerAddr = _aPeerUdpAddr[i];
BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
pSock->send(buffer,SOCKET_DEFAULE_FLAGS | FLAG_MORE,(struct sockaddr *)(&peerAddr));
});
m_pReader->setDetachCB([this](){
unordered_map<void * , onDetach > m_mapDetach_copy;
_pReader->setDetachCB([this](){
unordered_map<void * , onDetach > _mapDetach_copy;
{
lock_guard<recursive_mutex> lck(m_mtx);
m_mapDetach_copy = std::move(m_mapDetach);
lock_guard<recursive_mutex> lck(_mtx);
_mapDetach_copy = std::move(_mapDetach);
}
for(auto &pr : m_mapDetach_copy){
for(auto &pr : _mapDetach_copy){
pr.second();
}
});
DebugL << MultiCastAddressMaker::toString(*m_multiAddr) << " "
<< m_apUdpSock[0]->get_local_port() << " "
<< m_apUdpSock[1]->get_local_port() << " "
DebugL << MultiCastAddressMaker::toString(*_multiAddr) << " "
<< _apUdpSock[0]->get_local_port() << " "
<< _apUdpSock[1]->get_local_port() << " "
<< strVhost << " "
<< strApp << " " << strStream;
}
uint16_t RtpBroadCaster::getPort(TrackType trackType){
return m_apUdpSock[trackType]->get_local_port();
return _apUdpSock[trackType]->get_local_port();
}
string RtpBroadCaster::getIP(){
return inet_ntoa(m_aPeerUdpAddr[0].sin_addr);
return inet_ntoa(_aPeerUdpAddr[0].sin_addr);
}
RtpBroadCaster::Ptr RtpBroadCaster::make(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream){
try{

View File

@ -64,9 +64,9 @@ public:
private:
MultiCastAddressMaker(){};
void release(uint32_t iAddr);
uint32_t m_iAddr = 0;
recursive_mutex m_mtx;
unordered_set<uint32_t> m_setBadAddr;
uint32_t _iAddr = 0;
recursive_mutex _mtx;
unordered_set<uint32_t> _setBadAddr;
};
class RtpBroadCaster {
public:
@ -82,12 +82,12 @@ private:
static unordered_map<string , weak_ptr<RtpBroadCaster> > g_mapBroadCaster;
static Ptr make(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream);
std::shared_ptr<uint32_t> m_multiAddr;
recursive_mutex m_mtx;
unordered_map<void * , onDetach > m_mapDetach;
RtspMediaSource::RingType::RingReader::Ptr m_pReader;
Socket::Ptr m_apUdpSock[2];
struct sockaddr_in m_aPeerUdpAddr[2];
std::shared_ptr<uint32_t> _multiAddr;
recursive_mutex _mtx;
unordered_map<void * , onDetach > _mapDetach;
RtspMediaSource::RingType::RingReader::Ptr _pReader;
Socket::Ptr _apUdpSock[2];
struct sockaddr_in _aPeerUdpAddr[2];
RtpBroadCaster(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream);

View File

@ -68,7 +68,7 @@ RtpParser::RtpParser(const string& sdp) {
break;
}
}
m_fDuration = getTimeInSDP(sdp);
_fDuration = getTimeInSDP(sdp);
}
bool RtpParser::inputRtp(const RtpPacket::Ptr & rtp) {

View File

@ -51,7 +51,7 @@ public:
bool inputRtp(const RtpPacket::Ptr &rtp);
float getDuration() const override {
return m_fDuration;
return _fDuration;
}
/**
@ -76,7 +76,7 @@ private:
inline void onGetAudioTrack(const RtspTrack &audio);
inline void onGetVideoTrack(const RtspTrack &video);
private:
float m_fDuration = 0;
float _fDuration = 0;
AudioTrack::Ptr _audioTrack;
VideoTrack::Ptr _videoTrack;
RtpCodec::Ptr _audioRtpDecoder;

View File

@ -83,79 +83,79 @@ public:
break;
}
if (start == buf) {
m_strMethod = FindField(line.c_str(), NULL, " ");
m_strFullUrl = FindField(line.c_str(), " ", " ");
auto args_pos = m_strFullUrl.find('?');
_strMethod = FindField(line.c_str(), NULL, " ");
_strFullUrl = FindField(line.c_str(), " ", " ");
auto args_pos = _strFullUrl.find('?');
if(args_pos != string::npos){
m_strUrl = m_strFullUrl.substr(0,args_pos);
m_mapUrlArgs = parseArgs(m_strFullUrl.substr(args_pos + 1 ));
_strUrl = _strFullUrl.substr(0,args_pos);
_mapUrlArgs = parseArgs(_strFullUrl.substr(args_pos + 1 ));
}else{
m_strUrl = m_strFullUrl;
_strUrl = _strFullUrl;
}
m_strTail = FindField(line.c_str(), (m_strFullUrl + " ").c_str(), NULL);
_strTail = FindField(line.c_str(), (_strFullUrl + " ").c_str(), NULL);
} else {
auto field = FindField(line.c_str(), NULL, ": ");
auto value = FindField(line.c_str(), ": ", NULL);
if (field.size() != 0) {
m_mapHeaders[field] = value;
_mapHeaders[field] = value;
}
}
start = start + line.size() + 2;
if (strncmp(start, "\r\n", 2) == 0) { //协议解析完毕
m_strContent = FindField(start, "\r\n", NULL);
_strContent = FindField(start, "\r\n", NULL);
break;
}
}
}
const string& Method() const {
//rtsp方法
return m_strMethod;
return _strMethod;
}
const string& Url() const {
//rtsp url
return m_strUrl;
return _strUrl;
}
const string& FullUrl() const {
//rtsp url with args
return m_strFullUrl;
return _strFullUrl;
}
const string& Tail() const {
//RTSP/1.0
return m_strTail;
return _strTail;
}
const string& operator[](const char *name) const {
//rtsp field
auto it = m_mapHeaders.find(name);
if (it == m_mapHeaders.end()) {
return m_strNull;
auto it = _mapHeaders.find(name);
if (it == _mapHeaders.end()) {
return _strNull;
}
return it->second;
}
const string& Content() const {
return m_strContent;
return _strContent;
}
void Clear() {
m_strMethod.clear();
m_strUrl.clear();
m_strFullUrl.clear();
m_strTail.clear();
m_strContent.clear();
m_mapHeaders.clear();
m_mapUrlArgs.clear();
_strMethod.clear();
_strUrl.clear();
_strFullUrl.clear();
_strTail.clear();
_strContent.clear();
_mapHeaders.clear();
_mapUrlArgs.clear();
}
void setUrl(const string& url) {
this->m_strUrl = url;
this->_strUrl = url;
}
void setContent(const string& content) {
this->m_strContent = content;
this->_strContent = content;
}
StrCaseMap& getValues() const {
return m_mapHeaders;
return _mapHeaders;
}
StrCaseMap& getUrlArgs() const {
return m_mapUrlArgs;
return _mapUrlArgs;
}
static StrCaseMap parseArgs(const string &str,const char *pair_delim = "&", const char *key_delim = "="){
@ -170,14 +170,14 @@ public:
}
private:
string m_strMethod;
string m_strUrl;
string m_strTail;
string m_strContent;
string m_strNull;
string m_strFullUrl;
mutable StrCaseMap m_mapHeaders;
mutable StrCaseMap m_mapUrlArgs;
string _strMethod;
string _strUrl;
string _strTail;
string _strContent;
string _strNull;
string _strFullUrl;
mutable StrCaseMap _mapHeaders;
mutable StrCaseMap _mapUrlArgs;
};
typedef struct {

View File

@ -60,46 +60,46 @@ public:
RtspMediaSource(const string &strVhost,const string &strApp, const string &strId) :
MediaSource(RTSP_SCHEMA,strVhost,strApp,strId),
m_pRing(new RingBuffer<RtpPacket::Ptr>()) {
_pRing(new RingBuffer<RtpPacket::Ptr>()) {
}
virtual ~RtspMediaSource() {}
const RingType::Ptr &getRing() const {
//获取媒体源的rtp环形缓冲
return m_pRing;
return _pRing;
}
const string& getSdp() const {
//获取该源的媒体描述信息
return m_strSdp;
return _strSdp;
}
virtual uint32_t getSsrc(TrackType trackType) {
return m_mapTracks[trackType].ssrc;
return _mapTracks[trackType].ssrc;
}
virtual uint16_t getSeqence(TrackType trackType) {
return m_mapTracks[trackType].seq;
return _mapTracks[trackType].seq;
}
virtual uint32_t getTimestamp(TrackType trackType) {
return m_mapTracks[trackType].timeStamp;
return _mapTracks[trackType].timeStamp;
}
virtual void onGetSDP(const string& sdp) {
//派生类设置该媒体源媒体描述信息
m_strSdp = sdp;
_strSdp = sdp;
regist();
}
virtual void onGetRTP(const RtpPacket::Ptr &rtppt, bool keyPos) {
auto &trackRef = m_mapTracks[rtppt->type];
auto &trackRef = _mapTracks[rtppt->type];
trackRef.seq = rtppt->sequence;
trackRef.timeStamp = rtppt->timeStamp;
trackRef.ssrc = rtppt->ssrc;
trackRef.type = rtppt->type;
m_pRing->write(rtppt,keyPos);
_pRing->write(rtppt,keyPos);
}
protected:
unordered_map<int, RtspTrack> m_mapTracks;
string m_strSdp; //媒体描述信息
RingType::Ptr m_pRing; //rtp环形缓冲
unordered_map<int, RtspTrack> _mapTracks;
string _strSdp; //媒体描述信息
RingType::Ptr _pRing; //rtp环形缓冲
};
} /* namespace Rtsp */

View File

@ -44,9 +44,9 @@ namespace ZL {
namespace Rtsp {
#define POP_HEAD(trackidx) \
auto it = m_amapRtpSort[trackidx].begin(); \
auto it = _amapRtpSort[trackidx].begin(); \
onRecvRTP_l(it->second, trackidx); \
m_amapRtpSort[trackidx].erase(it);
_amapRtpSort[trackidx].erase(it);
#define RTP_BUF_SIZE (4 * 1024)
@ -54,48 +54,48 @@ const char kRtspMd5Nonce[] = "rtsp_md5_nonce";
const char kRtspRealm[] = "rtsp_realm";
RtspPlayer::RtspPlayer(void){
m_pktPool.setSize(64);
_pktPool.setSize(64);
}
RtspPlayer::~RtspPlayer(void) {
teardown();
if (m_pucRtpBuf) {
delete[] m_pucRtpBuf;
m_pucRtpBuf = nullptr;
if (_pucRtpBuf) {
delete[] _pucRtpBuf;
_pucRtpBuf = nullptr;
}
DebugL<<endl;
}
void RtspPlayer::teardown(){
if (alive()) {
sendRtspRequest("TEARDOWN" ,m_strContentBase);
sendRtspRequest("TEARDOWN" ,_strContentBase);
shutdown();
}
erase(kRtspMd5Nonce);
erase(kRtspRealm);
m_uiTrackCnt = 0;
m_onHandshake = nullptr;
m_uiRtpBufLen = 0;
m_strSession.clear();
m_uiCseq = 1;
m_strContentBase.clear();
CLEAR_ARR(m_apUdpSock);
CLEAR_ARR(m_aui16LastSeq)
CLEAR_ARR(m_aui16FirstSeq)
CLEAR_ARR(m_aui32SsrcErrorCnt)
CLEAR_ARR(m_aui64RtpRecv)
CLEAR_ARR(m_aui64SeqOkCnt)
CLEAR_ARR(m_abSortStarted)
CLEAR_ARR(m_aui64RtpRecv)
CLEAR_ARR(m_aui16NowSeq)
m_amapRtpSort[0].clear();
m_amapRtpSort[1].clear();
_uiTrackCnt = 0;
_onHandshake = nullptr;
_uiRtpBufLen = 0;
_strSession.clear();
_uiCseq = 1;
_strContentBase.clear();
CLEAR_ARR(_apUdpSock);
CLEAR_ARR(_aui16LastSeq)
CLEAR_ARR(_aui16FirstSeq)
CLEAR_ARR(_aui32SsrcErrorCnt)
CLEAR_ARR(_aui64RtpRecv)
CLEAR_ARR(_aui64SeqOkCnt)
CLEAR_ARR(_abSortStarted)
CLEAR_ARR(_aui64RtpRecv)
CLEAR_ARR(_aui16NowSeq)
_amapRtpSort[0].clear();
_amapRtpSort[1].clear();
m_pBeatTimer.reset();
m_pPlayTimer.reset();
m_pRtpTimer.reset();
m_fSeekTo = 0;
CLEAR_ARR(m_adFistStamp);
CLEAR_ARR(m_adNowStamp);
_pBeatTimer.reset();
_pPlayTimer.reset();
_pRtpTimer.reset();
_fSeekTo = 0;
CLEAR_ARR(_adFistStamp);
CLEAR_ARR(_adNowStamp);
}
void RtspPlayer::play(const char* strUrl){
@ -131,9 +131,9 @@ void RtspPlayer::play(const char* strUrl, const char *strUser, const char *strPw
(*this)[kRtspPwdIsMD5] = false;
}
m_eType = eType;
if (m_eType == RTP_TCP && !m_pucRtpBuf) {
m_pucRtpBuf = new uint8_t[RTP_BUF_SIZE];
_eType = eType;
if (_eType == RTP_TCP && !_pucRtpBuf) {
_pucRtpBuf = new uint8_t[RTP_BUF_SIZE];
}
auto ip = FindField(strUrl, "://", "/");
if (!ip.size()) {
@ -148,7 +148,7 @@ void RtspPlayer::play(const char* strUrl, const char *strUser, const char *strPw
ip = FindField(ip.c_str(), NULL, ":");
}
m_strUrl = strUrl;
_strUrl = strUrl;
if(!(*this)[PlayerBase::kNetAdapter].empty()){
setNetAdapter((*this)[PlayerBase::kNetAdapter]);
}
@ -164,7 +164,7 @@ void RtspPlayer::onConnect(const SockException &err){
sendDescribe();
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
m_pPlayTimer.reset( new Timer(10, [weakSelf]() {
_pPlayTimer.reset( new Timer(10, [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return false;
@ -178,7 +178,7 @@ void RtspPlayer::onConnect(const SockException &err){
void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) {
const char *buf = pBuf->data();
int size = pBuf->size();
if (m_onHandshake) {
if (_onHandshake) {
//rtsp回复
int offset = 0;
while(offset < size - 4){
@ -203,16 +203,16 @@ void RtspPlayer::onRecv(const Buffer::Ptr& pBuf) {
}
}
if (m_eType == RTP_TCP && m_pucRtpBuf) {
if (_eType == RTP_TCP && _pucRtpBuf) {
//RTP data
while (size > 0) {
int added = RTP_BUF_SIZE - m_uiRtpBufLen;
int added = RTP_BUF_SIZE - _uiRtpBufLen;
added = (added > size ? size : added);
memcpy(m_pucRtpBuf + m_uiRtpBufLen, buf, added);
m_uiRtpBufLen += added;
memcpy(_pucRtpBuf + _uiRtpBufLen, buf, added);
_uiRtpBufLen += added;
size -= added;
buf += added;
splitRtp(m_pucRtpBuf, m_uiRtpBufLen);
splitRtp(_pucRtpBuf, _uiRtpBufLen);
}
}
}
@ -263,13 +263,13 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
StrPrinter << "DESCRIBE:" << parser.Url() << " " << parser.Tail() << endl);
}
auto strSdp = parser.Content();
m_strContentBase = parser["Content-Base"];
_strContentBase = parser["Content-Base"];
if(m_strContentBase.empty()){
m_strContentBase = m_strUrl;
if(_strContentBase.empty()){
_strContentBase = _strUrl;
}
if (m_strContentBase.back() == '/') {
m_strContentBase.pop_back();
if (_strContentBase.back() == '/') {
_strContentBase.pop_back();
}
auto iLen = atoi(parser["Content-Length"].data());
@ -278,26 +278,26 @@ void RtspPlayer::handleResDESCRIBE(const Parser& parser) {
}
//解析sdp
m_uiTrackCnt = parserSDP(strSdp, m_aTrackInfo);
for (unsigned int i=0; i<m_uiTrackCnt; i++) {
m_aTrackInfo[i].ssrc=0;
m_aui32SsrcErrorCnt[i]=0;
_uiTrackCnt = parserSDP(strSdp, _aTrackInfo);
for (unsigned int i=0; i<_uiTrackCnt; i++) {
_aTrackInfo[i].ssrc=0;
_aui32SsrcErrorCnt[i]=0;
}
if (!m_uiTrackCnt) {
if (!_uiTrackCnt) {
throw std::runtime_error("解析SDP失败");
}
if (!onCheckSDP(strSdp, m_aTrackInfo, m_uiTrackCnt)) {
if (!onCheckSDP(strSdp, _aTrackInfo, _uiTrackCnt)) {
throw std::runtime_error("onCheckSDP faied");
}
sendSetup(0);
}
//发送SETUP命令
bool RtspPlayer::sendSetup(unsigned int trackIndex) {
m_onHandshake = std::bind(&RtspPlayer::handleResSETUP,this, placeholders::_1,trackIndex);
_onHandshake = std::bind(&RtspPlayer::handleResSETUP,this, placeholders::_1,trackIndex);
auto &track = m_aTrackInfo[trackIndex];
auto baseUrl = m_strContentBase + "/" + track.controlSuffix;
switch (m_eType) {
auto &track = _aTrackInfo[trackIndex];
auto baseUrl = _strContentBase + "/" + track.controlSuffix;
switch (_eType) {
case RTP_TCP: {
StrCaseMap header;
header["Transport"] = StrPrinter << "RTP/AVP/TCP;unicast;interleaved=" << track.type * 2 << "-" << track.type * 2 + 1;
@ -311,12 +311,12 @@ bool RtspPlayer::sendSetup(unsigned int trackIndex) {
}
break;
case RTP_UDP: {
m_apUdpSock[trackIndex].reset(new Socket());
if (!m_apUdpSock[trackIndex]->bindUdpSock(0, get_local_ip().data())) {
m_apUdpSock[trackIndex].reset();
_apUdpSock[trackIndex].reset(new Socket());
if (!_apUdpSock[trackIndex]->bindUdpSock(0, get_local_ip().data())) {
_apUdpSock[trackIndex].reset();
throw std::runtime_error("open udp sock err");
}
int port = m_apUdpSock[trackIndex]->get_local_port();
int port = _apUdpSock[trackIndex]->get_local_port();
StrCaseMap header;
header["Transport"] = StrPrinter << "RTP/AVP;unicast;client_port=" << port << "-" << port + 1;
return sendRtspRequest("SETUP",baseUrl,header);
@ -334,33 +334,33 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
StrPrinter << "SETUP:" << parser.Url() << " " << parser.Tail() << endl);
}
if (uiTrackIndex == 0) {
m_strSession = parser["Session"];
m_strSession.append(";");
m_strSession = FindField(m_strSession.data(), nullptr, ";");
_strSession = parser["Session"];
_strSession.append(";");
_strSession = FindField(_strSession.data(), nullptr, ";");
}
auto strTransport = parser["Transport"];
if(strTransport.find("TCP") != string::npos){
m_eType = RTP_TCP;
_eType = RTP_TCP;
}else if(strTransport.find("multicast") != string::npos){
m_eType = RTP_MULTICAST;
_eType = RTP_MULTICAST;
}else{
m_eType = RTP_UDP;
_eType = RTP_UDP;
}
if(m_eType == RTP_TCP) {
if(_eType == RTP_TCP) {
string interleaved = FindField( FindField((strTransport + ";").c_str(), "interleaved=", ";").c_str(), NULL, "-");
m_aTrackInfo[uiTrackIndex].interleaved = atoi(interleaved.c_str());
_aTrackInfo[uiTrackIndex].interleaved = atoi(interleaved.c_str());
}else{
const char *strPos = (m_eType == RTP_MULTICAST ? "port=" : "server_port=") ;
const char *strPos = (_eType == RTP_MULTICAST ? "port=" : "server_port=") ;
auto port_str = FindField((strTransport + ";").c_str(), strPos, ";");
uint16_t port = atoi(FindField(port_str.c_str(), NULL, "-").c_str());
auto &pUdpSockRef = m_apUdpSock[uiTrackIndex];
auto &pUdpSockRef = _apUdpSock[uiTrackIndex];
if(!pUdpSockRef){
pUdpSockRef.reset(new Socket());
}
if (m_eType == RTP_MULTICAST) {
if (_eType == RTP_MULTICAST) {
auto multiAddr = FindField((strTransport + ";").c_str(), "destination=", ";");
if (!pUdpSockRef->bindUdpSock(port, "0.0.0.0")) {
pUdpSockRef.reset();
@ -379,14 +379,14 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
}
}
if (uiTrackIndex < m_uiTrackCnt - 1) {
if (uiTrackIndex < _uiTrackCnt - 1) {
//需要继续发送SETUP命令
sendSetup(uiTrackIndex + 1);
return;
}
for (unsigned int i = 0; i < m_uiTrackCnt && m_eType != RTP_TCP; i++) {
auto &pUdpSockRef = m_apUdpSock[i];
for (unsigned int i = 0; i < _uiTrackCnt && _eType != RTP_TCP; i++) {
auto &pUdpSockRef = _apUdpSock[i];
if(!pUdpSockRef){
continue;
}
@ -406,7 +406,7 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
}
/////////////////////////心跳/////////////////////////////////
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
m_pBeatTimer.reset(new Timer(5, [weakSelf](){
_pBeatTimer.reset(new Timer(5, [weakSelf](){
auto strongSelf = weakSelf.lock();
if (!strongSelf){
return false;
@ -417,47 +417,47 @@ void RtspPlayer::handleResSETUP(const Parser &parser, unsigned int uiTrackIndex)
}
bool RtspPlayer::sendOptions() {
m_onHandshake = [](const Parser& parser){
_onHandshake = [](const Parser& parser){
return true;
};
return sendRtspRequest("OPTIONS",m_strContentBase);
return sendRtspRequest("OPTIONS",_strContentBase);
}
bool RtspPlayer::sendDescribe() {
//发送DESCRIBE命令后处理函数:handleResDESCRIBE
m_onHandshake = std::bind(&RtspPlayer::handleResDESCRIBE,this, placeholders::_1);
_onHandshake = std::bind(&RtspPlayer::handleResDESCRIBE,this, placeholders::_1);
StrCaseMap header;
header["Accept"] = "application/sdp";
return sendRtspRequest("DESCRIBE",m_strUrl,header);
return sendRtspRequest("DESCRIBE",_strUrl,header);
}
bool RtspPlayer::sendPause(bool bPause,float fTime){
if(!bPause){
//修改时间轴
m_aNowStampTicker[0].resetTime();
m_aNowStampTicker[1].resetTime();
_aNowStampTicker[0].resetTime();
_aNowStampTicker[1].resetTime();
float iTimeInc = fTime - getProgressTime();
for(unsigned int i = 0 ;i < m_uiTrackCnt ;i++){
if (m_aTrackInfo[i].type == TrackVideo) {
m_adFistStamp[i] = m_adNowStamp[i] + iTimeInc * 90000.0;
}else if (m_aTrackInfo[i].type == TrackAudio){
for(unsigned int i = 0 ;i < _uiTrackCnt ;i++){
if (_aTrackInfo[i].type == TrackVideo) {
_adFistStamp[i] = _adNowStamp[i] + iTimeInc * 90000.0;
}else if (_aTrackInfo[i].type == TrackAudio){
//todo(xzl) 修复此处
// m_adFistStamp[i] = m_adNowStamp[i] + iTimeInc * getAudioSampleRate();
// _adFistStamp[i] = _adNowStamp[i] + iTimeInc * getAudioSampleRate();
}
m_adNowStamp[i] = m_adFistStamp[i];
_adNowStamp[i] = _adFistStamp[i];
}
m_fSeekTo = fTime;
_fSeekTo = fTime;
}
//开启或暂停rtsp
m_onHandshake = std::bind(&RtspPlayer::handleResPAUSE,this, placeholders::_1,bPause);
_onHandshake = std::bind(&RtspPlayer::handleResPAUSE,this, placeholders::_1,bPause);
StrCaseMap header;
char buf[8];
sprintf(buf,"%.2f",fTime);
header["Range"] = StrPrinter << "npt=" << buf << "-";
return sendRtspRequest(bPause ? "PAUSE" : "PLAY",m_strContentBase,header);
return sendRtspRequest(bPause ? "PAUSE" : "PLAY",_strContentBase,header);
}
void RtspPlayer::pause(bool bPause) {
sendPause(bPause,getProgressTime());
@ -470,16 +470,16 @@ void RtspPlayer::handleResPAUSE(const Parser& parser, bool bPause) {
}
if (!bPause) {
//修正时间轴
m_aNowStampTicker[0].resetTime();
m_aNowStampTicker[1].resetTime();
_aNowStampTicker[0].resetTime();
_aNowStampTicker[1].resetTime();
auto strRange = parser["Range"];
if (strRange.size()) {
auto strStart = FindField(strRange.data(), "npt=", "-");
if (strStart == "now") {
strStart = "0";
}
m_fSeekTo = atof(strStart.data());
DebugL << "Range:" << m_fSeekTo << " " << strStart ;
_fSeekTo = atof(strStart.data());
DebugL << "Range:" << _fSeekTo << " " << strStart ;
}
auto strRtpInfo = parser["RTP-Info"];
if (strRtpInfo.size()) {
@ -490,14 +490,14 @@ void RtspPlayer::handleResPAUSE(const Parser& parser, bool bPause) {
auto strControlSuffix = strTrack.substr(1 + strTrack.rfind('/'),strTrack.find(';') - strTrack.rfind('/') - 1);
auto strRtpTime = FindField(strTrack.data(), "rtptime=", ";");
auto iIdx = getTrackIndexByControlSuffix(strControlSuffix);
m_adFistStamp[iIdx] = atoll(strRtpTime.data());
m_adNowStamp[iIdx] = m_adFistStamp[iIdx];
_adFistStamp[iIdx] = atoll(strRtpTime.data());
_adNowStamp[iIdx] = _adFistStamp[iIdx];
DebugL << "rtptime:" << strControlSuffix <<" " << strRtpTime;
}
}
onPlayResult_l(SockException(Err_success, "rtsp play success"));
} else {
m_pRtpTimer.reset();
_pRtpTimer.reset();
}
}
@ -518,8 +518,8 @@ int RtspPlayer::onProcess(const char* pcBuf) {
parser.setContent(strContent);
}
}
auto fun = m_onHandshake;
m_onHandshake = nullptr;
auto fun = _onHandshake;
_onHandshake = nullptr;
if(fun){
fun(parser);
}
@ -576,7 +576,7 @@ void RtspPlayer::splitRtp(unsigned char* pucRtp, unsigned int uiLen) {
uiLen -= (pos - rtp_ptr);
rtp_ptr = pos;
}
m_uiRtpBufLen = uiLen;
_uiRtpBufLen = uiLen;
if (rtp_ptr != pucRtp) {
memmove(pucRtp, rtp_ptr, uiLen);
}
@ -589,8 +589,8 @@ void RtspPlayer::splitRtp(unsigned char* pucRtp, unsigned int uiLen) {
bool RtspPlayer::handleOneRtp(int iTrackidx, unsigned char *pucData, unsigned int uiLen) {
auto &track = m_aTrackInfo[iTrackidx];
auto pt_ptr=m_pktPool.obtain();
auto &track = _aTrackInfo[iTrackidx];
auto pt_ptr=_pktPool.obtain();
auto &rtppt=*pt_ptr;
rtppt.interleaved = track.interleaved;
rtppt.length = uiLen + 4;
@ -613,13 +613,13 @@ bool RtspPlayer::handleOneRtp(int iTrackidx, unsigned char *pucData, unsigned in
} else if (track.ssrc != rtppt.ssrc) {
//ssrc错误
WarnL << "ssrc错误";
if (m_aui32SsrcErrorCnt[iTrackidx]++ > 10) {
if (_aui32SsrcErrorCnt[iTrackidx]++ > 10) {
track.ssrc = rtppt.ssrc;
WarnL << "ssrc更换!";
}
return false;
}
m_aui32SsrcErrorCnt[iTrackidx] = 0;
_aui32SsrcErrorCnt[iTrackidx] = 0;
rtppt.payload[0] = '$';
rtppt.payload[1] = rtppt.interleaved;
@ -642,30 +642,30 @@ bool RtspPlayer::handleOneRtp(int iTrackidx, unsigned char *pucData, unsigned in
memcpy(rtppt.payload + 4, pucData, uiLen);
/////////////////////////////////RTP排序逻辑///////////////////////////////////
if(rtppt.sequence != (uint16_t)(m_aui16LastSeq[iTrackidx] + 1) && m_aui16LastSeq[iTrackidx] != 0){
if(rtppt.sequence != (uint16_t)(_aui16LastSeq[iTrackidx] + 1) && _aui16LastSeq[iTrackidx] != 0){
//包乱序或丢包
m_aui64SeqOkCnt[iTrackidx] = 0;
m_abSortStarted[iTrackidx] = true;
//WarnL << "包乱序或丢包:" << trackidx <<" " << rtppt.sequence << " " << m_aui16LastSeq[trackidx];
_aui64SeqOkCnt[iTrackidx] = 0;
_abSortStarted[iTrackidx] = true;
//WarnL << "包乱序或丢包:" << trackidx <<" " << rtppt.sequence << " " << _aui16LastSeq[trackidx];
}else{
//正确序列的包
m_aui64SeqOkCnt[iTrackidx]++;
_aui64SeqOkCnt[iTrackidx]++;
}
m_aui16LastSeq[iTrackidx] = rtppt.sequence;
_aui16LastSeq[iTrackidx] = rtppt.sequence;
//开始排序缓存
if (m_abSortStarted[iTrackidx]) {
m_amapRtpSort[iTrackidx].emplace(rtppt.sequence, pt_ptr);
if (_abSortStarted[iTrackidx]) {
_amapRtpSort[iTrackidx].emplace(rtppt.sequence, pt_ptr);
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) {
if (_aui64SeqOkCnt[iTrackidx] >= clearCount) {
//网络环境改善,需要清空排序缓存
m_aui64SeqOkCnt[iTrackidx] = 0;
m_abSortStarted[iTrackidx] = false;
while (m_amapRtpSort[iTrackidx].size()) {
_aui64SeqOkCnt[iTrackidx] = 0;
_abSortStarted[iTrackidx] = false;
while (_amapRtpSort[iTrackidx].size()) {
POP_HEAD(iTrackidx)
}
} else if (m_amapRtpSort[iTrackidx].size() >= maxRtpCount) {
} else if (_amapRtpSort[iTrackidx].size() >= maxRtpCount) {
//排序缓存溢出
POP_HEAD(iTrackidx)
}
@ -678,27 +678,27 @@ bool RtspPlayer::handleOneRtp(int iTrackidx, unsigned char *pucData, unsigned in
}
void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &rtppt, int trackidx){
//统计丢包率
if (m_aui16FirstSeq[trackidx] == 0 || rtppt->sequence < m_aui16FirstSeq[trackidx]) {
m_aui16FirstSeq[trackidx] = rtppt->sequence;
m_aui64RtpRecv[trackidx] = 0;
if (_aui16FirstSeq[trackidx] == 0 || rtppt->sequence < _aui16FirstSeq[trackidx]) {
_aui16FirstSeq[trackidx] = rtppt->sequence;
_aui64RtpRecv[trackidx] = 0;
}
m_aui64RtpRecv[trackidx] ++;
m_aui16NowSeq[trackidx] = rtppt->sequence;
_aui64RtpRecv[trackidx] ++;
_aui16NowSeq[trackidx] = rtppt->sequence;
if (m_aNowStampTicker[trackidx].elapsedTime() > 500) {
m_adNowStamp[trackidx] = rtppt->timeStamp;
if (_aNowStampTicker[trackidx].elapsedTime() > 500) {
_adNowStamp[trackidx] = rtppt->timeStamp;
}
onRecvRTP_l(rtppt,m_aTrackInfo[trackidx]);
onRecvRTP_l(rtppt,_aTrackInfo[trackidx]);
}
float RtspPlayer::getRtpLossRate(int iTrackType) const{
int iTrackIdx = getTrackIndexByTrackType((TrackType)iTrackType);
if(iTrackIdx == -1){
uint64_t totalRecv = 0;
uint64_t totalSend = 0;
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
totalRecv += m_aui64RtpRecv[i];
totalSend += (m_aui16NowSeq[i] - m_aui16FirstSeq[i] + 1);
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
totalRecv += _aui64RtpRecv[i];
totalSend += (_aui16NowSeq[i] - _aui16FirstSeq[i] + 1);
}
if(totalSend == 0){
return 0;
@ -707,25 +707,25 @@ float RtspPlayer::getRtpLossRate(int iTrackType) const{
}
if(m_aui16NowSeq[iTrackIdx] - m_aui16FirstSeq[iTrackIdx] + 1 == 0){
if(_aui16NowSeq[iTrackIdx] - _aui16FirstSeq[iTrackIdx] + 1 == 0){
return 0;
}
return 1.0 - (double)m_aui64RtpRecv[iTrackIdx] / (m_aui16NowSeq[iTrackIdx] - m_aui16FirstSeq[iTrackIdx] + 1);
return 1.0 - (double)_aui64RtpRecv[iTrackIdx] / (_aui16NowSeq[iTrackIdx] - _aui16FirstSeq[iTrackIdx] + 1);
}
float RtspPlayer::getProgressTime() const{
double iTime[2] = {0,0};
for(unsigned int i = 0 ;i < m_uiTrackCnt ;i++){
if (m_aTrackInfo[i].type == TrackVideo) {
iTime[i] = (m_adNowStamp[i] - m_adFistStamp[i]) / 90000.0;
}else if (m_aTrackInfo[i].type == TrackAudio){
for(unsigned int i = 0 ;i < _uiTrackCnt ;i++){
if (_aTrackInfo[i].type == TrackVideo) {
iTime[i] = (_adNowStamp[i] - _adFistStamp[i]) / 90000.0;
}else if (_aTrackInfo[i].type == TrackAudio){
//todo(xzl) 修复此处
#if 0
iTime[i] = (m_adNowStamp[i] - m_adFistStamp[i]) / getAudioSampleRate();
iTime[i] = (_adNowStamp[i] - _adFistStamp[i]) / getAudioSampleRate();
#endif
}
}
return m_fSeekTo + MAX(iTime[0],iTime[1]);
return _fSeekTo + MAX(iTime[0],iTime[1]);
}
void RtspPlayer::seekToTime(float fTime) {
sendPause(false,fTime);
@ -733,9 +733,9 @@ void RtspPlayer::seekToTime(float fTime) {
bool RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrCaseMap &header_const) {
auto header = header_const;
header.emplace("CSeq",StrPrinter << m_uiCseq++);
if(!m_strSession.empty()){
header.emplace("Session",m_strSession);
header.emplace("CSeq",StrPrinter << _uiCseq++);
if(!_strSession.empty()){
header.emplace("Session",_strSession);
}
if(!(*this)[kRtspRealm].empty() && !(*this)[PlayerBase::kRtspUser].empty()){
@ -782,28 +782,28 @@ bool RtspPlayer::sendRtspRequest(const string &cmd, const string &url,const StrC
void RtspPlayer::onShutdown_l(const SockException &ex) {
WarnL << ex.getErrCode() << " " << ex.what();
m_pPlayTimer.reset();
m_pRtpTimer.reset();
m_pBeatTimer.reset();
_pPlayTimer.reset();
_pRtpTimer.reset();
_pBeatTimer.reset();
onShutdown(ex);
}
void RtspPlayer::onRecvRTP_l(const RtpPacket::Ptr &pRtppt, const RtspTrack &track) {
m_rtpTicker.resetTime();
_rtpTicker.resetTime();
onRecvRTP(pRtppt,track);
}
void RtspPlayer::onPlayResult_l(const SockException &ex) {
WarnL << ex.getErrCode() << " " << ex.what();
m_pPlayTimer.reset();
m_pRtpTimer.reset();
_pPlayTimer.reset();
_pRtpTimer.reset();
if (!ex) {
m_rtpTicker.resetTime();
_rtpTicker.resetTime();
weak_ptr<RtspPlayer> weakSelf = dynamic_pointer_cast<RtspPlayer>(shared_from_this());
m_pRtpTimer.reset( new Timer(5, [weakSelf]() {
_pRtpTimer.reset( new Timer(5, [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return false;
}
if(strongSelf->m_rtpTicker.elapsedTime()>10000) {
if(strongSelf->_rtpTicker.elapsedTime()>10000) {
//recv rtp timeout!
strongSelf->onShutdown_l(SockException(Err_timeout,"recv rtp timeout"));
strongSelf->teardown();
@ -816,16 +816,16 @@ void RtspPlayer::onPlayResult_l(const SockException &ex) {
}
int RtspPlayer::getTrackIndexByControlSuffix(const string &controlSuffix) const{
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
if (m_aTrackInfo[i].controlSuffix == controlSuffix) {
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
if (_aTrackInfo[i].controlSuffix == controlSuffix) {
return i;
}
}
return -1;
}
int RtspPlayer::getTrackIndexByInterleaved(int interleaved) const{
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
if (m_aTrackInfo[i].interleaved == interleaved) {
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
if (_aTrackInfo[i].interleaved == interleaved) {
return i;
}
}
@ -833,8 +833,8 @@ int RtspPlayer::getTrackIndexByInterleaved(int interleaved) const{
}
int RtspPlayer::getTrackIndexByTrackType(TrackType trackType) const {
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
if (m_aTrackInfo[i].type == trackType) {
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
if (_aTrackInfo[i].type == trackType) {
return i;
}
}

View File

@ -101,45 +101,45 @@ private:
bool sendDescribe();
bool sendRtspRequest(const string &cmd, const string &url ,const StrCaseMap &header = StrCaseMap());
private:
string m_strUrl;
unsigned int m_uiTrackCnt = 0;
RtspTrack m_aTrackInfo[2];
string _strUrl;
unsigned int _uiTrackCnt = 0;
RtspTrack _aTrackInfo[2];
function<void(const Parser&)> m_onHandshake;
RtspMediaSource::PoolType m_pktPool;
function<void(const Parser&)> _onHandshake;
RtspMediaSource::PoolType _pktPool;
uint8_t *m_pucRtpBuf = nullptr;
unsigned int m_uiRtpBufLen = 0;
Socket::Ptr m_apUdpSock[2];
uint8_t *_pucRtpBuf = nullptr;
unsigned int _uiRtpBufLen = 0;
Socket::Ptr _apUdpSock[2];
//rtsp info
string m_strSession;
unsigned int m_uiCseq = 1;
uint32_t m_aui32SsrcErrorCnt[2] = { 0, 0 };
string m_strContentBase;
eRtpType m_eType = RTP_TCP;
string _strSession;
unsigned int _uiCseq = 1;
uint32_t _aui32SsrcErrorCnt[2] = { 0, 0 };
string _strContentBase;
eRtpType _eType = RTP_TCP;
/* RTP包排序所用参数 */
uint16_t m_aui16LastSeq[2] = { 0 , 0 };
uint64_t m_aui64SeqOkCnt[2] = { 0 , 0};
bool m_abSortStarted[2] = { 0 , 0};
map<uint32_t , RtpPacket::Ptr> m_amapRtpSort[2];
uint16_t _aui16LastSeq[2] = { 0 , 0 };
uint64_t _aui64SeqOkCnt[2] = { 0 , 0};
bool _abSortStarted[2] = { 0 , 0};
map<uint32_t , RtpPacket::Ptr> _amapRtpSort[2];
/* 丢包率统计需要用到的参数 */
uint16_t m_aui16FirstSeq[2] = { 0 , 0};
uint16_t m_aui16NowSeq[2] = { 0 , 0 };
uint64_t m_aui64RtpRecv[2] = { 0 , 0};
uint16_t _aui16FirstSeq[2] = { 0 , 0};
uint16_t _aui16NowSeq[2] = { 0 , 0 };
uint64_t _aui64RtpRecv[2] = { 0 , 0};
//超时功能实现
Ticker m_rtpTicker;
std::shared_ptr<Timer> m_pPlayTimer;
std::shared_ptr<Timer> m_pRtpTimer;
Ticker _rtpTicker;
std::shared_ptr<Timer> _pPlayTimer;
std::shared_ptr<Timer> _pRtpTimer;
//心跳定时器
std::shared_ptr<Timer> m_pBeatTimer;
std::shared_ptr<Timer> _pBeatTimer;
//播放进度控制
float m_fSeekTo = 0;
double m_adFistStamp[2] = {0,0};
double m_adNowStamp[2] = {0,0};
Ticker m_aNowStampTicker[2];
float _fSeekTo = 0;
double _adFistStamp[2] = {0,0};
double _adNowStamp[2] = {0,0};
Ticker _aNowStampTicker[2];
};
} /* namespace Rtsp */

View File

@ -65,33 +65,33 @@ public:
private:
//派生类回调函数
bool onCheckSDP(const string &sdp, const RtspTrack *track, int trackCnt) override {
m_pRtspMediaSrc = dynamic_pointer_cast<RtspMediaSource>(m_pMediaSrc);
if(m_pRtspMediaSrc){
m_pRtspMediaSrc->onGetSDP(sdp);
_pRtspMediaSrc = dynamic_pointer_cast<RtspMediaSource>(_pMediaSrc);
if(_pRtspMediaSrc){
_pRtspMediaSrc->onGetSDP(sdp);
}
try {
m_parser.reset(new RtpParser(sdp));
_parser.reset(new RtpParser(sdp));
//todo(xzl) 修复此处
// m_parser->setOnVideoCB(m_onGetVideoCB);
// m_parser->setOnAudioCB(m_onGetAudioCB);
// _parser->setOnVideoCB(_onGetVideoCB);
// _parser->setOnAudioCB(_onGetAudioCB);
return true;
} catch (std::exception &ex) {
WarnL << ex.what();
return m_pRtspMediaSrc ? true : false;
return _pRtspMediaSrc ? true : false;
}
}
void onRecvRTP(const RtpPacket::Ptr &rtppt, const RtspTrack &track) override {
if(m_parser){
m_parser->inputRtp(rtppt);
if(_parser){
_parser->inputRtp(rtppt);
}
if(m_pRtspMediaSrc){
m_pRtspMediaSrc->onGetRTP(rtppt,true);
if(_pRtspMediaSrc){
_pRtspMediaSrc->onGetRTP(rtppt,true);
}
}
private:
RtspMediaSource::Ptr m_pRtspMediaSrc;
RtspMediaSource::Ptr _pRtspMediaSrc;
};

View File

@ -57,7 +57,7 @@ unordered_map<void *, std::shared_ptr<RtspSession> > RtspSession::g_mapPostter;
recursive_mutex RtspSession::g_mtxGetter; //对quicktime上锁保护
recursive_mutex RtspSession::g_mtxPostter; //对quicktime上锁保护
RtspSession::RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::Ptr &pSock) :
TcpSession(pTh, pSock), m_pSender(pSock) {
TcpSession(pTh, pSock), _pSender(pSock) {
//设置10秒发送缓存
pSock->setSendBufSecond(10);
//设置15秒发送超时时间
@ -67,8 +67,8 @@ RtspSession::RtspSession(const std::shared_ptr<ThreadPool> &pTh, const Socket::P
}
RtspSession::~RtspSession() {
if (m_onDestory) {
m_onDestory();
if (_onDestory) {
_onDestory();
}
DebugL << get_peer_ip();
}
@ -80,34 +80,34 @@ void RtspSession::shutdown_l(bool close){
if (_sock) {
_sock->emitErr(SockException(Err_other, "self shutdown"),close);
}
if (m_bBase64need && !_sock) {
if (_bBase64need && !_sock) {
//quickTime http postter,and self is detached from tcpServer
lock_guard<recursive_mutex> lock(g_mtxPostter);
g_mapPostter.erase(this);
}
if (m_pBrdcaster) {
m_pBrdcaster->setDetachCB(this, nullptr);
m_pBrdcaster.reset();
if (_pBrdcaster) {
_pBrdcaster->setDetachCB(this, nullptr);
_pBrdcaster.reset();
}
if (m_pRtpReader) {
m_pRtpReader.reset();
if (_pRtpReader) {
_pRtpReader.reset();
}
}
void RtspSession::onError(const SockException& err) {
TraceL << err.getErrCode() << " " << err.what();
if (m_bListenPeerUdpData) {
if (_bListenPeerUdpData) {
//取消UDP端口监听
UDPServer::Instance().stopListenPeer(get_peer_ip().data(), this);
m_bListenPeerUdpData = false;
_bListenPeerUdpData = false;
}
if (!m_bBase64need && m_strSessionCookie.size() != 0) {
if (!_bBase64need && _strSessionCookie.size() != 0) {
//quickTime http getter
lock_guard<recursive_mutex> lock(g_mtxGetter);
g_mapGetter.erase(m_strSessionCookie);
g_mapGetter.erase(_strSessionCookie);
}
if (m_bBase64need && err.getErrCode() == Err_eof) {
if (_bBase64need && err.getErrCode() == Err_eof) {
//quickTime http postter,正在发送rtp; QuickTime只是断开了请求连接,请继续发送rtp
_sock = nullptr;
lock_guard<recursive_mutex> lock(g_mtxPostter);
@ -121,24 +121,24 @@ void RtspSession::onError(const SockException& err) {
//流量统计事件广播
GET_CONFIG_AND_REGISTER(uint32_t,iFlowThreshold,Broadcast::kFlowThreshold);
if(m_ui64TotalBytes > iFlowThreshold * 1024){
if(_ui64TotalBytes > iFlowThreshold * 1024){
NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastFlowReport,
m_mediaInfo,
m_ui64TotalBytes,
m_ticker.createdTime()/1000,
_mediaInfo,
_ui64TotalBytes,
_ticker.createdTime()/1000,
*this);
}
}
void RtspSession::onManager() {
if (m_ticker.createdTime() > 15 * 1000) {
if (m_strSession.size() == 0) {
if (_ticker.createdTime() > 15 * 1000) {
if (_strSession.size() == 0) {
WarnL << "非法链接:" << get_peer_ip();
shutdown();
return;
}
}
if (m_rtpType != PlayerBase::RTP_TCP && m_ticker.elapsedTime() > 15 * 1000) {
if (_rtpType != PlayerBase::RTP_TCP && _ticker.elapsedTime() > 15 * 1000) {
WarnL << "RTSP会话超时:" << get_peer_ip();
shutdown();
return;
@ -148,11 +148,11 @@ void RtspSession::onManager() {
int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) {
char tmp[2 * 1024];
m_pcBuf = tmp;
_pcBuf = tmp;
m_parser.Parse(header); //rtsp请求解析
string strCmd = m_parser.Method(); //提取出请求命令字
m_iCseq = atoi(m_parser["CSeq"].data());
_parser.Parse(header); //rtsp请求解析
string strCmd = _parser.Method(); //提取出请求命令字
_iCseq = atoi(_parser["CSeq"].data());
typedef bool (RtspSession::*rtspCMDHandle)();
static unordered_map<string, rtspCMDHandle> g_mapCmd;
@ -180,15 +180,15 @@ int64_t RtspSession::onRecvHeader(const char *header,uint64_t len) {
WarnL << "cmd=" << strCmd;
}
m_parser.Clear();
_parser.Clear();
return 0;
}
void RtspSession::onRecv(const Buffer::Ptr &pBuf) {
m_ticker.resetTime();
m_ui64TotalBytes += pBuf->size();
if (m_bBase64need) {
_ticker.resetTime();
_ui64TotalBytes += pBuf->size();
if (_bBase64need) {
//quicktime 加密后的rtsp请求需要解密
auto str = decodeBase64(string(pBuf->data(),pBuf->size()));
inputRtspOrRtcp(str.data(),str.size());
@ -198,7 +198,7 @@ void RtspSession::onRecv(const Buffer::Ptr &pBuf) {
}
void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) {
if(data[0] == '$' && m_rtpType == PlayerBase::RTP_TCP){
if(data[0] == '$' && _rtpType == PlayerBase::RTP_TCP){
//这是rtcp
return;
}
@ -207,24 +207,24 @@ void RtspSession::inputRtspOrRtcp(const char *data,uint64_t len) {
bool RtspSession::handleReq_Options() {
//支持这些命令
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY,"
" PAUSE, SET_PARAMETER, GET_PARAMETER\r\n\r\n",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(m_pcBuf, n);
SocketHelper::send(_pcBuf, n);
return true;
}
bool RtspSession::handleReq_Describe() {
{
//解析url获取媒体名称
m_strUrl = m_parser.Url();
m_mediaInfo.parse(m_parser.FullUrl());
_strUrl = _parser.Url();
_mediaInfo.parse(_parser.FullUrl());
}
if (!findStream()) {
@ -235,7 +235,7 @@ bool RtspSession::handleReq_Describe() {
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
//该请求中的认证信息
auto authorization = m_parser["Authorization"];
auto authorization = _parser["Authorization"];
onGetRealm invoker = [weakSelf,authorization](const string &realm){
if(realm.empty()){
//无需认证,回复sdp
@ -248,7 +248,7 @@ bool RtspSession::handleReq_Describe() {
//广播是否需要认证事件
if(!NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastOnGetRtspRealm,
m_mediaInfo,
_mediaInfo,
invoker,
*this)){
//无人监听此事件,说明无需认证
@ -279,10 +279,10 @@ void RtspSession::onAuthSuccess(const weak_ptr<RtspSession> &weakSelf) {
"Content-Base: %s/\r\n"
"Content-Type: application/sdp\r\n"
"Content-Length: %d\r\n\r\n%s",
strongSelf->m_iCseq, SERVER_NAME,
strongSelf->_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), strongSelf->m_strUrl.data(),
(int) strongSelf->m_strSdp.length(), strongSelf->m_strSdp.data());
dateHeader().data(), strongSelf->_strUrl.data(),
(int) strongSelf->_strSdp.length(), strongSelf->_strSdp.data());
strongSelf->SocketHelper::send(response, n);
});
}
@ -304,16 +304,16 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin
GET_CONFIG_AND_REGISTER(bool,authBasic,Config::Rtsp::kAuthBasic);
if (!authBasic) {
//我们需要客户端优先以md5方式认证
strongSelf->m_strNonce = makeRandStr(32);
strongSelf->_strNonce = makeRandStr(32);
n = sprintf(response,
"RTSP/1.0 401 Unauthorized\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"WWW-Authenticate: Digest realm=\"%s\",nonce=\"%s\"\r\n\r\n",
strongSelf->m_iCseq, SERVER_NAME,
strongSelf->_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), realm.data(), strongSelf->m_strNonce.data());
dateHeader().data(), realm.data(), strongSelf->_strNonce.data());
}else {
//当然我们也支持base64认证,但是我们不建议这样做
n = sprintf(response,
@ -322,7 +322,7 @@ void RtspSession::onAuthFailed(const weak_ptr<RtspSession> &weakSelf,const strin
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"WWW-Authenticate: Basic realm=\"%s\"\r\n\r\n",
strongSelf->m_iCseq, SERVER_NAME,
strongSelf->_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), realm.data());
}
@ -359,7 +359,7 @@ void RtspSession::onAuthBasic(const weak_ptr<RtspSession> &weakSelf,const string
}
//此时必须提供明文密码
if(!NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastOnRtspAuth,strongSelf->m_mediaInfo,user, true,invoker,*strongSelf)){
if(!NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastOnRtspAuth,strongSelf->_mediaInfo,user, true,invoker,*strongSelf)){
//表明该流需要认证却没监听请求密码事件,这一般是大意的程序所为,警告之
WarnL << "请监听kBroadcastOnRtspAuth事件";
//但是我们还是忽略认证以便完成播放
@ -388,8 +388,8 @@ void RtspSession::onAuthDigest(const weak_ptr<RtspSession> &weakSelf,const strin
}
//check nonce
auto nonce = map["nonce"];
if(strongSelf->m_strNonce != nonce){
TraceL << "nonce not mached:" << nonce << "," << strongSelf->m_strNonce;
if(strongSelf->_strNonce != nonce){
TraceL << "nonce not mached:" << nonce << "," << strongSelf->_strNonce;
onAuthFailed(weakSelf,realm);
return ;
}
@ -440,7 +440,7 @@ void RtspSession::onAuthDigest(const weak_ptr<RtspSession> &weakSelf,const strin
};
//此时可以提供明文或md5加密的密码
if(!NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastOnRtspAuth,strongSelf->m_mediaInfo,username, false,invoker,*strongSelf)){
if(!NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastOnRtspAuth,strongSelf->_mediaInfo,username, false,invoker,*strongSelf)){
//表明该流需要认证却没监听请求密码事件,这一般是大意的程序所为,警告之
WarnL << "请监听kBroadcastOnRtspAuth事件";
//但是我们还是忽略认证以便完成播放
@ -469,80 +469,80 @@ void RtspSession::onAuthUser(const weak_ptr<RtspSession> &weakSelf,const string
}
}
inline void RtspSession::send_StreamNotFound() {
int n = sprintf(m_pcBuf, "RTSP/1.0 404 Stream Not Found\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 404 Stream Not Found\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(m_pcBuf, n);
SocketHelper::send(_pcBuf, n);
}
inline void RtspSession::send_UnsupportedTransport() {
int n = sprintf(m_pcBuf, "RTSP/1.0 461 Unsupported Transport\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 461 Unsupported Transport\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(m_pcBuf, n);
SocketHelper::send(_pcBuf, n);
}
inline void RtspSession::send_SessionNotFound() {
int n = sprintf(m_pcBuf, "RTSP/1.0 454 Session Not Found\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 454 Session Not Found\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(m_pcBuf, n);
SocketHelper::send(_pcBuf, n);
/*40 Method Not Allowed*/
}
bool RtspSession::handleReq_Setup() {
//处理setup命令该函数可能进入多次
auto controlSuffix = m_parser.FullUrl().substr(1 + m_parser.FullUrl().rfind('/'));
auto controlSuffix = _parser.FullUrl().substr(1 + _parser.FullUrl().rfind('/'));
int trackIdx = getTrackIndexByControlSuffix(controlSuffix);
if (trackIdx == -1) {
//未找到相应track
return false;
}
RtspTrack &trackRef = m_aTrackInfo[trackIdx];
RtspTrack &trackRef = _aTrackInfo[trackIdx];
if (trackRef.inited) {
//已经初始化过该Track
return false;
}
trackRef.inited = true; //现在初始化
auto strongRing = m_pWeakRing.lock();
auto strongRing = _pWeakRing.lock();
if (!strongRing) {
//the media source is released!
send_NotAcceptable();
return false;
}
if(!m_bSetUped){
m_bSetUped = true;
auto strTransport = m_parser["Transport"];
if(!_bSetUped){
_bSetUped = true;
auto strTransport = _parser["Transport"];
if(strTransport.find("TCP") != string::npos){
m_rtpType = PlayerBase::RTP_TCP;
_rtpType = PlayerBase::RTP_TCP;
}else if(strTransport.find("multicast") != string::npos){
m_rtpType = PlayerBase::RTP_MULTICAST;
_rtpType = PlayerBase::RTP_MULTICAST;
}else{
m_rtpType = PlayerBase::RTP_UDP;
_rtpType = PlayerBase::RTP_UDP;
}
}
if (!m_pRtpReader && m_rtpType != PlayerBase::RTP_MULTICAST) {
m_pRtpReader = strongRing->attach();
if (!_pRtpReader && _rtpType != PlayerBase::RTP_MULTICAST) {
_pRtpReader = strongRing->attach();
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
m_pRtpReader->setDetachCB([weakSelf]() {
_pRtpReader->setDetachCB([weakSelf]() {
auto strongSelf = weakSelf.lock();
if(!strongSelf) {
return;
@ -551,9 +551,9 @@ bool RtspSession::handleReq_Setup() {
});
}
switch (m_rtpType) {
switch (_rtpType) {
case PlayerBase::RTP_TCP: {
int iLen = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
int iLen = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
@ -562,13 +562,13 @@ bool RtspSession::handleReq_Setup() {
"Session: %s\r\n"
"x-Transport-Options: late-tolerance=1.400000\r\n"
"x-Dynamic-Rate: 1\r\n\r\n",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), trackRef.type * 2,
trackRef.type * 2 + 1,
printSSRC(trackRef.ssrc).data(),
m_strSession.data());
SocketHelper::send(m_pcBuf, iLen);
_strSession.data());
SocketHelper::send(_pcBuf, iLen);
}
break;
case PlayerBase::RTP_UDP: {
@ -587,44 +587,44 @@ bool RtspSession::handleReq_Setup() {
send_NotAcceptable();
return false;
}
m_apUdpSock[trackIdx] = pSockRtp;
_apUdpSock[trackIdx] = pSockRtp;
//设置客户端内网端口信息
string strClientPort = FindField(m_parser["Transport"].data(), "client_port=", NULL);
string strClientPort = FindField(_parser["Transport"].data(), "client_port=", NULL);
uint16_t ui16PeerPort = atoi( FindField(strClientPort.data(), NULL, "-").data());
struct sockaddr_in peerAddr;
peerAddr.sin_family = AF_INET;
peerAddr.sin_port = htons(ui16PeerPort);
peerAddr.sin_addr.s_addr = inet_addr(get_peer_ip().data());
bzero(&(peerAddr.sin_zero), sizeof peerAddr.sin_zero);
m_apPeerUdpAddr[trackIdx].reset((struct sockaddr *) (new struct sockaddr_in(peerAddr)));
_apPeerUdpAddr[trackIdx].reset((struct sockaddr *) (new struct sockaddr_in(peerAddr)));
//尝试获取客户端nat映射地址
startListenPeerUdpData();
//InfoL << "分配端口:" << srv_port;
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Transport: RTP/AVP/UDP;unicast;"
"client_port=%s;server_port=%d-%d;ssrc=%s;mode=play\r\n"
"Session: %s\r\n\r\n",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), strClientPort.data(),
pSockRtp->get_local_port(), pSockRtcp->get_local_port(),
printSSRC(trackRef.ssrc).data(),
m_strSession.data());
SocketHelper::send(m_pcBuf, n);
_strSession.data());
SocketHelper::send(_pcBuf, n);
}
break;
case PlayerBase::RTP_MULTICAST: {
if(!m_pBrdcaster){
m_pBrdcaster = RtpBroadCaster::get(get_local_ip(),m_mediaInfo.m_vhost, m_mediaInfo.m_app, m_mediaInfo.m_streamid);
if (!m_pBrdcaster) {
if(!_pBrdcaster){
_pBrdcaster = RtpBroadCaster::get(get_local_ip(),_mediaInfo._vhost, _mediaInfo._app, _mediaInfo._streamid);
if (!_pBrdcaster) {
send_NotAcceptable();
return false;
}
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
m_pBrdcaster->setDetachCB(this, [weakSelf]() {
_pBrdcaster->setDetachCB(this, [weakSelf]() {
auto strongSelf = weakSelf.lock();
if(!strongSelf) {
return;
@ -632,7 +632,7 @@ bool RtspSession::handleReq_Setup() {
strongSelf->safeShutdown();
});
}
int iSrvPort = m_pBrdcaster->getPort(trackRef.type);
int iSrvPort = _pBrdcaster->getPort(trackRef.type);
//我们用trackIdx区分rtp和rtcp包
auto pSockRtcp = UDPServer::Instance().getSock(get_local_ip().data(),2*trackIdx + 1,iSrvPort + 1);
if (!pSockRtcp) {
@ -643,20 +643,20 @@ bool RtspSession::handleReq_Setup() {
}
startListenPeerUdpData();
GET_CONFIG_AND_REGISTER(uint32_t,udpTTL,MultiCast::kUdpTTL);
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Transport: RTP/AVP;multicast;destination=%s;"
"source=%s;port=%d-%d;ttl=%d;ssrc=%s\r\n"
"Session: %s\r\n\r\n",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_pBrdcaster->getIP().data(),
dateHeader().data(), _pBrdcaster->getIP().data(),
get_local_ip().data(), iSrvPort, pSockRtcp->get_local_port(),
udpTTL,printSSRC(trackRef.ssrc).data(),
m_strSession.data());
SocketHelper::send(m_pcBuf, n);
_strSession.data());
SocketHelper::send(_pcBuf, n);
}
break;
default:
@ -666,39 +666,39 @@ bool RtspSession::handleReq_Setup() {
}
bool RtspSession::handleReq_Play() {
if (m_uiTrackCnt == 0) {
if (_uiTrackCnt == 0) {
//还没有Describe
return false;
}
if (m_parser["Session"] != m_strSession) {
if (_parser["Session"] != _strSession) {
send_SessionNotFound();
return false;
}
auto strRange = m_parser["Range"];
auto strRange = _parser["Range"];
auto onRes = [this,strRange](const string &err){
bool authSuccess = err.empty();
char response[2 * 1024];
m_pcBuf = response;
if(!authSuccess && m_bFirstPlay){
_pcBuf = response;
if(!authSuccess && _bFirstPlay){
//第一次play是播放否则是恢复播放。只对播放鉴权
int n = sprintf(m_pcBuf,
int n = sprintf(_pcBuf,
"RTSP/1.0 401 Unauthorized\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Content-Type: text/plain\r\n"
"Content-Length: %d\r\n\r\n%s",
m_iCseq, SERVER_NAME,
_iCseq, SERVER_NAME,
RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(),(int)err.size(),err.data());
SocketHelper::send(m_pcBuf,n);
SocketHelper::send(_pcBuf,n);
shutdown();
return;
}
if(m_pRtpReader){
if(_pRtpReader){
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
SockUtil::setNoDelay(m_pSender->rawFD(), false);
m_pRtpReader->setReadCB([weakSelf](const RtpPacket::Ptr &pack) {
SockUtil::setNoDelay(_pSender->rawFD(), false);
_pRtpReader->setReadCB([weakSelf](const RtpPacket::Ptr &pack) {
auto strongSelf = weakSelf.lock();
if(!strongSelf) {
return;
@ -714,10 +714,10 @@ bool RtspSession::handleReq_Play() {
});
}
auto pMediaSrc = m_pMediaSrc.lock();
auto pMediaSrc = _pMediaSrc.lock();
uint32_t iStamp = 0;
if(pMediaSrc){
if (strRange.size() && !m_bFirstPlay) {
if (strRange.size() && !_bFirstPlay) {
auto strStart = FindField(strRange.data(), "npt=", "-");
if (strStart == "now") {
strStart = "0";
@ -733,41 +733,41 @@ bool RtspSession::handleReq_Play() {
}else{
iStamp = pMediaSrc->getStamp();
}
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
auto &track = m_aTrackInfo[i];
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
auto &track = _aTrackInfo[i];
track.ssrc = pMediaSrc->getSsrc(track.type);
track.seq = pMediaSrc->getSeqence(track.type);
track.timeStamp = pMediaSrc->getTimestamp(track.type);
}
}
m_bFirstPlay = false;
int iLen = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
_bFirstPlay = false;
int iLen = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n"
"Range: npt=%.2f-\r\n"
"RTP-Info: ", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_strSession.data(),iStamp/1000.0);
"RTP-Info: ", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data(),iStamp/1000.0);
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
auto &track = m_aTrackInfo[i];
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
auto &track = _aTrackInfo[i];
if (track.inited == false) {
//还有track没有setup
shutdown();
return;
}
iLen += sprintf(m_pcBuf + iLen, "url=%s/%s;seq=%d;rtptime=%u,",
m_strUrl.data(), track.controlSuffix.data(), track.seq,track.timeStamp);
iLen += sprintf(_pcBuf + iLen, "url=%s/%s;seq=%d;rtptime=%u,",
_strUrl.data(), track.controlSuffix.data(), track.seq,track.timeStamp);
}
iLen -= 1;
(m_pcBuf)[iLen] = '\0';
iLen += sprintf(m_pcBuf + iLen, "\r\n\r\n");
SocketHelper::send(m_pcBuf, iLen);
(_pcBuf)[iLen] = '\0';
iLen += sprintf(_pcBuf + iLen, "\r\n\r\n");
SocketHelper::send(_pcBuf, iLen);
//提高发送性能
(*this) << SocketFlags(kSockFlags);
SockUtil::setNoDelay(m_pSender->rawFD(),false);
SockUtil::setNoDelay(_pSender->rawFD(),false);
};
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
@ -784,7 +784,7 @@ bool RtspSession::handleReq_Play() {
onRes(err);
});
};
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed,m_mediaInfo,invoker,*this);
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed,_mediaInfo,invoker,*this);
if(!flag){
//该事件无人监听,默认不鉴权
onRes("");
@ -793,40 +793,40 @@ bool RtspSession::handleReq_Play() {
}
bool RtspSession::handleReq_Pause() {
if (m_parser["Session"] != m_strSession) {
if (_parser["Session"] != _strSession) {
send_SessionNotFound();
return false;
}
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_strSession.data());
SocketHelper::send(m_pcBuf, n);
if(m_pRtpReader){
m_pRtpReader->setReadCB(nullptr);
"Session: %s\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data());
SocketHelper::send(_pcBuf, n);
if(_pRtpReader){
_pRtpReader->setReadCB(nullptr);
}
return true;
}
bool RtspSession::handleReq_Teardown() {
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_strSession.data());
"Session: %s\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data());
SocketHelper::send(m_pcBuf, n);
SocketHelper::send(_pcBuf, n);
TraceL << "播放器断开连接!";
return false;
}
bool RtspSession::handleReq_Get() {
m_strSessionCookie = m_parser["x-sessioncookie"];
int n = sprintf(m_pcBuf, "HTTP/1.0 200 OK\r\n"
_strSessionCookie = _parser["x-sessioncookie"];
int n = sprintf(_pcBuf, "HTTP/1.0 200 OK\r\n"
"%s"
"Connection: close\r\n"
"Cache-Control: no-store\r\n"
@ -835,23 +835,23 @@ bool RtspSession::handleReq_Get() {
dateHeader().data());
//注册GET
lock_guard<recursive_mutex> lock(g_mtxGetter);
g_mapGetter[m_strSessionCookie] = dynamic_pointer_cast<RtspSession>(shared_from_this());
//InfoL << m_strSessionCookie;
SocketHelper::send(m_pcBuf, n);
g_mapGetter[_strSessionCookie] = dynamic_pointer_cast<RtspSession>(shared_from_this());
//InfoL << _strSessionCookie;
SocketHelper::send(_pcBuf, n);
return true;
}
bool RtspSession::handleReq_Post() {
lock_guard<recursive_mutex> lock(g_mtxGetter);
string sessioncookie = m_parser["x-sessioncookie"];
string sessioncookie = _parser["x-sessioncookie"];
//Poster 找到 Getter
auto it = g_mapGetter.find(sessioncookie);
if (it == g_mapGetter.end()) {
//WarnL << sessioncookie;
return false;
}
m_bBase64need = true;
_bBase64need = true;
//Poster 找到Getter的SOCK
auto strongSession = it->second.lock();
g_mapGetter.erase(sessioncookie);
@ -866,46 +866,46 @@ bool RtspSession::handleReq_Post() {
bool RtspSession::handleReq_SET_PARAMETER() {
//TraceL<<endl;
int n = sprintf(m_pcBuf, "RTSP/1.0 200 OK\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 200 OK\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), m_strSession.data());
SocketHelper::send(m_pcBuf, n);
"Session: %s\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data(), _strSession.data());
SocketHelper::send(_pcBuf, n);
return true;
}
inline void RtspSession::send_NotAcceptable() {
int n = sprintf(m_pcBuf, "RTSP/1.0 406 Not Acceptable\r\n"
int n = sprintf(_pcBuf, "RTSP/1.0 406 Not Acceptable\r\n"
"CSeq: %d\r\n"
"Server: %s-%0.2f(build in %s)\r\n"
"%s"
"Connection: Close\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
"Connection: Close\r\n\r\n", _iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME,
dateHeader().data());
SocketHelper::send(m_pcBuf, n);
SocketHelper::send(_pcBuf, n);
}
inline bool RtspSession::findStream() {
RtspMediaSource::Ptr pMediaSrc =
dynamic_pointer_cast<RtspMediaSource>( MediaSource::find(RTSP_SCHEMA,m_mediaInfo.m_vhost, m_mediaInfo.m_app,m_mediaInfo.m_streamid) );
dynamic_pointer_cast<RtspMediaSource>( MediaSource::find(RTSP_SCHEMA,_mediaInfo._vhost, _mediaInfo._app,_mediaInfo._streamid) );
if (!pMediaSrc) {
WarnL << "No such stream:" << m_mediaInfo.m_vhost << " " << m_mediaInfo.m_app << " " << m_mediaInfo.m_streamid;
WarnL << "No such stream:" << _mediaInfo._vhost << " " << _mediaInfo._app << " " << _mediaInfo._streamid;
return false;
}
m_strSdp = pMediaSrc->getSdp();
m_pWeakRing = pMediaSrc->getRing();
_strSdp = pMediaSrc->getSdp();
_pWeakRing = pMediaSrc->getRing();
m_uiTrackCnt = parserSDP(m_strSdp, m_aTrackInfo);
if (m_uiTrackCnt == 0 || m_uiTrackCnt > 2) {
_uiTrackCnt = parserSDP(_strSdp, _aTrackInfo);
if (_uiTrackCnt == 0 || _uiTrackCnt > 2) {
return false;
}
m_strSession = makeRandStr(12);
m_pMediaSrc = pMediaSrc;
_strSession = makeRandStr(12);
_pMediaSrc = pMediaSrc;
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
auto &track = m_aTrackInfo[i];
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
auto &track = _aTrackInfo[i];
track.ssrc = pMediaSrc->getSsrc(track.type);
track.seq = pMediaSrc->getSeqence(track.type);
track.timeStamp = pMediaSrc->getTimestamp(track.type);
@ -917,19 +917,19 @@ inline bool RtspSession::findStream() {
inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
//InfoL<<(int)pkt.Interleaved;
switch (m_rtpType) {
switch (_rtpType) {
case PlayerBase::RTP_TCP: {
BufferRtp::Ptr buffer(new BufferRtp(pkt));
send(buffer);
#ifdef RTSP_SEND_RTCP
int iTrackIndex = getTrackIndexByTrackId(pkt.interleaved / 2);
RtcpCounter &counter = m_aRtcpCnt[iTrackIndex];
RtcpCounter &counter = _aRtcpCnt[iTrackIndex];
counter.pktCnt += 1;
counter.octCount += (pkt.length - 12);
auto &m_ticker = m_aRtcpTicker[iTrackIndex];
if (m_ticker.elapsedTime() > 5 * 1000) {
auto &_ticker = _aRtcpTicker[iTrackIndex];
if (_ticker.elapsedTime() > 5 * 1000) {
//send rtcp every 5 second
m_ticker.resetTime();
_ticker.resetTime();
counter.timeStamp = pkt.timeStamp;
sendRTCP();
}
@ -938,17 +938,17 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
break;
case PlayerBase::RTP_UDP: {
int iTrackIndex = getTrackIndexByTrackType(pkt->type);
auto pSock = m_apUdpSock[iTrackIndex].lock();
auto pSock = _apUdpSock[iTrackIndex].lock();
if (!pSock) {
shutdown();
return;
}
auto peerAddr = m_apPeerUdpAddr[iTrackIndex];
auto peerAddr = _apPeerUdpAddr[iTrackIndex];
if (!peerAddr) {
return;
}
BufferRtp::Ptr buffer(new BufferRtp(pkt,4));
m_ui64TotalBytes += buffer->size();
_ui64TotalBytes += buffer->size();
pSock->send(buffer,kSockFlags, peerAddr.get());
}
break;
@ -960,35 +960,35 @@ inline void RtspSession::sendRtpPacket(const RtpPacket::Ptr & pkt) {
inline void RtspSession::onRcvPeerUdpData(int iTrackIdx, const Buffer::Ptr &pBuf, const struct sockaddr& addr) {
if(iTrackIdx % 2 == 0){
//这是rtp探测包
if(!m_bGotAllPeerUdp){
if(!_bGotAllPeerUdp){
//还没有获取完整的rtp探测包
if(SockUtil::in_same_lan(get_local_ip().data(),get_peer_ip().data())){
//在内网中客户端上报的端口号是真实的所以我们忽略udp打洞包
m_bGotAllPeerUdp = true;
_bGotAllPeerUdp = true;
return;
}
//设置真实的客户端nat映射端口号
m_apPeerUdpAddr[iTrackIdx / 2].reset(new struct sockaddr(addr));
m_abGotPeerUdp[iTrackIdx / 2] = true;
m_bGotAllPeerUdp = true;//先假设获取到完整的rtp探测包
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
if (!m_abGotPeerUdp[i]) {
_apPeerUdpAddr[iTrackIdx / 2].reset(new struct sockaddr(addr));
_abGotPeerUdp[iTrackIdx / 2] = true;
_bGotAllPeerUdp = true;//先假设获取到完整的rtp探测包
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
if (!_abGotPeerUdp[i]) {
//还有track没获取到rtp探测包
m_bGotAllPeerUdp = false;
_bGotAllPeerUdp = false;
break;
}
}
}
}else{
//这是rtcp心跳包说明播放器还存活
m_ticker.resetTime();
_ticker.resetTime();
//TraceL << "rtcp:" << (iTrackIdx-1)/2 ;
}
}
inline void RtspSession::startListenPeerUdpData() {
m_bListenPeerUdpData = true;
_bListenPeerUdpData = true;
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
UDPServer::Instance().listenPeer(get_peer_ip().data(), this,
[weakSelf](int iTrackIdx,const Buffer::Ptr &pBuf,struct sockaddr *pPeerAddr)->bool {
@ -1009,15 +1009,15 @@ inline void RtspSession::startListenPeerUdpData() {
}
inline void RtspSession::initSender(const std::shared_ptr<RtspSession>& session) {
m_pSender = session->_sock;
_pSender = session->_sock;
weak_ptr<RtspSession> weakSelf = dynamic_pointer_cast<RtspSession>(shared_from_this());
session->m_onDestory = [weakSelf]() {
session->_onDestory = [weakSelf]() {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return;
}
//DebugL;
strongSelf->m_pSender->setOnErr([weakSelf](const SockException &err) {
strongSelf->_pSender->setOnErr([weakSelf](const SockException &err) {
auto strongSelf=weakSelf.lock();
if(!strongSelf) {
return;
@ -1033,9 +1033,9 @@ inline void RtspSession::sendRTCP() {
//DebugL;
uint8_t aui8Rtcp[60] = {0};
uint8_t *pui8Rtcp_SR = aui8Rtcp + 4, *pui8Rtcp_SDES = pui8Rtcp_SR + 28;
for (uint8_t i = 0; i < m_uiTrackCnt; i++) {
auto &track = m_aTrackInfo[i];
auto &counter = m_aRtcpCnt[i];
for (uint8_t i = 0; i < _uiTrackCnt; i++) {
auto &track = _aTrackInfo[i];
auto &counter = _aRtcpCnt[i];
aui8Rtcp[0] = '$';
aui8Rtcp[1] = track.trackId * 2 + 1;

View File

@ -90,8 +90,8 @@ protected:
private:
void inputRtspOrRtcp(const char *data,uint64_t len);
int send(const Buffer::Ptr &pkt) override{
m_ui64TotalBytes += pkt->size();
return m_pSender->send(pkt,_flags);
_ui64TotalBytes += pkt->size();
return _pSender->send(pkt,_flags);
}
void shutdown() override ;
void shutdown_l(bool close);
@ -123,16 +123,16 @@ private:
return tmp;
}
inline int getTrackIndexByTrackType(TrackType type) {
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
if (type == m_aTrackInfo[i].type) {
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
if (type == _aTrackInfo[i].type) {
return i;
}
}
return -1;
}
inline int getTrackIndexByControlSuffix(const string &controlSuffix) {
for (unsigned int i = 0; i < m_uiTrackCnt; i++) {
if (controlSuffix == m_aTrackInfo[i].controlSuffix) {
for (unsigned int i = 0; i < _uiTrackCnt; i++) {
if (controlSuffix == _aTrackInfo[i].controlSuffix) {
return i;
}
}
@ -150,53 +150,53 @@ private:
static void onAuthDigest(const weak_ptr<RtspSession> &weakSelf,const string &realm,const string &strMd5);
private:
char *m_pcBuf = nullptr;
Ticker m_ticker;
Parser m_parser; //rtsp解析类
string m_strUrl;
string m_strSdp;
string m_strSession;
bool m_bFirstPlay = true;
MediaInfo m_mediaInfo;
std::weak_ptr<RtspMediaSource> m_pMediaSrc;
char *_pcBuf = nullptr;
Ticker _ticker;
Parser _parser; //rtsp解析类
string _strUrl;
string _strSdp;
string _strSession;
bool _bFirstPlay = true;
MediaInfo _mediaInfo;
std::weak_ptr<RtspMediaSource> _pMediaSrc;
//RTP缓冲
weak_ptr<RingBuffer<RtpPacket::Ptr> > m_pWeakRing;
RingBuffer<RtpPacket::Ptr>::RingReader::Ptr m_pRtpReader;
weak_ptr<RingBuffer<RtpPacket::Ptr> > _pWeakRing;
RingBuffer<RtpPacket::Ptr>::RingReader::Ptr _pRtpReader;
PlayerBase::eRtpType m_rtpType = PlayerBase::RTP_UDP;
bool m_bSetUped = false;
int m_iCseq = 0;
unsigned int m_uiTrackCnt = 0; //媒体track个数
RtspTrack m_aTrackInfo[2]; //媒体track信息,trackid idx 为数组下标
bool m_bGotAllPeerUdp = false;
PlayerBase::eRtpType _rtpType = PlayerBase::RTP_UDP;
bool _bSetUped = false;
int _iCseq = 0;
unsigned int _uiTrackCnt = 0; //媒体track个数
RtspTrack _aTrackInfo[2]; //媒体track信息,trackid idx 为数组下标
bool _bGotAllPeerUdp = false;
#ifdef RTSP_SEND_RTCP
RtcpCounter m_aRtcpCnt[2]; //rtcp统计,trackid idx 为数组下标
Ticker m_aRtcpTicker[2]; //rtcp发送时间,trackid idx 为数组下标
RtcpCounter _aRtcpCnt[2]; //rtcp统计,trackid idx 为数组下标
Ticker _aRtcpTicker[2]; //rtcp发送时间,trackid idx 为数组下标
inline void sendRTCP();
#endif
//RTP over UDP
bool m_abGotPeerUdp[2] = { false, false }; //获取客户端udp端口计数
weak_ptr<Socket> m_apUdpSock[2]; //发送RTP的UDP端口,trackid idx 为数组下标
std::shared_ptr<struct sockaddr> m_apPeerUdpAddr[2]; //播放器接收RTP的地址,trackid idx 为数组下标
bool m_bListenPeerUdpData = false;
RtpBroadCaster::Ptr m_pBrdcaster;
bool _abGotPeerUdp[2] = { false, false }; //获取客户端udp端口计数
weak_ptr<Socket> _apUdpSock[2]; //发送RTP的UDP端口,trackid idx 为数组下标
std::shared_ptr<struct sockaddr> _apPeerUdpAddr[2]; //播放器接收RTP的地址,trackid idx 为数组下标
bool _bListenPeerUdpData = false;
RtpBroadCaster::Ptr _pBrdcaster;
//登录认证
string m_strNonce;
string _strNonce;
//RTSP over HTTP
function<void(void)> m_onDestory;
bool m_bBase64need = false; //是否需要base64解码
Socket::Ptr m_pSender; //回复rtsp时走的tcp通道供quicktime用
function<void(void)> _onDestory;
bool _bBase64need = false; //是否需要base64解码
Socket::Ptr _pSender; //回复rtsp时走的tcp通道供quicktime用
//quicktime 请求rtsp会产生两次tcp连接
//一次发送 get 一次发送post需要通过sessioncookie关联起来
string m_strSessionCookie;
string _strSessionCookie;
//消耗的总流量
uint64_t m_ui64TotalBytes = 0;
uint64_t _ui64TotalBytes = 0;
static recursive_mutex g_mtxGetter; //对quicktime上锁保护
static recursive_mutex g_mtxPostter; //对quicktime上锁保护

View File

@ -43,7 +43,7 @@ RtspToRtmpMediaSource::RtspToRtmpMediaSource(const string &vhost,
const string &id,
bool bEnableHls,
bool bEnableMp4) :
RtspMediaSource(vhost,app,id),m_bEnableHls(bEnableHls),m_bEnableMp4(bEnableMp4) {
RtspMediaSource(vhost,app,id),_bEnableHls(bEnableHls),_bEnableMp4(bEnableMp4) {
}
RtspToRtmpMediaSource::~RtspToRtmpMediaSource() {
@ -65,36 +65,36 @@ void RtspToRtmpMediaSource::makeVideoConfigPkt() {
rtmpPkt->strBuf.push_back(1); // version
//todo(xzl) 修复此处
string m_sps ;//= m_pParser->getSps().substr(4);
string m_pps ;//= m_pParser->getPps().substr(4);
//DebugL<<hexdump(m_sps.data(), m_sps.size());
rtmpPkt->strBuf.push_back(m_sps[1]); // profile
rtmpPkt->strBuf.push_back(m_sps[2]); // compat
rtmpPkt->strBuf.push_back(m_sps[3]); // level
string _sps ;//= _pParser->getSps().substr(4);
string _pps ;//= _pParser->getPps().substr(4);
//DebugL<<hexdump(_sps.data(), _sps.size());
rtmpPkt->strBuf.push_back(_sps[1]); // profile
rtmpPkt->strBuf.push_back(_sps[2]); // compat
rtmpPkt->strBuf.push_back(_sps[3]); // level
rtmpPkt->strBuf.push_back(0xff); // 6 bits reserved + 2 bits nal size length - 1 (11)
rtmpPkt->strBuf.push_back(0xe1); // 3 bits reserved + 5 bits number of sps (00001)
uint16_t size = m_sps.size();
uint16_t size = _sps.size();
size = htons(size);
rtmpPkt->strBuf.append((char *) &size, 2);
rtmpPkt->strBuf.append(m_sps);
rtmpPkt->strBuf.append(_sps);
/////////////pps
rtmpPkt->strBuf.push_back(1); // version
size = m_pps.size();
size = _pps.size();
size = htons(size);
rtmpPkt->strBuf.append((char *) &size, 2);
rtmpPkt->strBuf.append(m_pps);
rtmpPkt->strBuf.append(_pps);
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_VIDEO;
rtmpPkt->streamId = STREAM_MEDIA;
rtmpPkt->timeStamp = 0;
rtmpPkt->typeId = MSG_VIDEO;
m_pRtmpSrc->onGetMedia(rtmpPkt);
_pRtmpSrc->onGetMedia(rtmpPkt);
}
void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) {
if(m_pRecorder){
m_pRecorder->inputH264((char *) frame.data(), frame.size(), frame.timeStamp, frame.type);
if(_pRecorder){
_pRecorder->inputH264((char *) frame.data(), frame.size(), frame.timeStamp, frame.type);
}
uint8_t nal_type = frame.data()[4] & 0x1F;
int8_t flags = 7; //h.264
@ -124,17 +124,17 @@ void RtspToRtmpMediaSource::onGetH264(const H264Frame& frame) {
rtmpPkt->streamId = STREAM_MEDIA;
rtmpPkt->timeStamp = frame.timeStamp;
rtmpPkt->typeId = MSG_VIDEO;
m_pRtmpSrc->onGetMedia(rtmpPkt);
_pRtmpSrc->onGetMedia(rtmpPkt);
}
void RtspToRtmpMediaSource::onGetAAC(const AACFrame& frame) {
if(m_pRecorder){
m_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp);
if(_pRecorder){
_pRecorder->inputAAC((char *) frame.buffer, frame.aac_frame_length, frame.timeStamp);
}
RtmpPacket::Ptr rtmpPkt(new RtmpPacket);
//////////header
uint8_t is_config = false;
rtmpPkt->strBuf.push_back(m_ui8AudioFlags);
rtmpPkt->strBuf.push_back(_ui8AudioFlags);
rtmpPkt->strBuf.push_back(!is_config);
rtmpPkt->strBuf.append((char *) frame.buffer + 7, frame.aac_frame_length - 7);
@ -143,15 +143,15 @@ void RtspToRtmpMediaSource::onGetAAC(const AACFrame& frame) {
rtmpPkt->streamId = STREAM_MEDIA;
rtmpPkt->timeStamp = frame.timeStamp;
rtmpPkt->typeId = MSG_AUDIO;
m_pRtmpSrc->onGetMedia(rtmpPkt);
_pRtmpSrc->onGetMedia(rtmpPkt);
}
void RtspToRtmpMediaSource::makeAudioConfigPkt() {
//todo(xzl) 修复此处
#if 0
uint8_t flvStereoOrMono = (m_pParser->getAudioChannel() > 1);
uint8_t flvStereoOrMono = (_pParser->getAudioChannel() > 1);
uint8_t flvSampleRate;
switch (m_pParser->getAudioSampleRate()) {
switch (_pParser->getAudioSampleRate()) {
case 48000:
case 44100:
flvSampleRate = 3;
@ -168,57 +168,57 @@ void RtspToRtmpMediaSource::makeAudioConfigPkt() {
flvSampleRate = 0;
break;
}
uint8_t flvSampleBit = m_pParser->getAudioSampleBit() == 16;
uint8_t flvSampleBit = _pParser->getAudioSampleBit() == 16;
uint8_t flvAudioType = 10; //aac
m_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
_ui8AudioFlags = (flvAudioType << 4) | (flvSampleRate << 2) | (flvSampleBit << 1) | flvStereoOrMono;
RtmpPacket::Ptr rtmpPkt(new RtmpPacket);
//////////header
uint8_t is_config = true;
rtmpPkt->strBuf.push_back(m_ui8AudioFlags);
rtmpPkt->strBuf.push_back(_ui8AudioFlags);
rtmpPkt->strBuf.push_back(!is_config);
rtmpPkt->strBuf.append(m_pParser->getAudioCfg());
rtmpPkt->strBuf.append(_pParser->getAudioCfg());
rtmpPkt->bodySize = rtmpPkt->strBuf.size();
rtmpPkt->chunkId = CHUNK_AUDIO;
rtmpPkt->streamId = STREAM_MEDIA;
rtmpPkt->timeStamp = 0;
rtmpPkt->typeId = MSG_AUDIO;
m_pRtmpSrc->onGetMedia(rtmpPkt);
_pRtmpSrc->onGetMedia(rtmpPkt);
#endif
}
void RtspToRtmpMediaSource::makeMetaData() {
m_pRtmpSrc.reset(new RtmpMediaSource(getVhost(),getApp(),getId()));
m_pRtmpSrc->setListener(m_listener);
_pRtmpSrc.reset(new RtmpMediaSource(getVhost(),getApp(),getId()));
_pRtmpSrc->setListener(_listener);
AMFValue metaData(AMF_OBJECT);
metaData.set("duration", m_pParser->getDuration());
metaData.set("duration", _pParser->getDuration());
metaData.set("fileSize", 0);
//todo(xzl) 修复此处
#if 0
if (m_pParser->containVideo()) {
metaData.set("width", m_pParser->getVideoWidth());
metaData.set("height", m_pParser->getVideoHeight());
if (_pParser->containVideo()) {
metaData.set("width", _pParser->getVideoWidth());
metaData.set("height", _pParser->getVideoHeight());
metaData.set("videocodecid", "avc1"); //h.264
metaData.set("videodatarate", 5000);
metaData.set("framerate", m_pParser->getVideoFps());
metaData.set("framerate", _pParser->getVideoFps());
makeVideoConfigPkt();
}
if (m_pParser->containAudio()) {
if (_pParser->containAudio()) {
metaData.set("audiocodecid", "mp4a"); //aac
metaData.set("audiodatarate", 160);
metaData.set("audiosamplerate", m_pParser->getAudioSampleRate());
metaData.set("audiosamplesize", m_pParser->getAudioSampleBit());
metaData.set("audiochannels", m_pParser->getAudioChannel());
metaData.set("stereo", m_pParser->getAudioChannel() > 1);
metaData.set("audiosamplerate", _pParser->getAudioSampleRate());
metaData.set("audiosamplesize", _pParser->getAudioSampleBit());
metaData.set("audiochannels", _pParser->getAudioChannel());
metaData.set("stereo", _pParser->getAudioChannel() > 1);
makeAudioConfigPkt();
}
#endif
m_pRtmpSrc->onGetMetaData(metaData);
_pRtmpSrc->onGetMetaData(metaData);
}
} /* namespace Rtsp */
} /* namespace ZL */

View File

@ -52,11 +52,11 @@ public:
virtual void onGetSDP(const string& strSdp) override{
try {
m_pParser.reset(new RtpParser(strSdp));
m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser,m_bEnableHls,m_bEnableMp4));
_pParser.reset(new RtpParser(strSdp));
_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),_pParser,_bEnableHls,_bEnableMp4));
//todo(xzl) 修复此处
// m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1));
// m_pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
// _pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAAC, this, placeholders::_1));
// _pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1));
makeMetaData();
} catch (exception &ex) {
WarnL << ex.what();
@ -64,22 +64,22 @@ public:
RtspMediaSource::onGetSDP(strSdp);
}
virtual void onGetRTP(const RtpPacket::Ptr &pRtppkt, bool bKeyPos) override{
if (m_pParser) {
bKeyPos = m_pParser->inputRtp(pRtppkt);
if (_pParser) {
bKeyPos = _pParser->inputRtp(pRtppkt);
}
RtspMediaSource::onGetRTP(pRtppkt, bKeyPos);
}
int readerCount(){
return getRing()->readerCount() + (m_pRtmpSrc ? m_pRtmpSrc->getRing()->readerCount() : 0);
return getRing()->readerCount() + (_pRtmpSrc ? _pRtmpSrc->getRing()->readerCount() : 0);
}
void updateTimeStamp(uint32_t uiStamp) {
for (auto &pr : m_mapTracks) {
for (auto &pr : _mapTracks) {
switch (pr.second.type) {
case TrackAudio: {
//todo(xzl) 修复此处
// pr.second.timeStamp = uiStamp * (m_pParser->getAudioSampleRate() / 1000.0);
// pr.second.timeStamp = uiStamp * (_pParser->getAudioSampleRate() / 1000.0);
}
break;
case TrackVideo: {
@ -100,12 +100,12 @@ private:
void makeAudioConfigPkt();
void makeMetaData();
private:
RtpParser::Ptr m_pParser;
RtmpMediaSource::Ptr m_pRtmpSrc;
uint8_t m_ui8AudioFlags = 0;
MediaRecorder::Ptr m_pRecorder;
bool m_bEnableHls;
bool m_bEnableMp4;
RtpParser::Ptr _pParser;
RtmpMediaSource::Ptr _pRtmpSrc;
uint8_t _ui8AudioFlags = 0;
MediaRecorder::Ptr _pRecorder;
bool _bEnableHls;
bool _bEnableMp4;
};

View File

@ -48,10 +48,10 @@ UDPServer::~UDPServer() {
}
Socket::Ptr UDPServer::getSock(const char* strLocalIp, int iTrackIndex,uint16_t iLocalPort) {
lock_guard<mutex> lck(m_mtxUpdSock);
lock_guard<mutex> lck(_mtxUpdSock);
string strKey = StrPrinter << strLocalIp << ":" << iTrackIndex << endl;
auto it = m_mapUpdSock.find(strKey);
if (it == m_mapUpdSock.end()) {
auto it = _mapUpdSock.find(strKey);
if (it == _mapUpdSock.end()) {
Socket::Ptr pSock(new Socket());
//InfoL<<localIp;
if (!pSock->bindUdpSock(iLocalPort, strLocalIp)) {
@ -61,7 +61,7 @@ Socket::Ptr UDPServer::getSock(const char* strLocalIp, int iTrackIndex,uint16_t
pSock->setOnRead(bind(&UDPServer::onRcvData, this, iTrackIndex, placeholders::_1,placeholders::_2));
pSock->setOnErr(bind(&UDPServer::onErr, this, strKey, placeholders::_1));
m_mapUpdSock[strKey] = pSock;
_mapUpdSock[strKey] = pSock;
DebugL << strLocalIp << " " << pSock->get_local_port() << " " << iTrackIndex;
return pSock;
}
@ -69,15 +69,15 @@ Socket::Ptr UDPServer::getSock(const char* strLocalIp, int iTrackIndex,uint16_t
}
void UDPServer::listenPeer(const char* strPeerIp, void* pSelf, const onRecvData& cb) {
lock_guard<mutex> lck(m_mtxDataHandler);
auto &mapRef = m_mapDataHandler[strPeerIp];
lock_guard<mutex> lck(_mtxDataHandler);
auto &mapRef = _mapDataHandler[strPeerIp];
mapRef.emplace(pSelf, cb);
}
void UDPServer::stopListenPeer(const char* strPeerIp, void* pSelf) {
lock_guard<mutex> lck(m_mtxDataHandler);
auto it0 = m_mapDataHandler.find(strPeerIp);
if (it0 == m_mapDataHandler.end()) {
lock_guard<mutex> lck(_mtxDataHandler);
auto it0 = _mapDataHandler.find(strPeerIp);
if (it0 == _mapDataHandler.end()) {
return;
}
auto &mapRef = it0->second;
@ -86,22 +86,22 @@ void UDPServer::stopListenPeer(const char* strPeerIp, void* pSelf) {
mapRef.erase(it1);
}
if (mapRef.size() == 0) {
m_mapDataHandler.erase(it0);
_mapDataHandler.erase(it0);
}
}
void UDPServer::onErr(const string& strKey, const SockException& err) {
WarnL << err.what();
lock_guard<mutex> lck(m_mtxUpdSock);
m_mapUpdSock.erase(strKey);
lock_guard<mutex> lck(_mtxUpdSock);
_mapUpdSock.erase(strKey);
}
void UDPServer::onRcvData(int iTrackIndex, const Buffer::Ptr &pBuf, struct sockaddr* pPeerAddr) {
//TraceL << trackIndex;
struct sockaddr_in *in = (struct sockaddr_in *) pPeerAddr;
string peerIp = inet_ntoa(in->sin_addr);
lock_guard<mutex> lck(m_mtxDataHandler);
auto it0 = m_mapDataHandler.find(peerIp);
if (it0 == m_mapDataHandler.end()) {
lock_guard<mutex> lck(_mtxDataHandler);
auto it0 = _mapDataHandler.find(peerIp);
if (it0 == _mapDataHandler.end()) {
return;
}
auto &mapRef = it0->second;
@ -112,7 +112,7 @@ void UDPServer::onRcvData(int iTrackIndex, const Buffer::Ptr &pBuf, struct socka
}
}
if (mapRef.size() == 0) {
m_mapDataHandler.erase(it0);
_mapDataHandler.erase(it0);
}
}

View File

@ -56,11 +56,11 @@ public:
private:
void onRcvData(int iTrackId, const Buffer::Ptr &pBuf,struct sockaddr *pPeerAddr);
void onErr(const string &strKey,const SockException &err);
unordered_map<string, Socket::Ptr> m_mapUpdSock;
mutex m_mtxUpdSock;
unordered_map<string, Socket::Ptr> _mapUpdSock;
mutex _mtxUpdSock;
unordered_map<string, unordered_map<void *, onRecvData> > m_mapDataHandler;
mutex m_mtxDataHandler;
unordered_map<string, unordered_map<void *, onRecvData> > _mapDataHandler;
mutex _mtxDataHandler;
};
} /* namespace Rtsp */

View File

@ -48,14 +48,14 @@ ShellSession::~ShellSession() {
void ShellSession::onRecv(const Buffer::Ptr&buf) {
//DebugL << hexdump(buf->data(), buf->size());
GET_CONFIG_AND_REGISTER(uint32_t,maxReqSize,Config::Shell::kMaxReqSize);
if (m_strRecvBuf.size() + buf->size() >= maxReqSize) {
if (_strRecvBuf.size() + buf->size() >= maxReqSize) {
WarnL << "接收缓冲区溢出!";
shutdown();
return;
}
m_beatTicker.resetTime();
m_strRecvBuf.append(buf->data(), buf->size());
if (m_strRecvBuf.find("\xff\xf4\xff\0xfd\x06") != std::string::npos) {
_beatTicker.resetTime();
_strRecvBuf.append(buf->data(), buf->size());
if (_strRecvBuf.find("\xff\xf4\xff\0xfd\x06") != std::string::npos) {
WarnL << "收到Ctrl+C.";
send("\033[0m\r\n Bye bye!\r\n");
shutdown();
@ -63,9 +63,9 @@ void ShellSession::onRecv(const Buffer::Ptr&buf) {
}
size_t index;
string line;
while ((index = m_strRecvBuf.find("\r\n")) != std::string::npos) {
line = m_strRecvBuf.substr(0, index);
m_strRecvBuf.erase(0, index + 2);
while ((index = _strRecvBuf.find("\r\n")) != std::string::npos) {
line = _strRecvBuf.substr(0, index);
_strRecvBuf.erase(0, index + 2);
if (!onCommandLine(line)) {
shutdown();
return;
@ -74,7 +74,7 @@ void ShellSession::onRecv(const Buffer::Ptr&buf) {
}
void ShellSession::onManager() {
if (m_beatTicker.elapsedTime() > 1000 * 60 * 5) {
if (_beatTicker.elapsedTime() > 1000 * 60 * 5) {
//5 miniutes for alive
shutdown();
return;
@ -82,7 +82,7 @@ void ShellSession::onManager() {
}
inline bool ShellSession::onCommandLine(const string& line) {
auto loginInterceptor = m_loginInterceptor;
auto loginInterceptor = _loginInterceptor;
if (loginInterceptor) {
bool ret = loginInterceptor(line);
return ret;
@ -104,15 +104,15 @@ inline bool ShellSession::onCommandLine(const string& line) {
inline void ShellSession::pleaseInputUser() {
send("\033[0m");
send(StrPrinter << SERVER_NAME << " login: " << endl);
m_loginInterceptor = [this](const string &user_name) {
m_strUserName=user_name;
_loginInterceptor = [this](const string &user_name) {
_strUserName=user_name;
pleaseInputPasswd();
return true;
};
}
inline void ShellSession::pleaseInputPasswd() {
send("Password: \033[8m");
m_loginInterceptor = [this](const string &passwd) {
_loginInterceptor = [this](const string &passwd) {
auto onAuth = [this](const string &errMessage){
if(!errMessage.empty()){
//鉴权失败
@ -120,7 +120,7 @@ inline void ShellSession::pleaseInputPasswd() {
<<"\033[0mAuth failed("
<< errMessage
<<"), please try again.\r\n"
<<m_strUserName<<"@"<<SERVER_NAME
<<_strUserName<<"@"<<SERVER_NAME
<<"'s password: \033[8m"
<<endl);
return;
@ -130,7 +130,7 @@ inline void ShellSession::pleaseInputPasswd() {
send(StrPrinter<<"欢迎来到"<<SERVER_NAME<<", 你可输入\"help\"查看帮助.\r\n"<<endl);
send("-----------------------------------------\r\n");
printShellPrefix();
m_loginInterceptor=nullptr;
_loginInterceptor=nullptr;
};
weak_ptr<ShellSession> weakSelf = dynamic_pointer_cast<ShellSession>(shared_from_this());
@ -148,7 +148,7 @@ inline void ShellSession::pleaseInputPasswd() {
});
};
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastShellLogin,m_strUserName,passwd,invoker,*this);
auto flag = NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastShellLogin,_strUserName,passwd,invoker,*this);
if(!flag){
//如果无人监听shell登录事件那么默认shell无法登录
onAuth("please listen kBroadcastShellLogin event");
@ -158,7 +158,7 @@ inline void ShellSession::pleaseInputPasswd() {
}
inline void ShellSession::printShellPrefix() {
send(StrPrinter << m_strUserName << "@" << SERVER_NAME << "# " << endl);
send(StrPrinter << _strUserName << "@" << SERVER_NAME << "# " << endl);
}
}/* namespace Shell */

View File

@ -54,10 +54,10 @@ private:
inline void pleaseInputPasswd();
inline void printShellPrefix();
function<bool(const string &)> m_loginInterceptor;
string m_strRecvBuf;
Ticker m_beatTicker;
string m_strUserName;
function<bool(const string &)> _loginInterceptor;
string _strRecvBuf;
Ticker _beatTicker;
string _strUserName;
};
} /* namespace Shell */