制作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; }