天天看点

提取DirectShow中视频采集的数据

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中的数据.