#include "stdafx.h" #include "SpBase.h" #include "SpIni.h" #include "Event.h" #include "mod_mediacontroller/Event.h" #include "mod_assistantchannel/AssistantChannel_client_g.h" using namespace AssistantChannel; #include "mod_assistantchannel/chan_protocol.h" #include "rec_common.h" #include "libvideoqueue.h" #include "libfacecapture.h" #include "jpeg2k.h" #include "videoutil.h" #include "y2k_time.h" #include "EventCode.h" #include "CommEntityUtil.hpp" #include "cv.h" #include "highgui.h" #define LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE 0x50500001 //协助通道重启 #ifdef RVC_OS_WIN #define ENV_CAP_TIMEOUT 15 #define OPT_CAP_TIMEOUT 10 #else #define ENV_CAP_TIMEOUT 150 #define OPT_CAP_TIMEOUT 100 #endif class CPhotoCaptureEntity; class ChannelClient : public ChannelService_ClientBase { public: ChannelClient(CPhotoCaptureEntity *pEntity); virtual void OnMessage(ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer pData); }; // 旋转180度 int RotationDown(unsigned char* src, int srcW, int srcH, int channel) { unsigned char* tempSrc = NULL; int mSize = srcW * srcH * sizeof(char) * channel; int i = 0; int j = 0; int k = 0; int desW = 0; int desH = 0; desW = srcW; desH = srcH; tempSrc = (unsigned char*)malloc(sizeof(char) * srcW * srcH * channel); memcpy(tempSrc, src, mSize); for (i = 0; i < desH; i++) { for (j = 0; j < desW; j++) { for (k = 0; k < channel; k++) { //src[(i * desW + j) * channel + k] = tempSrc[((srcH - 1 - i) * srcW + srcW - 1 - j) * channel + k]; src[(i * desW + j) * channel + k] = tempSrc[((srcH - 1 - i) * srcW + j) * channel + k]; } } } free(tempSrc); return 0; } // id: 0x905 class CPhotoCaptureEntity : public CEntityBase, public ITimerListener, public ILogListener { public: CPhotoCaptureEntity() : m_video_env_q(NULL), m_video_opt_q(NULL), m_dwCapture(0) {} virtual ~CPhotoCaptureEntity() {} virtual const char *GetEntityName() const { return "Snapshot"; } virtual void OnPreStart(CAutoArray strArgs,CSmartPointer pTransactionContext) { ErrorCodeEnum Error = __OnStart(Error_Succeed); pTransactionContext->SendAnswer(Error); } virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer pTransactionContext) { ErrorCodeEnum Error = __OnClose(Error_Succeed); pTransactionContext->SendAnswer(Error); } ErrorCodeEnum __OnStart(ErrorCodeEnum preOperationError) { LOG_FUNCTION(); if (preOperationError != Error_Succeed) return preOperationError; //is Pad Version CSmartPointer spFunction = GetFunction(); CSystemStaticInfo stStaticinfo; spFunction->GetSystemStaticInfo(stStaticinfo); if (stricmp(stStaticinfo.strMachineType,"RVC.PAD")==0) { if (stricmp(stStaticinfo.strSite,"CMB.FLB")==0) { LOG_TRACE("the type is mobile pad"); m_eDeviceType = eMobilePadType; } else { LOG_TRACE("the type is pad"); m_eDeviceType = ePadtype; } } else if (stricmp(stStaticinfo.strMachineType,"RVC.Desk2S")==0) { LOG_TRACE("the type is Desk2S"); m_eDeviceType = eDesk2SType; } else if (stricmp(stStaticinfo.strMachineType,"RPM.Stand1S")==0) { LOG_TRACE("the type is RPM.Stand1S"); m_eDeviceType = eRpm1sType; } else { LOG_TRACE("the type is standard"); m_eDeviceType = eStand2sType; } ErrorCodeEnum Error; //int nCameraCount = 0; //ErrorCodeEnum Error; //Error = DecideCameraCount(nCameraCount); //if (Error != Error_Succeed || nCameraCount < 0 || nCameraCount > 2) { // LOG_TRACE("decide camera count failed!"); // return Error; //} //if ((ePadtype == m_eDeviceType)||(eMobilePadType == m_eDeviceType)||(eDesk2SType == m_eDeviceType) ) //{ // m_video_env_q = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_SNAPSHOT_QUEUE); //} //else //{ // == 2 // m_video_env_q = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_SNAPSHOT_QUEUE); // m_video_opt_q = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_SNAPSHOT_QUEUE); //} m_pChannelClient = new ChannelClient(this); Error = m_pChannelClient->Connect(); if (Error != Error_Succeed) { m_pChannelClient->SafeDelete(); return Error; } ChannelService_BeginRecv_Sub Sub; Sub.type = ACM_TYPE_PHT; Error = m_pChannelClient->BeginRecv(Sub); if (Error != Error_Succeed) { m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; return Error; } CSmartPointer spFunc = GetFunction(); int i = 0; m_arrListener.Init(4); spFunc->SubscribeLog(m_arrListener[i++], this, Log_Event, Severity_None, Error_IgnoreAll, MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_ENV); spFunc->SubscribeLog(m_arrListener[i++], this, Log_Event, Severity_None, Error_IgnoreAll, MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_OPT); spFunc->SubscribeLog(m_arrListener[i++], this, Log_Event, Severity_None, Error_IgnoreAll, MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_ENVOPT); spFunc->SubscribeLog(m_arrListener[i++], this, Log_Event, Severity_None, Error_IgnoreAll, LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE,NULL,false); return Error; } ErrorCodeEnum __OnClose(ErrorCodeEnum preOperationError) { LOG_FUNCTION(); CSmartPointer spFunction = GetFunction(); for (int i = 0; i < m_arrListener.GetCount(); ++i) { spFunction->UnsubscribeLog(m_arrListener[i]); } if (preOperationError != Error_Succeed) return preOperationError; if (m_pChannelClient) { m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; } if (NULL != m_video_env_q) { delete m_video_env_q; m_video_env_q = NULL; } if (NULL != m_video_opt_q) { delete m_video_opt_q; m_video_opt_q = NULL; } return Error_Succeed; } void WriteStamp(video_frame *srcfrm) { #ifdef RVC_OS_WIN __try { CImageFrame frm; frm.data = srcfrm->data[0]; frm.width = srcfrm->width; frm.height = srcfrm->height; frm.framesize = srcfrm->width * srcfrm->height * 3; if (!SnapShot(&frm)) { Dbg("write stamp failed!"); } } __except (EXCEPTION_EXECUTE_HANDLER) { Dbg("snapshot throw windows exception!"); } #else CImageFrame frm; frm.data = srcfrm->data[0]; frm.width = srcfrm->width; frm.height = srcfrm->height; frm.framesize = srcfrm->width * srcfrm->height * 3; if (!SnapShot(&frm)) { Dbg("write stamp failed!"); } #endif } void Capture(int rc) { video_frame *frm = NULL; if((rc == 0)||(rc==Error_TimeOut)) { if (m_video_env_q && m_video_opt_q) { int combine_width = REC_COMMON_VIDEO_SNAPSHOT_WIDTH; int combine_height = REC_COMMON_VIDEO_SNAPSHOT_WIDTH + REC_COMMON_VIDEO_SNAPSHOT_HEIGHT; frm = video_frame_new(combine_width, combine_height, VIDEO_FORMAT_RGB24); video_frame_fill_black(frm); // get env snapshot { video_frame tmp_frm = {0}; tmp_frm.data[0] = frm->data[0]; tmp_frm.linesize[0] = frm->linesize[0]; tmp_frm.format = frm->format; tmp_frm.width = REC_COMMON_VIDEO_SNAPSHOT_WIDTH; tmp_frm.height = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT; DWORD time = m_video_env_q->GetLastFrameTime(); y2k_time_t nowtime = y2k_time_now(); Dbg("%s:%d env now time is %d, get frame time is %d, time interval is %ds.", __FUNCTION__, __LINE__, nowtime, time, nowtime - time); if ((nowtime - time) < ENV_CAP_TIMEOUT) { m_video_env_q->GetVideo2(&tmp_frm, 0); } else { Dbg("the env snapshot videoqueque image timeout!"); } } // get opt snapshot { video_frame tmp_frm = {0}; tmp_frm.data[0] = frm->data[0] + frm->linesize[0] * REC_COMMON_VIDEO_SNAPSHOT_HEIGHT+(REC_COMMON_VIDEO_SNAPSHOT_WIDTH-REC_COMMON_VIDEO_SNAPSHOT_HEIGHT)/2*3; tmp_frm.linesize[0] = frm->linesize[0]; tmp_frm.format = frm->format; tmp_frm.width = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT; tmp_frm.height = REC_COMMON_VIDEO_SNAPSHOT_WIDTH; DWORD time = m_video_opt_q->GetLastFrameTime(); y2k_time_t nowtime = y2k_time_now(); Dbg("%s:%d opt now time is %d, get frame time is %d, time interval is %ds.", __FUNCTION__, __LINE__, nowtime, time, nowtime - time); if ((nowtime - time) < OPT_CAP_TIMEOUT) { m_video_opt_q->GetVideo2(&tmp_frm, 0); } else { Dbg("the opt snapshot videoqueque image timeout!"); } } } else if (m_video_env_q) { frm = video_frame_new(REC_COMMON_VIDEO_SNAPSHOT_WIDTH, REC_COMMON_VIDEO_SNAPSHOT_HEIGHT, VIDEO_FORMAT_RGB24); video_frame_fill_black(frm); video_frame tmp_frm = {0}; tmp_frm.data[0] = frm->data[0]; tmp_frm.linesize[0] = frm->linesize[0]; tmp_frm.format = frm->format; tmp_frm.width = REC_COMMON_VIDEO_SNAPSHOT_WIDTH; tmp_frm.height = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT; DWORD time = m_video_env_q->GetLastFrameTime(); y2k_time_t nowtime = y2k_time_now(); Dbg("%s:%d env now time is %d, get frame time is %d, time interval is %ds.", __FUNCTION__, __LINE__, nowtime, time, nowtime - time); if ((nowtime - time) < ENV_CAP_TIMEOUT) { m_video_env_q->GetVideo2(&tmp_frm, 0); } else { Dbg("the env snapshot videoqueque image timeout!"); } } else { //assert(0); // not go here rc = -1; } #ifndef RVC_OS_WIN { //linux需翻转环境摄像头图像 int size = frm->linesize[0] * frm->height; Dbg("size = %d, width= %d height= %d", size, frm->width, frm->height); RotationDown(frm->data[0], frm->width, REC_COMMON_VIDEO_SNAPSHOT_HEIGHT, 3); } #endif } jpeg2k_coded_image codec_image = {0}; if((rc == 0)||(rc==Error_TimeOut)) { WriteStamp(frm); jpeg2k_raw_image raw_image; raw_image.data = frm->data[0]; raw_image.width = frm->width; raw_image.height = frm->height; raw_image.len = raw_image.width * raw_image.height * 3; rc = jpeg2k_encode(&raw_image, &codec_image, 10); } if ((rc == 0)||(rc==Error_TimeOut)) { ChannelService_Send_Info Info; Info.compress = false; Info.encrypt = false; Info.type = ACM_TYPE_PHT; Info.id = 0; Info.sub_type = ACM_PHT_ANS | ACM_PHT_SNAPSHOT; Info.data.m_pData = (char *)codec_image.data; Info.data.m_iLength = codec_image.len; m_pChannelClient->Send(Info); jpeg2k_encode_free(&codec_image); } else { ChannelService_Send_Info Info; Info.compress = false; Info.encrypt = false; Info.type = ACM_TYPE_PHT; Info.id = 0; Info.sub_type = ACM_PHT_ANS | ACM_PHT_SNAPSHOT; Info.data.m_pData = (char *)&rc; Info.data.m_iLength = sizeof(rc); m_pChannelClient->Send(Info); } #if 0 video_frame_save_bmpfile("snapshot_abc.bmp", frm); //video_frame_save_bmpfile("d:\\ab.bmp", &frm); #endif if (frm) video_frame_delete(frm); } ErrorCodeEnum StartCapture(int id) { if ((ePadtype == m_eDeviceType) || (eMobilePadType == m_eDeviceType) || (eDesk2SType == m_eDeviceType)){ m_video_env_q = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_SNAPSHOT_QUEUE); } else{ // == 2 m_video_env_q = new Clibvideoqueue(REC_COMMON_VIDEO_ENV_SHM_SNAPSHOT_QUEUE); m_video_opt_q = new Clibvideoqueue(REC_COMMON_VIDEO_OPT_SHM_SNAPSHOT_QUEUE); } if (!m_video_env_q && !m_video_opt_q) { Dbg("cannot start capture!"); // never go here return Error_Unexpect; } if (m_dwCapture) { LOG_TRACE("already start capture!"); return Error_Duplication; } //触发对应的摄像头进行图像采集 if (m_video_env_q && m_video_opt_q) { LogEvent(Severity_Middle, MOD_EVENT_SNAPSHOT_START_CAPTURE_ENVOPT, "agent start capture env and opt camera picture!"); } else if (m_video_env_q) { LogEvent(Severity_Middle, MOD_EVENT_SNAPSHOT_START_CAPTURE_ENV, "agent start capture env camera picture!"); } else if (m_video_opt_q) { LogEvent(Severity_Middle, MOD_EVENT_SNAPSHOT_START_CAPTURE_OPT, "agent start capture opt camera picture!"); } m_dwCapture = SP::Module::Comm::RVCGetTickCount(); GetFunction()->SetTimer(1, this, 2000); return Error_Succeed; } void StopCapture() { GetFunction()->KillTimer(1); m_dwCapture = 0; } virtual void OnTimeout(DWORD dwTimerID) { Capture(Error_TimeOut); Dbg("timeout!"); GetFunction()->KillTimer(dwTimerID); m_dwCapture = 0; } virtual void OnLog(const CAutoArray &SubIDs, const CUUID nLogID,const LogTypeEnum eLogType, const SeverityLevelEnum eLevel, const DWORD dwSysError,const DWORD dwUserCode,const DWORD dwEntityInstanceID, const WORD wEntityDevelID, const CAutoArray &Param, const char *pszEntityName, const char *pszModuleName,const char *pszMessage) { if (dwUserCode == MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_ENVOPT || dwUserCode == MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_OPT || dwUserCode == MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_ENV) { DWORD dwNow = SP::Module::Comm::RVCGetTickCount(); LOG_TRACE("capture duration:%dms", dwNow - m_dwCapture); Capture(Error_Succeed); StopCapture(); } else if (dwUserCode == LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE) { Dbg("recv LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE"); if (m_pChannelClient != NULL) { m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; Dbg("Close AssistChannel Session "); } if (m_pChannelClient == NULL) { Dbg("ReConnection AssistChannel Session"); m_pChannelClient = new ChannelClient(this); ErrorCodeEnum Error = m_pChannelClient->Connect(); if (Error != Error_Succeed) { m_pChannelClient->SafeDelete(); m_pChannelClient = NULL; Dbg("AssistChannelClient connect fail!"); } if (Error == Error_Succeed) { ChannelService_BeginRecv_Sub Sub; Sub.type = ACM_TYPE_PHT; Error = m_pChannelClient->BeginRecv(Sub); if (Error != Error_Succeed) { m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; } } } } } private: // we use root.ini Video section config to decide camera count ErrorCodeEnum DecideCameraCount(int &nCount) { CSmartPointer spFunction = GetFunction(); CSmartPointer spConfig; ErrorCodeEnum Error = spFunction->OpenConfig(Config_Root, spConfig); if (Error == Error_Succeed) { CSimpleStringA strVideoEnv; CSimpleStringA strVideoOpt; SpIniMappingTable table; nCount = 0; table.AddEntryString("Video", "EnvCamera", strVideoEnv, "$"); table.AddEntryString("Video", "OptCamera", strVideoOpt, "$"); Error = table.Load(spConfig); if (Error == Error_Succeed) { if (strVideoEnv.GetLength() > 1) nCount++; if (strVideoOpt.GetLength() > 1) nCount++; } } return Error; } private: Clibvideoqueue *m_video_env_q; Clibvideoqueue *m_video_opt_q; ChannelClient *m_pChannelClient; CUUID m_uuidCaptureTimer; DWORD m_dwCapture; DeviceTypeEnum m_eDeviceType; CAutoArray m_arrListener; }; void ChannelClient::OnMessage( ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer pData ) { LOG_FUNCTION(); if (Error == Error_Succeed) { CPhotoCaptureEntity *pEntity = static_cast(m_pEntityBase); int cat = ACM_PHT_CAT(Msg.sub_type); if (cat == ACM_PHT_REQ) { Error = pEntity->StartCapture(Msg.id); if (Error) { pEntity->Capture(Error); } } else { _ASSERT(0); } } } ChannelClient::ChannelClient( CPhotoCaptureEntity *pEntity ) : ChannelService_ClientBase(pEntity) { } SP_BEGIN_ENTITY_MAP() SP_ENTITY(CPhotoCaptureEntity) SP_END_ENTITY_MAP()