GraphEdit
微软的SDK里面有个DirectShow的辅助工具GraphEdit,这里的文字简单介绍如何将应用程序生成的GraphBuilder插入到GraphEdit中直观的显示。
可能一开始我们对这种应用有点儿不理解,既然是自己写的代码,GraphBuilder里面的链路也是自己建立的,有必要多此一举么? 其实不然,微软在生成GraphBuilder其中的数据链路时,并不是完全按照咱们的代码中指示连接的,连接的真正过程包含了一些自动化的因素。比如我设置一个H.264 Decoder Filter直接连接播放Render Filter,Connet是成功的,从代码里看是Decoder的输出PIN直接连到Render的输入PIN,但是实际情况并不是这样,在GraphEdit里面显示你会发现,Decoder和Render之间被插入一个Color Space Converter的Filter,它负责吧Decoder的输出从YUV420的格式转换成Render能接受的RGB32格式。另一个例子,摄像头的输出可以直接接Render Filter,但是实际系统会在采集设备和Render之间插入解码器MJPEG Decompressor和色彩空间转换模块Color Space Converter。微软的这种自动化手段可以大大的简化我们建立GraphBuilder的过程(我粗略的统计了一下,基本每个工程都能减少40%到70%的代码量),产生的问题是这种自动化是隐性的,不直观可见的,不会体现在代码中。GraphEdit这个小工具就给我们提供了这样一个手段,去一窥其中究竟。
GraphEdit的简单使用
GraphEdit是一个很简单的工具软件,其实基本不用教大家也会用,但是为了文章的完整性,这里简单介绍两个最基本的功能。
功能(1)获得信息:
GraphEdit上方蓝色方块的按钮<Add Filter to graph>,点击后会出现上面图示的对话框。这个对话框中,你可以查看系统里现有的所有注册Filter;你可以知道Filter对应的文件的位置和名称;你可以知道Filter的FriendlyName用来枚举识别;你可以知道Filter的GUID用来直接创建实例,你可以知道Filter所有PIN的类型数量,并且可以知道每个PIN支持什么样的媒体类型,并知道该媒体类型的GUID或者名称。
在设计一个GraphBuilder之初,浏览这个名为Which filters do you want to insert的对话框,比查询MSDN可要方便快速多了。当然更多的细节还是要到如下地址去查询。MSDN Filters
功能(2)测试
GraphEdit也可以作为一个Filter的测试平台。当我们自己写好一个Filter并对它进行注册后,就可以在Filter列表中找到我们自己的Filter〈一般会出现在DircetShow Filters那个目录树底下〉。我们可以插入自己的Filter然后组建起一个链路,点击绿色箭头运行就可以测试了。这样进行测试不用写Test程序,实现快速容易,可以避免引入额外的错误。当然这一切的前提是您Filter的Propage要好好地写,使用Propage能配置你Filter运行需要的一切参数。
用GraphEdit辅助调试
这就是本文的重点了,首先必须要告诉您一个技巧,在使用GraphEdit加载您应用程序中的GraphBuilder之前,您必须先注册一个名为proppage.dll的文件,这个DLL就在GraphEdit同一个不录下,一般在SDK的Bin目录中。加载方法罗嗦一下,管理员权限的CMD窗口中"regsvr32 ./proppage.dll"回车。加载这个DLL以后GraphEdit的功能会稍稍出现变化,Filter的属性页会增加一两个Tab,你可以在属性页中查询一个Filter当前的输入输出的媒体类型和参数,也可以查询未连接PIN支持的所有媒体类型和参数。
要使用GraphEdit辅助调试应用程序,只需如下两步:
Step(1)代码中实现AddGraphToRot( )和RemoveGraphFromRot( )
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
HRESULT AddGraphToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
IMoniker * pMoniker;
IRunningObjectTable *pROT;
WCHAR wsz[128];
HRESULT hr;
if (!pUnkGraph || !pdwRegister)
return E_POINTER;
if (FAILED(GetRunningObjectTable(0, &pROT)))
return E_FAIL;
hr = StringCchPrintfW(wsz, NUMELMS(wsz), L"FilterGraph %08x pid %08x\0", (DWORD_PTR)pUnkGraph,
GetCurrentProcessId());
hr = CreateItemMoniker(L"!", wsz, &pMoniker);
if (SUCCEEDED(hr))
{
// Use the ROTFLAGS_REGISTRATIONKEEPSALIVE to ensure a strong reference
// to the object. Using this flag will cause the object to remain
// registered until it is explicitly revoked with the Revoke() method.
//
// Not using this flag means that if GraphEdit remotely connects
// to this graph and then GraphEdit exits, this object registration
// will be deleted, causing future attempts by GraphEdit to fail until
// this application is restarted or until the graph is registered again.
hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
pMoniker, pdwRegister);
pMoniker->Release();
}
pROT->Release();
return hr;
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
void RemoveGraphFromRot(DWORD pdwRegister)
{
IRunningObjectTable *pROT;
if (SUCCEEDED(GetRunningObjectTable(0, &pROT)))
{
pROT->Revoke(pdwRegister);
pROT->Release();
}
}
-------------------------------------------------------------------------------------------------------------------------------------------------------------------
这两个函数无需修改,直接贴到代码里面就可以使用。
在主函数调用时,首先声明一个DWORD 的句柄g_dwGraphRegister;
然后在初始化完GraphBuilder后Run之前调用AddGraphToRot( pMyGraph, &dwGraphRegister);
最后在函数推出之前调用RemoveGraphFromRot(DWORD dwGraphRegister);
这两个函数在SDK的例子里面都有出现,比如大家可以去看看Cap这个例子。
Step(2)在程序运行过程中显示
使用很简单了,点击"Connect to a running graph in another application"这个快捷键〈图标跟GraphEdit图标一样的那个〉就会出现以下对话框,选择一个点OK。
我们程序里面运行的GraphBuilder就会出现在眼前了。
我KaO怎么跟设计的不一样。Jok~ Jok~
我总结要注意的有以下两点:
一是运行程序的权限要和运行GraphEdit的一致,比如我调试SDK例子用的管理员权限,启动调试后打开GraphEdit必须也用管理员权限,否则啥也别想看见;
二是调试中不要试图用GraphEdit加载一个已经被中断的Application,那样您的GraphEdit就等着杀进程吧。
另外,有时候GraphEdit会不能正常显示,一启动就被最小化。那时候打开任务管理器到应用程序页面,选GraphEdit点右键选最大化就可以了。
转载自:http://hi.baidu.com/binaryghost/item/feb14f0cda0e40eaf45ba6bb