#include "stdafx.h" #include "SpBase.h" #include "SpIni.h" #include "Event.h" #include "mod_mediacontroller/Event.h" #include "AssistantChannel_client_g.h" using namespace AssistantChannel; #include "chan_protocol.h" #include "rvc_media_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" #include "../mod_interactivecontrol/Event.h" #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 #ifndef RVC_SAFE_DELETE #define RVC_SAFE_DELETE(p) { if(p){ (p)->SafeDelete(); (p)=NULL;} } #endif //RVC_SAFE_DELETE #ifndef MAX_PATH #define MAX_PATH 260 #endif class CPhotoCaptureEntity; class ChannelClient : public ChannelService_ClientBase { public: ChannelClient(CPhotoCaptureEntity *pEntity); virtual void OnMessage(ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer pData); }; 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), m_bConnectAssist(false) { m_pChannelClient = NULL; } 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) { if (preOperationError != Error_Succeed) { return preOperationError; } //is Pad Version m_eDeviceType = RvcGetDeviceType(); if (eStand1SPlusType == 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); } 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_MOD_ASSISCHAN_STARTED_SUCCESS,NULL,false); return Error_Succeed; } void OnStarted() { m_pChannelClient = new ChannelClient(this); if (Error_Succeed == ConnectAssistChannel()) { m_bConnectAssist = true; } else { GetFunction()->SetTimer(2, this, 3370); } } ErrorCodeEnum __OnClose(ErrorCodeEnum preOperationError) { 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) { 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)) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("write stamp failed!"); } } 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(); if ((y2k_time_now() - time) < ENV_CAP_TIMEOUT) { m_video_env_q->GetVideo2(&tmp_frm, 0); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("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(); if ((y2k_time_now() - time) < OPT_CAP_TIMEOUT) { m_video_opt_q->GetVideo2(&tmp_frm, 0); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("the opt snapshot video queque 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(); if ((y2k_time_now() - time) < ENV_CAP_TIMEOUT) { m_video_env_q->GetVideo2(&tmp_frm, 0); } else { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("the env snapshot video queque image timeout!"); } } else { //assert(0); // not go here rc = -1; } #ifndef RVC_OS_WIN { int size = frm->linesize[0] * 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)(EntityResource::getLink().upgradeLink())->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)(EntityResource::getLink().upgradeLink())->Send(Info); } if (frm) { video_frame_delete(frm); } } ErrorCodeEnum StartCapture(int id) { #if defined(RVC_OS_LINUX) if (eStand1SPlusType == 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); } #endif //RVC_OS_LINUX if (!m_video_env_q && !m_video_opt_q) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("cannot start capture!"); // never go here return Error_Unexpect; } if (m_dwCapture) { 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; } DeviceTypeEnum RvcGetDeviceType() { DeviceTypeEnum eType = eStand2sType; CSmartPointer spFunction = GetFunction(); CSystemStaticInfo stStaticinfo; spFunction->GetSystemStaticInfo(stStaticinfo); if (_stricmp(stStaticinfo.strMachineType, "RVC.Stand1SPlus") == 0) { eType = eStand1SPlusType; } else if (stricmp(stStaticinfo.strMachineType, "RVC.CardStore") == 0 || stricmp(stStaticinfo.strMachineType, "RVC.CardPrinter") == 0) { eType = eCardStore; } else { eType = eStand2sType; } if (eType >= 0 && eType < sizeof(Device_Type_Table) / sizeof(char*)) { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("device type is %s.", Device_Type_Table[eType]); } return eType; } virtual void OnTimeout(DWORD dwTimerID) { if (1 == dwTimerID) { Capture(Error_TimeOut); GetFunction()->KillTimer(dwTimerID); m_dwCapture = 0; } else if (2 == dwTimerID) { if (false == m_bConnectAssist) { if (Error_Succeed == ConnectAssistChannel()) { m_bConnectAssist = true; } } if (true == m_bConnectAssist) { GetFunction()->KillTimer(2); } } } 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, const linkContext& pLinkInfo) { switch (dwUserCode) { case MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_ENVOPT: case MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_OPT: case MOD_EVENT_MEDIACONTROLLER_FINISHED_CAPTURE_ENV: { DWORD dwNow = SP::Module::Comm::RVCGetTickCount(); Capture(Error_Succeed); StopCapture(); } break; case LOG_EVT_MOD_ASSISCHAN_STARTED_SUCCESS: { Sleep(975); if (m_pChannelClient != NULL) { m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; m_bConnectAssist = false; } if (Error_Succeed == ConnectAssistChannel()) { m_bConnectAssist = true; } else { GetFunction()->SetTimer(2, this, 3370); } } break; default: { DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("unknown dwUserCode = 0x%08x.", dwUserCode); } break; } } private: ErrorCodeEnum ConnectAssistChannel() { if (m_pChannelClient == NULL){ m_pChannelClient = new ChannelClient(this); } ErrorCodeEnum Error = m_pChannelClient->Connect(); if (Error_Succeed != Error){ m_pChannelClient = NULL; DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("AssistChannelClient connect fail!"); return Error; } if (Error_Succeed == Error){ ChannelService_BeginRecv_Sub Sub; Sub.type = ACM_TYPE_PHT; Error = (*m_pChannelClient)(EntityResource::getLink().upgradeLink())->BeginRecv(Sub); if (Error_Succeed != Error){ DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("BeginRecv ACM_TYPE_PHT fail!"); m_pChannelClient->GetFunction()->CloseSession(); m_pChannelClient = NULL; return Error; } } 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; bool m_bConnectAssist; }; void ChannelClient::OnMessage( ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer pData ) { 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()