在windowsSDK中有一个推模式的Source Filter例子,位于SDK安装目录samples\C++\Directshow\Ball下。
下面做一下简要分析:
功能:Live Source不断产生视频帧,演示在封闭围墙内碰撞的弹球的运动轨迹。使用该filter构建Filter Graph及其输出结果如下图:
类的继承结构关系为:
CBouncingBall继承自CSource
CBallStream继承自CSourceStream
可以知道,从CSource派生的Filter,它的输出Pin会使用一个数据线程,将Sample不断的推出去,具体实现如下:
//
// DoBufferProcessingLoop
//
// Grabs a buffer and calls the users processing function.
// Overridable, so that different delivery styles can be catered for.
HRESULT CSourceStream::DoBufferProcessingLoop(void) {
Command com;
OnThreadStartPlay();//开始数据传送前调用,子类可以重新实现以进行一些初始化
do {
while (!CheckRequest(&com)) {
IMediaSample *pSample;
<span style="white-space:pre"> </span>//输出Pin上得到一个空的Pin
HRESULT hr = GetDeliveryBuffer(&pSample,NULL,NULL,0);
if (FAILED(hr)) {
Sleep(1);
continue; // go round again. Perhaps the error will go away
// or the allocator is decommited & we will be asked to
// exit soon.
}
// 子类必须实现的一个函数,填写Sample的实际内容
hr = FillBuffer(pSample);
if (hr == S_OK) {
hr = Deliver(pSample);//往下一个filter发送数据
pSample->Release();
// downstream filter returns S_FALSE if it wants us to
// stop or an error if it's reporting an error.
if(hr != S_OK)
{
DbgLog((LOG_TRACE, 2, TEXT("Deliver() returned %08x; stopping"), hr));
return S_OK;
}
} else if (hr == S_FALSE) {
// derived class wants us to stop pushing data
pSample->Release();
DeliverEndOfStream();
return S_OK;
} else {
// derived class encountered an error
pSample->Release();
DbgLog((LOG_ERROR, 1, TEXT("Error %08lX from FillBuffer!!!"), hr))