加载中…
个人资料
南冠彤
南冠彤
  • 博客等级:
  • 博客积分:0
  • 博客访问:415,028
  • 关注人气:59
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
相关博文
推荐博文
谁看过这篇博文
加载中…
正文 字体大小:

(转)CCapture directshow 视频捕获类

(2012-09-06 13:05:50)
标签:

杂谈

分类: DirectShow
http://blog.csdn.net/xgx198831/article/details/7284618

// Capture.h for class CCapture

#include <dshow.h>
#include <qedit.h>
#include <atlbase.h>
#if !defined(CAPTURE_H_________)
#define CAPTURE_H_________

// image size: 160*120  176*144   320*240  640*480  1024*1806
#define IMG_WIDTH 320
#define IMG_HEIGHT 240

typedef void (*capCallBackFunc)(LPVOID lParam);
enum DeviceType{DTypeVideo, DTypeAudio};
class CSampleGrabberCB; // 用于不会帧数据保存图片的接口
class CCapture
{
    friend class CSampleGrabberCB;
public:
    // 设置回调函数 用于处理获取的图片帧数据
    CDialog *m_dlgParent;
    capCallBackFunc calFunc;
    void SetCallBKFun(capCallBackFunc f);
    /////////////////////////////////
    CCapture();
    virtual ~CCapture();
    int EnumDevice(HWND hCmbList, DeviceType deviceType); // 设备枚举
//    void SaveGraph(TCHAR *wFileName);    // 保存滤波器链表
    void SetCameraFormat(HWND hwndParent);    // 设置摄像头的视频格式
    void SetCameraFilter(HWND hwndParent);    // 设置摄像头的图像参数
    HRESULT CaptureVideo(CString inFileName);    // 捕获保存视频
    HRESULT CaptureImage(CString inFileName);    // 抓取保存图片
    HRESULT CaptureImage(); // 抓取图片并显示
    HRESULT Preview(int iDevVideoID, HWND hVideo, int iDevAudioID = 0, HWND hAudio = NULL);    // 采集预览视频
    HRESULT InitCaptureGraphBuilder();    // 创建滤波器管理器,查询其各种控制接口
    void StopCapture();  // 停止捕获
    void FreeMediaType(AM_MEDIA_TYPE &mt);  // 释放对象内存

    void SetOnShot(BOOL bFlag);   // 设置是否捕获帧数据
    void SetParent(CDialog *pdlg);
protected:
    bool BindFilter(int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType); // 把指定的设备滤波器捆绑到链表中
    void ResizeVideoWindow();            // 更改视频显示窗口
    HRESULT SetupVideoWindow();            // 设置视频显示窗口的特性
    static UINT ThreadFunDrawText(LPVOID lParam);
private:
    HWND m_hWnd;            // 视频显示窗口的句柄
    IBaseFilter *m_pVideoCap;        // 视频捕获滤波器
    IBaseFilter *m_pAudioCap;        // 音频捕获滤波器
    CComPtr<ISampleGrabber> m_pGrabber;        // 抓取图片滤波器
    IBaseFilter *m_pMux;    // 写文件滤波器
    ICaptureGraphBuilder2 *m_pCapGB;    // 增强型捕获滤波器链表管理
    IGraphBuilder *m_pGB;    // 滤波链表管理器
    IVideoWindow *m_pVW;    // 视频显示窗口接口
    IMediaControl *m_pMC;    // 媒体控制接口
    static bool m_bRecording;        // 录制视频标志

    IBaseFilter *m_pXviDCodec;   //mpeg4 滤波器
};


#endif


/// Capture.cpp for class CCapture implement
//
///
////////////////////////////////////////

#include "StdAfx.h"
#include "Capture.h"
#include <atlconv.h>
#include "VideoChatDlg.h"
#include "yuv2bmp.h"

#ifndef srelease
#define srelease(x) if (NULL != x)\
{\
    x->Release();\
    x = NULL;\
}
#endif

#ifndef MAX_PATH
#define  MAX_PATH 1024
#endif
BOOL bOneShot = FALSE; // 全局变量
capCallBackFunc fun;

class CSampleGrabberCB : public ISampleGrabberCB
{
public:
    long lWidth;
    long lHeight;
    CCapture *pCap;
    TCHAR m_szFileName[MAX_PATH]; // 位图文件名称
    CSampleGrabberCB(){
        strcpy(m_szFileName, ".\\sample.bmp");
    }
    STDMETHODIMP_(ULONG) AddRef() { return 2; }
    STDMETHODIMP_(ULONG) Release() { return 1; }
    STDMETHODIMP QueryInterface(REFIID riid, void ** ppv){
        if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ){ 
        *ppv = (void *) static_cast<ISampleGrabberCB*> ( this );
            return NOERROR;
       
        return E_NOINTERFACE;
    }
    STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ){
        return 0;
    }
    STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ){
        if( !bOneShot )
            return 0;
        if (!pBuffer)
        {
            AfxMessageBox(_T("Save Bmp File Failure!"));
            return E_POINTER;
        }
        if (pBuffer != NULL && pCap)
        {
//             BYTE *rgb = new BYTE[lWidth*lHeight*3];   
//             YUV422_C_RGB(pBuffer,rgb, (int)lHeight, (int)lWidth);
//            outBmpBuf(pBuffer, pCap);  // 将一帧图像数据传给显示函数
//            ((CVideoNetDlg *)pCap->m_dlgParent)->SendVideo(pBuffer, (int)lBufferSize);
        }
    //    SaveBitmap(pBuffer, lBufferSize);  // 保存成位图文件
//        bOneShot = FALSE; // 停止捕获图像
//        AfxMessageBox(_T("Get bmp data success."));
        return 0;
    }
    void outBmpBuf(BYTE *buf, CCapture* cap)
    {
        cap->calFunc(buf);
    }
    // 创建位图文件
    BOOL SaveBitmap(BYTE *pBuffer, long lBufferLen)
    {
        HANDLE hf = CreateFile(m_szFileName, GENERIC_WRITE,
            FILE_SHARE_READ, NULL, CREATE_ALWAYS, NULL, NULL);
        if (hf == INVALID_HANDLE_VALUE) return 0;
        // 写文件头
        BITMAPFILEHEADER fileheader;
        ZeroMemory(&fileheader, sizeof(BITMAPFILEHEADER));
        fileheader.bfType = 'MB';
        fileheader.bfSize = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER)+lBufferLen;
        fileheader.bfOffBits = sizeof(BITMAPFILEHEADER)+sizeof(BITMAPINFOHEADER);
        DWORD dwWritter = 0;
        WriteFile(hf, &fileheader, sizeof(BITMAPFILEHEADER), &dwWritter, NULL);
        // 写文图格式
        BITMAPINFOHEADER infoHeader;
        ZeroMemory(&infoHeader, sizeof(BITMAPINFOHEADER));
        infoHeader.biSize = sizeof(BITMAPINFOHEADER);
        infoHeader.biSizeImage = lBufferLen;
        infoHeader.biWidth = lWidth;
        infoHeader.biHeight = lHeight;
        infoHeader.biBitCount = 24;
        WriteFile(hf, &infoHeader, sizeof(BITMAPINFOHEADER), &dwWritter, NULL);
        // 写位图数据
        WriteFile(hf, pBuffer, lBufferLen, &dwWritter, NULL);
        CloseHandle(hf);
        MessageBox(NULL, _T("Save bmp file succeed!"), _T("warn"), MB_OK|MB_ICONINFORMATION);
        return 0;
    }
};

/////////////////////////////////////////////
/// for class CCapture's Function
///
////////////////////////////////////////////////
CSampleGrabberCB samCB;
CCapture::CCapture()
{
    CoInitialize(NULL);  // 初始化COM库
    m_hWnd = NULL;
    m_pVideoCap = NULL;
    m_pAudioCap = NULL;
    m_pCapGB = NULL;
    m_pGB = NULL;
    m_pMC = NULL;
    m_pMux = NULL;
    m_pVW = NULL;
    m_pGrabber = NULL;
    m_dlgParent = NULL;
}
bool CCapture::m_bRecording = false;

CCapture::~CCapture()
{
    if (m_pMC) m_pMC->Stop();
    if (m_pVW)
    {
        m_pVW->put_Owner(NULL);
        m_pVW->put_Visible(OAFALSE);
    }
    m_hWnd = NULL;
    srelease(m_pVideoCap);
    srelease(m_pGB);
    srelease(m_pCapGB);
    srelease(m_pMC);
    srelease(m_pVW);
    m_bRecording = false;
    CoUninitialize(); // 释放COM库
}

int CCapture::EnumDevice( HWND hCmbList, DeviceType deviceType )
{
    if (hCmbList == NULL) return -1;
    int id = 0;
    /////枚举捕获设备
    ICreateDevEnum *pCreateDevEnum;
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,
        NULL,
        CLSCTX_INPROC_SERVER,
        IID_ICreateDevEnum,
        (LPVOID *)&pCreateDevEnum);
    if ( hr != NOERROR) return -1;
    //////// 获取视频类的枚举器
    IEnumMoniker *pEm;             //枚举监控器接口
    if (deviceType == DTypeVideo)
        hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEm, 0);
    // 如果获取音频类的枚举器 用下面的代码
    else
         hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEm, 0);
//    if (hr != NOERROR) return -1;
    if (!pEm || FAILED(hr)) return -1;
    ////////////////////////
    pEm->Reset();   // 类型枚举器复位
    ULONG cFetched;
    IMoniker *pM;    // 监控器接口指针
    while(hr = pEm->Next(1, &pM, &cFetched), hr == S_OK)
    {
        IPropertyBag *pBag;   // 属性页接口指针
        hr = pM->BindToStorage(0, 0, IID_IPropertyBag, (void **)&pBag);
        // 获取设备属性页
        if (SUCCEEDED(hr))
        {
            VARIANT var;
            var.vt = VT_BSTR;        // 保存的是二进制数据
            // 获取firendlyName 形式的信息
            hr = pBag->Read(L"FriendlyName", &var, NULL);
            if (hr == NOERROR) // 获取成功
            {
                id++;
                char szDeviceName[256] = {0};
                WideCharToMultiByte(CP_ACP, 0, var.bstrVal, -1, szDeviceName,80, NULL, NULL);  // 字符串编码转换UNICODE TO ANSI
                ::SendMessage(hCmbList, CB_ADDSTRING, 0, (LPARAM)szDeviceName);//添加到组合列表框
                SysFreeString(var.bstrVal);  //释放资源,特别要注意
            }
            pBag->Release();
        }
        pM->Release();
    }
    return 0;
}

void CCapture::ResizeVideoWindow()
{
    if (m_pVW)
    {
        // 让图像充满整个指定窗口
        CRect rc;
        ::GetClientRect(m_hWnd, &rc);
        m_pVW->SetWindowPosition(0, 0, rc.right, rc.bottom);
    }
}

HRESULT CCapture::SetupVideoWindow()
{
    HRESULT hr;
    //m_hWnd为类CCapture的成员变量,在使用该函数前须初始化
    hr = m_pVW->put_Visible(OAFALSE);  // 视频窗口不可见
    hr = m_pVW->put_Owner((OAHWND)m_hWnd);  // 设置视频窗口
    if (FAILED(hr)) return hr;
    hr = m_pVW->put_WindowStyle(WS_CHILD | WS_CLIPCHILDREN); //设置窗口类型
    if (FAILED(hr)) return hr;
    ResizeVideoWindow();   // 更改窗口大小
    hr = m_pVW->put_Visible(OATRUE);  // 显示视频窗口
    return hr;
}

HRESULT CCapture::InitCaptureGraphBuilder()
{
    HRESULT hr;
    //创建IGraphBuilder接口(滤波器链表管理器) m_pGB
    hr = CoCreateInstance(CLSID_FilterGraph, NULL,
        CLSCTX_INPROC, IID_IGraphBuilder, (void **)&m_pGB);
    if (FAILED(hr)) return hr;
    //创建ICaptureGraphBuilder2接口(增强型捕获滤波器链表管理器)m_pCapGB
    hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC, IID_ICaptureGraphBuilder2, (void **)&m_pCapGB);
    if (FAILED(hr)) return hr;
    // 创建抓取图片滤波器
    if (m_pGrabber){
        m_pGrabber.Release();
        m_pGrabber = NULL;
    }

    hr = CoCreateInstance(CLSID_SampleGrabber, NULL,CLSCTX_INPROC_SERVER, IID_ISampleGrabber, (void **)&m_pGrabber);
//    hr = m_pGrabber.CoCreateInstance( CLSID_SampleGrabber );
    if (FAILED(hr)) return hr;
    // 初始化滤波器链表管理器IGraphBuilder
    m_pCapGB->SetFiltergraph(m_pGB);
    // 查询媒体控制接口
    hr = m_pGB->QueryInterface(IID_IMediaControl, (void **)&m_pMC);
    if (FAILED(hr))  return hr;
    // 查询视频窗口接口
    hr = m_pGB->QueryInterface(IID_IVideoWindow, (LPVOID *)&m_pVW);
    if (FAILED(hr)) return hr;
    /////
    return hr;
}

HRESULT CCapture::Preview( int iDevVideoID, HWND hVideo, int iDevAudioID , HWND hAudio )
{
    HRESULT hr;
    if (m_pMC)
        m_pMC->Stop();
    m_bRecording = false;
    // 初始化视频捕获滤波器链表管理器
    hr = InitCaptureGraphBuilder();
    if (FAILED(hr)) return hr;

    // 把指定的视频采集设备与滤波器捆绑
    if (BindFilter(iDevVideoID, &m_pVideoCap, DTypeVideo))
    {
        // 把滤波器添加到滤波器链表中
        hr = m_pGB->AddFilter(m_pVideoCap, L"Video Capture Filter");
        if (FAILED(hr)) return hr;
    }
    else return FALSE;

    if (BindFilter(iDevAudioID, &m_pAudioCap, DTypeAudio))
    {
        hr = m_pGB->AddFilter(m_pAudioCap, L"Audio Capture Filter");
        if (FAILED(hr))
        {
            MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);
        //    return hr;
        }
    }
    else
    {
        MessageBox(NULL, _T("绑定音频设备失败!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);
    //    return FALSE;
    }
    // 如果我们想抓取24位的RGB图片,如下设置媒体图片类型
    CComQIPtr<IBaseFilter, &IID_IBaseFilter> pGrabBase(m_pGrabber);

    AM_MEDIA_TYPE mediaType;
    VIDEOINFOHEADER vih;

    IAMStreamConfig* pConfig = NULL;
    m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, IID_IAMStreamConfig, (void**)&pConfig);
    // 设置视频格式
    ZeroMemory(&mediaType, sizeof(AM_MEDIA_TYPE));
    vih.bmiHeader.biWidth = IMG_WIDTH;
    vih.bmiHeader.biHeight = IMG_HEIGHT;
    vih.bmiHeader.biSizeImage = IMG_HEIGHT*IMG_WIDTH*3;
    mediaType.pbFormat = (BYTE *)(&vih);
    mediaType.cbFormat = sizeof(VIDEOINFOHEADER);
    mediaType.subtype = MEDIASUBTYPE_YUY2;
    mediaType.majortype = MEDIATYPE_Video;
    mediaType.formattype = FORMAT_VideoInfo;
    hr = pConfig->SetFormat(&mediaType);
    hr = m_pGrabber->SetMediaType(&mediaType);
    if( FAILED( hr ) ){
        AfxMessageBox("Fail to set media type!");
        return hr;
    }
   
    hr = m_pGB->AddFilter(pGrabBase, L"SampleGrabber");
    if (FAILED(hr)) return hr;
    // 渲染媒体, 把链表中滤波器链接起来
    hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Audio, m_pAudioCap, NULL, NULL);
    hr = m_pCapGB->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);
    if (FAILED(hr))
        hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, pGrabBase, NULL);
    if( FAILED( hr ) ){
        AfxMessageBox(_T("Can’t build the graph"));
        return hr;
    }

    ////////// 设置图片捕获数据
    hr = m_pGrabber->GetConnectedMediaType( &mediaType );
    if ( FAILED( hr) ){
        AfxMessageBox(_T("Failt to read the connected media type"));
        return hr;
    }
    VIDEOINFOHEADER * pVih = (VIDEOINFOHEADER*)mediaType.pbFormat;
    samCB.lWidth = pVih->bmiHeader.biWidth;
    samCB.lHeight = pVih->bmiHeader.biHeight;
    samCB.pCap = (CCapture *)this;
    FreeMediaType(mediaType);
    hr = m_pGrabber->SetBufferSamples( TRUE );  // 如果此处为false 第一次抓取图片时失败(不用回调方式)
    hr = m_pGrabber->SetOneShot( FALSE );    
    hr = m_pGrabber->SetCallback( &samCB, 1 );
    SetOnShot(TRUE);// ture 时开始捕获视频帧数据
    // 设置视频显示窗口
    m_hWnd = hVideo;
    SetupVideoWindow(); // 设置显示窗口
    hr = m_pMC->Run();  // 开始采集、预览视频,并在指定窗口显示
    if (FAILED(hr))
    {
        MessageBox(NULL, _T("请检查该设备是否被占用!"), _T("系统提示"), MB_OK|MB_ICONINFORMATION);
        return hr;
    }
    return S_OK;
}

#if 1  // avi video format
HRESULT CCapture::CaptureVideo( CString inFileName )  // 录制视频
{
    HRESULT hr = 0;
    DWORD dwId;
    HANDLE hThread;
    m_bRecording = false;
    m_pMC->Stop();   // 先停止视频采集

    // 设置文件名,注意第二个参数类型
    hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL);

    //渲染媒体 连接捕获器和AVI Muxer过滤器
    hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video, m_pVideoCap, NULL, m_pMux);
    hr = m_pCapGB->RenderStream(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Audio, m_pAudioCap, NULL, m_pMux);
    //设置音频流为主流
    IConfigAviMux *pConfigMux;
    m_pMux->QueryInterface(IID_IConfigAviMux, (void **)&pConfigMux);
    hr = pConfigMux->SetMasterStream(1);   // 0 为视频  1为音频

    pConfigMux->Release();
    m_pMux->Release();
    m_bRecording = true;
    hThread = CreateThread(NULL, 0,
        (LPTHREAD_START_ROUTINE)ThreadFunDrawText,
        (LPVOID)m_hWnd,
        0, &dwId);
    m_pMC->Run();  // 恢复视频采集,同时写入文件
   
    return hr;
}
#else  // mpeg4 format video
HRESULT CCapture::CaptureVideo(CString inFileName)
{
    HRESULT hr=0;
   
    m_pMC->Stop();
   
    m_pGB->AddFilter(m_pXviDCodec,L"99 Xvid MPEG-4 Codec");
    m_pXviDCodec->Release();
   
    hr = m_pCapGB->SetOutputFileName(&MEDIASUBTYPE_Avi, inFileName.AllocSysString(), &m_pMux, NULL );
    hr = ConnectFilters(m_pGB,m_pSmartTee_1,m_pXviDCodec, 0);    //0,连接capture引脚
    hr = ConnectFilters(m_pGB,m_pXviDCodec,m_pMux, 2);    //2,默认自然连接
    m_pMux->Release();
   
    m_pMC->Run();
   
    return hr;
}
#endif

///////////////////////////////

HRESULT CCapture::CaptureImage() // 抓取并显示图像
{ // 采用CB接口回调函数存储图片
    bOneShot = TRUE;
    return 0;
}

HRESULT CCapture::CaptureImage( CString inFileName ) // 抓取图像
{
    HRESULT hr;
     AM_MEDIA_TYPE mediaType;
    hr = m_pGrabber->GetConnectedMediaType(&mediaType);
    if (FAILED(hr))  return hr;
    VIDEOINFOHEADER *pVih;
    if (mediaType.formattype == FORMAT_VideoInfo &&
        (mediaType.cbFormat >= sizeof(VIDEOINFOHEADER)) &&
        mediaType.pbFormat != NULL)
    {
        pVih = (VIDEOINFOHEADER *)mediaType.pbFormat;
    }
    else    
        return VFW_E_INVALIDMEDIATYPE;

//    hr = m_pGrabber->SetOneShot(TRUE);
    if (SUCCEEDED(m_pGrabber->SetBufferSamples(TRUE)) )  // 设置为缓冲形式)
    {
        long cbBuffer = 0;
        hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, NULL);
        BYTE *pBuffer = new BYTE[cbBuffer];
        if (!pBuffer) return -1;
        // 获取一帧媒体的数据
        hr = m_pGrabber->GetCurrentBuffer(&cbBuffer, (long *)pBuffer);
        if (FAILED(hr))  return hr;
//          if (pBuffer != NULL)
//          {
//              calFunc(pBuffer);   // 将一帧图像数据传给显示函数
//         }

        ///-------------------------测试所得数据是rgb格式还是yuv格式--------
        long n1,n2;
        int datalen = IMG_WIDTH*IMG_HEIGHT*3;
        BYTE *rgb = new BYTE[datalen];
       
        YUV422_C_RGB(pBuffer,rgb, IMG_HEIGHT, IMG_WIDTH);
        n1 = strlen((char *)pBuffer);
        n2 = strlen((char *)rgb);
//        ((CVideoNetDlg *)(m_dlgParent))->SendVideo((BYTE *)pBuffer, (int)cbBuffer);
        ///------------------------------------------------------------------
///////////////////////////////////////////////////////////////
        // Create a file to hold the bitmap
        HANDLE hf = CreateFile(inFileName, GENERIC_WRITE, FILE_SHARE_READ, 
            NULL, CREATE_ALWAYS, NULL, NULL );
       
        if( hf == INVALID_HANDLE_VALUE ){
            MessageBox(NULL, _T("Create bmp file failure!"), _T(""), MB_OK|MB_ICONINFORMATION);
            return 0;
        }
       
        // Write out the file header
        //
        // 信息头
        BITMAPFILEHEADER bfh;
        memset( &bfh, 0, sizeof( bfh ) );
        bfh.bfType = 'MB';
        bfh.bfSize = sizeof( bfh ) + cbBuffer + sizeof( BITMAPINFOHEADER );
        bfh.bfOffBits = sizeof( BITMAPINFOHEADER ) + sizeof( BITMAPFILEHEADER );
       
        DWORD Written = 0;
        WriteFile( hf, &bfh, sizeof( bfh ), &Written, NULL );
       
        // Write the bitmap format
        //文件头
        BITMAPINFOHEADER bih;
        memset( &bih, 0, sizeof( bih ) );
        bih.biSize = sizeof( bih );
        bih.biWidth = pVih->bmiHeader.biWidth;
        bih.biHeight = pVih->bmiHeader.biHeight;
        bih.biPlanes = 1;
        bih.biBitCount = 24;
       
        Written = 0;
        WriteFile( hf, &bih, sizeof( bih ), &Written, NULL );
       
        // Write the bitmap bits
        //
        Written = 0;
        WriteFile( hf, rgb, datalen, &Written, NULL );    
        CloseHandle( hf );
        delete pBuffer;
        MessageBox(NULL, _T("Save photo succeeded!"), _T("抓取图片提示"), MB_OK|MB_ICONINFORMATION);
    }
    m_pGrabber->SetOneShot(FALSE);
    m_pGrabber->SetBufferSamples(FALSE);
    FreeMediaType(mediaType);
    return 0;
}

bool CCapture::BindFilter( int iDeviceID, IBaseFilter **pOutFilter, DeviceType deviceType )
{
    if (iDeviceID < 0) return false;
    // 枚举所有的视频设备
    ICreateDevEnum *pCreateDevEnum;
    //生成设备枚举器pCreateDevEnum
    HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,
        NULL, CLSCTX_INPROC_SERVER, IID_ICreateDevEnum, (void **)&pCreateDevEnum);
    if (hr != NOERROR) return false;
    IEnumMoniker *pEM;
    // 创建视频输入设备类枚举器
    if (deviceType == DTypeVideo)
        hr = pCreateDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pEM, 0);
    // 音频设备枚举器
    else
        hr = pCreateDevEnum->CreateClassEnumerator(CLSID_AudioInputDeviceCategory, &pEM, 0);
    if (hr != NOERROR) return false;
    pEM->Reset();  // 复位该设备
    ULONG cFetched;
    IMoniker *pM;
    int indexDev = 0;
    // 获取设备
    while(hr = pEM->Next(1, &pM, &cFetched), hr == S_OK, indexDev <= iDeviceID)
    {
        IPropertyBag *pBag;
        // 获取该设备属性集
        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 (indexDev == iDeviceID) pM->BindToObject(0, 0, IID_IBaseFilter, (void **)pOutFilter);
                SysFreeString(var.bstrVal);
            }
            pBag->Release();
        }
        pM->Release();
        indexDev++;
    }
    return true;
}

void CCapture::SetCameraFormat( HWND hwndParent ) // 设置视频格式
{
    HRESULT hr;
    IAMStreamConfig *pSC; // 流配置接口
    ISpecifyPropertyPages *pSpec; //属性页接口
    m_pMC->Stop();  // 只有停止后才能进行引脚属性的设置
    m_bRecording = false;
    // 首先查询捕获CAPTURE、视频Video接口
    hr = m_pCapGB->FindInterface(&PIN_CATEGORY_CAPTURE, &MEDIATYPE_Video,
        m_pVideoCap, IID_IAMStreamConfig, (void **)&pSC);

    CAUUID cauuid; // 所有属性页结构体
    hr = pSC->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);
    if (hr == S_OK)
    {
        // 显示属性页窗口
        hr = pSpec->GetPages(&cauuid);  // 获取所有属性页
        hr = OleCreatePropertyFrame(hwndParent, 30, 30, NULL, 1,
            (IUnknown **)&pSC, cauuid.cElems, (GUID *)cauuid.pElems, 0, 0, NULL);
        // 释放内存资源
        CoTaskMemFree(cauuid.pElems);
        pSpec->Release();
        pSC->Release();
    }
    // 恢复运行
    m_pMC->Run();       
}

void CCapture::SetCameraFilter( HWND hwndParent ) // 设置图像各参数设置
{
    HRESULT hr = 0;
    ISpecifyPropertyPages *pSpec;
    hr = m_pVideoCap->QueryInterface(IID_ISpecifyPropertyPages, (void **)&pSpec);
    if (SUCCEEDED(hr))
    {
        // 获取滤波器名称和IUnknown 接口指针
        FILTER_INFO FilterInfo;
        hr = m_pVideoCap->QueryFilterInfo(&FilterInfo);
        IUnknown *pFilterUnk;
        m_pVideoCap->QueryInterface(IID_IUnknown, (void **)&pFilterUnk);
        // 显示该页
        CAUUID caGUID;
        pSpec->GetPages(&caGUID);
        OleCreatePropertyFrame(hwndParent,
            0, 0,
            FilterInfo.achName,
            1,
            &pFilterUnk,
            caGUID.cElems,
            caGUID.pElems,
            0,
            0, NULL);
        // 释放内存资源
        CoTaskMemFree(caGUID.pElems);
        pFilterUnk->Release();
        FilterInfo.pGraph->Release();
        pSpec->Release();
    }
}

void CCapture::StopCapture()
{
    m_pMC->Stop();
}

UINT CCapture::ThreadFunDrawText( LPVOID lParam )
{
    HWND hwnd = (HWND)lParam;
    if (hwnd == NULL) return -1;
    HDC hdc = GetDC(hwnd);
    CRect rcDraw, rcTime;
    CTime time, time0;
    CTimeSpan timespan;
    CString strTime;
    CBrush br;
    time0 = CTime::GetCurrentTime();
    br.CreateSolidBrush(RGB(255,0,0));
    GetClientRect(hwnd, &rcDraw);
    rcTime = rcDraw;
    rcTime.bottom = rcTime.top + 30;
    rcDraw.top = rcDraw.bottom - 30;
    SelectObject(hdc, &br);
    SetTextColor(hdc, 0x0000ff);
    SetBkMode(hdc, TRANSPARENT);
    while(m_bRecording)
    {
        time = CTime::GetCurrentTime();
        timespan = time - time0;
        strTime = time.Format(_T(" %Y-%m-%d 星期%w %H:%M:%S"));
        DrawText(hdc, strTime, strTime.GetLength(), &rcTime, DT_VCENTER|DT_LEFT|DT_SINGLELINE);
        strTime = timespan.Format(_T("%H:%M:%S "));
        strTime = _T("●录制 ") + strTime;
        DrawText(hdc, strTime, strTime.GetLength(), &rcDraw, DT_VCENTER|DT_RIGHT|DT_SINGLELINE);
    }
    return 0;
}

void CCapture::FreeMediaType(AM_MEDIA_TYPE &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;
    }
}

void CCapture::SetOnShot( BOOL bFlag )
{
    bOneShot = bFlag;
}

void CCapture::SetCallBKFun( capCallBackFunc f )
{
    this->calFunc = f;
    samCB.pCap = static_cast<CCapture *>(this);
}

void CCapture::SetParent( CDialog *pdlg )
{
    m_dlgParent = pdlg;
}

0

阅读 评论 收藏 转载 喜欢 打印举报/Report
  • 评论加载中,请稍候...
发评论

    发评论

    以上网友发言只代表其个人观点,不代表新浪网的观点或立场。

      

    新浪BLOG意见反馈留言板 电话:4000520066 提示音后按1键(按当地市话标准计费) 欢迎批评指正

    新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 会员注册 | 产品答疑

    新浪公司 版权所有