From bd72a69d335ab15a63eb7ba40c337d587fdcca7c Mon Sep 17 00:00:00 2001 From: xiongziliang <771730766@qq.com> Date: Fri, 2 Feb 2018 18:06:08 +0800 Subject: [PATCH] =?UTF-8?q?=E5=88=9D=E6=AD=A5=E6=8F=90=E4=BA=A42.0?= =?UTF-8?q?=E7=89=88=E6=9C=AC=EF=BC=8C=E6=94=AF=E6=8C=81=E8=99=9A=E6=8B=9F?= =?UTF-8?q?=E4=B8=BB=E6=9C=BA?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- c_wrapper/src/common.cpp | 37 ------------ c_wrapper/src/common.h | 33 ----------- c_wrapper/src/media.cpp | 2 +- c_wrapper/src/proxyplayer.cpp | 2 +- src/Common/MediaSender.h | 2 +- src/Common/config.cpp | 43 +++++--------- src/Common/config.h | 44 ++++++-------- src/Device/Device.cpp | 94 ++++++++++++++---------------- src/Device/Device.h | 21 +------ src/Device/PlayerProxy.cpp | 5 +- src/Device/PlayerProxy.h | 3 +- src/Http/HttpSession.cpp | 32 +++++----- src/Http/HttpSession.h | 2 +- src/MediaFile/HLSMaker.cpp | 4 -- src/MediaFile/MediaReader.cpp | 56 +++++------------- src/MediaFile/MediaReader.h | 12 ++-- src/MediaFile/MediaRecorder.cpp | 41 ++++++++----- src/MediaFile/MediaRecorder.h | 8 +-- src/MediaFile/Mp4Maker.cpp | 11 +++- src/MediaFile/Mp4Maker.h | 7 ++- src/Rtmp/RtmpMediaSource.cpp | 24 -------- src/Rtmp/RtmpMediaSource.h | 86 +++------------------------ src/Rtmp/RtmpPusher.cpp | 6 +- src/Rtmp/RtmpPusher.h | 2 +- src/Rtmp/RtmpSession.cpp | 65 +++++++++++++-------- src/Rtmp/RtmpSession.h | 6 +- src/Rtmp/RtmpToRtspMediaSource.cpp | 22 +++---- src/Rtmp/RtmpToRtspMediaSource.h | 33 ++++------- src/Rtsp/RtpBroadCaster.cpp | 21 +++---- src/Rtsp/RtpBroadCaster.h | 6 +- src/Rtsp/Rtsp.h | 26 ++------- src/Rtsp/RtspMediaSource.cpp | 25 -------- src/Rtsp/RtspMediaSource.h | 92 ++++------------------------- src/Rtsp/RtspPlayer.cpp | 32 +++------- src/Rtsp/RtspSession.cpp | 89 +++++++++++++--------------- src/Rtsp/RtspSession.h | 5 +- src/Rtsp/RtspToRtmpMediaSource.cpp | 19 +++--- src/Rtsp/RtspToRtmpMediaSource.h | 26 ++------- src/Shell/ShellCMD.cpp | 16 ++--- src/Shell/ShellSession.cpp | 13 ++--- src/Shell/ShellSession.h | 1 - tests/test_rtmpPusher.cpp | 6 +- tests/test_rtmpPusherMp4.cpp | 2 +- tests/test_server.cpp | 2 +- 44 files changed, 354 insertions(+), 730 deletions(-) diff --git a/c_wrapper/src/common.cpp b/c_wrapper/src/common.cpp index 78bd1783..fe841ad6 100755 --- a/c_wrapper/src/common.cpp +++ b/c_wrapper/src/common.cpp @@ -111,43 +111,6 @@ API_EXPORT int API_CALL initRtmpServer(unsigned short port) { } } -API_EXPORT void API_CALL listenEvent_onPlay(onEventPlay cb,void *userData){ - NoticeCenter::Instance().addListener((void *)(cb),Config::Broadcast::kBroadcastRtspSessionPlay, - [cb,userData](BroadcastRtspSessionPlayArgs){ - static unordered_map s_timerKeyMap; - static mutex s_mtx; - uint64_t tag; - { - lock_guard lck(s_mtx); - //每个stream随机分配一个内存地址并且不重复 - tag = (uint64_t)&s_timerKeyMap[stream]; - } - string appTmp(app); - string streamTmp(stream); - AsyncTaskThread::Instance().CancelTask(tag); - int i = 2; - AsyncTaskThread::Instance().DoTaskDelay(tag,50,[cb,userData,appTmp,streamTmp,i](){ - InfoL << "listenEvent_onPlay:" << appTmp << " " << streamTmp << " " << i; - cb(userData,appTmp.data(),streamTmp.data()); - return (--const_cast(i)) > 0; - }); - }); -} - -API_EXPORT void API_CALL listenEvent_onRegistRtsp(onEventRegistMediaSrc cb,void *userData){ - NoticeCenter::Instance().addListener((void *)(cb),Config::Broadcast::kBroadcastRtspSrcRegisted, - [cb,userData](BroadcastRtspSrcRegistedArgs){ - cb(userData,app,stream); - }); -} - -API_EXPORT void API_CALL listenEvent_onRegistRtmp(onEventRegistMediaSrc cb,void *userData){ - NoticeCenter::Instance().addListener((void *)(cb),Config::Broadcast::kBroadcastRtmpSrcRegisted, - [cb,userData](BroadcastRtmpSrcRegistedArgs){ - cb(userData,app,stream); - }); -} - API_EXPORT void API_CALL log_printf(LogType level,const char* file, const char* function, int line,const char *fmt,...){ LogInfoMaker info((LogLevel)level,file,function,line); diff --git a/c_wrapper/src/common.h b/c_wrapper/src/common.h index 004185e3..12cd777a 100755 --- a/c_wrapper/src/common.h +++ b/c_wrapper/src/common.h @@ -75,39 +75,6 @@ API_EXPORT int API_CALL initRtspServer(unsigned short port); */ API_EXPORT int API_CALL initRtmpServer(unsigned short port); -/* - * 描述:播放事件回调函数定义 - * 参数:userData:用户数据指针strApp:应用名,strStream:流名称 - */ -typedef void (API_CALL *onEventPlay)(void *userData,const char *strApp,const char *strStream); - -/* - * 描述:监听事件 - * 参数:cb:回调函数指针,userData:用户数据指针 - * 返回值:无 - */ -API_EXPORT void API_CALL listenEvent_onPlay(onEventPlay cb,void *userData); - -/* - * 描述:注册RTSP事件 - * 参数:userData:用户数据指针strApp:应用名,strStream:流名称 - */ -typedef void (API_CALL *onEventRegistMediaSrc)(void *userData,const char *strApp,const char *strStream); - -/* - * 描述:监听事件 - * 参数:cb:回调函数指针,userData:用户数据指针 - * 返回值:无 - */ -API_EXPORT void API_CALL listenEvent_onRegistRtsp(onEventRegistMediaSrc cb,void *userData); - -/* - * 描述:监听事件 - * 参数:cb:回调函数指针,userData:用户数据指针 - * 返回值:无 - */ -API_EXPORT void API_CALL listenEvent_onRegistRtmp(onEventRegistMediaSrc cb,void *userData); - /////////////////////////日志//////////////////////////////// diff --git a/c_wrapper/src/media.cpp b/c_wrapper/src/media.cpp index 503274e4..fe3537ac 100755 --- a/c_wrapper/src/media.cpp +++ b/c_wrapper/src/media.cpp @@ -50,7 +50,7 @@ static onceToken s_token([](){ //////////////////////////Rtsp media/////////////////////////// API_EXPORT MediaContext API_CALL createMedia(const char *appName,const char *mediaName) { - DevChannel::Ptr ret(new DevChannel(appName,mediaName)); + DevChannel::Ptr ret(new DevChannel(DEFAULT_VHOST,appName,mediaName)); lock_guard lck(s_mtxMapMedia); s_mapMedia.emplace((void *) (ret.get()), ret); return ret.get(); diff --git a/c_wrapper/src/proxyplayer.cpp b/c_wrapper/src/proxyplayer.cpp index 3d7f223c..af942019 100644 --- a/c_wrapper/src/proxyplayer.cpp +++ b/c_wrapper/src/proxyplayer.cpp @@ -43,7 +43,7 @@ static onceToken s_token([](){ },nullptr); API_EXPORT ProxyPlayerContext API_CALL createProxyPlayer(const char *app,const char *stream,int rtp_type){ - PlayerProxy::Ptr ret(new PlayerProxy(app,stream)); + PlayerProxy::Ptr ret(new PlayerProxy(DEFAULT_VHOST,app,stream)); (*ret)[RtspPlayer::kRtpType] = rtp_type; lock_guard lck(s_mtxMapProxyPlayer); diff --git a/src/Common/MediaSender.h b/src/Common/MediaSender.h index b453ee57..a4fe7e41 100644 --- a/src/Common/MediaSender.h +++ b/src/Common/MediaSender.h @@ -34,7 +34,7 @@ using namespace ZL::Thread; class MediaSender { public: static ThreadPool & sendThread() { - static ThreadPool pool(1); + static ThreadPool pool(1,ThreadPool::PRIORITY_HIGHEST); return pool; } private: diff --git a/src/Common/config.cpp b/src/Common/config.cpp index 5f380f44..d8fc45cd 100644 --- a/src/Common/config.cpp +++ b/src/Common/config.cpp @@ -47,9 +47,8 @@ void loadIniConfig(){ } ////////////广播名称/////////// namespace Broadcast { -const char kBroadcastRtspSessionPlay[] = "kBroadcastRtspSessionPlay"; -const char kBroadcastRtspSrcRegisted[] = "kBroadcastRtspSrcRegisted"; -const char kBroadcastRtmpSrcRegisted[] = "kBroadcastRtmpSrcRegisted"; +const char kBroadcastMediaPlayed[] = "kBroadcastMediaPlayed"; +const char kBroadcastMediaChanged[] = "kBroadcastMediaChanged"; const char kBroadcastRecordMP4[] = "kBroadcastRecordMP4"; const char kBroadcastHttpRequest[] = "kBroadcastHttpRequest"; const char kBroadcastOnGetRtspRealm[] = "kBroadcastOnGetRtspRealm"; @@ -105,10 +104,6 @@ const char kMaxReqCount[] = HTTP_FIELD"maxReqCount"; #endif const char kCharSet[] = HTTP_FIELD"charSet"; -//http 服务器名称 -#define HTTP_SERVER_NAME "ZLServer" -const char kServerName[] = HTTP_FIELD"serverName"; - //http 服务器根目录 #define HTTP_ROOT_PATH (exeDir() + "httpRoot") const char kRootPath[] = HTTP_FIELD"rootPath"; @@ -119,17 +114,12 @@ const char kRootPath[] = HTTP_FIELD"rootPath"; ""\ "

您访问的资源不存在!

"\ "
"\ - HTTP_SERVER_NAME\ + SERVER_NAME\ "
"\ ""\ "" const char kNotFound[] = HTTP_FIELD"notFound"; -//HTTP访问url前缀 -#define HTTP_PREFIX (StrPrinter << "http://" \ - << SockUtil::get_local_ip() \ - << ":" << HTTP_PORT << endl) -const char kHttpPrefix[] = HTTP_FIELD"httpPrefix"; onceToken token([](){ mINI::Instance()[kPort] = HTTP_PORT; @@ -139,10 +129,8 @@ onceToken token([](){ mINI::Instance()[kKeepAliveSecond] = HTTP_KEEP_ALIVE_SECOND; mINI::Instance()[kMaxReqCount] = HTTP_MAX_REQ_CNT; mINI::Instance()[kCharSet] = HTTP_CHAR_SET; - mINI::Instance()[kServerName] = HTTP_SERVER_NAME; mINI::Instance()[kRootPath] = HTTP_ROOT_PATH; mINI::Instance()[kNotFound] = HTTP_NOT_FOUND; - mINI::Instance()[kHttpPrefix] = HTTP_PREFIX; },nullptr); }//namespace Http @@ -154,15 +142,11 @@ namespace Shell { #define SHELL_PORT 9000 const char kPort[] = SHELL_FIELD"port"; -#define SHELL_SERVER_NAME "ZLServer" -const char kServerName[] = SHELL_FIELD"serverName"; - #define SHELL_MAX_REQ_SIZE 1024 const char kMaxReqSize[] = SHELL_FIELD"maxReqSize"; onceToken token([](){ mINI::Instance()[kPort] = SHELL_PORT; - mINI::Instance()[kServerName] = SHELL_SERVER_NAME; mINI::Instance()[kMaxReqSize] = SHELL_MAX_REQ_SIZE; },nullptr); } //namespace Shell @@ -174,14 +158,10 @@ namespace Rtsp { #define RTSP_PORT 554 const char kPort[] = RTSP_FIELD"port"; -#define RTSP_SERVER_NAME "ZLServer" -const char kServerName[] = RTSP_FIELD"serverName"; - const char kAuthBasic[] = RTSP_FIELD"authBasic"; onceToken token([](){ mINI::Instance()[kPort] = RTSP_PORT; - mINI::Instance()[kServerName] = RTSP_SERVER_NAME; //默认Md5方式认证 mINI::Instance()[kAuthBasic] = 0; },nullptr); @@ -278,12 +258,6 @@ const char kSampleMS[] = RECORD_FIELD"sampleMS"; #define RECORD_FILE_SECOND (10*60) const char kFileSecond[] = RECORD_FIELD"fileSecond"; -//Rtsp访问url前缀 -#define RECORD_RTSP_PREFIX (StrPrinter << "rtsp://" \ - << SockUtil::get_local_ip() \ - << ":" << RTSP_PORT << endl) -const char kRtspPrefix[] = RECORD_FIELD"rtspPrefix"; - //录制文件路径 #define RECORD_FILE_PATH HTTP_ROOT_PATH const char kFilePath[] = RECORD_FIELD"filePath"; @@ -293,7 +267,6 @@ onceToken token([](){ mINI::Instance()[kSampleMS] = RECORD_SAMPLE_MS; mINI::Instance()[kFileSecond] = RECORD_FILE_SECOND; mINI::Instance()[kFilePath] = RECORD_FILE_PATH; - mINI::Instance()[kRtspPrefix] = RECORD_RTSP_PREFIX; },nullptr); } //namespace Record @@ -318,11 +291,21 @@ const char kFileBufSize[] = HLS_FIELD"fileBufSize"; #define HLS_FILE_PATH (HTTP_ROOT_PATH) const char kFilePath[] = HLS_FIELD"filePath"; +//HTTP访问url前缀 +#define HTTP_PREFIX (StrPrinter << "http://${" << VHOST_KEY << "}:" << HTTP_PORT << endl) +const char kHttpPrefix[] = HLS_FIELD"httpPrefix"; + +#define HTTP_PREFIX_DEFAULT_VHOST (StrPrinter << "http://" << SockUtil::get_local_ip() << ":" << HTTP_PORT << endl) +const char kHttpPrefixDefaultVhost[] = HLS_FIELD"httpPrefixDefaultVhost"; + onceToken token([](){ mINI::Instance()[kSegmentDuration] = HLS_SEGMENT_DURATION; mINI::Instance()[kSegmentNum] = HLS_SEGMENT_NUM; mINI::Instance()[kFileBufSize] = HLS_FILE_BUF_SIZE; mINI::Instance()[kFilePath] = HLS_FILE_PATH; + mINI::Instance()[kHttpPrefix] = HTTP_PREFIX; + mINI::Instance()[kHttpPrefixDefaultVhost] = HTTP_PREFIX_DEFAULT_VHOST; + },nullptr); } //namespace Hls diff --git a/src/Common/config.h b/src/Common/config.h index defa2ef8..aa24e4d0 100644 --- a/src/Common/config.h +++ b/src/Common/config.h @@ -25,8 +25,8 @@ */ -#ifndef appConfig_h -#define appConfig_h +#ifndef COMMON_CONFIG_H +#define COMMON_CONFIG_H #include "Util/mini.h" using namespace ZL::Util; @@ -35,12 +35,7 @@ namespace Config { void loadIniConfig(); ////////////TCP最大连接数/////////// -#ifdef __x86_64__ #define MAX_TCP_SESSION 100000 -#else -#define MAX_TCP_SESSION 128 -#endif - ////////////其他宏定义/////////// #ifndef MAX #define MAX(a,b) ((a) > (b) ? (a) : (b) ) @@ -54,17 +49,21 @@ void loadIniConfig(); #define CLEAR_ARR(arr) for(auto &item : arr){ item = 0;} #endif //CLEAR_ARR +#define SERVER_NAME "ZLMediaKit" +#define VHOST_KEY "vhost" +#define RTSP_SCHEMA "rtsp" +#define RTMP_SCHEMA "rtmp" +#define DEFAULT_VHOST "__defaultVhost__" +#define RTSP_VERSION 1.30 +#define RTSP_BUILDTIME __DATE__" CST" ////////////广播名称/////////// namespace Broadcast { -extern const char kBroadcastRtspSessionPlay[]; -#define BroadcastRtspSessionPlayArgs const char *app,const char *stream +extern const char kBroadcastMediaPlayed[]; +#define BroadcastMediaPlayedArgs const char *schema,const char *vhost,const char *app,const char *stream -extern const char kBroadcastRtspSrcRegisted[]; -#define BroadcastRtspSrcRegistedArgs const char *app,const char *stream - -extern const char kBroadcastRtmpSrcRegisted[]; -#define BroadcastRtmpSrcRegistedArgs const char *app,const char *stream +extern const char kBroadcastMediaChanged[]; +#define BroadcastMediaChangedArgs bool bRegist, const char *schema,const char *vhost,const char *app,const char *stream extern const char kBroadcastRecordMP4[]; #define BroadcastRecordMP4Args const Mp4Info &info @@ -103,29 +102,22 @@ extern const char kKeepAliveSecond[]; extern const char kMaxReqCount[]; //http 字符编码 extern const char kCharSet[]; -//http 服务器名称 -extern const char kServerName[]; //http 服务器根目录 extern const char kRootPath[]; //http 404错误提示内容 extern const char kNotFound[]; -//HTTP访问url前缀 -extern const char kHttpPrefix[]; + }//namespace Http ////////////SHELL配置/////////// namespace Shell { -extern const char kServerName[]; extern const char kMaxReqSize[]; extern const char kPort[]; } //namespace Shell ////////////RTSP服务器配置/////////// namespace Rtsp { -#define RTSP_VERSION 1.30 -#define RTSP_BUILDTIME __DATE__" CST" -extern const char kServerName[]; extern const char kPort[]; //是否优先base64方式认证?默认Md5方式认证 extern const char kAuthBasic[]; @@ -171,8 +163,6 @@ extern const char kAppName[]; extern const char kSampleMS[]; //MP4文件录制大小,不能太大,否则MP4Close函数执行事件太长 extern const char kFileSecond[]; -//Rtsp访问url前缀 -extern const char kRtspPrefix[]; //录制文件路径 extern const char kFilePath[]; } //namespace Record @@ -187,8 +177,12 @@ extern const char kSegmentNum[]; extern const char kFileBufSize[]; //录制文件路径 extern const char kFilePath[]; +//HTTP访问url前缀 +extern const char kHttpPrefix[]; +//HTTP默认vhost访问url前缀 +extern const char kHttpPrefixDefaultVhost[]; } //namespace Hls } // namespace Config -#endif /* appConfig_h */ +#endif /* COMMON_CONFIG_H */ diff --git a/src/Device/Device.cpp b/src/Device/Device.cpp index 4699caae..f11b8a38 100644 --- a/src/Device/Device.cpp +++ b/src/Device/Device.cpp @@ -36,28 +36,22 @@ using namespace ZL::Util; namespace ZL { namespace DEV { +DevChannel::DevChannel(const char *strVhost,const char *strApp, const char *strId,float fDuration,bool bLiveStream ) : + RtspToRtmpMediaSource(strVhost,strApp,strId , bLiveStream) { -///////////////////////////////////////////////////////////////////////////////// -#ifdef ENABLE_RTSP2RTMP -DevChannel::DevChannel(const char *strApp, const char *strId,float fDuration,bool bLiveStream ) : - m_mediaSrc(new RtspToRtmpMediaSource(strApp,strId , bLiveStream)) { -#else -DevChannel::DevChannel(const char *strApp, const char *strId,float fDuration,bool bLiveStream ) : - m_mediaSrc(new RtspToRtmpMediaSource(strApp,strId )) { -#endif //ENABLE_RTSP2RTMP - 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"; + 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"; //直播,时间长度永远 if(fDuration <= 0 || bLiveStream){ - m_strSDP += "a=range:npt=0-\r\n"; + m_strSdp += "a=range:npt=0-\r\n"; }else{ - m_strSDP += StrPrinter <<"a=range:npt=0-" << fDuration << "\r\n" << endl; + m_strSdp += StrPrinter <<"a=range:npt=0-" << fDuration << "\r\n" << endl; } - m_strSDP += "a=control:*\r\n"; + m_strSdp += "a=control:*\r\n"; } DevChannel::~DevChannel() { } @@ -110,7 +104,7 @@ void DevChannel::inputH264(char* pcData, int iDataLen, uint32_t uiStamp) { uint32_t ui32Ssrc; memcpy(&ui32Ssrc, makeRandStr(4, false).data(), 4); auto lam = [this](const RtpPacket::Ptr &pkt, bool bKeyPos) { - m_mediaSrc->onGetRTP(pkt,bKeyPos); + onGetRTP(pkt,bKeyPos); }; static uint32_t videoMtu = mINI::Instance()[Config::Rtp::kVideoMtuSize].as(); m_pRtpMaker_h264.reset(new RtpMaker_H264(lam, ui32Ssrc,videoMtu)); @@ -133,7 +127,7 @@ void DevChannel::inputAAC(char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp uint32_t ssrc; memcpy(&ssrc, makeRandStr(8, false).data() + 4, 4); auto lam = [this](const RtpPacket::Ptr &pkt, bool keyPos) { - m_mediaSrc->onGetRTP(pkt,keyPos); + onGetRTP(pkt,keyPos); }; static uint32_t audioMtu = mINI::Instance()[Config::Rtp::kAudioMtuSize].as(); m_pRtpMaker_aac.reset(new RtpMaker_AAC(lam, ssrc, audioMtu,m_audio->iSampleRate)); @@ -184,47 +178,47 @@ inline void DevChannel::makeSDP_264(unsigned char *pcData, int iDataLen) { } //视频通道 - m_strSDP += StrPrinter << "m=video 0 RTP/AVP " + 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() + 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() + m_strSdp += StrPrinter << "a=fmtp:" << m_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="; + m_strSdp += acTmp; + m_strSdp += ";sprop-parameter-sets="; memset(acTmp, 0, sizeof(acTmp)); av_base64_encode(acTmp, sizeof(acTmp), (uint8_t *) m_aucSPS, m_uiSPSLen); //WarnL<<"SPS base64:"<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_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"; + m_strSdp += StrPrinter << m_video->iWidth << endl; + m_strSdp += "-"; + m_strSdp += StrPrinter << m_video->iHeight << endl; + m_strSdp += "\r\n"; } - m_strSDP += StrPrinter << "a=control:trackID=" + 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); + makeSDP(m_strSdp); } } else { - makeSDP(m_strSDP); + makeSDP(m_strSdp); } } @@ -237,33 +231,33 @@ 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_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() + m_strSdp += "b=AS:96\r\n"; + m_strSdp += StrPrinter << "a=rtpmap:" << m_pRtpMaker_aac->getPlayloadType() << " MPEG4-GENERIC/" << m_pRtpMaker_aac->getSampleRate() << "\r\n" << endl; - m_strSDP += StrPrinter << "a=fmtp:" << m_pRtpMaker_aac->getPlayloadType() + m_strSdp += StrPrinter << "a=fmtp:" << m_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_strSdp += fConfigStr; + m_strSdp += "\r\n"; + m_strSdp += StrPrinter << "a=control:trackID=" << m_pRtpMaker_aac->getInterleaved() / 2 << "\r\n" << endl; m_bSdp_gotAAC = true; if (m_video) { if (m_bSdp_gotH264) { - makeSDP(m_strSDP); + makeSDP(m_strSdp); } } else { - makeSDP(m_strSDP); + makeSDP(m_strSdp); } } void DevChannel::makeSDP(const string& strSdp) { - m_mediaSrc->onGetSDP(strSdp); - m_mediaSrc->regist(); + onGetSDP(strSdp); + regist(); } void DevChannel::initVideo(const VideoInfo& info) { diff --git a/src/Device/Device.h b/src/Device/Device.h index f07cab21..0865a5b6 100644 --- a/src/Device/Device.h +++ b/src/Device/Device.h @@ -49,6 +49,7 @@ using namespace ZL::Codec; using namespace ZL::Codec; #endif //ENABLE_X264 + namespace ZL { namespace DEV { @@ -65,10 +66,10 @@ public: int iSampleRate; }; -class DevChannel { +class DevChannel : public RtspToRtmpMediaSource{ public: typedef std::shared_ptr Ptr; - DevChannel(const char *strApp, const char *strId,float fDuration = 0,bool bLiveStream = true); + DevChannel(const char *strVhost,const char *strApp, const char *strId,float fDuration = 0,bool bLiveStream = true); virtual ~DevChannel(); void initVideo(const VideoInfo &info); @@ -80,20 +81,6 @@ public: void inputH264(char *pcData, int iDataLen, uint32_t uiStamp); void inputAAC(char *pcDataWithAdts, int iDataLen, uint32_t uiStamp); void inputAAC(char *pcDataWithoutAdts,int iDataLen, uint32_t uiStamp,char *pcAdtsHeader); -#ifdef ENABLE_RTSP2RTMP - int readerCount() { - return m_mediaSrc ? m_mediaSrc->readerCount() : 0; - } - void updateTimeStamp(uint32_t uiStamp){ - m_mediaSrc->updateTimeStamp(uiStamp); - } -#endif //ENABLE_RTSP2RTMP - void setOnSeek(const function &onSeek){ - m_mediaSrc->setOnSeek(onSeek); - } - void setOnStamp(const function &cb) { - m_mediaSrc->setOnStamp(cb); - } private: inline void makeSDP_264(unsigned char *pucData, int iDataLen); inline void makeSDP_AAC(unsigned char *pucData); @@ -107,8 +94,6 @@ private: #endif //ENABLE_FAAC RtpMaker_AAC::Ptr m_pRtpMaker_aac; RtpMaker_H264::Ptr m_pRtpMaker_h264; - RtspToRtmpMediaSource::Ptr m_mediaSrc; - string m_strSDP; bool m_bSdp_gotH264 = false; bool m_bSdp_gotAAC = false; diff --git a/src/Device/PlayerProxy.cpp b/src/Device/PlayerProxy.cpp index 3d0b1f9d..1f7f651a 100644 --- a/src/Device/PlayerProxy.cpp +++ b/src/Device/PlayerProxy.cpp @@ -39,7 +39,8 @@ namespace DEV { const char PlayerProxy::kAliveSecond[] = "alive_second"; -PlayerProxy::PlayerProxy(const char *strApp,const char *strSrc){ +PlayerProxy::PlayerProxy(const char *strVhost,const char *strApp,const char *strSrc){ + m_strVhost = strVhost; m_strApp = strApp; m_strSrc = strSrc; } @@ -133,7 +134,7 @@ void PlayerProxy::initMedia() { if (!isInited()) { return; } - m_pChn.reset(new DevChannel(m_strApp.data(),m_strSrc.data(),getDuration())); + m_pChn.reset(new DevChannel(m_strVhost.data(),m_strApp.data(),m_strSrc.data(),getDuration())); if (containVideo()) { VideoInfo info; info.iFrameRate = getVideoFps(); diff --git a/src/Device/PlayerProxy.h b/src/Device/PlayerProxy.h index 6dc2fba1..216156af 100644 --- a/src/Device/PlayerProxy.h +++ b/src/Device/PlayerProxy.h @@ -45,7 +45,7 @@ public: //设置方法:proxy[PlayerProxy::kAliveSecond] = 100; static const char kAliveSecond[]; - PlayerProxy(const char *strApp, const char *strSrc); + PlayerProxy(const char *strVhost, const char *strApp, const char *strSrc); virtual ~PlayerProxy(); void play(const char* strUrl) override; void setOnExpired(const function &cb){ @@ -56,6 +56,7 @@ private : Ticker m_aliveTicker; uint32_t m_aliveSecond = 0; function onExpired; + string m_strVhost; string m_strApp; string m_strSrc; void initMedia(); diff --git a/src/Http/HttpSession.cpp b/src/Http/HttpSession.cpp index f934a79c..59826ce8 100644 --- a/src/Http/HttpSession.cpp +++ b/src/Http/HttpSession.cpp @@ -182,14 +182,13 @@ inline bool HttpSession::checkLiveFlvStream(){ //未找到".flv"后缀 return false; } - auto app = FindField(m_parser.Url().data(),"/","/"); - auto stream = FindField(m_parser.Url().data(),(string("/") + app + "/").data(),"."); - if(app.empty() || stream.empty()){ - //不能拆分成2级url - return false; + auto fullUrl = string("http://") + m_parser["Host"] + FindField(m_parser.Url().data(),NULL,pos); + MediaInfo info(fullUrl); + if(!m_parser.getUrlArgs()[VHOST_KEY].empty()){ + info.m_vhost = m_parser.getUrlArgs()[VHOST_KEY]; } - //TO-DO - auto mediaSrc = RtmpMediaSource::find(app,stream); + + auto mediaSrc = dynamic_pointer_cast(MediaSource::find(RTMP_SCHEMA,info.m_vhost,info.m_app,info.m_streamid)); if(!mediaSrc){ //该rtmp源不存在 return false; @@ -274,7 +273,13 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() { return Http_success; } //事件未被拦截,则认为是http下载请求 - string strFile = m_strPath + m_parser.Url(); + + auto fullUrl = string("http://") + m_parser["Host"] + m_parser.Url(); + MediaInfo info(fullUrl); + if(!m_parser.getUrlArgs()[VHOST_KEY].empty()){ + info.m_vhost = m_parser.getUrlArgs()[VHOST_KEY]; + } + string strFile = m_strPath + "/" + info.m_vhost + m_parser.Url(); /////////////HTTP连接是否需要被关闭//////////////// static uint32_t reqCnt = mINI::Instance()[Config::Http::kMaxReqCount].as(); bool bClose = (strcasecmp(m_parser["Connection"].data(),"close") == 0) && ( ++m_iReqCnt < reqCnt); @@ -283,7 +288,7 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() { if (strFile.back() == '/') { //生成文件夹菜单索引 string strMeun; - if (!makeMeun(strFile, strMeun)) { + if (!makeMeun(strFile,info.m_vhost, strMeun)) { //文件夹不存在 sendNotFound(bClose); return eHttpCode; @@ -372,7 +377,7 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() { //文件读完 //InfoL << "send complete!" << iRead << " " << iReq << " " << *piLeft; if(iRead>0) { - sendBuf->setSize(iRead); + sendBuf->setSize(iRead); strongSelf->sock->setSendPktSize(3);//强制写入socket缓存 strongSelf->sock->send(sendBuf,SOCKET_DEFAULE_FLAGS | FLAG_MORE); } @@ -409,7 +414,7 @@ inline HttpSession::HttpCode HttpSession::Handle_Req_GET() { return Http_success; } -inline bool HttpSession::makeMeun(const string &strFullPath, string &strRet) { +inline bool HttpSession::makeMeun(const string &strFullPath,const string &vhost, string &strRet) { string strPathPrefix(strFullPath); strPathPrefix = strPathPrefix.substr(0, strPathPrefix.length() - 1); if (!File::is_dir(strPathPrefix.data())) { @@ -423,7 +428,7 @@ inline bool HttpSession::makeMeun(const string &strFullPath, string &strRet) { "

文件索引:"; string strPath = strFullPath; - strPath = strPath.substr(m_strPath.length(), strFullPath.length() - m_strPath.length()); + strPath = strPath.substr(m_strPath.length() + vhost.length() + 1); strRet += strPath; strRet += "

\r\n"; if (strPath != "/") { @@ -503,13 +508,12 @@ inline void HttpSession::sendResponse(const char* pcStatus, const KeyValue& head } inline HttpSession::KeyValue HttpSession::makeHttpHeader(bool bClose, int64_t iContentSize,const char* pcContentType) { KeyValue headerOut; - static string serverName = mINI::Instance()[Config::Http::kServerName]; static string charSet = mINI::Instance()[Config::Http::kCharSet]; static uint32_t keepAliveSec = mINI::Instance()[Config::Http::kKeepAliveSecond].as(); static uint32_t reqCnt = mINI::Instance()[Config::Http::kMaxReqCount].as(); headerOut.emplace("Date", dateStr()); - headerOut.emplace("Server", serverName); + headerOut.emplace("Server", SERVER_NAME); headerOut.emplace("Connection", bClose ? "close" : "keep-alive"); if(!bClose){ headerOut.emplace("Keep-Alive",StrPrinter << "timeout=" << keepAliveSec << ", max=" << reqCnt << endl); diff --git a/src/Http/HttpSession.h b/src/Http/HttpSession.h index 26704fdd..0b17607e 100644 --- a/src/Http/HttpSession.h +++ b/src/Http/HttpSession.h @@ -87,7 +87,7 @@ private: inline bool checkLiveFlvStream(); inline bool emitHttpEvent(bool doInvoke); inline void urlDecode(Parser &parser); - inline bool makeMeun(const string &strFullPath, string &strRet); + inline bool makeMeun(const string &strFullPath,const string &vhost, string &strRet); inline void sendNotFound(bool bClose); inline void sendResponse(const char *pcStatus,const KeyValue &header,const string &strContent); inline static KeyValue makeHttpHeader(bool bClose=false,int64_t iContentSize=-1,const char *pcContentType="text/html"); diff --git a/src/MediaFile/HLSMaker.cpp b/src/MediaFile/HLSMaker.cpp index 8480e0fe..6b896ba1 100644 --- a/src/MediaFile/HLSMaker.cpp +++ b/src/MediaFile/HLSMaker.cpp @@ -38,10 +38,6 @@ HLSMaker::HLSMaker(const string& strM3u8File, const string& strHttpUrl, if (ui32BufSize < 16 * 1024) { ui32BufSize = 16 * 1024; } - - if(ui32Duration < 0){ - ui32Duration = 0; - } if(ui32Num < 1){ ui32Num = 1; } diff --git a/src/MediaFile/MediaReader.cpp b/src/MediaFile/MediaReader.cpp index 9247b1b3..66680e26 100644 --- a/src/MediaFile/MediaReader.cpp +++ b/src/MediaFile/MediaReader.cpp @@ -36,9 +36,9 @@ namespace ZL { namespace MediaFile { #ifdef ENABLE_MP4V2 -MediaReader::MediaReader(const string &strApp, const string &strId) { +MediaReader::MediaReader(const string &strVhost,const string &strApp, const string &strId) { static string recordPath = mINI::Instance()[Config::Record::kFilePath]; - auto strFileName = recordPath + "/" + strApp + "/" + strId; + auto strFileName = recordPath + "/" + strVhost + "/" + strApp + "/" + strId; m_hMP4File = MP4Read(strFileName.data()); if(m_hMP4File == MP4_INVALID_FILE_HANDLE){ @@ -129,7 +129,7 @@ MediaReader::MediaReader(const string &strApp, const string &strId) { } m_iDuration = MAX(m_video_ms,m_audio_ms); - m_pChn.reset(new DevChannel(strApp.data(),strId.data(),m_iDuration/1000.0,false)); + m_pChn.reset(new DevChannel(strVhost.data(),strApp.data(),strId.data(),m_iDuration/1000.0,false)); if (m_audio_trId != MP4_INVALID_TRACK_ID) { AudioInfo info; info.iChannel = m_audio_num_channels; @@ -169,26 +169,17 @@ MediaReader::~MediaReader() { void MediaReader::startReadMP4() { auto strongSelf = shared_from_this(); static uint32_t sampleMS = mINI::Instance()[Config::Record::kSampleMS].as(); - AsyncTaskThread::Instance().DoTaskDelay(reinterpret_cast(this), sampleMS, [strongSelf](){ return strongSelf->readSample(); }); - weak_ptr weakSelf = strongSelf; - m_pChn->setOnSeek([weakSelf](uint32_t ui32Stamp){ - auto strongSelf = weakSelf.lock(); - if(!strongSelf){ - return false; - } - strongSelf->seek(ui32Stamp); - return true; - }); - m_pChn->setOnStamp([weakSelf]() -> uint32_t { - auto strongSelf = weakSelf.lock(); - if(!strongSelf) { - return 0; - } - return strongSelf-> m_iSeekTime + strongSelf->m_ticker.elapsedTime(); - }); + m_pChn->setListener(strongSelf); +} + bool MediaReader::seekTo(uint32_t ui32Stamp){ + seek(ui32Stamp); + return true; +} +uint32_t MediaReader::getStamp() { + return m_iSeekTime + m_ticker.elapsedTime(); } bool MediaReader::readSample(int iTimeInc) { @@ -322,36 +313,18 @@ void MediaReader::seek(int iSeekTime,bool bReStart){ #endif //ENABLE_MP4V2 -RtspMediaSource::Ptr MediaReader::onMakeRtsp(const string &strApp, const string &strId) { -#ifdef ENABLE_MP4V2 - static string appName = mINI::Instance()[Config::Record::kAppName]; - if (strApp != appName) { - return nullptr; - } - try{ - MediaReader::Ptr pReader(new MediaReader(strApp,strId)); - pReader->startReadMP4(); - return RtspMediaSource::find(strApp, strId, false); - }catch (std::exception &ex) { - WarnL << ex.what(); - return nullptr; - } -#else - return nullptr; -#endif //ENABLE_MP4V2 -} -RtmpMediaSource::Ptr MediaReader::onMakeRtmp(const string &strApp, const string &strId) { +MediaSource::Ptr MediaReader::onMakeMediaSource(const string &strSchema,const string &strVhost,const string &strApp, const string &strId){ #ifdef ENABLE_MP4V2 static string appName = mINI::Instance()[Config::Record::kAppName]; if (strApp != appName) { return nullptr; } try { - MediaReader::Ptr pReader(new MediaReader(strApp, strId)); + MediaReader::Ptr pReader(new MediaReader(strVhost,strApp, strId)); pReader->startReadMP4(); - return RtmpMediaSource::find(strApp, strId, false); + return MediaSource::find(strSchema,strVhost,strApp, strId, false); } catch (std::exception &ex) { WarnL << ex.what(); return nullptr; @@ -359,7 +332,6 @@ RtmpMediaSource::Ptr MediaReader::onMakeRtmp(const string &strApp, const string #else return nullptr; #endif //ENABLE_MP4V2 - } diff --git a/src/MediaFile/MediaReader.h b/src/MediaFile/MediaReader.h index aeb671a1..81a74a49 100644 --- a/src/MediaFile/MediaReader.h +++ b/src/MediaFile/MediaReader.h @@ -42,13 +42,15 @@ using namespace ZL::Rtmp; namespace ZL { namespace MediaFile { -class MediaReader : public std::enable_shared_from_this{ +class MediaReader : public std::enable_shared_from_this ,public MediaSourceEvent{ public: typedef std::shared_ptr Ptr; - MediaReader(const string &strApp, const string &strId); + MediaReader(const string &strVhost,const string &strApp, const string &strId); virtual ~MediaReader(); - static RtspMediaSource::Ptr onMakeRtsp(const string &strApp, const string &strId); - static RtmpMediaSource::Ptr onMakeRtmp(const string &strApp, const string &strId); + static MediaSource::Ptr onMakeMediaSource(const string &strSchema,const string &strVhost,const string &strApp, const string &strId); +public: + bool seekTo(uint32_t ui32Stamp) override; + uint32_t getStamp() override; private: #ifdef ENABLE_MP4V2 @@ -95,6 +97,8 @@ private: inline bool readAudioSample(int iTimeInc = 0); inline void writeH264(uint8_t *pucData,int iLen,uint32_t uiStamp); inline void writeAAC(uint8_t *pucData,int iLen,uint32_t uiStamp); + + #endif //ENABLE_MP4V2 }; diff --git a/src/MediaFile/MediaRecorder.cpp b/src/MediaFile/MediaRecorder.cpp index e594db66..11fb5cdd 100644 --- a/src/MediaFile/MediaRecorder.cpp +++ b/src/MediaFile/MediaRecorder.cpp @@ -37,24 +37,39 @@ using namespace ZL::Network; namespace ZL { namespace MediaFile { -MediaRecorder::MediaRecorder(const string &strApp,const string &strId,const std::shared_ptr &pPlayer) { -#ifdef ENABLE_HLS - static string hlsPrefix = mINI::Instance()[Config::Http::kHttpPrefix]; +MediaRecorder::MediaRecorder(const string &strVhost ,const string &strApp,const string &strId,const std::shared_ptr &pPlayer) { + static string hlsPrefix = mINI::Instance()[Config::Hls::kHttpPrefix]; + static string hlsPrefixDefaultVhost = mINI::Instance()[Config::Hls::kHttpPrefixDefaultVhost]; static string hlsPath = mINI::Instance()[Config::Hls::kFilePath]; static uint32_t hlsBufSize = mINI::Instance()[Config::Hls::kFileBufSize].as(); static uint32_t hlsDuration = mINI::Instance()[Config::Hls::kSegmentDuration].as(); static uint32_t hlsNum = mINI::Instance()[Config::Hls::kSegmentNum].as(); - m_hlsMaker.reset(new HLSMaker(hlsPath + "/" + strApp + "/" + strId + "/hls.m3u8", - hlsPrefix + "/" + strApp + "/" + strId + "/", - hlsBufSize,hlsDuration,hlsNum)); -#endif //ENABLE_HLS - + string hlsPrefixVhost = hlsPrefix; + do{ + //生成hls http前缀 + if (strVhost.empty() || strVhost == DEFAULT_VHOST) { + hlsPrefixVhost = hlsPrefixDefaultVhost; + break; + } + auto pos_start = hlsPrefixVhost.find("${"); + auto pos_end = hlsPrefixVhost.find("}"); + if (pos_start != string::npos && pos_end != string::npos && pos_end - pos_start - 2 > 0 ) { + auto key = hlsPrefixVhost.substr(pos_start + 2, pos_end - pos_start - 2); + trim(key); + if (key == VHOST_KEY) { + hlsPrefixVhost.replace(pos_start, pos_end - pos_start + 1, strVhost); + } + } + }while(0); + m_hlsMaker.reset(new HLSMaker(hlsPath + "/" + strVhost + "/" + strApp + "/" + strId + "/hls.m3u8", + hlsPrefixVhost + "/" + strApp + "/" + strId + "/", + hlsBufSize,hlsDuration,hlsNum)); #ifdef ENABLE_MP4V2 static string recordPath = mINI::Instance()[Config::Record::kFilePath]; static string recordAppName = mINI::Instance()[Config::Record::kAppName]; - m_mp4Maker.reset(new Mp4Maker(recordPath + "/" + recordAppName + "/" + strApp + "/" + strId + "/", - strApp,strId,pPlayer)); + m_mp4Maker.reset(new Mp4Maker(recordPath + "/" + strVhost + "/" + recordAppName + "/" + strApp + "/" + strId + "/", + strVhost,strApp,strId,pPlayer)); #endif //ENABLE_MP4V2 } @@ -62,20 +77,14 @@ MediaRecorder::~MediaRecorder() { } void MediaRecorder::inputH264(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType) { -#ifdef ENABLE_HLS m_hlsMaker->inputH264(pData, ui32Length, ui32TimeStamp * 90, iType); -#endif //ENABLE_HLS - #ifdef ENABLE_MP4V2 m_mp4Maker->inputH264(pData, ui32Length, ui32TimeStamp, iType); #endif //ENABLE_MP4V2 } void MediaRecorder::inputAAC(void* pData, uint32_t ui32Length, uint32_t ui32TimeStamp) { -#ifdef ENABLE_HLS m_hlsMaker->inputAAC(pData, ui32Length, ui32TimeStamp * 90); -#endif //ENABLE_HLS - #ifdef ENABLE_MP4V2 m_mp4Maker->inputAAC(pData, ui32Length, ui32TimeStamp); #endif //ENABLE_MP4V2 diff --git a/src/MediaFile/MediaRecorder.h b/src/MediaFile/MediaRecorder.h index 39fcbb1e..127b2bc9 100644 --- a/src/MediaFile/MediaRecorder.h +++ b/src/MediaFile/MediaRecorder.h @@ -34,9 +34,7 @@ #include "Mp4Maker.h" #endif //ENABLE_MP4V2 -#ifdef ENABLE_HLS #include "HLSMaker.h" -#endif //ENABLE_HLS using namespace std; using namespace ZL::Player; @@ -48,7 +46,7 @@ namespace MediaFile { class MediaRecorder { public: typedef std::shared_ptr Ptr; - MediaRecorder(const string &strApp,const string &strId,const std::shared_ptr &pPlayer); + MediaRecorder(const string &strVhost,const string &strApp,const string &strId,const std::shared_ptr &pPlayer); virtual ~MediaRecorder(); void inputH264( void *pData, @@ -60,11 +58,7 @@ public: uint32_t ui32Length, uint32_t ui32TimeStamp); private: - -#ifdef ENABLE_HLS std::shared_ptr m_hlsMaker; -#endif //ENABLE_HLS - #ifdef ENABLE_MP4V2 std::shared_ptr m_mp4Maker; #endif //ENABLE_MP4V2 diff --git a/src/MediaFile/Mp4Maker.cpp b/src/MediaFile/Mp4Maker.cpp index e2093fb5..13b09b15 100644 --- a/src/MediaFile/Mp4Maker.cpp +++ b/src/MediaFile/Mp4Maker.cpp @@ -59,7 +59,11 @@ string timeStr(const char *fmt) { #endif } -Mp4Maker::Mp4Maker(const string& strPath,const string &strApp,const string &strStreamId, const PlayerBase::Ptr &pPlayer) { +Mp4Maker::Mp4Maker(const string& strPath, + const string &strVhost, + const string &strApp, + const string &strStreamId, + const PlayerBase::Ptr &pPlayer) { DebugL << strPath; m_pPlayer = pPlayer; m_strPath = strPath; @@ -67,6 +71,7 @@ Mp4Maker::Mp4Maker(const string& strPath,const string &strApp,const string &strS /////record 业务逻辑////// m_info.strAppName = strApp; m_info.strStreamId = strStreamId; + m_info.strVhost = strVhost; m_info.strFolder = strPath; //----record 业务逻辑----// } @@ -144,7 +149,6 @@ void Mp4Maker::createFile() { } closeFile(); - auto strDate = timeStr("%Y-%m-%d"); auto strTime = timeStr("%H-%M-%S"); auto strFileTmp = m_strPath + strDate + "/." + strTime + ".mp4"; @@ -155,7 +159,8 @@ void Mp4Maker::createFile() { m_info.strFileName = strTime + ".mp4"; m_info.strFilePath = strFile; static string appName = mINI::Instance()[Config::Record::kAppName]; - m_info.strUrl = appName + "/" + m_info.strUrl = m_info.strVhost + "/" + + appName + "/" + m_info.strAppName + "/" + m_info.strStreamId + "/" + strDate + "/" diff --git a/src/MediaFile/Mp4Maker.h b/src/MediaFile/Mp4Maker.h index d71f7017..d24021f1 100644 --- a/src/MediaFile/Mp4Maker.h +++ b/src/MediaFile/Mp4Maker.h @@ -57,11 +57,16 @@ public: string strUrl;//播放路径 string strAppName;//应用名称 string strStreamId;//流ID + string strVhost;//vhost }; class Mp4Maker { public: typedef std::shared_ptr Ptr; - Mp4Maker(const string &strPath,const string &strApp,const string &strStreamId, const PlayerBase::Ptr &pPlayer); + Mp4Maker(const string &strPath, + const string &strVhost , + const string &strApp, + const string &strStreamId, + const PlayerBase::Ptr &pPlayer); virtual ~Mp4Maker(); //时间戳:参考频率1000 void inputH264(void *pData, uint32_t ui32Length, uint32_t ui32TimeStamp, int iType); diff --git a/src/Rtmp/RtmpMediaSource.cpp b/src/Rtmp/RtmpMediaSource.cpp index 27a5486d..261e4cf6 100644 --- a/src/Rtmp/RtmpMediaSource.cpp +++ b/src/Rtmp/RtmpMediaSource.cpp @@ -32,30 +32,6 @@ using namespace ZL::MediaFile; namespace ZL { namespace Rtmp { -recursive_mutex RtmpMediaSource::g_mtxMediaSrc; -unordered_map > > RtmpMediaSource::g_mapMediaSrc; - -RtmpMediaSource::Ptr RtmpMediaSource::find(const string &strApp, const string &strId, bool bMake) { - //查找某一媒体源,找到后返回 - lock_guard lock(g_mtxMediaSrc); - auto itApp = g_mapMediaSrc.find(strApp); - if (itApp == g_mapMediaSrc.end()) { - return bMake ? MediaReader::onMakeRtmp(strApp, strId) : nullptr; - } - auto itId = itApp->second.find(strId); - if (itId == itApp->second.end()) { - return bMake ? MediaReader::onMakeRtmp(strApp, strId) : nullptr; - } - auto ret = itId->second.lock(); - if (ret) { - return ret; - } - itApp->second.erase(itId); - if (itApp->second.size() == 0) { - g_mapMediaSrc.erase(itApp); - } - return bMake ? MediaReader::onMakeRtmp(strApp, strId) : nullptr; -} } /* namespace Rtmp */ } /* namespace ZL */ diff --git a/src/Rtmp/RtmpMediaSource.h b/src/Rtmp/RtmpMediaSource.h index 6a9d4c21..73e5fc8f 100644 --- a/src/Rtmp/RtmpMediaSource.h +++ b/src/Rtmp/RtmpMediaSource.h @@ -36,6 +36,7 @@ #include "Rtmp.h" #include "Common/config.h" #include "Common/MediaSender.h" +#include "Common/MediaSource.h" #include "Util/util.h" #include "Util/logger.h" #include "Util/RingBuffer.h" @@ -47,72 +48,28 @@ using namespace std; using namespace ZL::Util; using namespace ZL::Thread; +using namespace ZL::Media; namespace ZL { namespace Rtmp { - -class RtmpMediaSource: public enable_shared_from_this { +class RtmpMediaSource: public MediaSource { public: typedef std::shared_ptr Ptr; typedef RingBuffer RingType; - RtmpMediaSource(const string &strApp, const string &strId) : - m_strApp(strApp), - m_strId(strId), + + RtmpMediaSource(const string &vhost,const string &strApp, const string &strId) : + MediaSource(RTMP_SCHEMA,vhost,strApp,strId), m_pRing(new RingBuffer()), m_thPool( MediaSender::sendThread()) { } - virtual ~RtmpMediaSource() { - unregist(); - } + virtual ~RtmpMediaSource() {} + const RingType::Ptr &getRing() const { //获取媒体源的rtp环形缓冲 return m_pRing; } - virtual void regist() { - //注册该源,注册后rtmp服务器才能找到该源 - lock_guard lock(g_mtxMediaSrc); - if (!g_mapMediaSrc[m_strApp].erase(m_strId)) { - InfoL << "Rtmp src:" << m_strApp << " " << m_strId; - } - g_mapMediaSrc[m_strApp].emplace(m_strId, shared_from_this()); - NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRtmpSrcRegisted,m_strApp.data(),m_strId.data()); - } - virtual void unregist() { - //反注册该源 - lock_guard lock(g_mtxMediaSrc); - auto it = g_mapMediaSrc.find(m_strApp); - if (it == g_mapMediaSrc.end()) { - return; - } - if (it->second.erase(m_strId)) { - if (it->second.size() == 0) { - g_mapMediaSrc.erase(it); - } - InfoL << "Rtmp src:" << m_strApp << " " << m_strId; - } - } - static set getMediaSet() { - set ret; - lock_guard lock(g_mtxMediaSrc); - for (auto &pr0 : g_mapMediaSrc) { - for (auto &pr1 : pr0.second) { - if (pr1.second.lock()) { - ret.emplace(pr0.first + "/" + pr1.first); - } - } - } - return ret; - } - static Ptr find(const string &strApp, const string &strId, bool bMake = true) ; - const string& getApp() const { - //获取该源的id - return m_strApp; - } - const string& getId() const { - //获取该源的id - return m_strId; - } + const AMFValue &getMetaData() const { return m_metadata; } @@ -140,37 +97,12 @@ public: _ring->write(pkt,pkt->isVideoKeyFrame()); }); } - bool seekTo(uint32_t ui32Stamp) { - if (!m_onSeek) { - return false; - } - return m_onSeek(ui32Stamp); - } - virtual void setOnSeek(const function &cb) { - m_onSeek = cb; - } - uint32_t getStamp() { - if (!m_onStamp) { - return 0; - } - return m_onStamp(); - } - virtual void setOnStamp(const function &cb) { - m_onStamp = cb; - } protected: - function m_onSeek; - function m_onStamp; -private: AMFValue m_metadata; unordered_map m_mapCfgFrame; mutable recursive_mutex m_mtxMap; - string m_strApp; //媒体app - string m_strId; //媒体id RingBuffer::Ptr m_pRing; //rtp环形缓冲 ThreadPool &m_thPool; - static unordered_map > > g_mapMediaSrc; //静态的媒体源表 - static recursive_mutex g_mtxMediaSrc; ///访问静态的媒体源表的互斥锁 }; } /* namespace Rtmp */ diff --git a/src/Rtmp/RtmpPusher.cpp b/src/Rtmp/RtmpPusher.cpp index b589356d..4f8546d1 100644 --- a/src/Rtmp/RtmpPusher.cpp +++ b/src/Rtmp/RtmpPusher.cpp @@ -36,10 +36,10 @@ namespace ZL { namespace Rtmp { unordered_map RtmpPusher::g_mapCmd; -RtmpPusher::RtmpPusher(const char *strApp,const char *strStream) { - auto src = RtmpMediaSource::find(strApp,strStream); +RtmpPusher::RtmpPusher(const char *strVhost,const char *strApp,const char *strStream) { + auto src = dynamic_pointer_cast(MediaSource::find(RTMP_SCHEMA,strVhost,strApp,strStream)); if (!src) { - auto strErr = StrPrinter << "media source:" << strApp << "/" << strStream << "not found!" << endl; + auto strErr = StrPrinter << "media source:" << strVhost << "/" << strApp << "/" << strStream << "not found!" << endl; throw std::runtime_error(strErr); } init(src); diff --git a/src/Rtmp/RtmpPusher.h b/src/Rtmp/RtmpPusher.h index c779c0f1..138bf35c 100644 --- a/src/Rtmp/RtmpPusher.h +++ b/src/Rtmp/RtmpPusher.h @@ -38,7 +38,7 @@ class RtmpPusher: public RtmpProtocol , public TcpClient{ public: typedef std::shared_ptr Ptr; typedef std::function Event; - RtmpPusher(const char *strApp,const char *strStream); + RtmpPusher(const char *strVhost,const char *strApp,const char *strStream); RtmpPusher(const RtmpMediaSource::Ptr &src); virtual ~RtmpPusher(); diff --git a/src/Rtmp/RtmpSession.cpp b/src/Rtmp/RtmpSession.cpp index 99852640..359880a5 100644 --- a/src/Rtmp/RtmpSession.cpp +++ b/src/Rtmp/RtmpSession.cpp @@ -97,7 +97,12 @@ void RtmpSession::onCmd_connect(AMFDecoder &dec) { ///////////set peerBandwidth//////////////// sendPeerBandwidth(5000000); - m_strApp = params["app"].as_string(); + m_mediaInfo.m_app = params["app"].as_string(); + m_strTcUrl = params["tcUrl"].as_string(); + if(m_strTcUrl.empty()){ + //defaultVhost:默认vhost + m_strTcUrl = "rtmp://127.0.0.1/" + m_mediaInfo.m_app; + } bool ok = true; //(app == APP_NAME); AMFValue version(AMF_OBJECT); version.set("fmsVer", "FMS/3,0,1,123"); @@ -109,7 +114,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_strApp); + throw std::runtime_error("Unsupported application: " + m_mediaInfo.m_app); } AMFEncoder invoke; @@ -123,12 +128,12 @@ void RtmpSession::onCmd_createStream(AMFDecoder &dec) { void RtmpSession::onCmd_publish(AMFDecoder &dec) { dec.load();/* NULL */ - m_strId = dec.load(); - auto iPos = m_strId.find('?'); - if (iPos != string::npos) { - m_strId.erase(iPos); - } - auto src = RtmpMediaSource::find(m_strApp,m_strId,false); + m_mediaInfo.parse(m_strTcUrl + "/" + dec.load()); + auto src = dynamic_pointer_cast(MediaSource::find(RTMP_SCHEMA, + m_mediaInfo.m_vhost, + m_mediaInfo.m_app, + m_mediaInfo.m_streamid, + false)); bool ok = (!src && !m_pPublisherSrc); AMFValue status(AMF_OBJECT); status.set("level", ok ? "status" : "error"); @@ -137,10 +142,13 @@ void RtmpSession::onCmd_publish(AMFDecoder &dec) { status.set("clientid", "0"); sendReply("onStatus", nullptr, status); if (!ok) { - throw std::runtime_error( StrPrinter << "Already publishing:" << m_strApp << "/" << m_strId << endl); + throw std::runtime_error( StrPrinter << "Already publishing:" + << m_mediaInfo.m_vhost << " " + << m_mediaInfo.m_app << " " + << m_mediaInfo.m_streamid << endl); } m_bPublisherSrcRegisted = false; - m_pPublisherSrc.reset(new RtmpToRtspMediaSource(m_strApp,m_strId)); + m_pPublisherSrc.reset(new RtmpToRtspMediaSource(m_mediaInfo.m_vhost,m_mediaInfo.m_app,m_mediaInfo.m_streamid)); } void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) { @@ -152,11 +160,15 @@ void RtmpSession::onCmd_deleteStream(AMFDecoder &dec) { throw std::runtime_error(StrPrinter << "Stop publishing." << endl); } -void RtmpSession::doPlay(){ - auto src = RtmpMediaSource::find(m_strApp,m_strId,true); +void RtmpSession::doPlay(AMFDecoder &dec){ + m_mediaInfo.parse(m_strTcUrl + "/" + dec.load()); + auto src = dynamic_pointer_cast(MediaSource::find(RTMP_SCHEMA, + m_mediaInfo.m_vhost, + m_mediaInfo.m_app, + m_mediaInfo.m_streamid, + true)); bool ok = (src.operator bool()); ok = ok && src->ready(); - //stream begin sendUserControl(CONTROL_STREAM_BEGIN, STREAM_MEDIA); @@ -165,11 +177,15 @@ void RtmpSession::doPlay(){ status.set("level", ok ? "status" : "error"); status.set("code", ok ? "NetStream.Play.Reset" : "NetStream.Play.StreamNotFound"); status.set("description", ok ? "Resetting and playing." : "No such stream."); - status.set("details", m_strId); + status.set("details", m_mediaInfo.m_streamid); status.set("clientid", "0"); sendReply("onStatus", nullptr, status); if (!ok) { - throw std::runtime_error( StrPrinter << "No such stream:" << m_strApp << " " << m_strId << endl); + throw std::runtime_error( StrPrinter << "No such stream:" + << m_mediaInfo.m_vhost << " " + << m_mediaInfo.m_app << " " + << m_mediaInfo.m_streamid + << endl); } // onStatus(NetStream.Play.Start) @@ -177,7 +193,7 @@ void RtmpSession::doPlay(){ status.set("level", "status"); status.set("code", "NetStream.Play.Start"); status.set("description", "Started playing."); - status.set("details", m_strId); + status.set("details", m_mediaInfo.m_streamid); status.set("clientid", "0"); sendReply("onStatus", nullptr, status); @@ -198,7 +214,7 @@ void RtmpSession::doPlay(){ status.set("level", "status"); status.set("code", "NetStream.Play.PublishNotify"); status.set("description", "Now published."); - status.set("details", m_strId); + status.set("details", m_mediaInfo.m_streamid); status.set("clientid", "0"); sendReply("onStatus", nullptr, status); @@ -239,18 +255,19 @@ void RtmpSession::doPlay(){ if(src->getRing()->readerCount() == 1){ src->seekTo(0); } + + NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, + RTMP_SCHEMA, + m_mediaInfo.m_vhost.data(), + m_mediaInfo.m_app.data(), + m_mediaInfo.m_streamid.data()); } void RtmpSession::onCmd_play2(AMFDecoder &dec) { - doPlay(); + doPlay(dec); } void RtmpSession::onCmd_play(AMFDecoder &dec) { dec.load();/* NULL */ - m_strId = dec.load(); - auto iPos = m_strId.find('?'); - if (iPos != string::npos) { - m_strId.erase(iPos); - } - doPlay(); + doPlay(dec); } void RtmpSession::onCmd_pause(AMFDecoder &dec) { diff --git a/src/Rtmp/RtmpSession.h b/src/Rtmp/RtmpSession.h index 044bee82..2efa95d4 100644 --- a/src/Rtmp/RtmpSession.h +++ b/src/Rtmp/RtmpSession.h @@ -53,8 +53,8 @@ public: void onError(const SockException &err) override; void onManager() override; private: - std::string m_strApp; - std::string m_strId; + std::string m_strTcUrl; + MediaInfo m_mediaInfo; double m_dNowReqID = 0; Ticker m_ticker;//数据接收时间 typedef void (RtmpSession::*rtmpCMDHandle)(AMFDecoder &dec); @@ -75,7 +75,7 @@ private: void onCmd_play(AMFDecoder &dec); void onCmd_play2(AMFDecoder &dec); - void doPlay(); + void doPlay(AMFDecoder &dec); void onCmd_seek(AMFDecoder &dec); void onCmd_pause(AMFDecoder &dec); void setMetaData(AMFDecoder &dec); diff --git a/src/Rtmp/RtmpToRtspMediaSource.cpp b/src/Rtmp/RtmpToRtspMediaSource.cpp index de6053b9..fbe37d2d 100644 --- a/src/Rtmp/RtmpToRtspMediaSource.cpp +++ b/src/Rtmp/RtmpToRtspMediaSource.cpp @@ -36,25 +36,23 @@ using namespace ZL::Network; namespace ZL { namespace Rtmp { -#ifdef ENABLE_RTMP2RTSP -RtmpToRtspMediaSource::RtmpToRtspMediaSource(const string &_app, const string &_id) : - RtmpMediaSource(_app,_id) { -} -RtmpToRtspMediaSource::~RtmpToRtspMediaSource() { +RtmpToRtspMediaSource::RtmpToRtspMediaSource(const string &vhost,const string &app, const string &id) : + RtmpMediaSource(vhost,app,id) { } +RtmpToRtspMediaSource::~RtmpToRtspMediaSource() {} -void RtmpToRtspMediaSource::regist() { - RtmpMediaSource::regist(); +bool RtmpToRtspMediaSource::regist() { if (m_pRtspSrc) { m_pRtspSrc->regist(); } + return MediaSource::regist(); } -void RtmpToRtspMediaSource::unregist() { - RtmpMediaSource::unregist(); +bool RtmpToRtspMediaSource::unregist() { if(m_pRtspSrc){ m_pRtspSrc->unregist(); } + return MediaSource::unregist(); } void RtmpToRtspMediaSource::onGetH264(const H264Frame &frame) { @@ -156,14 +154,12 @@ void RtmpToRtspMediaSource::makeSDP() { << "\r\n" << endl; } - m_pRtspSrc.reset(new RtspMediaSource(getApp(),getId())); - m_pRtspSrc->setOnSeek(m_onSeek); - m_pRtspSrc->setOnStamp(m_onStamp); + m_pRtspSrc.reset(new RtspMediaSource(getVhost(),getApp(),getId())); + m_pRtspSrc->setListener(m_listener); m_pRtspSrc->onGetSDP(strSDP); m_pRtspSrc->regist(); } -#endif // ENABLE_RTMP2RTSP } /* namespace Rtmp */ } /* namespace ZL */ diff --git a/src/Rtmp/RtmpToRtspMediaSource.h b/src/Rtmp/RtmpToRtspMediaSource.h index 1b24d23f..f5b0a48d 100644 --- a/src/Rtmp/RtmpToRtspMediaSource.h +++ b/src/Rtmp/RtmpToRtspMediaSource.h @@ -52,19 +52,20 @@ using namespace ZL::MediaFile; namespace ZL { namespace Rtmp { -#ifdef ENABLE_RTMP2RTSP class RtmpToRtspMediaSource: public RtmpMediaSource { public: typedef std::shared_ptr Ptr; - RtmpToRtspMediaSource(const string &_app, const string &_id); - virtual ~RtmpToRtspMediaSource(); - virtual void regist() override; - virtual void unregist() override; - virtual void onGetMetaData(const AMFValue &_metadata) override { + RtmpToRtspMediaSource(const string &vhost,const string &app, const string &id); + virtual ~RtmpToRtspMediaSource(); + + bool regist() override; + bool unregist() override; + + void onGetMetaData(const AMFValue &_metadata) override { try { m_pParser.reset(new RtmpParser(_metadata)); - m_pRecorder.reset(new MediaRecorder(getApp(),getId(),m_pParser)); + m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser)); m_pParser->setOnAudioCB(std::bind(&RtmpToRtspMediaSource::onGetAdts, this, placeholders::_1)); m_pParser->setOnVideoCB(std::bind(&RtmpToRtspMediaSource::onGetH264, this, placeholders::_1)); } catch (exception &ex) { @@ -73,7 +74,7 @@ public: RtmpMediaSource::onGetMetaData(_metadata); } - virtual void onGetMedia(const RtmpPacket::Ptr &pkt) override { + void onGetMedia(const RtmpPacket::Ptr &pkt) override { if (m_pParser) { if (!m_pRtspSrc && m_pParser->isInited()) { makeSDP(); @@ -82,18 +83,7 @@ public: } RtmpMediaSource::onGetMedia(pkt); } - void setOnSeek(const function &cb) override { - RtmpMediaSource::setOnSeek(cb); - if (m_pRtspSrc) { - m_pRtspSrc->setOnSeek(cb); - } - } - void setOnStamp(const function &cb) override{ - RtmpMediaSource::setOnStamp(cb); - if (m_pRtspSrc) { - m_pRtspSrc->setOnStamp(cb); - } - } + private: RtmpParser::Ptr m_pParser; RtspMediaSource::Ptr m_pRtspSrc; @@ -105,9 +95,6 @@ private: void onGetAdts(const AdtsFrame &frame); void makeSDP(); }; -#else - typedef RtmpMediaSource RtmpToRtspMediaSource; -#endif //ENABLE_RTMP2RTSP } /* namespace Rtmp */ } /* namespace ZL */ diff --git a/src/Rtsp/RtpBroadCaster.cpp b/src/Rtsp/RtpBroadCaster.cpp index 5f5d3b74..6f36f995 100644 --- a/src/Rtsp/RtpBroadCaster.cpp +++ b/src/Rtsp/RtpBroadCaster.cpp @@ -84,10 +84,10 @@ RtpBroadCaster::~RtpBroadCaster() { m_pReader->setDetachCB(nullptr); DebugL; } -RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strApp,const string &strStream) { - auto src = RtspMediaSource::find(strApp, strStream); +RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) { + auto src = dynamic_pointer_cast(MediaSource::find(RTSP_SCHEMA,strVhost,strApp, strStream)); if(!src){ - auto strErr = StrPrinter << "未找到媒体源:" << strApp << " " << strStream << endl; + auto strErr = StrPrinter << "未找到媒体源:" << strVhost << " " << strApp << " " << strStream << endl; throw std::runtime_error(strErr); } m_multiAddr = MultiCastAddressMaker::Instance().obtain(); @@ -130,6 +130,7 @@ RtpBroadCaster::RtpBroadCaster(const string &strLocalIp,const string &strApp,con DebugL << MultiCastAddressMaker::toString(*m_multiAddr) << " " << m_apUdpSock[0]->get_local_port() << " " << m_apUdpSock[1]->get_local_port() << " " + << strVhost << " " << strApp << " " << strStream; } uint16_t RtpBroadCaster::getPort(int iTrackId){ @@ -139,11 +140,11 @@ uint16_t RtpBroadCaster::getPort(int iTrackId){ string RtpBroadCaster::getIP(){ return inet_ntoa(m_aPeerUdpAddr[0].sin_addr); } -RtpBroadCaster::Ptr RtpBroadCaster::make(const string &strLocalIp,const string &strApp,const string &strStream){ +RtpBroadCaster::Ptr RtpBroadCaster::make(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream){ try{ - auto ret = Ptr(new RtpBroadCaster(strLocalIp,strApp,strStream)); + auto ret = Ptr(new RtpBroadCaster(strLocalIp,strVhost,strApp,strStream)); lock_guard lck(g_mtx); - string strKey = StrPrinter << strLocalIp << " " << strApp << " " << strStream << endl; + string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl; weak_ptr weakPtr = ret; g_mapBroadCaster.emplace(strKey,weakPtr); return ret; @@ -153,17 +154,17 @@ RtpBroadCaster::Ptr RtpBroadCaster::make(const string &strLocalIp,const string & } } -RtpBroadCaster::Ptr RtpBroadCaster::get(const string &strLocalIp,const string& strApp, const string& strStream) { - string strKey = StrPrinter << strLocalIp << " " << strApp << " " << strStream << endl; +RtpBroadCaster::Ptr RtpBroadCaster::get(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream) { + string strKey = StrPrinter << strLocalIp << " " << strVhost << " " << strApp << " " << strStream << endl; lock_guard lck(g_mtx); auto it = g_mapBroadCaster.find(strKey); if (it == g_mapBroadCaster.end()) { - return make(strLocalIp,strApp, strStream); + return make(strLocalIp,strVhost,strApp, strStream); } auto ret = it->second.lock(); if (!ret) { g_mapBroadCaster.erase(it); - return make(strLocalIp,strApp, strStream); + return make(strLocalIp,strVhost,strApp, strStream); } return ret; } diff --git a/src/Rtsp/RtpBroadCaster.h b/src/Rtsp/RtpBroadCaster.h index 55b359b6..135903bd 100644 --- a/src/Rtsp/RtpBroadCaster.h +++ b/src/Rtsp/RtpBroadCaster.h @@ -74,14 +74,14 @@ public: typedef std::shared_ptr Ptr; typedef function onDetach; virtual ~RtpBroadCaster(); - static Ptr get(const string &strLocalIp,const string &strApp,const string &strStream); + static Ptr get(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); void setDetachCB(void *listener,const onDetach &cb); uint16_t getPort(int iTrackId); string getIP(); private: static recursive_mutex g_mtx; static unordered_map > g_mapBroadCaster; - static Ptr make(const string &strLocalIp,const string &strApp,const string &strStream); + static Ptr make(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); std::shared_ptr m_multiAddr; recursive_mutex m_mtx; @@ -90,7 +90,7 @@ private: Socket::Ptr m_apUdpSock[2]; struct sockaddr_in m_aPeerUdpAddr[2]; - RtpBroadCaster(const string &strLocalIp,const string &strApp,const string &strStream); + RtpBroadCaster(const string &strLocalIp,const string &strVhost,const string &strApp,const string &strStream); }; diff --git a/src/Rtsp/Rtsp.h b/src/Rtsp/Rtsp.h index 9b033553..e50731ef 100644 --- a/src/Rtsp/Rtsp.h +++ b/src/Rtsp/Rtsp.h @@ -163,36 +163,18 @@ public: this->m_strContent = content; } - const StrCaseMap& getValues() const { + StrCaseMap& getValues() const { return m_mapValues; } - const StrCaseMap& getUrlArgs() const { + StrCaseMap& getUrlArgs() const { return m_mapUrlArgs; } - //注意:当字符串为空时,也会返回一个空字符串 - static vector split(const string& s, const char *delim) { - size_t last = 0; - size_t index = s.find_first_of(delim, last); - vector ret; - while (index != string::npos) { - ret.push_back(s.substr(last, index - last)); - last = index + 1; - index = s.find_first_of(delim, last); - } - if (index - last > 0) { - ret.push_back(s.substr(last, index - last)); - } - return ret; - } static StrCaseMap parseArgs(const string &str,const char *pair_delim = "&", const char *key_delim = "="){ StrCaseMap ret; auto arg_vec = split(str, pair_delim); for (string &key_val : arg_vec) { - if (!key_val.size()) { - continue; - } auto key_val_vec = split(key_val, key_delim); if (key_val_vec.size() >= 2) { ret[key_val_vec[0]] = key_val_vec[1]; @@ -207,8 +189,8 @@ private: string m_strTail; string m_strContent; string m_strNull; - StrCaseMap m_mapValues; - StrCaseMap m_mapUrlArgs; + mutable StrCaseMap m_mapValues; + mutable StrCaseMap m_mapUrlArgs; }; typedef struct { diff --git a/src/Rtsp/RtspMediaSource.cpp b/src/Rtsp/RtspMediaSource.cpp index ad57c83f..0e6f7d67 100644 --- a/src/Rtsp/RtspMediaSource.cpp +++ b/src/Rtsp/RtspMediaSource.cpp @@ -32,30 +32,5 @@ using namespace ZL::MediaFile; namespace ZL { namespace Rtsp { -recursive_mutex RtspMediaSource::g_mtxMediaSrc; -unordered_map > > RtspMediaSource::g_mapMediaSrc; - -RtspMediaSource::Ptr RtspMediaSource::find(const string &strApp, const string &strId,bool bMake) { - //查找某一媒体源,找到后返回 - lock_guard lock(g_mtxMediaSrc); - auto itApp = g_mapMediaSrc.find(strApp); - if (itApp == g_mapMediaSrc.end()) { - return bMake ? MediaReader::onMakeRtsp(strApp, strId) : nullptr; - } - auto itId = itApp->second.find(strId); - if (itId == itApp->second.end()) { - return bMake ? MediaReader::onMakeRtsp(strApp, strId) : nullptr; - } - auto ret = itId->second.lock(); - if(ret){ - return ret; - } - itApp->second.erase(itId); - if (itApp->second.size() == 0) { - g_mapMediaSrc.erase(itApp); - } - return bMake ? MediaReader::onMakeRtsp(strApp, strId) : nullptr; -} - } /* namespace Rtsp */ } /* namespace ZL */ diff --git a/src/Rtsp/RtspMediaSource.h b/src/Rtsp/RtspMediaSource.h index 0d7c02f3..ea1f4bb6 100644 --- a/src/Rtsp/RtspMediaSource.h +++ b/src/Rtsp/RtspMediaSource.h @@ -35,6 +35,8 @@ #include "Rtsp.h" #include "Common/config.h" #include "Common/MediaSender.h" +#include "Common/MediaSource.h" + #include "Util/logger.h" #include "Util/RingBuffer.h" #include "Util/TimeTicker.h" @@ -45,80 +47,33 @@ using namespace std; using namespace ZL::Util; using namespace ZL::Thread; +using namespace ZL::Media; namespace ZL { namespace Rtsp { - - -class RtspMediaSource: public enable_shared_from_this { +class RtspMediaSource: public MediaSource { public: typedef ResourcePool PoolType; typedef std::shared_ptr Ptr; typedef RingBuffer RingType; - RtspMediaSource(const string &strApp, const string &strId) : - m_strApp(strApp), - m_strId(strId), + + RtspMediaSource(const string &strVhost,const string &strApp, const string &strId) : + MediaSource(RTSP_SCHEMA,strVhost,strApp,strId), m_pRing(new RingBuffer()), m_thPool(MediaSender::sendThread()) { } - virtual ~RtspMediaSource() { - unregist(); - } + virtual ~RtspMediaSource() {} const RingType::Ptr &getRing() const { //获取媒体源的rtp环形缓冲 return m_pRing; } - const string& getSdp() const { //获取该源的媒体描述信息 return m_strSdp; } - virtual void regist() { - //注册该源,注册后rtsp服务器才能找到该源 - lock_guard lock(g_mtxMediaSrc); - if (!g_mapMediaSrc[m_strApp].erase(m_strId)) { - InfoL << "Rtsp src:" << m_strApp << " " << m_strId; - } - g_mapMediaSrc[m_strApp].emplace(m_strId, shared_from_this()); - NoticeCenter::Instance().emitEvent(Config::Broadcast::kBroadcastRtspSrcRegisted,m_strApp.data(),m_strId.data()); - } - virtual void unregist() { - //反注册该源 - lock_guard lock(g_mtxMediaSrc); - auto it = g_mapMediaSrc.find(m_strApp); - if (it == g_mapMediaSrc.end()) { - return; - } - if (it->second.erase(m_strId)) { - if(it->second.size() == 0){ - g_mapMediaSrc.erase(it); - } - InfoL << "Rtsp src:" << m_strApp << " " << m_strId; - } - } - static set getMediaSet() { - set ret; - lock_guard lock(g_mtxMediaSrc); - for (auto &pr0 : g_mapMediaSrc) { - for (auto &pr1 : pr0.second) { - if(pr1.second.lock()){ - ret.emplace(pr0.first + "/" + pr1.first); - } - } - } - return ret; - } - static Ptr find(const string &_app, const string &_id,bool bMake = true) ; - const string& getApp() const { - //获取该源的id - return m_strApp; - } - const string& getId() const { - return m_strId; - } virtual uint32_t getSsrc(int trackId) { return m_mapTracks[trackId].ssrc; } @@ -131,7 +86,7 @@ public: virtual void onGetSDP(const string& sdp) { //派生类设置该媒体源媒体描述信息 - this->m_strSdp = sdp; + m_strSdp = sdp; } virtual void onGetRTP(const RtpPacket::Ptr &rtppt, bool keyPos) { auto &trackRef = m_mapTracks[rtppt->interleaved / 2]; @@ -144,36 +99,11 @@ public: _outRing->write(rtppt,keyPos); }); } - bool seekTo(uint32_t ui32Stamp) { - if (!m_onSeek) { - return false; - } - return m_onSeek(ui32Stamp); - } - virtual void setOnSeek(const function &cb){ - m_onSeek = cb; - } - uint32_t getStamp() { - if (!m_onStamp) { - return 0; - } - return m_onStamp(); - } - virtual void setOnStamp(const function &cb) { - m_onStamp = cb; - } protected: - function m_onSeek; - function m_onStamp; unordered_map m_mapTracks; -private: - string m_strSdp; //媒体描述信息 - string m_strApp; //媒体app - string m_strId; //媒体id - RingType::Ptr m_pRing; //rtp环形缓冲 + string m_strSdp; //媒体描述信息 + RingType::Ptr m_pRing; //rtp环形缓冲 ThreadPool &m_thPool; - static unordered_map > > g_mapMediaSrc; //静态的媒体源表 - static recursive_mutex g_mtxMediaSrc; ///访问静态的媒体源表的互斥锁 }; } /* namespace Rtsp */ diff --git a/src/Rtsp/RtspPlayer.cpp b/src/Rtsp/RtspPlayer.cpp index 7d3e084f..3ff8d7fd 100644 --- a/src/Rtsp/RtspPlayer.cpp +++ b/src/Rtsp/RtspPlayer.cpp @@ -427,19 +427,6 @@ void RtspPlayer::pause(bool bPause) { sendPause(bPause,getProgressTime()); } -//注意:当字符串为空时,也会返回一个空字符串 -static void split(const string& s, const char *delim, vector &ret) { - size_t last = 0; - size_t index = s.find_first_of(delim, last); - while (index != string::npos) { - ret.push_back(s.substr(last, index - last)); - last = index + 1; - index = s.find_first_of(delim, last); - } - if (index - last > 0) { - ret.push_back(s.substr(last, index - last)); - } -} void RtspPlayer::HandleResPAUSE(const Parser& parser, bool bPause) { if (parser.Url() != "200") { WarnL <<(bPause ? "Pause" : "Play") << " failed:" << parser.Url() << " " << parser.Tail() << endl; @@ -461,18 +448,15 @@ void RtspPlayer::HandleResPAUSE(const Parser& parser, bool bPause) { auto strRtpInfo = parser["RTP-Info"]; if (strRtpInfo.size()) { strRtpInfo.append(","); - vector vec; - split(strRtpInfo, ",", vec); + vector vec = split(strRtpInfo, ","); for(auto &strTrack : vec){ - if (strTrack.size()) { - strTrack.append(";"); - auto strTrackId = FindField(strTrack.data(), m_aTrackInfo[0].trackStyle.data(), ";"); - auto strRtpTime = FindField(strTrack.data(), "rtptime=", ";"); - auto iIdx = getTrackIndex(atoi(strTrackId.data())); - m_adFistStamp[iIdx] = atoll(strRtpTime.data()); - m_adNowStamp[iIdx] = m_adFistStamp[iIdx]; - DebugL << "rtptime:" << strTrackId <<" " << strRtpTime; - } + strTrack.append(";"); + auto strTrackId = FindField(strTrack.data(), m_aTrackInfo[0].trackStyle.data(), ";"); + auto strRtpTime = FindField(strTrack.data(), "rtptime=", ";"); + auto iIdx = getTrackIndex(atoi(strTrackId.data())); + m_adFistStamp[iIdx] = atoll(strRtpTime.data()); + m_adNowStamp[iIdx] = m_adFistStamp[iIdx]; + DebugL << "rtptime:" << strTrackId <<" " << strRtpTime; } } _onPlayResult(SockException(Err_success, "rtsp play success")); diff --git a/src/Rtsp/RtspSession.cpp b/src/Rtsp/RtspSession.cpp index 528e8c6e..47993845 100644 --- a/src/Rtsp/RtspSession.cpp +++ b/src/Rtsp/RtspSession.cpp @@ -55,7 +55,6 @@ unordered_map > RtspSession::g_mapPostter; recursive_mutex RtspSession::g_mtxGetter; //对quicktime上锁保护 recursive_mutex RtspSession::g_mtxPostter; //对quicktime上锁保护 unordered_map RtspSession::g_mapCmd; -string RtspSession::g_serverName; RtspSession::RtspSession(const std::shared_ptr &pTh, const Socket::Ptr &pSock) : TcpLimitedSession(pTh, pSock), m_pSender(pSock) { static onceToken token( []() { @@ -69,7 +68,6 @@ RtspSession::RtspSession(const std::shared_ptr &pTh, const Socket::P g_mapCmd.emplace("POST",&RtspSession::handleReq_Post); g_mapCmd.emplace("SET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); g_mapCmd.emplace("GET_PARAMETER",&RtspSession::handleReq_SET_PARAMETER); - g_serverName = mINI::Instance()[Config::Rtsp::kServerName]; }, []() {}); #ifndef __x86_64__ @@ -184,7 +182,7 @@ bool RtspSession::handleReq_Options() { "%s" "Public: OPTIONS, DESCRIBE, SETUP, TEARDOWN, PLAY," " PAUSE, SET_PARAMETER, GET_PARAMETER\r\n\r\n", - m_iCseq, g_serverName.data(), + m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data()); send(m_pcBuf, n); @@ -192,7 +190,15 @@ bool RtspSession::handleReq_Options() { } bool RtspSession::handleReq_Describe() { - m_strUrl = m_parser.Url(); + { + //解析url获取媒体名称 + m_strUrl = m_parser.Url(); + m_mediaInfo.parse(m_strUrl); + if(!m_parser.getUrlArgs()[VHOST_KEY].empty()){ + m_mediaInfo.m_vhost = m_parser.getUrlArgs()[VHOST_KEY]; + } + } + if (!findStream()) { //未找到相应的MediaSource send_StreamNotFound(); @@ -213,7 +219,10 @@ bool RtspSession::handleReq_Describe() { }; //广播是否需要认证事件 - if(!NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastOnGetRtspRealm,m_strApp.data(),m_strStream.data(),invoker)){ + if(!NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastOnGetRtspRealm, + m_mediaInfo.m_app.data(), + m_mediaInfo.m_streamid.data(), + invoker)){ //无人监听此事件,说明无需认证 invoker(""); } @@ -242,7 +251,7 @@ void RtspSession::onAuthSuccess(const weak_ptr &weakSelf) { "Content-Base: %s/\r\n" "Content-Type: application/sdp\r\n" "Content-Length: %d\r\n\r\n%s", - strongSelf->m_iCseq, strongSelf->g_serverName.data(), + strongSelf->m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), strongSelf->m_strUrl.data(), (int) strongSelf->m_strSdp.length(), strongSelf->m_strSdp.data()); @@ -274,7 +283,7 @@ void RtspSession::onAuthFailed(const weak_ptr &weakSelf,const strin "Server: %s-%0.2f(build in %s)\r\n" "%s" "WWW-Authenticate:Digest realm=\"%s\",nonce=\"%s\"\r\n\r\n", - strongSelf->m_iCseq, strongSelf->g_serverName.data(), + strongSelf->m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), realm.data(), strongSelf->m_strNonce.data()); }else { @@ -285,7 +294,7 @@ void RtspSession::onAuthFailed(const weak_ptr &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, strongSelf->g_serverName.data(), + strongSelf->m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), realm.data()); } @@ -297,7 +306,7 @@ void RtspSession::onAuthBasic(const weak_ptr &weakSelf,const string //base64认证 char user_pwd_buf[512]; av_base64_decode((uint8_t *)user_pwd_buf,strBase64.data(),strBase64.size()); - auto user_pwd_vec = Parser::split(user_pwd_buf,":"); + auto user_pwd_vec = split(user_pwd_buf,":"); if(user_pwd_vec.size() < 2){ //认证信息格式不合法,回复401 Unauthorized onAuthFailed(weakSelf,realm); @@ -324,23 +333,7 @@ void RtspSession::onAuthBasic(const weak_ptr &weakSelf,const string invoker(false,pwd); } } -static string trim(string str){ - while(!str.empty()){ - if(str.front()==' ' || str.front()=='"'){ - str.erase(0,1); - continue; - } - break; - } - while(!str.empty()){ - if(str.back()==' ' || str.back()=='"'){ - str.pop_back(); - continue; - } - break; - } - return str; -} + void RtspSession::onAuthDigest(const weak_ptr &weakSelf,const string &realm,const string &strMd5){ auto strongSelf = weakSelf.lock(); if(!strongSelf){ @@ -351,7 +344,7 @@ void RtspSession::onAuthDigest(const weak_ptr &weakSelf,const strin auto mapTmp = Parser::parseArgs(strMd5,",","="); decltype(mapTmp) map; for(auto &pr : mapTmp){ - map[trim(pr.first)] = trim(pr.second); + map[trim(string(pr.first)," \"")] = trim(pr.second," \""); } //check realm if(realm != map["realm"]){ @@ -448,7 +441,7 @@ inline void RtspSession::send_StreamNotFound() { "Server: %s-%0.2f(build in %s)\r\n" "%s" "Connection: Close\r\n\r\n", - m_iCseq, g_serverName.data(), + m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data()); send(m_pcBuf, n); @@ -459,7 +452,7 @@ inline void RtspSession::send_UnsupportedTransport() { "Server: %s-%0.2f(build in %s)\r\n" "%s" "Connection: Close\r\n\r\n", - m_iCseq, g_serverName.data(), + m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data()); send(m_pcBuf, n); @@ -471,7 +464,7 @@ inline void RtspSession::send_SessionNotFound() { "Server: %s-%0.2f(build in %s)\r\n" "%s" "Connection: Close\r\n\r\n", - m_iCseq, g_serverName.data(), + m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data()); send(m_pcBuf, n); @@ -539,7 +532,7 @@ 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, g_serverName.data(), + m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), trackid * 2, trackid * 2 + 1, @@ -584,7 +577,7 @@ bool RtspSession::handleReq_Setup() { "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, g_serverName.data(), + m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), strClientPort.data(), pSockRtp->get_local_port(), pSockRtcp->get_local_port(), @@ -595,7 +588,7 @@ bool RtspSession::handleReq_Setup() { break; case PlayerBase::RTP_MULTICAST: { if(!m_pBrdcaster){ - m_pBrdcaster = RtpBroadCaster::get(getLocalIp(), m_strApp, m_strStream); + m_pBrdcaster = RtpBroadCaster::get(getLocalIp(),m_mediaInfo.m_vhost, m_mediaInfo.m_app, m_mediaInfo.m_streamid); if (!m_pBrdcaster) { send_NotAcceptable(); return false; @@ -627,7 +620,7 @@ bool RtspSession::handleReq_Setup() { "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, g_serverName.data(), + m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), m_pBrdcaster->getIP().data(), getLocalIp().data(), iSrvPort, pSockRtcp->get_local_port(), @@ -705,7 +698,7 @@ bool RtspSession::handleReq_Play() { "%s" "Session: %s\r\n" "Range: npt=%.2f-\r\n" - "RTP-Info: ", m_iCseq, g_serverName.data(), RTSP_VERSION, RTSP_BUILDTIME, + "RTP-Info: ", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), m_strSession.data(),iStamp/1000.0); for (unsigned int i = 0; i < m_uiTrackCnt; i++) { @@ -722,7 +715,11 @@ bool RtspSession::handleReq_Play() { (m_pcBuf)[iLen] = '\0'; iLen += sprintf(m_pcBuf + iLen, "\r\n\r\n"); send(m_pcBuf, iLen); - NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastRtspSessionPlay, m_strApp.data(),m_strStream.data()); + NoticeCenter::Instance().emitEvent(Broadcast::kBroadcastMediaPlayed, + RTSP_SCHEMA, + m_mediaInfo.m_vhost.data(), + m_mediaInfo.m_app.data(), + m_mediaInfo.m_streamid.data()); return true; } @@ -735,7 +732,7 @@ bool RtspSession::handleReq_Pause() { "CSeq: %d\r\n" "Server: %s-%0.2f(build in %s)\r\n" "%s" - "Session: %s\r\n\r\n", m_iCseq, g_serverName.data(), RTSP_VERSION, RTSP_BUILDTIME, + "Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), m_strSession.data()); send(m_pcBuf, n); if(m_pRtpReader){ @@ -750,7 +747,7 @@ bool RtspSession::handleReq_Teardown() { "CSeq: %d\r\n" "Server: %s-%0.2f(build in %s)\r\n" "%s" - "Session: %s\r\n\r\n", m_iCseq, g_serverName.data(), RTSP_VERSION, RTSP_BUILDTIME, + "Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), m_strSession.data()); send(m_pcBuf, n); @@ -801,7 +798,7 @@ bool RtspSession::handleReq_SET_PARAMETER() { "CSeq: %d\r\n" "Server: %s-%0.2f(build in %s)\r\n" "%s" - "Session: %s\r\n\r\n", m_iCseq, g_serverName.data(), RTSP_VERSION, RTSP_BUILDTIME, + "Session: %s\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data(), m_strSession.data()); send(m_pcBuf, n); return true; @@ -812,21 +809,17 @@ inline void RtspSession::send_NotAcceptable() { "CSeq: %d\r\n" "Server: %s-%0.2f(build in %s)\r\n" "%s" - "Connection: Close\r\n\r\n", m_iCseq, g_serverName.data(), RTSP_VERSION, RTSP_BUILDTIME, + "Connection: Close\r\n\r\n", m_iCseq, SERVER_NAME, RTSP_VERSION, RTSP_BUILDTIME, dateHeader().data()); send(m_pcBuf, n); } -void RtspSession::splitRtspUrl(const string &url,string &app,string &stream){ - string strHost = FindField(url.data(), "://", "/"); - app = FindField(url.data(), (strHost + "/").data(), "/"); - stream = FindField(url.data(), (strHost + "/" + app + "/").data(), NULL); -} + inline bool RtspSession::findStream() { - splitRtspUrl(m_strUrl,m_strApp,m_strStream); - RtspMediaSource::Ptr pMediaSrc = RtspMediaSource::find(m_strApp,m_strStream); + RtspMediaSource::Ptr pMediaSrc = + dynamic_pointer_cast( MediaSource::find(RTSP_SCHEMA,m_mediaInfo.m_vhost, m_mediaInfo.m_app,m_mediaInfo.m_streamid) ); if (!pMediaSrc) { - WarnL << "No such stream:" << m_strApp << " " << m_strStream; + WarnL << "No such stream:" << m_mediaInfo.m_vhost << " " << m_mediaInfo.m_app << " " << m_mediaInfo.m_streamid; return false; } m_strSdp = pMediaSrc->getSdp(); diff --git a/src/Rtsp/RtspSession.h b/src/Rtsp/RtspSession.h index c04da5c7..88722f78 100644 --- a/src/Rtsp/RtspSession.h +++ b/src/Rtsp/RtspSession.h @@ -109,7 +109,6 @@ private: void inline send_UnsupportedTransport(); //不支持的传输模式 void inline send_SessionNotFound(); //会话id错误 void inline send_NotAcceptable(); //rtsp同时播放数限制 - void splitRtspUrl(const string &url,string &app,string &stream); inline bool findStream(); //根据rtsp url查找 MediaSource实例 inline void initSender(const std::shared_ptr &pSession); //处理rtsp over http,quicktime使用的 @@ -148,8 +147,7 @@ private: string m_strSdp; string m_strSession; bool m_bFirstPlay = true; - string m_strApp; - string m_strStream; + MediaInfo m_mediaInfo; std::weak_ptr m_pMediaSrc; static unordered_map g_mapCmd; @@ -191,7 +189,6 @@ private: static recursive_mutex g_mtxPostter; //对quicktime上锁保护 static unordered_map > g_mapGetter; static unordered_map > g_mapPostter; - static string g_serverName; }; diff --git a/src/Rtsp/RtspToRtmpMediaSource.cpp b/src/Rtsp/RtspToRtmpMediaSource.cpp index c3e9e6f3..e111e9c1 100644 --- a/src/Rtsp/RtspToRtmpMediaSource.cpp +++ b/src/Rtsp/RtspToRtmpMediaSource.cpp @@ -37,28 +37,27 @@ using namespace ZL::Network; namespace ZL { namespace Rtsp { -#ifdef ENABLE_RTSP2RTMP -RtspToRtmpMediaSource::RtspToRtmpMediaSource(const string &_app,const string &_id,bool bEnableFile) : - RtspMediaSource(_app,_id),m_bEnableFile(bEnableFile) { +RtspToRtmpMediaSource::RtspToRtmpMediaSource(const string &vhost,const string &app,const string &id,bool bEnableFile) : + RtspMediaSource(vhost,app,id),m_bEnableFile(bEnableFile) { } RtspToRtmpMediaSource::~RtspToRtmpMediaSource() { } -void RtspToRtmpMediaSource::regist() { - RtspMediaSource::regist(); +bool RtspToRtmpMediaSource::regist() { if (m_pRtmpSrc) { m_pRtmpSrc->regist(); } + return MediaSource::regist(); } -void RtspToRtmpMediaSource::unregist() { - RtspMediaSource::unregist(); +bool RtspToRtmpMediaSource::unregist() { if (m_pRtmpSrc) { m_pRtmpSrc->unregist(); } + return MediaSource::unregist(); } void RtspToRtmpMediaSource::makeVideoConfigPkt() { @@ -196,9 +195,8 @@ void RtspToRtmpMediaSource::makeAudioConfigPkt() { } void RtspToRtmpMediaSource::makeMetaData() { - m_pRtmpSrc.reset(new RtmpMediaSource(getApp(),getId())); - m_pRtmpSrc->setOnSeek(m_onSeek); - m_pRtmpSrc->setOnStamp(m_onStamp); + m_pRtmpSrc.reset(new RtmpMediaSource(getVhost(),getApp(),getId())); + m_pRtmpSrc->setListener(m_listener); AMFValue metaData(AMF_OBJECT); metaData.set("duration", m_pParser->getDuration()); metaData.set("fileSize", 0); @@ -222,6 +220,5 @@ void RtspToRtmpMediaSource::makeMetaData() { m_pRtmpSrc->onGetMetaData(metaData); } -#endif //ENABLE_RTSP2RTMP } /* namespace Rtsp */ } /* namespace ZL */ diff --git a/src/Rtsp/RtspToRtmpMediaSource.h b/src/Rtsp/RtspToRtmpMediaSource.h index fe74cea5..185fe78a 100644 --- a/src/Rtsp/RtspToRtmpMediaSource.h +++ b/src/Rtsp/RtspToRtmpMediaSource.h @@ -38,18 +38,17 @@ using namespace ZL::MediaFile; namespace ZL { namespace Rtsp { -#ifdef ENABLE_RTSP2RTMP class RtspToRtmpMediaSource: public RtspMediaSource { public: typedef std::shared_ptr Ptr; - RtspToRtmpMediaSource(const string &_app,const string &_id,bool bEnableFile = true); + RtspToRtmpMediaSource(const string &vhost,const string &app,const string &id,bool bEnableFile = true); virtual ~RtspToRtmpMediaSource(); virtual void onGetSDP(const string& strSdp) override{ try { m_pParser.reset(new RtpParser(strSdp)); if(m_bEnableFile){ - m_pRecorder.reset(new MediaRecorder(getApp(),getId(),m_pParser)); + m_pRecorder.reset(new MediaRecorder(getVhost(),getApp(),getId(),m_pParser)); } m_pParser->setOnAudioCB( std::bind(&RtspToRtmpMediaSource::onGetAdts, this, placeholders::_1)); m_pParser->setOnVideoCB( std::bind(&RtspToRtmpMediaSource::onGetH264, this, placeholders::_1)); @@ -65,23 +64,13 @@ public: } RtspMediaSource::onGetRTP(pRtppkt, bKeyPos); } - virtual void regist() override ; - virtual void unregist() override; + virtual bool regist() override ; + virtual bool unregist() override; + int readerCount(){ return getRing()->readerCount() + (m_pRtmpSrc ? m_pRtmpSrc->getRing()->readerCount() : 0); } - void setOnSeek(const function &cb) override{ - RtspMediaSource::setOnSeek(cb); - if(m_pRtmpSrc){ - m_pRtmpSrc->setOnSeek(cb); - } - } - void setOnStamp(const function &cb) override{ - RtspMediaSource::setOnStamp(cb); - if (m_pRtmpSrc) { - m_pRtmpSrc->setOnStamp(cb); - } - } + void updateTimeStamp(uint32_t uiStamp) { for (auto &pr : m_mapTracks) { switch (pr.second.type) { @@ -111,9 +100,6 @@ private: void makeMetaData(); }; -#else -typedef RtspMediaSource RtspToRtmpMediaSource; -#endif //ENABLE_RTSP2RTMP } /* namespace Rtsp */ } /* namespace ZL */ diff --git a/src/Shell/ShellCMD.cpp b/src/Shell/ShellCMD.cpp index 1b8b78a3..aae1a4bc 100644 --- a/src/Shell/ShellCMD.cpp +++ b/src/Shell/ShellCMD.cpp @@ -19,10 +19,10 @@ public: _parser.reset(new OptionParser(nullptr)); (*_parser) << Option('l', "list", Option::ArgNone, nullptr,false, "list all media source of rtsp", [](const std::shared_ptr &stream, const string &arg) { - auto mediaSet = RtspMediaSource::getMediaSet(); - for (auto &src : mediaSet) { - (*stream) << "\t" << src << "\r\n"; - } +// auto mediaSet = RtspMediaSource::getMediaSet(); +// for (auto &src : mediaSet) { +// (*stream) << "\t" << src << "\r\n"; +// } return false; }); } @@ -37,10 +37,10 @@ public: _parser.reset(new OptionParser(nullptr)); (*_parser) << Option('l', "list", Option::ArgNone,nullptr,false, "list all media source of rtmp", [](const std::shared_ptr &stream, const string &arg) { - auto mediaSet = RtmpMediaSource::getMediaSet(); - for (auto &src : mediaSet) { - (*stream) << "\t" << src << "\r\n"; - } +// auto mediaSet = RtmpMediaSource::getMediaSet(); +// for (auto &src : mediaSet) { +// (*stream) << "\t" << src << "\r\n"; +// } return false; }); } diff --git a/src/Shell/ShellSession.cpp b/src/Shell/ShellSession.cpp index 8c2ce229..a3fe4cd4 100644 --- a/src/Shell/ShellSession.cpp +++ b/src/Shell/ShellSession.cpp @@ -35,15 +35,10 @@ namespace ZL { namespace Shell { unordered_map ShellSession::g_mapUser; -string ShellSession::g_serverName; ShellSession::ShellSession(const std::shared_ptr &_th, const Socket::Ptr &_sock) : TcpLimitedSession(_th, _sock) { - - static onceToken token([]() { - g_serverName = mINI::Instance()[Config::Shell::kServerName]; - }, nullptr); pleaseInputUser(); } @@ -107,7 +102,7 @@ inline bool ShellSession::onCommandLine(const string& line) { inline void ShellSession::pleaseInputUser() { send("\033[0m"); - send(StrPrinter << g_serverName << " login: " << endl); + send(StrPrinter << SERVER_NAME << " login: " << endl); m_requestCB = [this](const string &line) { m_strUserName=line; pleaseInputPasswd(); @@ -121,14 +116,14 @@ inline void ShellSession::pleaseInputPasswd() { send(StrPrinter <<"\033[0mPermission denied," <<" please try again.\r\n" - < g_mapUser; - static string g_serverName; }; } /* namespace Shell */ diff --git a/tests/test_rtmpPusher.cpp b/tests/test_rtmpPusher.cpp index d0ed0ce5..496dad18 100644 --- a/tests/test_rtmpPusher.cpp +++ b/tests/test_rtmpPusher.cpp @@ -48,7 +48,7 @@ void rePushDelay(const string &app,const string &stream,const string &url); //创建推流器并开始推流 void createPusher(const string &app,const string &stream,const string &url){ //创建推流器并绑定一个RtmpMediaSource - pusher.reset(new RtmpPusher(app.data(), stream.data())); + pusher.reset(new RtmpPusher(DEFAULT_VHOST,app.data(), stream.data())); //设置推流中断处理逻辑 pusher->setOnShutdown([app,stream, url](const SockException &ex) { WarnL << "Server connection is closed:" << ex.getErrCode() << " " << ex.what(); @@ -95,11 +95,11 @@ int domain(int argc, const char *argv[]) { //拉一个流,生成一个RtmpMediaSource,源的名称是"app/stream" //你也可以以其他方式生成RtmpMediaSource,比如说MP4文件(请查看test_rtmpPusherMp4.cpp代码) - PlayerProxy::Ptr player(new PlayerProxy("app", "stream")); + PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST,"app", "stream")); player->play(playUrl.data()); //监听RtmpMediaSource注册事件,在PlayerProxy播放成功后触发 - NoticeCenter::Instance().addListener(nullptr, Config::Broadcast::kBroadcastRtmpSrcRegisted, [pushUrl](BroadcastRtmpSrcRegistedArgs) { + NoticeCenter::Instance().addListener(nullptr, Config::Broadcast::kBroadcastMediaChanged, [pushUrl](BroadcastMediaChangedArgs) { //媒体源"app/stream"已经注册,这时方可新建一个RtmpPusher对象并绑定该媒体源 createPusher(app,stream,pushUrl); }); diff --git a/tests/test_rtmpPusherMp4.cpp b/tests/test_rtmpPusherMp4.cpp index e0c0254a..13ce429b 100644 --- a/tests/test_rtmpPusherMp4.cpp +++ b/tests/test_rtmpPusherMp4.cpp @@ -51,7 +51,7 @@ void createPusher(const string &app,const string &stream,const string &url); //创建推流器并开始推流 void createPusher(const string &app,const string &stream,const string &url){ - auto rtmpSrc = MediaReader::onMakeRtmp(app,stream); + auto rtmpSrc = dynamic_pointer_cast(MediaReader::onMakeMediaSource(RTMP_SCHEMA,DEFAULT_VHOST,app,stream)); if(!rtmpSrc){ //文件不存在 WarnL << "MP4 file not exited!"; diff --git a/tests/test_server.cpp b/tests/test_server.cpp index e74e2411..6cc1bbf9 100644 --- a/tests/test_server.cpp +++ b/tests/test_server.cpp @@ -135,7 +135,7 @@ int main(int argc,char *argv[]){ //http://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //rtsp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 //rtmp://127.0.0.1/record/live/0/2017-04-11/11-09-38.mp4 - PlayerProxy::Ptr player(new PlayerProxy("live",to_string(i).data())); + PlayerProxy::Ptr player(new PlayerProxy(DEFAULT_VHOST,"live",to_string(i).data())); //指定RTP over TCP(播放rtsp时有效) (*player)[RtspPlayer::kRtpType] = PlayerBase::RTP_TCP; //开始播放,如果播放失败或者播放中止,将会自动重试若干次,重试次数在配置文件中配置,默认一直重试