UB530View.cpp 35 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222122312241225122612271228122912301231123212331234123512361237123812391240124112421243124412451246124712481249125012511252125312541255125612571258125912601261126212631264126512661267126812691270127112721273127412751276127712781279
  1. // UB530View.cpp: 实现文件
  2. //
  3. #include "stdafx.h"
  4. #include "SATHelper.h"
  5. #include "UB530View.h"
  6. #include "MainFrm.h"
  7. extern CMemoryClient g_ub530;
  8. extern CMainFrame* g_pMainFrame;
  9. VOID Dbg2(CHAR* pszStr, ...)
  10. {
  11. char szData[MAX_PATH] = "[SC] ";
  12. va_list args;
  13. va_start(args, pszStr);
  14. _vsnprintf_s(szData + 5, MAX_PATH - 5, MAX_PATH - 6, pszStr, args);
  15. va_end(args);
  16. strcat_s(szData, "\n");
  17. OutputDebugStringA(szData);
  18. }
  19. // FORMAT CHANGED CALLBACK FUNCTION
  20. //
  21. QRETURN on_process_format_changed2(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, ULONG nVideoWidth, ULONG nVideoHeight, BOOL bVideoIsInterleaved, double dVideoFrameRate, ULONG nAudioChannels, ULONG nAudioBitsPerSample, ULONG nAudioSampleFrequency, PVOID pUserData)
  22. {
  23. //Dbg("format changed Detected \n");
  24. CUB530View* pView = (CUB530View*)pUserData;
  25. if (pView == NULL) { return QCAP_RT_OK; }
  26. if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
  27. pView->m_nVideoWidth = nVideoWidth;
  28. pView->m_nVideoHeight = nVideoHeight;
  29. pView->m_bVideoIsInterleaved = bVideoIsInterleaved;
  30. pView->m_dVideoFrameRate = dVideoFrameRate;
  31. pView->m_nAudioChannels = nAudioChannels;
  32. pView->m_nAudioBitsPerSample = nAudioBitsPerSample;
  33. pView->m_nAudioSampleFrequency = nAudioSampleFrequency;
  34. // OUTPUT FORMAT CHANGED MESSAGE
  35. //
  36. CHAR strVideoInput[MAX_PATH] = { 0 };
  37. CHAR strAudioInput[MAX_PATH] = { 0 };
  38. CHAR strFrameType[MAX_PATH] = { 0 };
  39. UINT nVH = 0;
  40. if (nVideoInput == 0) { sprintf_s(strVideoInput, "COMPOSITE"); }
  41. if (nVideoInput == 1) { sprintf_s(strVideoInput, "SVIDEO"); }
  42. if (nVideoInput == 2) { sprintf_s(strVideoInput, "HDMI"); }
  43. if (nVideoInput == 3) { sprintf_s(strVideoInput, "DVI_D"); }
  44. if (nVideoInput == 4) { sprintf_s(strVideoInput, "COMPONENTS (YCBCR)"); }
  45. if (nVideoInput == 5) { sprintf_s(strVideoInput, "DVI_A (RGB / VGA)"); }
  46. if (nVideoInput == 6) { sprintf_s(strVideoInput, "SDI"); }
  47. if (nVideoInput == 7) { sprintf_s(strVideoInput, "AUTO"); }
  48. if (nAudioInput == 0) { sprintf_s(strAudioInput, "EMBEDDED_AUDIO"); }
  49. if (nAudioInput == 1) { sprintf_s(strAudioInput, "LINE_IN"); }
  50. if (bVideoIsInterleaved == TRUE) { nVH = nVideoHeight / 2; }
  51. else { nVH = nVideoHeight; }
  52. if (bVideoIsInterleaved == TRUE) { sprintf_s(strFrameType, " I "); }
  53. else { sprintf_s(strFrameType, " P "); }
  54. pView->m_strFormatChangedOutput.Format(
  55. _T("INFO : %d x %d%s @%2.3f FPS , %d CH x %d BITS x %d HZ , VIDEO INPUT : %s , AUDIO INPUT : %s"),
  56. nVideoWidth,
  57. nVH,
  58. strFrameType,
  59. dVideoFrameRate,
  60. nAudioChannels,
  61. nAudioBitsPerSample,
  62. nAudioSampleFrequency,
  63. strVideoInput,
  64. strAudioInput
  65. );
  66. ::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)&pView->m_strFormatChangedOutput, ID_STATUSBAR_PANE1);
  67. // NO SOURCE
  68. //
  69. if (nVideoWidth == 0 &&
  70. nVideoHeight == 0 &&
  71. dVideoFrameRate == 0.0 &&
  72. nAudioChannels == 0 &&
  73. nAudioBitsPerSample == 0 &&
  74. nAudioSampleFrequency == 0)
  75. {
  76. pView->m_bNoSignal = TRUE;
  77. }
  78. else
  79. {
  80. pView->m_bNoSignal = FALSE;
  81. }
  82. pView->SetTimer(0x00000000, 1, NULL);
  83. return QCAP_RT_OK;
  84. }
  85. // NO SIGNAL DETEACTED CALLBACK FUNCTION
  86. //
  87. QRETURN on_process_no_signal_detected2(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, PVOID pUserData)
  88. {
  89. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  90. CUB530View* pView = (CUB530View*)pUserData;
  91. //Dbg("No Signal Detected \n");
  92. if (pView == NULL) { return QCAP_RT_OK; }
  93. if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
  94. //pView->SetRibbonStatusBarText("当前采集卡无信号。", ID_STATUSBAR_PANE1);
  95. ::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)&CString("当前采集卡无信号"), ID_STATUSBAR_PANE1);
  96. pView->m_bNoSignal = TRUE;
  97. pView->SetTimer(0x00000000, 1, NULL);
  98. return QCAP_RT_OK;
  99. }
  100. // SIGNAL REMOVED CALLBACK FUNCTION
  101. //
  102. QRETURN on_process_signal_removed2(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, PVOID pUserData)
  103. {
  104. AFX_MANAGE_STATE(AfxGetStaticModuleState());
  105. CUB530View* pView = (CUB530View*)pUserData;
  106. if (pView == NULL) { return QCAP_RT_OK; }
  107. if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
  108. //pView->SetRibbonStatusBarText("当前采集卡信号被移除。", ID_STATUSBAR_PANE1);
  109. ::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)&CString("当前采集卡信号被移除"), ID_STATUSBAR_PANE1);
  110. pView->m_bNoSignal = TRUE;
  111. pView->SetTimer(0x00000000, 1, NULL);
  112. return QCAP_RT_OK;
  113. }
  114. // PREVIEW VIDEO CALLBACK FUNCTION
  115. //
  116. QRETURN on_process_preview_video_buffer2(PVOID pDevice, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, PVOID pUserData)
  117. {
  118. CUB530View* pView = (CUB530View*)pUserData;
  119. if (pView) {
  120. // 尝试加锁;
  121. if (!pView->m_mut_cpature.try_lock()) {
  122. return QCAP_RT_OK;
  123. }
  124. // 是否触发截图;
  125. if (pView->m_bCaptureImage) {
  126. // 加锁;
  127. std::lock_guard<std::mutex> lk(pView->m_mut_thread);
  128. // 复制数据;
  129. pView->m_dwBufferLen = nFrameBufferLen;
  130. pView->m_pBuffer = new BYTE[nFrameBufferLen];
  131. memcpy(pView->m_pBuffer, pFrameBuffer, nFrameBufferLen);
  132. // 唤醒线程(通知线程保存图片);
  133. pView->m_thread_cond.notify_one();
  134. // 恢复截图标记,防止重复截图;
  135. pView->m_bCaptureImage = FALSE;
  136. }
  137. // 解锁;
  138. pView->m_mut_cpature.unlock();
  139. }
  140. return QCAP_RT_OK;
  141. }
  142. // PREVIEW AUDIO CALLBACK FUNCTION
  143. //
  144. QRETURN on_process_preview_audio_buffer2(PVOID pDevice, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, PVOID pUserData)
  145. {
  146. return QCAP_RT_OK;
  147. }
  148. // VIDEO HARDARE ENCODER CALLBACK FUNCTION
  149. //
  150. QRETURN on_process_hardware_encoder_video_buffer2(PVOID pDevice, UINT iRecNum, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, BOOL bIsKeyFrame, PVOID pUserData)
  151. {
  152. return QCAP_RT_OK;
  153. }
  154. QRETURN on_process_snapshot_done2(PVOID pDevice, CHAR* pszFilePathName, PVOID pUserData)
  155. {
  156. return QCAP_RT_OK;
  157. }
  158. QRETURN on_process_snapshot_stream2(PVOID pDevice, CHAR* pszFilePathName, BYTE* pStreamBuffer, ULONG nStreamBufferLen, PVOID pUserData)
  159. {
  160. // 注意:在调用本回调函数前,已经保存了图片!
  161. CUB530View* pView = (CUB530View*)pUserData;
  162. if (pView->m_bHoriontal || pView->m_bVertically)
  163. Global::SaveImgByRotate(pszFilePathName, pStreamBuffer, nStreamBufferLen, pView->m_bHoriontal, pView->m_bVertically);
  164. return QCAP_RT_OK;
  165. }
  166. // CUB530View
  167. IMPLEMENT_DYNCREATE(CUB530View, CFormView)
  168. CUB530View::CUB530View(): CFormView(DLG_UB530VIEW)
  169. {
  170. m_hVideoDevice = NULL;
  171. m_bIsRecord = FALSE;
  172. m_bNoSignal = FALSE;
  173. m_bVertically = FALSE;
  174. m_bHoriontal = FALSE;
  175. m_bAppQuit = FALSE;
  176. m_pBuffer = NULL;
  177. m_bCaptureImage = FALSE;
  178. m_dwBufferLen = 0;
  179. m_bIsMp4 = TRUE;
  180. m_bSupportGPU = FALSE;
  181. m_shotDir = ShotLocal;
  182. }
  183. CUB530View::~CUB530View()
  184. {
  185. g_ub530.EndOfThread();
  186. m_bAppQuit = TRUE;
  187. HwUninitialize();
  188. }
  189. void CUB530View::DoDataExchange(CDataExchange* pDX)
  190. {
  191. CFormView::DoDataExchange(pDX);
  192. }
  193. BEGIN_MESSAGE_MAP(CUB530View, CFormView)
  194. ///////////////////////////////////
  195. ON_WM_TIMER()
  196. ON_COMMAND(ID_CUT_BMP, &CUB530View::OnCutBmp)
  197. ON_COMMAND(ID_CUT_JPG, &CUB530View::OnCutJpg)
  198. ON_COMMAND(ID_START_RECORD, &CUB530View::OnStartRecord)
  199. ON_COMMAND(ID_STOP_RECORD, &CUB530View::OnStopRecord)
  200. ON_COMMAND(ID_CHECK_VERTICALLY, &CUB530View::OnCheckVertically)
  201. ON_COMMAND(ID_CHECK_HORIONTAL, &CUB530View::OnCheckHoriontal)
  202. ON_UPDATE_COMMAND_UI(ID_CHECK_VERTICALLY, &CUB530View::OnUpdateCheckVertically)
  203. ON_UPDATE_COMMAND_UI(ID_CHECK_HORIONTAL, &CUB530View::OnUpdateCheckHoriontal)
  204. ON_COMMAND(ID_TRAYMENU_RECONNECT, &CUB530View::OnTraymenuReconnect)
  205. ON_COMMAND(ID_CHECK_SUPORT_GPU, &CUB530View::OnCheckSuportGpu)
  206. ON_COMMAND(ID_CHECK_FORMAT_MP4, &CUB530View::OnCheckFormatMp4)
  207. ON_COMMAND(ID_CHECK_FORMAT_AVI, &CUB530View::OnCheckFormatAvi)
  208. ON_UPDATE_COMMAND_UI(ID_CHECK_SUPORT_GPU, &CUB530View::OnUpdateCheckSuportGpu)
  209. ON_UPDATE_COMMAND_UI(ID_CHECK_FORMAT_MP4, &CUB530View::OnUpdateCheckFormatMp4)
  210. ON_UPDATE_COMMAND_UI(ID_CHECK_FORMAT_AVI, &CUB530View::OnUpdateCheckFormatAvi)
  211. ON_UPDATE_COMMAND_UI(ID_START_RECORD, &CUB530View::OnUpdateStartRecord)
  212. ON_UPDATE_COMMAND_UI(ID_STOP_RECORD, &CUB530View::OnUpdateStopRecord)
  213. ON_COMMAND(ID_CHECK_SHOT_LOCAL, &CUB530View::OnCheckShotLocal)
  214. ON_UPDATE_COMMAND_UI(ID_CHECK_SHOT_LOCAL, &CUB530View::OnUpdateCheckShotLocal)
  215. ON_COMMAND(ID_CHECK_SHOT_SYSTEM, &CUB530View::OnCheckShotSystem)
  216. ON_UPDATE_COMMAND_UI(ID_CHECK_SHOT_SYSTEM, &CUB530View::OnUpdateCheckShotSystem)
  217. ON_COMMAND(ID_CHECK_SHOT_SPEC, &CUB530View::OnCheckShotSpec)
  218. ON_UPDATE_COMMAND_UI(ID_CHECK_SHOT_SPEC, &CUB530View::OnUpdateCheckShotSpec)
  219. ON_WM_CREATE()
  220. ON_COMMAND(ID_CHECK_IR_SHOT, &CUB530View::OnCheckIrShot)
  221. ON_UPDATE_COMMAND_UI(ID_CHECK_IR_SHOT, &CUB530View::OnUpdateCheckIrShot)
  222. END_MESSAGE_MAP()
  223. // CUB530View 诊断
  224. #ifdef _DEBUG
  225. void CUB530View::AssertValid() const
  226. {
  227. CFormView::AssertValid();
  228. }
  229. #ifndef _WIN32_WCE
  230. void CUB530View::Dump(CDumpContext& dc) const
  231. {
  232. CFormView::Dump(dc);
  233. }
  234. #endif
  235. #endif //_DEBUG
  236. // CUB530View 消息处理程序
  237. void CUB530View::OnInitialUpdate()
  238. {
  239. CFormView::OnInitialUpdate();
  240. // TODO: 在此添加专用代码和/或调用基类
  241. // CMemoryClient::m_pView2 = this;
  242. // g_ub530.InitMemery();
  243. // g_ub530.StartThread();
  244. //
  245. // // TODO: 在此添加您专用的创建代码
  246. // // 创建视频流,并关联指定显示窗口;
  247. // HwInitialize();
  248. //
  249. // // 创建截图线程;
  250. // std::thread t(CaptureImageThread, this);
  251. // t.detach();
  252. }
  253. void CUB530View::OnDraw(CDC* pDC)
  254. {
  255. // TODO: 在此添加专用代码和/或调用基类
  256. // TO FILL IN THE TEXT
  257. //
  258. if (m_hVideoDevice == 0 || m_bNoSignal) {
  259. CFont font;
  260. ULONG nFontSize = 300;
  261. font.CreatePointFont(nFontSize, TEXT("Arial"), NULL);
  262. HFONT hOldFont = (HFONT)pDC->SelectObject(&font);
  263. pDC->SetBkMode(TRANSPARENT);
  264. pDC->SetTextColor(RGB(255, 255, 255));
  265. CRect rect_client;
  266. GetClientRect(&rect_client);
  267. CString string = _T("");
  268. if (m_hVideoDevice == 0)
  269. {
  270. CBrush brush_fill_rect(RGB(0, 0, 0));
  271. pDC->FillRect(&rect_client, &brush_fill_rect);
  272. string = TEXT("No Device");
  273. //g_pMainFrame->SetRibbonStatusBarText("当前采集卡设备被移除。", ID_STATUSBAR_PANE1);
  274. }
  275. else if (m_bNoSignal)
  276. {
  277. CBrush brush_fill_rect(RGB(0, 0, 255));
  278. pDC->FillRect(&rect_client, &brush_fill_rect);
  279. string = TEXT("No Source");
  280. //g_pMainFrame->SetRibbonStatusBarText("当前采集卡信号被移除。", ID_STATUSBAR_PANE1);
  281. }
  282. pDC->DrawText(string, &rect_client, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
  283. pDC->SelectObject(&hOldFont);
  284. font.DeleteObject();
  285. }
  286. }
  287. BOOL CUB530View::HwInitialize()
  288. {
  289. if (m_hVideoDevice != NULL)
  290. return TRUE;
  291. // CALLBACK FUNCTION
  292. PF_FORMAT_CHANGED_CALLBACK pFormatChangedCB = { 0 };
  293. PF_VIDEO_PREVIEW_CALLBACK pPreviewVideoCB = { 0 };
  294. PF_AUDIO_PREVIEW_CALLBACK pPreviewAudioCB = { 0 };
  295. PF_VIDEO_HARDWARE_ENCODER_CALLBACK pHardwareEncoderVideoCB = { 0 };
  296. PF_NO_SIGNAL_DETECTED_CALLBACK pNoSignalDetectedCB = { 0 };
  297. PF_SIGNAL_REMOVED_CALLBACK pSignalRemovedCB = { 0 };
  298. PF_SNAPSHOT_DONE_CALLBACK pSnapShotDoneCB = { 0 };
  299. PF_SNAPSHOT_STREAM_CALLBACK pSnapShotStreamCB = { 0 };
  300. // CREATE CAPTURE DEVICE
  301. //
  302. if (m_hVideoDevice == NULL)
  303. {
  304. QRESULT qr = QCAP_CREATE("CY3014 USB", 0, m_hWnd, &m_hVideoDevice, 1);
  305. if ( qr != QCAP_RS_SUCCESSFUL )
  306. {
  307. OutputDebugString("初始化UB530失败\n");
  308. }
  309. }
  310. if (m_hVideoDevice == NULL) {
  311. return FALSE;
  312. }
  313. // REGISTER FORMAT CHANGED CALLBACK FUNCTION
  314. pFormatChangedCB = on_process_format_changed2;
  315. QCAP_REGISTER_FORMAT_CHANGED_CALLBACK(m_hVideoDevice, pFormatChangedCB, this);
  316. // REGISTER PREVIEW VIDEO CALLBACK FUNCTION
  317. pPreviewVideoCB = on_process_preview_video_buffer2;
  318. QCAP_REGISTER_VIDEO_PREVIEW_CALLBACK(m_hVideoDevice, pPreviewVideoCB, this);
  319. // REGISTER PREVIEW AUDIO CALLBACK FUNCTION
  320. //pPreviewAudioCB = on_process_preview_audio_buffer;
  321. //QCAP_REGISTER_AUDIO_PREVIEW_CALLBACK(m_hVideoDevice, pPreviewAudioCB, this);
  322. // REGISTER HARDWARE ENCODER VIDEO CALLBACK FUNCTION
  323. //pHardwareEncoderVideoCB = on_process_hardware_encoder_video_buffer;
  324. //QCAP_REGISTER_VIDEO_HARDWARE_ENCODER_CALLBACK(m_hVideoDevice, 0, pHardwareEncoderVideoCB, this);
  325. // REGISTER NO SIGNAL DETECTED CALLBACK FUNCTION
  326. pNoSignalDetectedCB = on_process_no_signal_detected2;
  327. QCAP_REGISTER_NO_SIGNAL_DETECTED_CALLBACK(m_hVideoDevice, pNoSignalDetectedCB, this);
  328. // REGISTER SIGNAL REMOVED CALLBACK FUNCTION
  329. pSignalRemovedCB = on_process_signal_removed2;
  330. QCAP_REGISTER_SIGNAL_REMOVED_CALLBACK(m_hVideoDevice, pSignalRemovedCB, this);
  331. #if 1
  332. //
  333. pSnapShotDoneCB = on_process_snapshot_done2;
  334. QCAP_REGISTER_SNAPSHOT_DONE_CALLBACK(m_hVideoDevice, pSnapShotDoneCB, this);
  335. //
  336. pSnapShotStreamCB = on_process_snapshot_stream2;
  337. QCAP_REGISTER_SNAPSHOT_STREAM_CALLBACK(m_hVideoDevice, pSnapShotStreamCB, this);
  338. #endif
  339. QCAP_SET_VIDEO_DEINTERLACE_TYPE(m_hVideoDevice, QCAP_SOFTWARE_DEINTERLACE_TYPE_BLENDING);
  340. QCAP_SET_VIDEO_DEINTERLACE(m_hVideoDevice, 0);
  341. QCAP_SET_AUDIO_VOLUME(m_hVideoDevice, 100);
  342. QCAP_SET_VIDEO_HARDWARE_ENCODER_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_FORMAT_H264, QCAP_RECORD_MODE_CBR, 8000, 12 * 1024 * 1024, 30, 0, 0, QCAP_DOWNSCALE_MODE_OFF, 0, 0);
  343. QCAP_SET_VIDEO_INPUT(m_hVideoDevice, QCAP_INPUT_TYPE_AUTO);
  344. QCAP_RUN(m_hVideoDevice);
  345. // 刷新区域;
  346. Invalidate();
  347. // UPDATE USER INTERFACE RESOURCE
  348. if (m_hVideoDevice == 0) {
  349. /*m_oSetupDialog.m_btnVideoInput.EnableWindow(FALSE);
  350. m_oSetupDialog.m_btnVideoQuality.EnableWindow(FALSE);
  351. m_oSetupDialog.m_btnAudioInput.EnableWindow(FALSE);
  352. m_oSetupDialog.m_btnSnapshot_bmp.EnableWindow(FALSE);
  353. m_oSetupDialog.m_btnSnapshot_jpg.EnableWindow(FALSE);
  354. m_oSetupDialog.m_btnRecordStart_1_1.EnableWindow(FALSE);
  355. m_oSetupDialog.m_btnRecordStop_1_1.EnableWindow(FALSE);
  356. m_oSetupDialog.m_btnRecordStart_1_2.EnableWindow(FALSE);
  357. m_oSetupDialog.m_btnRecordStop_1_2.EnableWindow(FALSE);
  358. m_oSetupDialog.m_btnRecordStart_1_3.EnableWindow(FALSE);
  359. m_oSetupDialog.m_btnRecordStop_1_3.EnableWindow(FALSE);
  360. m_oSetupDialog.m_checkGPU_1_1.EnableWindow(FALSE);
  361. m_oSetupDialog.m_checkGPU_1_1.SetCheck(0);
  362. m_oSetupDialog.m_checkGPU_1_2.EnableWindow(FALSE);
  363. m_oSetupDialog.m_checkGPU_1_2.SetCheck(0);
  364. m_oSetupDialog.m_checkGPU_1_3.EnableWindow(FALSE);
  365. m_oSetupDialog.m_checkGPU_1_3.SetCheck(0);
  366. m_oSetupDialog.m_checkAutoDeinterlace.EnableWindow(FALSE);
  367. m_oSetupDialog.m_checkAutoDeinterlace.SetCheck(0);*/
  368. }
  369. else {
  370. /*m_oSetupDialog.m_btnSnapshot_bmp.EnableWindow(TRUE);
  371. m_oSetupDialog.m_btnSnapshot_jpg.EnableWindow(TRUE);
  372. m_oSetupDialog.m_btnRecordStart_1_1.EnableWindow(TRUE);
  373. m_oSetupDialog.m_btnRecordStop_1_1.EnableWindow(FALSE);
  374. m_oSetupDialog.m_btnRecordStart_1_2.EnableWindow(TRUE);
  375. m_oSetupDialog.m_btnRecordStop_1_2.EnableWindow(FALSE);
  376. m_oSetupDialog.m_btnRecordStart_1_3.EnableWindow(TRUE);
  377. m_oSetupDialog.m_btnRecordStop_1_3.EnableWindow(FALSE);
  378. m_oSetupDialog.m_checkGPU_1_1.EnableWindow(FALSE);
  379. m_oSetupDialog.m_checkGPU_1_1.SetCheck(0);
  380. m_oSetupDialog.m_checkGPU_1_2.EnableWindow(TRUE);
  381. m_oSetupDialog.m_checkGPU_1_2.SetCheck(0);
  382. m_oSetupDialog.m_checkGPU_1_3.EnableWindow(TRUE);
  383. m_oSetupDialog.m_checkGPU_1_3.SetCheck(0);
  384. m_oSetupDialog.m_checkAutoDeinterlace.EnableWindow(TRUE);
  385. m_oSetupDialog.m_checkAutoDeinterlace.SetCheck(0);*/
  386. }
  387. return TRUE;
  388. }
  389. BOOL CUB530View::HwUninitialize()
  390. {
  391. if (m_hVideoDevice != 0) {
  392. QCAP_STOP(m_hVideoDevice);
  393. QCAP_DESTROY(m_hVideoDevice);
  394. m_hVideoDevice = NULL;
  395. }
  396. return TRUE;
  397. }
  398. void CUB530View::CaptureSingleImage(LPTSTR lpszFileName, BOOL bIsJPG)
  399. {
  400. if (m_hVideoDevice != NULL)
  401. {
  402. if (bIsJPG)
  403. {
  404. QCAP_SNAPSHOT_JPG(m_hVideoDevice, lpszFileName, 100, FALSE, 5000); //参数4:是否异步;
  405. }
  406. else
  407. {
  408. QCAP_SNAPSHOT_BMP(m_hVideoDevice, lpszFileName, FALSE, 5000);
  409. }
  410. //Global::WriteTextLog("完成:CaptureSingleImage=%s", lpszFileName);
  411. }
  412. }
  413. std::string CUB530View::CaptureSingleImageAutoName(LPCTSTR lpszDir, BOOL bIsJPG)
  414. {
  415. if (m_hVideoDevice != NULL)
  416. {
  417. TCHAR szPath[MAX_PATH] = { 0 };
  418. // 毫秒级;
  419. time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
  420. auto tt = std::chrono::system_clock::to_time_t(tp);
  421. std::tm now = { 0 };
  422. localtime_s(&now, &tt); // 时间戳转成本地时间;
  423. int msc = tp.time_since_epoch().count() % 1000;
  424. if (bIsJPG)
  425. {
  426. _stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d.jpg"),
  427. lpszDir ? lpszDir : Global::g_szCurModuleDir,
  428. now.tm_year + 1990,
  429. now.tm_mon + 1,
  430. now.tm_mday,
  431. now.tm_hour,
  432. now.tm_min,
  433. now.tm_sec,
  434. msc);
  435. QCAP_SNAPSHOT_JPG(m_hVideoDevice, szPath, 100, FALSE, 5000);
  436. }
  437. else
  438. {
  439. _stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d.bmp"),
  440. lpszDir ? lpszDir : Global::g_szCurModuleDir,
  441. now.tm_year + 1990,
  442. now.tm_mon + 1,
  443. now.tm_mday,
  444. now.tm_hour,
  445. now.tm_min,
  446. now.tm_sec,
  447. msc);
  448. QCAP_SNAPSHOT_BMP(m_hVideoDevice, szPath, FALSE, 5000);
  449. }
  450. //Global::WriteTextLog("完成:CaptureSingleImageAutoName=%s", szPath);
  451. return std::string(szPath);
  452. }
  453. return std::string();
  454. }
  455. void CUB530View::CaptureMultiImage(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime)
  456. {
  457. std::thread t([&](CUB530View* p, LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime) {
  458. // 连续截图;
  459. TCHAR szDir[MAX_PATH] = { 0 };
  460. TCHAR szPath[MAX_PATH] = { 0 };
  461. _stprintf_s(szDir, lpszPrefix ? _T("%s%s-") : _T("%s%s"),
  462. lpszDir ? lpszDir : Global::g_szCurModuleDir,
  463. lpszPrefix ? lpszPrefix : _T(""));
  464. auto start = system_clock::now();
  465. while (true)
  466. {
  467. // C++11获取当前时间;
  468. time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
  469. if (bIsJPG)
  470. {
  471. _stprintf_s(szPath, _T("%s%lld.jpg"), szDir, tp.time_since_epoch().count());
  472. QCAP_SNAPSHOT_JPG(m_hVideoDevice, szPath, 100, TRUE);
  473. // 等待磁盘完成写入;
  474. //Sleep(20);
  475. }
  476. else
  477. {
  478. _stprintf_s(szPath, _T("%s%lld.bmp"), szDir, tp.time_since_epoch().count());
  479. QCAP_SNAPSHOT_BMP(m_hVideoDevice, szPath, TRUE);
  480. // 等待磁盘完成写入;
  481. //Sleep(530);
  482. }
  483. auto duration = duration_cast<milliseconds>(system_clock::now() - start);
  484. if (duration.count() >= nDurationTime)
  485. break;
  486. }
  487. }, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
  488. t.detach();
  489. }
  490. void CUB530View::CaptureSingleImageEx(LPTSTR lpszFileName, BOOL bIsJPG)
  491. {
  492. // 等待截图完成;
  493. std::unique_lock<std::mutex> lk(m_mut_saveImg);
  494. {
  495. // 加锁;
  496. std::lock_guard<std::mutex> lk(m_mut_cpature);
  497. // 标记截图;
  498. m_bCaptureImage = TRUE;
  499. // 初始化数据;
  500. ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
  501. m_CaptureInfo.bIsJPG = bIsJPG;
  502. m_CaptureInfo.bSingle = TRUE;
  503. m_CaptureInfo.IsAutoName = FALSE;
  504. m_CaptureInfo.nCaputerCount = 0;
  505. m_CaptureInfo.nKeepTime = 0;
  506. memset(m_CaptureInfo.szPrefix, 0, 64);
  507. _stprintf_s(m_CaptureInfo.szSaveDir, _T("%s"), lpszFileName);
  508. m_bSaveImage = FALSE;
  509. }
  510. // 保存完成;
  511. m_saveImg_cond.wait(lk, [&]() {return m_bSaveImage; });
  512. // 解锁;
  513. lk.unlock();
  514. }
  515. std::string CUB530View::CaptureSingleImageAutoNameEx(LPCTSTR lpszDir, BOOL bIsJPG)
  516. {
  517. // 等待截图完成;
  518. std::unique_lock<std::mutex> lk(m_mut_saveImg);
  519. {
  520. // 加锁;
  521. std::lock_guard<std::mutex> lk(m_mut_cpature);
  522. // 标记截图;
  523. m_bCaptureImage = TRUE;
  524. // 初始化数据;
  525. ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
  526. m_CaptureInfo.bIsJPG = bIsJPG;
  527. m_CaptureInfo.bSingle = TRUE;
  528. m_CaptureInfo.IsAutoName = FALSE;
  529. m_CaptureInfo.nCaputerCount = 0;
  530. m_CaptureInfo.nKeepTime = 0;
  531. memset(m_CaptureInfo.szPrefix, 0, 64);
  532. memset(m_CaptureInfo.szSaveDir, 0, MAX_PATH);
  533. // 毫秒级;
  534. time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
  535. auto tt = std::chrono::system_clock::to_time_t(tp);
  536. std::tm now = { 0 };
  537. localtime_s(&now, &tt); // 时间戳转成本地时间;
  538. int msc = tp.time_since_epoch().count() % 1000;
  539. if (bIsJPG)
  540. {
  541. _stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%04d%02d%02d%02d%02d%02d%03d.jpg"),
  542. lpszDir ? lpszDir : Global::g_szCurModuleDir,
  543. now.tm_year + 1990,
  544. now.tm_mon + 1,
  545. now.tm_mday,
  546. now.tm_hour,
  547. now.tm_min,
  548. now.tm_sec,
  549. msc);
  550. }
  551. else
  552. {
  553. _stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%04d%02d%02d%02d%02d%02d%03d.bmp"),
  554. lpszDir ? lpszDir : Global::g_szCurModuleDir,
  555. now.tm_year + 1990,
  556. now.tm_mon + 1,
  557. now.tm_mday,
  558. now.tm_hour,
  559. now.tm_min,
  560. now.tm_sec,
  561. msc);
  562. }
  563. // 标记:未保存
  564. m_bSaveImage = FALSE;
  565. }
  566. // 唤醒:保存完成;
  567. m_saveImg_cond.wait(lk, [&]() {return m_bSaveImage; });
  568. // 解锁;
  569. lk.unlock();
  570. return std::string(m_CaptureInfo.szSaveDir);
  571. }
  572. void CUB530View::CaptureMultiImageEx(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime)
  573. {
  574. std::thread t([&](CUB530View* p, LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime) {
  575. // 连续截图;
  576. TCHAR szDir[MAX_PATH] = { 0 };
  577. _stprintf_s(szDir, lpszPrefix ? _T("%s%s-") : _T("%s%s"),
  578. lpszDir ? lpszDir : Global::g_szCurModuleDir,
  579. lpszPrefix ? lpszPrefix : _T(""));
  580. auto start = system_clock::now();
  581. while (true)
  582. {
  583. // C++11获取当前时间;
  584. time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
  585. // 等待截图完成;
  586. std::unique_lock<std::mutex> lk(m_mut_saveImg);
  587. {
  588. // 加锁;
  589. std::lock_guard<std::mutex> lk(m_mut_cpature);
  590. // 标记截图;
  591. m_bCaptureImage = TRUE;
  592. // 初始化数据;
  593. ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
  594. m_CaptureInfo.bIsJPG = bIsJPG;
  595. m_CaptureInfo.bSingle = FALSE;
  596. m_CaptureInfo.IsAutoName = TRUE;
  597. m_CaptureInfo.nCaputerCount = 0;
  598. m_CaptureInfo.nKeepTime = nDurationTime;
  599. _stprintf_s(m_CaptureInfo.szPrefix, _T("%s"), lpszPrefix);
  600. if (bIsJPG)
  601. {
  602. _stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%lld.jpg"), szDir, tp.time_since_epoch().count());
  603. }
  604. else
  605. {
  606. _stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%lld.bmp"), szDir, tp.time_since_epoch().count());
  607. }
  608. // 初始化标记为未保存;
  609. m_bSaveImage = FALSE;
  610. }
  611. // 唤醒:保存完成;
  612. m_saveImg_cond.wait(lk, [&]() {return m_bSaveImage; });
  613. // 解锁;
  614. lk.unlock();
  615. auto duration = duration_cast<milliseconds>(system_clock::now() - start);
  616. if (duration.count() >= nDurationTime)
  617. break;
  618. }
  619. }, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
  620. t.detach();
  621. }
  622. BOOL CUB530View::SaveImageByCaptureInfo(const CaptureInfo& capInfo)
  623. {
  624. if (m_pBuffer == NULL)
  625. {
  626. Global::WriteTextLog("SaveImageByCaptureInfo: m_pBuffer == NULL");
  627. return FALSE;
  628. }
  629. BOOL bRet = FALSE;
  630. // 保存截图;
  631. HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, m_nVideoWidth * m_nVideoHeight * 4);
  632. if (hMemery != NULL)
  633. {
  634. BYTE* pDstFrameBuffer = NULL;
  635. pDstFrameBuffer = (BYTE*)GlobalLock(hMemery);
  636. if (pDstFrameBuffer != NULL)
  637. {
  638. QRESULT QRet = QCAP_COLORSPACE_YUY2_TO_ABGR32(m_pBuffer,
  639. m_nVideoWidth,
  640. m_nVideoHeight,
  641. 0,
  642. pDstFrameBuffer,
  643. m_nVideoWidth,
  644. m_nVideoHeight,
  645. 0);
  646. Status stat = GenericError;
  647. Bitmap* pImg = ::new Bitmap(
  648. m_nVideoWidth,
  649. m_nVideoHeight,
  650. m_nVideoWidth * 4,
  651. PixelFormat32bppRGB,
  652. pDstFrameBuffer);
  653. if (m_bHoriontal && !m_bVertically)
  654. pImg->RotateFlip(RotateNoneFlipX);// 水平翻转;
  655. else if (m_bHoriontal && m_bVertically)
  656. pImg->RotateFlip(Rotate180FlipNone);// 270度;
  657. else if (!m_bHoriontal && m_bVertically)
  658. pImg->RotateFlip(Rotate180FlipX);// 垂直翻转;
  659. CLSID encoderClsid = { 0 };
  660. CString strFileName = m_CaptureInfo.szSaveDir;
  661. // 需要判断路径是否存在,不存在创建目录;
  662. int nIndex = strFileName.ReverseFind(_T('\\'));
  663. if (nIndex != -1)
  664. {
  665. if (!PathFileExists(strFileName.Left(nIndex)))
  666. {
  667. // 如果文件夹不存在,创建;
  668. SHCreateDirectoryEx(NULL, strFileName.Left(nIndex), NULL);
  669. }
  670. }
  671. BSTR newfile = strFileName.AllocSysString();
  672. if (!capInfo.bIsJPG)
  673. {
  674. Global::GetEncoderClsid(L"image/bmp", &encoderClsid);
  675. stat = pImg->Save(newfile, &encoderClsid, NULL);
  676. }
  677. else
  678. {
  679. Global::GetEncoderClsid(L"image/jpeg", &encoderClsid);
  680. EncoderParameters encoderParameters;
  681. encoderParameters.Count = 1;
  682. encoderParameters.Parameter[0].Guid = EncoderQuality;
  683. encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
  684. encoderParameters.Parameter[0].NumberOfValues = 1;
  685. // Save the image as a JPEG with quality level 100.
  686. ULONG uQuality = 100;
  687. encoderParameters.Parameter[0].Value = &uQuality;
  688. stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
  689. }
  690. if (pImg)
  691. ::delete pImg;
  692. pImg = NULL;
  693. SysFreeString(newfile);
  694. bRet = (stat == 0 ? TRUE : FALSE);
  695. if (!bRet)
  696. {
  697. Global::WriteTextLog("SaveImageByCaptureInfo: 保存图片失败 = %s", strFileName);
  698. }
  699. }
  700. else
  701. {
  702. Global::WriteTextLog("SaveImageByCaptureInfo: pDstFrameBuffer == NULL");
  703. }
  704. GlobalUnlock(hMemery);
  705. }
  706. else
  707. {
  708. DWORD dwError = GetLastError();
  709. CString strError = _T("");
  710. strError.Format(_T("hMemery == NULL分配内存出错:%ld\n"), dwError);
  711. Global::WriteTextLog("SaveImageByCaptureInfo: hMemery == NULL分配内存出错:%ld", dwError);
  712. }
  713. if (m_pBuffer)
  714. delete[]m_pBuffer;
  715. m_pBuffer = NULL;
  716. // 必须调用GlobalFree释放;
  717. GlobalFree(hMemery);
  718. return bRet;
  719. }
  720. void CUB530View::CaptureImageThread(CUB530View* pView)
  721. {
  722. CString strFileName = _T("");
  723. while (!pView->m_bAppQuit) {
  724. std::unique_lock<std::mutex> lk(pView->m_mut_thread); // 这里使用unique_lock是为了后面方便解锁
  725. #if 1 // 线程等待唤醒(避免线程虚假唤醒);
  726. pView->m_thread_cond.wait(lk, [&]() {return pView->m_pBuffer; });
  727. #else
  728. while (!pView->m_pBuffer)
  729. pView->m_data_cond.wait(lk);
  730. #endif
  731. //Global::WriteTextLogEx(1, "CaptureImageThread=%s", pView->m_CaptureInfo.szSaveDir);
  732. // 保存截图;
  733. pView->SaveImageByCaptureInfo(pView->m_CaptureInfo);
  734. // 标记保存完成;
  735. pView->m_bSaveImage = TRUE;
  736. // 通知截图完成;
  737. pView->m_saveImg_cond.notify_one();
  738. // 解锁;
  739. lk.unlock();
  740. }
  741. }
  742. void CUB530View::StartRecord(DWORD dwDuration, LPCTSTR lpSavePath)
  743. {
  744. QRESULT QRet = QCAP_RS_SUCCESSFUL;
  745. if (!m_bIsMp4) // 音频格式;
  746. {
  747. QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_PCM);
  748. //_tcscat_s(szPath, _T(".avi"));
  749. }
  750. else
  751. {
  752. QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC);
  753. //_tcscat_s(szPath, _T(".mp4"));
  754. }
  755. // 设置视频属性;
  756. QRet = QCAP_SET_VIDEO_RECORD_PROPERTY(
  757. m_hVideoDevice,
  758. 0,
  759. m_bSupportGPU ? QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK : QCAP_ENCODER_TYPE_SOFTWARE,
  760. QCAP_ENCODER_FORMAT_H264,
  761. QCAP_RECORD_MODE_CBR,
  762. 8000,
  763. 16 * 1024 * 1024, // 16最高质量;
  764. 30, // 每秒多少帧
  765. 0,
  766. 0,
  767. QCAP_DOWNSCALE_MODE_OFF);
  768. // 开始录屏;
  769. QRet = QCAP_START_RECORD(m_hVideoDevice, 0, const_cast<CHAR*>(lpSavePath), QCAP_RECORD_FLAG_FULL, 0.0, 0.0, 0.0, 0, NULL);
  770. m_bIsRecord = TRUE;
  771. }
  772. void CUB530View::StopRecord()
  773. {
  774. QCAP_STOP_RECORD(m_hVideoDevice, 0);
  775. m_bIsRecord = FALSE;
  776. }
  777. //////////////////////////////////////////////////////////////////////////
  778. void CUB530View::SetRibbonStatusBarText(CString strText, int uId)
  779. {
  780. if (g_pMainFrame)
  781. {
  782. g_pMainFrame->SetRibbonStatusBarText(strText, uId);
  783. }
  784. }
  785. void CUB530View::OnTimer(UINT_PTR nIDEvent)
  786. {
  787. // TODO: 在此添加消息处理程序代码和/或调用默认值
  788. if (nIDEvent == 0)
  789. {
  790. KillTimer(0);
  791. if (m_bNoSignal)
  792. {
  793. if (m_bIsRecord)
  794. {
  795. QCAP_STOP_RECORD(m_hVideoDevice, 0);
  796. m_bIsRecord = FALSE;
  797. }
  798. }
  799. else
  800. {
  801. }
  802. }
  803. CView::OnTimer(nIDEvent);
  804. }
  805. void CUB530View::OnCutBmp()
  806. {
  807. // TODO: 在此添加命令处理程序代码
  808. TCHAR szImgDir[MAX_PATH] = {0};
  809. if ( m_shotDir == ShotLocal )
  810. CaptureSingleImageAutoName(NULL, FALSE);
  811. else if (m_shotDir == ShotSystem)
  812. {
  813. CaptureSingleImageAutoName(g_pMainFrame->m_szCurMenuTreeDir, FALSE);
  814. }
  815. else if (m_shotDir == ShotSpec)
  816. {
  817. CaptureSingleImageAutoName(m_szSpecDir, FALSE);
  818. }
  819. }
  820. void CUB530View::OnCutJpg()
  821. {
  822. // TODO: 在此添加命令处理程序代码
  823. TCHAR szImgDir[MAX_PATH] = { 0 };
  824. if (m_shotDir == ShotLocal)
  825. CaptureSingleImageAutoName(NULL, TRUE);
  826. else if (m_shotDir == ShotSystem)
  827. {
  828. CaptureSingleImageAutoName(g_pMainFrame->m_szCurMenuTreeDir, TRUE);
  829. }
  830. else if (m_shotDir == ShotSpec)
  831. {
  832. CaptureSingleImageAutoName(m_szSpecDir, TRUE);
  833. }
  834. }
  835. void CUB530View::OnStartRecord()
  836. {
  837. // TODO: 在此添加命令处理程序代码
  838. TCHAR szPath[MAX_PATH] = { 0 };
  839. // 毫秒级;
  840. time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
  841. auto tt = std::chrono::system_clock::to_time_t(tp);
  842. std::tm now = { 0 };
  843. localtime_s(&now, &tt); // 时间戳转成本地时间;
  844. int msc = tp.time_since_epoch().count() % 1000;
  845. _stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d"),
  846. Global::g_szCurModuleDir,
  847. now.tm_year + 1990,
  848. now.tm_mon + 1,
  849. now.tm_mday,
  850. now.tm_hour,
  851. now.tm_min,
  852. now.tm_sec,
  853. msc);
  854. QRESULT QRet = QCAP_RS_SUCCESSFUL;
  855. if (!m_bIsMp4) // 音频格式;
  856. {
  857. QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_PCM);
  858. _tcscat_s(szPath, _T(".avi"));
  859. }
  860. else
  861. {
  862. QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC);
  863. _tcscat_s(szPath, _T(".mp4"));
  864. }
  865. // 设置视频属性;
  866. QRet = QCAP_SET_VIDEO_RECORD_PROPERTY(
  867. m_hVideoDevice,
  868. 0,
  869. m_bSupportGPU ? QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK : QCAP_ENCODER_TYPE_SOFTWARE,
  870. QCAP_ENCODER_FORMAT_H264,
  871. QCAP_RECORD_MODE_CBR,
  872. 8000,
  873. 16 * 1024 * 1024, // 16最高质量;
  874. 30, // 每秒多少帧
  875. 0,
  876. 0,
  877. QCAP_DOWNSCALE_MODE_OFF);
  878. // 开始录屏;
  879. QRet = QCAP_START_RECORD(m_hVideoDevice, 0, szPath, QCAP_RECORD_FLAG_FULL, 0.0, 0.0, 0.0, 0, NULL);
  880. m_bIsRecord = TRUE;
  881. }
  882. void CUB530View::OnStopRecord()
  883. {
  884. // TODO: 在此添加命令处理程序代码
  885. QCAP_STOP_RECORD(m_hVideoDevice, 0);
  886. m_bIsRecord = FALSE;
  887. }
  888. void CUB530View::OnCheckVertically()
  889. {
  890. // TODO: 在此添加命令处理程序代码
  891. CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
  892. CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_VERTICALLY);
  893. m_bVertically = !pCheckbox->IsChecked();
  894. if (m_hVideoDevice)
  895. {
  896. QCAP_SET_VIDEO_MIRROR(m_hVideoDevice, m_bHoriontal, m_bVertically);
  897. }
  898. }
  899. void CUB530View::OnCheckHoriontal()
  900. {
  901. // TODO: 在此添加命令处理程序代码
  902. CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
  903. CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_HORIONTAL);
  904. m_bHoriontal = !pCheckbox->IsChecked();
  905. if (m_hVideoDevice)
  906. {
  907. QCAP_SET_VIDEO_MIRROR(m_hVideoDevice, m_bHoriontal, m_bVertically);
  908. }
  909. }
  910. void CUB530View::OnUpdateCheckVertically(CCmdUI* pCmdUI)
  911. {
  912. // TODO: 在此添加命令更新用户界面处理程序代码
  913. pCmdUI->SetCheck(m_bVertically);
  914. }
  915. void CUB530View::OnUpdateCheckHoriontal(CCmdUI* pCmdUI)
  916. {
  917. // TODO: 在此添加命令更新用户界面处理程序代码
  918. pCmdUI->SetCheck(m_bHoriontal);
  919. }
  920. void CUB530View::OnTraymenuReconnect()
  921. {
  922. // TODO: 在此添加命令处理程序代码
  923. HwUninitialize();// 断开;
  924. Invalidate();
  925. HwInitialize();// 重连;
  926. }
  927. void CUB530View::OnCheckSuportGpu()
  928. {
  929. // TODO: 在此添加命令处理程序代码
  930. CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
  931. CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_SUPORT_GPU);
  932. m_bSupportGPU = !pCheckbox->IsChecked();
  933. }
  934. void CUB530View::OnCheckFormatMp4()
  935. {
  936. CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
  937. CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_FORMAT_MP4);
  938. m_bIsMp4 = !pCheckbox->IsChecked();
  939. }
  940. void CUB530View::OnCheckFormatAvi()
  941. {
  942. CMainFrame* pMain = (CMainFrame*)AfxGetMainWnd();
  943. CMFCRibbonButton* pCheckbox = pMain->GetRibbonButton(ID_CHECK_FORMAT_AVI);
  944. m_bIsMp4 = pCheckbox->IsChecked();
  945. }
  946. void CUB530View::OnUpdateCheckSuportGpu(CCmdUI* pCmdUI)
  947. {
  948. // TODO: 在此添加命令更新用户界面处理程序代码
  949. pCmdUI->SetCheck(m_bSupportGPU);
  950. }
  951. void CUB530View::OnUpdateCheckFormatMp4(CCmdUI* pCmdUI)
  952. {
  953. // TODO: 在此添加命令更新用户界面处理程序代码
  954. pCmdUI->SetCheck(m_bIsMp4);
  955. }
  956. void CUB530View::OnUpdateCheckFormatAvi(CCmdUI* pCmdUI)
  957. {
  958. // TODO: 在此添加命令更新用户界面处理程序代码
  959. pCmdUI->SetCheck(!m_bIsMp4);
  960. }
  961. void CUB530View::OnUpdateStartRecord(CCmdUI* pCmdUI)
  962. {
  963. // TODO: 在此添加命令更新用户界面处理程序代码
  964. pCmdUI->Enable(!m_bIsRecord);
  965. }
  966. void CUB530View::OnUpdateStopRecord(CCmdUI* pCmdUI)
  967. {
  968. // TODO: 在此添加命令更新用户界面处理程序代码
  969. pCmdUI->Enable(m_bIsRecord);
  970. }
  971. void CUB530View::OnCheckShotLocal()
  972. {
  973. CMFCRibbonBar* pRibbon = g_pMainFrame->GetRibbonBar();
  974. ASSERT_VALID(pRibbon);
  975. CMFCRibbonButton* pCheck = DYNAMIC_DOWNCAST(CMFCRibbonButton, pRibbon->FindByID(ID_CHECK_SHOT_LOCAL));
  976. if ( pCheck )
  977. {
  978. if ( pCheck->IsChecked() )
  979. {
  980. m_shotDir = ShotSystem;
  981. }
  982. else
  983. {
  984. m_shotDir = ShotLocal;
  985. }
  986. }
  987. }
  988. void CUB530View::OnUpdateCheckShotLocal(CCmdUI* pCmdUI)
  989. {
  990. // TODO: 在此添加命令更新用户界面处理程序代码
  991. if (m_shotDir == ShotLocal)
  992. pCmdUI->SetCheck(TRUE);
  993. else
  994. pCmdUI->SetCheck(FALSE);
  995. }
  996. void CUB530View::OnCheckShotSystem()
  997. {
  998. CMFCRibbonBar* pRibbon = g_pMainFrame->GetRibbonBar();
  999. ASSERT_VALID(pRibbon);
  1000. CMFCRibbonButton* pCheck = DYNAMIC_DOWNCAST(CMFCRibbonButton, pRibbon->FindByID(ID_CHECK_SHOT_SYSTEM));
  1001. if (pCheck)
  1002. {
  1003. if (pCheck->IsChecked())
  1004. {
  1005. m_shotDir = ShotSpec;
  1006. }
  1007. else
  1008. {
  1009. m_shotDir = ShotSystem;
  1010. }
  1011. }
  1012. }
  1013. void CUB530View::OnUpdateCheckShotSystem(CCmdUI* pCmdUI)
  1014. {
  1015. if (m_shotDir == ShotSystem)
  1016. pCmdUI->SetCheck(TRUE);
  1017. else
  1018. pCmdUI->SetCheck(FALSE);
  1019. }
  1020. void CUB530View::OnCheckShotSpec()
  1021. {
  1022. CMFCRibbonBar* pRibbon = g_pMainFrame->GetRibbonBar();
  1023. ASSERT_VALID(pRibbon);
  1024. CMFCRibbonButton* pCheck = DYNAMIC_DOWNCAST(CMFCRibbonButton, pRibbon->FindByID(ID_CHECK_SHOT_SPEC));
  1025. if (pCheck)
  1026. {
  1027. CFileFind finder;
  1028. CString path;
  1029. BOOL fileExist;
  1030. // 获取特定文件夹的LPITEMIDLIST,可以将之理解为HANDLE
  1031. // 所谓的特定文件夹,你可以用CSIDL_XXX来检索之。
  1032. LPITEMIDLIST rootLoation;
  1033. SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP, &rootLoation);
  1034. if (rootLoation == NULL) {
  1035. // unkown error
  1036. return;
  1037. }
  1038. // 配置对话框
  1039. BROWSEINFO bi;
  1040. ZeroMemory(&bi, sizeof(bi));
  1041. bi.pidlRoot = rootLoation; // 文件夹对话框之根目录,不指定的话则为我的电脑
  1042. bi.lpszTitle = _T("请选择截图保存路径……"); // 可以不指定
  1043. bi.hwndOwner = m_hWnd;
  1044. // 打开对话框, 有点像DoModal
  1045. LPITEMIDLIST targetLocation = SHBrowseForFolder(&bi);
  1046. if (targetLocation != NULL)
  1047. {
  1048. m_shotDir = ShotSpec;
  1049. SHGetPathFromIDList(targetLocation, m_szSpecDir);
  1050. _tcscat_s(m_szSpecDir, _T("\\"));
  1051. }
  1052. }
  1053. }
  1054. void CUB530View::OnUpdateCheckShotSpec(CCmdUI* pCmdUI)
  1055. {
  1056. if (m_shotDir == ShotSpec)
  1057. pCmdUI->SetCheck(TRUE);
  1058. else
  1059. pCmdUI->SetCheck(FALSE);
  1060. }
  1061. int CUB530View::OnCreate(LPCREATESTRUCT lpCreateStruct)
  1062. {
  1063. if (CFormView::OnCreate(lpCreateStruct) == -1)
  1064. return -1;
  1065. // TODO: 在此添加您专用的创建代码
  1066. // 初始化共享内存;
  1067. #if _USE_DLGVIEW_
  1068. CMemoryClient::m_pView = this;
  1069. #endif
  1070. g_ub530.InitMemery();
  1071. g_ub530.StartThread();
  1072. // TODO: 在此添加您专用的创建代码
  1073. // 创建视频流,并关联指定显示窗口;
  1074. HwInitialize();
  1075. // 创建截图线程;
  1076. std::thread t(CaptureImageThread, this);
  1077. t.detach();
  1078. return 0;
  1079. }
  1080. void CUB530View::OnCheckIrShot()
  1081. {
  1082. // TODO: 在此添加命令处理程序代码
  1083. CMFCRibbonBar* pRibbon = g_pMainFrame->GetRibbonBar();
  1084. ASSERT_VALID(pRibbon);
  1085. CMFCRibbonButton* pCheck = DYNAMIC_DOWNCAST(CMFCRibbonButton, pRibbon->FindByID(ID_CHECK_IR_SHOT));
  1086. if ( pCheck )
  1087. {
  1088. g_pMainFrame->m_bShotIR = !pCheck->IsChecked();
  1089. }
  1090. }
  1091. void CUB530View::OnUpdateCheckIrShot(CCmdUI* pCmdUI)
  1092. {
  1093. // TODO: 在此添加命令更新用户界面处理程序代码
  1094. pCmdUI->SetCheck(g_pMainFrame->m_bShotIR);
  1095. }