DirectShow 开启摄像头

来源:互联网 发布:类似知否的诙谐宅斗文 编辑:程序博客网 时间:2024/05/01 14:40

Win10 64 + VS2012

工程下载:
http://download.csdn.net/detail/yulinxx/9263639

建一个基于Dialog的MFC程序,而局如下:
一个PIC控件,用于显示摄像头捕捉画面,几个按钮
这里写图片描述

创建一个C++类,类名为:CCamera
在CCamera.h中,需要包含

#include <atlbase.h>#include "qedit.h"#include "dshow.h"#include <windows.h>

在#include “qedit.h”之前,需要添加如下代码,避免qedit.h报错:

#pragma include_alias( "dxtrans.h", "qedit.h" )#define __IDxtCompositor_INTERFACE_DEFINED__#define __IDxtAlphaSetter_INTERFACE_DEFINED__#define __IDxtJpeg_INTERFACE_DEFINED__#define __IDxtKey_INTERFACE_DEFINED__

CCamera.h 全文为:

#pragma once#pragma include_alias( "dxtrans.h", "qedit.h" )#define __IDxtCompositor_INTERFACE_DEFINED__#define __IDxtAlphaSetter_INTERFACE_DEFINED__#define __IDxtJpeg_INTERFACE_DEFINED__#define __IDxtKey_INTERFACE_DEFINED__#include <atlbase.h>#include "qedit.h"#include "dshow.h"#include <windows.h>#define MYFREEMEDIATYPE(mt)    {if ((mt).cbFormat != 0)        \{CoTaskMemFree((PVOID)(mt).pbFormat);    \    (mt).cbFormat =0;                        \    (mt).pbFormat = NULL;                    \}                                            \    if ((mt).pUnk != NULL)                        \{                                            \    (mt).pUnk->Release();                    \    (mt).pUnk = NULL;                        \}}                  class CCamera{public:    CCamera(void);    ~CCamera(void);private:    CImage m_image;    bool m_bConnected;    int m_nWidth;    int m_nHeight;    bool m_bLock;    bool m_bChanged;    long m_nBufferSize;    CComPtr<IGraphBuilder> m_pGraphBuilder;    CComPtr<IBaseFilter> m_pDeviceFilter;    CComPtr<IMediaControl> m_pMediaControl;    CComPtr<IBaseFilter> m_pSampleGrabberFilter;    CComPtr<ISampleGrabber> m_pSampleGrabber;    CComPtr<IPin> m_pGrabberInput;    CComPtr<IPin> m_pGrabberOutput;    CComPtr<IPin> m_pCameraOutput;    CComPtr<IMediaEvent> m_pMediaEvent;    CComPtr<IBaseFilter> m_pNullFilter;    CComPtr<IPin> m_pNullInputPin;    bool BindFilter(int nCameraIndex, IBaseFilter **pFilter);public:    static int CameraCount();     bool OpenCamera(int nCamID, bool bDisplayProperties=true, int nWidth =320, int nHeight =240);    CImage* QueryFrame(); };

CCamera.cpp 全文为

#include "stdafx.h"#include "Camera.h"#pragma comment(lib,"Strmiids.lib") CCamera::CCamera(void){}CCamera::~CCamera(void){}bool CCamera::BindFilter(int nCameraIndex, IBaseFilter **pFilter){    if (nCameraIndex < 0)        return false;    // enumerate all video capture devices    CComPtr<ICreateDevEnum> pCreateDevEnum;    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,        IID_ICreateDevEnum, (void**)&pCreateDevEnum);    if (hr != NOERROR)    {        return false;    }    CComPtr<IEnumMoniker> pEm;      // This will access the actual devices    // 为指定的Filter注册类型目录创建一个枚举器,并获得 IEnumMoniker接口 (Video Capture Sources    )    // 可以访问捕捉设备的列表了    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);    if (hr != NOERROR)     {        return false;    }    pEm->Reset();       // Go to the start of the enumerated list    ULONG cFetched;    IMoniker *pM;    int index =0;    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK, index <= nCameraIndex)    {        IPropertyBag *pBag;        // BindToStorage之后就可以访问设备标识的属性集了。        // Binds to the storage for the specified object. Unlike the IMoniker::BindToObject method,         //      this method does not activate the object identified by the moniker.        hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void**)&pBag);        if(SUCCEEDED(hr))         {            VARIANT var;            var.vt = VT_BSTR;            hr = pBag->Read(L"FriendlyName", &var, NULL);            if (hr == NOERROR)             {                if (index == nCameraIndex)                {                    // BindToObject将某个设备标识绑定到一个DirectShow Filter,                    //     然后调用IFilterGraph::AddFilter加入到Filter Graph中,这个设备就可以参与工作了                    // 调用IMoniker::BindToObject建立一个和选择的device联合的filter,                    //      并且装载filter的属性(CLSID,FriendlyName, and DevicePath)。                    // Binds to the specified object. The binding process involves finding the object,                     //      putting it into the running state if necessary,                     //      and providing the caller with a pointer to a specified interface on the identified object.                    pM->BindToObject(0, 0, IID_IBaseFilter, (void**)pFilter);                }                SysFreeString(var.bstrVal);            }            pBag->Release();        }        pM->Release();        index++;    }    pCreateDevEnum = NULL;    return true;}int CCamera::CameraCount(){    CoInitialize(NULL);    int nCount =0;    // enumerate all video capture devices    CComPtr<ICreateDevEnum> pCreateDevEnum;    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC_SERVER,        IID_ICreateDevEnum, (void**)&pCreateDevEnum);    CComPtr<IEnumMoniker> pEm;    // 使用接口方法ICreateDevEnum::CreateClassEnumerator为指定的Filter注册类型目录创建一个枚举器,并获得 IEnumMoniker接口;    hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);    if (hr != NOERROR)     {        return nCount;    }    pEm->Reset();    ULONG cFetched;    IMoniker *pM;    while(hr = pEm->Next(1, &pM, &cFetched), hr==S_OK)    {        nCount++;    }    pCreateDevEnum = NULL;    pEm = NULL;    return nCount;}bool CCamera::OpenCamera(int nCamID, bool bDisplayProperties/*=true*/, int nWidth /*=320*/, int nHeight /*=240*/){    HRESULT hr = S_OK;    CoInitialize(NULL);    // 调用CoCreateInstance来创建筛选器表管理器.筛选器表管理器由一个进程内的DLL提供,所以执行上下文是 CLSCTX_INPROC_SERVER    // 对CoCreateInstance的调用返回IGraphBuilder接口,它主要包含了生成筛选器表的方法。此例中用到的另两个接口为:    // IMediaControl,作用是控制流。它包含了停止和启动表的方法    //  IMediaEvent,它包含的方法是从筛选器表管理器中得到事件。    // 创建IGraphBuilder接口 Create the Filter Graph Manager. (用指定的类标识符创建一个Com对象)    // Filter Graph Manager    hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC,         IID_IGraphBuilder, (void**)&m_pGraphBuilder);    // IMediaControl接口,用来控制流媒体在Filter Graph中的流动,例如流媒体的启动和停止;    hr = m_pGraphBuilder->QueryInterface(IID_IMediaControl, (void**) &m_pMediaControl);    // IMediaEvent接口,该接口在Filter Graph发生一些事件时用来创建事件的标志信息并传送给应用程序    hr = m_pGraphBuilder->QueryInterface(IID_IMediaEvent, (void**) &m_pMediaEvent);    hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,        IID_IBaseFilter, (LPVOID*) &m_pNullFilter);    hr = m_pGraphBuilder->AddFilter(m_pNullFilter, L"NullRenderer");    hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,         IID_IBaseFilter, (LPVOID *)&m_pSampleGrabberFilter);    // 查询得到组件对象上的接口    hr = m_pSampleGrabberFilter->QueryInterface(IID_ISampleGrabber, (void**)&m_pSampleGrabber);    AM_MEDIA_TYPE   mt;    ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));    mt.majortype = MEDIATYPE_Video;    mt.subtype = MEDIASUBTYPE_RGB24;    mt.formattype = FORMAT_VideoInfo;     hr = m_pSampleGrabber->SetMediaType(&mt);    MYFREEMEDIATYPE(mt);    m_pGraphBuilder->AddFilter(m_pSampleGrabberFilter, L"Grabber");    // Bind Device Filter.  We know the device because the id was passed in    BindFilter(nCamID, &m_pDeviceFilter);    m_pGraphBuilder->AddFilter(m_pDeviceFilter, NULL);    CComPtr<IEnumPins> pEnum;    m_pDeviceFilter->EnumPins(&pEnum);    hr = pEnum->Reset();    // The Reset method resets the enumeration sequence to the beginning.    hr = pEnum->Next(1, &m_pCameraOutput, NULL);    // The Next method retrieves a specified number of pins in the enumeration sequence.    pEnum = NULL;     m_pSampleGrabberFilter->EnumPins(&pEnum);    pEnum->Reset();    hr = pEnum->Next(1, &m_pGrabberInput, NULL);     pEnum = NULL;    m_pSampleGrabberFilter->EnumPins(&pEnum);    pEnum->Reset();    pEnum->Skip(1);    hr = pEnum->Next(1, &m_pGrabberOutput, NULL);     pEnum = NULL;    m_pNullFilter->EnumPins(&pEnum);    pEnum->Reset();    hr = pEnum->Next(1, &m_pNullInputPin, NULL);    //SetCrossBar();    if (bDisplayProperties)     {        CComPtr<ISpecifyPropertyPages> pPages;        HRESULT hr = m_pCameraOutput->QueryInterface(IID_ISpecifyPropertyPages, (void**)&pPages);        if (SUCCEEDED(hr))        {            PIN_INFO PinInfo;            m_pCameraOutput->QueryPinInfo(&PinInfo);            CAUUID caGUID;            pPages->GetPages(&caGUID);            OleCreatePropertyFrame(NULL, 0, 0,                L"Property Sheet", 1,                (IUnknown **)&(m_pCameraOutput.p),                caGUID.cElems,                caGUID.pElems,                0, 0, NULL);            CoTaskMemFree(caGUID.pElems);            PinInfo.pFilter->Release();        }        pPages = NULL;    }    else     {        //////////////////////////////////////////////////////////////////////////////        // 加入由 lWidth和lHeight设置的摄像头的宽和高 的功能,默认320*240        // by flymanbox @2009-01-24        //////////////////////////////////////////////////////////////////////////////        int _Width = nWidth, _Height = nHeight;        IAMStreamConfig* iconfig = NULL;        hr = m_pCameraOutput->QueryInterface(IID_IAMStreamConfig, (void**)&iconfig);           AM_MEDIA_TYPE* pmt;            if(iconfig->GetFormat(&pmt) !=S_OK)         {            //printf("GetFormat Failed ! \n");            return false;           }        VIDEOINFOHEADER* phead;        if ( pmt->formattype == FORMAT_VideoInfo)           {               phead=( VIDEOINFOHEADER*)pmt->pbFormat;               phead->bmiHeader.biWidth = _Width;               phead->bmiHeader.biHeight = _Height;               if(( hr=iconfig->SetFormat(pmt)) != S_OK )               {                return false;            }        }           iconfig->Release();           iconfig=NULL;           MYFREEMEDIATYPE(*pmt);    }    hr = m_pGraphBuilder->Connect(m_pCameraOutput, m_pGrabberInput);    hr = m_pGraphBuilder->Connect(m_pGrabberOutput, m_pNullInputPin);    if (FAILED(hr))    {        switch(hr)        {        case VFW_S_NOPREVIEWPIN :            break;        case E_FAIL :            break;        case E_INVALIDARG :            break;        case E_POINTER :            break;        }    }    // The SetBufferSamples method specifies whether to copy sample data into a buffer as it goes through the filter.    m_pSampleGrabber->SetBufferSamples(TRUE);    // The SetOneShot method specifies whether the Sample Grabber filter halts after the filter receives a sample.    m_pSampleGrabber->SetOneShot(TRUE);    hr = m_pSampleGrabber->GetConnectedMediaType(&mt);    if(FAILED(hr))        return false;    VIDEOINFOHEADER *videoHeader;    videoHeader = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);    m_nWidth = videoHeader->bmiHeader.biWidth;    m_nHeight = videoHeader->bmiHeader.biHeight;    m_bConnected =true;    pEnum = NULL;    return true;}CImage* CCamera::QueryFrame(){    long evCode;    long size =0;    m_pMediaControl->Run();         // 运行filter    // 当筛选器运行时,数据从筛选器中移出,并以视频和音频的方式还原出来。    // 播放会启动另一个线程。您可以调用IMediaEvent::WaitForCompletion方法。    // 等待结束    m_pMediaEvent->WaitForCompletion(INFINITE, &evCode);    m_pSampleGrabber->GetCurrentBuffer(&size, NULL);    // If pBuffer is NULL, this parameter receives the required buffer size    //if the buffer size changed    if (size != m_nBufferSize)    {        m_nBufferSize = size;        m_image.Create(m_nWidth,m_nHeight,24);    }    if(m_image.IsNull())    {        return 0;    }    byte*q = NULL;    byte*p = new byte[m_nWidth*m_nHeight*3];    m_pSampleGrabber->GetCurrentBuffer(&m_nBufferSize, (long*)p);   // If pBuffer is not NULL, set this parameter equal to the size of the buffer, in bytes.    for(int y=0, z=m_nHeight-1; y<m_nHeight,z>=0; y++,z--)    {        q = (byte*)m_image.GetPixelAddress(0,z);        memcpy(q,&p[m_nWidth*3*y],m_nWidth*3);    }    delete []p;    return &m_image;}

”开启摄像头“”开启摄像头(选择性)“需互斥,
即点击其中一个按钮后,需禁用另一个按钮
选择性,可以在开启前,选择分辨率等参数

在Dlg.cpp中,点击”开启摄像头“按钮,响应如下代码:

    GetDlgItem(IDC_BTN_VIEW)->EnableWindow(TRUE);    GetDlgItem(IDC_BTN_VIEW2)->EnableWindow(FALSE);    int nCameraCount = CCamera::CameraCount();    m_vecCamera.resize(nCameraCount);    if (!m_vecCamera[nCameraCount-1].OpenCamera(nCameraCount-1, false, 640, 480))    {        AfxMessageBox(_T("打开摄像头失败"));        return;    }    while (true)    {        if (m_bStop)        {            break;        }        m_pImageView = m_vecCamera[nCameraCount - 1].QueryFrame();        OnDlgEvent();        ShowPicture(m_pImageView, &m_wndStcView);    }   

在Dlg.cpp中,点击”开启摄像头(选择性)“按钮,响应如下代码:

    GetDlgItem(IDC_BTN_VIEW)->EnableWindow(FALSE);    GetDlgItem(IDC_BTN_VIEW2)->EnableWindow(TRUE);    int nCameraCount = CCamera::CameraCount();    m_vecCamera.resize(nCameraCount);    if (!m_vecCamera[nCameraCount-1].OpenCamera(nCameraCount-1, true, 640, 480))    {        AfxMessageBox(_T("打开摄像头失败"));        return;    }    while (true)    {        if (m_bStop)        {            break;        }        m_pImageView = m_vecCamera[nCameraCount - 1].QueryFrame();        OnDlgEvent();        ShowPicture(m_pImageView, &m_wndStcView);    }   

DShowCameraDlg.h 全文为:

// DShowCameraDlg.h : 头文件//#pragma once#include <vector>// CDShowCameraDlg 对话框#include "Camera.h"#include "afxwin.h"class CDShowCameraDlg : public CDialogEx{// 构造public:    CDShowCameraDlg(CWnd* pParent = NULL);  // 标准构造函数// 对话框数据    enum { IDD = IDD_DSHOWCAMERA_DIALOG };    protected:    virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持// 实现protected:    HICON m_hIcon;    void ShowPicture(CImage* pImg,CStatic* pStcView);    // 生成的消息映射函数    virtual BOOL OnInitDialog();    afx_msg void OnPaint();    afx_msg void OnClose();    afx_msg void OnBnClickedOk();    afx_msg void OnBnClickedCancel();    afx_msg void OnBnClickedBtnView();    afx_msg void OnBnClickedBtnView2();    afx_msg HCURSOR OnQueryDragIcon();    DECLARE_MESSAGE_MAP()protected:    BOOL m_bStop;    CImage* m_pImageView;    int m_nCameraCount;    std::vector<CCamera> m_vecCamera;    CStatic m_wndStcView;};

DShowCameraDlg. cpp全文为:

// DShowCameraDlg.cpp : 实现文件//#include "stdafx.h"#include "DShowCamera.h"#include "DShowCameraDlg.h"#include "afxdialogex.h"#ifdef _DEBUG#define new DEBUG_NEW#endif// CDShowCameraDlg 对话框CDShowCameraDlg::CDShowCameraDlg(CWnd* pParent /*=NULL*/)    : CDialogEx(CDShowCameraDlg::IDD, pParent){    m_hIcon = AfxGetApp()->LoadIcon(IDR_MAINFRAME);    m_nCameraCount = -1;    m_pImageView = NULL;    m_bStop = FALSE;}void CDShowCameraDlg::DoDataExchange(CDataExchange* pDX){    CDialogEx::DoDataExchange(pDX);    DDX_Control(pDX, IDC_STC_VIEW, m_wndStcView);}BEGIN_MESSAGE_MAP(CDShowCameraDlg, CDialogEx)    ON_WM_PAINT()    ON_WM_QUERYDRAGICON()    ON_BN_CLICKED(IDC_BTN_VIEW, &CDShowCameraDlg::OnBnClickedBtnView)    ON_WM_DESTROY()    ON_WM_CLOSE()    ON_BN_CLICKED(IDOK, &CDShowCameraDlg::OnBnClickedOk)    ON_BN_CLICKED(IDCANCEL, &CDShowCameraDlg::OnBnClickedCancel)    ON_BN_CLICKED(IDC_BTN_VIEW2, &CDShowCameraDlg::OnBnClickedBtnView2)END_MESSAGE_MAP()// CDShowCameraDlg 消息处理程序void CDShowCameraDlg::ShowPicture(CImage* pImg,CStatic* pStcView){    if(pImg == NULL)         return;    int width = pImg->GetWidth();    int height = pImg->GetHeight();    CRect rectView;    pStcView->GetClientRect(&rectView);    CRect rt(rectView);    CDC* dc = pStcView->GetDC();    ASSERT(dc);    CBrush *pBrush = CBrush::FromHandle((HBRUSH)GetStockObject(WHITE_BRUSH));    //dc->FillRect(rt, pBrush);    if(rectView.Height() * width > height * rectView.Width())    {        CPoint p1(0, (rectView.Height()-(rectView.Width()*height/width))/2);        CPoint p2(rectView.Width(),(rectView.Height() - p1.y));        rt.SetRect(p1,p2);    }    else    {        CPoint pt1((rectView.Width()-(rectView.Height()*width/height))/2,0);        CPoint pt2(rectView.Width()-pt1.x, rectView.Height());        rt.SetRect(pt1,pt2);    }    if (dc)    {        ::SetStretchBltMode(dc->m_hDC, HALFTONE);        pImg->Draw(dc->m_hDC, rt);    }}BOOL CDShowCameraDlg::OnInitDialog(){    CDialogEx::OnInitDialog();    // 设置此对话框的图标。当应用程序主窗口不是对话框时,框架将自动    //  执行此操作    SetIcon(m_hIcon, TRUE);         // 设置大图标    SetIcon(m_hIcon, FALSE);        // 设置小图标    // TODO: 在此添加额外的初始化代码    return TRUE;  // 除非将焦点设置到控件,否则返回 TRUE}// 如果向对话框添加最小化按钮,则需要下面的代码//  来绘制该图标。对于使用文档/视图模型的 MFC 应用程序,//  这将由框架自动完成。void CDShowCameraDlg::OnPaint(){    if (IsIconic())    {        CPaintDC dc(this); // 用于绘制的设备上下文        SendMessage(WM_ICONERASEBKGND, reinterpret_cast<WPARAM>(dc.GetSafeHdc()), 0);        // 使图标在工作区矩形中居中        int cxIcon = GetSystemMetrics(SM_CXICON);        int cyIcon = GetSystemMetrics(SM_CYICON);        CRect rect;        GetClientRect(&rect);        int x = (rect.Width() - cxIcon + 1) / 2;        int y = (rect.Height() - cyIcon + 1) / 2;        // 绘制图标        dc.DrawIcon(x, y, m_hIcon);    }    else    {        CDialogEx::OnPaint();    }}//当用户拖动最小化窗口时系统调用此函数取得光标//显示。HCURSOR CDShowCameraDlg::OnQueryDragIcon(){    return static_cast<HCURSOR>(m_hIcon);}void OnDlgEvent(){    MSG msg;    if (::PeekMessage(&msg,NULL,0,0,PM_REMOVE))    {        ::TranslateMessage(&msg);        ::DispatchMessage(&msg);    }}// 开启摄像头void CDShowCameraDlg::OnBnClickedBtnView(){    GetDlgItem(IDC_BTN_VIEW)->EnableWindow(TRUE);    GetDlgItem(IDC_BTN_VIEW2)->EnableWindow(FALSE);    int nCameraCount = CCamera::CameraCount();    m_vecCamera.resize(nCameraCount);    if (!m_vecCamera[nCameraCount-1].OpenCamera(nCameraCount-1, false, 640, 480))    {        AfxMessageBox(_T("打开摄像头失败"));        return;    }    while (true)    {        if (m_bStop)        {            break;        }        m_pImageView = m_vecCamera[nCameraCount - 1].QueryFrame();        OnDlgEvent();        ShowPicture(m_pImageView, &m_wndStcView);    }   }void CDShowCameraDlg::OnBnClickedBtnView2(){    // TODO: 在此添加控件通知处理程序代码    GetDlgItem(IDC_BTN_VIEW)->EnableWindow(FALSE);    GetDlgItem(IDC_BTN_VIEW2)->EnableWindow(TRUE);    int nCameraCount = CCamera::CameraCount();    m_vecCamera.resize(nCameraCount);    if (!m_vecCamera[nCameraCount-1].OpenCamera(nCameraCount-1, true, 640, 480))    {        AfxMessageBox(_T("打开摄像头失败"));        return;    }    while (true)    {        if (m_bStop)        {            break;        }        m_pImageView = m_vecCamera[nCameraCount - 1].QueryFrame();        OnDlgEvent();        ShowPicture(m_pImageView, &m_wndStcView);    }   }void CDShowCameraDlg::OnClose(){    // TODO: 在此添加消息处理程序代码和/或调用默认值    m_bStop = TRUE;    CDialogEx::OnClose();}void CDShowCameraDlg::OnBnClickedOk(){    // TODO: 在此添加控件通知处理程序代码    m_bStop = TRUE;    CDialogEx::OnOK();}void CDShowCameraDlg::OnBnClickedCancel(){    // TODO: 在此添加控件通知处理程序代码    m_bStop = TRUE;    CDialogEx::OnCancel();}

qedit.h (可网上下载)全文为:

这里写图片描述

这里写图片描述


获取摄像头所支持的所有分辨率:

std::vector<POINT> CCamera::GetAllSupportPix(int iDeviceID){    HRESULT hr = S_OK;    std::vector<POINT> vecPix;    ICaptureGraphBuilder2* _pCapture = NULL;    IBaseFilter* _pBF;    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC,        IID_ICaptureGraphBuilder2, (void **)&_pCapture);    if (FAILED(hr))        return vecPix;    if (!BindFilter(iDeviceID, &_pBF))    {        srelease(_pCapture);        return vecPix;    }    IAMStreamConfig*  pStreamConfig;    AM_MEDIA_TYPE *pmtConfig;    hr = _pCapture->FindInterface(&PIN_CATEGORY_CAPTURE, 0,_pBF, IID_IAMStreamConfig, (void**)&pStreamConfig);     if (FAILED(hr))    {        srelease(_pCapture);        srelease(_pBF);        return vecPix;    }    pStreamConfig->GetFormat(&pmtConfig);    if (FAILED(hr))    {        srelease(_pCapture);        srelease(_pBF);        pStreamConfig->Release();        return vecPix;    }    VIDEOINFOHEADER * vi = (VIDEOINFOHEADER*) pmtConfig->pbFormat;    int iCount, iSize;    VIDEO_STREAM_CONFIG_CAPS caps;    pStreamConfig->GetNumberOfCapabilities(&iCount, &iSize);    AM_MEDIA_TYPE *pmtPV = NULL;    for (int i = 0; i<iCount; ++i)    {        if (pStreamConfig->GetStreamCaps(i, &pmtPV, (BYTE*)&caps) == S_OK)        {            if (pmtPV->subtype == MEDIASUBTYPE_RGB24)            {                POINT pix = {caps.MaxOutputSize.cx,caps.MaxOutputSize.cy};                vecPix.push_back(pix);            }            //FreeMediaType(*pmtPV);        }    }    srelease(_pCapture);    srelease(_pBF);    //FreeMediaType(*pmtConfig);    pStreamConfig->Release();    return vecPix;}


补充:
Camera.cpp 释放的时候
CCamera::~CCamera(void)

if(m_bConnected)    {        m_pMediaControl->Stop();    }    m_pGraphBuilder = NULL;    m_pDeviceFilter = NULL;    m_pMediaControl = NULL;    m_pSampleGrabberFilter = NULL;    m_pSampleGrabber = NULL;    m_pGrabberInput = NULL;    m_pGrabberOutput = NULL;    m_pCameraOutput = NULL;    m_pMediaEvent = NULL;    m_pNullFilter = NULL;    m_pNullInputPin = NULL;    if(!m_image.IsNull())    {        m_image.Destroy();    }    m_bConnected = false;    m_nWidth = 0;    m_nHeight = 0;    m_bLock = false;    m_bChanged = false;    m_nBufferSize = 0;    CoUninitialize();
0 0
原创粉丝点击