日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

使用SampleGrabber过滤器扑获图像

發布時間:2024/1/17 编程问答 35 豆豆
生活随笔 收集整理的這篇文章主要介紹了 使用SampleGrabber过滤器扑获图像 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Sample Grabber過濾器是一個可以被插入流的過濾器,它有自己的緩沖,存放采樣。

如果你想從一個視頻文件中簡單的撲獲一楨,那么我建議你使用Media Detector對象。Sample Grabber提供了更復雜的更靈活的控制。我們通過下面的步驟使用Sample Grabber過濾器:

1、 指定你想要撲獲的媒體類型

在Sample Grabber 過濾器連接到別的過濾器之前你必須配置它。首先你要調用CoCreateInstance來創建Sample Grabber ,然后調用IfilterGraph::AddFilter來加載它到過濾圖形中。然后查詢IsampleGrabber接口。我們使用 IsampleGrabber::SetMediaType方法來設置媒體類型。這個方法指定了Sample Grabber過濾器將要連接的媒體類型。你可以僅僅指定主媒體類型;或者主類型加子類型;或者主類型,子類型和類型格式。

例如,如果你想撲獲一個未壓縮的視頻楨,這個視頻楨要求是兼容當前顯示模式的,你可以設置主類型為MEDIATYPE_Video然后設置基于當前顯示位深的子類型。下面的例子也許能說明問題:

// 創建 Sample Grabber.IBaseFilter *pF = NULL;ISampleGrabber *pGrabber = NULL;hr = CoCreateInstance(CLSID_SampleGrabber, NULL, CLSCTX_INPROC_SERVER,??? IID_IBaseFilter, reinterpret_cast<void**>(&pF));hr = pF->QueryInterface(IID_ISampleGrabber,??? reinterpret_cast<void**>(&pGrabber));hr = pGraph->AddFilter(pF, LSampleGrabber);// 找到當前的色深HDC hdc = GetDC(NULL);int iBitDepth = GetDeviceCaps(hdc, BITSPIXEL);ReleaseDC(NULL, hdc);// 設置媒體類型AM_MEDIA_TYPE mt;ZeroMemory(&mt, sizeof(AM_MEDIA_TYPE));mt.majortype = MEDIATYPE_Video;switch (iBitDepth){case 8:??? mt.subtype = MEDIASUBTYPE_RGB8;??? break;case 16:??? mt.subtype = MEDIASUBTYPE_RGB555;??? break;case 24:??? mt.subtype = MEDIASUBTYPE_RGB24;??? break;case 32:??? mt.subtype = MEDIASUBTYPE_RGB32;??? break;default:??? return E_FAIL;}hr = pGrabber->SetMediaType(&mt);

?

?

2、 建立包含Sample Grabber過濾圖形

在你指定媒體類型之后,你就可以建立一個包含Sample Grabber的過濾圖形了。Sample Grabber將僅連接到指定的類型,而且允許你在建立過濾圖形時使用智能連接機制。

例 如前面的代碼就指定了未壓縮的視頻楨。準備好了以后,你就可以調用IgraphBuilder::AddSourceFilter方法從視頻文件源流中加 入捕獲過濾器。為了將這個過濾器插入過濾圖形,我們還需要調用IgraphBuilder::Connect方法來連接源過濾器和Sample Grabber。過濾圖形管理器會自動的添加需要的解碼過濾器。

下面的代碼就是這樣做的。它使用了兩個幫助函數來枚舉引腳。GetPin函數在過濾器中找到第一個引腳,輸入或者輸出引腳。ConnectFilters函數找到過濾器中的第一個輸出引腳,然后連接這個引腳到另外一個過濾器的第一個輸入引腳。

HRESULT GetPin(IBaseFilter *, PIN_DIRECTION, IPin **);HRESULT ConnectFilters(IGraphBuilder *, IBaseFilter *, IBaseFilter *); IBaseFilter *pSrc;hr = pGraph->AddSourceFilter(wszFileName, LSource, &pSrc);hr = ConnectTwoFilters(pGraph, pSrc, pF); // Helper functions:HRESULT GetPin(IBaseFilter *pFilter, PIN_DIRECTION PinDir, IPin **ppPin){??? IEnumPins *pEnum;??? IPin?????? *pPin;??? pFilter->EnumPins(&pEnum);??? while(pEnum->Next(1, &pPin, 0) == S_OK)??? {??????? PIN_DIRECTION PinDirThis;??????? pPin->QueryDirection(&PinDirThis);??????? if (PinDir == PinDirThis)??????? {??????????? pEnum->Release();??????????? *ppPin = pPin;??????????? return S_OK;??????? }??????? pPin->Release();??? }??? pEnum->Release();??? return E_FAIL; } HRESULT ConnectFilters(IGraphBuilder *pGraph, IBaseFilter *pFirst, IBaseFilter *pSecond){??? IPin *pOut = NULL, *pIn = NULL;??? HRESULT hr = GetPin(pFirst, PINDIR_OUTPUT, &pOut);??? if (FAILED(hr)) return hr;??? hr = GetPin(pSecond, PINDIR_INPUT, &pIn);??? if (FAILED(hr)) ???? {??????? pOut->Release();??????? return E_FAIL;???? }??? hr = pGraph->Connect(pOut, pIn);??? pIn->Release();??? pOut->Release();??? return hr;}

應用程序必須連接了Sample Grabber的輸出引腳。如果你想丟棄采樣,那么你可以連接Null Renderer過濾器。這個過濾器將會丟棄它所收到的每一楨。

???????? IBaseFilter *pNull = NULL;???????? hr = CoCreateInstance(CLSID_NullRenderer, NULL, CLSCTX_INPROC_SERVER,???????? ??? IID_IBaseFilter, reinterpret_cast<void**>(&pNull));???????? hr = pGraph->AddFilter(pNull, LNullRenderer);???????? hr = ConnectTwoFilters(pGraph, pF, pNull);

?

3、 運行過濾圖形

Sample Grabber工作包含兩種模式:

A、 在將采樣向下傳送之前產生每個采樣的拷貝,然后放到其緩沖。

B、 以回調方式進行處理數據,回調由應用程序定義。

這里我們僅討論一下緩沖模式。但是大家要注意的是回調方式會影響我們的工作效率,甚至死鎖?;卣{函數設置我們用IsampleGrabber::SetCallback方法。

為 了激活緩沖模式,我們調用IsampleGrabberr::SetBufferSample方法,參數填充TRUE。你也可以使用 IsampleGrabber::SetOneShot方法,這樣會導致每捕獲一楨后過濾圖形停止。這個特性對我們如果僅想在流里面捕獲一楨的需求十分有 益。我們可以搜索到想要捕獲的地方運行過濾圖形,進行截獲。但是楨的精確度還是要靠數據源的性質決定。

下面的例子實現的就是這些:

???????? // 設置快照和緩沖模式.???????? hr = pGrabber->SetOneShot(TRUE);???????? hr = pGrabber->SetBufferSamples(TRUE); ???????? IMediaFilter *pMediaFilter = NULL;???????? IMediaControl *pControl = NULL;???????? IMediaEventEx *pEvent = NULL;????????????? ???????? pMediaFilter->SetSyncSource(NULL); // 關掉參考時鐘???????? pControl->Run(); // 運行過濾圖形.???????? pEvent->WaitForCompletion(INFINITE, &evCode); // 等待直到結束

??????

?

4、 從Sample Grabber中得到緩沖采樣,或者實現回調函數來獲得數據。

在 緩沖模式,Sample Grabber過濾器存儲了它收到的每個采樣的拷貝。我們要獲得緩沖數據就要調用IsampleGrabber::GetCurrentBuffer方 法。這個方法填充一個調用者分配好的矩陣。為了能獲得緩沖區大小,調用方法的時候必須將緩沖的指針填NULL。

???????? long cbBuffer = 0;???????? hr = pGrabber->GetCurrentBuffer(&cbBuffer, NULL);???????? char *pBuffer = new char[cbBuffer];???????? if (!pBuffer) ???????? {???????? ??? return E_OUTOFMEMORY;???????? }???????? hr = pGrabber->GetCurrentBuffer(&cbBuffer, ???????? ???? reinterpret_cast<long*>(pBuffer));

使 用IsampleGrabber::GetConnectedMediaType方法來獲得緩沖格式。例如,如果緩沖是一個未壓縮的視頻楨,它的格式就是 VIDEOINFOHEADER結構格式。注意,Sample Grabber不支持VIDEOINFOHEADER2結構。

???????? AM_MEDIA_TYPE mt;???????? hr = pGrabber->GetConnectedMediaType(mt);???????? VIDEOINFOHEADER *pVih;???????? if (mt.formattype == FORMAT_VideoInfo) ???????? ???? pVih = reinterpret_cast<VIDEOINFOHEADER*>(mt.pbFormat);???????? else ???????? ???? return VFW_E_INVALIDMEDIATYPE; // Something went wrong???????? // pVih->bmiHeader 這個參數是BITMAPINFOHEADER 結構,是每一楨的圖形信息.???????? ???????? // 釋放格式塊 ? ??

轉載于:https://www.cnblogs.com/mfryf/archive/2012/02/15/2352651.html

總結

以上是生活随笔為你收集整理的使用SampleGrabber过滤器扑获图像的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。