directshow中,数据流(data flow)都是依次流过各个filter的.它对数据的管理也有自己的方法,而且并没有向用户提供一个统一的接口,供用户操作数据流.这里以提取视频采集在的每帧为位图数据为例,说说如何在directshow中提取数据.
这里我们用到了directshow提供给我们的接口isamplegrabber,并定义了一个供它回调的csamplegrabbercb对象(继承isamplegrabbercb接口).
我们知道,directshow中的数据存储是通过sample完成的,所以提取数据也需要通过samplegrabber.
步骤如下:
1.建立csamplegrabbercb对象.
class csamplegrabbercb : public isamplegrabbercb
{
stdmethodimp buffercb( double dblsampletime, byte * pbuffer, long lbuffersize )
{
//callback method that receives a pointer to the sample buffer.
}
stdmethodimp samplecb( double sampletime, imediasample * psample )
{
//callback method that receives a pointer to the media sample.
}
}
2.定义isamplegrabber接口并初始化
ccomptr< isamplegrabber > m_pgrabber;
hresult hr;
hr = m_pgrabber.cocreateinstance( clsid_samplegrabber );
if(failed(hr))
//error action;
3.定义grabber filter,设置它的媒体类型,并将它加入graph中
ccomqiptr< ibasefilter, &iid_ibasefilter > pgrabbase( m_pgrabber );
cmediatype videotype;
videotype.settype(&mediatype_video);
videotype.setsubtype(&mediasubtype_rgb24);
hr = m_pgrabber->setmediatype(&videotype);
hr = pgraph->addfilter(pgrabbase,l"grabber");
4.设置回调(callback),使grabber能够通过buffercb自动完成采集数据.
// don't buffer the samples as they pass through
//
hr = m_pgrabber->setbuffersamples( false );
// only grab one at a time, stop stream after
// grabbing one sample
hr = m_pgrabber->setoneshot( false );
// set the callback, so we can grab the one sample
hr = m_pgrabber->setcallback( &mcb, 1 ); //mcb为csamplegrabber对象
这样,在directshow数据流动过程中,mcb.buffercb会自动执行,提取graph中的数据.