diff --git a/ABLMediaServer/ABLMediaServer.cpp b/ABLMediaServer/ABLMediaServer.cpp index 03a4791..051a18f 100644 --- a/ABLMediaServer/ABLMediaServer.cpp +++ b/ABLMediaServer/ABLMediaServer.cpp @@ -419,6 +419,16 @@ CNetRevcBase_ptr GetNetRevcBaseClientNoLock(NETHANDLE CltHandle) CMediaStreamSource_ptr CreateMediaStreamSource(char* szURL, uint64_t nClient, MediaSourceType nSourceType, uint32_t nDuration, H265ConvertH264Struct h265ConvertH264Struct) { + //获取提供源 + CNetRevcBase_ptr pSourceClient = GetNetRevcBaseClient(nClient); + if (pSourceClient == NULL) + { + WriteLog(Log_Debug, "媒体源提供者不存在 nClient = %llu ", nClient); + return NULL; + } + strcpy(pSourceClient->m_szShareMediaURL, szURL); + pSourceClient->SplitterAppStream(pSourceClient->m_szShareMediaURL); + std::lock_guard lock(ABL_CMediaStreamSourceMapLock); @@ -567,70 +577,67 @@ bool DeleteClientMediaStreamSource(uint64_t nClient) //删除媒体源 int CloseMediaStreamSource(closeStreamsStruct closeStruct) { - std::lock_guard lock(ABL_CMediaStreamSourceMapLock); - CMediaStreamSource_ptrMap::iterator iterator1; - CMediaStreamSource_ptr pClient = NULL; + std::lock_guard lock(ABL_CNetRevcBase_ptrMapLock); int nDeleteCount = 0; - for (iterator1 = xh_ABLMediaStreamSourceMap.begin(); iterator1 != xh_ABLMediaStreamSourceMap.end(); ++iterator1) + CNetRevcBase_ptrMap::iterator iterator1; + CNetRevcBase_ptr pClient = NULL; + + for (iterator1 = xh_ABLNetRevcBaseMap.begin(); iterator1 != xh_ABLNetRevcBaseMap.end(); iterator1++) { pClient = (*iterator1).second; - - if (closeStruct.force == 1 && strlen(closeStruct.app) > 0 && strlen(closeStruct.stream) > 0) - {//强制关闭 - if (strcmp(pClient->app, closeStruct.app) == 0 && strcmp(pClient->stream, closeStruct.stream) == 0) - { - nDeleteCount++; - pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); - } - } - else if (closeStruct.force == 1 && strlen(closeStruct.app) > 0 && strlen(closeStruct.stream) == 0) - {//强制关闭 - if (strcmp(pClient->app, closeStruct.app) == 0) - { - nDeleteCount++; - pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); - } - } - else if (closeStruct.force == 1 && strlen(closeStruct.app) == 0 && strlen(closeStruct.stream) > 0) - {//强制关闭 - if (strcmp(pClient->stream, closeStruct.stream) == 0) - { - nDeleteCount++; - pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); + if (pClient->netBaseNetType == NetBaseNetType_RtspServerRecvPushVideo || + pClient->netBaseNetType == NetBaseNetType_RtspServerRecvPushAudio || + pClient->netBaseNetType == NetBaseNetType_GB28181TcpPSInputStream || + pClient->netBaseNetType == NetBaseNetType_WebSocektRecvAudio || + pClient->netBaseNetType == NetBaseNetType_RtmpServerRecvPush || + pClient->netBaseNetType == NetBaseNetType_RtspServerRecvPush || + pClient->netBaseNetType == NetBaseNetType_addStreamProxyControl || + pClient->netBaseNetType == NetBaseNetType_NetGB28181RtpServerUDP || + pClient->netBaseNetType == NetBaseNetType_NetGB28181RtpServerListen || + pClient->netBaseNetType == NetBaseNetType_NetGB28181RtpServerTCP_Active || + pClient->netBaseNetType == NetBaseNetType_NetGB28181RtpServerTCP_Server || + pClient->netBaseNetType == NetBaseNetType_NetGB28181RtpServerTCP_Client || + pClient->netBaseNetType == NetBaseNetType_NetGB28181RecvRtpPS_TS || + pClient->netBaseNetType == NetBaseNetType_NetGB28181UDPPSStreamInput || + pClient->netBaseNetType == NetBaseNetType_NetGB28181UDPTSStreamInput || + pClient->netBaseNetType == NetBaseNetType_NetServerReadMultRecordFile || + pClient->netBaseNetType == ReadRecordFileInput_ReadTSFile + ) + { + if (strlen(closeStruct.app) > 0 && strlen(closeStruct.stream) > 0) + {//强制关闭 + if (strcmp(pClient->app, closeStruct.app) == 0 && strcmp(pClient->stream, closeStruct.stream) == 0) + { + nDeleteCount++; + pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); + } } - } - else if (closeStruct.force == 1 && strlen(closeStruct.app) == 0 && strlen(closeStruct.stream) == 0) - {//强制关闭 - nDeleteCount++; - pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); - } - else if (closeStruct.force == 0 && strlen(closeStruct.app) > 0 && strlen(closeStruct.stream) > 0) - {//不强制关闭 - if (pClient->mediaSendMap.size() == 0 && strcmp(pClient->app, closeStruct.app) == 0 && strcmp(pClient->stream, closeStruct.stream) == 0) - { - nDeleteCount++; - pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); + else if (strlen(closeStruct.app) > 0 && strlen(closeStruct.stream) == 0) + {//强制关闭 + if (strcmp(pClient->app, closeStruct.app) == 0) + { + nDeleteCount++; + pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); + } } - } - else if (closeStruct.force == 0 && strlen(closeStruct.app) > 0 && strlen(closeStruct.stream) == 0) - {//不强制关闭 - if (pClient->mediaSendMap.size() == 0 && strcmp(pClient->app, closeStruct.app) == 0) - { - nDeleteCount++; - pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); + else if (strlen(closeStruct.app) == 0 && strlen(closeStruct.stream) > 0) + {//强制关闭 + if (strcmp(pClient->stream, closeStruct.stream) == 0) + { + nDeleteCount++; + pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); + } } - } - else if (closeStruct.force == 0 && strlen(closeStruct.app) == 0 && strlen(closeStruct.stream) > 0) - {//不强制关闭 - if (pClient->mediaSendMap.size() == 0 && strcmp(pClient->stream, closeStruct.stream) == 0) - { + else if (strlen(closeStruct.app) == 0 && strlen(closeStruct.stream) == 0 && !(pClient->netBaseNetType == NetBaseNetType_GB28181TcpPSInputStream || pClient->netBaseNetType == NetBaseNetType_NetGB28181RecvRtpPS_TS)) + {//强制关闭 nDeleteCount++; pDisconnectBaseNetFifo.push((unsigned char*)&pClient->nClient, sizeof(pClient->nClient)); } } } - return nDeleteCount; + + return nDeleteCount; } //先把基类的视频接入对象ID全部装入FIFO,这样减少一个lock,杜绝外部混乱调用http api 函数造成死锁 @@ -1184,7 +1191,7 @@ int queryRecordListByTime(char* szMediaSourceInfo, queryRecordListStruct querySt bFlag2 = false; if (nFileOrder == 0) { - if (nTime1 <= nTime2 && (nTime1 + ABL_MediaServerPort.fileSecond) > nTime2) + if ((nTime1 <= nTime2 && (nTime1 + ABL_MediaServerPort.fileSecond) > nTime2) || nTime2 < nTime1) bFlag1 = true;//第一个符合条件的文件 } if (nFileOrder >= 1 && *it2 <= atoll(queryStruct.endtime)) @@ -1268,6 +1275,13 @@ int queryRecordListByTime(char* szMediaSourceInfo, queryRecordListStruct querySt fclose(fp); } } + + //后面的mp4文件不再符合条件 ,需要中断查询 + if (*it2 > atoll(queryStruct.endtime)) + { + WriteLog(Log_Debug, "queryRecordListByTime() 后面的mp4文件不再符合条件 ,需要中断查询 *it2 = %llu , endtime = %s ", *it2, queryStruct.endtime); + break; + } } } else @@ -1598,7 +1612,7 @@ CNetRevcBase_ptr CreateNetRevcBaseClient(int netClientType, NETHANDLE serverHand pXHClient->netBaseNetType = NetBaseNetType_NetGB28181SendRtpTCP_Passive;//国标28181 tcp 被动方式发送码流 gb28181Listen->nMediaClient = CltHandle; //已经有人连接进来,只允许一个连接进来 memcpy((char*)&pXHClient->m_startSendRtpStruct, (char*)&gb28181Listen->m_startSendRtpStruct, sizeof(pXHClient->m_startSendRtpStruct)); //把listen对象的 m_startSendRtpStruct 拷贝给CNetGB28181RtpClient对象的 m_startSendRtpStruct - pXHClient->SendFirstRequst(); + } } else @@ -2027,7 +2041,7 @@ CNetRevcBase_ptr CreateNetRevcBaseClient(int netClientType, NETHANDLE serverHand pXHClient->netBaseNetType = NetBaseNetType_NetGB28181SendRtpTCP_Passive;//国标28181 tcp 被动方式发送码流 gb28181Listen->nMediaClient = CltHandle; //已经有人连接进来,只允许一个连接进来 memcpy((char*)&pXHClient->m_startSendRtpStruct, (char*)&gb28181Listen->m_startSendRtpStruct, sizeof(pXHClient->m_startSendRtpStruct)); //把listen对象的 m_startSendRtpStruct 拷贝给CNetGB28181RtpClient对象的 m_startSendRtpStruct - pXHClient->SendFirstRequst(); + } } else @@ -2934,6 +2948,7 @@ void LIBNET_CALLMETHOD onaccept(NETHANDLE srvhandle, unsigned short nPort = 5567; uint64_t hParent; int nAcceptNumvber; + CNetRevcBase_ptr pNetRevcBase_ptr = NULL; if (address) { @@ -2942,10 +2957,18 @@ void LIBNET_CALLMETHOD onaccept(NETHANDLE srvhandle, nPort = ::ntohs(addr->sin_port); } - if (CreateNetRevcBaseClient(NetRevcBaseClient_ServerAccept, srvhandle, clihandle, temp, nPort, "") == NULL) + if ((pNetRevcBase_ptr = CreateNetRevcBaseClient(NetRevcBaseClient_ServerAccept, srvhandle, clihandle, temp, nPort, "")) == NULL) XHNetSDK_Disconnect(clihandle); + + if (pNetRevcBase_ptr != NULL) + { + if (pNetRevcBase_ptr->netBaseNetType == NetBaseNetType_NetGB28181SendRtpTCP_Passive) + {//国标28181 tcp 被动方式发送码流 + pNetRevcBase_ptr->SendFirstRequst(); + } + } } -# + void LIBNET_CALLMETHOD onread(NETHANDLE srvhandle, NETHANDLE clihandle, uint8_t* data, @@ -2956,11 +2979,12 @@ void LIBNET_CALLMETHOD onread(NETHANDLE srvhandle, if (pBasePtr != NULL) { pBasePtr->InputNetData(srvhandle, clihandle, data, datasize, address); - NetBaseThreadPool->InsertIntoTask(clihandle);//验证使用、arm平台有点问题 - //pBasePtr->ProcessNetData(); + NetBaseThreadPool->InsertIntoTask(clihandle);//Window、Linux 平台使用 + //pBasePtr->ProcessNetData();//arm平台 使用 } } + void LIBNET_CALLMETHOD onclose(NETHANDLE srvhandle, NETHANDLE clihandle) { @@ -3236,7 +3260,7 @@ void* ABLMedisServerFastDeleteThread(void* lpVoid) pDisconnectBaseNetFifo.pop_front(); } - SendToMapFromMutePacketList(); + std::this_thread::sleep_for(std::chrono::milliseconds(64)); //Sleep(64); } @@ -3683,7 +3707,7 @@ void WebRtcCallBack(const char* callbackJson, void* pUserHandle) if (callbackStruct.eventID == 2) {//创建webrtc播放 - CMediaStreamSource_ptr pMediaSource = GetMediaStreamSource(callbackStruct.stream, false); + CMediaStreamSource_ptr pMediaSource = GetMediaStreamSource(callbackStruct.stream, true); if (pMediaSource == NULL) WriteLog(Log_Debug, "不存在流 %s ", callbackStruct.stream); else diff --git a/ABLMediaServer/ABLMediaServer.ini b/ABLMediaServer/ABLMediaServer.ini index 1ae5ad8..110bc69 100644 --- a/ABLMediaServer/ABLMediaServer.ini +++ b/ABLMediaServer/ABLMediaServer.ini @@ -1,293 +1,259 @@ [ABLMediaServer] -webrtcPort = 8002 -#流媒体服务器ID,用于集群识别流媒体服务器 -mediaServerID = ABLMediaServer_00001 +#娴佸獟浣撴湇鍔″櫒ID锛岀敤浜庨泦缇よ瘑鍒祦濯掍綋鏈嶅姟鍣 +mediaServerID=ABLMediaServer_00001 + +#涓浜涙瘮杈冩晱鎰熺殑http api鍦ㄨ闂椂闇瑕佹彁渚泂ecret锛屽惁鍒欐棤鏉冮檺璋冪敤 +secret=035c73f7-bb6b-4889-a715-d9eb2d1925cc + +#鏈満鐨処P鍦板潃锛屾渶濂介渶瑕侀厤缃噯纭紙濡傛灉涓嶉厤缃▼搴忎細鑷姩鑾峰彇涓涓湴鍧浠f浛锛屽鏋滄湰鏈烘湁澶氫釜鍦板潃鍙兘浼氫笉鍑嗙‘锛屽鏋滈厤缃垯浣跨敤閰嶇疆鐨処P鍦板潃锛夛紝鍥犱负璋冪敤getMediaList 鑾峰彇鍙敤鐨勫獟浣撴簮鐨刯son涓紝浼氫娇鐢ㄥ埌鏈満鐨処P鍦板潃鏉ユ嫾鎺tsp銆乺tmp銆乭ttp-flv銆亀s-flv銆乭ls銆乭ttp-mp4 鐨勬挱鏀緐rl +localipAddress= + +#鎵鏈夋帴鍏ユ祦锛屽綋澶氶暱鏃堕棿鎸佺画鏃犱汉瑙傜湅鏃朵細鑷姩鏂紑鐮佹祦鎺ュ叆锛屽寘鎷帹娴佹帴鍏ワ紝鎷夋祦鎺ュ叆锛屽浗鏍囨帴鍏ワ紝鏃堕棿鍗曚綅 鍒嗛挓銆傛敮鎸佹敮鎸佸~鍏ュ皬鏁帮紝姣斿 0.5 鍒嗛挓灏辨槸 30绉 锛0.25 鍒嗛挓灏辨槸15绉 锛0.20 鍒嗛挓 灏辨槸12绉 锛屾渶濂戒笉瑕佸皬浜 0.2 鍒嗛挓 +#銆愭敞鎰:褰撹璺帴鍏ユ祦鍚姩浜嗗綍鍍忥紝涓嶇鏄惁鏈変汉瑙傜湅閮戒笉浼氬叧闂 锛岄櫎闈炲叧闂綍鍍忓姛鑳 銆 +maxTimeNoOneWatch=9999999 + +#褰曞儚鏂囦欢淇濆瓨璺緞,濡傛灉涓嶉厤缃綍鍍忔枃浠朵繚瀛樺湪搴旂敤绋嬪簭鎵鍦ㄧ殑璺緞涓嬬殑record瀛愯矾寰勶紝濡傛灉閰嶇疆璺緞鍒欎繚瀛樺湪閰嶇疆鐨勮矾寰勭殑record閲岄潰 +#娉ㄦ剰锛氬鏋滈渶瑕佸綍鍍忓瓨鍌紝瀛樺偍鐨勭‖鐩樺崈涓囦笉瑕佸垎鍖猴紝鏁翠釜纭洏浣滀负涓涓尯锛屽洜涓烘湇鍔″櫒娌℃湁鎵ц涓や釜浠ヤ笂鐨勭洏绗︽搷浣溿 +#褰曞儚淇濆瓨璺緞閰嶇疆 windows骞冲彴鐨勮矾寰勯厤缃 姣斿 D:\video ,Linux 骞冲彴閰嶇疆 /home/video +#褰曞儚璺緞浣跨敤浜嗛粯璁よ矾寰勶紝灏变竴鐩翠娇鐢ㄩ粯璁よ矾寰勶紝濡傛灉浣跨敤浜嗛厤缃矾寰勫氨涓鐩翠娇鐢ㄩ厤缃矾寰勩傜‘淇濅娇鐢ㄧ殑璺緞鐨勭‖鐩樼┖闂翠负鏈澶х殑銆 +recordPath= +#鍥剧墖鎶撴媿淇濆瓨璺緞,濡傛灉涓嶅~灏卞湪搴旂敤绋嬪簭鐨勮矾寰勪綔涓烘牴鐩綍锛屽浘鐗囨枃浠跺湪./picture锛屽彲浠ヨ窡褰曞儚鏂囦欢璁剧疆涓哄悓涓涓牴璺緞锛屽洜涓哄浘鐗囪矾寰勮繕浼氬垱寤哄瓙璺緞 ../picture/app/stream ,褰曞儚鏂囦欢瀛愯矾寰勪负 ../record/app/stream +picturePath= +#鍥剧墖鎶撴媿鏈澶у苟鍙戞暟閲忛檺鍒讹紝鎰忔濊鏈嶅姟鍣ㄦ渶澶у厑璁稿灏戣矾鍦ㄥ悓鏃惰繘琛屾姄鎷嶏紝鍥犱负鎶撴媿寰堟秷鑰楃‖浠惰祫婧愶紝闇瑕佽В鐮佽棰戜负YUV锛屽啀鎶奩UV缂栫爜涓篔PEG鍥剧墖锛岀敤鎴疯皟澶axSameTimeSnap杩欎釜鍙傛暟锛岀湅鐪嬫湇鍔″櫒鑳藉惁鏀拺鐨勪綇澶ч噺骞跺彂鎶撴媿锛屾湇鍔″櫒CPU鎬ц兘涓嶅悓锛岃繖涓弬鏁颁篃涓嶅悓 +maxSameTimeSnap=16 +#杈撳嚭鐨勬姄鎷嶅浘鐗囧 锛0 灏辨槸榛樿鐨勫锛屽洜涓鸿棰戝垎杈ㄧ巼涓嶇煡閬擄紝涓嶅悓鐨勬憚鍍忓ご鍚勪釜涓嶅悓锛屽氨浣跨敤0鏉ヤ唬鏇块粯璁ゅ師灏哄鐨勫銆傚鏋滅敤鎴烽渶瑕佹寚瀹氬鐨勫ぇ灏忓彲浠ュ~鍏 1920銆1280銆960銆720銆640銆352 +snapOutPictureWidth=0 +#杈撳嚭鐨勬姄鎷嶅浘鐗囬珮 锛0 灏辨槸榛樿鐨勯珮锛屽洜涓鸿棰戝垎杈ㄧ巼涓嶇煡閬擄紝涓嶅悓鐨勬憚鍍忓ご鍚勪釜涓嶅悓锛屽氨浣跨敤0鏉ヤ唬鏇块粯璁ゅ師灏哄鐨勯珮銆傚鏋滅敤鎴烽渶瑕佹寚瀹氶珮鐨勫ぇ灏忓彲浠ュ~鍏 1080銆 720銆640銆576銆480銆288 +snapOutPictureHeight=0 +#鎶撴媿瀵硅薄鏄惁閿姣侊紝濡傛灉閽堝200璺互鍐呯殑濯掍綋娴佽繘琛岄暱鏈熻繘琛岄珮棰戠巼鐨勬姄鎷嶏紝鍙互璁剧疆0锛屽氨鏄瘡娆℃姄鎷嶅畬姣曞悗涓嶇珛鍗抽攢姣佸璞★紝涓嬩竴娆″啀閲嶆柊浣跨敤鎶撴媿瀵硅薄銆傛瘮濡傞拡瀵200浠ュ唴璺棰戞瘡闅2绉掕繘琛屾姄鎷嶅浘鐗囷紝鍙互璁剧疆涓0锛岃繖鏍锋彁渚涙姄鎷嶉熷害銆 +snapObjectDestroy=1 +#鎶撴媿瀵硅薄鏈澶т繚瀛樻椂闀(鍗曚綅锛氱)锛屽綋 snapObjectDestroy 绛変簬 0 鏃讹紝璇ュ弬鏁版湁鏁堬紝鎰忔濊褰撴姄鎷嶅璞″鐢ㄦ椂锛屾渶澶ф湁鏁堟椂闂村唴澶嶇敤鎶撴媿瀵硅薄鎵嶆湁鏁堬紝杩欐牱鍋氭槸闃叉鍐呭瓨娉勬紡锛屽綋瓒呭嚭鏈闀垮鐢ㄦ椂闀匡紝瀵硅薄浼氳嚜鍔ㄩ攢姣侊紝鍐嶆姄鎷嶆椂浼氶噸鏂板垱寤烘姄鎷嶅璞 +snapObjectDuration=120 +#鎶撴媿鍥剧墖鍥炲绫诲瀷 1 鍥炲鎶撴媿浜х敓鍥剧墖鐨勯摼鎺ュ湴鍧 姣斿锛歨ttp://192.168.1.218:7088/Media/Camera_00001/2022032008501201.jpg 2 杩斿洖鎶撴媿鍥剧墖鐨勫唴瀹瑰嵆杩斿洖鎶撴媿鐨刯pg瀹屾暣鍥剧墖鍐呭锛宧ttp鍝嶅簲杩斿洖绫诲瀷涓 Content-Type: image/jpeg +captureReplayType=1 +#褰 鎺ュ叆瑙嗛婧愭敞閿鏃舵垨鑰呮祦濯掍綋鏈嶅姟鍣ㄥ畨鍏ㄩ鍑烘椂 鍒犻櫎璇ヨ矾瑙嗛婧愭姄鎷嶆墍浜х敓鐨勬墍鏈夊浘鐗 璁剧疆涓 0 涓嶅垹闄わ紝1 鍒犻櫎 +deleteSnapPicture=0 +#姣忎竴涓獟浣撴簮鍏佽鏈澶т繚鐣欑殑鎶撴媿鍥剧墖鏁伴噺锛屽鏋滆秴杩囧氨浼氳鐩栨渶鑰佺殑鍥剧墖锛岃鐩栨柟寮忓拰褰曞儚鏂囦欢涓鑷,鐢ㄦ埛鏍规嵁鑷繁闇瑕佷及璁℃瘡澶┿佹瘡鍛ㄣ佹瘡鏈堣兘浜х敓澶氬皯寮犳姄鎷嶅浘鐗囷紝璁剧疆濂芥渶澶ф姄鎷嶆暟閲忥紝涔熷氨鏄缃簡鍥剧墖鏈澶т繚瀛樻椂闀 +pictureMaxCount=30 +#rtsp銆乺tmp 鎺ㄦ祦鎺ュ叆鏄惁寮鍚痬p4褰曞儚 0 鏈紑鍚 锛 1 寮鍚 銆傘愭敞鎰忥細浠g悊鎷夋祦鎺ュ叆銆佸浗鏍噂b28181鎺ュ叆濡傛灉寮鍚綍鍍忓垯闇鎸囧畾鍙傛暟 enable_mp4 绛変簬 1 銆 +pushEnable_mp4=0 +#mp4銆乫mp4銆乼s 褰曞埗鍒囩墖鏃堕棿锛屽崟浣嶇锛屾渶澶т笉瀹滆秴杩600绉掞紙10鍒嗛挓锛夈愬鏋滈噰鐢 ts 鍒囩墖鏃堕暱涓嶅疁瓒呰繃180绉掋戯紝鍥犱负鏃堕棿瓒婇暱浜х敓鐨刴p4鏂囦欢灏辫秺澶э紝鍦ㄧ偣鎾椂鎵撳紑褰曞儚鏂囦欢鐨勯熷害浼氬彉鎱 +fileSecond=360 +#褰曞儚鏂囦欢閲囩敤鐨勬枃浠舵牸寮 1 涓 fmp4鏍煎紡 锛2 涓 mp4 鏍煎紡 , 3 ts 鏍煎紡銆愬鏋滈噰鐢 ts 鍒囩墖锛屽湪褰曞儚鍥炴斁鏃舵敮鎸 hls 鍥炴斁锛岃棰戠敾闈㈠彲浠ョ寮 銆 +videoFileFormat=3 +#褰曞儚鏂囦欢鏈澶т繚鐣欐椂闀匡紝鍗曚綅灏忔椂 +fileKeepMaxTime=3 +#鏌ヨ褰曞儚鍒楄〃鏄惁鑾峰彇褰曞儚鏂囦欢鐪熸鏃堕暱锛屽鏋滃紑鍚幏鍙栧綍鍍忕湡姝f椂闀夸細閫犳垚褰曞儚鏌ユ壘姣旇緝鎱紝濡傛灉涓嶅紑鍚氨浼氳繑鍥炲綍鍍忓垏鐗囨椂闂磃ileSecond 鐨勫,銆0 榛樿涓嶅紑鍚 ,銆 1 寮鍚 鑾峰彇鐪熸褰曞儚鏃堕暱銆 +enable_GetFileDuration=0 +#http鏂瑰紡褰曞儚涓嬭浇閫熷害璁剧疆 璁剧疆鐨勫艰秺澶э紝涓嬭浇鐨勯熷害灏辫秺蹇 锛岀敤鎴锋牴鎹渶瑕佽皟鏁 锛岃寖鍥 1 ~ 10 +httpDownloadSpeed=6 +#MP4鐐规挱 (rtsp銆乺tmp銆乭ttp-flv銆亀s-flv銆乭ls )鏄惁寰幆鎾斁鏂囦欢 +fileRepeat=0 + +#H265瑙嗛杞爜閮ㄥ垎,H265ConvertH264_enable 绛変簬 0 鏈紑鍚浆鐮 锛孒265ConvertH264_enable 绛変簬 1 寮鍚浆鐮 锛岃繖涓弬鏁版槸鍏ㄥ眬鑼冨洿锛屽彧瑕佽缃负 1锛屾墍鏈夋帴鍏ョ殑H265瑙嗛閮戒細杞爜涓篐264锛屽鏋滆浆鐮侀儴鍒嗙殑H265瑙嗛闇瑕佹妸 H265ConvertH264_enable 鍙傛暟 蹇呴』璁剧疆涓 0 +#鍗充娇 H265ConvertH264_enable 璁剧疆涓 0 锛屼絾鏄湪浠g悊鎷夋祦鎺ュ叆銆佸浗鏍囨帴鍏 褰撴寚瀹氬 convertOutWidth 銆侀珮 convertOutHeight 鍙傛暟鐨勫兼椂 灏变細杞爜璇ヨ矾鐨凥265瑙嗛锛屼篃浼氳鐩栭厤缃枃浠朵腑榛樿鐨勮棰戣浆鐮 瀹姐侀珮 锛屼互浠g悊鎷夋祦銆佸浗鏍囨帴鍏ョ殑瀹姐侀珮涓哄噯 +H265ConvertH264_enable=0 +#H265杞爜绫诲瀷 0 CPU ,1 鑻变紵杈剧殑GUP 銆愭敞鎰忥細瑕佺數鑴戠‘瀹氬畨瑁呮湁鑻变紵杈炬樉鍗″苟涓斿畨瑁呭ソ椹卞姩鎯呭喌涓嬫墠鑳藉紑鍚紝鍚﹀垯涔熶細鍒囨崲涓篶pu 銆 锛2 AMD 鐨 GPU (灏氭湭鏀寔) 銆愭敞鎰忥細瑕佺數鑴戠‘瀹氬畨瑁呮湁AMD鏄惧崱骞朵笖瀹夎濂介┍鍔ㄦ儏鍐典笅鎵嶈兘寮鍚紝鍚﹀垯涔熶細鍒囨崲涓篶pu 銆 +H265DecodeCpuGpuType=0 +#H264杞爜绫诲瀷 H264DecodeEncode_enable 绛変簬 1寮濮嬭浆鐮佸姛鑳 ,褰撹緭鍏ヤ负H264锛岃嫢鍏抽棴姝ゅ姛鑳斤紝鍒欑缉鏀俱佹按鍗板姛鑳戒細澶辨晥 +H264DecodeEncode_enable=0 +#鏀寔鏈澶х殑杞爜璺暟锛岀敱浜庨槻姝㈡湇鍔″櫒琚浆鐮佸姛鑳借繃搴︿娇鐢紝璁剧疆涓涓渶澶ц浆鐮佽矾鏁帮紝瓒呰繃杩欎釜璺暟鍒265鐨勮棰戜笉鍐嶈浆鐮侊紝鐢变簬鐢佃剳CPU銆丟PU涓嶅お鐩稿悓锛岃繖涓渶澶ц浆鐮佽矾鏁颁篃浼氫笉鍚岋紝瀹為檯鍟嗙敤鏃堕渶瑕佺敤鎴峰疄娴嬩箣鍚庡啀淇敼杩欎釜鍙傛暟鍊硷紝鍙兘浼氬彉澶э紝涔熷彲鑳戒細鍙樺皬 +convertMaxObject=26 +#姘村嵃杩囨护鍣 FilterVideo_enable 绛変簬 1寮鍚按鍗板姛鑳 涓0鏃禙ilterVideo_text瀛楁澶辨晥 銆愭敞鎰忥細姘村嵃闇瑕侀噸鏂扮紪瑙g爜锛屾按鍗板姛鑳介渶淇濊瘉H265ConvertH264_enable 涓 1銆丠264DecodeEncode_enable 涓 1杞爜寮鍚 +filterVideo_enable=0 +#姘村嵃鏂囧瓧 涓虹┖瑙嗕负涓嶅紑鍚按鍗 闀垮害涓嶈秴杩64 +filterVideo_text=ABL姘村嵃娴嬭瘯123 +#姘村嵃瀛椾綋澶у皬 8銆9銆12銆15銆18銆20銆22銆36銆48銆60 +FilterFontSize=30 +#姘村嵃瀛椾綋棰滆壊 green ,red , blue , yellow ,black , white +FilterFontColor=red +#姘村嵃瀛椾綋杈撳嚭璧峰x鍧愭爣 +FilterFontLeft=5 +#姘村嵃瀛椾綋杈撳嚭璧峰y鍧愭爣 +FilterFontTop=5 +#姘村嵃瀛椾綋鏂囧瓧閫忔槑搴 0.1銆0.2銆0.3 ~ 0.9 +FilterFontAlpha=0.6 +#杞爜杈撳嚭瀹斤紝鍦℉265杞爜涓篐264鏃讹紝鎸囧畾杈撳嚭鐨勫 锛屾瘮濡 1280銆800銆720銆352銆 +convertOutWidth=960 +#杞爜杈撳嚭楂橈紝鍦℉265杞爜涓篐264鏃讹紝鎸囧畾杈撳嚭鐨勫 锛屾瘮濡 720銆480銆480銆288銆 +convertOutHeight=640 +#杈撳嚭杞爜瑙嗛鐨勭爜娴 锛屽崟浣 K/bps 锛屽彲浠ュ~鍐 512 銆768 銆1024 銆2048銆3072銆4096 锛屼絾鏄敱浜庤浆鐮佽緭鍑虹殑鍒嗚鲸鐜囦笉楂橈紝涓嶉渶瑕佸~鍐 澶ぇ鐨勭爜鐜 寤鸿 1024 宸﹀彸鍗冲彲 +convertOutBitrate=1658 + +#浜嬩欢閫氱煡閮ㄥ垎,褰 璁剧疆 1 鏃讹紝寮鍚簨浠堕氱煡锛岃缃 0 鏃跺叧闂簨浠堕氱煡 锛岄氱煡鏈嶅姟鍣ㄧ殑鍦板潃锛岀鍙e彿涓瀹氳閰嶇疆鍑嗙‘姣斿锛欼P锛192.168.1.158 绔彛 18080 +hook_enable=0 +#鏌愪竴璺爜娴佹寔缁灏戠鏃犱汉瑙傜湅灏变細鍙戦 鏃犱汉瑙傜湅閫氱煡娑堟伅 锛屽崟浣嶇 +noneReaderDuration=15 +#鏌愪竴璺 i甯 鍒拌揪閫氱煡娆℃暟鎬绘暟锛屽綋瓒呰繃杩欐暟閲忔椂涓嶅啀閫氱煡锛屽鏋滄兂涓鐩撮氱煡鍙互鎶30淇敼涓轰竴涓緢澶х殑鏁伴噺锛屾瘮濡 999999999999 锛岃 鍙傛暟鍜 浜嬩欢 on_stream_iframe_arrive 鏄湁鍏宠仈鐨 +iframeArriveNoticCount=30 +#鏈嶅姟鍣ㄥ惎鍔ㄥ悗浼氬彂閫侀氱煡娑堟伅锛屽憡鐭ユ湇鍔″櫒涓婄嚎 +on_server_started=http://192.168.1.128:18080/index/hook/on_server_started +#鏈嶅姟鍣ㄦ鍦ㄨ繍琛屼細鍙戦佷繚娲讳簨浠讹紝鍛婄煡鏈嶅姟鍣ㄦ鍦ㄦ甯歌繍琛岋紝鐩稿綋浜庢湇鍔″櫒蹇冭烦锛20绉掑彂閫佷竴娆″績璺充俊鎭紝鍛婄煡鏈嶅姟鍣ㄥ浜庢甯歌繍琛 銆愭敞鎰 蹇冭烦浜嬩欢鏄繀椤昏閰嶇疆 銆 +on_server_keepalive=http://192.168.1.128:18080/index/hook/on_server_keepalive +#娴佸獟浣撴湇鍔″櫒鍙戦佸績璺虫椂闀块棿闅旓紝鍗曚綅绉 +keepaliveDuration=20 +#鎾斁鏌愪竴璺棰戞椂锛屼細鍙戦佷簨浠堕氱煡锛屽鏋滀笉闇瑕 鍒欏垹闄 http://192.168.1.128:18080/index/hook/on_play +on_play=http://192.168.1.128:18080/index/hook/on_play +#褰撴湇鍔″櫒鎺ュ叆鏌愪竴璺爜娴佹椂锛屼細鍙戦佷簨浠堕氱煡 锛屽鏋滀笉闇瑕佸垯鍒犻櫎 http://192.168.1.128:18080/index/hook/on_publish +on_publish=http://192.168.1.128:18080/index/hook/on_publish +#褰撴煇涓璺殑鐮佹祦杈惧埌鏃朵細閫氱煡涓娆★紝娉ㄦ剰锛氬鏋滀笉闇瑕侀氱煡璇ヤ簨浠讹紝灏辨妸 http://192.168.1.128:18080/index/hook/on_stream_arrive 鍒犻櫎鎺 +on_stream_arrive=http://192.168.1.128:18080/index/hook/on_stream_arrive +#褰撴煇涓璺 i甯 杈惧埌鍒版椂浼氶氱煡锛屾敞鎰忥細濡傛灉涓嶉渶瑕侀氱煡璇ヤ簨浠讹紝灏辨妸 http://192.168.1.128:18080/index/hook/on_stream_iframe_arrive 鍒犻櫎鎺 +on_stream_iframe_arrive= +#鍦ㄤ唬鐞嗘媺娴佹帴鍏ャ佸浗鏍囨帴鍏ヤ腑锛屽綋鐢宠鎴愬姛鍚庯紝浣嗘槸杩欎竴璺殑鐮佹祦娌℃湁杈惧埌鏃朵細閫氱煡涓娆★紝娉ㄦ剰锛氬鏋滀笉闇瑕侀氱煡璇ヤ簨浠讹紝灏辨妸 http://192.168.1.128:18080/index/hook/on_stream_not_arrive 鍒犻櫎鎺 +on_stream_not_arrive=http://192.168.1.128:18080/index/hook/on_stream_not_arrive +#褰撴煇涓璺祦鏃犱汉瑙傜湅鏃讹紝浼氳Е鍙戣閫氱煡浜嬩欢锛屾帴鏀剁鏀跺埌鍚庡彲浠ヨ繘琛屾柇娴佹搷浣滐紝姣斿鍏抽棴鍥芥爣鍙戞祦锛屾柇寮浠g悊鎷夋祦锛屾柇寮鎺ㄦ祦绛夌瓑鎿嶄綔 锛屾敞鎰忥細涓嶉渶瑕佽浜嬩欢 鎶 http://192.168.1.128:18080/index/hook/on_stream_none_reader 鍒犻櫎鎺 +on_stream_none_reader=http://192.168.1.128:18080/index/hook/on_stream_none_reader +#褰撴煇涓璺爜娴佹柇寮鏃朵細閫氱煡涓娆 锛屾敞鎰忥細涓嶉渶瑕佽浜嬩欢锛屾妸 http://192.168.1.128:18080/index/hook/on_stream_disconnect 鍒犻櫎 +on_stream_disconnect=http://192.168.1.128:18080/index/hook/on_stream_disconnect +#鎾斁鏃讹紝鎵句笉鍒版挱鏀剧殑鐮佹祦锛岄氳繃閰嶅悎on_stream_none_reader浜嬩欢鍙互瀹屾垚鎸夐渶鎷夋祦 娉ㄦ剰锛氬鏋滀笉闇瑕佽浜嬩欢锛屾妸 http://192.168.1.128:18080/index/hook/on_stream_not_found 鍒犻櫎 +on_stream_not_found=http://192.168.1.128:18080/index/hook/on_stream_not_found +#褰曞埗瀹屾瘯涓娈祄p4鏂囦欢閫氱煡 娉ㄦ剰锛氬鏋滀笉闇瑕侀氱煡璇ヤ簨浠讹紝灏辨妸 http://192.168.1.128:18080/index/hook/on_record_mp4 鍒犻櫎鎺 +on_record_mp4=http://192.168.1.128:18080/index/hook/on_record_mp4 +#褰撳綍鍍忔枃浠惰瑕嗙洊鏃讹紝浼氬彂閫佽瑕嗙洊鐨勫綍鍍忔枃浠跺悕瀛,鍙互鐞嗚В涓鸿閫氱煡鐨勫垹闄ゅ綍鍍忔枃浠跺悕瀛楋紝濡傛灉涓嶉渶瑕侀氱煡璇ヤ簨浠讹紝灏辨妸 http://192.168.1.128:18080/index/hook/on_delete_record_mp4 鍒犻櫎鎺 +on_delete_record_mp4=http://192.168.1.128:18080/index/hook/on_delete_record_mp4 +#褰曞儚杩涘害:褰撳墠褰曞儚鏂囦欢宸茬粡褰曞埗浜嗗灏戠锛屾诲綍鍍忔椂闀垮凡缁忓埌澶氬皯绉掞細濡傛灉涓嶉渶瑕侀氱煡璇ヤ簨浠讹紝灏辨妸 http://192.168.1.128:18080/index/hook/on_record_progress鍒犻櫎鎺 +on_record_progress=http://192.168.1.128:18080/index/hook/on_record_progress +#褰曞埗 hls ts 鍒囩墖瀹屾垚浜嬩欢閫氱煡锛堝綋TS鏂囦欢鍒囩墖鑷崇‖鐩樻椂鎵嶉氱煡锛屽嵆 hlsCutType 绛変簬 1锛 娉ㄦ剰锛氬鏋滀笉闇瑕侀氱煡璇ヤ簨浠讹紝灏辨妸 http://192.168.1.128:18080/index/hook/on_record_ts 鍒犻櫎鎺 +on_record_ts=http://192.168.1.128:18080/index/hook/on_record_ts + +#http鎿嶄綔銆佽姹傜鍙o紙tcp绫诲瀷锛 +httpServerPort=7088 +#http璇锋眰鎿嶄綔寮哄埗璁剧疆涓虹煭杩炴帴锛 1 涓哄己鍒朵负鐭繛鎺ヨ姹傦紝 0 涓洪粯璁ょ殑杩炴帴绫诲瀷 +httqRequstClose=0 + +#rtsp 杩愯绔彛 rtsp鎺ㄦ祦銆乺tsp鎷夋祦閮芥槸浣跨敤璇ョ鍙 锛坱cp绫诲瀷锛 +rtspPort=554 + +#rtmp 杩愯绔彛 rtmp鎺ㄦ祦銆乺tmp鎷夋祦閮芥槸浣跨敤璇ョ鍙o紙tcp绫诲瀷锛 +rtmpPort=1935 + +#http-mp4 杩愯绔彛,http-mp4 鎷夋祦鏃堕噰鐢ㄨ绔彛 锛坱cp绫诲瀷锛 +httpMp4Port=5088 + +#ws-flv 杩愯绔彛,ws-flv 鎷夋祦鏃堕噰鐢ㄨ绔彛 锛坱cp绫诲瀷锛 +wsFlvPort=6088 + +#http-flv 杩愯绔彛,http-flv 鎷夋祦鏃堕噰鐢ㄨ绔彛 锛坱cp绫诲瀷锛 +httpFlvPort=8088 + +#webrtc鎾斁瑙嗛绔彛锛坱cp绫诲瀷锛 +webrtcPort=8192 + +#websocket鍗忚浠ョ鏈夋牸寮忔帴鍏cm鏁版嵁 +WsRecvPcmPort=9298 + +#鍥芥爣鍗曠鍙f帴鏀 锛坲dp绫诲瀷锛 +ps_tsRecvPort=10000 + +#-----hls鐩稿叧閰嶇疆------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- +#鏄惁鍚敤hls鍒囩墖 锛屽嵆9088 绔彛鏈嶅姟鏄惁寮鍚 銆 1 寮鍚疕LS 鍒囩墖 锛 0 鍏抽棴HLS 鍒囩墖 銆戯紝濡傛灉 hls_enable 绛変簬 0 锛岄偅涔 hlsPort 銆乭lsCutType 銆乭265CutType 杩欎笁涓弬鏁板け鏁 +hls_enable=1 + +#hls 杩愯绔彛,鎾斁hls 濯掍綋娴佹椂浣跨敤璇ョ鍙o紙tcp绫诲瀷锛 +hlsPort=9088 + +#hls鍒囩墖鏃堕棿闀匡紝鍗曚綅锛氱 锛1 ~ 10 绉掞級 +hlsCutTime=1 + +#褰撳垏鐗囧埌纭洏鏃讹紝鏈澶т繚鐣檛s鏂囦欢涓暟 +maxTsFileCount=10 + +#HLS鍒囩墖鏂瑰紡 銆恏lsCutType 绛変簬 1 璁剧疆涓哄垏鐗囨枃浠跺埌纭洏 锛屽鏋滄湇鍔″櫒鍐呭瓨姣旇緝灏忥紝鍙互鍒囩墖鏂囦欢淇濆瓨鍒扮‖鐩樸戙恏lsCutType 绛変簬 2 璁剧疆涓哄垏鐗囨枃浠朵繚瀛樺埌鍐呭瓨涓 锛屽鏋滃唴瀛樺緢澶э紝姣斿 64G銆128G 锛屾帹鑽愬垏鐗囨枃浠朵繚瀛樺埌鍐呭瓨銆 +hlsCutType=2 + +#褰撳垏鐗囧埌纭洏鏃讹紝鍙互璁剧疆ts鏂囦欢淇濆瓨鐨勮矾寰勶紝濡傛灉闇瑕乭ls鍒囩墖鐨勮棰戣矾鏁拌緝澶氾紝寤鸿鍒囩墖鍒板唴瀛樼‖鐩樹笂锛岃繖鏍稨LS鍒囩墖鏃舵渶澶х▼搴︿笉褰卞搷鏈嶅姟鍣ㄧ殑鎬ц兘, 褰 wwwPath 涓嶅~鍐欙紝鍒囩墖璺緞灏卞湪 褰撳墠鏈嶅姟鎵鍦ㄨ矾寰勭殑 www 瀛愯矾寰勯噷 +#sudo mkdir /mnt/ramdisk 鍒涘缓鍐呭瓨纭洏鐨勮矾寰 锛寃wwPath 鐨勫煎彲浠ュ~鍐 /mnt/ramdisk +#sudo mount -t tmpfs tmpfs /mnt/ramdisk -o size=8G,defaults,noatime,mode=777 鍒涘缓鍐呭瓨纭洏 +wwwPath= + +#H265瑙嗛鍒囩墖鏂瑰紡 銆1 鍒囩墖涓篢S 鏂囦欢锛2 鍒囩墖涓簃p4 鏂囦欢 銆 +h265CutType=2 +#-----hls鐩稿叧閰嶇疆------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- + +#鏄惁寮鍚煶棰戯紝寮鍚煶棰戞椂锛屾祦濯掍綋杈撳嚭鎵嶆湁闊抽锛屽惁鍒欒繃婊ゆ帀闊抽鏁版嵁 enable_audio 绛変簬 1 鏃跺紑鍚紝enable_audio 绛変簬 0 鏃讹紝鍏抽棴澹伴煶 +enable_audio=1 +#http-flv銆亀s-flv鎾斁鏃讹紝褰撴簮娴佹病鏈夐煶棰戞椂鍊欐槸鍚﹀紑鍚鍔犻潤闊筹紝濡傛灉鏈嶅姟鍣ㄥ湪linux骞冲彴杩愯寤鸿寮鍚鍔犻潤闊筹紝windows骞冲彴寤鸿鍏抽棴,褰 enable_audio = 0 鏃 flvPlayAddMute 璁剧疆鍙傛暟澶辨晥 銆1 澧炲姞闈欓煶 锛0 涓嶅鍔犻潤闊炽 +flvPlayAddMute=1 +#鍦ㄦ祦濯掍綋杈撳嚭闊抽鏃讹紝濡傛灉婧愭祦闊抽鏄痝711A銆丟711U锛岃鍙傛暟鍐冲畾鏄惁杞崲涓篈AC锛屽鏋滆浆鎹负AAC 锛屽湪娴忚鍣ㄦ挱鏀惧0闊冲氨姝e父浜嗭紝0 涓嶈浆鎹紝1 杞崲涓篈AC 锛岃浆鎹㈠悗鏍煎紡 1 閫氶亾 锛8000 閲囨牱棰戠巼 +G711ConvertAAC=0 + +#iocontent 鏁伴噺 Cpu 鏈夊嚑涓牳蹇冿紝灏卞彲浠ュ~鍐欏嚑涓紝浣跨敤榛樿16涔熷彲浠ワ紝濡傛灉cpu鏄32銆40銆64 鏍稿績锛屽氨鐩稿簲濉啓 32銆40銆64 +IOContentNumber=16 + +#姣忎釜iocontent涓婂垱寤虹嚎绋嬫暟閲 +ThreadCountOfIOContent=2 + +#缃戠粶鏁版嵁鎺ユ敹绾跨▼鏁伴噺锛屽彲浠ユ牴鎹瓹PU鏍告暟閲 x 2 鏉ラ厤缃 ,涔熷彲浠ヤ娇鐢ㄩ粯璁ゅ弬鏁64 +RecvThreadCount=32 + +#缃戠粶鏁版嵁鍙戦佺嚎绋嬫暟閲,鍙互鏍规嵁CPU鏍告暟閲 x 2 鏉ラ厤缃 ,涔熷彲浠ヤ娇鐢ㄩ粯璁ゅ弬鏁64 +SendThreadCount=64 -#一些比较敏感的http api在访问时需要提供secret,否则无权限调用 -secret = 035c73f7-bb6b-4889-a715-d9eb2d1925cc +#褰曞儚鍥炴斁妯″潡绾跨▼鏁伴噺 +RecordReplayThread=8 -#本机的IP地址,最好需要配置准确(如果不配置程序会自动获取一个地址代替,如果本机有多个地址可能会不准确,如果配置则使用配置的IP地址),因为调用getMediaList 获取可用的媒体源的json中,会使用到本机的IP地址来拼接rtsp、rtmp、http-flv、ws-flv、hls、http-mp4 的播放url -localipAddress = 192.168.2.5 +#GB28181 TCP 鏂瑰紡鍙戦乺tp(璐熻浇PS)鐮佹祦鏃讹紝鍖呭ご闀垮害閫夋嫨锛1锛 4涓瓧鑺傛柟寮忥紝2锛2涓瓧鑺傛柟寮忥級 +GB28181RtpTCPHeadType=2 -#所有接入流,当多长时间持续无人观看时会自动断开码流接入,包括推流接入,拉流接入,国标接入, 时间单位 分钟 -#【注意:当该路接入流启动了录像,不管是否有人观看都不会关闭 ,除非关闭录像功能 】 -maxTimeNoOneWatch = 9999999 +#GB28181 鍥芥爣鎺ュ叆锛屽鏋滅敱 ABLMediaServer鑷姩鍒嗛厤鐨勮缃殑鏈灏忕鍙o紝鑼冨洿 浠 GB28181RtpMinPort 鑷 GB28181RtpMaxPort +GB28181RtpMinPort=35000 -#录像文件保存路径,如果不配置录像文件保存在应用程序所在的路径下的record子路径,如果配置路径则保存在配置的路径的record里面 -#注意:如果需要录像存储,存储的硬盘千万不要分区,整个硬盘作为一个区,因为服务器没有执行两个以上的盘符操作。 -#录像保存路径配置 windows平台的路径配置 比如 D:\video ,Linux 平台配置 /home/video -#录像路径使用了默认路径,就一直使用默认路径,如果使用了配置路径就一直使用配置路径。确保使用的路径的硬盘空间为最大的。 -recordPath = +#GB28181 鍥芥爣鎺ュ叆锛屽鏋滅敱 ABLMediaServer鑷姩鍒嗛厤鐨勮缃殑鏈澶х鍙 锛岃寖鍥 浠 GB28181RtpMinPort 鑷 GB28181RtpMaxPort +GB28181RtpMaxPort=40000 -#图片抓拍保存路径,如果不填就在应用程序的路径作为根目录,图片文件在./picture,可以跟录像文件设置为同一个根路径,因为图片路径还会创建子路径 ../picture/app/stream ,录像文件子路径为 ../record/app/stream -picturePath = +#浠g悊鎷夋祦銆佹帹娴 绛夌瓑缃戠粶杩炴帴鏂嚎鍚庨噸杩炴鏁 720 锛屾瘡闅15绉掓柇绾块噸杩1娆★紝鐢ㄦ埛鏍规嵁闇瑕佷慨鏀归噸杩炴鏁 锛屽鏋滃鏂瑰苟涓嶅湪绾夸笉瀹滈噸杩炴鏁拌繃澶 +ReConnectingCount=720 -#图片抓拍最大并发数量限制,意思说服务器最大允许多少路在同时进行抓拍,因为抓拍很消耗硬件资源,需要解码视频为YUV,再把YUV编码为JPEG图片,用户调大maxSameTimeSnap这个参数,看看服务器能否支撑的住大量并发抓拍,服务器CPU性能不同,这个参数也不同 -maxSameTimeSnap = 16 +#缃戠粶鏂嚎瓒呮椂妫娴嬫渶澶ф椂闀匡紝鎰忔濊鏈澶ф椂闀挎病鏈夌綉缁滄暟鎹揪鍒板氨璁や负宸茬粡鏂嚎 锛岃繘琛岄攢姣佸鐞 +MaxDiconnectTimeoutSecond=40 -#输出的抓拍图片宽 ,0 就是默认的宽,因为视频分辨率不知道,不同的摄像头各个不同,就使用0来代替默认原尺寸的宽。如果用户需要指定宽的大小可以填入 1920、1280、960、720、640、352 -snapOutPictureWidth = 0 +#寮哄埗鍙戦両甯э紝褰撴湁璁稿鎽勫儚澶寸殑gop璁剧疆涓50锛屾垨鑰呴渶瑕佺偣鎾棰戞椂蹇熺殑鍑虹敾闈紝鍙互寮鍚己鍒跺彂閫乮甯с +ForceSendingIFrame=1 -#输出的抓拍图片高 ,0 就是默认的高,因为视频分辨率不知道,不同的摄像头各个不同,就使用0来代替默认原尺寸的高。如果用户需要指定高的大小可以填入 1080、 720、640、576、480、288 -snapOutPictureHeight = 0 - -#抓拍对象是否销毁,如果针对200路以内的媒体流进行长期进行高频率的抓拍,可以设置0,就是每次抓拍完毕后不立即销毁对象,下一次再重新使用抓拍对象。比如针对200以内路视频每隔2秒进行抓拍图片,可以设置为0,这样提供抓拍速度。 -snapObjectDestroy = 1 - -#抓拍对象最大保存时长(单位:秒),当 snapObjectDestroy 等于 0 时,该参数有效,意思说当抓拍对象复用时,最大有效时间内复用抓拍对象才有效,这样做是防止内存泄漏,当超出最长复用时长,对象会自动销毁,再抓拍时会重新创建抓拍对象 -snapObjectDuration = 120 - -#抓拍图片回复类型 1 回复抓拍产生图片的链接地址 比如:http://192.168.1.218:7088/Media/Camera_00001/2022032008501201.jpg 2 返回抓拍图片的内容即返回抓拍的jpg完整图片内容,http响应返回类型为 Content-Type: image/jpeg -captureReplayType = 1 - -#当 接入视频源注销时或者流媒体服务器安全退出时 删除该路视频源抓拍所产生的所有图片 设置为 0 不删除,1 删除 -deleteSnapPicture = 0 - -#每一个媒体源允许最大保留的抓拍图片数量,如果超过就会覆盖最老的图片,覆盖方式和录像文件一致,用户根据自己需要估计每天、每周、每月能产生多少张抓拍图片,设置好最大抓拍数量,也就是设置了图片最大保存时长 -pictureMaxCount = 30 - -#rtsp、rtmp 推流接入是否开启mp4录像 0 未开启 , 1 开启 。【注意:代理拉流接入、国标gb28181接入如果开启录像则需指定参数 enable_mp4 等于 1 】 -pushEnable_mp4 = 0 - -#mp4、fmp4录制切片时间,单位秒,最大不宜超过600秒(10分钟),因为时间越长产生的mp4文件就越大,在点播时打开录像文件的速度会变慢 -fileSecond = 300 - -#录像文件采用的文件格式 1 为 fmp4格式 ,2 为 mp4 格式 -videoFileFormat = 1 - -#录像文件最大保留时长,单位小时 -fileKeepMaxTime = 3 - -#http方式录像下载速度设置 设置的值越大,下载的速度就越快 ,用户根据需要调整 ,范围 1 ~ 10 -httpDownloadSpeed = 6 - -#MP4点播 (rtsp、rtmp、http-flv、ws-flv、hls )是否循环播放文件 -fileRepeat = 0 - -#H265视频转码部分,H265ConvertH264_enable 等于 0 未开启转码 ,H265ConvertH264_enable 等于 1 开启转码 ,这个参数是全局范围,只要设置为 1,所有接入的H265视频都会转码为H264,如果转码部分的H265视频需要把 H265ConvertH264_enable 参数 必须设置为 0 -#即使 H265ConvertH264_enable 设置为 0 ,但是在代理拉流接入、国标接入 当指定宽 convertOutWidth 、高 convertOutHeight 参数的值时 就会转码该路的H265视频,也会覆盖配置文件中默认的视频转码 宽、高 ,以代理拉流、国标接入的宽、高为准 -H265ConvertH264_enable = 0 - -#H265转码类型 0 CPU ,1 英伟达的GUP 【注意:要电脑确定安装有英伟达显卡并且安装好驱动情况下才能开启,否则也会切换为cpu 】 ,2 AMD 的 GPU (尚未支持) 【注意:要电脑确定安装有AMD显卡并且安装好驱动情况下才能开启,否则也会切换为cpu 】 -H265DecodeCpuGpuType = 0 - -#H264转码类型 H264DecodeEncode_enable 等于 1开始转码功能 ,当输入为H264,若关闭此功能,则缩放、水印功能会失效 -H264DecodeEncode_enable = 0 - -#支持最大的转码路数,由于防止服务器被转码功能过度使用,设置一个最大转码路数,超过这个路数则265的视频不再转码,由于电脑CPU、GPU不太相同,这个最大转码路数也会不同,实际商用时需要用户实测之后再修改这个参数值,可能会变大,也可能会变小 -convertMaxObject = 26 - -#水印过滤器 FilterVideo_enable 等于 1开启水印功能 为0时FilterVideo_text字段失效 【注意:水印需要重新编解码,水印功能需保证H265ConvertH264_enable 为 1、H264DecodeEncode_enable 为 1转码开启】 -filterVideo_enable = 0 - -#水印文字 为空视为不开启水印 长度不超过64 -filterVideo_text = ABL水印测试123 - -#水印字体大小 8、9、12、15、18、20、22、36、48、60 -FilterFontSize = 30 - -#水印字体颜色 green ,red , blue , yellow ,black , white -FilterFontColor = red - -#水印字体输出起始x坐标 -FilterFontLeft = 5 - -#水印字体输出起始y坐标 -FilterFontTop = 5 - -#水印字体文字透明度 0.1、0.2、0.3 ~ 0.9 -FilterFontAlpha = 0.6 - -#转码输出宽,在H265转码为H264时,指定输出的宽 ,比如 1280、800、720、352、 -convertOutWidth = 960 - -#转码输出高,在H265转码为H264时,指定输出的宽 ,比如 720、480、480、288、 -convertOutHeight = 640 - -#输出转码视频的码流 ,单位 K/bps ,可以填写 512 、768 、1024 、2048、3072、4096 ,但是由于转码输出的分辨率不高,不需要填写 太大的码率 建议 1024 左右即可 -convertOutBitrate = 1658 - -#事件通知部分,当 设置 1 时,开启事件通知,设置 0 时关闭事件通知 ,通知服务器的地址,端口号一定要配置准确比如:IP:192.168.1.158 端口 80 -hook_enable = 0 - -#某一路码流持续多少秒无人观看就会发送 无人观看通知消息 ,单位秒 -noneReaderDuration = 15 - -#某一路 i帧 到达通知次数总数,当超过这数量时不再通知,如果想一直通知可以把30修改为一个很大的数量,比如 999999999999 ,该 参数和 事件 on_stream_iframe_arrive 是有关联的 -iframeArriveNoticCount = 30 - -#服务器启动后会发送通知消息,告知服务器上线 -on_server_started = http://10.0.0.238:4088/index/hook/on_server_started - -#服务器正在运行会发送保活事件,告知服务器正在正常运行,相当于服务器心跳,10秒发送一次心跳信息,告知服务器处于正常运行 ,如果不需要该通知,则把 http://10.0.0.238:4088/index/hook/on_server_keepalive 删除 -on_server_keepalive = http://10.0.0.238:4088/index/hook/on_server_keepalive - -#播放某一路视频时,会发送事件通知,如果不需要 则删除 http://10.0.0.238:4088/index/hook/on_play -on_play = http://10.0.0.238:4088/index/hook/on_play - -#当服务器接入某一路码流时,会发送事件通知 ,如果不需要则删除 http://10.0.0.238:4088/index/hook/on_publish -on_publish = http://10.0.0.238:4088/index/hook/on_publish - -#当某一路的码流达到时会通知一次,注意:如果不需要通知该事件,就把 http://10.0.0.238:4088/index/hook/on_stream_arrive 删除掉 -on_stream_arrive = http://10.0.0.238:4088/index/hook/on_stream_arrive - -#当某一路 i帧 达到到时会通知,注意:如果不需要通知该事件,就把 http://10.0.0.238:4088/index/hook/on_stream_iframe_arrive 删除掉 -on_stream_iframe_arrive = - -#在代理拉流接入、国标接入中,当申请成功后,但是这一路的码流没有达到时会通知一次,注意:如果不需要通知该事件,就把 http://10.0.0.238:4088/index/hook/on_stream_not_arrive 删除掉 -on_stream_not_arrive = http://10.0.0.238:4088/index/hook/on_stream_not_arrive - -#当某一路流无人观看时,会触发该通知事件,接收端收到后可以进行断流操作,比如关闭国标发流,断开代理拉流,断开推流等等操作 ,注意:不需要该事件 把 http://10.0.0.238:4088/index/hook/on_stream_none_reader 删除掉 -on_stream_none_reader = http://10.0.0.238:4088/index/hook/on_stream_none_reader - -#当某一路码流断开时会通知一次 ,注意:不需要该事件,把 http://10.0.0.238:4088/index/hook/on_stream_disconnect 删除 -on_stream_disconnect = http://10.0.0.238:4088/index/hook/on_stream_disconnect - -#播放时,找不到播放的码流,通过配合on_stream_none_reader事件可以完成按需拉流 注意:如果不需要该事件,把 http://10.0.0.238:4088/index/hook/on_stream_not_found 删除 -on_stream_not_found = - -#录制完毕一段mp4文件通知 注意:如果不需要通知该事件,就把 http://10.0.0.238:4088/index/hook/on_record_mp4 删除掉 -on_record_mp4 = http://10.0.0.238:4088/index/hook/on_record_mp4 - -#当录像文件被覆盖时,会发送被覆盖的录像文件名字,可以理解为被通知的删除录像文件名字,如果不需要通知该事件,就把 http://10.0.0.238:4088/index/hook/on_delete_record_mp4 删除掉 -on_delete_record_mp4 = http://10.0.0.238:4088/index/hook/on_delete_record_mp4 - -#录像进度:当前录像文件已经录制了多少秒,总录像时长已经到多少秒:如果不需要通知该事件,就把 http://10.0.0.238:4088/index/hook/on_record_progress删除掉 -on_record_progress = http://10.0.0.238:4088/index/hook/on_record_progress - -#录制 hls ts 切片完成事件通知(当TS文件切片至硬盘时才通知,即 hlsCutType 等于 1) 注意:如果不需要通知该事件,就把 http://10.0.0.238:4088/index/hook/on_record_ts 删除掉 -on_record_ts = http://10.0.0.238:4088/index/hook/on_record_ts - -#http操作、请求端口 -httpServerPort = 7088 - -#http请求操作强制设置为短连接, 1 为强制为短连接请求, 0 为默认的连接类型 -httqRequstClose = 0 - -#rtsp 运行端口 rtsp推流、rtsp拉流都是使用该端口 -rtspPort = 554 - -#rtmp 运行端口 rtmp推流、rtmp拉流都是使用该端口 -rtmpPort = 1935 - -#http-mp4 运行端口,http-mp4 拉流时采用该端口 -httpMp4Port = 5088 - -#ws-flv 运行端口,ws-flv 拉流时采用该端口 -wsFlvPort = 6088 - -#http-flv 运行端口,http-flv 拉流时采用该端口 -httpFlvPort = 8088 - -#国标单端口接收 -ps_tsRecvPort = 10000 - -#-----hls相关配置------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- -#是否启用hls切片 ,即9088 端口服务是否开启 【 1 开启HLS 切片 , 0 关闭HLS 切片 】,如果 hls_enable 等于 0 ,那么 hlsPort 、hlsCutType 、h265CutType 这三个参数失效 -hls_enable = 0 - -#hls 运行端口,播放hls 媒体流时使用该端口 -hlsPort = 9088 - -#hls切片时间长,单位:秒 (1 ~ 10 秒) -hlsCutTime = 1 - -#当切片到硬盘时,最大保留ts文件个数 -maxTsFileCount = 10 - -#HLS切片方式 【hlsCutType 等于 1 设置为切片文件到硬盘 ,如果服务器内存比较小,可以切片文件保存到硬盘】【hlsCutType 等于 2 设置为切片文件保存到内存中 ,如果内存很大,比如 64G、128G ,推荐切片文件保存到内存】 -hlsCutType = 2 - -#当切片到硬盘时,可以设置ts文件保存的路径,如果需要hls切片的视频路数较多,建议切片到内存硬盘上,这样HLS切片时最大程度不影响服务器的性能, 当 wwwPath 不填写,切片路径就在 当前服务所在路径的 www 子路径里 -#sudo mkdir /mnt/ramdisk 创建内存硬盘的路径 ,wwwPath 的值可以填写 /mnt/ramdisk -#sudo mount -t tmpfs tmpfs /mnt/ramdisk -o size=8G,defaults,noatime,mode=777 创建内存硬盘 -wwwPath = - -#H265视频切片方式 【1 切片为TS 文件,2 切片为mp4 文件 】 -h265CutType = 2 - -#-----hls相关配置------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- - -#是否开启音频,开启音频时,流媒体输出才有音频,否则过滤掉音频数据 enable_audio 等于 1 时开启,enable_audio 等于 0 时,关闭声音 -enable_audio = 1 - -#在流媒体输出音频时,如果源流音频是g711A、G711U,该参数决定是否转换为AAC,如果转换为AAC ,在浏览器播放声音就正常了,0 不转换,1 转换为AAC ,转换后格式 1 通道 ,8000 采样频率 -G711ConvertAAC = 1 - -#iocontent 数量 -IOContentNumber = 16 - -#每个iocontent上创建线程数量 -ThreadCountOfIOContent = 8 - -#网络数据接收线程数量,可以根据CPU核数量 x 2 来配置 ,也可以使用默认参数64 -RecvThreadCount = 64 - -#网络数据发送线程数量,可以根据CPU核数量 x 2 来配置 ,也可以使用默认参数64 -SendThreadCount = 64 - -#录像回放模块线程数量 -RecordReplayThread = 8 - -#GB28181 TCP 方式发送rtp(负载PS)码流时,包头长度选择(1: 4个字节方式,2:2个字节方式) -GB28181RtpTCPHeadType = 2 - -#GB28181 国标接入,如果由 ABLMediaServer自动分配的设置的最小端口,范围 从 GB28181RtpMinPort 至 GB28181RtpMaxPort -GB28181RtpMinPort=10000 - -#GB28181 国标接入,如果由 ABLMediaServer自动分配的设置的最大端口 ,范围 从 GB28181RtpMinPort 至 GB28181RtpMaxPort -GB28181RtpMaxPort=10500 - -#代理拉流、推流 等等网络连接断线后重连次数 720 ,每隔15秒断线重连1次,用户根据需要修改重连次数 ,如果对方并不在线不宜重连次数过多 -ReConnectingCount = 720 - -#网络断线超时检测最大时长,意思说最大时长没有网络数据达到就认为已经断线 ,进行销毁处理 -MaxDiconnectTimeoutSecond = 40 - -#强制发送I帧,当有许多摄像头的gop设置为50,或者需要点播视频时快速的出画面,可以开启强制发送i帧。 -ForceSendingIFrame = 1 - -#国标打包、解包库的选择, 1 使用自研库国标打包解包库,2 使用北京老陈国标打包解包库 -gb28181LibraryUse = 2 +#鍥芥爣鎵撳寘銆佽В鍖呭簱鐨勯夋嫨, 1 浣跨敤鑷爺搴撳浗鏍囨墦鍖呰В鍖呭簱锛2 浣跨敤鍖椾含鑰侀檲鍥芥爣鎵撳寘瑙e寘搴 +gb28181LibraryUse=1 [api] -#默认截图图片,在启动FFmpeg截图后但是截图还未生成时,可以返回默认的预设图片 +#榛樿鎴浘鍥剧墖锛屽湪鍚姩FFmpeg鎴浘鍚庝絾鏄埅鍥捐繕鏈敓鎴愭椂锛屽彲浠ヨ繑鍥為粯璁ょ殑棰勮鍥剧墖 defaultSnap = ./picture/logo.jpg -#是否参考wvp-zlm的接口返回 +#鏄惁鍙傝僿vp-zlm鐨勬帴鍙h繑鍥 usewvp = 0 [rtp_proxy] -#随机端口范围,最少确保36个端口 -#该范围同时限制rtsp服务器udp端口范围 +#闅忔満绔彛鑼冨洿锛屾渶灏戠‘淇36涓鍙 +#璇ヨ寖鍥村悓鏃堕檺鍒秗tsp鏈嶅姟鍣╱dp绔彛鑼冨洿 port_range = 30000-35000 [rtc] listening-ip = 192.168.2.5 -#外部IP,直接写公网IP +#澶栭儴IP锛岀洿鎺ュ啓鍏綉IP external-ip = 192.168.2.5 -# TURN服务器UDP/TCP监听端口,默认:3478,同时根据协议会自动开启3479 -# 应该需要防火墙开放端口 +# TURN鏈嶅姟鍣║DP/TCP鐩戝惉绔彛锛岄粯璁わ細3478锛屽悓鏃舵牴鎹崗璁細鑷姩寮鍚3479 +# 搴旇闇瑕侀槻鐏寮鏀剧鍙 listening-port = 3478 -# UDP中继端口范围,用于UDP转发,注意安全组放通 +# UDP涓户绔彛鑼冨洿锛岀敤浜嶶DP杞彂锛屾敞鎰忓畨鍏ㄧ粍鏀鹃 # (default values are 49152 and 65535) min-port = 50000 max-port = 65535 -# 默认域Realm -# 当在数据库中没有显示的域关系定义时,或没有使用任何db时使用。 -# 配合long-term认证机制或者TURN REST API使用,需要设置。 -#realm=relaxwalk.com 用公网ip +# 榛樿鍩烺ealm +# 褰撳湪鏁版嵁搴撲腑娌℃湁鏄剧ず鐨勫煙鍏崇郴瀹氫箟鏃讹紝鎴栨病鏈変娇鐢ㄤ换浣昫b鏃朵娇鐢ㄣ +# 閰嶅悎long-term璁よ瘉鏈哄埗鎴栬匱URN REST API浣跨敤锛岄渶瑕佽缃 +#realm=relaxwalk.com 鐢ㄥ叕缃慽p realm = yunshiting.com -##快捷的添加用户是使用user=XXX:XXXX的方式,可以添加多个。 +##蹇嵎鐨勬坊鍔犵敤鎴锋槸浣跨敤user=XXX:XXXX鐨勬柟寮忥紝鍙互娣诲姞澶氫釜銆 user = admin:admin +##濡傛灉涓嶉傜敤鑷繁turn 鏈嶅姟鍣 鐩存帴璁剧疆杩欎釜澶栫綉閮ㄧ讲濂界殑turn鍦板潃 +turnurl=admin:admin@175.178.213.69:3478 diff --git a/ABLMediaServer/ABLMediaServer.vcxproj b/ABLMediaServer/ABLMediaServer.vcxproj index 4ee1bf9..667997c 100644 --- a/ABLMediaServer/ABLMediaServer.vcxproj +++ b/ABLMediaServer/ABLMediaServer.vcxproj @@ -116,7 +116,7 @@ false - ..\rapidjson-master\include;..\media-server-master\libflv\include;..\media-server-master\librtmp\include;..\media-server-master\libmpeg\include;..\media-server-master\libhls\include;..\media-server-master\libmov\include;..\media-server-master\librtp\include;../3rd/ffmpeg6\include;.\;../3rd/spdlog/include;$(IncludePath) + ..\rapidjson-master\include;..\media-server-master\libflv\include;..\media-server-master\librtmp\include;..\media-server-master\libmpeg\include;..\media-server-master\libhls\include;..\media-server-master\libmov\include;..\media-server-master\librtp\include;../3rd/ffmpeg6\include;./;../3rd/spdlog/include;$(IncludePath) ..\media-server-master\x64\Release;..\3rd\ffmpeg6\lib\x64;$(LibraryPath) $(SolutionDir)bin\$(Platform) diff --git a/ABLMediaServer/ABLString.h b/ABLMediaServer/ABLString.h index a590c0e..f5e552e 100644 --- a/ABLMediaServer/ABLString.h +++ b/ABLMediaServer/ABLString.h @@ -4,7 +4,7 @@ #include #include #include -#include + #include #ifdef _WIN32 #include diff --git a/ABLMediaServer/CNetRtmpServerRecv.cpp b/ABLMediaServer/CNetRtmpServerRecv.cpp index 74de01b..9be6e37 100644 --- a/ABLMediaServer/CNetRtmpServerRecv.cpp +++ b/ABLMediaServer/CNetRtmpServerRecv.cpp @@ -603,19 +603,6 @@ int CNetRtmpServerRecv::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, cha if (strlen(mediaCodecInfo.szVideoName) == 0) strcpy(mediaCodecInfo.szVideoName, szVideoCodec); -#ifndef OS_System_Windows //window 不增加静音 - if (!bAddMuteFlag && strlen(mediaCodecInfo.szAudioName) == 0) - { - bAddMuteFlag = true; - strcpy(mediaCodecInfo.szAudioName, "AAC"); - mediaCodecInfo.nChannels = 1; - mediaCodecInfo.nSampleRate = 16000; - mediaCodecInfo.nBaseAddAudioTimeStamp = 64; - AddClientToMapAddMutePacketList(nClient); - WriteLog(Log_Debug, "媒体源 %s 没有音频 ,创建 Rtmp 音频输出格式为: 视频 %s、音频:AAC( chans:1,sampleRate:16000 ) nClient = %llu ", m_szShareMediaURL, mediaCodecInfo.szVideoName, nClient); - } -#endif - m_videoFifo.push(pVideoData, nDataLength); return 0; } diff --git a/ABLMediaServer/MediaStreamSource.cpp b/ABLMediaServer/MediaStreamSource.cpp index 505003f..e7c1967 100644 --- a/ABLMediaServer/MediaStreamSource.cpp +++ b/ABLMediaServer/MediaStreamSource.cpp @@ -1258,12 +1258,13 @@ bool CMediaStreamSource::PushVideo(unsigned char* szVideo, int nLength, char* sz auto pClient = GetNetRevcBaseClient(nClient); if (pClient) { + m_bNoticeOnPublish = true; MessageNoticeStruct msgNotice; msgNotice.nClient = NetBaseNetType_HttpClient_on_publish; sprintf(msgNotice.szMsg, "{\"eventName\":\"on_publish\",\"id\":\"%d\",\"app\":\"%s\",\"stream\":\"%s\",\"schema\":\"%d\",\"mediaServerId\":\"%s\",\"networkType\":%d,\"key\":%llu,\"ip\":\"%s\" ,\"port\":%d,\"params\":\"%s\",\"vhost\":\"__defaultVhost__\"}", pClient->nClient, app, stream, pClient->netBaseNetType, ABL_MediaServerPort.mediaServerID, pClient->netBaseNetType, pClient->nClient, pClient->szClientIP, pClient->nClientPort, pClient->szPlayParams); pMessageNoticeFifo.push((unsigned char*)&msgNotice, sizeof(MessageNoticeStruct)); - m_bNoticeOnPublish = true; + } } else @@ -2523,21 +2524,19 @@ bool CMediaStreamSource::GetVideoWidthHeight(char* szVideoCodeName, unsigned ch { MessageNoticeStruct msgNotice; msgNotice.nClient = NetBaseNetType_HttpClient_on_stream_arrive; - sprintf(msgNotice.szMsg, "{\"eventName\":\"on_stream_arrive\",\"key\":%llu,\"app\":\"%s\",\"stream\":\"%s\",\"mediaServerId\":\"%s\",\"networkType\":%d,\"status\":%s,\"enable_hls\":%s,\"transcodingStatus\":%s,\"sourceURL\":\"%s\",\"networkType\":%d,\"readerCount\":%d,\"noneReaderDuration\":%d,\"videoCodec\":\"%s\",\"videoFrameSpeed\":%d,\"width\":%d,\"height\":%d,\"videoBitrate\":%d,\"audioCodec\":\"%s\",\"audioChannels\":%d,\"audioSampleRate\":%d,\"audioBitrate\":%d,\"url\":{\"rtsp\":\"rtsp://%s:%d/%s/%s\",\"rtmp\":\"rtmp://%s:%d/%s/%s\",\"http-flv\":\"http://%s:%d/%s/%s.flv\",\"ws-flv\":\"ws://%s:%d/%s/%s.flv\",\"http-mp4\":\"http://%s:%d/%s/%s.mp4\",\"http-hls\":\"http://%s:%d/%s/%s.m3u8\",\"webrtc\":\"http://%s:%d/webrtc-streamer.html?video=/%s/%s\"}}",nClient, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, ABL_MediaServerPort.mediaServerID, netBaseNetType, enable_mp4 == true ? "true" : "false", enable_hls == true ? "true" : "false", H265ConvertH264_enable == true ? "true" : "false", pClient->m_addStreamProxyStruct.url, pClient->netBaseNetType, mediaSendMap.size(), (int)0, + sprintf(msgNotice.szMsg, "{\"eventName\":\"on_stream_arrive\",\"key\":%llu,\"app\":\"%s\",\"stream\":\"%s\",\"mediaServerId\":\"%s\",\"networkType\":%d,\"status\":%s,\"enable_hls\":%s,\"transcodingStatus\":%s,\"sourceURL\":\"%s\",\"networkType\":%d,\"readerCount\":%d,\"noneReaderDuration\":%d,\"videoCodec\":\"%s\",\"videoFrameSpeed\":%d,\"width\":%d,\"height\":%d,\"videoBitrate\":%d,\"audioCodec\":\"%s\",\"audioChannels\":%d,\"audioSampleRate\":%d,\"audioBitrate\":%d,\"url\":{\"rtsp\":\"rtsp://%s:%d/%s/%s\",\"rtmp\":\"rtmp://%s:%d/%s/%s\",\"http-flv\":\"http://%s:%d/%s/%s.flv\",\"ws-flv\":\"ws://%s:%d/%s/%s.flv\",\"http-mp4\":\"http://%s:%d/%s/%s.mp4\",\"http-hls\":\"http://%s:%d/%s/%s.m3u8\"}}",nClient, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, ABL_MediaServerPort.mediaServerID, netBaseNetType, enable_mp4 == true ? "true" : "false", enable_hls == true ? "true" : "false", H265ConvertH264_enable == true ? "true" : "false", pClient->m_addStreamProxyStruct.url, pClient->netBaseNetType, mediaSendMap.size(), (int)0, m_mediaCodecInfo.szVideoName, m_mediaCodecInfo.nVideoFrameRate, m_mediaCodecInfo.nWidth, m_mediaCodecInfo.nHeight, m_mediaCodecInfo.nVideoBitrate, m_mediaCodecInfo.szAudioName, m_mediaCodecInfo.nChannels, m_mediaCodecInfo.nSampleRate, m_mediaCodecInfo.nAudioBitrate, ABL_szLocalIP, ABL_MediaServerPort.nRtspPort, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, ABL_szLocalIP, ABL_MediaServerPort.nRtmpPort, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, ABL_szLocalIP, ABL_MediaServerPort.nHttpFlvPort, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, ABL_szLocalIP, ABL_MediaServerPort.nWSFlvPort, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, ABL_szLocalIP, ABL_MediaServerPort.nHttpMp4Port, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, - ABL_szLocalIP, ABL_MediaServerPort.nHlsPort, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream, - ABL_szLocalIP, ABL_MediaServerPort.nWebRtcPort, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream); + ABL_szLocalIP, ABL_MediaServerPort.nHlsPort, pClient->m_addStreamProxyStruct.app, pClient->m_addStreamProxyStruct.stream); pMessageNoticeFifo.push((unsigned char*)&msgNotice, sizeof(MessageNoticeStruct)); bNoticeClientArriveFlag = true; } } - if (!(m_mediaCodecInfo.nWidth == 0 && m_mediaCodecInfo.nHeight == 0) || pVideoData == NULL || nDataLength <= 0 || !(strcmp(szVideoCodeName, "H264") == 0 || strcmp(szVideoCodeName, "H265") == 0) ) return false; diff --git a/ABLMediaServer/NetClientFFmpegRecv.cpp b/ABLMediaServer/NetClientFFmpegRecv.cpp index 10e8b81..9f80cb0 100644 --- a/ABLMediaServer/NetClientFFmpegRecv.cpp +++ b/ABLMediaServer/NetClientFFmpegRecv.cpp @@ -9,14 +9,16 @@ E-Mail 79941308@qq.com #include "stdafx.h" #include "NetClientFFmpegRecv.h" #ifdef USE_BOOST -extern CNetBaseThreadPool* RecordReplayThreadPool;//录像回放线程池 +extern CNetBaseThreadPool* RecordReplayThreadPool;//录像回放线程池 extern CMediaFifo pDisconnectBaseNetFifo; //清理断裂的链接 extern bool DeleteNetRevcBaseClient(NETHANDLE CltHandle); extern boost::shared_ptr GetNetRevcBaseClient(NETHANDLE CltHandle); extern boost::shared_ptr CreateMediaStreamSource(char* szURL, uint64_t nClient, MediaSourceType nSourceType, uint32_t nDuration, H265ConvertH264Struct h265ConvertH264Struct); extern bool DeleteMediaStreamSource(char* szURL); extern MediaServerPort ABL_MediaServerPort; -extern char ABL_MediaSeverRunPath[256]; //当前路径 +extern char ABL_MediaSeverRunPath[256] ; //当前路径 +extern CMediaFifo pMessageNoticeFifo; //消息通知FIFO + #else extern CNetBaseThreadPool* RecordReplayThreadPool;//录像回放线程池 @@ -27,9 +29,9 @@ extern std::shared_ptr CreateMediaStreamSource(char* szURL, extern bool DeleteMediaStreamSource(char* szURL); extern MediaServerPort ABL_MediaServerPort; extern char ABL_MediaSeverRunPath[256]; //当前路径 +extern CMediaFifo pMessageNoticeFifo; //消息通知FIFO #endif - extern int avpriv_mpeg4audio_sample_rates[]; #ifdef OS_System_Windows @@ -60,25 +62,24 @@ bool CNetClientFFmpegRecv::GetMediaShareURLFromFileName(char* szRecordFileName, nPos = strRecordFileName.rfind("/", strlen(szRecordFileName)); if (nPos > 0) { - memcpy(szTempFileName, szRecordFileName + nPos + 1, strlen(szRecordFileName) - nPos); + memcpy(szTempFileName, szRecordFileName + nPos+1, strlen(szRecordFileName) - nPos); szTempFileName[strlen(szTempFileName) - 4] = 0x00; sprintf(m_szShareMediaURL, "%s%s%s", szMediaURL, RecordFileReplaySplitter, szTempFileName); return true; - } - else - return false; + }else + return false; } //查找视频,音频格式 -int CNetClientFFmpegRecv::open_codec_context(int* stream_idx, AVCodecContext** dec_ctx, AVFormatContext* fmt_ctx, enum AVMediaType type) +int CNetClientFFmpegRecv::open_codec_context(int *stream_idx,AVCodecContext **dec_ctx, AVFormatContext *fmt_ctx, enum AVMediaType type) { int ret, stream_index; - AVStream* st; - const AVCodec* dec = NULL; + AVStream *st; + const AVCodec *dec = NULL; ret = av_find_best_stream(fmt_ctx, type, -1, -1, NULL, 0); if (ret < 0) { - WriteLog(Log_Debug, "Could not find %s stream in input file '%s'\n", av_get_media_type_string(type), szFileNameUTF8); + WriteLog(Log_Debug,"Could not find %s stream in input file '%s'\n",av_get_media_type_string(type), szFileNameUTF8); return ret; } else { @@ -89,7 +90,7 @@ int CNetClientFFmpegRecv::open_codec_context(int* stream_idx, AVCodecContext** d dec = avcodec_find_decoder(st->codecpar->codec_id); if (!dec) { - WriteLog(Log_Debug, "Failed to find %s codec\n", av_get_media_type_string(type)); + WriteLog(Log_Debug, "Failed to find %s codec\n",av_get_media_type_string(type)); return AVERROR(EINVAL); } @@ -160,7 +161,8 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, if (strstr(szIP, "rtsp://") != NULL) { AVDictionary* format_opts = NULL; - av_dict_set(&format_opts, "buffer_size", "2024000", 0); + av_dict_set(&format_opts, "buffer_size", "9924000", 0); + av_dict_set(&format_opts, "fifo_size", "9924000", 0); av_dict_set(&format_opts, "timeout", "5000000", 0); av_dict_set(&format_opts, "rtsp_transport", "tcp", 0); nRet2 = avformat_open_input(&pFormatCtx2, szIP, NULL, &format_opts); @@ -170,20 +172,20 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, { AVDictionary* format_opts = NULL; av_dict_set(&format_opts, "rw_timeout", "3000000", 0); //设置链接超时时间(us) - nRet2 = avformat_open_input(&pFormatCtx2, szIP, NULL, &format_opts); + nRet2 = avformat_open_input(&pFormatCtx2, szIP, NULL, &format_opts); av_dict_free(&format_opts); } - + if (nRet2 != 0) { av_strerror(nRet2, szFFmpegErrorMsg, sizeof(szFFmpegErrorMsg)); sprintf(szReadFileError, "connect %s failed ! Msg: %s ", szIP, szFFmpegErrorMsg); WriteLog(Log_Debug, "NetClientFFmpegRecv = %X ,nClient = %llu connect %s failed ,Msg : %s ", this, hClient, szIP, szFFmpegErrorMsg); pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); - return; + return ; } - //确定是否有媒体源 + //确定是否有媒体源 if (avformat_find_stream_info(pFormatCtx2, NULL) < 0) { strcpy(szReadFileError, "file is Not Media File ! "); @@ -197,13 +199,12 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, if (open_codec_context(&stream_isVideo, &video_dec_ctx, pFormatCtx2, AVMEDIA_TYPE_VIDEO) >= 0) { video_stream = pFormatCtx2->streams[stream_isVideo]; - if (video_stream->codecpar->codec_id == AV_CODEC_ID_H264) + if(video_stream->codecpar->codec_id == AV_CODEC_ID_H264) strcpy(mediaCodecInfo.szVideoName, "H264"); else if (video_stream->codecpar->codec_id == AV_CODEC_ID_H265) { strcpy(mediaCodecInfo.szVideoName, "H265"); - } - else + }else { strcpy(szReadFileError, "http-flv (h265) Video Codec Is Not Support ! "); WriteLog(Log_Debug, "NetClientFFmpegRecv = %X ,nClient = %llu ,video_stream->codecpar->codec_id = %d 视频格式不是H264、H265 ", this, hClient, video_stream->codecpar->codec_id); @@ -212,11 +213,18 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, return; } - mediaCodecInfo.nWidth = video_dec_ctx->width; + mediaCodecInfo.nWidth = video_dec_ctx->width; mediaCodecInfo.nHeight = video_dec_ctx->height; pix_fmt = video_dec_ctx->pix_fmt; + } + else + { + avformat_close_input(&pFormatCtx2); + WriteLog(Log_Debug, "CNetClientFFmpegRecv = %X ,nClient = %llu 文件中不存在视频、音频流 ", this, hClient); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient,sizeof(nClient)); //清理断裂的链接 + return; } - + //查找出音频源 if (open_codec_context(&stream_isAudio, &audio_dec_ctx, pFormatCtx2, AVMEDIA_TYPE_AUDIO) >= 0) { @@ -231,7 +239,7 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, strcpy(mediaCodecInfo.szAudioName, "MP3"); else if (audio_stream->codecpar->codec_id == AV_CODEC_ID_OPUS) strcpy(mediaCodecInfo.szAudioName, "OPUS"); - else + else strcpy(mediaCodecInfo.szAudioName, "UNKNOW"); mediaCodecInfo.nSampleRate = audio_stream->codecpar->sample_rate; //采样频率 @@ -270,16 +278,7 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, mediaCodecInfo.nBaseAddAudioTimeStamp = nInputAudioDelay; } } - - if (stream_isVideo == -1) - { - strcpy(szReadFileError, "rtmp http-flv (h265) Video Codec Is Not Support ! "); - WriteLog(Log_Debug, "NetClientFFmpegRecv = %X ,nClient = %llu ,http-flv、rtmp (h265) Video Codec Is Not Support ! ", this, hClient); - avformat_close_input(&pFormatCtx2); - pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); - return; - } - + packet2 = av_packet_alloc(); #ifdef FFMPEG6 @@ -291,13 +290,13 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, if (pFormatCtx2->streams[stream_isVideo]->codecpar->extradata_size > 0) { int ret; - codecpar = pFormatCtx2->streams[stream_isVideo]->codecpar; + codecpar = pFormatCtx2->streams[stream_isVideo]->codecpar; if (codecpar != NULL) { - if (strcmp(mediaCodecInfo.szVideoName, "H264") == 0) - buffersrc = (AVBitStreamFilter*)av_bsf_get_by_name("h264_mp4toannexb"); + if (strcmp(mediaCodecInfo.szVideoName,"H264") == 0) + buffersrc = (AVBitStreamFilter *)av_bsf_get_by_name("h264_mp4toannexb"); else if (strcmp(mediaCodecInfo.szVideoName, "H265") == 0) - buffersrc = (AVBitStreamFilter*)av_bsf_get_by_name("hevc_mp4toannexb"); + buffersrc = (AVBitStreamFilter *)av_bsf_get_by_name("hevc_mp4toannexb"); ret = av_bsf_alloc(buffersrc, &bsf_ctx); avcodec_parameters_copy(bsf_ctx->par_in, codecpar); ret = av_bsf_init(bsf_ctx); @@ -312,25 +311,6 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, //确定帧速度 mediaCodecInfo.nVideoFrameRate = 25;// video_stream->avg_frame_rate.num / video_stream->avg_frame_rate.den; - - //创建录像点播媒体源 - pMediaSource = CreateMediaStreamSource(m_szShareMediaURL, 0, MediaSourceType_LiveMedia, duration, m_h265ConvertH264Struct); - if (pMediaSource == NULL) - { - WriteLog(Log_Debug, "NetClientFFmpegRecv 创建媒体源失败 = %X ,nClient = %llu m_szShareMediaURL %s ", this, hClient, m_szShareMediaURL); - pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); - return; - } - strcpy(pMediaSource->m_mediaCodecInfo.szVideoName, mediaCodecInfo.szVideoName); - strcpy(pMediaSource->m_mediaCodecInfo.szAudioName, mediaCodecInfo.szAudioName); - pMediaSource->m_mediaCodecInfo.nSampleRate = mediaCodecInfo.nSampleRate; //采样频率 - pMediaSource->m_mediaCodecInfo.nChannels = mediaCodecInfo.nChannels; - pMediaSource->m_mediaCodecInfo.nVideoFrameRate = mediaCodecInfo.nVideoFrameRate; - if (strcmp(mediaCodecInfo.szAudioName, "AAC") == 0) - pMediaSource->m_mediaCodecInfo.nBaseAddAudioTimeStamp = nInputAudioDelay; - - strcpy(m_addStreamProxyStruct.app, pMediaSource->app); - strcpy(m_addStreamProxyStruct.stream, pMediaSource->stream); strcpy(m_addStreamProxyStruct.url, szIP); nAVType = nOldAVType = AVType_Audio; @@ -341,42 +321,42 @@ CNetClientFFmpegRecv::CNetClientFFmpegRecv(NETHANDLE hServer, NETHANDLE hClient, m_bPauseFlag = false; m_nStartTimestamp = 0; nReadVideoFrameCount = nReadAudioFrameCount = 0; - nVideoFirstPTS = 0; + nVideoFirstPTS = 0 ; nAudioFirstPTS = 0; - - bRestoreVideoFrameFlag = false;//是否需要恢复视频帧总数 - bRestoreAudioFrameFlag = false;//是否需要恢复音频帧总数 + + bRestoreVideoFrameFlag = false ;//是否需要恢复视频帧总数 + bRestoreAudioFrameFlag = false ;//是否需要恢复音频帧总数 mov_readerTime = GetTickCount64(); #ifdef WriteAACFileFlag char aacFile[256] = { 0 }; sprintf(aacFile, "%s%X.aac", ABL_MediaSeverRunPath, this); - fWriteAAC = fopen(aacFile, "wb"); + fWriteAAC = fopen(aacFile,"wb"); #endif - RecordReplayThreadPool->InsertIntoTask(nClient); + RecordReplayThreadPool->InsertIntoTask(nClient); } -CNetClientFFmpegRecv::~CNetClientFFmpegRecv() +CNetClientFFmpegRecv::~CNetClientFFmpegRecv() { if (!bResponseHttpFlag) {//回复代理拉流请求 bResponseHttpFlag = true; - sprintf(szResponseBody, "{\"code\":%d,\"memo\":\"Error : %s \",\"key\":%llu}", IndexApiCode_RequestFileNotFound, szReadFileError, hParent); + sprintf(szResponseBody, "{\"code\":%d,\"memo\":\"Error : %s \",\"key\":%llu}", IndexApiCode_RequestFileNotFound, szReadFileError,hParent); ResponseHttp(nClient_http, szResponseBody, false); } - WriteLog(Log_Debug, "CNetClientFFmpegRecv 析构函数 = %X ,nClient = %llu ", this, nClient); + WriteLog(Log_Debug, "CNetClientFFmpegRecv 析构函数 = %X ,nClient = %llu ", this, nClient); std::lock_guard lock(readRecordFileInputLock); if (pFormatCtx2 != NULL) { - if (video_dec_ctx) - avcodec_free_context(&video_dec_ctx); - if (audio_dec_ctx) - avcodec_free_context(&audio_dec_ctx); + if(video_dec_ctx) + avcodec_free_context(&video_dec_ctx); + if(audio_dec_ctx) + avcodec_free_context(&audio_dec_ctx); - avformat_close_input(&pFormatCtx2); + avformat_close_input(&pFormatCtx2); pFormatCtx2 = NULL; if (bsf_ctx != NULL) av_bsf_free(&bsf_ctx); @@ -385,21 +365,30 @@ CNetClientFFmpegRecv::~CNetClientFFmpegRecv() av_packet_free(&packet2); } + //码流没有达到通知 + if (ABL_MediaServerPort.hook_enable == 1 && pMediaSource == NULL) + { + MessageNoticeStruct msgNotice; + msgNotice.nClient = NetBaseNetType_HttpClient_on_stream_not_arrive; + sprintf(msgNotice.szMsg, "{\"eventName\":\"on_stream_not_arrive\",\"app\":\"%s\",\"stream\":\"%s\",\"mediaServerId\":\"%s\",\"networkType\":%d,\"key\":%llu}", m_addStreamProxyStruct.app, m_addStreamProxyStruct.stream, ABL_MediaServerPort.mediaServerID, netBaseNetType, hParent); + pMessageNoticeFifo.push((unsigned char*)&msgNotice, sizeof(MessageNoticeStruct)); + } + //删除分发源 if (strlen(m_szShareMediaURL) > 0) - DeleteMediaStreamSource(m_szShareMediaURL); + DeleteMediaStreamSource(m_szShareMediaURL); m_audioCacheFifo.FreeFifo(); #ifdef WriteAACFileFlag - fclose(fWriteAAC); + fclose(fWriteAAC); #endif - malloc_trim(0); + malloc_trim(0); } int CNetClientFFmpegRecv::InputNetData(NETHANDLE nServerHandle, NETHANDLE nClientHandle, uint8_t* pData, uint32_t nDataLength, void* address) { - return 0; + return 0 ; } int CNetClientFFmpegRecv::ProcessNetData() @@ -407,16 +396,37 @@ int CNetClientFFmpegRecv::ProcessNetData() std::lock_guard lock(readRecordFileInputLock); nRecvDataTimerBySecond = 0; - //修改媒体源的提供ID - if (pMediaSource->nClient == 0 && hParent > 0) + //创建录像点播媒体源 + if (pMediaSource == NULL) { + pMediaSource = CreateMediaStreamSource(m_szShareMediaURL, nClient, MediaSourceType_LiveMedia, duration, m_h265ConvertH264Struct); + if (pMediaSource == NULL) + { + WriteLog(Log_Debug, "NetClientFFmpegRecv 创建媒体源失败 = %X ,nClient = %llu m_szShareMediaURL %s ", this, nClient, m_szShareMediaURL); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); + return -1; + } + strcpy(pMediaSource->m_mediaCodecInfo.szVideoName, mediaCodecInfo.szVideoName); + strcpy(pMediaSource->m_mediaCodecInfo.szAudioName, mediaCodecInfo.szAudioName); + pMediaSource->m_mediaCodecInfo.nSampleRate = mediaCodecInfo.nSampleRate; //采样频率 + pMediaSource->m_mediaCodecInfo.nChannels = mediaCodecInfo.nChannels; + pMediaSource->m_mediaCodecInfo.nVideoFrameRate = mediaCodecInfo.nVideoFrameRate; + if (strcmp(mediaCodecInfo.szAudioName, "AAC") == 0) + pMediaSource->m_mediaCodecInfo.nBaseAddAudioTimeStamp = nInputAudioDelay; + + strcpy(m_addStreamProxyStruct.app, pMediaSource->app); + strcpy(m_addStreamProxyStruct.stream, pMediaSource->stream); + pMediaSource->nClient = hParent; //修改代理拉流成功,往后拉流断线后可以反复重连 auto pParentPtr = GetNetRevcBaseClient(hParent); if (pParentPtr && pParentPtr->bProxySuccessFlag == false) + { bProxySuccessFlag = pParentPtr->bProxySuccessFlag = true; - } + pParentPtr->SplitterAppStream(m_szShareMediaURL); + } +} if (!bResponseHttpFlag && nReadVideoFrameCount >= 5) {//回复代理拉流请求 @@ -428,7 +438,7 @@ int CNetClientFFmpegRecv::ProcessNetData() nCurrentDateTime = GetTickCount64(); if (m_bPauseFlag == true) { - //Sleep(2); + //Sleep(2); std::this_thread::sleep_for(std::chrono::milliseconds(2)); RecordReplayThreadPool->InsertIntoTask(nClient); return -1; @@ -438,8 +448,7 @@ int CNetClientFFmpegRecv::ProcessNetData() {//打开mp4文件后需要等待一段事件,否则读取文件会失败 if (nCurrentDateTime - mov_readerTime < nWaitTime) { - //Sleep(2); - std::this_thread::sleep_for(std::chrono::milliseconds(2)); + Sleep(2); RecordReplayThreadPool->InsertIntoTask(nClient); return 0; } @@ -511,12 +520,12 @@ int CNetClientFFmpegRecv::ProcessNetData() fflush(fWriteAAC); #endif m_audioCacheFifo.push(pAACBufferADTS, +packet2->size + 7); - } + } //获取AAC音频时间戳增量 if (mediaCodecInfo.nBaseAddAudioTimeStamp == 0) mediaCodecInfo.nBaseAddAudioTimeStamp = pMediaSource->m_mediaCodecInfo.nBaseAddAudioTimeStamp; - } } + } else if (strcmp(mediaCodecInfo.szAudioName, "G711_A") == 0 || strcmp(mediaCodecInfo.szAudioName, "G711_U") == 0) { nInputAudioDelay = (packet2->size / 80) * 10; @@ -538,8 +547,8 @@ int CNetClientFFmpegRecv::ProcessNetData() return -1; } nOldAVType = nAVType; - //Sleep(1); - std::this_thread::sleep_for(std::chrono::milliseconds(1)); + Sleep(1); + //加入音频 if (m_audioCacheFifo.GetSize() > 0) { @@ -584,12 +593,12 @@ bool CNetClientFFmpegRecv::UpdatePauseFlag(bool bFlag) bool CNetClientFFmpegRecv::ReaplyFileSeek(uint64_t nTimestamp) { std::lock_guard lock(readRecordFileInputLock); - if (m_bPauseFlag == true) - return false; - if (nTimestamp > duration) + if ( m_bPauseFlag == true) + return false; + if (nTimestamp > duration) { - WriteLog(Log_Debug, "ReaplyFileSeek 拖动时间戳超出文件最大时长 ,nClient = %llu ,nTimestamp = %llu ,duration = %d ", nClient, nTimestamp, duration); - return false; + WriteLog(Log_Debug, "ReaplyFileSeek 拖动时间戳超出文件最大时长 ,nClient = %llu ,nTimestamp = %llu ,duration = %d ", nClient, nTimestamp, duration ); + return false; } int nRet = av_seek_frame(pFormatCtx2, -1, nTimestamp * 1000000, AVSEEK_FLAG_BACKWARD); @@ -615,39 +624,40 @@ void CNetClientFFmpegRecv::AddADTSHeadToAAC(unsigned char* szData, int nAACLeng memcpy(pAACBufferADTS + 7, szData, nAACLength); } -int CNetClientFFmpegRecv::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, char* szVideoCodec) +int CNetClientFFmpegRecv::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, char* szVideoCodec) { - return 0; + return 0 ; } -int CNetClientFFmpegRecv::PushAudio(uint8_t* pAudioData, uint32_t nDataLength, char* szAudioCodec, int nChannels, int SampleRate) +int CNetClientFFmpegRecv::PushAudio(uint8_t* pAudioData, uint32_t nDataLength, char* szAudioCodec, int nChannels, int SampleRate) { - return 0; + return 0 ; } -int CNetClientFFmpegRecv::SendVideo() +int CNetClientFFmpegRecv::SendVideo() { - return 0; + return 0 ; } -int CNetClientFFmpegRecv::SendAudio() +int CNetClientFFmpegRecv::SendAudio() { - return 0; + return 0 ; } -int CNetClientFFmpegRecv::SendFirstRequst() +int CNetClientFFmpegRecv::SendFirstRequst() { - return 0; + return 0 ; } -bool CNetClientFFmpegRecv::RequestM3u8File() +bool CNetClientFFmpegRecv::RequestM3u8File() { - - return true; + + return true ; } + \ No newline at end of file diff --git a/ABLMediaServer/NetClientReadLocalMediaFile.cpp b/ABLMediaServer/NetClientReadLocalMediaFile.cpp index 2aaddf1..f9112b6 100644 --- a/ABLMediaServer/NetClientReadLocalMediaFile.cpp +++ b/ABLMediaServer/NetClientReadLocalMediaFile.cpp @@ -19,7 +19,6 @@ extern boost::shared_ptr CreateMediaStreamSource(char* szURL extern std::shared_ptr CreateMediaStreamSource(char* szURL, uint64_t nClient, MediaSourceType nSourceType, uint32_t nDuration, H265ConvertH264Struct h265ConvertH264Struct); #endif - extern bool DeleteMediaStreamSource(char* szURL); extern MediaServerPort ABL_MediaServerPort; extern char ABL_MediaSeverRunPath[256] ; //当前路径 @@ -233,6 +232,13 @@ CNetClientReadLocalMediaFile::CNetClientReadLocalMediaFile(NETHANDLE hServer, NE mediaCodecInfo.nHeight = video_dec_ctx->height; pix_fmt = video_dec_ctx->pix_fmt; } + else + { + avformat_close_input(&pFormatCtx2); + WriteLog(Log_Debug, "CNetClientReadLocalMediaFile = %X ,nClient = %llu 文件中不存在视频、音频流 ", this, hClient); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient,sizeof(nClient)); //清理断裂的链接 + return; + } //查找出音频源 if (open_codec_context(&stream_isAudio, &audio_dec_ctx, pFormatCtx2, AVMEDIA_TYPE_AUDIO) >= 0) diff --git a/ABLMediaServer/NetClientRecvRtsp.cpp b/ABLMediaServer/NetClientRecvRtsp.cpp index 73c3ae3..cf9d9f0 100644 --- a/ABLMediaServer/NetClientRecvRtsp.cpp +++ b/ABLMediaServer/NetClientRecvRtsp.cpp @@ -948,7 +948,7 @@ void CNetClientRecvRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt } else if (memcmp(pRecvData, "TEARDOWN", 8) == 0 && strstr((char*)pRecvData, "\r\n\r\n") != NULL) { - WriteLog(Log_Debug, "收到断开 TEARDOWN 命令,立即执行删除 nClient = %llu ", nClient); + WriteLog(Log_Debug, "收到 TEARDOWN 命令,立即执行删除 nClient = %llu ", nClient); bRunFlag = false; DeleteNetRevcBaseClient(nClient); } diff --git a/ABLMediaServer/NetClientSendRtsp.cpp b/ABLMediaServer/NetClientSendRtsp.cpp index 0c48488..7cb116f 100644 --- a/ABLMediaServer/NetClientSendRtsp.cpp +++ b/ABLMediaServer/NetClientSendRtsp.cpp @@ -50,7 +50,7 @@ extern void LIBNET_CALLMETHOD onread(NETHANDLE srvhandle, extern void LIBNET_CALLMETHOD onclose(NETHANDLE srvhandle, NETHANDLE clihandle); -CNetClientSendRtsp::CNetClientSendRtsp(NETHANDLE hServer, NETHANDLE hClient, char* szIP, unsigned short nPort, char* szShareMediaURL) +CNetClientSendRtsp::CNetClientSendRtsp(NETHANDLE hServer, NETHANDLE hClient, char* szIP, unsigned short nPort,char* szShareMediaURL) { nServer = hServer; nClient = hClient; @@ -70,7 +70,7 @@ CNetClientSendRtsp::CNetClientSendRtsp(NETHANDLE hServer, NETHANDLE hClient, cha netDataCacheLength = 0;//网络数据缓存大小 nNetStart = nNetEnd = 0; //网络数据起始位置\结束位置 - MaxNetDataCacheCount = MaxNetDataCacheBufferLength; + MaxNetDataCacheCount = MaxNetDataCacheBufferLength ; data_Length = 0; nRecvLength = 0; @@ -82,7 +82,7 @@ CNetClientSendRtsp::CNetClientSendRtsp(NETHANDLE hServer, NETHANDLE hClient, cha m_bHaveSPSPPSFlag = false; m_nSpsPPSLength = 0; - memset(s_extra_data, 0x00, sizeof(s_extra_data)); + memset(s_extra_data,0x00,sizeof(s_extra_data)); extra_data_size = 0; RtspProtectArrayOrder = 0; @@ -90,8 +90,8 @@ CNetClientSendRtsp::CNetClientSendRtsp(NETHANDLE hServer, NETHANDLE hClient, cha memset((char*)&RtspProtectArray[i], 0x00, sizeof(RtspProtectArray[i])); for (int i = 0; i < MaxRtpHandleCount; i++) - hRtpHandle[i] = 0; - + hRtpHandle[i] = 0 ; + for (int i = 0; i < 3; i++) bExitProcessFlagArray[i] = true; @@ -109,7 +109,7 @@ CNetClientSendRtsp::CNetClientSendRtsp(NETHANDLE hServer, NETHANDLE hClient, cha nMediaCount = 0; #ifdef WriteRtpDepacketFileFlag fWriteRtpVideo = fopen("d:\\rtspRecv.264", "wb"); - fWriteRtpAudio = fopen("d:\\rtspRecv.aac", "wb"); + fWriteRtpAudio = fopen("d:\\rtspRecv.aac", "wb"); bStartWriteFlag = false; #endif bRunFlag = true; @@ -120,10 +120,10 @@ CNetClientSendRtsp::CNetClientSendRtsp(NETHANDLE hServer, NETHANDLE hClient, cha CNetClientSendRtsp::~CNetClientSendRtsp() { - WriteLog(Log_Debug, "CNetClientSendRtsp 等待任务退出 nTime = %llu, nClient = %llu ", GetTickCount64(), nClient); + WriteLog(Log_Debug, "CNetClientSendRtsp 等待任务退出 nTime = %llu, nClient = %llu ",GetTickCount64(), nClient); bRunFlag = false; - std::lock_guard lock(businessProcMutex); - + std::lock_guard lock(businessProcMutex); + for (int i = 0; i < 3; i++) { while (!bExitProcessFlagArray[i]) @@ -131,14 +131,14 @@ CNetClientSendRtsp::~CNetClientSendRtsp() //Sleep(5); } WriteLog(Log_Debug, "CNetClientSendRtsp 任务退出完毕 nTime = %llu, nClient = %llu ", GetTickCount64(), nClient); - + #ifdef WriteRtpDepacketFileFlag - if (fWriteRtpVideo) - fclose(fWriteRtpVideo); - if (fWriteRtpAudio) - fclose(fWriteRtpAudio); + if(fWriteRtpVideo) + fclose(fWriteRtpVideo); + if(fWriteRtpAudio) + fclose(fWriteRtpAudio); #endif - + if (hRtpVideo != 0) { rtp_packet_stop(hRtpVideo); @@ -158,7 +158,7 @@ CNetClientSendRtsp::~CNetClientSendRtsp() int CNetClientSendRtsp::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, char* szVideoCodec) { nRecvDataTimerBySecond = 0; - if (!bRunFlag || m_addPushProxyStruct.disableVideo[0] != 0x30) + if (!bRunFlag || m_addPushProxyStruct.disableVideo[0] != 0x30 ) return -1; std::lock_guard lock(businessProcMutex); @@ -244,7 +244,7 @@ int CNetClientSendRtsp::InputNetData(NETHANDLE nServerHandle, NETHANDLE nClientH nNetStart = 0; nNetEnd = netDataCacheLength; - if (MaxNetDataCacheCount - nNetEnd < nDataLength) + if (MaxNetDataCacheCount - nNetEnd < nDataLength) { nNetStart = nNetEnd = netDataCacheLength = 0; WriteLog(Log_Debug, "CNetClientSendRtsp = %X nClient = %llu 数据异常 , 执行删除", this, nClient); @@ -262,7 +262,7 @@ int CNetClientSendRtsp::InputNetData(NETHANDLE nServerHandle, NETHANDLE nClientH netDataCacheLength += nDataLength; nNetEnd += nDataLength; } - return 0; + return 0 ; } //读取网络数据 ,模拟原来底层网络库读取函数 @@ -272,24 +272,24 @@ int32_t CNetClientSendRtsp::XHNetSDKRead(NETHANDLE clihandle, uint8_t* buffer, bExitProcessFlagArray[0] = false; while (!bIsInvalidConnectFlag && bRunFlag) { - if (netDataCacheLength >= *buffsize) + if (netDataCacheLength >= *buffsize) { memcpy(buffer, netDataCache + nNetStart, *buffsize); nNetStart += *buffsize; netDataCacheLength -= *buffsize; - + bExitProcessFlagArray[0] = true; - return 0; + return 0; } // Sleep(10); std::this_thread::sleep_for(std::chrono::milliseconds(10)); - nWaitCount++; + nWaitCount ++; if (nWaitCount >= 100 * 3) break; } bExitProcessFlagArray[0] = true; - return -1; + return -1; } bool CNetClientSendRtsp::ReadRtspEnd() @@ -331,7 +331,7 @@ bool CNetClientSendRtsp::ReadRtspEnd() int CNetClientSendRtsp::FindHttpHeadEndFlag() { if (data_Length <= 0) - return -1; + return -1 ; for (int i = 0; i < data_Length; i++) { @@ -402,7 +402,7 @@ void CNetClientSendRtsp::GetHttpModemHttpURL(char* szMedomHttpURL) } } -//把http头数据填充到结构中 + //把http头数据填充到结构中 int CNetClientSendRtsp::FillHttpHeadToStruct() { RtspProtectArrayOrder = 0; @@ -430,7 +430,7 @@ int CNetClientSendRtsp::FillHttpHeadToStruct() memset(RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szKey, 0x00, sizeof(RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szKey));//要清空 memset(RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szValue, 0x00, sizeof(RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szValue));//要清空 - memcpy(RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szKey, szTemp, nFlagLength); + memcpy(RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szKey, szTemp, nFlagLength); memcpy(RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szValue, szTemp + nFlagLength + 2, strlen(szTemp) - nFlagLength - 2); strcpy(szKey, RtspProtectArray[RtspProtectArrayOrder].rtspField[nKeyCount].szKey); @@ -455,14 +455,14 @@ int CNetClientSendRtsp::FillHttpHeadToStruct() else {//保存 http 方法、URL GetHttpModemHttpURL(szTemp); - } + } nPos = i + 2; } } return true; -} +} bool CNetClientSendRtsp::GetFieldValue(char* szFieldName, char* szFieldValue) { @@ -490,7 +490,7 @@ int CNetClientSendRtsp::GetRtspPathCount(char* szRtspURL) string strCurRtspURL = szRtspURL; int nPos1, nPos2; int nPathCount = 0; - nPos1 = strCurRtspURL.find("//", 0); + nPos1 = strCurRtspURL.find("//", 0); if (nPos1 < 0) return 0;//地址非法 @@ -500,7 +500,7 @@ int CNetClientSendRtsp::GetRtspPathCount(char* szRtspURL) if (nPos1 >= 0) { nPos1 += 1; - nPathCount++; + nPathCount ++; } else break; @@ -512,40 +512,40 @@ int CNetClientSendRtsp::GetRtspPathCount(char* szRtspURL) void Video_rtp_packet_callback_func_send(_rtp_packet_cb* cb) { CNetClientSendRtsp* pRtspClient = (CNetClientSendRtsp*)cb->userdata; - if (pRtspClient->bRunFlag) - pRtspClient->ProcessRtpVideoData(cb->data, cb->datasize); + if(pRtspClient->bRunFlag) + pRtspClient->ProcessRtpVideoData(cb->data, cb->datasize); } //rtp 打包回调音频 void Audio_rtp_packet_callback_func_send(_rtp_packet_cb* cb) { CNetClientSendRtsp* pRtspClient = (CNetClientSendRtsp*)cb->userdata; - if (pRtspClient->bRunFlag) - pRtspClient->ProcessRtpAudioData(cb->data, cb->datasize); + if(pRtspClient->bRunFlag) + pRtspClient->ProcessRtpAudioData(cb->data, cb->datasize); } -void CNetClientSendRtsp::ProcessRtpVideoData(unsigned char* pRtpVideo, int nDataLength) +void CNetClientSendRtsp::ProcessRtpVideoData(unsigned char* pRtpVideo,int nDataLength) { - if ((MaxRtpSendVideoMediaBufferLength - nSendRtpVideoMediaBufferLength < nDataLength + 4) && nSendRtpVideoMediaBufferLength > 0) + if ((MaxRtpSendVideoMediaBufferLength - nSendRtpVideoMediaBufferLength < nDataLength + 4) && nSendRtpVideoMediaBufferLength > 0 ) {//剩余空间不够存储 ,防止出错 SumSendRtpMediaBuffer(szSendRtpVideoMediaBuffer, nSendRtpVideoMediaBufferLength); - nSendRtpVideoMediaBufferLength = 0; + nSendRtpVideoMediaBufferLength = 0; } memcpy((char*)&nCurrentVideoTimestamp, pRtpVideo + 4, sizeof(uint32_t)); - if (nStartVideoTimestamp != VideoStartTimestampFlag && nStartVideoTimestamp != nCurrentVideoTimestamp && nSendRtpVideoMediaBufferLength > 0) + if (nStartVideoTimestamp != VideoStartTimestampFlag && nStartVideoTimestamp != nCurrentVideoTimestamp && nSendRtpVideoMediaBufferLength > 0) {//产生一帧新的视频 //WriteLog(Log_Debug, "CNetClientSendRtsp= %X, 发送一帧视频 ,Length = %d ", this, nSendRtpVideoMediaBufferLength); SumSendRtpMediaBuffer(szSendRtpVideoMediaBuffer, nSendRtpVideoMediaBufferLength); nSendRtpVideoMediaBufferLength = 0; } - + szSendRtpVideoMediaBuffer[nSendRtpVideoMediaBufferLength + 0] = '$'; szSendRtpVideoMediaBuffer[nSendRtpVideoMediaBufferLength + 1] = 0; nVideoRtpLen = htons(nDataLength); memcpy(szSendRtpVideoMediaBuffer + (nSendRtpVideoMediaBufferLength + 2), (unsigned char*)&nVideoRtpLen, sizeof(nVideoRtpLen)); - memcpy(szSendRtpVideoMediaBuffer + (nSendRtpVideoMediaBufferLength + 4), pRtpVideo, nDataLength); - + memcpy(szSendRtpVideoMediaBuffer + (nSendRtpVideoMediaBufferLength + 4), pRtpVideo, nDataLength); + nStartVideoTimestamp = nCurrentVideoTimestamp; nSendRtpVideoMediaBufferLength += nDataLength + 4; } @@ -553,7 +553,7 @@ void CNetClientSendRtsp::ProcessRtpAudioData(unsigned char* pRtpAudio, int nData { if (hRtpVideo != 0) { - if ((MaxRtpSendAudioMediaBufferLength - nSendRtpAudioMediaBufferLength < nDataLength + 4) && nSendRtpAudioMediaBufferLength > 0) + if ((MaxRtpSendAudioMediaBufferLength - nSendRtpAudioMediaBufferLength < nDataLength + 4) && nSendRtpAudioMediaBufferLength > 0 ) {//剩余空间不够存储 ,防止出错 SumSendRtpMediaBuffer(szSendRtpAudioMediaBuffer, nSendRtpAudioMediaBufferLength); @@ -567,13 +567,13 @@ void CNetClientSendRtsp::ProcessRtpAudioData(unsigned char* pRtpAudio, int nData memcpy(szSendRtpAudioMediaBuffer + (nSendRtpAudioMediaBufferLength + 2), (unsigned char*)&nAudioRtpLen, sizeof(nAudioRtpLen)); memcpy(szSendRtpAudioMediaBuffer + (nSendRtpAudioMediaBufferLength + 4), pRtpAudio, nDataLength); - nSendRtpAudioMediaBufferLength += nDataLength + 4; - nCalcAudioFrameCount++; + nSendRtpAudioMediaBufferLength += nDataLength + 4; + nCalcAudioFrameCount ++; - if (nCalcAudioFrameCount >= 3 && nSendRtpAudioMediaBufferLength > 0) + if (nCalcAudioFrameCount >= 3 && nSendRtpAudioMediaBufferLength > 0 ) { SumSendRtpMediaBuffer(szSendRtpAudioMediaBuffer, nSendRtpAudioMediaBufferLength); - nSendRtpAudioMediaBufferLength = 0; + nSendRtpAudioMediaBufferLength = 0; nCalcAudioFrameCount = 0; } } @@ -594,17 +594,17 @@ void CNetClientSendRtsp::ProcessRtpAudioData(unsigned char* pRtpAudio, int nData void CNetClientSendRtsp::SumSendRtpMediaBuffer(unsigned char* pRtpMedia, int nRtpLength) { std::lock_guard lock(MediaSumRtpMutex); - + if (bRunFlag) { nSendRet = XHNetSDK_Write(nClient, pRtpMedia, nRtpLength, 1); if (nSendRet != 0) { - nSendRtpFailCount++; + nSendRtpFailCount ++ ; //WriteLog(Log_Debug, "发送rtp 包失败 ,累计次数 nSendRtpFailCount = %d 次 ,nClient = %llu ", nSendRtpFailCount, nClient); if (nSendRtpFailCount >= 30) { - bRunFlag = false; + bRunFlag = false; WriteLog(Log_Debug, "发送rtp 包失败 ,累计次数 已经达到 nSendRtpFailCount = %d 次,即将删除 ,nClient = %llu ", nSendRtpFailCount, nClient); pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); } @@ -622,7 +622,7 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd //视频 nVideoSSRC = rand(); memset((char*)&optionVideo, 0x00, sizeof(optionVideo)); - if (strcmp(sdpContent.szVideoName, "H264") == 0) + if (strcmp(sdpContent.szVideoName,"H264") == 0) { optionVideo.streamtype = e_rtppkt_st_h264; if (bGetFlag) @@ -630,7 +630,7 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd else nVideoPayload = 96; sprintf(szRtspSDPContent, "v=0\r\no=- 0 0 IN IP4 127.0.0.1\r\ns=No Name\r\nc=IN IP4 190.15.240.36\r\nt=0 0\r\na=tool:libavformat 55.19.104\r\nm=video 6000 RTP/AVP %d\r\nb=AS:832\r\na=rtpmap:%d H264/90000\r\na=fmtp:%d packetization-mode=1\r\na=control:streamid=0\r\n", nVideoPayload, nVideoPayload, nVideoPayload); - nMediaCount++; + nMediaCount ++; } else if (strcmp(sdpContent.szVideoName, "H265") == 0) { @@ -638,7 +638,7 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd if (bGetFlag) nVideoPayload = sdpContent.nVidePayload; else - nVideoPayload = 97; + nVideoPayload = 97; sprintf(szRtspSDPContent, "v=0\r\no=- 0 0 IN IP4 127.0.0.1\r\ns=No Name\r\nc=IN IP4 190.15.240.36\r\nt=0 0\r\na=tool:libavformat 55.19.104\r\nm=video 6000 RTP/AVP %d\r\nb=AS:3007\r\na=rtpmap:%d H265/90000\r\na=fmtp:%d packetization-mode=1\r\na=control:streamid=0\r\n", nVideoPayload, nVideoPayload, nVideoPayload); nMediaCount++; } @@ -653,13 +653,13 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd nRet = rtp_packet_start(Video_rtp_packet_callback_func_send, (void*)this, &hRtpVideo); if (nRet != e_rtppkt_err_noerror) { - WriteLog(Log_Debug, "CNetClientSendRtsp = %X ,创建视频rtp打包失败,nClient = %llu, nRet = %d", this, nClient, nRet); + WriteLog(Log_Debug, "CNetClientSendRtsp = %X ,创建视频rtp打包失败,nClient = %llu, nRet = %d", this,nClient, nRet); return false; } - optionVideo.handle = hRtpVideo; + optionVideo.handle = hRtpVideo; optionVideo.ssrc = nVideoSSRC; optionVideo.mediatype = e_rtppkt_mt_video; - optionVideo.payload = nVideoPayload; + optionVideo.payload = nVideoPayload; optionVideo.ttincre = 90000 / mediaCodecInfo.nVideoFrameRate; //视频时间戳增量 inputVideo.handle = hRtpVideo; @@ -672,8 +672,8 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd return false; } } - memset(szRtspAudioSDP, 0x00, sizeof(szRtspAudioSDP)); - + memset(szRtspAudioSDP, 0x00, sizeof(szRtspAudioSDP)); + memset((char*)&optionAudio, 0x00, sizeof(optionAudio)); if (strcmp(sdpContent.szAudioName, "G711_A") == 0 && ABL_MediaServerPort.nEnableAudio == 1) { @@ -682,11 +682,11 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd if (bGetFlag) nAudioPayload = sdpContent.nAudioPayload; else - nAudioPayload = 8; - if (hRtpVideo != 0) - sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMA/%d\r\na=control:streamid=1\r\na=framerate:25\r\n", nAudioPayload, nAudioPayload, 8000); + nAudioPayload = 8; + if(hRtpVideo != 0) + sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMA/%d\r\na=control:streamid=1\r\na=framerate:25\r\n",nAudioPayload, nAudioPayload, 8000); else - sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMA/%d\r\na=control:streamid=0\r\na=framerate:25\r\n", nAudioPayload, nAudioPayload, 8000); + sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMA/%d\r\na=control:streamid=0\r\na=framerate:25\r\n", nAudioPayload, nAudioPayload, 8000); nMediaCount++; } @@ -699,24 +699,24 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd else nAudioPayload = 0; if (hRtpVideo != 0) - sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMU/%d\r\na=control:streamid=1\r\na=framerate:25\r\n", nAudioPayload, nAudioPayload, 8000); + sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMU/%d\r\na=control:streamid=1\r\na=framerate:25\r\n",nAudioPayload, nAudioPayload, 8000); else - sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMU/%d\r\na=control:streamid=0\r\na=framerate:25\r\n", nAudioPayload, nAudioPayload, 8000); + sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\nb=AS:50\r\na=recvonly\r\na=rtpmap:%d PCMU/%d\r\na=control:streamid=0\r\na=framerate:25\r\n", nAudioPayload, nAudioPayload, 8000); nMediaCount++; } else if (strcmp(sdpContent.szAudioName, "AAC") == 0 && ABL_MediaServerPort.nEnableAudio == 1) { - optionAudio.ttincre = 1024;//aac 的长度增量 + optionAudio.ttincre = 1024 ;//aac 的长度增量 optionAudio.streamtype = e_rtppkt_st_aac; if (bGetFlag) nAudioPayload = sdpContent.nAudioPayload; else nAudioPayload = 104; if (hRtpVideo != 0) - sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\na=rtpmap:%d MPEG4-GENERIC/%d/%d\r\na=fmtp:%d profile-level-id=15; streamtype=5; mode=AAC-hbr; config=1408;SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;\r\na=control:streamid=1\r\n", nAudioPayload, nAudioPayload, sdpContent.nSampleRate, sdpContent.nChannels, nAudioPayload); + sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\na=rtpmap:%d MPEG4-GENERIC/%d/%d\r\na=fmtp:%d profile-level-id=15; streamtype=5; mode=AAC-hbr; config=1408;SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;\r\na=control:streamid=1\r\n",nAudioPayload, nAudioPayload, sdpContent.nSampleRate, sdpContent.nChannels, nAudioPayload); else - sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\na=rtpmap:%d MPEG4-GENERIC/%d/%d\r\na=fmtp:%d profile-level-id=15; streamtype=5; mode=AAC-hbr; config=1408;SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;\r\na=control:streamid=0\r\n", nAudioPayload, nAudioPayload, sdpContent.nSampleRate, sdpContent.nChannels, nAudioPayload); + sprintf(szRtspAudioSDP, "m=audio 0 RTP/AVP %d\r\na=rtpmap:%d MPEG4-GENERIC/%d/%d\r\na=fmtp:%d profile-level-id=15; streamtype=5; mode=AAC-hbr; config=1408;SizeLength=13; IndexLength=3; IndexDeltaLength=3; Profile=1;\r\na=control:streamid=0\r\n", nAudioPayload, nAudioPayload, sdpContent.nSampleRate, sdpContent.nChannels, nAudioPayload); nMediaCount++; } @@ -727,7 +727,7 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd int32_t nRet = rtp_packet_start(Audio_rtp_packet_callback_func_send, (void*)this, &hRtpAudio); if (nRet != e_rtppkt_err_noerror) { - WriteLog(Log_Debug, "CNetClientSendRtsp = %X ,创建音频rtp打包失败 ,nClient = %llu, nRet = %d", this, nClient, nRet); + WriteLog(Log_Debug, "CNetClientSendRtsp = %X ,创建音频rtp打包失败 ,nClient = %llu, nRet = %d", this,nClient, nRet); return false; } optionAudio.handle = hRtpAudio; @@ -735,15 +735,15 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd optionAudio.mediatype = e_rtppkt_mt_audio; optionAudio.payload = nAudioPayload; - inputAudio.handle = hRtpAudio; + inputAudio.handle = hRtpAudio; inputAudio.ssrc = optionAudio.ssrc; rtp_packet_setsessionopt(&optionAudio); if (hRtpVideo != 0) - strcat(szRtspSDPContent, szRtspAudioSDP); + strcat(szRtspSDPContent, szRtspAudioSDP); else - strcpy(szRtspSDPContent, szRtspAudioSDP); + strcpy(szRtspSDPContent, szRtspAudioSDP); } if (bGetFlag) @@ -757,11 +757,11 @@ bool CNetClientSendRtsp::GetRtspSDPFromMediaStreamSource(RtspSDPContentStruct sd void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLength) { #if 0 - if (nDataLength < 1024) + if (nDataLength < 1024) WriteLog(Log_Debug, "RecvData \r\n%s \r\n", pRecvData); #endif - if (memcmp(data_, "RTSP/1.0 401", 12) == 0 && nRtspProcessStep == RtspProcessStep_OPTIONS && strstr((char*)pRecvData, "\r\n\r\n") != NULL) + if (memcmp(data_, "RTSP/1.0 401", 12) == 0 && nRtspProcessStep == RtspProcessStep_OPTIONS && strstr((char*)pRecvData, "\r\n\r\n") != NULL) {//大华摄像机,OPTIONS需要发送md5方式验证 if (!GetWWW_Authenticate()) { @@ -777,7 +777,7 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt auto pMediaSource = GetMediaStreamSource(m_szShareMediaURL, true); if (pMediaSource == NULL) { - WriteLog(Log_Debug, "CNetClientSendRtsp = %X ,媒体源 %s 不存在 , nClient = %llu ", this, m_szShareMediaURL, nClient); + WriteLog(Log_Debug, "CNetClientSendRtsp = %X ,媒体源 %s 不存在 , nClient = %llu ", this, m_szShareMediaURL,nClient); DeleteNetRevcBaseClient(nClient); return; } @@ -807,7 +807,7 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt } SendANNOUNCE(AuthenticateType); - } + } else if (memcmp(data_, "RTSP/1.0 200", 12) == 0 && nRtspProcessStep == RtspProcessStep_ANNOUNCE && strstr((char*)pRecvData, "\r\n\r\n") != NULL) { GetFieldValue("Session", szSessionID); @@ -831,7 +831,7 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt strcpy(szSessionID, "1000005"); } SendSetup(AuthenticateType); - } + } else if (memcmp(data_, "RTSP/1.0 200", 12) == 0 && nRtspProcessStep == RtspProcessStep_SETUP && strstr((char*)pRecvData, "\r\n\r\n") != NULL) { if (nMediaCount == 1) @@ -849,7 +849,7 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt } nRecvLength = nHttpHeadEndLength = 0; - } + } else if (memcmp(data_, "RTSP/1.0 200", 12) == 0 && nRtspProcessStep == RtspProcessStep_RECORD && strstr((char*)pRecvData, "\r\n\r\n") != NULL) { WriteLog(Log_Debug, "收到 RECORD 回复命令,rtsp交互完毕 nClient = %llu ", nClient); @@ -858,11 +858,10 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt { WriteLog(Log_Debug, "CNetClientSendRtsp = %X nClient = %llu ,不存在媒体源 %s", this, nClient, m_szShareMediaURL); DeleteNetRevcBaseClient(nClient); - return; + return ; } m_videoFifo.InitFifo(MaxLiveingVideoFifoBufferLength); m_audioFifo.InitFifo(MaxLiveingAudioFifoBufferLength); - pMediaSource->AddClientToMap(nClient); bUpdateVideoFrameSpeedFlag = true; //代表成功交互 @@ -876,10 +875,10 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt if (pParentPtr && pParentPtr->bProxySuccessFlag == false) bProxySuccessFlag = pParentPtr->bProxySuccessFlag = true; - } + } else if (memcmp(pRecvData, "TEARDOWN", 8) == 0 && strstr((char*)pRecvData, "\r\n\r\n") != NULL) { - WriteLog(Log_Debug, "收到断开 TEARDOWN 命令,立即执行删除 nClient = %llu ", nClient); + WriteLog(Log_Debug, "收到 TEARDOWN 命令,立即执行删除 nClient = %llu ", nClient); bRunFlag = false; DeleteNetRevcBaseClient(nClient); } @@ -892,7 +891,7 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt nSendRet = XHNetSDK_Write(nClient, (unsigned char*)szResponseBuffer, strlen(szResponseBuffer), 1); if (nSendRet != 0) pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); - } + } else { //回复http请求 @@ -900,7 +899,7 @@ void CNetClientSendRtsp::InputRtspData(unsigned char* pRecvData, int nDataLengt ResponseHttp(nClient_http, szResponseBody, false); bIsInvalidConnectFlag = true; //确认为非法连接 - WriteLog(Log_Debug, "非法的rtsp 命令,立即执行删除 nClient = %llu , \r\n%s ", nClient, pRecvData); + WriteLog(Log_Debug, "非法的rtsp 命令,立即执行删除 nClient = %llu , \r\n%s ",nClient, pRecvData); //删除掉代理拉流、推流 pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); @@ -976,11 +975,11 @@ int CNetClientSendRtsp::ProcessNetData() { std::lock_guard lock(netDataLock); - bExitProcessFlagArray[2] = false; + bExitProcessFlagArray[2] = false; tRtspProcessStartTime = GetTickCount64(); while (!bIsInvalidConnectFlag && bRunFlag && netDataCacheLength > 4) { - uint32_t nReadLength = 4; + uint32_t nReadLength = 4; data_Length = 0; int nRet = XHNetSDKRead(nClient, data_ + data_Length, &nReadLength, true, true); @@ -1000,7 +999,7 @@ int CNetClientSendRtsp::ProcessNetData() } else if (data_[1] == 0x02) { - nPrintCount++; + nPrintCount ++; } else if (data_[1] == 0x01) {//收到RTCP包,需要回复rtcp报告包 @@ -1009,7 +1008,7 @@ int CNetClientSendRtsp::ProcessNetData() } else if (data_[1] == 0x03) {//收到RTCP包,需要回复rtcp报告包 - SendRtcpReportData(nVideoSSRC + 1, data_[1]); + SendRtcpReportData(nVideoSSRC+1, data_[1]); //WriteLog(Log_Debug, "this =%X ,收到 音频 的RTCP包,需要回复rtcp报告包,netBaseNetType = %d 收到RCP包长度 = %d ", this, netBaseNetType, nReadLength); } } @@ -1028,7 +1027,7 @@ int CNetClientSendRtsp::ProcessNetData() WriteLog(Log_Debug, "ReadDataFunc() ,尚未读取到rtsp (1)数据 ! nClient = %llu ", nClient); bExitProcessFlagArray[2] = true; pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); - return -1; + return -1; } else { @@ -1125,7 +1124,7 @@ void CNetClientSendRtsp::ProcessRtcpData(char* szRtcpData, int nDataLength, int int CNetClientSendRtsp::SendFirstRequst() { SendOptions(AuthenticateType); - return 0; + return 0; } //请求m3u8文件 @@ -1260,7 +1259,7 @@ void CNetClientSendRtsp::FindVideoAudioInSDP() void CNetClientSendRtsp::SendOptions(WWW_AuthenticateType wwwType) { //确定类型 - nSendSetupCount = 0; + nSendSetupCount = 0; nMediaCount = 0; nTrackIDOrer = 1;//从1开始,不从0开始 CSeq = 1; @@ -1272,7 +1271,7 @@ void CNetClientSendRtsp::SendOptions(WWW_AuthenticateType wwwType) else if (wwwType == WWW_Authenticate_MD5) { Authenticator author; - char* szResponse; + char* szResponse; author.setRealmAndNonce(m_rtspStruct.szRealm, m_rtspStruct.szNonce); author.setUsernameAndPassword(m_rtspStruct.szUser, m_rtspStruct.szPwd); @@ -1310,7 +1309,7 @@ void CNetClientSendRtsp::SendANNOUNCE(WWW_AuthenticateType wwwType) else if (wwwType == WWW_Authenticate_MD5) { Authenticator author; - char* szResponse; + char* szResponse; author.setRealmAndNonce(m_rtspStruct.szRealm, m_rtspStruct.szNonce); author.setUsernameAndPassword(m_rtspStruct.szUser, m_rtspStruct.szPwd); @@ -1362,7 +1361,7 @@ void CNetClientSendRtsp::SendSetup(WWW_AuthenticateType wwwType) else if (wwwType == WWW_Authenticate_MD5) { Authenticator author; - char* szResponse; + char* szResponse; author.setRealmAndNonce(m_rtspStruct.szRealm, m_rtspStruct.szNonce); author.setUsernameAndPassword(m_rtspStruct.szUser, m_rtspStruct.szPwd); @@ -1418,18 +1417,18 @@ void CNetClientSendRtsp::SendRECORD(WWW_AuthenticateType wwwType) {//\r\nScale: 255 if (wwwType == WWW_Authenticate_None) { - sprintf(szResponseBuffer, "RECORD %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: ABL_RtspServer_3.0.1\r\nSession: %s\r\nRange: npt=0.000-\r\n\r\n", m_rtspStruct.szSrcRtspPullUrl, CSeq, szSessionID); + sprintf(szResponseBuffer, "RECORD %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: ABL_RtspServer_3.0.1\r\nSession: %s\r\nRange: npt=0.000-\r\n\r\n", m_rtspStruct.szSrcRtspPullUrl, CSeq, szSessionID); } else if (wwwType == WWW_Authenticate_MD5) { Authenticator author; - char* szResponse; + char* szResponse; author.setRealmAndNonce(m_rtspStruct.szRealm, m_rtspStruct.szNonce); author.setUsernameAndPassword(m_rtspStruct.szUser, m_rtspStruct.szPwd); szResponse = (char*)author.computeDigestResponse("PLAY", m_rtspStruct.szSrcRtspPullUrl); //要注意 uri ,有时候没有最后的 斜杠 / - sprintf(szResponseBuffer, "RECORD %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: ABL_RtspServer_3.0.1\r\nSession: %s\r\nAuthorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\nRange: npt=0.000-\r\n\r\n", m_rtspStruct.szSrcRtspPullUrl, CSeq, szSessionID, m_rtspStruct.szUser, m_rtspStruct.szRealm, m_rtspStruct.szNonce, m_rtspStruct.szSrcRtspPullUrl, szResponse); + sprintf(szResponseBuffer, "RECORD %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: ABL_RtspServer_3.0.1\r\nSession: %s\r\nAuthorization: Digest username=\"%s\", realm=\"%s\", nonce=\"%s\", uri=\"%s\", response=\"%s\"\r\nRange: npt=0.000-\r\n\r\n", m_rtspStruct.szSrcRtspPullUrl, CSeq, szSessionID, m_rtspStruct.szUser, m_rtspStruct.szRealm, m_rtspStruct.szNonce, m_rtspStruct.szSrcRtspPullUrl, szResponse); author.reclaimDigestResponse(szResponse); } @@ -1437,7 +1436,7 @@ void CNetClientSendRtsp::SendRECORD(WWW_AuthenticateType wwwType) { UserPasswordBase64(szBasic); - sprintf(szResponseBuffer, "RECORD %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: ABL_RtspServer_3.0.1\r\nSession: %s\r\nAuthorization: Basic %s\r\nRange: npt=0.000-\r\n\r\n", m_rtspStruct.szSrcRtspPullUrl, CSeq, szSessionID, szBasic); + sprintf(szResponseBuffer, "RECORD %s RTSP/1.0\r\nCSeq: %d\r\nUser-Agent: ABL_RtspServer_3.0.1\r\nSession: %s\r\nAuthorization: Basic %s\r\nRange: npt=0.000-\r\n\r\n", m_rtspStruct.szSrcRtspPullUrl, CSeq, szSessionID, szBasic); } XHNetSDK_Write(nClient, (unsigned char*)szResponseBuffer, strlen(szResponseBuffer), 1); diff --git a/ABLMediaServer/NetClientWebrtcPlayer.cpp b/ABLMediaServer/NetClientWebrtcPlayer.cpp index 823064c..7e2c24c 100644 --- a/ABLMediaServer/NetClientWebrtcPlayer.cpp +++ b/ABLMediaServer/NetClientWebrtcPlayer.cpp @@ -93,7 +93,7 @@ CNetClientWebrtcPlayer::CNetClientWebrtcPlayer(NETHANDLE hServer, NETHANDLE hCli streamInfo["format"] = std::to_string(format); - m_decder = FFmpegAudioDecoderAPI::CreateDecoder(streamInfo); + m_AudioDecder = FFmpegAudioDecoderAPI::CreateDecoder(streamInfo); // 处理音频数据的线程函数 ABL::ThreadPool::getInstance().append([&]() { @@ -105,8 +105,6 @@ CNetClientWebrtcPlayer::CNetClientWebrtcPlayer(NETHANDLE hServer, NETHANDLE hCli int ret = m_resampler->GetOneFrame(output_data, &sample_size); if (ret < 0) { - // std::unique_lock lock(m_mutex); - //audioDataCV.wait(lock, [&]() { return !stopThread.load(); }); if (stopThread.load()) { return; @@ -154,10 +152,10 @@ CNetClientWebrtcPlayer::~CNetClientWebrtcPlayer() stopThread.store(true); std::this_thread::sleep_for(std::chrono::milliseconds(10)); - if (m_decder != nullptr) + if (m_AudioDecder != nullptr) { - delete m_decder; - m_decder = nullptr; + delete m_AudioDecder; + m_AudioDecder = nullptr; } if (m_resampler != nullptr) { @@ -165,6 +163,14 @@ CNetClientWebrtcPlayer::~CNetClientWebrtcPlayer() m_resampler = nullptr; } + // 释放资源 + for (int i = 0; i < AV_NUM_DATA_POINTERS; ++i) { + if (outData[i] != nullptr) { + delete[] outData[i]; + outData[i] = nullptr; + } + } + if (pMediaSource != NULL) { if (pMediaSource->bCreateWebRtcPlaySourceFlag.load() == true) @@ -231,20 +237,14 @@ int CNetClientWebrtcPlayer::PushAudio(uint8_t* pVideoData, uint32_t nDataLength, int outSize = 0; - uint8_t* outData[AV_NUM_DATA_POINTERS] = { 0 }; - bool res = m_decder->DecodeData(pVideoData, nDataLength, outData, &outSize); + + bool res = m_AudioDecder->DecodeData(pVideoData, nDataLength, outData, &outSize); if (res && outSize>0) { res = m_resampler->FillingPCM(outData, outSize); } - // 释放资源 - for (int i = 0; i < AV_NUM_DATA_POINTERS; ++i) { - if (outData[i] != nullptr) { - delete[] outData[i]; - outData[i] = nullptr; - } - } + return 0; } diff --git a/ABLMediaServer/NetClientWebrtcPlayer.h b/ABLMediaServer/NetClientWebrtcPlayer.h index 54ee3f8..e22e6fc 100644 --- a/ABLMediaServer/NetClientWebrtcPlayer.h +++ b/ABLMediaServer/NetClientWebrtcPlayer.h @@ -45,12 +45,13 @@ class CNetClientWebrtcPlayer : public CNetRevcBase #endif AudioResamplerAPI* m_resampler = nullptr; - FFmpegAudioDecoderAPI* m_decder = nullptr; + FFmpegAudioDecoderAPI* m_AudioDecder = nullptr; int m_nb_channels = 2; int m_sample_rate = 48000; std::atomic stopThread; + uint8_t* outData[AV_NUM_DATA_POINTERS] = { 0 }; }; #endif \ No newline at end of file diff --git a/ABLMediaServer/NetGB28181RtpClient.cpp b/ABLMediaServer/NetGB28181RtpClient.cpp index 672a45c..cbddc16 100644 --- a/ABLMediaServer/NetGB28181RtpClient.cpp +++ b/ABLMediaServer/NetGB28181RtpClient.cpp @@ -2,7 +2,8 @@ 功能: 负责发送 GB28181 Rtp 码流,包括UDP、TCP模式 增加 国标接收 (即国标发送的同时也支持国标接收) 2023-05-19 -日期 2021-08-15 + 增加支持1078码流以 2016\2019版本发送 2023-12-23 + 日期 2021-08-15 作者 罗家兄弟 QQ 79941308 E-Mail 79941308@qq.com @@ -115,9 +116,8 @@ void CNetGB28181RtpClient::GB28181SentRtpVideoData(unsigned char* pRtpVideo, in if (nSendRet != 0) { bRunFlag = false; - - WriteLog(Log_Debug, "CNetGB28181RtpClient = %X, 发送国标RTP码流出错 ,Length = %d ,nSendRet = %d", this, nSendRtpVideoMediaBufferLength, nSendRet); - DeleteNetRevcBaseClient(nClient); + WriteLog(Log_Debug, "CNetGB28181RtpClient = %X, 发送国标RTP码流出错 ,Length = %d ,nSendRet = %d", this, nSendRtpVideoMediaBufferLength, nSendRet); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient,sizeof(nClient)); return; } @@ -131,7 +131,8 @@ void CNetGB28181RtpClient::GB28181SentRtpVideoData(unsigned char* pRtpVideo, in if (nSendRet != 0) { WriteLog(Log_Debug, "CNetGB28181RtpClient = %X, 发送国标RTP码流出错 ,Length = %d ,nSendRet = %d", this, nSendRtpVideoMediaBufferLength, nSendRet); - DeleteNetRevcBaseClient(nClient); + bRunFlag = false; + pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); return; } @@ -424,6 +425,8 @@ void CNetGB28181RtpClient::CreateRtpHandle() int CNetGB28181RtpClient::SendVideo() { + std::lock_guard lock(businessProcMutex); + if (!bRunFlag ) return -1; @@ -529,6 +532,8 @@ int CNetGB28181RtpClient::SendVideo() int CNetGB28181RtpClient::SendAudio() { + std::lock_guard lock(businessProcMutex); + if ( ABL_MediaServerPort.nEnableAudio == 0 || !bRunFlag || m_startSendRtpStruct.disableAudio[0] == 0x31 ) return 0; @@ -752,6 +757,7 @@ int CNetGB28181RtpClient::ProcessNetData() //发送第一个请求 int CNetGB28181RtpClient::SendFirstRequst() {//当 gb28181 为tcp时,触发该函数 + std::lock_guard lock(businessProcMutex); if (netBaseNetType == NetBaseNetType_NetGB28181SendRtpTCP_Connect) {//回复http请求,连接成功, @@ -766,7 +772,6 @@ int CNetGB28181RtpClient::SendFirstRequst() pMediaSource->AddClientToMap(nClient); } - return 0; } diff --git a/ABLMediaServer/NetGB28181RtpServer.cpp b/ABLMediaServer/NetGB28181RtpServer.cpp index 0967f8d..8b51cdb 100644 --- a/ABLMediaServer/NetGB28181RtpServer.cpp +++ b/ABLMediaServer/NetGB28181RtpServer.cpp @@ -1519,9 +1519,8 @@ void CNetGB28181RtpServer::GB28181SentRtpVideoData(unsigned char* pRtpVideo, in if (nSendRet != 0) { bRunFlag = false; - - WriteLog(Log_Debug, "CNetGB28181RtpClient = %X, 发送国标RTP码流出错 ,Length = %d ,nSendRet = %d", this, nSendRtpVideoMediaBufferLength, nSendRet); - DeleteNetRevcBaseClient(nClient); + WriteLog(Log_Debug, "CNetGB28181RtpClient = %X, 发送国标RTP码流出错 ,Length = %d ,nSendRet = %d", this, nSendRtpVideoMediaBufferLength, nSendRet); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); return; } @@ -1535,7 +1534,8 @@ void CNetGB28181RtpServer::GB28181SentRtpVideoData(unsigned char* pRtpVideo, in if (nSendRet != 0) { WriteLog(Log_Debug, "CNetGB28181RtpClient = %X, 发送国标RTP码流出错 ,Length = %d ,nSendRet = %d", this, nSendRtpVideoMediaBufferLength, nSendRet); - DeleteNetRevcBaseClient(nClient); + bRunFlag = false; + pDisconnectBaseNetFifo.push((unsigned char*)&nClient, sizeof(nClient)); return; } diff --git a/ABLMediaServer/NetRecvBase.cpp b/ABLMediaServer/NetRecvBase.cpp index a2c8a85..a3fa244 100644 --- a/ABLMediaServer/NetRecvBase.cpp +++ b/ABLMediaServer/NetRecvBase.cpp @@ -473,8 +473,8 @@ int CNetRevcBase::CalcVideoFrameSpeed(unsigned char* pRtpData, int nLength) m_nVideoFrameSpeed = 25; else if (m_nVideoFrameSpeed == 7) m_nVideoFrameSpeed = 30; - else if (m_nVideoFrameSpeed > 30) - m_nVideoFrameSpeed = 30; + else if (m_nVideoFrameSpeed > 120) + m_nVideoFrameSpeed = 120; if(nSpeedCount[0] > 10 ) m_nVideoFrameSpeed = 25; @@ -529,8 +529,8 @@ int CNetRevcBase::CalcFlvVideoFrameSpeed(int nVideoPTS, int nMaxValue) m_nVideoFrameSpeed = 25; else if (m_nVideoFrameSpeed == 7) m_nVideoFrameSpeed = 30; - else if(m_nVideoFrameSpeed > 30) - m_nVideoFrameSpeed = 30; + else if(m_nVideoFrameSpeed > 120) + m_nVideoFrameSpeed = 120; if (nSpeedCount[0] > 10) m_nVideoFrameSpeed = 25; @@ -567,6 +567,9 @@ bool CNetRevcBase::SplitterAppStream(char* szMediaSoureFile) memcpy(m_addStreamProxyStruct.app, szMediaSoureFile+1, nPos2 - 1 ); memcpy(m_addStreamProxyStruct.stream, szMediaSoureFile + nPos2 +1 ,strlen(szMediaSoureFile) - nPos2 - 1); + strcpy(app, m_addStreamProxyStruct.app); + strcpy(stream, m_addStreamProxyStruct.stream); + return true; } diff --git a/ABLMediaServer/NetRtspServer.cpp b/ABLMediaServer/NetRtspServer.cpp index 538ea38..a346afa 100644 --- a/ABLMediaServer/NetRtspServer.cpp +++ b/ABLMediaServer/NetRtspServer.cpp @@ -1336,6 +1336,13 @@ void CNetRtspServer::InputRtspData(unsigned char* pRecvData, int nDataLength) DeleteNetRevcBaseClient(nClient); return; } + + auto pSourceClient = GetNetRevcBaseClient(pMediaSource->nClient); + if (pSourceClient != NULL) + {//记录回放源ID + if(pSourceClient->netBaseNetType == ReadRecordFileInput_ReadFMP4File || pSourceClient->netBaseNetType == NetBaseNetType_NetServerReadMultRecordFile) + nReplayClient = pMediaSource->nClient; + } } else {//录像点播 @@ -1509,6 +1516,7 @@ void CNetRtspServer::InputRtspData(unsigned char* pRecvData, int nDataLength) else if (memcmp(pRecvData, "PLAY", 4) == 0 && strstr((char*)pRecvData, "\r\n\r\n") != NULL) { GetFieldValue("CSeq", szCSeq); + nRecvDataTimerBySecond = 0 ; sprintf(szResponseBuffer, "RTSP/1.0 200 OK\r\nServer: %s\r\nCSeq: %s\r\nSession: ABLMediaServer_%llu\r\nRTP-Info: %s\r\n\r\n", MediaServerVerson, szCSeq, currentSession, szCurRtspURL); nSendRet = XHNetSDK_Write(nClient, (unsigned char*)szResponseBuffer, strlen(szResponseBuffer), 1); @@ -1529,11 +1537,21 @@ void CNetRtspServer::InputRtspData(unsigned char* pRecvData, int nDataLength) if(nReplayClient > 0 ) { - auto pBasePtr = GetNetRevcBaseClient(nReplayClient); + CReadRecordFileInput* pReplayPtr1 = NULL ;//单文件 + CNetServerReadMultRecordFile* pReplayPtr2 = NULL;//多文件 + + auto pBasePtr = GetNetRevcBaseClient(nReplayClient); if (pBasePtr) { - CReadRecordFileInput* pReplayPtr = (CReadRecordFileInput*)pBasePtr.get(); - pReplayPtr->UpdatePauseFlag(false);//继续播放 + if (pBasePtr->netBaseNetType == ReadRecordFileInput_ReadFMP4File) + { + pReplayPtr1 = (CReadRecordFileInput*)pBasePtr.get(); + pReplayPtr1->UpdatePauseFlag(false);//继续播放 + }else if (pBasePtr->netBaseNetType == NetBaseNetType_NetServerReadMultRecordFile) + { + pReplayPtr2 = (CNetServerReadMultRecordFile*)pBasePtr.get(); + pReplayPtr2->UpdatePauseFlag(false);//继续播放 + } nRtspPlayCount++; @@ -1548,7 +1566,16 @@ void CNetRtspServer::InputRtspData(unsigned char* pRecvData, int nDataLength) else m_rtspPlayerType = RtspPlayerType_RecordReplay; - pReplayPtr->UpdateReplaySpeed(atof(szScale), m_rtspPlayerType); + if (pBasePtr->netBaseNetType == ReadRecordFileInput_ReadFMP4File) + { + if(pReplayPtr1) + pReplayPtr1->UpdateReplaySpeed(atof(szScale), m_rtspPlayerType); + } + else if (pBasePtr->netBaseNetType == NetBaseNetType_NetServerReadMultRecordFile) + { + if(pReplayPtr2) + pReplayPtr2->UpdateReplaySpeed(atof(szScale), m_rtspPlayerType); + } } //实现拖动播放 @@ -1566,7 +1593,18 @@ void CNetRtspServer::InputRtspData(unsigned char* pRecvData, int nDataLength) { memcpy(szRangeValue, szRange + nPos1 + 4, nPos2 - nPos1 - 4); if (atoi(szRangeValue) > 0) - pReplayPtr->ReaplyFileSeek(atoi(szRangeValue)); + { + if (pBasePtr->netBaseNetType == ReadRecordFileInput_ReadFMP4File) + { + if(pReplayPtr1) + pReplayPtr1->ReaplyFileSeek(atoi(szRangeValue)); + } + else if (pBasePtr->netBaseNetType == NetBaseNetType_NetServerReadMultRecordFile) + { + if(pReplayPtr2) + pReplayPtr2->ReaplyFileSeek(atoi(szRangeValue)); + } + } } } } @@ -1580,8 +1618,16 @@ void CNetRtspServer::InputRtspData(unsigned char* pRecvData, int nDataLength) auto pBasePtr = GetNetRevcBaseClient(nReplayClient); if (pBasePtr) { - CReadRecordFileInput* pReplayPtr = (CReadRecordFileInput*)pBasePtr.get(); - pReplayPtr->UpdatePauseFlag(true);//暂停播放 + if (pBasePtr->netBaseNetType == ReadRecordFileInput_ReadFMP4File) + {//读取单个mp4文件 + CReadRecordFileInput* pReplayPtr = (CReadRecordFileInput*)pBasePtr.get(); + pReplayPtr->UpdatePauseFlag(true);//暂停播放 + } + else if (pBasePtr->netBaseNetType == NetBaseNetType_NetServerReadMultRecordFile) + {//读取多个mp4文件 + CNetServerReadMultRecordFile* pReplayPtr = (CNetServerReadMultRecordFile*)pBasePtr.get(); + pReplayPtr->UpdatePauseFlag(true);//暂停播放 + } } GetFieldValue("CSeq", szCSeq); @@ -1593,11 +1639,11 @@ void CNetRtspServer::InputRtspData(unsigned char* pRecvData, int nDataLength) return; } - WriteLog(Log_Debug, "收到断开 暂停 命令,立即执行暂停 nClient = %llu , nReplayClient = %llu ", nClient, nReplayClient); + WriteLog(Log_Debug, "收到 暂停 命令,立即执行暂停 nClient = %llu , nReplayClient = %llu ", nClient, nReplayClient); } else if (memcmp(pRecvData, "TEARDOWN", 8) == 0 && strstr((char*)pRecvData, "\r\n\r\n") != NULL) { - WriteLog(Log_Debug, "收到断开 TEARDOWN 命令,立即执行删除 nClient = %llu ", nClient); + WriteLog(Log_Debug, "收到 TEARDOWN 命令,立即执行删除 nClient = %llu ", nClient); bRunFlag = false; DeleteNetRevcBaseClient(nClient); } @@ -1692,7 +1738,6 @@ bool CNetRtspServer::GetMediaInfoFromRtspSDP() ABL::to_upper(strVideoName); #endif - strcpy(szVideoName, strVideoName.c_str()); } diff --git a/ABLMediaServer/NetServerHLS.cpp b/ABLMediaServer/NetServerHLS.cpp index bd85b76..9c398bc 100644 --- a/ABLMediaServer/NetServerHLS.cpp +++ b/ABLMediaServer/NetServerHLS.cpp @@ -539,6 +539,11 @@ int CNetServerHLS::SendRecordHLS() #endif sprintf(szRequestFileName, "%s%s", ABL_MediaServerPort.recordPath, strTemp.c_str()+1); + strTemp = szRequestFileName; + int nPos = strTemp.rfind("?", strTemp.size()); + if (nPos > 0) + szRequestFileName[nPos] = 0x00; + FILE* fReadM3u8 = NULL; fReadM3u8 = fopen(szRequestFileName, "rb"); diff --git a/ABLMediaServer/NetServerHTTP.cpp b/ABLMediaServer/NetServerHTTP.cpp index 917c537..a4c1060 100644 --- a/ABLMediaServer/NetServerHTTP.cpp +++ b/ABLMediaServer/NetServerHTTP.cpp @@ -451,7 +451,9 @@ bool CNetServerHTTP::SplitterTextParam(char* szTextParam) memset(szBlockString, 0x00, sizeof(szBlockString)); strcpy(szBlockString, strBlockString.c_str()); - RequestKeyValue* keyValue = new RequestKeyValue(); + RequestKeyValue* keyValue = NULL; + while(keyValue == NULL) + keyValue = new RequestKeyValue(); nFind2 = strBlockString.find("=", 0); if (nFind2 > 0) { @@ -545,7 +547,9 @@ bool CNetServerHTTP::SplitterJsonParam(char* szJsonParam) sprintf(szValue, "%llu", jValue.GetInt64()); } - RequestKeyValue* keyValue = new RequestKeyValue(); + RequestKeyValue* keyValue = NULL; + while(keyValue == NULL ) + keyValue = new RequestKeyValue(); strcpy(keyValue->key, name.c_str()); strcpy(keyValue->value, szValue); requestKeyValueMap.insert(RequestKeyValueMap::value_type(keyValue->key, keyValue)); @@ -1734,17 +1738,6 @@ bool CNetServerHTTP::index_api_startSendRtp() return false; } - //如果是tcp 被动连接,必须指定本地端口 - if (is_udp == 2) - { - if (atoi(m_startSendRtpStruct.src_port) == 0) - { - sprintf(szResponseBody, "{\"code\":%d,\"memo\":\"src_port parameter error ,if tcp passive connected, the binding: src_port must be specified \"}", IndexApiCode_ParamError); - ResponseSuccess(szResponseBody); - return false; - } - } - if (strlen(m_startSendRtpStruct.payload) == 0 || atoi(m_startSendRtpStruct.payload) < 0 ) { sprintf(szResponseBody, "{\"code\":%d,\"memo\":\"payload parameter error \",\"key\":%d}", IndexApiCode_ParamError, 0); @@ -1923,7 +1916,20 @@ bool CNetServerHTTP::index_api_startSendRtp() } else if (is_udp == 2) {//tcp 被动连接 - nRet = XHNetSDK_Listen((int8_t*)("0.0.0.0"), atoi(m_startSendRtpStruct.src_port), &nMediaClient, onaccept, onread, onclose, true); + if(atoi(m_startSendRtpStruct.src_port) > 0 ) + nRet = XHNetSDK_Listen((int8_t*)("0.0.0.0"), atoi(m_startSendRtpStruct.src_port), &nMediaClient, onaccept, onread, onclose, true); + else + { + while (true) + {//一直绑定到成功为止 + nRet = XHNetSDK_Listen((int8_t*)("0.0.0.0"), ABL_nGB28181Port, &nMediaClient, onaccept, onread, onclose, true); + ABL_nGB28181Port += 2; + if (nRet == 0) + break; + } + sprintf(m_startSendRtpStruct.src_port, "%d", ABL_nGB28181Port - 2);//修改为实际绑定的端口 + } + WriteLog(Log_Debug, "XHNetSDK_Listen() nMediaClient = %llu", nMediaClient); if (nRet == 0 && nMediaClient > 0) { @@ -2423,7 +2429,7 @@ bool CNetServerHTTP::index_api_getSnap() return false; } - if (strcmp(m_getSnapStruct.secret, m_getSnapStruct.secret) != 0) + if (strcmp(m_getSnapStruct.secret, ABL_MediaServerPort.secret) != 0) {//密码检测 sprintf(szResponseBody, "{\"code\":%d,\"memo\":\"secret error\"}", IndexApiCode_secretError); ResponseSuccess(szResponseBody); diff --git a/ABLMediaServer/NetServerHTTP.h b/ABLMediaServer/NetServerHTTP.h index 5033836..aa8f7f4 100644 --- a/ABLMediaServer/NetServerHTTP.h +++ b/ABLMediaServer/NetServerHTTP.h @@ -22,7 +22,7 @@ using namespace boost; #define MaxNetServerHttpBuffer 1024*1024*2 #define MaxMediaSourceInfoLength 1024*1024*6 -typedef map > RequestKeyValueMap; +typedef std::map > RequestKeyValueMap; class CNetServerHTTP : public CNetRevcBase { diff --git a/ABLMediaServer/NetServerHTTP_FLV.cpp b/ABLMediaServer/NetServerHTTP_FLV.cpp index 0a5e461..65c9443 100644 --- a/ABLMediaServer/NetServerHTTP_FLV.cpp +++ b/ABLMediaServer/NetServerHTTP_FLV.cpp @@ -156,8 +156,6 @@ int CNetServerHTTP_FLV::PushAudio(uint8_t* pAudioData, uint32_t nDataLength, cha if (ABL_MediaServerPort.nEnableAudio == 0) return -1; - if ( !(strcmp(szAudioCodec, "AAC") == 0 || strcmp(szAudioCodec,"MP3") == 0 )) - return 0; m_audioFifo.push(pAudioData, nDataLength); @@ -167,7 +165,7 @@ int CNetServerHTTP_FLV::PushAudio(uint8_t* pAudioData, uint32_t nDataLength, cha void CNetServerHTTP_FLV::MuxerVideoFlV(char* codeName, unsigned char* pVideo, int nLength) { //只有视频,或者屏蔽音频 - if(ABL_MediaServerPort.nEnableAudio == 0 || strcmp(mediaCodecInfo.szAudioName,"G711_A") == 0 || strcmp(mediaCodecInfo.szAudioName, "G711_U") == 0) + if(ABL_MediaServerPort.nEnableAudio == 0 ) nVideoStampAdd = 1000 / mediaCodecInfo.nVideoFrameRate; if (strcmp(codeName, "H264") == 0) @@ -199,17 +197,15 @@ void CNetServerHTTP_FLV::MuxerAudioFlV(char* codeName, unsigned char* pAudio, i flv_muxer_aac(flvMuxer, pAudio, nLength, audioDts, audioDts); else if (strcmp(mediaCodecInfo.szAudioName, "MP3") == 0) flv_muxer_mp3(flvMuxer, pAudio, nLength, audioDts, audioDts); - } - - if(bUserNewAudioTimeStamp == false) - audioDts += mediaCodecInfo.nBaseAddAudioTimeStamp ; - else - { - nUseNewAddAudioTimeStamp --; - audioDts += nNewAddAudioTimeStamp; - if (nUseNewAddAudioTimeStamp <= 0) + else if (strcmp(mediaCodecInfo.szAudioName, "G711_A") == 0) + { + flv_muxer_g711a(flvMuxer, pAudio, nLength, audioDts, audioDts); + audioDts += nLength / 8; + } + else if (strcmp(mediaCodecInfo.szAudioName, "G711_U") == 0) { - bUserNewAudioTimeStamp = false; + flv_muxer_g711u(flvMuxer, pAudio, nLength, audioDts, audioDts); + audioDts += nLength / 8; } } @@ -261,10 +257,6 @@ int CNetServerHTTP_FLV::SendAudio() return -1; } - //不是AAC,mp3 - if (!(strcmp(mediaCodecInfo.szAudioName, "AAC") == 0 || strcmp(mediaCodecInfo.szAudioName, "MP3") == 0)) - return -1; - unsigned char* pData = NULL; int nLength = 0; if((pData = m_audioFifo.pop(&nLength)) != NULL) @@ -329,7 +321,7 @@ int CNetServerHTTP_FLV::ProcessNetData() { if (!bFindFlvNameFlag) { - if (netDataCacheLength > string_length_4096 ) + if (netDataCacheLength > string_length_4096) { WriteLog(Log_Debug, "CNetServerHTTP_FLV = %X , nClient = %llu ,netDataCacheLength = %d, 发送过来的url数据长度非法 ,立即删除 ", this, nClient, netDataCacheLength); DeleteNetRevcBaseClient(nClient); @@ -420,7 +412,6 @@ int CNetServerHTTP_FLV::ProcessNetData() if (strstr(szFlvName, RecordFileReplaySplitter) == NULL) {//实况点播 pushClient = GetMediaStreamSource(szFlvName, true); - if (pushClient == NULL) { WriteLog(Log_Debug, "CNetServerHTTP_FLV=%X, 没有推流对象的地址 %s nClient = %llu ", this, szFlvName, nClient); @@ -488,36 +479,17 @@ int CNetServerHTTP_FLV::ProcessNetData() flvWrite = flv_writer_create(szWriteFlvName); #else //通过网络传输 if ((strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H264") == 0 || strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H265") == 0) && - strcmp(pushClient->m_mediaCodecInfo.szAudioName, "AAC") == 0 && ABL_MediaServerPort.nEnableAudio == 1) + strlen(pushClient->m_mediaCodecInfo.szAudioName) > 0 && ABL_MediaServerPort.nEnableAudio == 1) {//H264、H265 && AAC,创建音频,视频 flvWrite = flv_writer_create2(1, 1, NetServerHTTP_FLV_OnWrite_CB, (void*)this); WriteLog(Log_Debug, "创建http-flv 输出格式为: 视频 %s、音频 %s nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, pushClient->m_mediaCodecInfo.szAudioName, nClient); } - else if ( strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H264") == 0 || strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H265") == 0) + else if ((strlen(pushClient->m_mediaCodecInfo.szAudioName) == 0 || ABL_MediaServerPort.nEnableAudio == 0) && ( strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H264") == 0 || strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H265") == 0)) {//H264、H265 只创建视频 - if (ABL_MediaServerPort.nEnableAudio == 0 || ABL_MediaServerPort.flvPlayAddMute == 0) - {//没有音频输出,或者没有开启静音 - flvWrite = flv_writer_create2(0, 1, NetServerHTTP_FLV_OnWrite_CB, (void*)this); - WriteLog(Log_Debug, "创建http-flv 输出格式为: 视频 %s、音频:无音频 nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, nClient); - } - else - { -#ifdef OS_System_Windows //window 不增加静音 - flvWrite = flv_writer_create2(0, 1, NetServerHTTP_FLV_OnWrite_CB, (void*)this); + flvWrite = flv_writer_create2(0, 1, NetServerHTTP_FLV_OnWrite_CB, (void*)this); WriteLog(Log_Debug, "创建http-flv 输出格式为: 视频 %s、音频:无音频 nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, nClient); -#else - flvWrite = flv_writer_create2(1, 1, NetServerHTTP_FLV_OnWrite_CB, (void*)this); - bAddMuteFlag = true; - strcpy(mediaCodecInfo.szAudioName, "AAC"); - mediaCodecInfo.nChannels = 1; - mediaCodecInfo.nSampleRate = 16000; - mediaCodecInfo.nBaseAddAudioTimeStamp = 64; - AddClientToMapAddMutePacketList(nClient); - WriteLog(Log_Debug, "创建http-flv 输出格式为: 视频 %s、音频:AAC(chans:1,sampleRate:16000) nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, nClient); -#endif - } - } - else if (strlen(pushClient->m_mediaCodecInfo.szVideoName) == 0 && (strcmp(pushClient->m_mediaCodecInfo.szAudioName, "AAC") == 0 || strcmp(pushClient->m_mediaCodecInfo.szAudioName, "MP3") == 0)) + } + else if (strlen(pushClient->m_mediaCodecInfo.szVideoName) == 0 && strlen(pushClient->m_mediaCodecInfo.szAudioName) > 0 ) {//只创建音频 flvWrite = flv_writer_create2(1,0, NetServerHTTP_FLV_OnWrite_CB, (void*)this); WriteLog(Log_Debug, "创建http-flv 输出格式为: 无视频 、只有音频 %s nClient = %llu ", pushClient->m_mediaCodecInfo.szAudioName, nClient); diff --git a/ABLMediaServer/NetServerReadMultRecordFile.cpp b/ABLMediaServer/NetServerReadMultRecordFile.cpp index fbd40b0..b397e6e 100644 --- a/ABLMediaServer/NetServerReadMultRecordFile.cpp +++ b/ABLMediaServer/NetServerReadMultRecordFile.cpp @@ -197,7 +197,14 @@ CNetServerReadMultRecordFile::CNetServerReadMultRecordFile(NETHANDLE hServer, NE mediaCodecInfo.nWidth = video_dec_ctx->width; mediaCodecInfo.nHeight = video_dec_ctx->height; pix_fmt = video_dec_ctx->pix_fmt; - } + } + else + { + avformat_close_input(&pFormatCtx2); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient,sizeof(nClient)); //清理断裂的链接 + WriteLog(Log_Debug, "NetServerReadMultRecordFile = %X ,nClient = %llu 文件中不存在视频、音频流 ", this, hClient); + return ; + } //查找出音频源 if (open_codec_context(&stream_isAudio, &audio_dec_ctx, pFormatCtx2, AVMEDIA_TYPE_AUDIO) >= 0) @@ -224,7 +231,6 @@ CNetServerReadMultRecordFile::CNetServerReadMultRecordFile(NETHANDLE hServer, NE mediaCodecInfo.nChannels = audio_stream->codecpar->channels; #endif // FFMPEG6 - sample_index = 8; for (int i = 0; i < 13; i++) { @@ -453,7 +459,19 @@ int CNetServerReadMultRecordFile::ProcessNetData() if (nAVType == AVType_Video && packet2->size > 0 ) {//读取视频 - pMediaSource->PushVideo(packet2->data, packet2->size,mediaCodecInfo.szVideoName); + if (abs(m_dScaleValue - 8.0) <= 0.01 || abs(m_dScaleValue - 16.0) <= 0.01) + {//抽帧 + if (m_rtspPlayerType == RtspPlayerType_RecordReplay) + {//录像回放 + if (CheckVideoIsIFrame(mediaCodecInfo.szVideoName, packet2->data, packet2->size)) + pMediaSource->PushVideo(packet2->data, packet2->size , mediaCodecInfo.szVideoName); + } + else //录像下载 + pMediaSource->PushVideo(packet2->data, packet2->size, mediaCodecInfo.szVideoName); + } + else + pMediaSource->PushVideo(packet2->data, packet2->size, mediaCodecInfo.szVideoName); + nReadVideoFrameCount ++; if (nFirstTimestamp == -1 && packet2) @@ -718,6 +736,13 @@ bool CNetServerReadMultRecordFile::ReadNextRecordFile() goto BeginReadFile; } } + else + { + avformat_close_input(&pFormatCtx2); + WriteLog(Log_Debug, "NetServerReadMultRecordFile = %X ,nClient = %llu 文件中不存在视频、音频流 ", this, nClient); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient,sizeof(nClient)); //清理断裂的链接 + return false ; + } //重新产生转换器 if (stream_isVideo >=0 && pFormatCtx2->streams[stream_isVideo]->codecpar->extradata_size > 0) diff --git a/ABLMediaServer/NetServerWS_FLV.cpp b/ABLMediaServer/NetServerWS_FLV.cpp index fda2793..a006a19 100644 --- a/ABLMediaServer/NetServerWS_FLV.cpp +++ b/ABLMediaServer/NetServerWS_FLV.cpp @@ -152,15 +152,15 @@ int CNetServerWS_FLV::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, char* int CNetServerWS_FLV::PushAudio(uint8_t* pAudioData, uint32_t nDataLength, char* szAudioCodec, int nChannels, int SampleRate) { nRecvDataTimerBySecond = 0; + if (ABL_MediaServerPort.nEnableAudio == 0) + return -1; + if (strlen(mediaCodecInfo.szAudioName) == 0) { strcpy(mediaCodecInfo.szAudioName, szAudioCodec); mediaCodecInfo.nChannels = nChannels; mediaCodecInfo.nSampleRate = SampleRate; } - if (ABL_MediaServerPort.nEnableAudio == 0 || !(strcmp(szAudioCodec, "AAC") == 0 || strcmp(szAudioCodec, "MP3") == 0)) - return -1; - m_audioFifo.push(pAudioData, nDataLength); return 0; @@ -169,7 +169,7 @@ int CNetServerWS_FLV::PushAudio(uint8_t* pAudioData, uint32_t nDataLength, char* void CNetServerWS_FLV::MuxerVideoFlV(char* codeName, unsigned char* pVideo, int nLength) { //只有视频,或者屏蔽音频 - if (ABL_MediaServerPort.nEnableAudio == 0 || strcmp(mediaCodecInfo.szAudioName, "G711_A") == 0 || strcmp(mediaCodecInfo.szAudioName, "G711_U") == 0) + if(ABL_MediaServerPort.nEnableAudio == 0 ) nVideoStampAdd = 1000 / mediaCodecInfo.nVideoFrameRate; if (strcmp(codeName, "H264") == 0) @@ -195,17 +195,15 @@ void CNetServerWS_FLV::MuxerAudioFlV(char* codeName, unsigned char* pAudio, int flv_muxer_aac(flvMuxer, pAudio, nLength, audioDts, audioDts); else if (strcmp(mediaCodecInfo.szAudioName, "MP3") == 0) flv_muxer_mp3(flvMuxer, pAudio, nLength, audioDts, audioDts); - } - - if (bUserNewAudioTimeStamp == false) - audioDts += mediaCodecInfo.nBaseAddAudioTimeStamp; - else - { - nUseNewAddAudioTimeStamp --; - audioDts += nNewAddAudioTimeStamp; - if (nUseNewAddAudioTimeStamp <= 0) + else if (strcmp(mediaCodecInfo.szAudioName, "G711_A") == 0) { - bUserNewAudioTimeStamp = false; + flv_muxer_g711a(flvMuxer, pAudio, nLength, audioDts, audioDts); + audioDts += nLength / 8; + } + else if (strcmp(mediaCodecInfo.szAudioName, "G711_U") == 0) + { + flv_muxer_g711u(flvMuxer, pAudio, nLength, audioDts, audioDts); + audioDts += nLength / 8; } } @@ -256,10 +254,6 @@ int CNetServerWS_FLV::SendAudio() return -1; } - //不是AAC,mp3 - if (ABL_MediaServerPort.nEnableAudio == 0 || !(strcmp(mediaCodecInfo.szAudioName, "AAC") == 0 || strcmp(mediaCodecInfo.szAudioName, "MP3") == 0)) - return -1; - unsigned char* pData = NULL; int nLength = 0; if((pData = m_audioFifo.pop(&nLength)) != NULL) @@ -329,7 +323,7 @@ int CNetServerWS_FLV::ProcessNetData() unsigned char nCommand = 0x00 ; unsigned char szPong[4] = { 0x8A,0x80,0x00,0x00 }; - if (netDataCacheLength > string_length_4096 ) + if (netDataCacheLength > string_length_4096) { WriteLog(Log_Debug, "CNetServerWS_FLV = %X , nClient = %llu ,netDataCacheLength = %d, 发送过来的url数据长度非法 ,立即删除 ", this, nClient, netDataCacheLength); DeleteNetRevcBaseClient(nClient); @@ -471,7 +465,6 @@ bool CNetServerWS_FLV::Create_WS_FLV_Handle() if (strstr(szFlvName, RecordFileReplaySplitter) == NULL) {//实况点播 pushClient = GetMediaStreamSource(szFlvName, true); - if (pushClient == NULL) { WriteLog(Log_Debug, "CNetServerWS_FLV=%X, 没有推流对象的地址 %s nClient = %llu ", this, szFlvName, nClient); @@ -561,36 +554,17 @@ bool CNetServerWS_FLV::Create_WS_FLV_Handle() flvWrite = flv_writer_create(szWriteFlvName); #else //通过网络传输 if ((strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H264") == 0 || strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H265") == 0) && - strcmp(pushClient->m_mediaCodecInfo.szAudioName, "AAC") == 0 && ABL_MediaServerPort.nEnableAudio == 1) + strlen(pushClient->m_mediaCodecInfo.szAudioName) > 0 && ABL_MediaServerPort.nEnableAudio == 1) {//H264、H265 && AAC,创建音频,视频 flvWrite = flv_writer_create2(1, 1, NetServerWS_FLV_OnWrite_CB, (void*)this); WriteLog(Log_Debug, "创建ws-flv 输出格式为: 视频 %s、音频 %s nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, pushClient->m_mediaCodecInfo.szAudioName, nClient); } - else if (strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H264") == 0 || strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H265") == 0 ) + else if ((strlen(pushClient->m_mediaCodecInfo.szAudioName) == 0 || ABL_MediaServerPort.nEnableAudio == 0) && ( strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H264") == 0 || strcmp(pushClient->m_mediaCodecInfo.szVideoName, "H265") == 0)) {//H264、H265 只创建视频 - if (ABL_MediaServerPort.nEnableAudio == 0 || ABL_MediaServerPort.flvPlayAddMute == 0) - {//没有音频输出,或者没有开启静音 - flvWrite = flv_writer_create2(0, 1, NetServerWS_FLV_OnWrite_CB, (void*)this); - WriteLog(Log_Debug, "创建ws-flv 输出格式为: 视频 %s、音频:无音频 nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, nClient); - } - else - { -#ifdef OS_System_Windows //window 不增加静音 - flvWrite = flv_writer_create2(0, 1, NetServerWS_FLV_OnWrite_CB, (void*)this); - WriteLog(Log_Debug, "创建ws-flv 输出格式为: 视频 %s、音频:无音频 nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, nClient); -#else - flvWrite = flv_writer_create2(1, 1, NetServerWS_FLV_OnWrite_CB, (void*)this); - bAddMuteFlag = true; - strcpy(mediaCodecInfo.szAudioName, "AAC"); - mediaCodecInfo.nChannels = 1; - mediaCodecInfo.nSampleRate = 16000; - mediaCodecInfo.nBaseAddAudioTimeStamp = 64; - AddClientToMapAddMutePacketList(nClient); - WriteLog(Log_Debug, "创建ws-flv 输出格式为: 视频 %s、音频:AAC(chans:1,sampleRate:16000) nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, nClient); -#endif - } - } - else if (strlen(pushClient->m_mediaCodecInfo.szVideoName) == 0 && (strcmp(pushClient->m_mediaCodecInfo.szAudioName, "AAC") == 0 || strcmp(pushClient->m_mediaCodecInfo.szAudioName, "MP3") == 0)) + flvWrite = flv_writer_create2(0, 1, NetServerWS_FLV_OnWrite_CB, (void*)this); + WriteLog(Log_Debug, "创建ws-flv 输出格式为: 视频 %s、音频:无音频 nClient = %llu ", pushClient->m_mediaCodecInfo.szVideoName, nClient); + } + else if (strlen(pushClient->m_mediaCodecInfo.szVideoName) == 0 && strlen(pushClient->m_mediaCodecInfo.szAudioName) > 0 ) {//只创建音频 flvWrite = flv_writer_create2(1, 0, NetServerWS_FLV_OnWrite_CB, (void*)this); WriteLog(Log_Debug, "创建ws-flv 输出格式为: 无视频 、只有音频 %s nClient = %llu ", pushClient->m_mediaCodecInfo.szAudioName, nClient); diff --git a/ABLMediaServer/ReadRecordFileInput.cpp b/ABLMediaServer/ReadRecordFileInput.cpp index f8c6c5f..0587a63 100644 --- a/ABLMediaServer/ReadRecordFileInput.cpp +++ b/ABLMediaServer/ReadRecordFileInput.cpp @@ -9,7 +9,7 @@ E-Mail 79941308@qq.com #include "stdafx.h" #include "ReadRecordFileInput.h" -extern CNetBaseThreadPool* RecordReplayThreadPool;//录像回放线程池 +extern CNetBaseThreadPool* RecordReplayThreadPool;//录像回放线程池 extern CMediaFifo pDisconnectBaseNetFifo; //清理断裂的链接 extern bool DeleteNetRevcBaseClient(NETHANDLE CltHandle); #ifdef USE_BOOST @@ -237,6 +237,13 @@ CReadRecordFileInput::CReadRecordFileInput(NETHANDLE hServer, NETHANDLE hClient, mediaCodecInfo.nHeight = video_dec_ctx->height; pix_fmt = video_dec_ctx->pix_fmt; } + else + { + avformat_close_input(&pFormatCtx2); + WriteLog(Log_Debug, "CReadRecordFileInput = %X ,nClient = %llu 文件中不存在视频、音频流 ", this, hClient); + pDisconnectBaseNetFifo.push((unsigned char*)&nClient,sizeof(nClient)); //清理断裂的链接 + return; + } //查找出音频源 if (open_codec_context(&stream_isAudio, &audio_dec_ctx, pFormatCtx2, AVMEDIA_TYPE_AUDIO) >= 0) diff --git a/ABLMediaServer/StreamRecordFMP4.cpp b/ABLMediaServer/StreamRecordFMP4.cpp index c5ae1da..f02c588 100644 --- a/ABLMediaServer/StreamRecordFMP4.cpp +++ b/ABLMediaServer/StreamRecordFMP4.cpp @@ -146,7 +146,7 @@ int CStreamRecordFMP4::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, char m_videoFifo.push(pVideoData, nDataLength); - if (ABL_MediaServerPort.hook_enable == 1 && (GetTickCount64() - nCreateDateTime ) >= 1000 * 15 ) + if (ABL_MediaServerPort.hook_enable == 1 && (GetTickCount64() - nCreateDateTime ) >= 1000 * 30 ) { MessageNoticeStruct msgNotice; msgNotice.nClient = NetBaseNetType_HttpClient_Record_Progress; diff --git a/ABLMediaServer/StreamRecordMP4.cpp b/ABLMediaServer/StreamRecordMP4.cpp index c522020..3f64b4a 100644 --- a/ABLMediaServer/StreamRecordMP4.cpp +++ b/ABLMediaServer/StreamRecordMP4.cpp @@ -143,7 +143,7 @@ int CStreamRecordMP4::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, char* m_videoFifo.push(pVideoData, nDataLength); - if (ABL_MediaServerPort.hook_enable == 1 && (GetTickCount64() - nCreateDateTime) >= 1000 * 15 ) + if (ABL_MediaServerPort.hook_enable == 1 && (GetTickCount64() - nCreateDateTime) >= 1000 * 30 ) { MessageNoticeStruct msgNotice; msgNotice.nClient = NetBaseNetType_HttpClient_Record_Progress; diff --git a/ABLMediaServer/StreamRecordTS.cpp b/ABLMediaServer/StreamRecordTS.cpp index 1f97369..3690b31 100644 --- a/ABLMediaServer/StreamRecordTS.cpp +++ b/ABLMediaServer/StreamRecordTS.cpp @@ -155,7 +155,7 @@ bool CStreamRecordTS::H264H265FrameToTSFile(unsigned char* szVideo, int nLength } nVideoOrder ++; - if (nVideoOrder % (ABL_MediaServerPort.fileSecond * 25) == 0) + if (nVideoOrder % (ABL_MediaServerPort.fileSecond * mediaCodecInfo.nVideoFrameRate) == 0) {//1秒切片1次 fflush(fTSFileWrite); @@ -264,7 +264,7 @@ int CStreamRecordTS::PushVideo(uint8_t* pVideoData, uint32_t nDataLength, char* m_videoFifo.push(pVideoData, nDataLength); - if (ABL_MediaServerPort.hook_enable == 1 && (GetTickCount64() - nCreateDateTime ) >= 1000 * 15 ) + if (ABL_MediaServerPort.hook_enable == 1 && (GetTickCount64() - nCreateDateTime ) >= 1000 * 30 ) { MessageNoticeStruct msgNotice; msgNotice.nClient = NetBaseNetType_HttpClient_Record_Progress; diff --git a/ABLMediaServer/stdafx.h b/ABLMediaServer/stdafx.h index 4a58528..1b4c3a7 100644 --- a/ABLMediaServer/stdafx.h +++ b/ABLMediaServer/stdafx.h @@ -45,6 +45,7 @@ #include #include #include +#include #include #include @@ -54,7 +55,6 @@ #include #include #include -#include #include #include @@ -72,7 +72,6 @@ #include #include -#include #define BYTE unsigned char @@ -503,7 +502,7 @@ enum NetBaseNetType NetBaseNetType_NetServerReadMultRecordFile = 140,//连续读取多个录像文件 }; -#define MediaServerVerson "ABLMediaServer-6.3.6(2024-06-08)" +#define MediaServerVerson "ABLMediaServer-6.3.6(2024-08-09)" #define RtspServerPublic "DESCRIBE, SETUP, TEARDOWN, PLAY, PAUSE, OPTIONS, ANNOUNCE, RECORD,GET_PARAMETER" #define RecordFileReplaySplitter "__ReplayFMP4RecordFile__" //实况、录像区分的标志字符串,用于区分实况,放置在url中。