DirectShow--用GraphEdit辅助调试

前面的话

GraphEdit

  微软的SDK里面有个DirectShow的辅助工具GraphEdit,这里的文字简单介绍如何将应用程序生成的GraphBuilder插入到GraphEdit中直观的显示。

DirectShow--用GraphEdit辅助调试_第1张图片

  可能一开始我们对这种应用有点儿不理解,既然是自己写的代码,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是一个很简单的工具软件,其实基本不用教大家也会用,但是为了文章的完整性,这里简单介绍两个最基本的功能。

DirectShow--用GraphEdit辅助调试_第2张图片 

  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点右键选最大化就可以了。

你可能感兴趣的:(DirectShow--用GraphEdit辅助调试)