directshow的視頻採集

 directxShow的視頻採集,9.0版本之後的sdk把directshow從中分離出來了,所以本人下了後面的幾個版本都沒有找到要的SDK,汗啊.......

 所以下載9.0b,在微軟的網站上有,後面好像有個(2003)字樣.去下吧.

好了,從裏面提出一個只採集視頻的程序.

1.

// TestVideoDlg.h : 頭文件
//

#pragma once
#include 
"afxwin.h"


// CTestVideoDlg 對話框
class CTestVideoDlg : public CDialog
{
// 構造
public:
    CTestVideoDlg(CWnd
* pParent = NULL);    // 標準構造函數

// 對話框數據
    enum { IDD = IDD_TESTVIDEO_DIALOG };

    
protected:
    
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持


// 實現
protected:
    HICON m_hIcon;

    
// 生成的消息映射函數
    virtual BOOL OnInitDialog();
    afx_msg 
void OnSysCommand(UINT nID, LPARAM lParam);
    afx_msg 
void OnPaint();
    afx_msg HCURSOR OnQueryDragIcon();
    DECLARE_MESSAGE_MAP()
public:
    CStatic m_wndVideo;
protected:
    CComPtr
< IGraphBuilder > m_pGraph;
    CComPtr
< ISampleGrabber > m_pGrabber;

    HRESULT InitStillGraph( );

    
void Error( TCHAR * pText );

    
void GetDefaultCapDevice( IBaseFilter ** ppCap );
}
;

 

2.實現部分

 

// TestVideoDlg.cpp : 實現文件
//

#include 
"stdafx.h"
#include 
"TestVideo.h"
#include 
"TestVideoDlg.h"

#include 
"......commondshowutil.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#endif


#ifdef DEBUG
#define REGISTER_FILTERGRAPH
#endif

// 用於應用程序“關於”菜單項的 CAboutDlg 對話框

class CAboutDlg : public CDialog
{
public:
    CAboutDlg();

// 對話框數據
    enum { IDD = IDD_ABOUTBOX };

    
protected:
    
virtual void DoDataExchange(CDataExchange* pDX);    // DDX/DDV 支持

// 實現
protected:
    DECLARE_MESSAGE_MAP()
}
;

CAboutDlg::CAboutDlg() : CDialog(CAboutDlg::IDD)
{
}


void CAboutDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
}


BEGIN_MESSAGE_MAP(CAboutDlg, CDialog)
END_MESSAGE_MAP()


// CTestVideoDlg 對話框

HWND g_hwnd
=0;
DWORD g_dwGraphRegister
=0;  // For running object table

CTestVideoDlg::CTestVideoDlg(CWnd
* pParent /*=NULL*/)
    : CDialog(CTestVideoDlg::IDD, pParent)
{
    m_hIcon 
= AfxGetApp()->LoadIcon(IDR_MAINFRAME);
}


void CTestVideoDlg::DoDataExchange(CDataExchange* pDX)
{
    CDialog::DoDataExchange(pDX);
    DDX_Control(pDX, IDC_STATIC_VIDEO, m_wndVideo);
}


BEGIN_MESSAGE_MAP(CTestVideoDlg, CDialog)
    ON_WM_SYSCOMMAND()
    ON_WM_PAINT()
    ON_WM_QUERYDRAGICON()
    
//}}AFX_MSG_MAP
END_MESSAGE_MAP()


// CTestVideoDlg 消息處理程序

BOOL CTestVideoDlg::OnInitDialog()
{
    CDialog::OnInitDialog();

    
// 將“關於...”菜單項添加到系統菜單中。

    
// IDM_ABOUTBOX 必須在系統命令範圍內。
    ASSERT((IDM_ABOUTBOX & 0xFFF0== IDM_ABOUTBOX);
    ASSERT(IDM_ABOUTBOX 
< 0xF000);

    CMenu
* pSysMenu = GetSystemMenu(FALSE);
    
if (pSysMenu != NULL)
    
{
        CString strAboutMenu;
        strAboutMenu.LoadString(IDS_ABOUTBOX);
        
if (!strAboutMenu.IsEmpty())
        
{
            pSysMenu
->AppendMenu(MF_SEPARATOR);
            pSysMenu
->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu);
        }

    }


    
// 設置此對話框的圖標。當應用程序主窗口不是對話框時,框架將自動
    
//  執行此操作
    SetIcon(m_hIcon, TRUE);            // 設置大圖標
    SetIcon(m_hIcon, FALSE);        // 設置小圖標

    
// TODO: 在此添加額外的初始化代碼

    CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);

    g_hwnd 
= GetSafeHwnd();

    
// start up the still image capture graph
    
//
    HRESULT hr = InitStillGraph( );

    m_wndVideo.ModifyStyle(
0, WS_CLIPCHILDREN);
    
    
return TRUE;  // 除非設置了控件的焦點,否則返回 TRUE
}


void CTestVideoDlg::OnSysCommand(UINT nID, LPARAM lParam)
{
    
if ((nID & 0xFFF0== IDM_ABOUTBOX)
    
{
        CAboutDlg dlgAbout;
        dlgAbout.DoModal();
    }

    
else
    
{
        CDialog::OnSysCommand(nID, lParam);
    }

}


// 如果向對話框添加最小化按鈕,則需要下面的代碼
//  來繪製該圖標。對於使用文檔/視圖模型的 MFC 應用程序,
//  這將由框架自動完成。

void CTestVideoDlg::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
    
{
        CDialog::OnPaint();
    }

}


//當用戶拖動最小化窗口時系統調用此函數取得光標顯示。
HCURSOR CTestVideoDlg::OnQueryDragIcon()
{
    
return static_cast<HCURSOR>(m_hIcon);
}

void CTestVideoDlg::Error( TCHAR * pText )
{
    ::MessageBox( NULL, pText, TEXT(
"Error!"), MB_OK | MB_TASKMODAL | MB_SETFOREGROUND );
}



HRESULT CTestVideoDlg::InitStillGraph( )
{
    HRESULT hr;

    
// create a filter graph
    
//
    hr = m_pGraph.CoCreateInstance( CLSID_FilterGraph );
    
if!m_pGraph )
    
{
        Error( TEXT(
"Could not create filter graph") );
        
return E_FAIL;
    }


    
// get whatever capture device exists
    
//
    CComPtr< IBaseFilter > pCap;
    GetDefaultCapDevice( 
&pCap );
    
if!pCap )
    
{
        Error( TEXT(
"No video capture device was detected on your system. ")
               TEXT(
"This sample requires a functional video capture device, such ")
               TEXT(
"as a USB web camera.  Video capture will be disabled.") );
        
return E_FAIL;
    }


    
// add the capture filter to the graph
    
//
    hr = m_pGraph->AddFilter( pCap, L"Cap" );
    
if( FAILED( hr ) )
    
{
        Error( TEXT(
"Could not put capture device in graph"));
        
return E_FAIL;
    }


    
// create a sample grabber
    
//
    hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
    
if!m_pGrabber )
    
{
        Error( TEXT(
"Could not create SampleGrabber (is qedit.dll registered?)"));
        
return hr;
    }

    CComQIPtr
< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pGrabber );

    
// force it to connect to video, 24 bit
    
//
    CMediaType VideoType;
    VideoType.SetType( 
&MEDIATYPE_Video );
    VideoType.SetSubtype( 
&MEDIASUBTYPE_RGB24 );
    hr 
= m_pGrabber->SetMediaType( &VideoType ); // shouldn't fail
    if( FAILED( hr ) )
    
{
        Error( TEXT(
"Could not set media type"));
        
return hr;
    }


    
// add the grabber to the graph
    
//
    hr = m_pGraph->AddFilter( pGrabBase, L"Grabber" );
    
if( FAILED( hr ) )
    
{
        Error( TEXT(
"Could not put sample grabber in graph"));
        
return hr;
    }


    
// build the graph
    CComPtr<ICaptureGraphBuilder2> pCGB2;
    hr 
= pCGB2.CoCreateInstance (CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC);
    
if (FAILED( hr ))
    
{
        Error(TEXT (
"Can't get a ICaptureGraphBuilder2 reference"));
        
return hr;
    }


    hr 
= pCGB2->SetFiltergraph( m_pGraph );
    
if (FAILED( hr ))
    
{
        Error(TEXT(
"SetGraph failed"));
        
return hr;
    }



    
// If there is a VP pin present on the video device, then put the 
    
// renderer on CLSID_NullRenderer
    CComPtr<IPin> pVPPin;
    hr 
= pCGB2->FindPin(
                        pCap, 
                        PINDIR_OUTPUT, 
                        
&PIN_CATEGORY_VIDEOPORT, 
                        NULL, 
                        FALSE, 
                        
0
                        
&pVPPin);


    
// If there is a VP pin, put the renderer on NULL Renderer
    CComPtr<IBaseFilter> pRenderer;
    
if (S_OK == hr)
    
{   
        hr 
= pRenderer.CoCreateInstance(CLSID_NullRenderer);    
        
if (S_OK != hr)
        
{
            Error(TEXT(
"Unable to make a NULL renderer"));
            
return S_OK;
        }

        hr 
= m_pGraph->AddFilter(pRenderer, L"NULL renderer");
        
if (FAILED (hr))
        
{
            Error(TEXT(
"Can't add the filter to graph"));
            
return hr;
        }

    }


    hr 
= pCGB2->RenderStream(
                            
&PIN_CATEGORY_PREVIEW,
                            
&MEDIATYPE_Interleaved, 
                            pCap, 
                            pGrabBase, 
                            pRenderer);
    
if (FAILED (hr))
    
{
        
// try to render preview pin
        hr = pCGB2->RenderStream( 
                                
&PIN_CATEGORY_PREVIEW, 
                                
&MEDIATYPE_Video,
                                pCap, 
                                pGrabBase, 
                                pRenderer);

        
// try to render capture pin
        if( FAILED( hr ) )
        
{
            hr 
= pCGB2->RenderStream( 
                                    
&PIN_CATEGORY_CAPTURE, 
                                    
&MEDIATYPE_Video,
                                    pCap, 
                                    pGrabBase, 
                                    pRenderer);
        }

    }


    
if( FAILED( hr ) )
    
{
        Error( TEXT(
"Can't build the graph") );
        
return hr;
    }


    
// ask for the connection media type so we know how big
    
// it is, so we can write out bitmaps
    
//
    AM_MEDIA_TYPE mt;
    hr 
= m_pGrabber->GetConnectedMediaType( &mt );
    
if ( FAILED( hr) )
    
{
        Error( TEXT(
"Could not read the connected media type"));
        
return hr;
    }

    
    VIDEOINFOHEADER 
* vih = (VIDEOINFOHEADER*) mt.pbFormat;
  
/*  mCB.pOwner = this;
    mCB.lWidth  = vih->bmiHeader.biWidth;
    mCB.lHeight = vih->bmiHeader.biHeight;
*/

    FreeMediaType( mt );

    
// don't buffer the samples as they pass through
    
//
    hr = m_pGrabber->SetBufferSamples( FALSE );

    
// only grab one at a time, stop stream after
    
// grabbing one sample
    
//
    hr = m_pGrabber->SetOneShot( FALSE );

    
// set the callback, so we can grab the one sample
    
//
 
// hr = m_pGrabber->SetCallback( &mCB, 1 );

    
// find the video window and stuff it in our window
    
//
    CComQIPtr< IVideoWindow, &IID_IVideoWindow > pWindow = m_pGraph;
    
if!pWindow )
    
{
        Error( TEXT(
"Could not get video window interface"));
        
return E_FAIL;
    }


    
// set up the preview window to be in our dialog
    
// instead of floating popup
    
//
    HWND hwndPreview = NULL;
    GetDlgItem( IDC_STATIC_VIDEO, 
&hwndPreview );
    RECT rc;
    ::GetWindowRect( hwndPreview, 
&rc );

    hr 
= pWindow->put_Owner( (OAHWND) hwndPreview );
    hr 
= pWindow->put_Left( 0 );
    hr 
= pWindow->put_Top( 0 );
    hr 
= pWindow->put_Width( rc.right - rc.left );
    hr 
= pWindow->put_Height( rc.bottom - rc.top );
    hr 
= pWindow->put_WindowStyle( WS_CHILD | WS_CLIPSIBLINGS );
    hr 
= pWindow->put_Visible( OATRUE );
    
    
// Add our graph to the running object table, which will allow
    
// the GraphEdit application to "spy" on our graph
//#ifdef REGISTER_FILTERGRAPH
//    hr = AddGraphToRot(m_pGraph, &g_dwGraphRegister);
//    if (FAILED(hr))
//    {
//        Error(TEXT("Failed to register filter graph with ROT!"));
//        g_dwGraphRegister = 0;
//    }
//#endif

    
// run the graph
    
//
    CComQIPtr< IMediaControl, &IID_IMediaControl > pControl = m_pGraph;
    hr 
= pControl->Run( );
    
if( FAILED( hr ) )
    
{
        Error( TEXT(
"Could not run graph"));
        
return hr;
    }


// UpdateStatus(_T("Previewing Live Video"));
    return 0;
}


void CTestVideoDlg::GetDefaultCapDevice( IBaseFilter ** ppCap )
{
    HRESULT hr;

    ASSERT(ppCap);
    
if (!ppCap)
        
return;

    
*ppCap = NULL;

    
// create an enumerator
    
//
    CComPtr< ICreateDevEnum > pCreateDevEnum;
    pCreateDevEnum.CoCreateInstance( CLSID_SystemDeviceEnum );

    ASSERT(pCreateDevEnum);
    
if!pCreateDevEnum )
        
return;

    
// enumerate video capture devices
    
//
    CComPtr< IEnumMoniker > pEm;
    pCreateDevEnum
->CreateClassEnumerator( CLSID_VideoInputDeviceCategory, &pEm, 0 );

    ASSERT(pEm);
    
if!pEm )
        
return;

    pEm
->Reset( );
 
    
// go through and find first video capture device
    
//
    while1 )
    
{
        ULONG ulFetched 
= 0;
        CComPtr
< IMoniker > pM;

        hr 
= pEm->Next( 1&pM, &ulFetched );
        
if( hr != S_OK )
            
break;

        
// get the property bag interface from the moniker
        
//
        CComPtr< IPropertyBag > pBag;
        hr 
= pM->BindToStorage( 00, IID_IPropertyBag, (void**&pBag );
        
if( hr != S_OK )
            
continue;

        
// ask for the english-readable name
        
//
        CComVariant var;
        var.vt 
= VT_BSTR;
        hr 
= pBag->Read( L"FriendlyName"&var, NULL );
        
if( hr != S_OK )
            
continue;

        
// set it in our UI
        
//
        USES_CONVERSION;
//        SetDlgItemText( IDC_CAPOBJ, W2T( var.bstrVal ) );

        
// ask for the actual filter
        
//
        hr = pM->BindToObject( 00, IID_IBaseFilter, (void**) ppCap );
        
if*ppCap )
            
break;
    }


    
return;
}

 

3.其中要的類庫都在directshow的SDK例子中能找到.

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章