SATHelperView.cpp 34 KB

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