mod_screenshot.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557
  1. #include "stdafx.h"
  2. #include "SpBase.h"
  3. #include "screencapture.h"
  4. #include <screencodec.h>
  5. #include "../..//Other/libvideoframework/videoutil.h"
  6. #include "../../Other/rvcmediacommon/rvc_media_common.h"
  7. #include "mod_assistantchannel/AssistantChannel_client_g.h"
  8. using namespace AssistantChannel;
  9. #include "mod_assistantchannel/chan_protocol.h"
  10. #include "mod_assistantchannel/VideoDesc.h"
  11. // add by ly 20150514
  12. #include "jpeg2k.h"
  13. #include "ScreenShot_server_g.h"
  14. #include "cv.h"
  15. #include "highgui.h"
  16. #include "cxcore.h"
  17. #include "CommEntityUtil.hpp"
  18. using namespace ScreenShot;
  19. #define LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE 0x50500001 //协助通道重启
  20. // step 1 screen capture
  21. // step 2 compress using libpng
  22. // step 3 split to 56k each chunk to send out
  23. // future improvement:
  24. // 1. adding 8bit depth color options
  25. // 2. adding business zone options
  26. class CScreenCaptureEntity;
  27. // add by ly 20150514
  28. class CScreenShotSession: public ScreenShotService_ServerSessionBase
  29. {
  30. public:
  31. CScreenShotSession(CScreenCaptureEntity* pEntity, int id) : m_id(id), m_pEntity(pEntity)
  32. {
  33. }
  34. virtual void Handle_StartScreenShot(SpReqAnsContext<ScreenShotService_StartScreenShot_Req, ScreenShotService_StartScreenShot_Ans>::Pointer ctx);
  35. virtual void OnClose( ErrorCodeEnum eErrorCode );
  36. private:
  37. int m_id;
  38. CScreenCaptureEntity* m_pEntity;
  39. };
  40. class ChannelClient : public ChannelService_ClientBase
  41. {
  42. public:
  43. ChannelClient(CScreenCaptureEntity *pEntity);
  44. virtual void OnMessage(ErrorCodeEnum Error, ChannelService_State_Info &Msg, CSmartPointer<IReleasable> pData);
  45. virtual void OnMessage(ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer<IReleasable> pData);
  46. };
  47. class CScreenCaptureEntity : public CEntityBase,public ILogListener
  48. {
  49. public:
  50. CScreenCaptureEntity() : m_enc_session(NULL), m_id_seq(0) {}
  51. virtual ~CScreenCaptureEntity() {}
  52. virtual const char *GetEntityName() const { return "ScreenShot"; }
  53. // add by ly 20150514
  54. virtual bool IsService() const { return true; }
  55. // add by ly 20150514
  56. virtual CServerSessionBase *OnNewSession(const char* pszRemoteEntityName, const char * pszClass)
  57. {
  58. LOG_FUNCTION();
  59. LOG_TRACE("%s connected class = %s!", pszRemoteEntityName, pszClass);
  60. return new CScreenShotSession(this, m_id_seq++);
  61. }
  62. virtual void OnPreStart(CAutoArray<CSimpleStringA> strArgs,CSmartPointer<ITransactionContext> pTransactionContext)
  63. {
  64. ErrorCodeEnum Error = __OnStart(Error_Succeed);
  65. pTransactionContext->SendAnswer(Error);
  66. }
  67. virtual void OnPreClose(EntityCloseCauseEnum eCloseCause,CSmartPointer<ITransactionContext> pTransactionContext)
  68. {
  69. ErrorCodeEnum Error = __OnClose(Error_Succeed);
  70. pTransactionContext->SendAnswer(Error);
  71. }
  72. virtual void OnLog(const CAutoArray<CUUID> &SubIDs, const CUUID nLogID,const LogTypeEnum eLogType, const SeverityLevelEnum eLevel,
  73. const DWORD dwSysError,const DWORD dwUserCode,const DWORD dwEntityInstanceID, const WORD wEntityDevelID,
  74. const CAutoArray<DWORD> &Param, const char *pszEntityName, const char *pszModuleName,const char *pszMessage)
  75. {
  76. if (dwUserCode == LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE)
  77. {
  78. Dbg("recv LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE");
  79. if (m_pChannelClient!=NULL)
  80. {
  81. m_pChannelClient->GetFunction()->CloseSession();
  82. m_pChannelClient->SafeDelete();
  83. m_pChannelClient = NULL;
  84. Dbg("Close AssistChannel Session ");
  85. }
  86. if (m_pChannelClient == NULL)
  87. {
  88. Dbg("ReConnection AssistChannel Session");
  89. m_pChannelClient = new ChannelClient(this);
  90. ErrorCodeEnum Error = m_pChannelClient->Connect();
  91. if (Error != Error_Succeed)
  92. {
  93. m_pChannelClient->SafeDelete();
  94. m_pChannelClient = NULL;
  95. Dbg("AssistChannelClient connect fail!");
  96. }
  97. if (Error == Error_Succeed)
  98. {
  99. ChannelService_BeginRecv_Sub Sub;
  100. Sub.type = ACM_TYPE_SRN;
  101. Error = m_pChannelClient->BeginRecv(Sub);
  102. if (Error != Error_Succeed)
  103. {
  104. m_pChannelClient->GetFunction()->CloseSession();
  105. m_pChannelClient->SafeDelete();
  106. m_pChannelClient = NULL;
  107. }
  108. }
  109. if (Error == Error_Succeed)
  110. {
  111. ChannelService_BeginState_Sub Sub;
  112. Error = m_pChannelClient->BeginState(Sub);
  113. if (Error != Error_Succeed)
  114. {
  115. LOG_TRACE("BeginState biz channel failed!");
  116. m_pChannelClient->GetFunction()->CloseSession();
  117. m_pChannelClient->SafeDelete();
  118. m_pChannelClient = NULL;
  119. }
  120. }
  121. }
  122. }
  123. }
  124. virtual void OnSelfTest(EntityTestEnum eTestType,CSmartPointer<ITransactionContext> pTransactionContext)
  125. {
  126. if (Test_ShakeHand == eTestType)
  127. {
  128. pTransactionContext->SendAnswer(Error_Succeed);
  129. }
  130. }
  131. ErrorCodeEnum __OnStart(ErrorCodeEnum preOperationError)
  132. {
  133. LOG_FUNCTION();
  134. CSmartPointer<IEntityFunction> pFunc = GetFunction();
  135. int i = 0;
  136. m_arrListener.Init(1);
  137. pFunc->SubscribeLog(m_arrListener[i++], this, Log_Event, Severity_None, Error_IgnoreAll, LOG_EVT_SELFCHECK_ASSISTANTCHANNEL_IDLE,NULL,false);
  138. if (preOperationError != Error_Succeed)
  139. return preOperationError;
  140. //is Pad Version
  141. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  142. CSystemStaticInfo stStaticinfo;
  143. spFunction->GetSystemStaticInfo(stStaticinfo);
  144. if (stricmp(stStaticinfo.strMachineType,"RVC.WALL")==0)
  145. {
  146. m_bIsWallMachine = TRUE;
  147. Dbg("the machine type is rvc.wall");
  148. }
  149. else
  150. {
  151. m_bIsWallMachine = FALSE;
  152. }
  153. ErrorCodeEnum Error;
  154. m_pChannelClient = new ChannelClient(this);
  155. Error = m_pChannelClient->Connect();
  156. if (Error != Error_Succeed) {
  157. m_pChannelClient->SafeDelete();
  158. return Error;
  159. }
  160. if (Error == Error_Succeed) {
  161. ChannelService_BeginRecv_Sub Sub;
  162. Sub.type = ACM_TYPE_SRN;
  163. Error = m_pChannelClient->BeginRecv(Sub);
  164. if (Error != Error_Succeed) {
  165. m_pChannelClient->GetFunction()->CloseSession();
  166. m_pChannelClient->SafeDelete();
  167. m_pChannelClient = NULL;
  168. return Error;
  169. }
  170. }
  171. if (Error == Error_Succeed) {
  172. ChannelService_BeginState_Sub Sub;
  173. Error = m_pChannelClient->BeginState(Sub);
  174. if (Error != Error_Succeed) {
  175. LOG_TRACE("BeginState biz channel failed!");
  176. m_pChannelClient->GetFunction()->CloseSession();
  177. m_pChannelClient->SafeDelete();
  178. m_pChannelClient = NULL;
  179. }
  180. }
  181. return Error;
  182. }
  183. ErrorCodeEnum __OnClose(ErrorCodeEnum preOperationError)
  184. {
  185. LOG_FUNCTION();
  186. CSmartPointer<IEntityFunction> spFunction = GetFunction();
  187. for (int i = 0; i < m_arrListener.GetCount(); ++i)
  188. {
  189. spFunction->UnsubscribeLog(m_arrListener[i]);
  190. }
  191. if (preOperationError != Error_Succeed)
  192. return preOperationError;
  193. m_pChannelClient->GetFunction()->CloseSession();
  194. m_pChannelClient->SafeDelete();
  195. m_pChannelClient = NULL;
  196. return Error_Succeed;
  197. }
  198. void DumpCaptureDat(const char *buf, int n)
  199. {
  200. char tmp[MAX_PATH];
  201. static int seq = 0;
  202. sprintf(tmp, ".%scapture_%08d.dat", SPLIT_SLASH_STR, seq++);
  203. FILE *fp = fopen(tmp, "wb");
  204. if (fp)
  205. {
  206. fwrite(buf,1,n, fp);
  207. fclose(fp);
  208. }
  209. }
  210. ErrorCodeEnum InitCapture()
  211. {
  212. if (m_enc_session) {
  213. screen_encoder_session_destroy(m_enc_session);
  214. m_enc_session = NULL;
  215. }
  216. #ifdef RVC_OS_WIN
  217. int cx = GetSystemMetrics(SM_CXSCREEN);
  218. int cy = GetSystemMetrics(SM_CYSCREEN);
  219. #else
  220. int cx, cy;
  221. getScreenSize(&cx, &cy);
  222. #endif
  223. if (m_bIsWallMachine)
  224. {
  225. cy = cy-640;
  226. }
  227. screen_encoder_session_create(cx, cy, &m_enc_session);
  228. return Error_Succeed;
  229. }
  230. void ExitCapture()
  231. {
  232. if (m_enc_session) {
  233. screen_encoder_session_destroy(m_enc_session);
  234. m_enc_session = NULL;
  235. }
  236. }
  237. void Capture(int id)
  238. {
  239. CSystemStaticInfo SysInfo;
  240. #ifdef RVC_OS_WIN
  241. int cx = GetSystemMetrics(SM_CXSCREEN);
  242. int cy = GetSystemMetrics(SM_CYSCREEN);
  243. #else
  244. int cx, cy;
  245. getScreenSize(&cx, &cy);
  246. #endif
  247. RECT rc = {0, 0, cx, cy};
  248. int size = 0;
  249. int err = screencapture_capture(&rc, NULL, &size);
  250. if (err != 0) {
  251. LOG_TRACE("capture screen failed! %d", err);
  252. return;
  253. }
  254. Dbg("capture screen, cx: %d, cy: %d, size: %d", cx, cy, size);
  255. void *buf = malloc(size);
  256. err = screencapture_capture(&rc, buf, &size);
  257. if (err != 0) {
  258. free(buf);
  259. LOG_TRACE("capture screen failed! %d", err);
  260. return;
  261. }
  262. if((SysInfo.eScreen == 1)&&!m_bIsWallMachine)
  263. {
  264. CSimpleStringA strValue;
  265. ErrorCodeEnum Error = GetFunction()->GetSysVar("VideoWindowInitializeParam", strValue);
  266. if (Error == Error_Succeed)
  267. {
  268. int local_view_x;
  269. int local_view_y;
  270. int local_view_cx;
  271. int local_view_cy;
  272. int remote_view_x;
  273. int remote_view_y;
  274. int remote_view_cx;
  275. int remote_view_cy;
  276. ParseVideoViewParam((LPCSTR)strValue, local_view_x, local_view_y, local_view_cx, local_view_cy,
  277. remote_view_x, remote_view_y, remote_view_cx, remote_view_cy);
  278. RECT rcs[] = {
  279. {local_view_x, cy - local_view_y - local_view_cy, local_view_x+local_view_cx, cy - local_view_y},
  280. {remote_view_x, cy - remote_view_y - remote_view_cy, remote_view_x+remote_view_cx, cy - remote_view_y},
  281. };
  282. screencapture_clipoff(cx, cy, buf, 2, rcs);
  283. }
  284. }
  285. ChannelService_Send_Info Info;
  286. Info.compress = false;
  287. Info.encrypt = false;
  288. Info.type = ACM_TYPE_SRN;
  289. Info.id = id;
  290. Info.sub_type = ACM_SRN_ANS | ACM_SRN_SNAPSHOT;
  291. if (m_bIsWallMachine)
  292. {
  293. int width = rc.right - rc.left;
  294. int height = rc.bottom - 640;
  295. int linesize = (width * 3 + 3) & 0xfffffffc;
  296. int newsize = linesize * height;
  297. Info.data.Alloc(newsize);
  298. Dbg("width = %d,height = %d,linesize = %d,newsize = %d",width,height,linesize,newsize);
  299. void *buftmp = malloc(newsize);
  300. memcpy(buftmp,buf,newsize);
  301. screen_encoder_session_encode(m_enc_session, buftmp, Info.data.m_pData, &Info.data.m_iLength);
  302. m_pChannelClient->Send(Info);
  303. free(buftmp);
  304. }
  305. else
  306. {
  307. Info.data.Alloc(size);
  308. screen_encoder_session_encode(m_enc_session, buf, Info.data.m_pData, &Info.data.m_iLength);
  309. m_pChannelClient->Send(Info);
  310. }
  311. #if 0
  312. int linesize = size / cy;
  313. video_frame tmp_frame;
  314. video_frame_alloc(linesize/3, cy, VIDEO_FORMAT_RGB24, &tmp_frame);
  315. video_frame_fill_black(&tmp_frame);
  316. memcpy(tmp_frame.data[0], buf, size);
  317. video_frame_save_bmpfile("screenshot_abc.bmp", &tmp_frame);
  318. video_frame_free(&tmp_frame);
  319. //video_frame_save_bmpfile("d:\\ab.bmp", &rtp_frame);
  320. Dbg("capture screen, linesize: %d.", linesize);
  321. #endif
  322. free(buf);
  323. LOG_TRACE("encode size = %d Bytes, time = %d", Info.data.m_iLength, SP::Module::Comm::RVCGetTickCount());
  324. }
  325. void Capture1(int id)
  326. {
  327. CSystemStaticInfo SysInfo;
  328. #ifdef RVC_OS_WIN
  329. int cx = GetSystemMetrics(SM_CXSCREEN);
  330. int cy = GetSystemMetrics(SM_CYSCREEN);
  331. #else
  332. int cx, cy;
  333. getScreenSize(&cx, &cy);
  334. #endif
  335. RECT rc = {0, 0, cx, cy};
  336. int size = 0;
  337. int err = screencapture_capture(&rc, NULL, &size);
  338. if (err != 0) {
  339. LOG_TRACE("capture screen failed! %d", err);
  340. return;
  341. }
  342. void *buf = malloc(size);
  343. err = screencapture_capture(&rc, buf, &size);
  344. if (err != 0) {
  345. free(buf);
  346. LOG_TRACE("capture screen failed! %d", err);
  347. return;
  348. }
  349. if (SysInfo.eScreen == 1) {
  350. CSimpleStringA strValue;
  351. ErrorCodeEnum Error = GetFunction()->GetSysVar("VideoWindowInitializeParam", strValue);
  352. if (Error == Error_Succeed) {
  353. int local_view_x;
  354. int local_view_y;
  355. int local_view_cx;
  356. int local_view_cy;
  357. int remote_view_x;
  358. int remote_view_y;
  359. int remote_view_cx;
  360. int remote_view_cy;
  361. ParseVideoViewParam((LPCSTR)strValue, local_view_x, local_view_y, local_view_cx, local_view_cy,
  362. remote_view_x, remote_view_y, remote_view_cx, remote_view_cy);
  363. RECT rcs[] = {
  364. {local_view_x, cy - local_view_y - local_view_cy, local_view_x+local_view_cx, cy - local_view_y},
  365. {remote_view_x, cy - remote_view_y - remote_view_cy, remote_view_x+remote_view_cx, cy - remote_view_y},
  366. };
  367. screencapture_clipoff(cx, cy, buf, 2, rcs);
  368. }
  369. }
  370. ChannelService_Send_Info Info;
  371. Info.compress = false;
  372. Info.encrypt = false;
  373. Info.type = ACM_TYPE_SRN;
  374. Info.id = id;
  375. Info.sub_type = ACM_SRN_ANS | ACM_SRN_SNAPSHOT;
  376. Info.data.Alloc(size);
  377. screencapture_encode(cx, cy, buf, Info.data.m_pData, &Info.data.m_iLength);
  378. //DumpCaptureDat((const char*)Info.data.m_pData, Info.data.m_iLength);
  379. m_pChannelClient->Send(Info);
  380. free(buf);
  381. LOG_TRACE("encode size = %d Bytes, time = %d", Info.data.m_iLength, SP::Module::Comm::RVCGetTickCount());
  382. }
  383. void Capture2(RECT *lprc, CBlob &image)
  384. {
  385. int width = lprc->right-lprc->left;
  386. int height = lprc->bottom-lprc->top;
  387. int size = 0;
  388. int err = screencapture_capture(lprc, NULL, &size);
  389. if (err != 0) {
  390. LOG_TRACE("capture screen failed! %d", err);
  391. return;
  392. }
  393. void *buf = malloc(size);
  394. err = screencapture_capture(lprc, buf, &size);
  395. if (err != 0) {
  396. free(buf);
  397. LOG_TRACE("capture screen failed! %d", err);
  398. return;
  399. }
  400. //Dbg("size = %d, 3*width*height= %d", size, 3*width*height);
  401. //IplImage *pImage = cvCreateImage(cvSize(width, height), IPL_DEPTH_8U, 3);
  402. //memcpy(pImage->imageData, buf, size);
  403. //cvFlip(pImage);
  404. //cvSaveImage(".\\jietu_opencv.jpg", pImage);
  405. //cvReleaseImage(&pImage);
  406. // encode with jpeg2k
  407. jpeg2k_coded_image codec_image = {0};
  408. jpeg2k_raw_image raw_image;
  409. raw_image.data = (BYTE*)buf;
  410. raw_image.width = width;
  411. raw_image.height = height;
  412. raw_image.len = raw_image.width * raw_image.height * 3;
  413. int nRet = jpeg2k_encode(&raw_image, &codec_image, 30); // ratio越小质量越好
  414. if (nRet == 0 || nRet == Error_TimeOut)
  415. {
  416. size = codec_image.len;
  417. image.Alloc(size);
  418. memmove(image.m_pData, codec_image.data, size);
  419. //char tmp[MAX_PATH];
  420. //static int seq = 0;
  421. //sprintf(tmp, ".\\jietu_%08d.jp2", seq++);
  422. //FILE *fp = fopen(tmp, "wb");
  423. //if (fp) {
  424. // fwrite(codec_image.data,1,size, fp);
  425. // fclose(fp);
  426. //}
  427. image.Resize(size);
  428. jpeg2k_encode_free(&codec_image);
  429. }
  430. free(buf);
  431. }
  432. private:
  433. screen_encoder_session_t *m_enc_session;
  434. ChannelClient *m_pChannelClient;
  435. CAutoArray<CUUID> m_arrListener;
  436. // add by ly 20150514
  437. int m_id_seq;
  438. BOOL m_bIsWallMachine;
  439. };
  440. // add by ly 20150514
  441. void CScreenShotSession::Handle_StartScreenShot(SpReqAnsContext<ScreenShotService_StartScreenShot_Req, ScreenShotService_StartScreenShot_Ans>::Pointer ctx)
  442. {
  443. Dbg("accepted params: %d, %d, %d, %d", ctx->Req.Left, ctx->Req.Top, ctx->Req.Width, ctx->Req.Height);
  444. #ifdef RVC_OS_WIN
  445. int cx = GetSystemMetrics(SM_CXSCREEN);
  446. int cy = GetSystemMetrics(SM_CYSCREEN);
  447. #else
  448. int cx, cy;
  449. getScreenSize(&cx, &cy);
  450. #endif
  451. if (ctx->Req.Left < 0 || ctx->Req.Left > cx || ctx->Req.Width <= 0 || ctx->Req.Width > cx ||
  452. ctx->Req.Top < 0 || ctx->Req.Top > cy || ctx->Req.Height <= 0 || ctx->Req.Height > cy)
  453. {
  454. ctx->Answer(Error_Unexpect);
  455. }
  456. RECT rc = {ctx->Req.Left, ctx->Req.Top, ctx->Req.Left + ctx->Req.Width, ctx->Req.Top + ctx->Req.Height};
  457. m_pEntity->Capture2(&rc, ctx->Ans.Image);
  458. if (ctx->Ans.Image.m_iLength == 0)
  459. {
  460. ctx->Answer(Error_Unexpect);
  461. }
  462. else
  463. {
  464. ctx->Answer(Error_Succeed);
  465. }
  466. }
  467. // add by ly 20150514
  468. void CScreenShotSession::OnClose( ErrorCodeEnum eErrorCode )
  469. {
  470. LOG_FUNCTION();
  471. }
  472. void ChannelClient::OnMessage(ErrorCodeEnum Error, ChannelService_State_Info &Msg, CSmartPointer<IReleasable> pData)
  473. {
  474. if (Error == Error_Succeed) {
  475. CScreenCaptureEntity *pEntity = static_cast<CScreenCaptureEntity*>(m_pEntityBase);
  476. if (Msg.state == eChannelState_Idle) {
  477. pEntity->ExitCapture();
  478. } else if (Msg.state == eChannelState_Connected) {
  479. pEntity->InitCapture();
  480. }
  481. }
  482. }
  483. void ChannelClient::OnMessage( ErrorCodeEnum Error, ChannelService_Packet_Info &Msg, CSmartPointer<IReleasable> pData )
  484. {
  485. LOG_FUNCTION();
  486. if (Error == Error_Succeed) {
  487. CScreenCaptureEntity *pEntity = static_cast<CScreenCaptureEntity*>(m_pEntityBase);
  488. int cat = ACM_SRN_CAT(Msg.sub_type);
  489. if (cat == ACM_SRN_REQ) {
  490. //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_BELOW_NORMAL);
  491. pEntity->Capture(Msg.id);
  492. //SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_NORMAL);
  493. } else {
  494. _ASSERT(0);
  495. }
  496. }
  497. }
  498. ChannelClient::ChannelClient( CScreenCaptureEntity *pEntity ) : ChannelService_ClientBase(pEntity)
  499. {
  500. }
  501. SP_BEGIN_ENTITY_MAP()
  502. SP_ENTITY(CScreenCaptureEntity)
  503. SP_END_ENTITY_MAP()