|  | @@ -22,12 +22,223 @@
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #include "SATHelperDoc.h"
 | 
	
		
			
				|  |  |  #include "SATHelperView.h"
 | 
	
		
			
				|  |  | +#include "MainFrm.h"
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  #ifdef _DEBUG
 | 
	
		
			
				|  |  |  #define new DEBUG_NEW
 | 
	
		
			
				|  |  |  #endif
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +CMemoryClient g_ub530;
 | 
	
		
			
				|  |  | +static CMainFrame* g_pMainFrame = NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +VOID Dbg(CHAR* pszStr, ...)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	char szData[MAX_PATH] = "[SC] ";
 | 
	
		
			
				|  |  | +	va_list args;
 | 
	
		
			
				|  |  | +	va_start(args, pszStr);
 | 
	
		
			
				|  |  | +	_vsnprintf_s(szData + 5, MAX_PATH - 5, MAX_PATH - 6, pszStr, args);
 | 
	
		
			
				|  |  | +	va_end(args);
 | 
	
		
			
				|  |  | +	strcat_s(szData, "\n");
 | 
	
		
			
				|  |  | +	OutputDebugStringA(szData);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +//  FORMAT CHANGED CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +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)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	//Dbg("format changed Detected  \n");
 | 
	
		
			
				|  |  | +	CSATHelperView* pView = (CSATHelperView*)pUserData;
 | 
	
		
			
				|  |  | +	if (pView == NULL) { return QCAP_RT_OK; }
 | 
	
		
			
				|  |  | +	if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pView->m_nVideoWidth = nVideoWidth;
 | 
	
		
			
				|  |  | +	pView->m_nVideoHeight = nVideoHeight;
 | 
	
		
			
				|  |  | +	pView->m_bVideoIsInterleaved = bVideoIsInterleaved;
 | 
	
		
			
				|  |  | +	pView->m_dVideoFrameRate = dVideoFrameRate;
 | 
	
		
			
				|  |  | +	pView->m_nAudioChannels = nAudioChannels;
 | 
	
		
			
				|  |  | +	pView->m_nAudioBitsPerSample = nAudioBitsPerSample;
 | 
	
		
			
				|  |  | +	pView->m_nAudioSampleFrequency = nAudioSampleFrequency;
 | 
	
		
			
				|  |  | +	// OUTPUT FORMAT CHANGED MESSAGE
 | 
	
		
			
				|  |  | +	//
 | 
	
		
			
				|  |  | +	CHAR strVideoInput[MAX_PATH] = { 0 };
 | 
	
		
			
				|  |  | +	CHAR strAudioInput[MAX_PATH] = { 0 };
 | 
	
		
			
				|  |  | +	CHAR strFrameType[MAX_PATH] = { 0 };
 | 
	
		
			
				|  |  | +	UINT nVH = 0;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (nVideoInput == 0) { sprintf_s(strVideoInput, "COMPOSITE"); }
 | 
	
		
			
				|  |  | +	if (nVideoInput == 1) { sprintf_s(strVideoInput, "SVIDEO"); }
 | 
	
		
			
				|  |  | +	if (nVideoInput == 2) { sprintf_s(strVideoInput, "HDMI"); }
 | 
	
		
			
				|  |  | +	if (nVideoInput == 3) { sprintf_s(strVideoInput, "DVI_D"); }
 | 
	
		
			
				|  |  | +	if (nVideoInput == 4) { sprintf_s(strVideoInput, "COMPONENTS (YCBCR)"); }
 | 
	
		
			
				|  |  | +	if (nVideoInput == 5) { sprintf_s(strVideoInput, "DVI_A (RGB / VGA)"); }
 | 
	
		
			
				|  |  | +	if (nVideoInput == 6) { sprintf_s(strVideoInput, "SDI"); }
 | 
	
		
			
				|  |  | +	if (nVideoInput == 7) { sprintf_s(strVideoInput, "AUTO"); }
 | 
	
		
			
				|  |  | +	if (nAudioInput == 0) { sprintf_s(strAudioInput, "EMBEDDED_AUDIO"); }
 | 
	
		
			
				|  |  | +	if (nAudioInput == 1) { sprintf_s(strAudioInput, "LINE_IN"); }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (bVideoIsInterleaved == TRUE) { nVH = nVideoHeight / 2; }
 | 
	
		
			
				|  |  | +	else { nVH = nVideoHeight; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (bVideoIsInterleaved == TRUE) { sprintf_s(strFrameType, " I "); }
 | 
	
		
			
				|  |  | +	else { sprintf_s(strFrameType, " P "); }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pView->m_strFormatChangedOutput.Format(
 | 
	
		
			
				|  |  | +		_T("INFO : %d x %d%s @%2.3f FPS , %d CH x %d BITS x %d HZ ,  VIDEO INPUT : %s ,  AUDIO INPUT : %s"),
 | 
	
		
			
				|  |  | +		nVideoWidth,
 | 
	
		
			
				|  |  | +		nVH,
 | 
	
		
			
				|  |  | +		strFrameType,
 | 
	
		
			
				|  |  | +		dVideoFrameRate,
 | 
	
		
			
				|  |  | +		nAudioChannels,
 | 
	
		
			
				|  |  | +		nAudioBitsPerSample,
 | 
	
		
			
				|  |  | +		nAudioSampleFrequency,
 | 
	
		
			
				|  |  | +		strVideoInput,
 | 
	
		
			
				|  |  | +		strAudioInput
 | 
	
		
			
				|  |  | +	);
 | 
	
		
			
				|  |  | +	Global::WriteTextLog(_T("采集卡格式变更:%d x %d%s @%2.3f FPS , %d CH x %d BITS x %d HZ ,  视频输入源 : %s ,  音频输入源 : %s"),
 | 
	
		
			
				|  |  | +		nVideoWidth,
 | 
	
		
			
				|  |  | +		nVH,
 | 
	
		
			
				|  |  | +		strFrameType,
 | 
	
		
			
				|  |  | +		dVideoFrameRate,
 | 
	
		
			
				|  |  | +		nAudioChannels,
 | 
	
		
			
				|  |  | +		nAudioBitsPerSample,
 | 
	
		
			
				|  |  | +		nAudioSampleFrequency,
 | 
	
		
			
				|  |  | +		strVideoInput,
 | 
	
		
			
				|  |  | +		strAudioInput);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)&pView->m_strFormatChangedOutput, ID_STATUSBAR_PANE1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// NO SOURCE
 | 
	
		
			
				|  |  | +	//
 | 
	
		
			
				|  |  | +	if (nVideoWidth == 0 &&
 | 
	
		
			
				|  |  | +		nVideoHeight == 0 &&
 | 
	
		
			
				|  |  | +		dVideoFrameRate == 0.0 &&
 | 
	
		
			
				|  |  | +		nAudioChannels == 0 &&
 | 
	
		
			
				|  |  | +		nAudioBitsPerSample == 0 &&
 | 
	
		
			
				|  |  | +		nAudioSampleFrequency == 0)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		pView->m_bNoSignal = TRUE;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	else
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		pView->m_bNoSignal = FALSE;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pView->SetTimer(0x00000000, 1, NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// NO SIGNAL DETEACTED CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +QRETURN on_process_no_signal_detected(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, PVOID pUserData)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	AFX_MANAGE_STATE(AfxGetStaticModuleState());
 | 
	
		
			
				|  |  | +	CSATHelperView* pView = (CSATHelperView*)pUserData;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	//Dbg("No Signal Detected  \n");
 | 
	
		
			
				|  |  | +	if (pView == NULL) { return QCAP_RT_OK; }
 | 
	
		
			
				|  |  | +	if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	//pView->SetRibbonStatusBarText("当前采集卡无信号。", ID_STATUSBAR_PANE1);
 | 
	
		
			
				|  |  | +	Global::WriteTextLog(_T("当前采集卡无信号"));
 | 
	
		
			
				|  |  | +	::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)&CString("当前采集卡无信号"), ID_STATUSBAR_PANE1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pView->m_bNoSignal = TRUE;
 | 
	
		
			
				|  |  | +	pView->SetTimer(0x00000000, 1, NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// SIGNAL REMOVED CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +QRETURN on_process_signal_removed(PVOID pDevice, ULONG nVideoInput, ULONG nAudioInput, PVOID pUserData)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	AFX_MANAGE_STATE(AfxGetStaticModuleState());
 | 
	
		
			
				|  |  | +	CSATHelperView* pView = (CSATHelperView*)pUserData;
 | 
	
		
			
				|  |  | +	if (pView == NULL) { return QCAP_RT_OK; }
 | 
	
		
			
				|  |  | +	if (pView->GetSafeHwnd() == NULL) { return QCAP_RT_OK; }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	//pView->SetRibbonStatusBarText("当前采集卡信号被移除。", ID_STATUSBAR_PANE1);
 | 
	
		
			
				|  |  | +	Global::WriteTextLog(_T("当前采集卡信号被移除"));
 | 
	
		
			
				|  |  | +	::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)&CString("当前采集卡信号被移除"), ID_STATUSBAR_PANE1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	pView->m_bNoSignal = TRUE;
 | 
	
		
			
				|  |  | +	pView->SetTimer(0x00000000, 1, NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// PREVIEW VIDEO CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +QRETURN on_process_preview_video_buffer(PVOID pDevice, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, PVOID pUserData)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	CSATHelperView* pView = (CSATHelperView*)pUserData;
 | 
	
		
			
				|  |  | +	if (pView)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		// 尝试加锁;
 | 
	
		
			
				|  |  | +		if (!pView->m_mut_cpature.try_lock())
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +			OutputDebugStringA("!pView->m_mut_cpature.try_lock()\n");
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +			return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 是否触发截图;
 | 
	
		
			
				|  |  | +		if (pView->m_bCaptureImage)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			// 加锁;
 | 
	
		
			
				|  |  | +			std::lock_guard<std::mutex> lk(pView->m_mut_thread);
 | 
	
		
			
				|  |  | +			// 复制数据;
 | 
	
		
			
				|  |  | +			pView->m_dwBufferLen = nFrameBufferLen;
 | 
	
		
			
				|  |  | +			pView->m_pBuffer = new BYTE[nFrameBufferLen];
 | 
	
		
			
				|  |  | +			memcpy(pView->m_pBuffer, pFrameBuffer, nFrameBufferLen);
 | 
	
		
			
				|  |  | +			// 通知线程保存图片;
 | 
	
		
			
				|  |  | +			pView->m_thread_cond.notify_one();
 | 
	
		
			
				|  |  | +			// 恢复截图标记,防止重复截图;
 | 
	
		
			
				|  |  | +			pView->m_bCaptureImage = FALSE;
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +			OutputDebugStringA("preview_video_buffer:pView->m_bCaptureImage\n");
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 解锁;
 | 
	
		
			
				|  |  | +		pView->m_mut_cpature.unlock();
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// PREVIEW AUDIO CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +QRETURN on_process_preview_audio_buffer(PVOID pDevice, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, PVOID pUserData)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +// VIDEO HARDARE ENCODER CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +//
 | 
	
		
			
				|  |  | +QRETURN on_process_hardware_encoder_video_buffer(PVOID pDevice, UINT iRecNum, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, BOOL bIsKeyFrame, PVOID pUserData)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +QRETURN on_process_snapshot_done(PVOID pDevice, CHAR* pszFilePathName, PVOID pUserData)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +QRETURN on_process_snapshot_stream(PVOID pDevice, CHAR* pszFilePathName, BYTE* pStreamBuffer, ULONG nStreamBufferLen, PVOID pUserData)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	// 注意:在调用本回调函数前,已经保存了图片!
 | 
	
		
			
				|  |  | +	CSATHelperView* pView = (CSATHelperView*)pUserData;
 | 
	
		
			
				|  |  | +	if (pView->m_bHoriontal || pView->m_bVertically)
 | 
	
		
			
				|  |  | +		Global::SaveImgByRotate(pszFilePathName, pStreamBuffer, nStreamBufferLen, pView->m_bHoriontal, pView->m_bVertically);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return QCAP_RT_OK;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  |  // CSATHelperView
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  IMPLEMENT_DYNCREATE(CSATHelperView, CView)
 | 
	
	
		
			
				|  | @@ -39,6 +250,7 @@ BEGIN_MESSAGE_MAP(CSATHelperView, CView)
 | 
	
		
			
				|  |  |  	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CSATHelperView::OnFilePrintPreview)
 | 
	
		
			
				|  |  |  	ON_WM_CONTEXTMENU()
 | 
	
		
			
				|  |  |  	ON_WM_RBUTTONUP()
 | 
	
		
			
				|  |  | +	ON_WM_CREATE()
 | 
	
		
			
				|  |  |  END_MESSAGE_MAP()
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // CSATHelperView 构造/析构
 | 
	
	
		
			
				|  | @@ -46,11 +258,24 @@ END_MESSAGE_MAP()
 | 
	
		
			
				|  |  |  CSATHelperView::CSATHelperView() noexcept
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	// TODO: 在此处添加构造代码
 | 
	
		
			
				|  |  | -
 | 
	
		
			
				|  |  | +	m_hVideoDevice = NULL;
 | 
	
		
			
				|  |  | +	m_bIsRecord = FALSE;
 | 
	
		
			
				|  |  | +	m_bNoSignal = FALSE;
 | 
	
		
			
				|  |  | +	m_bVertically = FALSE;
 | 
	
		
			
				|  |  | +	m_bHoriontal = FALSE;
 | 
	
		
			
				|  |  | +	m_bAppQuit = FALSE;
 | 
	
		
			
				|  |  | +	m_pBuffer = NULL;
 | 
	
		
			
				|  |  | +	m_bCaptureImage = FALSE;
 | 
	
		
			
				|  |  | +	m_dwBufferLen = 0;
 | 
	
		
			
				|  |  | +	m_bIsMp4 = TRUE;
 | 
	
		
			
				|  |  | +	m_bSupportGPU = FALSE;
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  CSATHelperView::~CSATHelperView()
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  | +	g_ub530.EndOfThread();
 | 
	
		
			
				|  |  | +	m_bAppQuit = TRUE;
 | 
	
		
			
				|  |  | +	HwUninitialize();
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  BOOL CSATHelperView::PreCreateWindow(CREATESTRUCT& cs)
 | 
	
	
		
			
				|  | @@ -63,13 +288,48 @@ BOOL CSATHelperView::PreCreateWindow(CREATESTRUCT& cs)
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // CSATHelperView 绘图
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -void CSATHelperView::OnDraw(CDC* /*pDC*/)
 | 
	
		
			
				|  |  | +void CSATHelperView::OnDraw(CDC* pDC)
 | 
	
		
			
				|  |  |  {
 | 
	
		
			
				|  |  |  	CSATHelperDoc* pDoc = GetDocument();
 | 
	
		
			
				|  |  |  	ASSERT_VALID(pDoc);
 | 
	
		
			
				|  |  |  	if (!pDoc)
 | 
	
		
			
				|  |  |  		return;
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +	// TO FILL IN THE TEXT 
 | 
	
		
			
				|  |  | +	//
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice == 0 || m_bNoSignal) {
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		CFont font;
 | 
	
		
			
				|  |  | +		ULONG nFontSize = 300;
 | 
	
		
			
				|  |  | +		font.CreatePointFont(nFontSize, TEXT("Arial"), NULL);
 | 
	
		
			
				|  |  | +		HFONT hOldFont = (HFONT)pDC->SelectObject(&font);
 | 
	
		
			
				|  |  | +		pDC->SetBkMode(TRANSPARENT);
 | 
	
		
			
				|  |  | +		pDC->SetTextColor(RGB(255, 255, 255));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		CRect rect_client;
 | 
	
		
			
				|  |  | +		GetClientRect(&rect_client);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		CString string = _T("");
 | 
	
		
			
				|  |  | +		if (m_hVideoDevice == 0)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			CBrush brush_fill_rect(RGB(0, 0, 0));
 | 
	
		
			
				|  |  | +			pDC->FillRect(&rect_client, &brush_fill_rect);
 | 
	
		
			
				|  |  | +			string = TEXT("No Device");
 | 
	
		
			
				|  |  | +			//g_pMainFrame->SetRibbonStatusBarText("当前采集卡设备被移除。", ID_STATUSBAR_PANE1);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		else if (m_bNoSignal)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			CBrush brush_fill_rect(RGB(0, 0, 255));
 | 
	
		
			
				|  |  | +			pDC->FillRect(&rect_client, &brush_fill_rect);
 | 
	
		
			
				|  |  | +			string = TEXT("No Source");
 | 
	
		
			
				|  |  | +			//g_pMainFrame->SetRibbonStatusBarText("当前采集卡信号被移除。", ID_STATUSBAR_PANE1);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		pDC->DrawText(string, &rect_client, DT_SINGLELINE | DT_CENTER | DT_VCENTER);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		pDC->SelectObject(&hOldFont);
 | 
	
		
			
				|  |  | +		font.DeleteObject();
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  	// TODO: 在此处为本机数据添加绘制代码
 | 
	
		
			
				|  |  |  }
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -136,3 +396,587 @@ CSATHelperDoc* CSATHelperView::GetDocument() const // 非调试版本是内联
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |  // CSATHelperView 消息处理程序
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +BOOL CSATHelperView::HwInitialize()
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice != NULL)
 | 
	
		
			
				|  |  | +		return TRUE;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// CALLBACK FUNCTION       
 | 
	
		
			
				|  |  | +	PF_FORMAT_CHANGED_CALLBACK pFormatChangedCB = { 0 };
 | 
	
		
			
				|  |  | +	PF_VIDEO_PREVIEW_CALLBACK  pPreviewVideoCB = { 0 };
 | 
	
		
			
				|  |  | +	PF_AUDIO_PREVIEW_CALLBACK pPreviewAudioCB = { 0 };
 | 
	
		
			
				|  |  | +	PF_VIDEO_HARDWARE_ENCODER_CALLBACK pHardwareEncoderVideoCB = { 0 };
 | 
	
		
			
				|  |  | +	PF_NO_SIGNAL_DETECTED_CALLBACK pNoSignalDetectedCB = { 0 };
 | 
	
		
			
				|  |  | +	PF_SIGNAL_REMOVED_CALLBACK pSignalRemovedCB = { 0 };
 | 
	
		
			
				|  |  | +	PF_SNAPSHOT_DONE_CALLBACK pSnapShotDoneCB = { 0 };
 | 
	
		
			
				|  |  | +	PF_SNAPSHOT_STREAM_CALLBACK pSnapShotStreamCB = { 0 };
 | 
	
		
			
				|  |  | +	// CREATE CAPTURE DEVICE
 | 
	
		
			
				|  |  | +	//
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice == NULL)
 | 
	
		
			
				|  |  | +		QCAP_CREATE("CY3014 USB", 0, m_hWnd, &m_hVideoDevice, 1);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice == NULL) {
 | 
	
		
			
				|  |  | +		return FALSE;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// REGISTER FORMAT CHANGED CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +	pFormatChangedCB = on_process_format_changed;
 | 
	
		
			
				|  |  | +	QCAP_REGISTER_FORMAT_CHANGED_CALLBACK(m_hVideoDevice, pFormatChangedCB, this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// REGISTER PREVIEW VIDEO CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +	pPreviewVideoCB = on_process_preview_video_buffer;
 | 
	
		
			
				|  |  | +	QCAP_REGISTER_VIDEO_PREVIEW_CALLBACK(m_hVideoDevice, pPreviewVideoCB, this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// REGISTER PREVIEW AUDIO CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +	//pPreviewAudioCB = on_process_preview_audio_buffer;
 | 
	
		
			
				|  |  | +	//QCAP_REGISTER_AUDIO_PREVIEW_CALLBACK(m_hVideoDevice, pPreviewAudioCB, this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// REGISTER HARDWARE ENCODER VIDEO CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +	//pHardwareEncoderVideoCB = on_process_hardware_encoder_video_buffer;
 | 
	
		
			
				|  |  | +	//QCAP_REGISTER_VIDEO_HARDWARE_ENCODER_CALLBACK(m_hVideoDevice, 0, pHardwareEncoderVideoCB, this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// REGISTER NO SIGNAL DETECTED CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +	pNoSignalDetectedCB = on_process_no_signal_detected;
 | 
	
		
			
				|  |  | +	QCAP_REGISTER_NO_SIGNAL_DETECTED_CALLBACK(m_hVideoDevice, pNoSignalDetectedCB, this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// REGISTER SIGNAL REMOVED CALLBACK FUNCTION
 | 
	
		
			
				|  |  | +	pSignalRemovedCB = on_process_signal_removed;
 | 
	
		
			
				|  |  | +	QCAP_REGISTER_SIGNAL_REMOVED_CALLBACK(m_hVideoDevice, pSignalRemovedCB, this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#if 1
 | 
	
		
			
				|  |  | +	// 
 | 
	
		
			
				|  |  | +	pSnapShotDoneCB = on_process_snapshot_done;
 | 
	
		
			
				|  |  | +	QCAP_REGISTER_SNAPSHOT_DONE_CALLBACK(m_hVideoDevice, pSnapShotDoneCB, this);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 
 | 
	
		
			
				|  |  | +	pSnapShotStreamCB = on_process_snapshot_stream;
 | 
	
		
			
				|  |  | +	QCAP_REGISTER_SNAPSHOT_STREAM_CALLBACK(m_hVideoDevice, pSnapShotStreamCB, this);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	QCAP_SET_VIDEO_DEINTERLACE_TYPE(m_hVideoDevice, QCAP_SOFTWARE_DEINTERLACE_TYPE_BLENDING);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	QCAP_SET_VIDEO_DEINTERLACE(m_hVideoDevice, 0);
 | 
	
		
			
				|  |  | +	QCAP_SET_AUDIO_VOLUME(m_hVideoDevice, 100);
 | 
	
		
			
				|  |  | +	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);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	QCAP_SET_VIDEO_INPUT(m_hVideoDevice, QCAP_INPUT_TYPE_AUTO);
 | 
	
		
			
				|  |  | +	QCAP_RUN(m_hVideoDevice);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 刷新区域;
 | 
	
		
			
				|  |  | +	Invalidate();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// UPDATE USER INTERFACE RESOURCE
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice == 0) {
 | 
	
		
			
				|  |  | +		/*m_oSetupDialog.m_btnVideoInput.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnVideoQuality.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnAudioInput.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnSnapshot_bmp.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnSnapshot_jpg.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStart_1_1.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStop_1_1.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStart_1_2.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStop_1_2.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStart_1_3.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStop_1_3.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_1.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_1.SetCheck(0);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_2.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_2.SetCheck(0);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_3.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_3.SetCheck(0);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkAutoDeinterlace.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkAutoDeinterlace.SetCheck(0);*/
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	else {
 | 
	
		
			
				|  |  | +		/*m_oSetupDialog.m_btnSnapshot_bmp.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnSnapshot_jpg.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStart_1_1.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStop_1_1.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStart_1_2.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStop_1_2.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStart_1_3.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_btnRecordStop_1_3.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_1.EnableWindow(FALSE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_1.SetCheck(0);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_2.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_2.SetCheck(0);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_3.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkGPU_1_3.SetCheck(0);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkAutoDeinterlace.EnableWindow(TRUE);
 | 
	
		
			
				|  |  | +		m_oSetupDialog.m_checkAutoDeinterlace.SetCheck(0);*/
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return TRUE;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +BOOL CSATHelperView::HwUninitialize()
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice != 0) {
 | 
	
		
			
				|  |  | +		QCAP_STOP(m_hVideoDevice);
 | 
	
		
			
				|  |  | +		QCAP_DESTROY(m_hVideoDevice);
 | 
	
		
			
				|  |  | +		m_hVideoDevice = NULL;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return TRUE;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void CSATHelperView::CaptureSingleImage(LPTSTR lpszFileName, BOOL bIsJPG)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice != NULL)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		if (bIsJPG)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			QCAP_SNAPSHOT_JPG(m_hVideoDevice, lpszFileName, 100, FALSE, 5000); //参数4:是否异步;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			QCAP_SNAPSHOT_BMP(m_hVideoDevice, lpszFileName, FALSE, 5000);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +#ifdef _DEBUG
 | 
	
		
			
				|  |  | +		Global::WriteTextLog("完成:CaptureSingleImage");
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +std::string CSATHelperView::CaptureSingleImageAutoName(LPCTSTR lpszDir, BOOL bIsJPG)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (m_hVideoDevice != NULL)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		TCHAR szPath[MAX_PATH] = { 0 };
 | 
	
		
			
				|  |  | +		// 毫秒级;
 | 
	
		
			
				|  |  | +		time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
 | 
	
		
			
				|  |  | +		auto tt = std::chrono::system_clock::to_time_t(tp);
 | 
	
		
			
				|  |  | +		std::tm now = { 0 };
 | 
	
		
			
				|  |  | +		localtime_s(&now, &tt); // 时间戳转成本地时间;
 | 
	
		
			
				|  |  | +		int msc = tp.time_since_epoch().count() % 1000;
 | 
	
		
			
				|  |  | +		if (bIsJPG)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			_stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d.jpg"),
 | 
	
		
			
				|  |  | +				lpszDir ? lpszDir : Global::g_szCurModuleDir,
 | 
	
		
			
				|  |  | +				now.tm_year + 1990,
 | 
	
		
			
				|  |  | +				now.tm_mon + 1,
 | 
	
		
			
				|  |  | +				now.tm_mday,
 | 
	
		
			
				|  |  | +				now.tm_hour,
 | 
	
		
			
				|  |  | +				now.tm_min,
 | 
	
		
			
				|  |  | +				now.tm_sec,
 | 
	
		
			
				|  |  | +				msc);
 | 
	
		
			
				|  |  | +			QCAP_SNAPSHOT_JPG(m_hVideoDevice, szPath, 100, FALSE, 5000);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			_stprintf_s(szPath, _T("%s%04d%02d%02d%02d%02d%02d%03d.bmp"),
 | 
	
		
			
				|  |  | +				lpszDir ? lpszDir : Global::g_szCurModuleDir,
 | 
	
		
			
				|  |  | +				now.tm_year + 1990,
 | 
	
		
			
				|  |  | +				now.tm_mon + 1,
 | 
	
		
			
				|  |  | +				now.tm_mday,
 | 
	
		
			
				|  |  | +				now.tm_hour,
 | 
	
		
			
				|  |  | +				now.tm_min,
 | 
	
		
			
				|  |  | +				now.tm_sec,
 | 
	
		
			
				|  |  | +				msc);
 | 
	
		
			
				|  |  | +			QCAP_SNAPSHOT_BMP(m_hVideoDevice, szPath, FALSE, 5000);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +#ifdef _DEBUG
 | 
	
		
			
				|  |  | +		Global::WriteTextLog("完成:CaptureSingleImageAutoName");
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +		return std::string(szPath);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return std::string();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void CSATHelperView::CaptureMultiImage(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	std::thread t([&](CSATHelperView* p, LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime) {
 | 
	
		
			
				|  |  | +		// 连续截图;
 | 
	
		
			
				|  |  | +		TCHAR szDir[MAX_PATH] = { 0 };
 | 
	
		
			
				|  |  | +		TCHAR szPath[MAX_PATH] = { 0 };
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		_stprintf_s(szDir, lpszPrefix ? _T("%s%s-") : _T("%s%s"),
 | 
	
		
			
				|  |  | +			lpszDir ? lpszDir : Global::g_szCurModuleDir,
 | 
	
		
			
				|  |  | +			lpszPrefix ? lpszPrefix : _T(""));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		auto start = system_clock::now();
 | 
	
		
			
				|  |  | +		while (true)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			// C++11获取当前时间;
 | 
	
		
			
				|  |  | +			time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
 | 
	
		
			
				|  |  | +			if (bIsJPG)
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				_stprintf_s(szPath, _T("%s%lld.jpg"), szDir, tp.time_since_epoch().count());
 | 
	
		
			
				|  |  | +				QCAP_SNAPSHOT_JPG(m_hVideoDevice, szPath, 100, TRUE);
 | 
	
		
			
				|  |  | +				// 等待磁盘完成写入;
 | 
	
		
			
				|  |  | +				//Sleep(20);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			else
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				_stprintf_s(szPath, _T("%s%lld.bmp"), szDir, tp.time_since_epoch().count());
 | 
	
		
			
				|  |  | +				QCAP_SNAPSHOT_BMP(m_hVideoDevice, szPath, TRUE);
 | 
	
		
			
				|  |  | +				// 等待磁盘完成写入;
 | 
	
		
			
				|  |  | +				//Sleep(530);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			auto duration = duration_cast<milliseconds>(system_clock::now() - start);
 | 
	
		
			
				|  |  | +			if (duration.count() >= nDurationTime)
 | 
	
		
			
				|  |  | +				break;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
 | 
	
		
			
				|  |  | +	t.detach();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void CSATHelperView::CaptureSingleImageEx(LPTSTR lpszFileName, BOOL bIsJPG)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		// 加锁;
 | 
	
		
			
				|  |  | +		std::lock_guard<std::mutex> lk(m_mut_cpature);
 | 
	
		
			
				|  |  | +		// 标记截图;
 | 
	
		
			
				|  |  | +		m_bCaptureImage = TRUE;
 | 
	
		
			
				|  |  | +		// 初始化数据;
 | 
	
		
			
				|  |  | +		ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
 | 
	
		
			
				|  |  | +		m_CaptureInfo.bIsJPG = bIsJPG;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.bSingle = TRUE;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.IsAutoName = FALSE;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.nCaputerCount = 0;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.nKeepTime = 0;
 | 
	
		
			
				|  |  | +		memset(m_CaptureInfo.szPrefix, 0, 64);
 | 
	
		
			
				|  |  | +		//_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s"), lpszFileName);
 | 
	
		
			
				|  |  | +		_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s"), lpszFileName);
 | 
	
		
			
				|  |  | +		//m_strCaptureName = lpszFileName;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 等待截图完成;
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		// 加锁;
 | 
	
		
			
				|  |  | +		std::unique_lock<std::mutex> lk(m_mut_cpature);
 | 
	
		
			
				|  |  | +		m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
 | 
	
		
			
				|  |  | +		// 解锁;
 | 
	
		
			
				|  |  | +		lk.unlock();
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +std::string CSATHelperView::CaptureSingleImageAutoNameEx(LPCTSTR lpszDir, BOOL bIsJPG)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		// 加锁;
 | 
	
		
			
				|  |  | +		std::lock_guard<std::mutex> lk(m_mut_cpature);
 | 
	
		
			
				|  |  | +		// 标记截图;
 | 
	
		
			
				|  |  | +		m_bCaptureImage = TRUE;
 | 
	
		
			
				|  |  | +		// 初始化数据;
 | 
	
		
			
				|  |  | +		ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
 | 
	
		
			
				|  |  | +		m_CaptureInfo.bIsJPG = bIsJPG;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.bSingle = TRUE;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.IsAutoName = FALSE;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.nCaputerCount = 0;
 | 
	
		
			
				|  |  | +		m_CaptureInfo.nKeepTime = 0;
 | 
	
		
			
				|  |  | +		memset(m_CaptureInfo.szPrefix, 0, 64);
 | 
	
		
			
				|  |  | +		memset(m_CaptureInfo.szSaveDir, 0, MAX_PATH);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 毫秒级;
 | 
	
		
			
				|  |  | +		time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
 | 
	
		
			
				|  |  | +		auto tt = std::chrono::system_clock::to_time_t(tp);
 | 
	
		
			
				|  |  | +		std::tm now = { 0 };
 | 
	
		
			
				|  |  | +		localtime_s(&now, &tt); // 时间戳转成本地时间;
 | 
	
		
			
				|  |  | +		int msc = tp.time_since_epoch().count() % 1000;
 | 
	
		
			
				|  |  | +		if (bIsJPG)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%04d%02d%02d%02d%02d%02d%03d.jpg"),
 | 
	
		
			
				|  |  | +				lpszDir ? lpszDir : Global::g_szCurModuleDir,
 | 
	
		
			
				|  |  | +				now.tm_year + 1990,
 | 
	
		
			
				|  |  | +				now.tm_mon + 1,
 | 
	
		
			
				|  |  | +				now.tm_mday,
 | 
	
		
			
				|  |  | +				now.tm_hour,
 | 
	
		
			
				|  |  | +				now.tm_min,
 | 
	
		
			
				|  |  | +				now.tm_sec,
 | 
	
		
			
				|  |  | +				msc);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%04d%02d%02d%02d%02d%02d%03d.bmp"),
 | 
	
		
			
				|  |  | +				lpszDir ? lpszDir : Global::g_szCurModuleDir,
 | 
	
		
			
				|  |  | +				now.tm_year + 1990,
 | 
	
		
			
				|  |  | +				now.tm_mon + 1,
 | 
	
		
			
				|  |  | +				now.tm_mday,
 | 
	
		
			
				|  |  | +				now.tm_hour,
 | 
	
		
			
				|  |  | +				now.tm_min,
 | 
	
		
			
				|  |  | +				now.tm_sec,
 | 
	
		
			
				|  |  | +				msc);
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +		OutputDebugStringA(m_CaptureInfo.szSaveDir);
 | 
	
		
			
				|  |  | +		OutputDebugStringA("\tCVideoCaptureView::CaptureSingleImageAutoNameEx\n");
 | 
	
		
			
				|  |  | +#endif // DEBUG
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 等待截图完成;
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		// 加锁;
 | 
	
		
			
				|  |  | +		std::unique_lock<std::mutex> lk(m_mut_cpature);
 | 
	
		
			
				|  |  | +		m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
 | 
	
		
			
				|  |  | +		// 解锁;
 | 
	
		
			
				|  |  | +		lk.unlock();
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return std::string(m_CaptureInfo.szSaveDir);
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void CSATHelperView::CaptureMultiImageEx(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	std::thread t([&](CSATHelperView* p, LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIsJPG, int nDurationTime) {
 | 
	
		
			
				|  |  | +		// 连续截图;
 | 
	
		
			
				|  |  | +		TCHAR szDir[MAX_PATH] = { 0 };
 | 
	
		
			
				|  |  | +		_stprintf_s(szDir, lpszPrefix ? _T("%s%s-") : _T("%s%s"),
 | 
	
		
			
				|  |  | +			lpszDir ? lpszDir : Global::g_szCurModuleDir,
 | 
	
		
			
				|  |  | +			lpszPrefix ? lpszPrefix : _T(""));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		auto start = system_clock::now();
 | 
	
		
			
				|  |  | +		while (true)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			// C++11获取当前时间;
 | 
	
		
			
				|  |  | +			time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				// 加锁;
 | 
	
		
			
				|  |  | +				std::lock_guard<std::mutex> lk(m_mut_cpature);
 | 
	
		
			
				|  |  | +				// 标记截图;
 | 
	
		
			
				|  |  | +				m_bCaptureImage = TRUE;
 | 
	
		
			
				|  |  | +				// 初始化数据;
 | 
	
		
			
				|  |  | +				ZeroMemory(&m_CaptureInfo, sizeof(CaptureInfo));
 | 
	
		
			
				|  |  | +				m_CaptureInfo.bIsJPG = bIsJPG;
 | 
	
		
			
				|  |  | +				m_CaptureInfo.bSingle = FALSE;
 | 
	
		
			
				|  |  | +				m_CaptureInfo.IsAutoName = TRUE;
 | 
	
		
			
				|  |  | +				m_CaptureInfo.nCaputerCount = 0;
 | 
	
		
			
				|  |  | +				m_CaptureInfo.nKeepTime = nDurationTime;
 | 
	
		
			
				|  |  | +				_stprintf_s(m_CaptureInfo.szPrefix, _T("%s"), lpszPrefix);
 | 
	
		
			
				|  |  | +				if (bIsJPG)
 | 
	
		
			
				|  |  | +				{
 | 
	
		
			
				|  |  | +					_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%lld.jpg"), szDir, tp.time_since_epoch().count());
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +				else
 | 
	
		
			
				|  |  | +				{
 | 
	
		
			
				|  |  | +					_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%lld.bmp"), szDir, tp.time_since_epoch().count());
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			// 等待截图完成;
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				// 加锁;
 | 
	
		
			
				|  |  | +				std::unique_lock<std::mutex> lk(m_mut_cpature);
 | 
	
		
			
				|  |  | +				m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
 | 
	
		
			
				|  |  | +				// 解锁;
 | 
	
		
			
				|  |  | +				lk.unlock();
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			auto duration = duration_cast<milliseconds>(system_clock::now() - start);
 | 
	
		
			
				|  |  | +			if (duration.count() >= nDurationTime)
 | 
	
		
			
				|  |  | +				break;
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +		}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
 | 
	
		
			
				|  |  | +	t.detach();
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +BOOL CSATHelperView::SaveImageByCaptureInfo(const CaptureInfo& capInfo)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (m_pBuffer == NULL)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		return FALSE;
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	BOOL bRet = FALSE;
 | 
	
		
			
				|  |  | +	// 保存截图;
 | 
	
		
			
				|  |  | +	HGLOBAL hMemery = GlobalAlloc(GMEM_MOVEABLE, m_nVideoWidth * m_nVideoHeight * 4);
 | 
	
		
			
				|  |  | +	if (hMemery != NULL)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		BYTE* pDstFrameBuffer = NULL;
 | 
	
		
			
				|  |  | +		pDstFrameBuffer = (BYTE*)GlobalLock(hMemery);
 | 
	
		
			
				|  |  | +		if (pDstFrameBuffer != NULL)
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			QRESULT QRet = QCAP_COLORSPACE_YUY2_TO_ABGR32(m_pBuffer,
 | 
	
		
			
				|  |  | +				m_nVideoWidth,
 | 
	
		
			
				|  |  | +				m_nVideoHeight,
 | 
	
		
			
				|  |  | +				0,
 | 
	
		
			
				|  |  | +				pDstFrameBuffer,
 | 
	
		
			
				|  |  | +				m_nVideoWidth,
 | 
	
		
			
				|  |  | +				m_nVideoHeight,
 | 
	
		
			
				|  |  | +				0);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			Status stat = GenericError;
 | 
	
		
			
				|  |  | +			Bitmap* pImg = ::new Bitmap(
 | 
	
		
			
				|  |  | +				m_nVideoWidth,
 | 
	
		
			
				|  |  | +				m_nVideoHeight,
 | 
	
		
			
				|  |  | +				m_nVideoWidth * 4,
 | 
	
		
			
				|  |  | +				PixelFormat32bppRGB,
 | 
	
		
			
				|  |  | +				pDstFrameBuffer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			if (m_bHoriontal && !m_bVertically)
 | 
	
		
			
				|  |  | +				pImg->RotateFlip(RotateNoneFlipX);// 水平翻转;
 | 
	
		
			
				|  |  | +			else if (m_bHoriontal && m_bVertically)
 | 
	
		
			
				|  |  | +				pImg->RotateFlip(Rotate180FlipNone);// 270度;
 | 
	
		
			
				|  |  | +			else if (!m_bHoriontal && m_bVertically)
 | 
	
		
			
				|  |  | +				pImg->RotateFlip(Rotate180FlipX);// 垂直翻转;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			CLSID encoderClsid = { 0 };
 | 
	
		
			
				|  |  | +			CString strFileName = m_CaptureInfo.szSaveDir;
 | 
	
		
			
				|  |  | +			// 需要判断路径是否存在,不存在创建目录;
 | 
	
		
			
				|  |  | +			int nIndex = strFileName.ReverseFind(_T('\\'));
 | 
	
		
			
				|  |  | +			if (nIndex != -1)
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				if (!PathFileExists(strFileName.Left(nIndex)))
 | 
	
		
			
				|  |  | +				{
 | 
	
		
			
				|  |  | +					// 如果文件夹不存在,创建;
 | 
	
		
			
				|  |  | +					SHCreateDirectoryEx(NULL, strFileName.Left(nIndex), NULL);
 | 
	
		
			
				|  |  | +				}
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			BSTR newfile = strFileName.AllocSysString();
 | 
	
		
			
				|  |  | +			if (!capInfo.bIsJPG)
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				Global::GetEncoderClsid(L"image/bmp", &encoderClsid);
 | 
	
		
			
				|  |  | +				stat = pImg->Save(newfile, &encoderClsid, NULL);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +			else
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				Global::GetEncoderClsid(L"image/jpeg", &encoderClsid);
 | 
	
		
			
				|  |  | +				EncoderParameters encoderParameters;
 | 
	
		
			
				|  |  | +				encoderParameters.Count = 1;
 | 
	
		
			
				|  |  | +				encoderParameters.Parameter[0].Guid = EncoderQuality;
 | 
	
		
			
				|  |  | +				encoderParameters.Parameter[0].Type = EncoderParameterValueTypeLong;
 | 
	
		
			
				|  |  | +				encoderParameters.Parameter[0].NumberOfValues = 1;
 | 
	
		
			
				|  |  | +				// Save the image as a JPEG with quality level 100.
 | 
	
		
			
				|  |  | +				ULONG uQuality = 100;
 | 
	
		
			
				|  |  | +				encoderParameters.Parameter[0].Value = &uQuality;
 | 
	
		
			
				|  |  | +				stat = pImg->Save(newfile, &encoderClsid, &encoderParameters);
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			if (pImg)
 | 
	
		
			
				|  |  | +				::delete pImg;
 | 
	
		
			
				|  |  | +			pImg = NULL;
 | 
	
		
			
				|  |  | +			SysFreeString(newfile);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +			bRet = (stat == 0 ? TRUE : FALSE);
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +			if (bRet)
 | 
	
		
			
				|  |  | +			{
 | 
	
		
			
				|  |  | +				OutputDebugStringA(strFileName);
 | 
	
		
			
				|  |  | +				OutputDebugStringA("\tSave Image::Ok\n");
 | 
	
		
			
				|  |  | +			}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +		else
 | 
	
		
			
				|  |  | +		{
 | 
	
		
			
				|  |  | +			OutputDebugStringA("pDstFrameBuffer == NULL\n");
 | 
	
		
			
				|  |  | +		}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		GlobalUnlock(hMemery);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +#ifdef DEBUG
 | 
	
		
			
				|  |  | +	else
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		DWORD dwError = GetLastError();
 | 
	
		
			
				|  |  | +		CString strError = _T("");
 | 
	
		
			
				|  |  | +		strError.Format(_T("hMemery == NULL分配内存出错:%ld\n"), dwError);
 | 
	
		
			
				|  |  | +		OutputDebugStringA(strError);
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	if (m_pBuffer)
 | 
	
		
			
				|  |  | +		delete[]m_pBuffer;
 | 
	
		
			
				|  |  | +	m_pBuffer = NULL;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 必须调用GlobalFree释放;
 | 
	
		
			
				|  |  | +	GlobalFree(hMemery);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return bRet;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void CSATHelperView::CaptureImageThread(CSATHelperView* pView)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	CString strFileName = _T("");
 | 
	
		
			
				|  |  | +	while (!pView->m_bAppQuit)
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		std::unique_lock<std::mutex> lk(pView->m_mut_thread);   // 这里使用unique_lock是为了后面方便解锁
 | 
	
		
			
				|  |  | +#if 1	// 避免线程虚假唤醒;
 | 
	
		
			
				|  |  | +		pView->m_thread_cond.wait(lk, [&]() {return pView->m_pBuffer; });
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +		while (!pView->m_pBuffer)
 | 
	
		
			
				|  |  | +			pView->m_data_cond.wait(lk);
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +		// 保存截图;
 | 
	
		
			
				|  |  | +		pView->SaveImageByCaptureInfo(pView->m_CaptureInfo);
 | 
	
		
			
				|  |  | +		// 通知截图完成;
 | 
	
		
			
				|  |  | +		pView->m_capture_cond.notify_one();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// 解锁;
 | 
	
		
			
				|  |  | +		lk.unlock();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +		// sleep 10ms;
 | 
	
		
			
				|  |  | +		//this_thread::sleep_for(chrono::milliseconds(10));
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void CSATHelperView::StartRecord(DWORD dwDuration, LPCTSTR lpSavePath)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	QRESULT QRet = QCAP_RS_SUCCESSFUL;
 | 
	
		
			
				|  |  | +	if (!m_bIsMp4) // 音频格式;
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_PCM);
 | 
	
		
			
				|  |  | +		//_tcscat_s(szPath, _T(".avi"));
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +	else
 | 
	
		
			
				|  |  | +	{
 | 
	
		
			
				|  |  | +		QRet = QCAP_SET_AUDIO_RECORD_PROPERTY(m_hVideoDevice, 0, QCAP_ENCODER_TYPE_SOFTWARE, QCAP_ENCODER_FORMAT_AAC);
 | 
	
		
			
				|  |  | +		//_tcscat_s(szPath, _T(".mp4"));
 | 
	
		
			
				|  |  | +	}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 设置视频属性;
 | 
	
		
			
				|  |  | +	QRet = QCAP_SET_VIDEO_RECORD_PROPERTY(
 | 
	
		
			
				|  |  | +		m_hVideoDevice,
 | 
	
		
			
				|  |  | +		0,
 | 
	
		
			
				|  |  | +		m_bSupportGPU ? QCAP_ENCODER_TYPE_INTEL_MEDIA_SDK : QCAP_ENCODER_TYPE_SOFTWARE,
 | 
	
		
			
				|  |  | +		QCAP_ENCODER_FORMAT_H264,
 | 
	
		
			
				|  |  | +		QCAP_RECORD_MODE_CBR,
 | 
	
		
			
				|  |  | +		8000,
 | 
	
		
			
				|  |  | +		16 * 1024 * 1024, // 16最高质量;
 | 
	
		
			
				|  |  | +		30, // 每秒多少帧
 | 
	
		
			
				|  |  | +		0,
 | 
	
		
			
				|  |  | +		0,
 | 
	
		
			
				|  |  | +		QCAP_DOWNSCALE_MODE_OFF);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 开始录屏;
 | 
	
		
			
				|  |  | +	QRet = QCAP_START_RECORD(m_hVideoDevice, 0, const_cast<CHAR*>(lpSavePath), QCAP_RECORD_FLAG_FULL, 0.0, 0.0, 0.0, 0, NULL);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	m_bIsRecord = TRUE;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +void CSATHelperView::StopRecord()
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	QCAP_STOP_RECORD(m_hVideoDevice, 0);
 | 
	
		
			
				|  |  | +	m_bIsRecord = FALSE;
 | 
	
		
			
				|  |  | +}
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +int CSATHelperView::OnCreate(LPCREATESTRUCT lpCreateStruct)
 | 
	
		
			
				|  |  | +{
 | 
	
		
			
				|  |  | +	if (CView::OnCreate(lpCreateStruct) == -1)
 | 
	
		
			
				|  |  | +		return -1;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// TODO:  在此添加您专用的创建代码
 | 
	
		
			
				|  |  | +	// 初始化共享内存;
 | 
	
		
			
				|  |  | +	CMemoryClient::m_pView = this;
 | 
	
		
			
				|  |  | +	g_ub530.InitMemery();
 | 
	
		
			
				|  |  | +	g_ub530.StartThread();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	g_pMainFrame = (CMainFrame*)this->GetParent();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// TODO:  在此添加您专用的创建代码
 | 
	
		
			
				|  |  | +	// 创建视频流,并关联指定显示窗口;
 | 
	
		
			
				|  |  | +	HwInitialize();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	// 创建截图线程;
 | 
	
		
			
				|  |  | +	std::thread t(CaptureImageThread, this);
 | 
	
		
			
				|  |  | +	t.detach();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +	return 0;
 | 
	
		
			
				|  |  | +}
 |