关闭

directshow的视频采集

标签: nullvideoreferencedialogclass框架
2405人阅读 评论(1) 收藏 举报
分类:

 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例子中能找到.

 

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:47991次
    • 积分:599
    • 等级:
    • 排名:千里之外
    • 原创:15篇
    • 转载:9篇
    • 译文:1篇
    • 评论:16条
    文章分类
    文章存档
    最新评论