Browse Source

【软件版本】
V
【模块名称】

【问题原因】
多次打开摄像头时,程序崩溃,且内存会一直增涨。
【修改描述】
解决多次打开时,内存增长、程序崩溃的问题。(关闭Tab标签栏未实现,在切换下拉框时,仍会看到Tab页)
【测试结果】

sat23 3 years ago
parent
commit
6fbf98bbac

+ 23 - 6
FieldTestTool/FieldTestTool/CaptureVideo.cpp

@@ -30,6 +30,7 @@ CCaptureVideo::~CCaptureVideo()
 	SAFE_RELEASE(m_pMC);
 	SAFE_RELEASE(m_pGB);
 	SAFE_RELEASE(m_pBF);
+    SAFE_RELEASE(m_pVW);
 	SAFE_RELEASE(m_pGrabber);
 	CoUninitialize( );
 }
@@ -38,23 +39,32 @@ int CCaptureVideo::EnumDevices(CMFCRibbonComboBox *pCombobox)
 {
 	if (!pCombobox)
 		return -1;
+
 	int id = 0;
-	//枚举视频扑捉设备
+	// 建立系统设备枚举实例;
 	ICreateDevEnum *pCreateDevEnum;
 	HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,IID_ICreateDevEnum, (void**)&pCreateDevEnum);
 	if (hr != NOERROR)
-		return -1;
+    {
+        CoUninitialize();
+        return -1;
+    }
 
+    // 获取设备类枚举器;
 	IEnumMoniker *pEnum;
 	hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&pEnum, 0);
 	if (hr != NOERROR)
-		return -1;
+    {
+        CoUninitialize();
+        return -1;
+    }
 
     CString strCurName;
     int nIndex = pCombobox->GetCurSel();
     if ( nIndex != -1 )
         strCurName = pCombobox->GetItem(nIndex);
 
+    // 枚举设备名称;
 	pEnum->Reset();
 	ULONG cFetched;
 	IMoniker *pM;
@@ -101,7 +111,8 @@ HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
 		return hr;
 	}
 	// Bind Device Filter. We know the device because the id was passed in
-	if(!BindFilter(iDeviceID, &m_pBF))return S_FALSE;
+	if(!BindFilter(iDeviceID, &m_pBF))
+        return S_FALSE;
 	hr = m_pGB->AddFilter(m_pBF, L"Capture Filter");
 	// hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
 	// m_pBF, NULL, NULL);
@@ -118,9 +129,13 @@ HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
 	CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );
 	//设置视频格式
 	AM_MEDIA_TYPE mt;
+    IAMStreamConfig *pSC = NULL;
+    m_pCapture->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pBF, IID_IAMStreamConfig, (void **)&pSC);
+
 	ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));
 	mt.majortype = MEDIATYPE_Video;
-	mt.subtype = MEDIASUBTYPE_RGB24;
+	mt.subtype = MEDIASUBTYPE_RGB32;
+    mt.bTemporalCompression = FALSE;
 	hr = m_pGrabber->SetMediaType(&mt);
 	if( FAILED( hr ) )
     {
@@ -156,6 +171,8 @@ HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
 	VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat;
 	mCB.lWidth = vih->bmiHeader.biWidth;
 	mCB.lHeight = vih->bmiHeader.biHeight;
+    // 单位为100ns,所以每帧(10^7/p3)*100ns
+    vih->AvgTimePerFrame = 10000000 / 50;
 	FreeMediaType(mt);
 	hr = m_pGrabber->SetBufferSamples( FALSE );
 	hr = m_pGrabber->SetOneShot( FALSE );
@@ -164,7 +181,7 @@ HRESULT CCaptureVideo::Init(int iDeviceID, HWND hWnd)
 	m_hWnd = hWnd ;
 	SetupVideoWindow();
 	hr = m_pMC->Run();//开始视频捕捉
-	if(FAILED(hr))
+	if ( FAILED( hr) )
 	{
 		AfxMessageBox("Couldn’t run the graph!");
 		return hr;

+ 2 - 0
FieldTestTool/FieldTestTool/CaptureVideo.h

@@ -33,7 +33,9 @@ private:
 	IGraphBuilder *m_pGB;
 	ICaptureGraphBuilder2* m_pCapture;
 	IBaseFilter* m_pBF;
+    // 提供和播放控制有关的一些接口;
 	IMediaControl* m_pMC;
+    // 提供和窗口有关的一些接口;
 	IVideoWindow* m_pVW;
 	ISampleGrabber *m_pGrabber;
 protected:

+ 8 - 0
FieldTestTool/FieldTestTool/ChildFrm.cpp

@@ -30,6 +30,7 @@ BEGIN_MESSAGE_MAP(CChildFrame, CMDIChildWndEx)
 	ON_COMMAND(ID_FILE_PRINT_DIRECT, &CChildFrame::OnFilePrint)
 	ON_COMMAND(ID_FILE_PRINT_PREVIEW, &CChildFrame::OnFilePrintPreview)
 	ON_UPDATE_COMMAND_UI(ID_FILE_PRINT_PREVIEW, &CChildFrame::OnUpdateFilePrintPreview)
+    ON_WM_CLOSE()
 END_MESSAGE_MAP()
 
 // CChildFrame 构造/析构
@@ -96,3 +97,10 @@ void CChildFrame::OnUpdateFilePrintPreview(CCmdUI* pCmdUI)
 {
 	pCmdUI->SetCheck(m_dockManager.IsPrintPreviewValid());
 }
+
+void CChildFrame::OnClose()
+{
+    // TODO: 在此添加消息处理程序代码和/或调用默认值
+
+    CMDIChildWndEx::OnClose();
+}

+ 1 - 0
FieldTestTool/FieldTestTool/ChildFrm.h

@@ -45,4 +45,5 @@ protected:
 	DECLARE_MESSAGE_MAP()
 public:
 
+    afx_msg void OnClose();
 };

+ 46 - 8
FieldTestTool/FieldTestTool/MainFrm.cpp

@@ -64,6 +64,7 @@ BEGIN_MESSAGE_MAP(CMainFrame, CMDIFrameWndEx)
     ON_UPDATE_COMMAND_UI(ID_RIBBON_SWITCHER_CHECKBOXB, &CMainFrame::OnUpdateSwitcherCheckboxB)
     // 计时器;
     ON_WM_TIMER()
+    ON_WM_CLOSE()
 END_MESSAGE_MAP()
 
 // CMainFrame 构造/析构
@@ -77,11 +78,14 @@ CMainFrame::CMainFrame()
     m_bFindSwitcherPort = false;
     m_bSwitcherCheckA = false;
     m_bSwitcherCheckB = false;
+    m_pActiveView = NULL;
+    m_pChildFrame = NULL;
 	theApp.m_nAppLook = theApp.GetInt(_T("ApplicationLook"), ID_VIEW_APPLOOK_OFF_2007_BLUE);
 }
 
 CMainFrame::~CMainFrame()
 {
+    
 }
 
 int CMainFrame::OnCreate(LPCREATESTRUCT lpCreateStruct)
@@ -614,27 +618,47 @@ void CMainFrame::OnCameraCombobox()
         int nCurSel = pCameraCombo->GetCurSel();
         if ( nCurSel != -1 )
         {
+            if ( m_pChildFrame )
+            {
+                CFieldTestToolView *pView = (CFieldTestToolView*)m_pChildFrame->GetActiveView();
+                if ( pView->m_pCamera )
+                    delete pView->m_pCamera;
+                pView->m_pCamera = NULL;
+                //pView->GetDocument()->OnCloseDocument();
+
+                //pView->SendMessage(WM_CLOSE, 0, 0);
+                //pView->CloseWindow();
+                //m_pChildFrame->MDIDestroy();
+                m_pChildFrame->CloseWindow();
+                //m_pChildFrame->DestroyWindow();
+                //m_pChildFrame->SendMessage(WM_CLOSE, 0, 0);
+                //delete m_pChildFrame;
+                m_pChildFrame = NULL;
+            }
+  
             CString strCamera = pCameraCombo->GetItem(nCurSel);
             OutputDebugString(strCamera + _T("\r\n"));
 
             CCreateContext context;
-            CChildFrame *pChildView = new CChildFrame();
+            m_pChildFrame = new CChildFrame();
             context.m_pLastView = NULL;
             context.m_pCurrentFrame = this;
             context.m_pCurrentDoc = m_pDoc;
             context.m_pNewViewClass = RUNTIME_CLASS(CFieldTestToolView);
             context.m_pNewDocTemplate = m_pDocTemplate;
 
-            if (pChildView->LoadFrame(IDR_MAINFRAME, WS_MAXIMIZE | WS_CHILDWINDOW, this, &context))
+            if (m_pChildFrame->LoadFrame(IDR_MAINFRAME, WS_MAXIMIZE | WS_CHILDWINDOW, this, &context))
             {
-                pChildView->MDIActivate();
-                pChildView->InitialUpdateFrame(m_pDoc, TRUE);
-                pChildView->ShowWindow(SW_SHOWMAXIMIZED);
-                CFieldTestToolView *pView = (CFieldTestToolView*)pChildView->GetActiveView();
+                m_pChildFrame->MDIActivate();
+                m_pChildFrame->InitialUpdateFrame(m_pDoc, TRUE);
+                m_pChildFrame->ShowWindow(SW_SHOWMAXIMIZED);
+                CFieldTestToolView *pView = (CFieldTestToolView*)m_pChildFrame->GetActiveView();
+
                 if ( pView )
-                    pView->m_pCamera = &m_cap;
-                m_cap.Init(1, pChildView->GetSafeHwnd());
+                    pView->m_pCamera = new CCaptureVideo();
+                pView->m_pCamera->Init(nCurSel, m_pChildFrame->GetSafeHwnd());
             }
+            
         }
     }
 }
@@ -1163,3 +1187,17 @@ BOOL CMainFrame::PreTranslateMessage(MSG* pMsg)
     }
     return CMDIFrameWndEx::PreTranslateMessage(pMsg);
 }
+
+void CMainFrame::OnClose()
+{
+    // TODO: 在此添加消息处理程序代码和/或调用默认值
+    if ( m_pChildFrame )
+    {
+        CFieldTestToolView *pView = (CFieldTestToolView*)m_pChildFrame->GetActiveView();
+        if ( pView->m_pCamera )
+            delete pView->m_pCamera;
+        pView->m_pCamera = NULL;
+    }
+
+    CMDIFrameWndEx::OnClose();
+}

+ 6 - 0
FieldTestTool/FieldTestTool/MainFrm.h

@@ -19,6 +19,8 @@
 #include "CaptureVideo.h"
 #include "FieldTestToolDoc.h"
 
+class CChildFrame;
+
 class COutlookBar : public CMFCOutlookBar
 {
 	virtual BOOL AllowShowOnPaneMenu() const { return TRUE; }
@@ -124,11 +126,15 @@ public:
     // 查找USB切U盘设备串口
     bool IsUSBSwitchPort(CString strCOMPort);
 
+    // 记录活动窗口;
+    CView *m_pActiveView;
+    CChildFrame *m_pChildFrame;
 	CMFCOutlookBarTabCtrl* FindOutlookParent(CWnd* pWnd);
 	CMFCOutlookBarTabCtrl* m_pCurrOutlookWnd;
 	CMFCOutlookBarPane*    m_pCurrOutlookPage;
     afx_msg void OnTimer(UINT_PTR nIDEvent);
     virtual BOOL PreTranslateMessage(MSG* pMsg);
+    afx_msg void OnClose();
 };