科技行者

行者学院 转型私董会 科技行者专题报道 网红大战科技行者

知识库

知识库 安全导航

至顶网软件频道基础软件DirectShow入门之模拟构建Graph

DirectShow入门之模拟构建Graph

  • 扫一扫
    分享文章到微信

  • 扫一扫
    关注官方公众号
    至顶头条

本篇文档主要讲述如何使用GraphEdit来模拟构建graph图,测试你的filter。

作者:智慧的鱼 来源:天极开发 2007年10月16日

关键字:

  • 评论
  • 分享微博
  • 分享邮件
Loading a Graph From an External Process

  GraphEdit可以加载其他进程创建的filter Graph,利用这个特性,只使用少量的代码,你可以清楚地看到你的应用程序创建的所有的filter Graph。

  这个特性只有win2000,XP才支持。

  应用程序首先必须在Running Object Table (ROT).中注册一个filter graph的实例。ROT是一个全局的对象表,用来查看所有正在运行的对象。对象都是通过moniker注册到rot上。Graph Edit通过搜索ROT中和指定名字moniker就ok。

  !FilterGraph X pid Y

  这里,x是Filter Graph Manager的地址,y是进程ID,也是16进制。

  当你的应用程序创建filter graph的时候,调用下面的代码:

HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)
{
 IMoniker * pMoniker;
 IRunningObjectTable *pROT;
 if (FAILED(GetRunningObjectTable(0, &pROT))) {
  return E_FAIL;
 }
 WCHAR wsz[256];
 wsprintfW(wsz, L"FilterGraph %08x pid %08x", (DWORD_PTR)pUnkGraph, GetCurrentProcessId());
HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);
 if (SUCCEEDED(hr)) {
  hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE, pUnkGraph,
   pMoniker, pdwRegister);
  pMoniker->Release();
 }
 pROT->Release();
 return hr;
}

  这个函数创建了一个moniker作为filter graph在ROT中的入口,第一个参数是指向filter Graph的指针,第二个参数返回filter graph在ROT中的入口。当应用程序销毁filter graph的时候,一定要调用下面的函数来删除这个ROT入口:

void RemoveFromRot(DWORD pdwRegister)
{
 IRunningObjectTable *pROT;
 if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {
  pROT->Revoke(pdwRegister);
  pROT->Release();
 }
}

  下面的代码演示了如何调用上面的两个函数:

IGraphBuilder *pGraph;
DWORD dwRegister;

// Create the filter graph manager.
CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
IID_IGraphBuilder, (void **)&pGraph);
#ifdef _DEBUG
hr = AddToRot(pGraph, &dwRegister);
#endif

// Rest of the application (not shown).

#ifdef _DEBUG
RemoveFromRot(dwRegister);
#endif
pGraph->Release();

  同时运行你的应用程序和GraphEdit,你就可以在GraphEdit中查看你应用程序中的filter graph了。在GraphEdit中,如下:


图8

  然后就出现了下面的对话框


图9

  Saving a Filter Graph to a GraphEdit File

  下面的代码演示了如何保存一个GraphEdit(.gif)文件,这个可以用来调试你的应用程序。

HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath)
{
 const WCHAR wszStreamName[] = L"ActiveMovieGraph";
 HRESULT hr;

 IStorage *pStorage = NULL;
 hr = StgCreateDocfile(
  wszPath,
  STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE | STGM_SHARE_EXCLUSIVE,
  0, &pStorage);
 if(FAILED(hr))
 {
  return hr;
 }

 IStream *pStream;
 hr = pStorage->CreateStream(
  wszStreamName,
  STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,
  0, 0, &pStream);
 if (FAILED(hr))
 {
  pStorage->Release();
  return hr;
 }

 IPersistStream *pPersist = NULL;
 pGraph->QueryInterface(IID_IPersistStream, (void**)&pPersist);
 hr = pPersist->Save(pStream, TRUE);
 pStream->Release();
 pPersist->Release();
 if (SUCCEEDED(hr))
 {
  hr = pStorage->Commit(STGC_DEFAULT);
 }
 pStorage->Release();
 return hr;
}

  例如,下面的代码创建了文件回放的graph并保存为MyGraph.grf:

void __cdecl main(void)
{
 HRESULT hr;
 IGraphBuilder *pGraph;
 CoInitialize(NULL);

 // Create the Filter Graph Manager and render a file.
 CoCreateInstance(CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER,
 IID_IGraphBuilder, reinterpret_cast<void**>(&pGraph));
 hr = pGraph->RenderFile(L"C:\\Video.avi", NULL);

 if (SUCCEEDED(hr))
 {
  hr = SaveGraphFile(pGraph, L"C:\\MyGraph.grf");
 }

 pGraph->Release();
 CoUninitialize();
}

  Loading a GraphEdit File Programmatically

  在应用程序中可以通过IPersistStream接口来加载一个GraphEdit (.grf) file,实例代码如下:

HRESULT LoadGraphFile(IGraphBuilder *pGraph, const WCHAR* wszName)
{
 IStorage *pStorage = 0;
 if (S_OK != StgIsStorageFile(wszName))
 {
  return E_FAIL;
 }
 HRESULT hr = StgOpenStorage(wszName, 0,
  STGM_TRANSACTED | STGM_READ | STGM_SHARE_DENY_WRITE,
  0, 0, &pStorage);
 if (FAILED(hr))
 {
  return hr;
 }
 IPersistStream *pPersistStream = 0;
 hr = pGraph->QueryInterface(IID_IPersistStream,
  reinterpret_cast<void**>(&pPersistStream));
 if (SUCCEEDED(hr))
 {
  IStream *pStream = 0;
  hr = pStorage->OpenStream(L"ActiveMovieGraph", 0,
   STGM_READ | STGM_SHARE_EXCLUSIVE, 0, &pStream);
  if(SUCCEEDED(hr))
  {
   hr = pPersistStream->Load(pStream);
   pStream->Release();
  }
  pPersistStream->Release();
 }
 pStorage->Release();
 return hr;
}

  必须要注意的是,GraphEdit文件只是用来测试或者调试用的,并不是为了让终端客户用的。

查看本文源

    • 评论
    • 分享微博
    • 分享邮件
    邮件订阅

    如果您非常迫切的想了解IT领域最新产品与技术信息,那么订阅至顶网技术邮件将是您的最佳途径之一。

    重磅专题
    往期文章
    最新文章