directshow捕获摄像头数据 您所在的位置:网站首页 英国签证被取消过再办签证有影响吗 directshow捕获摄像头数据

directshow捕获摄像头数据

2024-07-10 17:33| 来源: 网络整理| 查看: 265

directshow捕获摄像头的数据并显示

#include "stdafx.h" #include #include #include #define CHECK_HR(s) if (FAILED(s)) {return 1;} #define SAFE_RELEASE(p) do { if ((p)) { (p)->Release(); (p) = NULL; } } while(0) LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam); #pragma comment(lib, "Dxguid.lib") #pragma comment(lib, "Strmiids.lib") int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nCmdShow) { CoInitialize(NULL); int nRes = 0; WNDCLASSEX wcex; wcex.cbSize = sizeof(WNDCLASSEX); wcex.style = CS_HREDRAW | CS_VREDRAW; wcex.lpfnWndProc = WndProc; wcex.cbClsExtra = 0; wcex.cbWndExtra = 0; wcex.hInstance = hInstance; wcex.hIcon = LoadIcon(hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); wcex.hCursor = LoadCursor(NULL, IDC_ARROW); wcex.hbrBackground = (HBRUSH)(COLOR_WINDOW + 1); wcex.lpszMenuName = NULL; wcex.lpszClassName = _T("dshow capture"); wcex.hIconSm = LoadIcon(wcex.hInstance, MAKEINTRESOURCE(IDI_APPLICATION)); if (!RegisterClassEx(&wcex)) { MessageBox(NULL, _T("Call to RegisterClassEx failed!"), _T("Win32 Guided Tour"), NULL); return 1; } HWND m_hWnd = ::CreateWindowA("STATIC", "ds_video_preview", WS_POPUP, 100, 100, 500, 500, NULL, NULL, NULL, NULL); ShowWindow(m_hWnd, nCmdShow); UpdateWindow(m_hWnd); if (m_hWnd == NULL) { nRes = 11; } //----------------------用dshow获取摄像头---start-------------------------- IGraphBuilder *m_pGraph;//filter总图表管理器 ICaptureGraphBuilder2 *m_pBuild;//捕获图表管理器 IVideoWindow *m_pVidWin;//窗口接口 HRESULT hr = CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, IID_IGraphBuilder, (void**)&m_pGraph); CHECK_HR(1); hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL, CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&m_pBuild); CHECK_HR(2); hr = m_pBuild->SetFiltergraph(m_pGraph);//给捕获图表管理器指定一个可用的图表管理器来进行使用 CHECK_HR(3); hr = m_pGraph->QueryInterface(IID_IVideoWindow, (void **)&m_pVidWin);//通过此函数来查询某个组件是否支持某个特定的接口,如果支持就返回这些接口的指针 CHECK_HR(4); ICreateDevEnum *pDevEnum = NULL; IEnumMoniker *pClsEnum = NULL; IMoniker *pMoniker = NULL; //创建设备枚举COM对象 hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL, CLSCTX_INPROC, IID_ICreateDevEnum, (void **)&pDevEnum); CHECK_HR(5); //创建视频采集设备枚举COM对象 hr = pDevEnum->CreateClassEnumerator(CLSID_VideoInputDeviceCategory, &pClsEnum, 0); CHECK_HR(6); int i = 0; while (i Next(1, &pMoniker, NULL); ++i; } CHECK_HR(7); IBaseFilter *m_pSrc; hr = pMoniker->BindToObject(0, 0, IID_IBaseFilter, (void **)&m_pSrc);//就是这句获得Filter CHECK_HR(8); SAFE_RELEASE(pMoniker); SAFE_RELEASE(pClsEnum); SAFE_RELEASE(pDevEnum); //将设备添加到filter管理器graph hr = m_pGraph->AddFilter(m_pSrc, L"Video Capture"); CHECK_HR(9); hr = m_pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pSrc, NULL, NULL); CHECK_HR(10); m_pVidWin->put_Owner((OAHWND)m_hWnd); m_pVidWin->SetWindowPosition(100, 100, 400, 300); m_pVidWin->put_WindowStyle(WS_CHILD | WS_CLIPSIBLINGS); //IMediaControl接口,用来控制流媒体在Filter Graph中的流动,例如流媒体的启动和停止 IMediaControl *m_pMediaControl; hr = m_pGraph->QueryInterface(IID_IMediaControl, (void **)&m_pMediaControl); CHECK_HR(12); hr = m_pMediaControl->Run(); //----------------------用dshow获取摄像头---end-------------------------- MSG msg; while (GetMessage(&msg, NULL, 0, 0)) { TranslateMessage(&msg); DispatchMessage(&msg); } return (int)msg.wParam; } LRESULT CALLBACK WndProc(HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam) { PAINTSTRUCT ps; HDC hdc; TCHAR greeting[] = _T("Hello, World!"); switch (message) { case WM_PAINT: hdc = BeginPaint(hWnd, &ps); TextOut(hdc, 5, 5, greeting, _tcslen(greeting)); EndPaint(hWnd, &ps); break; case WM_DESTROY: PostQuitMessage(0); break; default: return DefWindowProc(hWnd, message, wParam, lParam); break; } return 0; }

这是直接捕获并绘制到窗口上,一般的应用是获取流然后和音频一起编码,做直播和网络传输。那么有没有这种方式,进行传输呢,其实directshow 提供了ISampleGrabber,可以实现直接得到缓冲,或者异步回调数据。

1  从ISampleGrabber实例化一个sample grabber,充当一个transform filter

CComPtr m_pSampleGrabber;

2 设置相关参数,将Grabber注册并加入到filter graph中

//Add SampleGrabber // create a sample grabber // hr = m_pSampleGrabber.CoCreateInstance( CLSID_SampleGrabber ); if( !m_pSampleGrabber ) { MessageBox(NULL, L"Could not create SampleGrabber (is qedit.dll registered?)", L"", MB_OK); return hr; } CComQIPtr< IBaseFilter, &IID_IBaseFilter > pGrabBase( m_pSampleGrabber ); // force it to connect to video, 24 bit // CMediaType VideoType; VideoType.SetType( &MEDIATYPE_Video ); VideoType.SetSubtype( &MEDIASUBTYPE_RGB24 ); VideoType.SetFormatType(&FORMAT_VideoInfo); hr = m_pSampleGrabber->SetMediaType( &VideoType ); // shouldn't fail if (FAILED(hr)) { MessageBox(NULL, L"不能初始化SampleGrabber媒体类型。", L"", MB_OK); return hr; } hr = m_pGB->AddFilter( pGrabBase, L"Grabber" ); if( FAILED( hr ) ) { MessageBox(NULL, L"Could not put sample grabber in graph", L"", MB_OK); return hr; }

3 连接成功以后,将Sample Grabber作为一个中间filter,利用CSampleGrabber的实例调用回调函数BufferCB,从源filter中得到

摄像头设备捕获的每一帧数据,作为视频预览

hr = m_pCapture->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video, m_pBF, pGrabBase, m_pVMR); if (FAILED(hr)) { MessageBox(NULL, L"Could not put sample into sample grabber", L"", MB_OK); return hr; } //Set mCB AM_MEDIA_TYPE mt; hr = m_pSampleGrabber->GetConnectedMediaType( &mt ); if ( FAILED( hr) ) { MessageBox( NULL, TEXT("Could not read the connected media type"),L"", MB_OK); return hr; } VIDEOINFOHEADER * vih = (VIDEOINFOHEADER*) mt.pbFormat; mCB.IWidth = vih->bmiHeader.biWidth; mCB.IHeight = vih->bmiHeader.biHeight; FreeMediaType( mt ); hr = RenderFileList(m_pGB,m_pVMR ); // don't buffer the samples as they pass through // hr = m_pSampleGrabber->SetBufferSamples( TRUE); // only grab one at a time, stop stream after // grabbing one sample // hr = m_pSampleGrabber->SetOneShot( FALSE ); // set the callback, so we can grab the one sample // hr = m_pSampleGrabber->SetCallback( &mCB, 1 ); if (FAILED(hr)) { MessageBox(NULL, L"Could not call callback method BufferCB().", L"", MB_OK); return hr; } pGrabBase.Release();

4 实现接口类ISampleGrabber,用于捕获视频帧的sample,从BufferCB中返回图像数据,用户传输,之前已设定了

图像的采样格式,这里不再赘述。

//SampleGrabber // Global data #define WM_CAPTURE_BITMAP WM_APP + 1 BOOL g_bOneShot=TRUE; // Structures typedef struct _callbackinfo { double dblSampleTime; long lBufferSize; BYTE *pBuffer; BITMAPINFOHEADER bih; } CALLBACKINFO; CALLBACKINFO cb={0}; class CSampleGrabberCB : public ISampleGrabberCB { private: LPBITMAPFILEHEADER m_pFileHeader ; // Bmp文件头 LPBITMAPINFOHEADER m_pBmpInfo ; // Bmp信息头指针 BYTE* m_pImgFileData; //Bmp文件数据 BOOL m_bViladImage ; LPBYTE m_pBitmapHeader ; LPVOID m_pvColorTable ; //调色板指针 public: // these will get set by the main thread below. We need to // know this in order to write out the bmp long IWidth; long IHeight; CSampleGrabberCB( ) { m_pFileHeader = new BITMAPFILEHEADER ; m_pBitmapHeader = new BYTE[sizeof(BITMAPINFOHEADER)] ; } // fake out any COM ref counting // STDMETHODIMP_(ULONG) AddRef() { return 2; } STDMETHODIMP_(ULONG) Release() { return 1; } // fake out any COM QI'ing // STDMETHODIMP QueryInterface(REFIID riid, void ** ppv) { if( riid == IID_ISampleGrabberCB || riid == IID_IUnknown ) { *ppv = (void *) static_cast ( this ); return NOERROR; } return E_NOINTERFACE; } // we don't implement this interface for this example // STDMETHODIMP SampleCB( double SampleTime, IMediaSample * pSample ) { return 0; } // As a workaround, copy the bitmap data during the callback, // post a message to our app, and write the data later. // STDMETHODIMP BufferCB( double dblSampleTime, BYTE * pBuffer, long lBufferSize ) { // this flag will get set to true in order to take a picture // if( !g_bOneShot ) return 0; if (!pBuffer) { return E_POINTER; } if( cb.lBufferSize < lBufferSize ) { delete [] cb.pBuffer; cb.pBuffer = NULL; cb.lBufferSize = 0; } // Since we can't access Windows API functions in this callback, just // copy the bitmap data to a global structure for later reference. cb.dblSampleTime = dblSampleTime; // If we haven't yet allocated the data buffer, do it now. // Just allocate what we need to store the new bitmap. if (!cb.pBuffer) { cb.pBuffer = new BYTE[lBufferSize]; cb.lBufferSize = lBufferSize; } if( !cb.pBuffer ) { cb.lBufferSize = 0; return E_OUTOFMEMORY; } //Get bmp information BITMAPINFOHEADER bih; memset( &bih, 0, sizeof( bih ) ); bih.biSize = sizeof( bih ); bih.biWidth = IWidth; bih.biHeight = IHeight; bih.biPlanes = 1; bih.biBitCount = 24; memcpy(&(cb.bih), &bih, sizeof(bih)); // Copy the bitmap data into our global buffer memcpy(cb.pBuffer, pBuffer, lBufferSize); // Post a message to our application, telling it to come back // and write the saved data to a bitmap file on the user's disk. SendMessage(m_hWnd, WM_CAPTURE_BITMAP, 0, 0L); return 0; } BOOL FormatImage( BYTE *lpImageData, int nBitCount, int nWidth, int nHeight ) { m_bViladImage = FALSE ; int nKlsBmpBitCount ; int nImgWidth = nWidth ; int nImgHeight = nHeight ; if (nBitCount == 8 || nBitCount == 24 || nBitCount == 32) { nKlsBmpBitCount = nBitCount; } else { return m_bViladImage ; } int nDataWidth = nKlsBmpBitCount / 8 * nWidth ; nDataWidth = ( nDataWidth % 4 == 0 ) ? nDataWidth : ( ( nDataWidth / 4 + 1 ) * 4 ) ; //m_pFileHeader = new BITMAPFILEHEADER ; m_pFileHeader->bfType = 0x4d42 ; m_pFileHeader->bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + nDataWidth*nImgHeight ; m_pFileHeader->bfReserved1 = 0 ; m_pFileHeader->bfReserved2 = 0 ; if ( nBitCount == 8 ) { int nBmpInfoSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 256 * 4 ; m_pFileHeader->bfOffBits = nBmpInfoSize ; m_pBitmapHeader = new BYTE[nBmpInfoSize] ; m_pBmpInfo = (LPBITMAPINFOHEADER)m_pBitmapHeader ; m_pvColorTable = m_pBitmapHeader + sizeof(BITMAPINFOHEADER) ; LPRGBQUAD pDibQuad = (LPRGBQUAD)(m_pvColorTable) ; for ( int c=0; cbfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) ; //m_pBitmapHeader = new BYTE[sizeof(BITMAPINFOHEADER)] ; m_pBmpInfo = (LPBITMAPINFOHEADER)m_pBitmapHeader ; m_pvColorTable = NULL ; } m_pBmpInfo->biBitCount = nKlsBmpBitCount ; m_pBmpInfo->biWidth = nImgWidth ; m_pBmpInfo->biHeight = nImgHeight ; m_pBmpInfo->biPlanes = 1 ; m_pBmpInfo->biSize = sizeof(BITMAPINFOHEADER) ; m_pBmpInfo->biSizeImage = nImgWidth * nImgHeight * nKlsBmpBitCount / 8 ; m_pBmpInfo->biClrImportant = 0 ; m_pBmpInfo->biClrUsed = 0 ; m_pBmpInfo->biCompression = 0 ; m_pBmpInfo->biXPelsPerMeter = 0 ; m_pBmpInfo->biYPelsPerMeter = 0 ; //m_pImgFileData = new BYTE[nDataWidth*nImgHeight] ; SetImgFileData(nDataWidth, nImgHeight); if ( nBitCount == 8 ) { if ( nImgWidth % 4 == 0 ) { memset( m_pImgFileData, 0, nDataWidth*nImgHeight ) ; memcpy( m_pImgFileData, lpImageData, cb.lBufferSize) ; } else { memset( m_pImgFileData, 0, nDataWidth*nImgHeight ) ; for ( int i=0; i


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有