如何写filter的转帖 之 ----开发source filter的source sourcestream两个基类介绍

转贴地址:http://www.cnblogs.com/wqj1212/archive/2012/04/09/2439692.html

第一个是source,第二个是sourcestream

3.3几种常用Filter的基类 
3.3.1CSource 
class CSource : public CBaseFilter { 
public: 
CSource(TCHAR *pName, LPUNKNOWN lpunk, CLSID clsid, HRESULT *phr); 
CSource(TCHAR *pName, LPUNKNOWN lpunk, CLSID clsid); 
#ifdef UNICODE 
CSource(CHAR *pName, LPUNKNOWN lpunk, CLSID clsid, HRESULT *phr); 
CSource(CHAR *pName, LPUNKNOWN lpunk, CLSID clsid); 
#endif 
~CSource();

int GetPinCount(void); 
CBasePin *GetPin(int n);

CCritSec* pStateLock(void) { return &m_cStateLock; } 
HRESULT AddPin(CSourceStream *); 
HRESULT RemovePin(CSourceStream *);

STDMETHODIMP FindPin(LPCWSTR Id,IPin ** ppPin );

int FindPinNumber(IPin *iPin);

protected:

int m_iPins; 
CSourceStream **m_paStreams; // the pins on this filter. 
CCritSec m_cStateLock; // Lock this to serialize 
};

CSource类是开发源Filter的基类,一个从从CSource类派生的Filter一般都支持一个或者几个从CSourceSteam类派生的输出pin。每一个输出pin都创建了一个工作线程用来将数据传递给下游的Filter。 
为了生产一个输出pin,请按照如下的步骤 
1 从CSoureceStream类派生一个类。 
2重载CSourceStream::GetMediaType和CSourceStream::CheckMediaType方法。 
3重载CBaseOutputPin::DecideBufferSize,这个方法将返回pin的buffer要求 
4重载CSourceStream::FillBuffer,这个方法用来产生数据流,将数据填充到buffer中 
为了派生一个源Filter,可以按照下面的步骤来做 
1从CSourec类派生一个类。 
2在构造函数中创建一个或者多个的输出pin。注意,这个pin要从CSourceStream派生哦。这些pin会在他们的构造函数中自动将自己添加到Filter中。并且在他们的析构函数种从Filter中删除Pin。 
为了在多线程中同步Filter的状态,调用CSource::pStateLock方法,这个方法返回一个指向临界区的指针,通过CAutoLock来生成一个锁,在pin中,你可以通过CBasePin::m_pFilter来指针来操纵临界区保护你的Filter,从而达到同步。例如 
CAutoLock lock(m_pFilter->pStateLock()); 
注意:CSource用来生成推模式的源Filter,如果要读文件,则应该使用拉模式。 
下面我们分析一下CSourec的数据成员 
int m_iPins; 
CSourceStream **m_paStreams; 
CCritSec m_cStateLock; 
总共三个数据成员,一个表示pin的数量,一个pin的数组,用来存放Filter支持的所有的pin,另外一个是临界区对象。 
下面分析方法,也比较简单。 
1CSource::GetPinCount 
这个函数用来返回Filter支持的pin的数目。 
2CSource::GetPin 
CBasePin *GetPin( int n); 
根据指定的序号返回pin的指针。0,1,2,就是从Filter的那个pin数组中返回就是了,根据序号。 
3CCritSec* pStateLock(void); 
返回临界区对象 
4CSource::AddPin 
HRESULT AddPin( CSourceStream *pStream); 
构造函数通常调用这个函数将一个输出pin添加到Filter中。 
5CSource::RemovePin 
HRESULT RemovePin( CSourceStream *pStream); 
析构函数通常通过这个函数将一个输出pin从Filter中删除 
6CSource::FindPinNumber 
int FindPinNumber( IPin *iPin); 
这个函数根据指定的pin的指针,返回他的序号,如果返回-1表示没有这个pin。 
7CSource::FindPin 
HRESULT FindPin( LPCWSTR Id, IPin **ppPin); 
根据指定的ID返回pin。 
注意,Filter的第一个pin ID为1开始,然后是23456789等。

3.3.2CSourceStream 
class CSourceStream : public CAMThread, public CBaseOutputPin { 
public:

CSourceStream(TCHAR *pObjectName, 
HRESULT *phr, 
CSource *pms, 
LPCWSTR pName); 
#ifdef UNICODE 
CSourceStream(CHAR *pObjectName, 
HRESULT *phr, 
CSource *pms, 
LPCWSTR pName); 
#endif 
virtual ~CSourceStream(void); // virtual destructor ensures derived class destructors are called too.

protected:

CSource *m_pFilter; // The parent of this stream

virtual HRESULT FillBuffer(IMediaSample *pSamp) PURE;

virtual HRESULT OnThreadCreate(void) {return NOERROR;}; 
virtual HRESULT OnThreadDestroy(void) {return NOERROR;}; 
virtual HRESULT OnThreadStartPlay(void) {return NOERROR;};

HRESULT Active(void); // Starts up the worker thread 
HRESULT Inactive(void); // Exits the worker thread.

public: 
// thread commands 
enum Command {CMD_INIT, CMD_PAUSE, CMD_RUN, CMD_STOP, CMD_EXIT}; 
HRESULT Init(void) { return CallWorker(CMD_INIT); } 
HRESULT Exit(void) { return CallWorker(CMD_EXIT); } 
HRESULT Run(void) { return CallWorker(CMD_RUN); } 
HRESULT Pause(void) { return CallWorker(CMD_PAUSE); } 
HRESULT Stop(void) { return CallWorker(CMD_STOP); }

protected: 
Command GetRequest(void) { return (Command) CAMThread::GetRequest(); } 
BOOL CheckRequest(Command *pCom) { return CAMThread::CheckRequest( (DWORD *) pCom); }

// override these if you want to add thread commands 
virtual DWORD ThreadProc(void); // the thread function

virtual HRESULT DoBufferProcessingLoop(void); 
virtual HRESULT CheckMediaType(const CMediaType *pMediaType); 
virtual HRESULT GetMediaType(int iPosition, CMediaType *pMediaType); 
virtual HRESULT GetMediaType(CMediaType *pMediaType) {return E_UNEXPECTED;}

STDMETHODIMP QueryId( 
LPWSTR * Id 
); 
};

CSourceStream类用来生成一个输出pin,当然为了CSource配合。 
关于如何使用这个类,可以参看CSource,这个类从CAMThread类继承而来,这个类提供了产生了数据流的工作线程,CSourceStream类通过下面的方法来给线程发送请求。 
CSourceStream::Exit,CSourceStream::Init,CSourceStream::Pause,CSourceStream::Run, 
CSourceStream::Stop 
发给线程的第一个请求一定是Init,Exit请求用来结束线程,实际上,我们没有必要亲自调用这些函数,因为在CSourceStream::Active and CSourceStream::Inactive都调用了所需要的方法。 
这个类也提供几个handler方法 
CSourceStream::OnThreadCreate 
CSourceStream::OnThreadDestroy 
CSourceStream::OnThreadStartPlay 
首先分析一下数据成员 
CSource *m_pFilter; 
靠,就一个数据成员,用来指向这个pin连接的Filter。 
看看成员函数吧, 
1CSourceStream::OnThreadCreate 
virtual HRESULT OnThreadCreate(void); 
线程处理CSourceStream::ThreadProc在第一次接收到Init请求的时候,就会调用这个方法,在基类的实现中,这个函数没有作任何的事情,派生类可以在这个函数中做一些初始化线程的工作。 
2CSourceStream::OnThreadDestroy 
当线程退出的时候,会调用这个函数,基类的实现没有作任何的事情,你可以在派生类中做清理现场的工作。 
3CSourceStream::OnThreadStartPlay 
在CSourceStream::DoBufferProcessingLoop开始的时候,会调用到这个函数 
4CSourceStream::Active 
5CSourceStream::Inactive 
6CSourceStream::GetRequest 
Command GetRequest(void); 
这个函数可以等待下一个线程请求。这个方法重载了CAMThread::GetRequest 
7CSourceStream::CheckRequest 
非阻塞情况下,这个函数用来查询是否有个线程请求 
8CSourceStream::ThreadProc 
这个函数是工作线程的函数体,重载了CAMThread::ThreadProc方法。 
virtual DWORD ThreadProc(void); 
这个函数会无限的等待线程的请求,通过调用CAMThread::GetRequest方法,如果它接收到CSourceStream::Run or CSourceStream::Pause请求,它就调用 
CSourceStream::DoBufferProcessingLoop方法,DoBufferProcessingLoop会一直往外推数据,直到它接收到一个CSourceStream::Stop请求,线程处理器当接收到CSourceStream::Exit请求,就会退出了。 
9CSourceStream::DoBufferProcessingLoop 
virtual HRESULT DoBufferProcessingLoop(void); 
这个方法其实是线程的实现函数,在这个循环中处理数据,并且将数据传递给下下游的Filter,每次,这个方法都会申请一个空的内存sample,然后将这个sample传递给CSourceStream::FillBuffer方法,FillBuffer方法在派生类中一定要实现哦,这个函数是用来产生数据,并将数据拷贝到sample。 
当发生下面的情形时,循环停止,退出 
1 当IMemInputPin::Receive方法拒绝samples。 
2FillBuffer返回False,表示结束发送数据了 
3线程接收到一个CSourceStream::Stop请求。 
10CSourceStream::CheckMediaType 
virtual HRESULT CheckMediaType( const CMediaType *pMediaType); 
确认是否支持指定的媒体类型。 
11CSourceStream::GetMediaType 
virtual HRESULT GetMediaType( int iPosition, CMediaType *pMediaType);

virtual HRESULT GetMediaType( CMediaType *pMediaType); 
获取指定位置的媒体类型。 
12CSourceStream::Init 
HRESULT Init(void); 
这个函数用来启动一个线程,CSourceStream::Active方法会调用这个函数的。 
13CSourceStream::Exit 
The CSourceStream::Inactive method calls this method. 
14CSourceStream::Run 
15CSourceStream::Pause 
CSourceStream::Active会调用这个方法的。当CSourceStream::ThreadProc接收这个请求,它会调用CSourceStream::DoBufferProcessingLoop方法。 
16CSourceStream::Stop 
The CSourceStream::Inactive method calls this method. 
17CSourceStream::FillBuffer 
virtual HRESULT FillBuffer( IMediaSample *pSample) PURE; 
最重要的一个函数。 
派生类中一定要实现这个函数,媒体samples没有给这个方法提供时间戳,派生类应该调用IMediaSample::SetTime方法来设置时间戳。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值