生活随笔
收集整理的這篇文章主要介紹了
DirectShow基础编程 最简单的源Filter的编写步骤 (转)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
轉自: http://blog.csdn.net/bwmwm/article/details/5463852
?
?
1.創建一個空的Dll工程,添加5個空文件分別名為:MyOutputPin.h、MySourceFilter.h、MyOutputPin.cpp、MySourceFilter.cpp和MySourceFilter.def。
?
2.聲明兩個類,一個是Filter的實現類,一個是輸出Pin的實現類,由于是最簡單的源Filter,因此Filter只有一個輸出Pin。實現的功能是從本地磁盤讀取三個圖片文件,輪流顯示這三張圖片,效果是模擬一個視頻流。這兩個類的聲明代碼:
?
[cpp]?view plaincopyprint?
class?CMySourceFilter???????????:???public?CSource????????????{??public:??????????static?CUnknown?*?WINAPI?CreateInstance(LPUNKNOWN?lpunk,?HRESULT?*phr);??private:??????????CMySourceFilter(LPUNKNOWN?lpunk,?HRESULT?*phr);???};?? ?
?
[cpp]?view plaincopyprint?
class?CMyOutputPin???????????:public?CSourceStream??{??public:??????CMyOutputPin(HRESULT?*phr,?CSource?*pFilter);??????~CMyOutputPin(void);????????????????????HRESULT?FillBuffer(IMediaSample?*pMediaSample);????????????HRESULT?DecideBufferSize(IMemAllocator?*pIMemAlloc,??????????ALLOCATOR_PROPERTIES?*pProperties);????????????????????HRESULT?GetMediaType(int?iPosition,?CMediaType?*pmt);????????????HRESULT?CheckMediaType(const?CMediaType?*pMediaType);????????????STDMETHODIMP?Notify(IBaseFilter?*pSelf,?Quality?q)??????{??????????return?E_FAIL;??????}????private:??????BYTE*?m_pData[3];????int?m_nWidth;????int?m_nHeight;????int?m_nImageSize;????int?m_nCount;};?? ?
?
3.實現CMySourceFilter類。這個類只有兩個函數需要編寫,很簡單。
?
[cpp]?view plaincopyprint?
CUnknown*?CMySourceFilter::CreateInstance(LPUNKNOWN?lpunk,?HRESULT?*phr)??{???????????CUnknown?*punk?=?new?CMySourceFilter(lpunk,phr);???????if?(punk?==?NULL)???????{???????????*phr?=?E_OUTOFMEMORY;???????}???????return?punk;??}????CMySourceFilter::CMySourceFilter(LPUNKNOWN?lpunk,?HRESULT?*phr)???:?CSource(L"MyFilter",lpunk,CLSID_MyFilter,phr)??{??????????????CMyOutputPin*?pOutPin?=?new?CMyOutputPin(phr,this);??????if?(FAILED(*phr))??????{??????????????????RemovePin(pOutPin);??????????pOutPin->Release();??????}??}?? ?
?
4.實現CMyOutputPin類,編寫Filter主要就是寫pin。
?
[cpp]?view plaincopyprint?
??CMyOutputPin::CMyOutputPin(HRESULT?*phr,?CSource?*pFilter)??:?CSourceStream(L"MyFilter",phr,pFilter,L"Out")??,?m_nWidth(0)??,?m_nHeight(0)??,?m_nImageSize(0)??,?m_nCount(0)??{??????????m_pData[0]?=?LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//1.bmp",??????????m_nWidth,m_nHeight,m_nImageSize);??????m_pData[1]?=?LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//2.bmp",??????????m_nWidth,m_nHeight,m_nImageSize);??????m_pData[2]?=?LoadBitmapFileToMemory(L"E://DirectShow//MySourceFilter//3.bmp",??????????m_nWidth,m_nHeight,m_nImageSize);??}????CMyOutputPin::~CMyOutputPin(void)??{??????????delete?[]m_pData[0];??????delete?[]m_pData[1];??????delete?[]m_pData[2];??}????HRESULT?CMyOutputPin::GetMediaType(int?iPosition,?CMediaType?*pmt)??{??????CheckPointer(pmt,E_POINTER);????????CAutoLock?cAutoLock(m_pFilter->pStateLock());??????if(iPosition?<?0)??????{??????????return?E_INVALIDARG;??????}??????????if(iPosition?>?0)??????{??????????return?VFW_S_NO_MORE_ITEMS;??????}????????????????VIDEOINFO?*pvi?=?(VIDEOINFO?*)?pmt->AllocFormatBuffer(sizeof(VIDEOINFO));??????if(NULL?==?pvi)??????????return(E_OUTOFMEMORY);????????ZeroMemory(pvi,?sizeof(VIDEOINFO));??????pvi->bmiHeader.biBitCount?=?24;??????pvi->bmiHeader.biHeight?=?m_nHeight;??????pvi->bmiHeader.biWidth?=?m_nWidth;??????pvi->bmiHeader.biSizeImage?=?m_nImageSize;??????pvi->bmiHeader.biPlanes?=?1;??????pvi->bmiHeader.biSize?=?sizeof(BITMAPINFOHEADER);??????pvi->bmiHeader.biCompression?=?BI_RGB;??????pvi->bmiHeader.biClrImportant?=?0;????????SetRectEmpty(&pvi->rcSource);??????SetRectEmpty(&pvi->rcTarget);????????pmt->SetType(&MEDIATYPE_Video);????pmt->SetSubtype(&MEDIASUBTYPE_RGB24);????pmt->SetFormatType(&FORMAT_VideoInfo);????pmt->SetSampleSize(m_nImageSize);????pmt->SetTemporalCompression(FALSE);????????return?NOERROR;??}????HRESULT?CMyOutputPin::CheckMediaType(const?CMediaType?*pMediaType)??{??????CheckPointer(pMediaType,E_POINTER);????????if?(*(pMediaType->Type())?!=?MEDIATYPE_Video??????????||?!(pMediaType->IsFixedSize()))??????{??????????return?E_INVALIDARG;??????}????????const?GUID?*SubType?=?pMediaType->Subtype();??????if?(SubType?==?NULL)??????{??????????return?E_INVALIDARG;??????}??????if?(*SubType?!=?MEDIASUBTYPE_RGB24)??????{??????????return?E_INVALIDARG;??????}??????const?GUID*?FormatType?=?pMediaType->FormatType();??????if?(FormatType?==?NULL)??????{??????????return?E_INVALIDARG;??????}??????if?(*FormatType?!=?FORMAT_VideoInfo)??????{??????????return?E_INVALIDARG;??????}????????VIDEOINFO*?pvi?=?(VIDEOINFO*)pMediaType->Format();??????if?(pvi?==?NULL)??????{??????????return?E_INVALIDARG;??????}??????if?(pvi->bmiHeader.biBitCount?!=?24?||???????????pvi->bmiHeader.biWidth?!=?m_nWidth?||??????????pvi->bmiHeader.biHeight?!=?m_nHeight)??????{??????????return?E_INVALIDARG;??????}????????return?S_OK;??}????HRESULT?CMyOutputPin::DecideBufferSize(IMemAllocator?*pIMemAlloc,?ALLOCATOR_PROPERTIES?*pProperties)??{??????CheckPointer(pIMemAlloc,E_POINTER);??????CheckPointer(pProperties,E_POINTER);????????CAutoLock?cAutoLock(m_pFilter->pStateLock());??????HRESULT?hr?=?NOERROR;????????VIDEOINFO?*pvi?=?(VIDEOINFO?*)?m_mt.Format();??????????pProperties->cBuffers?=?1;??????????pProperties->cbBuffer?=?m_nImageSize;????????ASSERT(pProperties->cbBuffer);????????????ALLOCATOR_PROPERTIES?Actual;??????hr?=?pIMemAlloc->SetProperties(pProperties,&Actual);??????if(FAILED(hr))??????{??????????return?hr;??????}????????if(Actual.cbBuffer?<?pProperties->cbBuffer)??????{??????????return?E_FAIL;??????}????????ASSERT(Actual.cBuffers?==?1);??????return?NOERROR;??}????HRESULT?CMyOutputPin::FillBuffer(IMediaSample?*pMediaSample)??{??????CheckPointer(pMediaSample,E_POINTER);??????BYTE*?pData?=?NULL;??????long?lDataSize?=?0;????????????pMediaSample->GetPointer(&pData);??????????lDataSize?=?pMediaSample->GetSize();????????ZeroMemory(pData,lDataSize);??????????CopyMemory(pData,m_pData[m_nCount%3],m_nImageSize);????????????REFERENCE_TIME?start?=?TS_ONE?*?m_nCount;??????REFERENCE_TIME?stop?=?TS_ONE?+?start;??????pMediaSample->SetTime(&start,&stop);????????????m_nCount++;????????pMediaSample->SetSyncPoint(TRUE);????????????return?NOERROR;??}?? ?
LoadBitmapFileToMemory函數的實現
?
[cpp]?view plaincopyprint?
BYTE*?LoadBitmapFileToMemory(TCHAR*?pFileName,?int&?nWidth,?int&?nHeight,?int&?nImageDataSize)??{??????HBITMAP?hBitmap?=?(HBITMAP)LoadImage(?NULL,?pFileName,?IMAGE_BITMAP,?0,?0,??????????LR_CREATEDIBSECTION?|?LR_DEFAULTSIZE?|?LR_LOADFROMFILE?);????????if(hBitmap?==?NULL)??????????return?NULL;????????HDC?hDC?=?CreateCompatibleDC(NULL);??????HBITMAP?hOldBitmap?=?(HBITMAP)SelectObject(hDC,?hBitmap);????????BITMAP?bmp;??????GetObject(hBitmap,?sizeof(bmp),?&bmp);????????BITMAPINFOHEADER?bih?=?{0};????bih.biBitCount?=?bmp.bmBitsPixel;????bih.biCompression?=?BI_RGB;??????bih.biHeight?=?bmp.bmHeight;????bih.biPlanes?=?1;??????bih.biSize?=?sizeof(BITMAPINFOHEADER);??????bih.biSizeImage?=?bmp.bmWidthBytes?*?bmp.bmHeight;????bih.biWidth?=?bmp.bmWidth;??????nImageDataSize?=?bmp.bmWidthBytes?*?bmp.bmHeight;??????byte?*?p?=?new?byte[nImageDataSize];????GetDIBits(hDC,?hBitmap,?0,?bmp.bmHeight,?p,??????????(LPBITMAPINFO)?&bih,?DIB_RGB_COLORS);??????SelectObject(hDC,?hOldBitmap);??????DeleteObject(hBitmap);??????DeleteDC(hDC);????????nWidth?=?bmp.bmWidth;??????nHeight?=?bmp.bmHeight;????????return?p;??}?? ?
?
5.主要的工作已經做完了,功能已經實現,接下來就是生成Filter。
?
[cpp]?view plaincopyprint?
????extern?"C"?BOOL?WINAPI?DllEntryPoint(HINSTANCE,?ULONG,?LPVOID);????????BOOL?APIENTRY?DllMain(HANDLE?hModule,???????????DWORD??dwReason,???????????LPVOID?lpReserved)??????{??????????return?DllEntryPoint((HINSTANCE)(hModule),?dwReason,?lpReserved);??????}??STDAPI?DllRegisterServer()??????{??????????return?AMovieDllRegisterServer2(TRUE);????????}??STDAPI?DllUnregisterServer()??????{??????????return?AMovieDllRegisterServer2(FALSE);????????}????DEFINE_GUID(CLSID_MyFilter,???????????????0x159386e0,?0x5193,?0x48ac,?0x8a,?0x57,?0x17,?0x88,?0xc7,?0x33,?0x40,?0xc1);????const?AMOVIESETUP_MEDIATYPE?sudOpPinTypes?=??{??????&MEDIATYPE_Video,???????????&MEDIASUBTYPE_NULL??????};????const?AMOVIESETUP_PIN?sudOpPin?=??{??????L"Output",???????????????????FALSE,???????????????????????TRUE,?????????????????????????FALSE,????????????????????????FALSE,????????????????????????&CLSID_NULL,?????????????????NULL,????????????????????????1,????????????????????????????&sudOpPinTypes?};?????????????const?AMOVIESETUP_FILTER?sudBallax?=??????{??????????&CLSID_MyFilter,????????????L"MyFilter",???????????????MERIT_DO_NOT_USE,?????????????????1,????????????????????????????????&sudOpPin???????????????};????????????????CFactoryTemplate?g_Templates[]?=?{??????????{?L"MyFilter"????????,?&CLSID_MyFilter????????,?CMySourceFilter::CreateInstance????????,?NULL??????????,?&sudBallax?}??????};??????int?g_cTemplates?=?sizeof(g_Templates)?/?sizeof(g_Templates[0]);?? ?
?
6.MySourceFilter.def文件的內容
?
[cpp]?view plaincopyprint?
LIBRARY?"MySourceFilter.ax"????EXPORTS??????????????DllMain?????????????????PRIVATE??????????????DllGetClassObject???????PRIVATE??????????????DllCanUnloadNow?????????PRIVATE??????????????DllRegisterServer???????PRIVATE??????????????DllUnregisterServer?????PRIVATE?? ?
?
7.注意
1)包含頭文件?#include <initguid.h>,否則有可能提示 error LNK2001: 無法解析的外部符號 _CLSID_MyFilter
2)包含導出庫#pragma comment(lib, "winmm")
3)包含導入庫#pragma comment(lib, "strmbase.lib"),Debug下包含#pragma comment(lib, "strmbasd.lib")
?
8.大功告成。調用regsvr32注冊Filter。使用GraphEdit調試Filter。(VS2005)
在工程的屬性中選擇調試,在命令中填入GraphEdit的完整路徑,把Filter的工程作為啟動項。按下F5,在運行的GraphEdit中選擇我們的Filter,Render pin,就可以看到一條完整的鏈路,然后run,效果出來了,三幅圖片輪流顯示在窗口中。
轉載于:https://www.cnblogs.com/signal/p/4094102.html
總結
以上是生活随笔為你收集整理的DirectShow基础编程 最简单的源Filter的编写步骤 (转)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。