DShow中调试方法 (收藏)

程序设计的过程经常会遇到很多预想不到的情况。当情况发生的时候我们经常不知所措,调试的时候如果方法不对,经常会陷入绝望的地步,因为此时发生了错误,但是就是找不到该错误究竟在什么地方。在使用DShow的过程中,经常会遇到这种情况,我们单步跟踪,不知不觉我们就来到了汇编里面,此时只能茫然。下面我来说说我在使用dshow的过程常使用的方法。

使用GraphEdit

GraphEditDXSDK里面自带的一个创建和调试Filter Graph工具(DXSDK ROOT/DXSDK/Bin/DXUtils/graphedt.exe)。对于其说明可以参见其帮助文档。

所见即所得

在使用Filter的时候,当我们不知道该Filter是否能和另外一个FilterPin建立连接得时候,我们可以在GraphEdit里面进行,动动鼠标,结果便会呈现在你的眼前。

程序运行时候Graph的显示

运用SDK里面的函数AddToRotRemoveFromRot,可以在程序运行的时候把Graph的信息显示出来。

#001 //Parameters:

#002 //IUnknown – pointer to the graph to be outputted

#003 //DWORD     - The pecess identifier.

#004 HRESULT AddToRot(IUnknown *pUnkGraph, DWORD *pdwRegister)

#005 {

#006     IMoniker * pMoniker;

#007     IRunningObjectTable *pROT;

#008     if (FAILED(GetRunningObjectTable(0, &pROT)))

#009     {

#010         return E_FAIL;

#011     }

#012     WCHAR wsz[256];

#013     wsprintfW(wsz, L"FilterGraph %08x pid %08x",                                      (DWORD_PTR)pUnkGraph, GetCurrentProcessId());

#014     

#015     HRESULT hr = CreateItemMoniker(L"!", wsz, &pMoniker);

#016

#017     if (SUCCEEDED(hr))

#018     {

#019         hr = pROT->Register(ROTFLAGS_REGISTRATIONKEEPSALIVE,

#020                  pUnkGraph,

#021               pMoniker, pdwRegister);

#022          pMoniker->Release();

#023     }

#024     pROT->Release();

#025     return hr;

#026 }

 

 

#001 void RemoveFromRot(DWORD pdwRegister)

#002 {

#003     IRunningObjectTable *pROT;

#004     if (SUCCEEDED(GetRunningObjectTable(0, &pROT))) {

#005         pROT->Revoke(pdwRegister);

#006         pROT->Release();

#007     }

#008 }

示例代码:

#001 //suppose that the IGraphBuilder interface has been initialized

#002 IGaphBuilder *pGraph = NULL;

#003 //……Initialize here

#004 DWORD dwGraphRegister;

#005 HRESULT hr = AddToRot(pGraph, &dwGraphRegister);

#006 If(FAILED(hr))

#007 {

#008   //exceptions here

#009 }

#010 //……programming running

#011 //Before program shutdown or the IGraphBuilder release

#012 RemoveFromRot(dwGraphRegister);

#013 //……program clean up

保存Graph供察看和调试

首先可以调用SDK里面的函数用来保存Graph

#001 //Parameters:

#002 //IGraphBuiler – pointer to the graph to be saved

#003 ­//WCHAR – the file where to be saved.

#004 HRESULT SaveGraphFile(IGraphBuilder *pGraph, WCHAR *wszPath)

#005 {

#006     const WCHAR wszStreamName[] = L"ActiveMovieGraph";

#007     HRESULT hr;

#008     

#009    IStorage *pStorage = NULL;

#010     hr = StgCreateDocfile(

#011         wszPath,

#012         STGM_CREATE | STGM_TRANSACTED | STGM_READWRITE |                  STGM_SHARE_EXCLUSIVE,

#013         0, &pStorage);

#014     if(FAILED(hr))

#015     {

#016         return hr;

#017     }

#018  

#019     IStream *pStream;

#020     hr = pStorage->CreateStream(

#021         wszStreamName,

#022         STGM_WRITE | STGM_CREATE | STGM_SHARE_EXCLUSIVE,

#023         0, 0, &pStream);

#024     if (FAILED(hr))

#025     {

#026         pStorage->Release();   

#027         return hr;

#028     }

#029  

#030     IPersistStream *pPersist = NULL;

#031     pGraph->QueryInterface(IID_IPersistStream,                               (void**)&pPersist);

#032     hr = pPersist->Save(pStream, TRUE);

#033     pStream->Release();

#034     pPersist->Release();

#035     if (SUCCEEDED(hr))

#036     {

#037         hr = pStorage->Commit(STGC_DEFAULT);

#038     }

#039     pStorage->Release();

#040     return hr;

#041 }

使用方法我就不用多说了J.保存的Graph File可以被方法“所见即所得”使用J.

JIF的妙用

首先宏JIF的定义如下:

#001 void Msg(TCHAR *szFormat, ...)

#002 {

#003   TCHAR szBuffer[1024]; // Large buffer for long filenames or URLs

#004   const size_t NUMCHARS=sizeof(szBuffer)/sizeof(szBuffer[0]);

#005   const int LASTCHAR = NUMCHARS - 1;

#006  

#007   // Format the input string

#008   va_list pArgs;

#009   va_start(pArgs, szFormat);

#010  

#011   // Use a bounded buffer size to prevent buffer overruns.  Limit        // count to

#012   // character size minus one to allow for a NULL terminating        //character.

#013   _vsntprintf(szBuffer, NUMCHARS - 1, szFormat, pArgs);

#014   va_end(pArgs);

#015  

#016   // Ensure that the formatted string is NULL-terminated

#017   szBuffer[LASTCHAR] = TEXT('/0');

#018

#019   // Display a message box with the formatted string

#020   ::MessageBox(NULL, szBuffer, TEXT("Warning"), MB_OK);

#021 }

 

 

#001 #define JIF(x) if (FAILED(hr=(x))) /

#002   {Msg(TEXT("FAILED(hr=0x%x) in ") TEXT(#x) TEXT("/n/0"), hr);/

#003   return hr;}

当我们在调用COM的一个接口初始化一个变量或者对一个接口进行操作的时候,如果发生错误,JIF宏会给出提示错误的返回值和所执行操作的名字。

现在有一个问题,如果我们在程序中多次执行同样的操作,而这个操作抛出了一个异常,那这个异常究竟是哪一次操作所抛出的呢L?我们可以修改该宏:

#001 #define JIF(x) if (FAILED(hr=(x))) /

#002   {Msg(TEXT("FAILED(hr=0x%x) in ") /

#003       TEXT(#x) TEXT("/tFILE: %s/tLINE: %d"), /

#004       hr, __FILE__, __LINE__);}

当我们抛出异常的时候,显示的将包括抛出异常的地方。 
     
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值