DirectShow过滤器开发-获取过滤器图事件过滤器

下载本过滤器DLL
本过滤器获取过滤器图事件,将事件代码及参数以列表形式显示在窗口中。下面是事件列表窗口图片:
在这里插入图片描述

过滤器信息

过滤器名称:事件
过滤器GUID:{380338B5-4292-4DB3-826C-2A582678737E}
DLL注册函数名:DllRegisterServer
删除注册函数名:DllUnregisterServer
过滤器没有引脚。

过滤器开发信息

过滤器类从CBaseFilter类派生。在过滤器加入过滤器图时(JoinFilterGraph函数),获取过滤器图管理器指针,获取图事件接口指针;创建事件列表窗口,创建“获取过滤器图事件”线程;并在该线程中,使用图事件接口,在图事件队列中获取事件。

下面是本过滤器DLL的全部代码

头文件:CFilter.h

#include "resource.h"

#include <streams.h>
#include <initguid.h>

#if _DEBUG
	#pragma comment(lib, "Strmbasd.lib")//C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Debug\strmbasd.lib
#else
	#pragma comment(lib, "Strmbase.lib")//C:\Program Files\Microsoft SDKs\Windows\v7.1\Samples\multimedia\directshow\baseclasses\Release\strmbase.lib
#endif
#pragma comment(lib, "Winmm.lib")//C:\Program Files\Microsoft SDKs\Windows\v7.1\Lib\Winmm.lib
#pragma comment(lib, "msvcrt.lib")//C:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\lib\msvcrt.lib

// {380338B5-4292-4DB3-826C-2A582678737E}
DEFINE_GUID(CLSID_Event, 
0x380338b5, 0x4292, 0x4db3, 0x82, 0x6c, 0x2a, 0x58, 0x26, 0x78, 0x73, 0x7e);


class CFilter : public CBaseFilter, public CCritSec
{
public:
    CFilter(LPWSTR lpName, LPUNKNOWN pUnk,HRESULT *phr);
    virtual ~CFilter();
    DECLARE_IUNKNOWN
	static CUnknown * WINAPI CreateInstance(LPUNKNOWN, HRESULT *);
	STDMETHODIMP JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName);
	HRESULT FindFilters(IFilterGraph* pGraph, int& n);//自定义函数,查找图中事件过滤器数量
    int GetPinCount();
    CBasePin *GetPin(int n);
	HMENU hMenu;//菜单句柄
	HWND hwnd;//窗口句柄
	HWND hList;//列表视图控件窗口句柄
	HANDLE hDestroy;//“过滤器已销毁”事件句柄
	IFilterGraph * m_pGraph;//过滤器图管理器指针
	IMediaEvent* pEvent;//过滤器图事件接口
};

源文件:CFilter.cpp

#include "CFilter.h"
#include "Commctrl.h"
#include "wchar.h"
#include "wmsdkidl.h"

HINSTANCE Hinstance;//DLL模块句柄
CFilter* m_pCFilter=NULL;//过滤器指针

DWORD WINAPI  CreateWindowThread(LPVOID pParam);//创建窗口线程函数声明

DWORD WINAPI  GetEventThread(LPVOID pParam);//获取事件线程函数声明

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);//窗口过程函数声明

#pragma warning(disable:4355 4127)//禁用警告C4355

CFilter::CFilter(LPWSTR lpName, LPUNKNOWN pUnk,HRESULT *phr) : CBaseFilter(lpName, pUnk, (CCritSec *) this, CLSID_Event)
{
	m_pGraph=NULL;pEvent=NULL;
	hDestroy=CreateEvent( NULL, FALSE, FALSE, NULL); //创建“过滤器已销毁”事件,自动重置,初始状态无信号
	m_pCFilter=this;
}

CFilter::~CFilter()
{
	SetEvent(hDestroy);//发出“过滤器已销毁”信号
	SendMessage(hwnd,WM_CLOSE,0,0);//关闭事件窗口
	DestroyWindow(hwnd);//销毁事件窗口
	if(m_pGraph!=NULL)m_pGraph->Release();
	if(pEvent!=NULL)pEvent->Release();
	UnregisterClass(L"事件窗口类", Hinstance);//删除窗口类注册
}

CUnknown * WINAPI CFilter::CreateInstance(LPUNKNOWN pUnk, HRESULT *phr)
{
    return new CFilter(L"事件", pUnk, phr);//创建过滤器
} 

STDMETHODIMP CFilter::JoinFilterGraph(IFilterGraph * pGraph, LPCWSTR pName)
{
	HRESULT hr;
	if(pGraph!=NULL)
	{
		int n=0;
		FindFilters(pGraph,n);//获取图中“事件过滤器”数量
		if(n>1)
		{
			MessageBox(0,L"只能创建一个事件过滤器",0,MB_OK);return S_FALSE;
		}
		hr=pGraph->QueryInterface(IID_IMediaEvent,(void**)&pEvent);
		if(pEvent!=NULL)
		{
			hr=pEvent->CancelDefaultHandling(EC_STATE_CHANGE); //取消事件默认处理
			hr=pEvent->CancelDefaultHandling(EC_DISPLAY_CHANGED); 
			hr=pEvent->CancelDefaultHandling(EC_NEED_RESTART);
			hr=pEvent->CancelDefaultHandling(EC_REPAINT);
			hr=pEvent->CancelDefaultHandling(EC_STARVATION); 
			hr=pEvent->CancelDefaultHandling(EC_STEP_COMPLETE); 
			hr=pEvent->CancelDefaultHandling(EC_WINDOW_DESTROYED); 
		}
		m_pGraph=pGraph;pGraph->AddRef();
		CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)CreateWindowThread,this,0,NULL);//创建窗口线程
		CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)GetEventThread,this,0,NULL);//创建“获取过滤器图事件”线程
	}
	return CBaseFilter::JoinFilterGraph(pGraph, pName);
}

HRESULT CFilter::FindFilters(IFilterGraph* pGraph, int& n)//查找图中事件过滤器数量
{
	IEnumFilters* pEnum = NULL;
	IBaseFilter* pFilter;
	ULONG cFetched;
	HRESULT hr = pGraph->EnumFilters(&pEnum);//获取IEnumFilters接口
	if (FAILED(hr)) return hr;
	while (pEnum->Next(1, &pFilter, &cFetched) == S_OK)
	{
		GUID guid;
		hr = pFilter->GetClassID(&guid);
		if (guid==CLSID_Event)//如果是事件过滤器
		{
			n++;
		}
		pFilter->Release();
	}
	pEnum->Release();
	return S_OK;
}

int CFilter::GetPinCount()
{
	return 0;
}

CBasePin *CFilter::GetPin(int n)
{
	return NULL;
}

COLORREF color1=RGB(95,108,163),color2=RGB(255,255,255);
DWORD WINAPI  CreateWindowThread(LPVOID pParam)//创建窗口线程
{
	CFilter* p=(CFilter*)pParam;
	WNDCLASSEX wcx;
	wcx.cbSize = sizeof(wcx);//结构的大小
	wcx.style = CS_HREDRAW | CS_VREDRAW; //窗口类样式
	wcx.lpfnWndProc = WndProc; //窗口过程
	wcx.cbClsExtra = 0;                //没有额外的类内存
	wcx.cbWndExtra = 0;            //没有额外的窗口内存
	wcx.hInstance = Hinstance;  //实例句柄
	wcx.hIcon = LoadIcon(NULL, IDI_APPLICATION);  //预定义的应用程序图标
	wcx.hCursor = LoadCursor(NULL, IDC_ARROW);   //预定义的光标
	HBRUSH hBrush=CreateSolidBrush(RGB(57,64,97));
	wcx.hbrBackground = hBrush;  //背景笔刷
	wcx.lpszMenuName = L"EventMenu"; //菜单资源名称
	wcx.lpszClassName = L"事件窗口类"; //窗口类的名称
	wcx.hIconSm = (HICON)LoadImage(Hinstance, MAKEINTRESOURCE(5),IMAGE_ICON,GetSystemMetrics(SM_CXSMICON),GetSystemMetrics(SM_CYSMICON),LR_DEFAULTCOLOR);//小类图标 
	RegisterClassEx(&wcx);//注册窗口类
	p->hMenu=LoadMenu(Hinstance,MAKEINTRESOURCE(IDR_MENU1));//加载菜单
	RECT PM_rect;
	SystemParametersInfo(SPI_GETWORKAREA, 0, (PVOID)&PM_rect, 0);//获取桌面工作区矩形
	int Width=915;int Height=400;//窗口的宽高
	HWND hwnd= CreateWindowEx(//创建"事件列表窗口"
		WS_EX_TOPMOST,                      //窗口扩展样式      
		L"事件窗口类",          //类名                
		L"事件列表",         //窗口名称         
		WS_VISIBLE|WS_SYSMENU|WS_CAPTION|WS_CLIPCHILDREN|WS_MINIMIZEBOX|WS_POPUP,   //窗口样式      
		(PM_rect.right-PM_rect.left)/2-Width/2,          //窗口左侧位置
		PM_rect.bottom-Height-30,          //窗口顶部位置
		Width,           //窗口宽度        
		Height,          //窗口高度       
		(HWND)NULL,    //没有父窗口或所有者窗口
		p->hMenu,           //使用的菜单      
		Hinstance,           //实例句柄     
		NULL);                 //没有窗口创建数据
	p->hwnd=hwnd;

	RECT rect;
	GetClientRect(hwnd,&rect);
	p->hList=CreateWindow(L"SysListView32",NULL,WS_CHILD|WS_VISIBLE|LVS_REPORT|LVS_SINGLESEL|LVS_NOSORTHEADER  ,5,5, rect.right-10,rect.bottom-10,hwnd,NULL,Hinstance,NULL);//创建列表视图控件

	LVCOLUMN LV;
	LV.mask=LVCF_WIDTH|LVCF_TEXT;
	LV.pszText=L"事件";LV.cx=300;
	SendMessage(p->hList,LVM_INSERTCOLUMN,(WPARAM)0,(LPARAM)&LV);//列表视图控件添加第1列
	LV.pszText=L"事件参数1";LV.cx=300;
	SendMessage(p->hList,LVM_INSERTCOLUMN,(WPARAM)1,(LPARAM)&LV);//列表视图控件添加第2列
	LV.pszText=L"事件参数2";LV.cx=300;
	SendMessage(p->hList,LVM_INSERTCOLUMN,(WPARAM)2,(LPARAM)&LV);//列表视图控件添加第3列
	SendMessage(p->hList,LVM_SETBKCOLOR,0,(LPARAM)color1);//设置列表视图控件背景色
	SendMessage(p->hList,LVM_SETTEXTBKCOLOR,0,(LPARAM)color1);//设置列表视图控件文本背景色
	SendMessage(p->hList,LVM_SETTEXTCOLOR,0,(LPARAM)color2);//设置列表视图控件文本颜色

	MSG msg;
	BOOL fGotMessage;
    while ((fGotMessage = GetMessage(&msg, hwnd, 0, 0)) != 0 && fGotMessage != -1) 
    { 
        TranslateMessage(&msg); 
        DispatchMessage(&msg); 
    } 
	return 1;
}

LRESULT CALLBACK WndProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)//窗口过程函数
{
	HMENU hMenu=GetMenu(hwnd);
	switch(uMsg)
	{
	case WM_CLOSE://点击了样本窗口关闭按钮
		ShowWindow(hwnd, SW_MINIMIZE);//最小化窗口
		return 0;//不调用DefWindowProc,防止销毁窗口
	case WM_COMMAND:
			switch(LOWORD(wParam)) //响应点击菜单项
			{
			case ID_40001:
				SendMessage(m_pCFilter->hList,LVM_DELETEALLITEMS,0,0);//列表视图删除所有项
				break;
			case ID_Menu://EC_ACTIVATE
				if(GetMenuState(hMenu,ID_Menu,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_Menu,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_ACTIVATE);//恢复事件默认处理
				}
				else
				{
					CheckMenuItem(hMenu,ID_Menu,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_ACTIVATE); //取消事件默认处理
				}
				break;
			case ID_40004://EC_COMPLETE
				if(GetMenuState(hMenu,ID_40004,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40004,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_COMPLETE); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40004,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_COMPLETE);
				}
				break;
			case ID_40002://EC_STATE_CHANGE
				if(GetMenuState(hMenu,ID_40002,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40002,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_STATE_CHANGE); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40002,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_STATE_CHANGE); 
				}
				break;
			case ID_40005://EC_DISPLAY_CHANGED
				if(GetMenuState(hMenu,ID_40005,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40005,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_DISPLAY_CHANGED); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40005,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_DISPLAY_CHANGED); 
				}
				break;
			case ID_40007://EC_NEED_RESTART
				if(GetMenuState(hMenu,ID_40007,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40007,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_NEED_RESTART); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40007,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_NEED_RESTART);
				}
				break;
			case ID_40008://EC_REPAINT
				if(GetMenuState(hMenu,ID_40008,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40008,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_REPAINT); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40008,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_REPAINT);
				}
				break;
			case ID_40010://EC_STARVATION
				if(GetMenuState(hMenu,ID_40010,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40010,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_STARVATION); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40010,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_STARVATION); 
				}
				break;
			case ID_40011://EC_STEP_COMPLETE
				if(GetMenuState(hMenu,ID_40011,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40011,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_STEP_COMPLETE); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40011,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_STEP_COMPLETE); 
				}
				break;
			case ID_40012://EC_WINDOW_DESTROYED
				if(GetMenuState(hMenu,ID_40012,MF_BYCOMMAND)==MF_CHECKED)
				{
					CheckMenuItem(hMenu,ID_40012,MF_UNCHECKED);m_pCFilter->pEvent->RestoreDefaultHandling(EC_WINDOW_DESTROYED); 
				}
				else
				{
					CheckMenuItem(hMenu,ID_40012,MF_CHECKED);m_pCFilter->pEvent->CancelDefaultHandling(EC_WINDOW_DESTROYED); 
				}
				break;
			}
		break;
	}
	return DefWindowProc(hwnd, uMsg, wParam, lParam);
}

DWORD WINAPI  GetEventThread(LPVOID pParam)//获取图事件线程
{
	CFilter* p=(CFilter*)pParam;
	long evCode; LONG_PTR lParam1, lParam2;
	LVITEM LT0;
	LT0.mask=LVIF_TEXT;LT0.iItem=0;LT0.iSubItem=0;
	LVITEM LT1;
	LT1.mask=LVIF_TEXT;LT1.iItem=0;LT1.iSubItem=1;
	LVITEM LT2;
	LT2.mask=LVIF_TEXT;LT2.iItem=0;LT2.iSubItem=2;
	
Agan:
	if(p->pEvent->GetEvent(&evCode,&lParam1,&lParam2,1)==S_OK)
	{
		wchar_t wch1[100],wch2[100];
		wmemset(wch1,0,100);wmemset(wch2,0,100);
		_itow_s(lParam1,wch1,10);_itow_s(lParam2,wch2,10);
		wchar_t WCH0[100];wmemset(WCH0,0,100);
		wchar_t WCH1[100]=L"lParam1=";
		wchar_t WCH2[100]=L"lParam2=";
		wcscat_s(WCH1,100,wch1);wcscat_s(WCH2,100,wch2);
		switch (evCode)
		{
		case EC_ACTIVATE:
			wcscat_s(WCH0,100,L"EC_ACTIVATE//激活或停用窗口");
			if(lParam1)wcscat_s(WCH1,100,L"//激活窗口");
			else wcscat_s(WCH1,100,L"//停用窗口");
			wcscat_s(WCH2,100,L"//渲染器IBaseFilter接口指针");
			break;
		case EC_BUFFERING_DATA:
			wcscat_s(WCH0,100,L"EC_BUFFERING_DATA");
			if(lParam1)wcscat_s(WCH1,100,L"//图开始缓冲");
			else wcscat_s(WCH1,100,L"//图已停止缓冲");
			break;
		case EC_BUILT:
			wcscat_s(WCH0,100,L"EC_BUILT//图构建完成。由视频控件发送");
			break;
		case EC_CLOCK_CHANGED:
			wcscat_s(WCH0,100,L"EC_CLOCK_CHANGED//参考时钟已更改");
			break;
		case EC_CLOCK_UNSET:
			wcscat_s(WCH0,100,L"EC_CLOCK_UNSET//时钟提供程序已断开连接");
			break;
		case EC_CODECAPI_EVENT:
			wcscat_s(WCH0,100,L"EC_CODECAPI_EVENT//编码器发出编码信号。");
			wcscat_s(WCH1,100,L"//用户数据");
			wcscat_s(WCH2,100,L"//指向事件数据的指针");
			break;
		case EC_COMPLETE:
			wcscat_s(WCH0,100,L"EC_COMPLETE//流渲染完成");
			if(lParam1==0)wcscat_s(WCH1,100,L"//(HRESULT)返回S_OK");
			else wcscat_s(WCH1,100,L"//(HRESULT)返回值");
			if(lParam2!=0)wcscat_s(WCH2,100,L"//渲染器IBaseFilter接口的指针");
			break;
		case EC_DEVICE_LOST:
			wcscat_s(WCH0,100,L"EC_DEVICE_LOST//即插即用设备已删除或再次可用");
			wcscat_s(WCH1,100,L"//代表设备过滤器的IUnknown接口指针");
			if(lParam2)wcscat_s(WCH2,100,L"//设备再次可用");
			else wcscat_s(WCH2,100,L"//设备已删除");
			break;
		case EC_DISPLAY_CHANGED:
			wcscat_s(WCH0,100,L"EC_DISPLAY_CHANGED//显示模式已更改");
			if(lParam2)
			{
				if(lParam1)wcscat_s(WCH1,100,L"//输入引脚的IPin接口数组的指针");
				wcscat_s(WCH2,100,L"//数组的大小");
			}
			else
			{
				if(lParam1)wcscat_s(WCH1,100,L"//输入引脚的IPin接口的指针");
			}
			break;
		case EC_END_OF_SEGMENT:
			wcscat_s(WCH0,100,L"EC_END_OF_SEGMENT\\到达段的结尾");
			wcscat_s(WCH1,100,L"//自段开始的流时间,以100纳秒为单位");
			wcscat_s(WCH2,100,L"//段号(从零开始)");
			break;
		case EC_ERROR_STILLPLAYING:
			wcscat_s(WCH0,100,L"EC_ERROR_STILLPLAYING//异步命令运行图失败");
			wcscat_s(WCH1,100,L"//失败代码");
			break;
		case EC_ERRORABORT:
			wcscat_s(WCH0,100,L"EC_ERRORABORT//由于错误,操作被中止");
			wcscat_s(WCH1,100,L"//(HRESULT)失败代码");
			break;
		case EC_EXTDEVICE_MODE_CHANGE:
			wcscat_s(WCH0,100,L"EC_EXTDEVICE_MODE_CHANGE");
			break;
		case EC_FULLSCREEN_LOST:
			wcscat_s(WCH0,100,L"EC_FULLSCREEN_LOST//视频渲染器将退出全屏模式");
			wcscat_s(WCH2,100,L"//视频渲染器IBaseFilter接口的指针");
			break;
		case EC_GRAPH_CHANGED:
			wcscat_s(WCH0,100,L"EC_GRAPH_CHANGED//图已更改");
			break;
		case EC_LENGTH_CHANGED:
			wcscat_s(WCH0,100,L"EC_LENGTH_CHANGED//源的长度已更改");
			break;
		case EC_NEED_RESTART:
			wcscat_s(WCH0,100,L"EC_NEED_RESTART//过滤器要求重新启动图");
			break;
		case EC_NOTIFY_WINDOW:
			wcscat_s(WCH0,100,L"EC_NOTIFY_WINDOW//报告视频渲染器窗口");
			wcscat_s(WCH1,100,L"//(HWND)窗口句柄");
			break;
		case EC_OLE_EVENT:
			wcscat_s(WCH0,100,L"EC_OLE_EVENT//过滤器正将文本传递给应用程序");
			wcscat_s(WCH1,100,L"//(BSTR)字符串");
			wcscat_s(WCH2,100,L"//(BSTR)字符串");
			break;
		case EC_OPENING_FILE:
			wcscat_s(WCH0,100,L"EC_OPENING_FILE//图正在打开文件,或已完成打开文件");
			if(lParam1)wcscat_s(WCH1,100,L"//正在打开文件");
			else wcscat_s(WCH1,100,L"//完成打开文件");
			break;
		case EC_PALETTE_CHANGED:
			wcscat_s(WCH0,100,L"EC_PALETTE_CHANGED//视频调色板已更改");
			break;
		case EC_PAUSED:
			wcscat_s(WCH0,100,L"EC_PAUSED//暂停请求已完成");
			if(lParam1==0)wcscat_s(WCH1,100,L"//(HRESULT)返回S_OK");
			else wcscat_s(WCH1,100,L"//(HRESULT)返回值");
			break;
		case EC_PREPROCESS_COMPLETE:
			wcscat_s(WCH0,100,L"EC_PREPROCESS_COMPLETE//WM ASF Writer过滤器完成多遍编码的预处理");
			wcscat_s(WCH2,100,L"//过滤器IBaseFilter接口的指针");
			break;
		case EC_PROCESSING_LATENCY:
			wcscat_s(WCH0,100,L"EC_PROCESSING_LATENCY//处理每个样本所花费的时间");
			wcscat_s(WCH1,100,L"//处理每个样本的时间,单位100纳秒");
			break;
		case EC_QUALITY_CHANGE:
			wcscat_s(WCH0,100,L"EC_QUALITY_CHANGE//图正在删除样本,以进行质量控制");
			break;
		case EC_REPAINT:
			wcscat_s(WCH0,100,L"EC_REPAINT//引脚需要重新发送数据");
			wcscat_s(WCH1,100,L"//视频渲染器输入引脚IPin接口的指针");
			break;
		case EC_SAMPLE_LATENCY:
			wcscat_s(WCH0,100,L"EC_SAMPLE_LATENCY//处理样本的进度落后");
			wcscat_s(WCH1,100,L"//落后时间,单位100纳秒");
			break;
		case EC_SAMPLE_NEEDED://
			wcscat_s(WCH0,100,L"EC_SAMPLE_NEEDED//请求新的输入样本");
			wcscat_s(WCH1,100,L"//需要新输入的流的标识符");
			break;
		case EC_SCRUB_TIME:
			wcscat_s(WCH0,100,L"EC_SCRUB_TIME//指定最近的帧步的时间戳");
			wcscat_s(WCH1,100,L"//(DWORD)时间戳的低32位");
			wcscat_s(WCH2,100,L"//(DWORD)时间戳的高32位");
			break;
		case EC_SEGMENT_STARTED:
			wcscat_s(WCH0,100,L"EC_SEGMENT_STARTED//新段已经开始");
			wcscat_s(WCH1,100,L"//自段开始的流时间,单位100纳秒");
			wcscat_s(WCH2,100,L"//(DWORD)段号(从零开始)");
			break;
		case EC_SHUTTING_DOWN:
			wcscat_s(WCH0,100,L"EC_SHUTTING_DOWN//图正在关闭");
			break;
		case EC_SNDDEV_IN_ERROR:
			wcscat_s(WCH0,100,L"EC_SNDDEV_IN_ERROR//音频捕获过滤器发生了设备错误");
			wcscat_s(WCH1,100,L"//SNDDEV_ERR枚举值,指示发生故障时如何访问设备");
			wcscat_s(WCH2,100,L"//DWORD值,指示从声音设备调用返回的错误");
			break;
		case EC_SNDDEV_OUT_ERROR:
			wcscat_s(WCH0,100,L"EC_SNDDEV_OUT_ERROR//音频渲染过滤器发生设备错误");
			wcscat_s(WCH1,100,L"//SNDDEV_ERR枚举值,指示发生故障时如何访问设备");
			wcscat_s(WCH2,100,L"//DWORD值,指示从声音设备调用返回的错误");
			break;
		case EC_STARVATION:
			wcscat_s(WCH0,100,L"EC_STARVATION//过滤器未接收到足够的数据");
			break;
		case EC_STATE_CHANGE:
			wcscat_s(WCH0,100,L"EC_STATE_CHANGE//图状态已更改");
			if(lParam1 ==State_Stopped)wcscat_s(WCH1,100,L"//新的图状态为停止");
			if(lParam1 ==State_Paused )wcscat_s(WCH1,100,L"//新的图状态为暂停");
			if(lParam1 ==State_Running)wcscat_s(WCH1,100,L"//新的图状态为运行");
			break;
		case EC_STEP_COMPLETE:
			wcscat_s(WCH0,100,L"EC_STEP_COMPLETE//过滤器已完成帧步进");
			break;
		case EC_STREAM_CONTROL_STARTED:
			wcscat_s(WCH0,100,L"EC_STREAM_CONTROL_STARTED//流控制启动命令生效");
			wcscat_s(WCH1,100,L"//启动流的引脚的IPin接口指针");
			wcscat_s(WCH2,100,L"//(DWORD)用户定义的值");
			break;
		case EC_STREAM_CONTROL_STOPPED:
			wcscat_s(WCH0,100,L"EC_STREAM_CONTROL_STOPPED//流控制停止命令已经生效");
			wcscat_s(WCH1,100,L"//停止流的引脚的IPin接口指针");
			wcscat_s(WCH2,100,L"//(DWORD)用户定义的值");
			break;
		case EC_STREAM_ERROR_STILLPLAYING:
			wcscat_s(WCH0,100,L"EC_STREAM_ERROR_STILLPLAYING//流中发生错误,但流仍在运行");
			wcscat_s(WCH1,100,L"//(HRESULT)失败代码");
			wcscat_s(WCH2,100,L"//(DWORD)次要错误代码");
			break;	
		case EC_STREAM_ERROR_STOPPED:
			wcscat_s(WCH0,100,L"EC_STREAM_ERROR_STOPPED//由于错误,流已停止");
			wcscat_s(WCH1,100,L"//(HRESULT)失败代码");
			wcscat_s(WCH2,100,L"//(DWORD)次要错误代码");
			break;
		case EC_TIMECODE_AVAILABLE:
			wcscat_s(WCH0,100,L"EC_TIMECODE_AVAILABLE//由支持时间码的过滤器发送");
			break;
		case EC_UNBUILT:
			wcscat_s(WCH0,100,L"EC_UNBUILT//图从已构建状态转换为未构建状态");
			break;
		case EC_USERABORT:
			wcscat_s(WCH0,100,L"EC_USERABORT//用户已终止运行");
			break;
		case EC_VIDEO_SIZE_CHANGED:
			wcscat_s(WCH0,100,L"EC_VIDEO_SIZE_CHANGED//视频大小已更改");
			wcscat_s(WCH1,100,L"//(DWORD)低位WORD新的宽度,高位WORD新高度;以像素为单位");
			break;
		case EC_VMR_RECONNECTION_FAILED:
			wcscat_s(WCH0,100,L"EC_VMR_RECONNECTION_FAILED//尝试动态格式更改,VMR无法接受新格式");
			break;
		case EC_VMR_RENDERDEVICE_SET:
			wcscat_s(WCH0,100,L"EC_VMR_RENDERDEVICE_SET//标识渲染机制");
			if(lParam1 ==VMR_RENDER_DEVICE_OVERLAY)wcscat_s(WCH1,100,L"//渲染到表面");
			if(lParam1 ==VMR_RENDER_DEVICE_VIDMEM)wcscat_s(WCH1,100,L"//渲染到视频内存");
			if(lParam1 ==VMR_RENDER_DEVICE_SYSMEM )wcscat_s(WCH1,100,L"//渲染到系统内存");
			break;
		case EC_VMR_SURFACE_FLIPPED:
			wcscat_s(WCH0,100,L"EC_VMR_SURFACE_FLIPPED//调用DirectDraw Flip方法");
			wcscat_s(WCH1,100,L"//(HRESULT)从DirectDraw Flip方法返回的状态代码");
			break;
		case EC_WINDOW_DESTROYED:
			wcscat_s(WCH0,100,L"EC_WINDOW_DESTROYED//窗口被销毁时由视频渲染器发送");
			wcscat_s(WCH1,100,L"//视频渲染器的IBaseFilter接口指针");
			break;
		case EC_WMT_EVENT:
			wcscat_s(WCH0,100,L"EC_WMT_EVENT//读取受数字版权管理(DRM)保护的ASF文件");
			break;
		case EC_WMT_INDEX_EVENT:
			wcscat_s(WCH0,100,L"EC_WMT_INDEX_EVENT//使用WM ASF Writer过滤器索引WMV文件");
			if(lParam1 ==WMT_STARTED)wcscat_s(WCH1,100,L"//索引已开始");
			if(lParam1 ==WMT_CLOSED )wcscat_s(WCH1,100,L"//索引已完成");
			if(lParam1 ==WMT_INDEX_PROGRESS )
			{
				wcscat_s(WCH1,100,L"//正在建立索引");
				wcscat_s(WCH2,100,L"//当前进度百分比");
			}
			break;
		default:
			break;
		}
		if (p->pEvent != NULL)p->pEvent->FreeEventParams(evCode, lParam1, lParam2);
		LT0.pszText=WCH0;LT1.pszText=WCH1;LT2.pszText=WCH2;
		SendMessage(p->hList,LVM_INSERTITEM,0,(LPARAM)&LT0);//列表视图添加项
		SendMessage(p->hList,LVM_SETITEMTEXT,0,(LPARAM)&LT1);//列表视图设置子项1文本
		SendMessage(p->hList,LVM_SETITEMTEXT,0,(LPARAM)&LT2);//列表视图设置子项2文本
	}
	DWORD dw = WaitForSingleObject(p->hDestroy,0);//获取“过滤器已销毁”事件信号
	if(dw!=WAIT_OBJECT_0)//如果没有信号
	{
		goto Agan;//再次获取事件
	}
	CloseHandle(p->hDestroy);
	return 1;
}

const AMOVIESETUP_FILTER Event =  //过滤器的注册信息
{
    &CLSID_Event,           //过滤器的类标识
    L"事件",                //过滤器的名称
    MERIT_DO_NOT_USE,      //过滤器优先值
    0,                     // 引脚数量
    NULL                   // 引脚信息
};

CFactoryTemplate g_Templates []  = {
    {
		L"事件"
      , &CLSID_Event
      , CFilter::CreateInstance
      , NULL
      , &Event
	}
};

int g_cTemplates = 1;

STDAPI DllRegisterServer()//注册DLL
{
    return AMovieDllRegisterServer2(TRUE);
} 

STDAPI DllUnregisterServer()//删除DLL注册
{
    return AMovieDllRegisterServer2(FALSE);
}

extern "C" BOOL WINAPI DllEntryPoint(HINSTANCE, ULONG, LPVOID);

BOOL APIENTRY DllMain(HANDLE hModule, DWORD  dwReason, LPVOID lpReserved)
{
	Hinstance=(HINSTANCE)hModule;
    return DllEntryPoint((HINSTANCE)(hModule), dwReason, lpReserved);
}


DLL模块定义文件:事件.def

LIBRARY     事件.dll

EXPORTS
            DllMain                 PRIVATE
            DllGetClassObject       PRIVATE
            DllCanUnloadNow         PRIVATE
            DllRegisterServer       PRIVATE
            DllUnregisterServer     PRIVATE

下载本过滤器DLL

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

h3974

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值