制作Transform Filters

Step 1. 选择一个基类

  以下是base filters共你选择继承:

  1. CTransformFilter.     其利用了独立的输入输出缓存。这种类型的filter也叫做copy-transform filter。 当copy-transform filter接收到一个输入的sample,其将新构造的数据写入到output sample,然后在传递output sample 到下一个filter。              

  2.CTransInPlaceFilter.     其在原始缓存中直接操作数据,又被叫做trans-in-place filter。当trans-in-place filter接收到一个sample,其改变数据内部的sample,然后传递该sample到downstream。本filter的input pin 和output pin总是匹配媒体类型的。

  3. CBaseFilter其作为其他类的父类,其他类都是继承本类的。

Step 2. 声明自定义filter类

  *.在CTransformFilter情形下,pin委托了绝大多数工作给了filter,so你可能不必在改写pins了。你必须整体定义的一个唯一CLSID为了filter。下面演示了定义DEINE_GUID宏:

  [RleFilt.h]

  DEFINE_GUID(CLSID_RLEFilter,0x1915c5c7, 0x2aa, 0x415f, 0x89, 0xf, 0x76, 0xd9, 0x4c, 0x85, 0xaa, 0xf1);

  [RleFilt.cpp]

  #include <initguid.h>

  #include "RleFilt.h"

 

  *.下一步写类构造器

  CRleFilter::CRleFilter()

    :CTransformFilter(NAME("my RLE Encoder"), 0, CLSID_RLEFilter)

  {

      /* Initialize any private variables here. */
  }         

  //注意这里的CLSID是在本filter头文件中定义了的。

 

 

Step 3. Support Media Type Negotiation.(磋商媒体类型)

  *.当两个pins建立连接,他们必须在媒体类型上达成一致。媒体类型描述了数据的格式。基本的磋商机制如下:

      IPin::ReceiveConnection

  当Output pin在input pin上调用该方法,附带着确定了的媒体类型。此时input pin接受连接请求,要么拒绝。如果拒绝了output pin的连接请求,output pin也有尝试其他媒体类型的机会。可选择,让inputpin 枚举一张其可行的类型表,通过调用         

      IPin::EnumMediaTypes

  output pin可以利用该表来匹配媒体类型。

 

  *.input pin其依赖于上游的filter建议的媒体类型。

  *.当上游的filter要求了一种类型,此时input pin调用

      CTransformFilter::CheckInputType

  方法来接受或拒绝上游filter要求的媒体类型。

 

  *. output pin在input pin统一并建立了连接后,才会统一连接(注:建立连接不是由filter管理,而是由Filter Graph Manager管理)。通常filter在先决定了input pin的类型后再设置output 类型。

 

  *.   CTransformFilter::GetMediaType; 

  该方法对于output pin来说,在建立了与input pin连接之后才能调用

 

  *.  检查output pin 类型是否兼容input pin,调用

      CTransformFilter::CheckTransform

 

 

 

Step 4. Set Allocator Properties(设置allocator属性)

  对于一个transform filter,其input pin 接受上游filter所确定了在input pin内部的allocator.

  1.如果下游filter能够提供一个allocator,output pin就利用它。如果下游filter不能提供呢,那么上游filter 创建一个allocator.

  2.output pin 接收下游filter的allocator 配置,通过调用

      IMemInputPin::GetAllocatorRequirements

  3. output pin配置下游filter的allocator buff大小,通过调用

      CTransformFilter::DecideBufferSize

 

 

Step 5. Transform the Image(传送图像)

  上游filter为了传递samples到下游的transform filter,通过调用:

      IMemInputPin::Receive      

  ,在transform filter中的input pin上

 

 

Transform functon

  HRESULT CRleFilter::Transform(
                  IMediaSample *pSource, 
                  IMediaSample *pDest
                  )
  {    
    // Get pointers to the underlying buffers.    
    BYTE *pBufferIn, *pBufferOut;    
    hr = pSource->GetPointer(&pBufferIn);
        if (FAILED(hr))    
    {        
      return hr;    
    }    
    hr = pDest->GetPointer(&pBufferOut);    
    if (FAILED(hr))    
    {        return hr;    }    
    // Process the data.正式编码    
    DWORD cbDest = EncodeFrame(pBufferIn, pBufferOut);    
    KASSERT((long)cbDest <= pDest->GetSize());
        pDest->SetActualDataLength(cbDest);    
    pDest->SetSyncPoint(TRUE);    
    return S_OK;
}

posted @ 2010-11-03 13:46  hungryMan  阅读(412)  评论(0编辑  收藏  举报