Jelajahi Sumber

修复截图失败问题:
1、CaptureSingleImageEx、CaptureSingleImageAutoNameEx、CaptureMultiImageEx三个函数均要加锁,该锁不与on_process_preview_video_buffer2共用同一个锁(m_mut_cpature),独立使用m_mut_saveImg锁;
2、CaptureSingleImageEx、CaptureSingleImageAutoNameEx、CaptureMultiImageEx三个函数均要加锁,且解锁动作由m_bSaveImage来决定;
3、CaptureSingleImageEx使用m_mut_saveImg确保某一时刻只有一个截图动作,再获取 m_mut_cpature 锁,更新截图信息,使用on_process_preview_video_buffer2开始保存图片数据,on_process_preview_video_buffer2再唤醒线程CaptureImageThread进行数据保存。

scbc.sat2 5 tahun lalu
induk
melakukan
e54aa1db40
2 mengubah file dengan 55 tambahan dan 74 penghapusan
  1. 52 73
      SATHelper/SATHelper/UB530View.cpp
  2. 3 1
      SATHelper/SATHelper/UB530View.h

+ 52 - 73
SATHelper/SATHelper/UB530View.cpp

@@ -72,6 +72,7 @@ QRETURN on_process_format_changed2(PVOID pDevice, ULONG nVideoInput, ULONG nAudi
 		strVideoInput,
 		strAudioInput
 	);
+	/*
 	Global::WriteTextLog(_T("采集卡格式变更:%d x %d%s @%2.3f FPS , %d CH x %d BITS x %d HZ ,  视频输入源 : %s ,  音频输入源 : %s"),
 		nVideoWidth,
 		nVH,
@@ -82,7 +83,7 @@ QRETURN on_process_format_changed2(PVOID pDevice, ULONG nVideoInput, ULONG nAudi
 		nAudioSampleFrequency,
 		strVideoInput,
 		strAudioInput);
-
+	*/
 	::SendMessage(g_pMainFrame->m_hWnd, MSG_STATUS_BAR, (WPARAM)&pView->m_strFormatChangedOutput, ID_STATUSBAR_PANE1);
 
 	// NO SOURCE
@@ -118,7 +119,6 @@ QRETURN on_process_no_signal_detected2(PVOID pDevice, ULONG nVideoInput, ULONG n
 	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;
@@ -137,7 +137,6 @@ QRETURN on_process_signal_removed2(PVOID pDevice, ULONG nVideoInput, ULONG nAudi
 	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;
@@ -151,33 +150,24 @@ QRETURN on_process_signal_removed2(PVOID pDevice, ULONG nVideoInput, ULONG nAudi
 QRETURN on_process_preview_video_buffer2(PVOID pDevice, double dSampleTime, BYTE* pFrameBuffer, ULONG nFrameBufferLen, PVOID pUserData)
 {
 	CUB530View* pView = (CUB530View*)pUserData;
-	if (pView)
-	{
+	if (pView) {
 		// 尝试加锁;
-		if (!pView->m_mut_cpature.try_lock())
-		{
-#ifdef DEBUG
-			OutputDebugStringA("!pView->m_mut_cpature.try_lock()\n");
-#endif
+		if (!pView->m_mut_cpature.try_lock()) {
 			return QCAP_RT_OK;
 		}
 
 		// 是否触发截图;
-		if (pView->m_bCaptureImage)
-		{
+		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
 		}
 
 		// 解锁;
@@ -500,9 +490,8 @@ void CUB530View::CaptureSingleImage(LPTSTR lpszFileName, BOOL bIsJPG)
 		{
 			QCAP_SNAPSHOT_BMP(m_hVideoDevice, lpszFileName, FALSE, 5000);
 		}
-#ifdef _DEBUG
-		Global::WriteTextLog("完成:CaptureSingleImage");
-#endif
+
+		Global::WriteTextLog("完成:CaptureSingleImage=%s", lpszFileName);
 	}
 }
 
@@ -543,9 +532,9 @@ std::string CUB530View::CaptureSingleImageAutoName(LPCTSTR lpszDir, BOOL bIsJPG)
 				msc);
 			QCAP_SNAPSHOT_BMP(m_hVideoDevice, szPath, FALSE, 5000);
 		}
-#ifdef _DEBUG
-		Global::WriteTextLog("完成:CaptureSingleImageAutoName");
-#endif
+
+		Global::WriteTextLog("完成:CaptureSingleImageAutoName=%s", szPath);
+
 		return std::string(szPath);
 	}
 
@@ -587,13 +576,15 @@ void CUB530View::CaptureMultiImage(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL bIs
 			if (duration.count() >= nDurationTime)
 				break;
 		}
-		}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
+	}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
 	t.detach();
 }
 
 
 void CUB530View::CaptureSingleImageEx(LPTSTR lpszFileName, BOOL bIsJPG)
 {
+	// 等待截图完成;
+	std::unique_lock<std::mutex> lk(m_mut_saveImg);
 	{
 		// 加锁;
 		std::lock_guard<std::mutex> lk(m_mut_cpature);
@@ -607,23 +598,21 @@ void CUB530View::CaptureSingleImageEx(LPTSTR lpszFileName, BOOL bIsJPG)
 		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;
+		m_bSaveImage = FALSE;
 	}
+	
+	// 保存完成;
+	m_saveImg_cond.wait(lk, [&]() {return m_bSaveImage; });
+	// 解锁;
+	lk.unlock();
 
-	// 等待截图完成;
-	{
-		// 加锁;
-		std::unique_lock<std::mutex> lk(m_mut_cpature);
-		m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
-		// 解锁;
-		lk.unlock();
-	}
 }
 
 std::string CUB530View::CaptureSingleImageAutoNameEx(LPCTSTR lpszDir, BOOL bIsJPG)
 {
+	// 等待截图完成;
+	std::unique_lock<std::mutex> lk(m_mut_saveImg);
 	{
 		// 加锁;
 		std::lock_guard<std::mutex> lk(m_mut_cpature);
@@ -670,21 +659,15 @@ std::string CUB530View::CaptureSingleImageAutoNameEx(LPCTSTR lpszDir, BOOL bIsJP
 				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();
+		// 标记:未保存
+		m_bSaveImage = FALSE;
 	}
 
+	// 唤醒:保存完成;
+	m_saveImg_cond.wait(lk, [&]() {return m_bSaveImage; });
+	// 解锁;
+	lk.unlock();
+	
 	return std::string(m_CaptureInfo.szSaveDir);
 }
 
@@ -703,6 +686,8 @@ void CUB530View::CaptureMultiImageEx(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL b
 			// C++11获取当前时间;
 			time_point<system_clock, ::chrono::milliseconds> tp = time_point_cast<std::chrono::milliseconds>(system_clock::now());
 
+			// 等待截图完成;
+			std::unique_lock<std::mutex> lk(m_mut_saveImg);
 			{
 				// 加锁;
 				std::lock_guard<std::mutex> lk(m_mut_cpature);
@@ -724,22 +709,20 @@ void CUB530View::CaptureMultiImageEx(LPCTSTR lpszDir, LPCTSTR lpszPrefix, BOOL b
 				{
 					_stprintf_s(m_CaptureInfo.szSaveDir, _T("%s%lld.bmp"), szDir, tp.time_since_epoch().count());
 				}
+				// 初始化标记为未保存;
+				m_bSaveImage = FALSE;
 			}
 
-			// 等待截图完成;
-			{
-				// 加锁;
-				std::unique_lock<std::mutex> lk(m_mut_cpature);
-				m_capture_cond.wait(lk, [&]() {return !m_pBuffer; });
-				// 解锁;
-				lk.unlock();
-			}
+			// 唤醒:保存完成;
+			m_saveImg_cond.wait(lk, [&]() {return m_bSaveImage; });
+			// 解锁;
+			lk.unlock();			
 
 			auto duration = duration_cast<milliseconds>(system_clock::now() - start);
 			if (duration.count() >= nDurationTime)
 				break;
 		}
-		}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
+	}, this, lpszDir, lpszPrefix, bIsJPG, nDurationTime);
 	t.detach();
 }
 
@@ -747,6 +730,7 @@ BOOL CUB530View::SaveImageByCaptureInfo(const CaptureInfo& capInfo)
 {
 	if (m_pBuffer == NULL)
 	{
+		Global::WriteTextLog("SaveImageByCaptureInfo: m_pBuffer == NULL");
 		return FALSE;
 	}
 
@@ -822,32 +806,28 @@ BOOL CUB530View::SaveImageByCaptureInfo(const CaptureInfo& capInfo)
 			SysFreeString(newfile);
 
 			bRet = (stat == 0 ? TRUE : FALSE);
-#ifdef DEBUG
-			if (bRet)
+
+			if (!bRet)
 			{
-				OutputDebugStringA(strFileName);
-				OutputDebugStringA("\tSave Image::Ok\n");
+				Global::WriteTextLog("SaveImageByCaptureInfo: 保存图片失败 = %s", strFileName);
 			}
-#endif
+
+			Global::WriteTextLogEx(3,"SaveImageByCaptureInfo: 保存图片成功 = %s", strFileName);
 		}
-#ifdef DEBUG
 		else
 		{
-			OutputDebugStringA("pDstFrameBuffer == NULL\n");
+			Global::WriteTextLog("SaveImageByCaptureInfo: pDstFrameBuffer == NULL");
 		}
-#endif
 
 		GlobalUnlock(hMemery);
 	}
-#ifdef DEBUG
 	else
 	{
 		DWORD dwError = GetLastError();
 		CString strError = _T("");
 		strError.Format(_T("hMemery == NULL分配内存出错:%ld\n"), dwError);
-		OutputDebugStringA(strError);
+		Global::WriteTextLog("SaveImageByCaptureInfo: hMemery == NULL分配内存出错:%ld", dwError);
 	}
-#endif
 
 	if (m_pBuffer)
 		delete[]m_pBuffer;
@@ -862,25 +842,24 @@ BOOL CUB530View::SaveImageByCaptureInfo(const CaptureInfo& capInfo)
 void CUB530View::CaptureImageThread(CUB530View* pView)
 {
 	CString strFileName = _T("");
-	while (!pView->m_bAppQuit)
-	{
+	while (!pView->m_bAppQuit) {
 		std::unique_lock<std::mutex> lk(pView->m_mut_thread);   // 这里使用unique_lock是为了后面方便解锁
-#if 1	// 避免线程虚假唤醒;
+#if 1	// 线程等待唤醒(避免线程虚假唤醒;
 		pView->m_thread_cond.wait(lk, [&]() {return pView->m_pBuffer; });
 #else
 		while (!pView->m_pBuffer)
 			pView->m_data_cond.wait(lk);
 #endif
+		Global::WriteTextLogEx(1, "CaptureImageThread=%s", pView->m_CaptureInfo.szSaveDir);
 		// 保存截图;
 		pView->SaveImageByCaptureInfo(pView->m_CaptureInfo);
+		// 标记保存完成;
+		pView->m_bSaveImage = TRUE;
 		// 通知截图完成;
-		pView->m_capture_cond.notify_one();
+		pView->m_saveImg_cond.notify_one();
 
 		// 解锁;
 		lk.unlock();
-
-		// sleep 10ms;
-		//this_thread::sleep_for(chrono::milliseconds(10));
 	}
 }
 

+ 3 - 1
SATHelper/SATHelper/UB530View.h

@@ -108,8 +108,10 @@ public:
 	// ->预览截图;
 	CaptureInfo m_CaptureInfo;
 	BOOL m_bCaptureImage;
+	BOOL m_bSaveImage;
 	std::mutex m_mut_cpature;
-	std::condition_variable m_capture_cond;
+	std::mutex m_mut_saveImg;
+	std::condition_variable m_saveImg_cond;
 	// 单次截图;
 	void CaptureSingleImageEx(LPTSTR lpszFileName, BOOL bIsJPG = TRUE);
 	// 单次截图并自动命名;