mod_facetracking.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526
  1. #include "stdafx.h"
  2. #include "SpBase.h"
  3. #include "SpIni.h"
  4. #include "../mod_assistantchannel/AssistantChannel_client_g.h"
  5. using namespace AssistantChannel;
  6. #include "../mod_assistantchannel/chan_protocol.h"
  7. #include "rvc_media_common.h"
  8. #include "libvideoqueue.h"
  9. #include "jpeg2k.h"
  10. #include "libfacecapture.h"
  11. #include "y2k_time.h"
  12. #include "sysvar.h"
  13. #include "Event.h"
  14. #include "fileutil.h"
  15. #include "EventCode.h"
  16. #include "../mod_mediacontroller/Event.h"
  17. #ifndef MAX_LOG_LEN
  18. #define MAX_LOG_LEN 512
  19. #endif
  20. #ifndef rvc_snprintf
  21. #ifdef RVC_OS_WIN
  22. #define rvc_snprintf _snprintf
  23. #else
  24. #define rvc_snprintf snprintf
  25. #endif // RVC_OS_WIN
  26. #endif // rvc_snprintf
  27. // 脸部跟踪&拍照 devel: 0x302
  28. static struct {
  29. int monitor_id;
  30. int evt_code;
  31. char* evt_msg;
  32. } monitor_id_evtmsg[] = {
  33. {0, EVENT_MOD_CUSTOMER_CLOSE, "客户接近 1.5m"},
  34. {1, EVENT_MOD_CUSTOMER_LEAVE, "客户消失或退出到接近距离1.5M之外"},
  35. {2, EVENT_MOD_CUSTOMER_ENTEROPERATE, "客户进入操作距离0.5m"},
  36. {3, EVENT_MOD_CUSTOMER_BACKTOCLOSE, "客户退回到接近距离"},
  37. {4, EVENT_MOD_CUSTOMER_APPEAR, "有人出现"},
  38. {5, EVENT_MOD_CUSTOMER_CHANGE, "客户已经换人"},
  39. {6, EVENT_MOD_CUSTOMER_CAPTUREFACE, "捕获脸部事件"},
  40. {7, EVENT_MOD_CUSTOMER_LOSEFACE, "失去脸部事件"},
  41. {8, EVENT_MOD_FACE_BREAKDOWN,"the opencv library breakdown"}
  42. };
  43. class CFaceTrackingEntity;
  44. class ChannelClient : public ChannelService_ClientBase
  45. {
  46. public:
  47. ChannelClient(CFaceTrackingEntity *pEntity);
  48. virtual void OnMessage(ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer<IReleasable> pData);
  49. };
  50. class CFaceTrackingEntity : public CEntityBase, public CHostApi , public CVideoMonitorEvent, public ISysVarListener, public ITimerListener,public ILogListener
  51. {
  52. public:
  53. CFaceTrackingEntity() : m_facecapture(NULL), bIsSessionChange(false),strCustomerID(false),strSessionID(false),bIsCustomerChange(false), m_bSingleCamera(false)
  54. {
  55. // note: this object initialize at DllMain, so it suggests keep your code simple here.
  56. // 1) do simple initializing here
  57. // 2) dont do complex operation, complex operation such as create new process(thread) and so on
  58. }
  59. virtual ~CFaceTrackingEntity() {}
  60. virtual const char *GetEntityName() const { return "FaceTracking"; }
  61. virtual void OnPreStart(CAutoArray<CSimpleStringA> strArgs,CSmartPointer<ITransactionContext> pTransactionContext)
  62. {
  63. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  64. ErrorCodeEnum Error;
  65. bool bRet = false;
  66. m_facecapture = new Clibfacecapture(&bRet, this, this, REC_COMMON_VIDEO_ENV_SHM_RTP_QUEUE, REC_COMMON_VIDEO_ENV_SHM_SNAPSHOT_QUEUE, REC_COMMON_VIDEO_OPT_SHM_RTP_QUEUE);
  67. if (!bRet)
  68. {
  69. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("load libface capture failed!");
  70. pTransactionContext->SendAnswer(Error_Resource);
  71. return;
  72. }
  73. Error = GetFunction()->RegistSysVarEvent("SessionID", this);
  74. if (Error != Error_Succeed)
  75. {
  76. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("register sysvar %s failed!", "SessionID");
  77. }
  78. Error = GetFunction()->RegistSysVarEvent("CustomerID", this);
  79. if (Error != Error_Succeed)
  80. {
  81. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("register sysvar %s failed!", "CustomerID");
  82. }
  83. Error = GetFunction()->RegistSysVarEvent(SYSVAR_CAMERASTATE, this);
  84. if (Error != Error_Succeed)
  85. {
  86. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("register sysvar %s failed!", SYSVAR_CAMERASTATE);
  87. }
  88. CSimpleStringA strValue;
  89. GetFunction()->GetSysVar(SYSVAR_CAMERASTATE, strValue);
  90. if (strValue[0] == 'N')
  91. {
  92. m_facecapture->SetCameraState(0);
  93. }
  94. else if (strValue[0] == 'E')
  95. {
  96. m_facecapture->SetCameraState(1);
  97. }
  98. else if (strValue[0] == 'O')
  99. {
  100. m_facecapture->SetCameraState(2);
  101. }
  102. else if (strValue[0] == 'B')
  103. {
  104. m_facecapture->SetCameraState(3);
  105. }
  106. //is Pad Version
  107. CSystemStaticInfo stStaticinfo;
  108. spFunction->GetSystemStaticInfo(stStaticinfo);
  109. if (stricmp(stStaticinfo.strMachineType,"RVC.Stand1SPlus")==0){
  110. m_bSingleCamera = true;
  111. }
  112. spFunction->SubscribeLog(m_UUid1, this, Log_Event, Severity_None, Error_IgnoreAll, LOG_EVT_HEADLIGHT_GREEN_OFF,NULL,false);
  113. spFunction->SubscribeLog(m_UUid2, this, Log_Event, Severity_None, Error_IgnoreAll, LOG_EVT_MEDIACONTROLLER_CAMERA_STARTED,NULL,false);
  114. spFunction->SubscribeLog(m_UUid3, this, Log_Event, Severity_None, Error_IgnoreAll, LOG_EVT_MEDIACONTROLLER_CAMERA_STOPPED,NULL,false);
  115. spFunction->SubscribeLog(m_UUid4, this, Log_Event, Severity_None, Error_IgnoreAll, LOG_EVT_MEDIACONTROLLER_RESET_ACTIVECAMERA, NULL, false);
  116. pTransactionContext->SendAnswer(Error);
  117. }
  118. virtual void OnStarted()
  119. {
  120. LogEvent(Severity_Middle, LOG_EVT_MOD_FACETRACKING_STARTED_SUCCESS, "facetracking entity started successfully.");
  121. }
  122. virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext)
  123. {
  124. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  125. delete m_facecapture;
  126. m_facecapture = NULL;
  127. spFunction->UnsubscribeLog(m_UUid1);
  128. spFunction->UnsubscribeLog(m_UUid2);
  129. spFunction->UnsubscribeLog(m_UUid3);
  130. spFunction->UnsubscribeLog(m_UUid4);
  131. spFunction->UnregistSysVarEvent("SessionID");
  132. spFunction->UnregistSysVarEvent("CustomerID");
  133. spFunction->UnregistSysVarEvent(SYSVAR_CAMERASTATE);
  134. pTransactionContext->SendAnswer(Error_Succeed);
  135. }
  136. virtual void OnPaused()
  137. {
  138. Capture(0);
  139. }
  140. int TransCameraStateToInt(char cData)
  141. {
  142. int iRet = 0;
  143. if ('E' == cData){
  144. iRet = 1;
  145. }
  146. else if('O' == cData){
  147. iRet = 2;
  148. }
  149. else if('B' == cData){
  150. iRet = 3;
  151. }
  152. return iRet;
  153. }
  154. void OnLog(const CAutoArray<CUUID> &SubIDs, const CUUID nLogID,const LogTypeEnum eLogType, const SeverityLevelEnum eLevel,
  155. const DWORD dwSysError,const DWORD dwUserCode,const DWORD dwEntityInstanceID, const WORD wEntityDevelID,
  156. const CAutoArray<DWORD> &Param, const char *pszEntityName, const char *pszModuleName,const char *pszMessage, const linkContext &pLinkInfo)
  157. {
  158. switch (dwUserCode)
  159. {
  160. case LOG_EVT_HEADLIGHT_GREEN_OFF:
  161. m_facecapture->SetLightChange();
  162. break;
  163. case LOG_EVT_MEDIACONTROLLER_CAMERA_STARTED:
  164. {
  165. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("recv LOG_EVT_MEDIACONTROLLER_CAMERA_STARTED event");
  166. CSimpleStringA strValue;
  167. GetFunction()->GetSysVar(SYSVAR_CAMERASTATE, strValue);
  168. #if defined(RVC_OS_WIN)
  169. int iState = TransCameraStateToInt(strValue[0]);
  170. if (3 != iState) {
  171. m_facecapture->SetCameraState(iState);
  172. m_facecapture->StartFaceCapture();
  173. }
  174. else {
  175. m_facecapture->SetCameraState(3);
  176. }
  177. #else
  178. if (strValue[0] == 'N') {
  179. m_facecapture->SetCameraState(0);
  180. m_facecapture->StartFaceCapture();
  181. }
  182. else if (strValue[0] == 'E')
  183. {
  184. m_facecapture->SetCameraState(1);
  185. m_facecapture->StartFaceCapture();
  186. }
  187. else if (strValue[0] == 'O')
  188. {
  189. m_facecapture->SetCameraState(2);
  190. m_facecapture->StartFaceCapture();
  191. }
  192. else if (strValue[0] == 'B')
  193. {
  194. m_facecapture->SetCameraState(3);
  195. }
  196. #endif //RVC_OS_WIN
  197. if (!m_bSingleCamera) {
  198. GetFunction()->SetTimer(1, this, 1000);
  199. }
  200. }
  201. break;
  202. case LOG_EVT_MEDIACONTROLLER_CAMERA_STOPPED:
  203. {
  204. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("recv LOG_EVT_MEDIACONTROLLER_CAMERA_STOPPED event");
  205. m_facecapture->StopFaceCapture();
  206. CSimpleStringA strValue;
  207. GetFunction()->GetSysVar(SYSVAR_CAMERASTATE, strValue);
  208. int iState = TransCameraStateToInt(strValue[0]);
  209. m_facecapture->SetCameraState(iState);
  210. if (!m_bSingleCamera) {
  211. GetFunction()->KillTimer(1);
  212. }
  213. GetFunction()->SetSysVar(SYSVAR_ACTIVETRACKINGCAMERA, ACTIVETRACKINGCAMERA_ENV); // from Operation -> Environment
  214. }
  215. break;
  216. case LOG_EVT_MEDIACONTROLLER_RESET_ACTIVECAMERA:
  217. {
  218. CSimpleStringA strValue;
  219. GetFunction()->GetSysVar(SYSVAR_ACTIVETRACKINGCAMERA, strValue); // E or O
  220. if ('O' == strValue[0]) {
  221. GetFunction()->SetSysVar(SYSVAR_ACTIVETRACKINGCAMERA, ACTIVETRACKINGCAMERA_ENV); // from Operation -> Environment
  222. }
  223. }
  224. break;
  225. default:
  226. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("unknown event.");
  227. break;
  228. }
  229. }
  230. void Capture(int id)
  231. {
  232. #if 0
  233. CImageFrame frm;
  234. frm.data = new unsigned char[REC_COMMON_VIDEO_SNAPSHOT_WIDTH*REC_COMMON_VIDEO_SNAPSHOT_HEIGHT*4];
  235. frm.width = REC_COMMON_VIDEO_SNAPSHOT_WIDTH;
  236. frm.height = REC_COMMON_VIDEO_SNAPSHOT_HEIGHT;
  237. frm.framesize = frm.width * frm.height * 3;
  238. if (m_facecapture->SnapShot(frm)) {
  239. int rc;
  240. jpeg2k_raw_image raw_image;
  241. jpeg2k_coded_image codec_image = {0};
  242. raw_image.data = frm.data;
  243. raw_image.width = frm.width;
  244. raw_image.height = frm.height;
  245. raw_image.len = raw_image.width * raw_image.height * 3;
  246. rc = jpeg2k_encode(&raw_image, &codec_image, 10);
  247. if (rc == 0) {
  248. ChannelService_Send_Info Info;
  249. Info.compress = false;
  250. Info.encrypt = false;
  251. Info.type = ACM_TYPE_PHT;
  252. Info.id = id;
  253. Info.sub_type = ACM_PHT_ANS | ACM_PHT_SNAPSHOT;
  254. Info.data.m_pData = codec_image.data;
  255. Info.data.m_iLength = codec_image.len;
  256. (*m_pChannelClient)(EntityResource::getLink().upgradeLink())->Send(Info);
  257. }
  258. jpeg2k_encode_free(&codec_image);
  259. } else {
  260. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("get video frm failed!");
  261. }
  262. delete frm.data;
  263. #endif
  264. }
  265. //////////////////////////////////////////////////////////////////////////////////////////////////////
  266. // ITimerListener implementation
  267. virtual void OnTimeout(DWORD dwTimerID)
  268. {
  269. uint64_t uid;
  270. CCustomerStatus status;
  271. //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("before GetMainCustomerStatus");
  272. if (m_facecapture->GetMainCustomerStatus(uid, status))
  273. {
  274. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  275. CSimpleStringA strValue;
  276. //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("OnTimeout, check value, eCamera = %d", status.stCustomerPos.eCamera);
  277. spFunction->GetSysVar(SYSVAR_ACTIVETRACKINGCAMERA, strValue); // E or O
  278. if (status.stCustomerPos.eCamera == EnvironCamera)
  279. {
  280. if (strValue[0] == 'O')
  281. {
  282. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("ActiveTrackingCamera change from Opt->Env!");
  283. spFunction->SetSysVar(SYSVAR_ACTIVETRACKINGCAMERA, ACTIVETRACKINGCAMERA_ENV); // from Operation -> Environment
  284. }
  285. }
  286. else
  287. {
  288. if (strValue[0] == 'E')
  289. {
  290. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("ActiveTrackingCamera change from Env->Opt!");
  291. spFunction->SetSysVar(SYSVAR_ACTIVETRACKINGCAMERA, ACTIVETRACKINGCAMERA_OPT); // from Environment -> Operation
  292. }
  293. }
  294. }
  295. else
  296. {
  297. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("GetMainCustomerStatus failed!");
  298. }
  299. }
  300. //////////////////////////////////////////////////////////////////////////////////////////////////////
  301. // CHostApi implementation
  302. virtual uint64_t GenerateUUID()
  303. {
  304. m_lastUUID = CUUID::Create(m_lastUUID);
  305. return m_lastUUID;
  306. }
  307. virtual bool IsCustomerChange()
  308. {
  309. bool bChange = bIsSessionChange||bIsCustomerChange;
  310. return bChange;
  311. }
  312. virtual void GetFaceImgName(char* FaceName, uint32_t uLen)
  313. {
  314. CSimpleStringA strPath;
  315. ErrorCodeEnum Error = GetFunction()->GetPath("UploadPhoto", strPath);
  316. if (Error == Error_Succeed)
  317. {
  318. if (((const char*)strCustomerID == NULL)||(_stricmp(strCustomerID,"N") == 0))
  319. {
  320. rvc_snprintf(FaceName, uLen,"%s%s%s_0", strPath.GetData(), SPLIT_SLASH_STR, strSessionID.GetData());
  321. }
  322. else
  323. {
  324. rvc_snprintf(FaceName, uLen, "%s%s%s_%s", strPath.GetData(), SPLIT_SLASH_STR, strSessionID.GetData(), strCustomerID.GetData());
  325. }
  326. bIsSessionChange = false;
  327. bIsCustomerChange = false;
  328. }
  329. else
  330. {
  331. DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("getpath uploadphoto failed!");
  332. }
  333. }
  334. virtual bool LoadConfig(CFaceCaptureConfig &config)
  335. {
  336. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  337. CSmartPointer<IConfigInfo> spConfig;
  338. ErrorCodeEnum Error(Error_Succeed);
  339. /*
  340. PrimCamera=1
  341. UpCameraEdgeLimit=3
  342. DownCameraEdgeLimit=2
  343. ServersType=0
  344. ContourMinAera=14400
  345. FaceDataDirPath=facedata
  346. OperateFaceSize=4.2
  347. CloseFaceSize=6.6
  348. FarFaceSize=8.2
  349. SearchFaceSize=8.2
  350. DetectFaceSize=6.6
  351. FaceSizeOffset=18
  352. SleepLong=800
  353. SleepMiddle=600
  354. SleepShort=500
  355. ThresholdNum=10
  356. */
  357. CSimpleStringA strPath;
  358. config.nServersType = 0;
  359. GetFunction()->GetPath("cfg", strPath);
  360. strcpy(config.strFaceDataDirPath, strPath);
  361. strcat(config.strFaceDataDirPath, SPLIT_SLASH_STR "facedata");
  362. config.nPrimCamera = 1;
  363. config.nContourMinAera = 14400;
  364. config.nUpCameraEdgeLimit = 3;
  365. config.nDownCameraEdgeLimit = 2;
  366. config.fOperateFaceSize = 4.2f;
  367. config.fCloseFaceSize = 6.6f;
  368. config.fFarFaceSize = 8.2f;
  369. config.fSearchFaceSize = 8.2f;
  370. config.fDetectFaceSize = 6.6f;
  371. config.nFaceSizeOffset = 18;
  372. config.nSleepLong = 800;
  373. config.nSleepMiddle = 600;
  374. config.nSleepShort = 500;
  375. config.nThresholdNum = 10;
  376. Error = Error_Succeed;
  377. return Error == Error_Succeed;
  378. }
  379. virtual void Debug(facecap_loglevel elevel, const char *fmt, ...)
  380. {
  381. va_list arg;
  382. va_start(arg, fmt);
  383. int n = vsnprintf(NULL, 0, fmt, arg);
  384. if (n >= MAX_LOG_LEN) {
  385. char* buf = (char*)malloc((size_t)(n + 1));
  386. vsnprintf(buf, n + 1, fmt, arg);
  387. DbgWithLink((LOG_LEVEL_E)elevel, LOG_TYPE_SYSTEM)("%s", buf);
  388. free(buf);
  389. }
  390. else{
  391. char strlog[MAX_LOG_LEN] = {0};
  392. vsnprintf(strlog, MAX_LOG_LEN, fmt, arg);
  393. DbgWithLink((LOG_LEVEL_E)elevel, LOG_TYPE_SYSTEM)("%s", strlog);
  394. }
  395. va_end(arg);
  396. }
  397. ////////////////////////////////////////////////////////////////////////////////////
  398. // CVideoMonitorEvent
  399. void GenerateMonitorEvent(video_monitor_event_type eType)
  400. {
  401. LogEvent(Severity_Middle, monitor_id_evtmsg[eType].evt_code, monitor_id_evtmsg[eType].evt_msg);
  402. }
  403. private:
  404. virtual void OnSysVarEvent(const char *pszKey, const char *pszValue,const char *pszOldValue,const char *pszEntityName)
  405. {
  406. if (_stricmp(pszKey,"SessionID") == 0)
  407. {
  408. GetFunction()->GetSysVar("SessionID",strSessionID);
  409. //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("sessionID change to %s",strSessionID);
  410. bIsSessionChange = true;
  411. }
  412. if (_stricmp(pszKey,"CustomerID") == 0)
  413. {
  414. GetFunction()->GetSysVar("CustomerID",strCustomerID);
  415. //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("customerID change to %s",strCustomerID);
  416. bIsCustomerChange = true;
  417. }
  418. if (_stricmp(pszKey, SYSVAR_CAMERASTATE) == 0)
  419. {
  420. CSimpleStringA str;
  421. GetFunction()->GetSysVar(SYSVAR_CAMERASTATE,str);
  422. //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("customerID change to %s",strCustomerID);
  423. if (str == 'N')
  424. {
  425. m_facecapture->SetCameraState(0);
  426. }
  427. else if (str == 'E')
  428. {
  429. m_facecapture->SetCameraState(1);
  430. }
  431. else if (str == 'O')
  432. {
  433. m_facecapture->SetCameraState(2);
  434. }
  435. else if (str == 'B')
  436. {
  437. m_facecapture->SetCameraState(3);
  438. //DbgWithLink(LOG_LEVEL_INFO, LOG_TYPE_SYSTEM)("set Camera State to 3");
  439. }
  440. }
  441. }
  442. private:
  443. CUUID m_UUid1,m_UUid2,m_UUid3,m_UUid4;
  444. bool bIsSessionChange;
  445. bool bIsCustomerChange;
  446. CSimpleStringA strCustomerID;
  447. CSimpleStringA strSessionID;
  448. CUUID m_lastUUID;
  449. ChannelClient *m_pChannelClient;
  450. Clibfacecapture *m_facecapture;
  451. bool m_bSingleCamera;
  452. };
  453. void ChannelClient::OnMessage( ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer<IReleasable> pData )
  454. {
  455. if (Error == Error_Succeed)
  456. {
  457. CFaceTrackingEntity *pEntity = static_cast<CFaceTrackingEntity*>(m_pEntityBase);
  458. int cat = ACM_PHT_CAT(Msg.sub_type);
  459. if (cat == ACM_PHT_REQ)
  460. {
  461. //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
  462. pEntity->Capture(Msg.id);
  463. //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  464. } else
  465. {
  466. _ASSERT(0);
  467. }
  468. }
  469. }
  470. ChannelClient::ChannelClient( CFaceTrackingEntity *pEntity ) : ChannelService_ClientBase(pEntity)
  471. {
  472. }
  473. SP_BEGIN_ENTITY_MAP()
  474. SP_ENTITY(CFaceTrackingEntity)
  475. SP_END_ENTITY_MAP()