Enumerating things in DirectShow

  在任何领域做段日子以后,或多或少都会积累起一些自己熟悉和习惯的工具函数/类,今天把最近做 DirectShow 程序的时候写的两个小函数晒一下:)

  在 DirectShow 里做东西肯定有需要枚举一些 object 的场合,比如枚举出某 filter 的所有 pin,或者某 pin 支持的所有 media type。由于 DS 基于 COM 来构建,所以在枚举代码里时不时要照顾到 release 的逻辑,而且这些枚举代码也比较有共性,所以就写了两个小函数来封装一把,下面这个是枚举某 filter 特定方向上所有 pin 的:

  1. bool
  2.  EnumPinsOfFilter(
  3.      IBaseFilter    *pFilter,
  4.      PIN_DIRECTION   dir,
  5.      IEnumPins     **ppEnum,
  6.      IPin          **ppPin )
  7.  {
  8.      bool bResult = false;
  9.  
  10.      while( true )
  11.      {
  12.          if( NULL == pFilter || NULL == ppEnum || NULL == ppPin )
  13.              break;
  14.  
  15.          SafeRelease( *ppPin );
  16.  
  17.          HRESULT hResult = S_OK;
  18.          if( NULL == *ppEnum )
  19.          {
  20.              hResult = pFilter->EnumPins( ppEnum );
  21.              if( FAILED( hResult ) )
  22.                  break;
  23.              (*ppEnum)->Reset();
  24.          }
  25.  
  26.          ULONG uFetched = 0;
  27.          hResult = (*ppEnum)->Next( 1, ppPin, &uFetched );
  28.          if( FAILED( hResult ) )
  29.              break;
  30.  
  31.          if( 0 == uFetched )  // no more pins
  32.              break;
  33.  
  34.          PIN_DIRECTION pindir = PINDIR_INPUT;
  35.          hResult = (*ppPin)->QueryDirection( &pindir );
  36.          if( FAILED( hResult ) || pindir != dir )
  37.          {
  38.              SafeRelease( *ppPin );
  39.              continue;
  40.          }
  41.  
  42.          bResult = true;
  43.          break;
  44.      }
  45.  
  46.      return( bResult );
  47.  }

调用者需要实现准备一个枚举器指针和一个 pin 指针,不断调用这个函数,直到得到一个 false 的返回值。每成功的调用一次需要 release 一下 pin 指针,最后一次调用结束后 release 枚举器指针:

  1. IEnumPins *pEnum = NULL;
  2.  IPin      *pPin  = NULL;
  3.  while( EnumPinsOfFilter( pFilter, PINDIR_OUTPUT, &pEnum, &pPin ) )
  4.  {
  5.      // use pPin
  6.      SafeRelease( pPin );
  7.  }
  8.  SafeRelease( pEnum );

下面这个函数是用来枚举某 pin 支持的所有 media type 的:

  1. bool
  2.  EnumMediaTypesOfPin(
  3.      IPin             *pPin,
  4.      IEnumMediaTypes **ppEnum,
  5.      AM_MEDIA_TYPE   **ppType )
  6.  {
  7.      bool bResult = false;
  8.  
  9.      do
  10.      {
  11.          if( NULL == pPin || NULL == ppEnum || NULL == ppType )
  12.              break;
  13.  
  14.          SafeDeleteMediaType( *ppType );
  15.  
  16.          HRESULT hResult = S_OK;
  17.          if( NULL == *ppEnum )
  18.          {
  19.              hResult = pPin->EnumMediaTypes( ppEnum );
  20.              if( FAILED( hResult ) )
  21.                  break;
  22.              (*ppEnum)->Reset();
  23.          }
  24.  
  25.          ULONG uFetched = 0;
  26.          hResult = (*ppEnum)->Next( 1, ppType, &uFetched );
  27.          if( FAILED( hResult ) )
  28.              break;
  29.  
  30.          if( 0 == uFetched )  // no more types
  31.              break;
  32.  
  33.          bResult = true;
  34.      }
  35.      while( false );
  36.  
  37.      return( bResult );
  38.  }

用法类似,不多说了;)

-=-= =-=-

iPhone OS 4.0 发布以后,果然支持多任务,不过不是真正的多任务就对了。当然,这也不一定完全是坏处,还是要兼顾电力和内存的限制,达到硬件限制和使用体验的最佳平衡。不管怎么说,到夏天的时候就可以升级了。

Leave a Reply