/* * Copyright (c) 2016-present The ZLMediaKit project authors. All Rights Reserved. * * This file is part of ZLMediaKit(https://github.com/ZLMediaKit/ZLMediaKit). * * Use of this source code is governed by MIT-like license that can be found in the * LICENSE file in the root of the source tree. All contributing project authors * may be found in the AUTHORS file in the root of the source tree. */ #ifdef ENABLE_HKDEVICE #include "DeviceHK.h" #include "Util/TimeTicker.h" #include "Util/MD5.h" namespace mediakit { #define HK_APP_NAME "live" DeviceHK::DeviceHK() { InfoL << endl; static onceToken token( []() { NET_DVR_Init(); NET_DVR_SetDVRMessageCallBack_V31([](LONG lCommand,NET_DVR_ALARMER *pAlarmer,char *pAlarmInfo,DWORD dwBufLen,void* pUser){ WarnL< hkLoginCB; loginInfo.bUseAsynLogin = TRUE; weak_ptr weakSelf = shared_from_this(); loginInfo.pUser = new hkLoginCB([weakSelf,cb](LONG lUserID, DWORD dwResult, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo ) { //TraceL<sSerialNumber; connectResult result; if(dwResult==TRUE) { result.strDevName=(char *)(lpDeviceInfo->sSerialNumber); result.ui16ChnStart=lpDeviceInfo->byStartChan; result.ui16ChnCount=lpDeviceInfo->byChanNum; auto _strongSelf=weakSelf.lock(); if(_strongSelf) { auto strongSelf=dynamic_pointer_cast(_strongSelf); strongSelf->onConnected(lUserID,lpDeviceInfo); } } else { WarnL<<"connect deviceHK failed:"<(pUser); (*fun)(lUserID,dwResult,lpDeviceInfo); delete fun; }; NET_DVR_SetConnectTime(iTimeOut * 1000, 3); NET_DVR_Login_V40(&loginInfo, &loginResult); } void DeviceHK::disconnect(const relustCB& cb) { m_mapChannels.clear(); if (m_i64LoginId >= 0) { NET_DVR_Logout(m_i64LoginId); m_i64LoginId = -1; Device::onDisconnected(true); } } void DeviceHK::addChannel(int iChn, bool bMainStream) { DevChannel::Ptr channel( new DevChannelHK(m_i64LoginId, (char *) m_deviceInfo.sSerialNumber, iChn, bMainStream)); m_mapChannels[iChn] = channel; } void DeviceHK::delChannel(int chn) { m_mapChannels.erase(chn); } void DeviceHK::onConnected(LONG lUserID, LPNET_DVR_DEVICEINFO_V30 lpDeviceInfo) { m_i64LoginId = lUserID; m_deviceInfo = *lpDeviceInfo; Device::onConnected(); } void DeviceHK::addAllChannel(bool bMainStream) { InfoL << endl; for (int i = 0; i < m_deviceInfo.byChanNum; i++) { addChannel(m_deviceInfo.byStartChan + i, bMainStream); } } DevChannelHK::DevChannelHK(int64_t i64LoginId, const char* pcDevName, int iChn, bool bMainStream) : DevChannel(HK_APP_NAME,(StrPrinter<(pUser); if(self->m_i64PreviewHandle!=(int64_t)lPlayHandle) { return; } self->onPreview(dwDataType,pBuffer,dwBufSize); }, this); if (m_i64PreviewHandle == -1) { throw std::runtime_error( StrPrinter << "设备[" << pcDevName << "/" << iChn << "]开始实时预览失败:" << NET_DVR_GetLastError() << endl); } } DevChannelHK::~DevChannelHK() { InfoL << endl; if (m_i64PreviewHandle >= 0) { NET_DVR_StopRealPlay(m_i64PreviewHandle); m_i64PreviewHandle = -1; } if (m_iPlayHandle >= 0) { PlayM4_StopSoundShare(m_iPlayHandle); PlayM4_Stop(m_iPlayHandle); m_iPlayHandle = -1; } } void DevChannelHK::onPreview(DWORD dwDataType, BYTE* pBuffer, DWORD dwBufSize) { //TimeTicker1(-1); switch (dwDataType) { case NET_DVR_SYSHEAD: { //系统头数据 if (!PlayM4_GetPort(&m_iPlayHandle)) { //获取播放库未使用的通道号 WarnL << "PlayM4_GetPort:" << NET_DVR_GetLastError(); break; } if (dwBufSize > 0) { if (!PlayM4_SetStreamOpenMode(m_iPlayHandle, STREAME_REALTIME)) { //设置实时流播放模式 WarnL << "PlayM4_SetStreamOpenMode:" << NET_DVR_GetLastError(); break; } if (!PlayM4_OpenStream(m_iPlayHandle, pBuffer, dwBufSize, 1024 * 1024)) { //打开流接口 WarnL << "PlayM4_OpenStream:" << NET_DVR_GetLastError(); break; } PlayM4_SetDecCallBackMend(m_iPlayHandle, [](int nPort,char * pBuf,int nSize,FRAME_INFO * pFrameInfo, void* nUser,int nReserved2) { DevChannelHK *chn=reinterpret_cast(nUser); if(chn->m_iPlayHandle!=nPort) { return; } chn->onGetDecData(pBuf,nSize,pFrameInfo); }, this); if (!PlayM4_Play(m_iPlayHandle, 0)) { //播放开始 WarnL << "PlayM4_Play:" << NET_DVR_GetLastError(); break; } InfoL << "设置解码器成功!" << endl; //打开音频解码, 需要码流是复合流 if (!PlayM4_PlaySoundShare(m_iPlayHandle)) { WarnL << "PlayM4_PlaySound:" << NET_DVR_GetLastError(); break; } } } break; case NET_DVR_STREAMDATA: { //流数据(包括复合流或音视频分开的视频流数据) if (dwBufSize > 0 && m_iPlayHandle != -1) { if (!PlayM4_InputData(m_iPlayHandle, pBuffer, dwBufSize)) { WarnL << "PlayM4_InputData:" << NET_DVR_GetLastError(); break; } } } break; case NET_DVR_AUDIOSTREAMDATA: { //音频数据 } break; case NET_DVR_PRIVATE_DATA: { //私有数据,包括智能信息 } break; default: break; } } void DevChannelHK::onGetDecData(char* pBuf, int nSize, FRAME_INFO* pFrameInfo) { //InfoL << pFrameInfo->nType; switch (pFrameInfo->nType) { case T_YV12: { if (!m_bVideoSeted) { m_bVideoSeted = true; VideoInfo video; video.iWidth = pFrameInfo->nWidth; video.iHeight = pFrameInfo->nHeight; video.iFrameRate = pFrameInfo->nFrameRate; initVideo(video); } char *yuv[3]; int yuv_len[3]; yuv_len[0] = pFrameInfo->nWidth; yuv_len[1] = pFrameInfo->nWidth / 2; yuv_len[2] = pFrameInfo->nWidth / 2; int dwOffset_Y = pFrameInfo->nWidth * pFrameInfo->nHeight; yuv[0] = pBuf; yuv[2] = yuv[0] + dwOffset_Y; yuv[1] = yuv[2] + dwOffset_Y / 4; inputYUV(yuv, yuv_len, pFrameInfo->nStamp); } break; case T_AUDIO16: { if (!m_bAudioSeted) { m_bAudioSeted = true; AudioInfo audio; audio.iChannel = pFrameInfo->nWidth; audio.iSampleBit = pFrameInfo->nHeight; audio.iSampleRate = pFrameInfo->nFrameRate; initAudio(audio); } inputPCM(pBuf, nSize, pFrameInfo->nStamp); } break; default: break; } } } /* namespace mediakit */ #endif //ENABLE_HKDEVICE