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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

DirectShow基础编程 最简单的源Filter的编写步骤 (转)

發布時間:2025/5/22 编程问答 78 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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?
  • //MySourceFilter.h??
  • class?CMySourceFilter???
  • ????//從SDK庫中的CSource類派生??
  • ????:???public?CSource????????????
  • {??
  • public:??
  • ????//實例化接口??
  • ????static?CUnknown?*?WINAPI?CreateInstance(LPUNKNOWN?lpunk,?HRESULT?*phr);??
  • private:??
  • ????//構造函數??
  • ????CMySourceFilter(LPUNKNOWN?lpunk,?HRESULT?*phr);???
  • };??
  • ?

    ?

    [cpp]?view plaincopyprint?
  • //MyOutputPin.h??
  • class?CMyOutputPin???
  • ????//CSource的派生類都使用CSourceStream的派生類做為pin??
  • ????:public?CSourceStream??
  • {??
  • public:??
  • ????CMyOutputPin(HRESULT?*phr,?CSource?*pFilter);??
  • ????~CMyOutputPin(void);??
  • ??
  • ????//填充樣本函數??
  • ????//參數pMediaSample就是要傳遞到下一個Filter輸入pin的樣本??
  • ????//把數據填充到pMediaSample中就是這個函數的功能??
  • ????HRESULT?FillBuffer(IMediaSample?*pMediaSample);??
  • ??
  • ????//協商每個CMediaSample數據塊的大小??
  • ????HRESULT?DecideBufferSize(IMemAllocator?*pIMemAlloc,??
  • ????????ALLOCATOR_PROPERTIES?*pProperties);??
  • ??
  • ????//獲得媒體類型??
  • ????//在枚舉器中枚舉支持的媒體類型時調用此函數得到PIN支持的媒體類型??
  • ????//此函數設置pmt的各個成員,因此,由此函數的內容覺得PIN支持什么媒體類型??
  • ????HRESULT?GetMediaType(int?iPosition,?CMediaType?*pmt);??
  • ??
  • ????//檢測是否支持參數傳入的媒體類型??
  • ????HRESULT?CheckMediaType(const?CMediaType?*pMediaType);??
  • ??
  • ????//這是質量控制接口,最簡單的源Filter不需要質量控制??
  • ????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?
  • //CMySourceFilter.cpp??
  • CUnknown*?CMySourceFilter::CreateInstance(LPUNKNOWN?lpunk,?HRESULT?*phr)??
  • {??
  • ????//實例化函數的工作就是實例化一個源Filter的對象??
  • ?????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)??
  • {??
  • ????//創建一個pin的對象實例??
  • ????//在CSourceStream的構造函數中,會把pin添加到Filter中??
  • ????CMyOutputPin*?pOutPin?=?new?CMyOutputPin(phr,this);??
  • ????if?(FAILED(*phr))??
  • ????{??
  • ????????//因此,在創建失敗的時候,要將這個pin從Filter中移除??
  • ????????RemovePin(pOutPin);??
  • ????????pOutPin->Release();??
  • ????}??
  • }??
  • ?

    ?

    4.實現CMyOutputPin類,編寫Filter主要就是寫pin。

    ?

    [cpp]?view plaincopyprint?
  • //MyOutputPin.cpp??
  • ??
  • //構造函數??
  • 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];??
  • }??
  • ??
  • //獲取媒體類型??
  • //填充pmt??
  • //最簡單的源Filter,因此只支持一種類型,所以iPosition為0??
  • HRESULT?CMyOutputPin::GetMediaType(int?iPosition,?CMediaType?*pmt)??
  • {??
  • ????CheckPointer(pmt,E_POINTER);??
  • ??
  • ????CAutoLock?cAutoLock(m_pFilter->pStateLock());??
  • ????if(iPosition?<?0)??
  • ????{??
  • ????????return?E_INVALIDARG;??
  • ????}??
  • ????//?Have?we?run?off?the?end?of?types???
  • ????if(iPosition?>?0)??
  • ????{??
  • ????????return?VFW_S_NO_MORE_ITEMS;??
  • ????}??
  • ??
  • ????//給媒體類型申請Format的空間??
  • ????//填充每一個對象,主要是BITMAPINFOHEADER結構??
  • ????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);//設置Sample的大小??
  • ????pmt->SetTemporalCompression(FALSE);??
  • ??
  • ????return?NOERROR;??
  • }??
  • ??
  • //檢查媒體類型??
  • //主要是對GetMediaType中設置的各個參數進行比較??
  • 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;??
  • }??
  • ??
  • //協商Sample的大小??
  • 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();??
  • ????//確定只有一個buffer??
  • ????pProperties->cBuffers?=?1;??
  • ????//設置buffer的大小??
  • ????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;??
  • }??
  • ??
  • //填充Sample??
  • HRESULT?CMyOutputPin::FillBuffer(IMediaSample?*pMediaSample)??
  • {??
  • ????CheckPointer(pMediaSample,E_POINTER);??
  • ????BYTE*?pData?=?NULL;??
  • ????long?lDataSize?=?0;??
  • ??
  • ????//獲得Sample中存放數據的地址??
  • ????pMediaSample->GetPointer(&pData);??
  • ????//取得Sample分配的內存大小??
  • ????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?
  • //MySourceFilter.h??
  • //動態庫工程自然也要有入口函數(固定格式)??
  • ????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);??
  • ??
  • ????}??
  • ??
  • //組件,就要有GUID(通過工具創建)??
  • DEFINE_GUID(CLSID_MyFilter,???
  • ????????????0x159386e0,?0x5193,?0x48ac,?0x8a,?0x57,?0x17,?0x88,?0xc7,?0x33,?0x40,?0xc1);??
  • ??
  • //以下是注冊信息的模版,寫了注釋的地方是我們需要填寫的,其他的采用默認??
  • const?AMOVIESETUP_MEDIATYPE?sudOpPinTypes?=??
  • {??
  • ????&MEDIATYPE_Video,???????//?Major?type??
  • ????&MEDIASUBTYPE_NULL??????//?Minor?type??
  • };??
  • ??
  • const?AMOVIESETUP_PIN?sudOpPin?=??
  • {??
  • ????L"Output",???????????????
  • ????FALSE,???????????????????
  • ????TRUE,?????????????????????
  • ????FALSE,????????????????????
  • ????FALSE,????????????????????
  • ????&CLSID_NULL,?????????????
  • ????NULL,????????????????????
  • ????1,????????????????????????
  • ????&sudOpPinTypes?};???????
  • ??
  • ????const?AMOVIESETUP_FILTER?sudBallax?=??
  • ????{??
  • ????????&CLSID_MyFilter,????//?自定義的GUID??
  • ????????L"MyFilter",???????//?Filter的名字??
  • ????????MERIT_DO_NOT_USE,?????????
  • ????????1,????????????????????????
  • ????????&sudOpPin???????????
  • ????};??
  • ??
  • ??
  • ????//?COM?global?table?of?objects?in?this?dll??
  • ??
  • ????CFactoryTemplate?g_Templates[]?=?{??
  • ????????{?L"MyFilter"//Filter的名字??
  • ????????,?&CLSID_MyFilter//自定義的GUID??
  • ????????,?CMySourceFilter::CreateInstance//Filter的實例化接口??
  • ????????,?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的编写步骤 (转)的全部內容,希望文章能夠幫你解決所遇到的問題。

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