DirectShow使用大全(zz)

网页 专栏收录该内容
6 篇文章 0 订阅

一使用directshow时应该添加lib文件Strmiids.lib、Quartz.lib 、Strmbase.lib 具体添加那个见下面的说明

Header Files
All DirectShow applications use the Dshow.h header file. Some DirectShow interfaces require additional header files. These requirements are noted in the interface reference.
Library Files
The following table shows the library files DirectShow uses.
Library file Description
Quartz.lib Exports the AMGetErrorText function. If you do not call this function, this library is not required.
Strmbase.lib If you do not use the DirectShow base classes, this library is not required. For information about the difference between Strmbase.lib and Qtzbase.lib, see Building DirectShow Filters 
Strmiids.lib Exports class identifiers (CLSIDs) and interface identifiers (IIDs). All DirectShow applications require this library.
In your build environment, the SDK Include and Lib directories should be the first directories in the search path. This ensures that you are using the most recent versions of these files.
DirectShow初探 <script language=javascript type=text/javascript> document.title="DirectShow初探 - "+document.title </script>
可能到现在为止,还没有哪个玩过游戏的人没有接触过Microsoft的DirectX的。因为现今大多数的游戏都是用DirectX开发出来的。
相比之下,DirectShow只是DirectX的一个子集。DirectX中还包括DirectSound、Direct3D等集合。DirectShow主要用来处理一些与音视频有关的多媒体任务,比如音视频采集、回放等。过年回来后,在一个项目中要求在WIN32下采集视频信号,以前做过GDI的,不过效率低下,而且效果也很烂,所以决定加速,怎样加速,答案就在DirectShow。
1、DirectShow的结构
我们知道,Windows操作系统只用了CPU中的两个特权级(0和3)。0是内核模式,它可以直接访问硬件;3是用户模式,它不能直接访问硬件。DirectShow的基本工作单元是Filter(过滤器),过滤器的就像一个筛子,它一般有输入引脚(PIN)和输出引脚,数据从输入引脚流入而从输出端口流出。DirectShow中的过滤器一般分为下列3类:
       1) Source Filter (用于提供原始的多媒体数据,比如一个视频文件)
       2)Transform Filter(用于处理从Source Filter 传过来的多媒体数据,比如MPEG-4解码器)
       3)Rendering Filter(用于显示、回放和存储多媒体数据给用户,比如文件写入器)
要完成特定的多媒体功能,必须用相应的Filter组成特定的Filter Graph。多媒体数据在Graph中流动,到达Rendering Filter时回放给用户。
用户应用程序怎么样控制Filter Graph呢?他必须创建一个相应的Filter Graph Manager,应用程序向Manager发送相应的命令(Command),然后从Manager那接收相应的Event,最后做出相应的响应。
每个Filter都有操作硬件的能力,这就是为什么DirectShow能如此高效的使用多媒体了。
DirectShow的结构原理图如下:
2、使用DirectShow编写一个简单的应用程序
      使用DirectShow编写应用程序的一般步骤如下:
      1)根据系统完成的功能构建相应的Filter Graph。
      2)构建Graph中的每个Filter,并将它们连接起来。
      3)创建Filter Graph Manager,运用Application控制Manager,从而控制整个的流程。
       4)DirectShow是基于COM(组件对象模型)的,所以在编写Filter前必须初始化COM库。
      下面是一个完整的播放AVI文件的小程序,其中的注解说明了编程的步骤。
#include <stdio.h>
#include <dshow.h>    //DirectShow必须包含的头文件,LIB库为Strmiids.lib 和 Quartz.lib
int main()
{
 IGraphBuilder *pGraph = NULL;      //  用于创建Filter Graph的接口
 IMediaControl *pControl = NULL;    //  用于向Filter Graph Manager发送Command
 IMediaEvent   *pEvent = NULL;        //   用于接收Filter Graph Manager发出的Event
 // Initialize the COM library.
 HRESULT hr = CoInitialize(NULL);   //初始化COM Library
 if( FAILED(hr) )
 {
  fprintf(stderr,"could not init the COM library!");
  return 0;
 }
//创建Filter Graph Manager
hr = CoCreateInstance(CLSID_FilterGraph,NULL,CLSCTX_INPROC_SERVER,IID_IGraphBuilder,(void **)&pGraph);     
 if( FAILED(hr) )
 {
  fprintf(stderr,"could not create Filter Graph Manager!");
  return 0;
 }
 //查询并获得接口指针
 hr = pGraph->QueryInterface(IID_IMediaControl,(void **)&pControl);
 hr = pGraph->QueryInterface(IID_IMediaEvent,(void **)&pEvent);
 // RenderFile库函数是少数几个能够自动创建Graph的成页,所以这里省去了创建Graph这一步
 hr = pGraph->RenderFile(L"e://football.avi",NULL);
 if( SUCCEEDED(hr) )
 {
  hr = pControl->Run();
  if( SUCCEEDED(hr) )
  {
   // 等待视频结束
   long evCode;
   pEvent->WaitForCompletion(INFINITE, &evCode);
   // 无限等待
  }
  
 }
 pControl->Release();
 pEvent->Release();
 pGraph->Release();
//释放接口
 CoUninitialize();   //御载COM 库

 return 0;
}
三、
用DirectShow实现视频采集 <script language=javascript type=text/javascript> document.title="用DirectShow实现视频采集 - "+document.title </script>
DirectShow作为DirectX的一个子集,它为用户提供了强大、方便的多媒体开接口,并且它拥有直接操作硬件的能力,这使得它的效率远胜于用GDI等图形方式编写的多媒体程序。前面一篇文章已经对DirectShow作了粗略的介绍,阐述了它的原理及一些编程方法。这里结合实践中运用DirectShow实现视频采集(WIN32)来加深对DirectShow的理解和操作能力。
1.系统环境及开发环境
  
l       系统支持DirectX(Win 2K以上系统)
l       VC++ 6.0安装有DirectX SDK(最好与系统支持的DirectX版本相同)
l       视频采集设备(如USB摄像头,本文以USB PC Camera 310P为例)
2.基本思想
DirectShow的基本原理是多媒体数据在过滤器图表(Filter Graph)中流动,通过过滤器图表中各过滤器(Filter)实现在功能,最终实现多媒体数据在渲染过滤器(Vendering Filters)中的显示和回放。
前面我们已经知道,一般过滤器可分为三类:源过滤器(Source Filters)、转换过滤器(Transform Filters)、渲染过滤器(Vendering Filters)。它们分别完成数据提供、数据格式转换(压缩编码等)和数据渲染和回放功能。所以,为了实现在WIN32系统下的视频采集,我们首先要构造出一个适当的过滤器图表,然后通过应用程序对过滤器图表的管理来完成视频采集的功能。  
这里我们一般需要2至3个过滤器。为什么这个数字会不准确呢?那是因为一方面系统采集设备的驱动模型是不确定的(一般有WDM和VFW两种);另一方面同一采集设备它们的Filter会由于驱动程序的差异造成Filter中引脚(Pin)的不一致;还有就是不同总线的采集设备(PCI、USB、AGP)它们的Filter也是不一致的。比如:同为USB摄像头,有些Filter有两个输出引脚(Capture和Preview);而有些Filter则只有一个输出引脚(Capture)。这里Preview引脚用来将做视频预览,Capture引脚用来将输入数据以供编码、保存等用处。
这几个过滤器分别是:
l       Video Capture Filter 采集设备Filter
l       Smart Tee Filter 将没有Preview引脚Filter的Capture引脚分为两支数据流(可选)
l       Video Venderer 视频渲染及回放Filter
通过上面3个过滤器,我们可以构造出一个完整的视频采集过滤器图表(如图1)  
 
                                                                    1
我们也可以对上面的过滤器图表稍做修改,将它变为一个既可以预览视频,又可以将视频保存为媒体文件的图表(如图2)。
 
                                                                    2
图表构造出来后,接下来就午剩下具体的实现了,我们只需依次构造每个Filter,然后将各信Filter的Pin按序相连即可完成图表的构造。最后,我们通过应用程序向图表发送命令(通过图表管理器完成)来控制整个视频采集的流程。
3.具体实现
首先我们需要创建几个接口全局变量。
IGraphBuilder *pGraph;   //过滤器图表管理器
ICaptureGraphBuilder2 *pBuild; //视频采集过滤器图表
IBaseFilter *pCap;   //Video Capture Filter
IBaseFilter *pSmartTee;   //Smart Tee Filter
IBaseFilter *pRender; //Video Renderer Filter
IMediaControl *pControl; //用户命令接口,用来控制过滤器图表
IMediaEvent *pEvent;     //过滤器图表事件接口
1) 采集设备枚举
在构造Video Capture Filter前,我们必须列举出系统的所有采集设备,然后才能根据列举的设备名称创建Video Capture Filter。列举设备的函数实现如下
bool ListCaptureDevices()
{
       ICreateDevEnum *pDevEnum = NULL; //设备枚举器Interface
       IEnumMoniker *pEnum = NULL;       //名称枚举Interface
       // Create the System Device Enumerator.
       HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum, NULL,
    CLSCTX_INPROC_SERVER, IID_ICreateDevEnum,
    reinterpret_cast<void**>(&pDevEnum)); //创建设备枚举COM对象
      
       if (SUCCEEDED(hr))
       {
              // Create an enumerator for the video capture category.
              hr = pDevEnum->CreateClassEnumerator(
                      CLSID_VideoInputDeviceCategory,
                      &pEnum, 0);       //创建视频采集设备枚举COM对象
       }
      
       IMoniker *pMoniker = NULL;
       if(pEnum == NULL)
       {
              return false; //如果没有设备,返回
       } 
       while (pEnum->Next(1, &pMoniker, NULL) == S_OK) //依次枚举,直至为空
       {
             
              IPropertyBag *pPropBag;
              hr = pMoniker->BindToStorage(0, 0, IID_IPropertyBag,
                  (void**)(&pPropBag));
              if (FAILED(hr))
              {
                  pMoniker->Release();
                  continue; // Skip this one, maybe the next one will work.
              }
               // Find the description or friendly name.
              VARIANT varName;
              VariantInit(&varName);
              hr = pPropBag->Read(L"Description", &varName, 0);
              if (FAILED(hr))
              {
                     hr = pPropBag->Read(L"FriendlyName", &varName, 0); //设备友好名称
              }
              if (SUCCEEDED(hr))
              {
               // Add it to the application's list box.
                     char displayName[1024];
                     WideCharToMultiByte(CP_ACP,0,varName.bstrVal,-1,displayName,1024,"",NULL);
                     m_nList.AddString(displayName); //字符转换,枚举名称均为UNICODE码  
                     VariantClear(&varName);
              }
              pPropBag->Release();
              pMoniker->Release();
       }
       return true;
}
2)创建Video Capture Filter
根据枚举出来的设备友好名称(FriendlyName)创建Video Capture Filter。
bool CTest_capDlg::CreateHardwareFilter(const char * friendlyName)
{   //将friendlyName与所有的设备名称依次对比,如果相同,则创建Filter
       ICreateDevEnum * enumHardware = NULL;
 HRESULT hr = CoCreateInstance(CLSID_SystemDeviceEnum,NULL,CLSCTX_ALL
,IID_ICreateDevEnum,(void **)&enumHardware);  
       if( FAILED(hr) )
       {
              return false;
       }
       IEnumMoniker * enumMoniker = NULL; 
       hr = enumHardware->CreateClassEnumerator(CLSID_VideoInputDeviceCategory,&enumMoniker,0); 
       if(enumMoniker)
       {
              enumMoniker->Reset();
              ULONG fetched = 0;
              IMoniker * moniker = NULL;
              char friendlyName[256];
              while(!pCap && SUCCEEDED(enumMoniker->Next(1,&moniker,&fetched)) && fetched)
              {
                     if(moniker)
                     {
                            IPropertyBag * propertyBag = NULL;
                            VARIANT name;
                            friendlyName[0]=0;
                            hr=moniker->BindToStorage(0,0,IID_IPropertyBag,(void **)&propertyBag);                           
                            if(SUCCEEDED(hr))
                            {
                                   name.vt=VT_BSTR;
                                   hr = propertyBag->Read(L"FriendlyName",&name,NULL);
                            }
                            else
                                   return false;                   
                            if(SUCCEEDED(hr))
                            {           
                                   WideCharToMultiByte(CP_ACP,0,name.bstrVal,-1,friendlyName,256,NULL,NULL);                            
                                   moniker->BindToObject(0,0,IID_IBaseFilter,(void **)&pCap);
                            }
                            else
                                   return false;
                            if(propertyBag)
                            {
                                  propertyBag->Release();
                                   propertyBag=NULL;
                            }
                            moniker->Release();
                     }
              }
              enumMoniker->Release();
       }
       enumHardware->Release();
       return true;
}
3)创建视频采集过滤器图表
DirectX较高版本中一般都为开发者提供了一个ICaptureGraphBuilder2接口,开发者可以通过它方便地创建视频采集过滤器图表,然后再将它添加到IGraphBuilder图表管理器中(如图3)。                                                                
                        
                   3
bool InitCaptureGraphBuilder()
{
       HRESULT hr = CoCreateInstance(CLSID_CaptureGraphBuilder2, NULL,
        CLSCTX_INPROC_SERVER, IID_ICaptureGraphBuilder2, (void**)&pBuild); 
       if(FAILED(hr))
              return false;
       hr = CoCreateInstance(CLSID_FilterGraph, 0, CLSCTX_INPROC_SERVER,
            IID_IGraphBuilder, (void**)&pGraph);
       if(FAILED(hr))
       {
              pBuild->Release();
              return false;
       }
       pBuild->SetFiltergraph(pGraph);   / 过滤器图表添加到管理器中  
       pGraph->QueryInterface(IID_IMediaControl,(void **)&pControl);
       pGraph->QueryInterface(IID_IMediaEvent,(void **)&pEvent);
       return true;
}
4)创建剩余的Smart Tee和Video Renderer Filter并连接成完整的图表  
在创建完Video Capture Filter后,我们需要将Filter添加到过滤器图表中。
pGraph->AddFilter(pCap,L"Capture Filter");
然后,我们创建剩余的Filter并相连即可,值得注意的是:ICaptureGraphBuilder2为用户提供了一个RenderStream函数,它可以自动构建Smart Tee和Video Renderer Filter并将它们连接成一个完整的图表,从而完成视频采集的功能。
pBuild->RenderStream(&PIN_CATEGORY_PREVIEW, &MEDIATYPE_Video,
    pCap, NULL, NULL);
为了说明整个过程,这里我们按部就搬,依次创建各个Filter。
Smart Tee
CoCreateInstance(CLSID_SmartTee,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void **)&pSmartTee);
Video Renderer Filter
CoCreateInstance(CLSID_VideoRenderer,NULL,CLSCTX_INPROC_SERVER,IID_IBaseFilter,(void **)&pRender);  
创建好各个Filter后,我们依次取得它们的引脚(Pin),将它们按序相连即可。
IPin * GetSmartTeeInputPin() //取得Smart Tee 输入引脚
{
       if(pSmartTee)
       {
              IPin * pPin;
              HRESULT hr = pSmartTee->FindPin(L"Input",&pPin);
              if(SUCCEEDED(hr))
              {
                     pPin->Release();
                     return pPin;
              }
       }
       return NULL;
}
IPin * GetSmartTeeCapturePin() //取得Smart Tee Capture引脚
{
       if(pSmartTee)
       {
              IPin * pPin;
              HRESULT hr = pSmartTee->FindPin(L"Capture",&pPin);
              if(SUCCEEDED(hr))
              {
                     pPin->Release();
                     return pPin;
              }
       }
       return NULL;
}
IPin * GetSmartTeePreviewPin() //取得Smart Tee Preview引脚
{
       if(pSmartTee)
       {
              IPin * pPin;
              HRESULT hr = pSmartTee->FindPin(L"Preview",&pPin);
              if(SUCCEEDED(hr))
              {
                     pPin->Release();
                     return pPin;
              }
       }
       return NULL;
}
IPin * GetRendererPin() //取得Video Renderer Filter的输入Pin
{
       if(pBuild)
       {
              IPin * pPin;
              HRESULT hr = pBuild->FindPin(pRender,PINDIR_INPUT,NULL,NULL,FALSE,0,&pPin);
              if(SUCCEEDED(hr))
              {
                     pPin->Release();
                     return pPin;
              }
       }
       return NULL;
将各个引脚按序连接:
IPin * pOut = FindVideoPin(&PIN_CATEGORY_CAPTURE);
IPin * pIn = GetSmartTeeInputPin();
pGraph->Connect(pOut,pIn); //Video Capture Filter’ Capture Pin à Smart Tee’Input Pin
IPin * mOut = GetSmartTeePreviewPin(); 
IPin * mIn = GetRendererPin();                 
      
             
pGraph->Connect(mOut,mIn); //Smart Tee’s Preview Pin à Video Renderer Filter’s Input Pin
这样,一个完整的视频采集图表管理器就构造完成了。
5)开始视频采集
通过用户命令接口,我们可以方便的完成开始,暂停,停止视频采集。
pControl->Run();
pControl->Stop();  
4.小结
通过上述视频采集过程的实现,不难发现DirectShow是一个流程清晰,开发容易的多媒体开发工具。我们在使用DirectX为我们提供的Filter构建多媒体功能的同时,也可以自己着手创建具备特定功能的Filter。总之,Direct系统还是一个巨大的宝藏,等待着我们去发掘和开采。

 四

提取DirectShow中视频采集的数据. <script language=javascript type=text/javascript> document.title="提取DirectShow中视频采集的数据. - "+document.title </script>
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中的数据.

怎样改变DirectShow中采集的视频大小. <script language=javascript type=text/javascript> document.title="怎样改变DirectShow中采集的视频大小. - "+document.title </script>
在利用Directshow采集视频的过程中,一般初始化时我们要给Capture Graph视频参数..比如它的长和宽,亮度什么的...当然,如果你什么都不给,DirectShow会为你分配一个系统默认的值..这里介绍如何在初始化时改变采集的视频的长和宽..
1.定义IAMStreamConfig Interface
IAMStreamConfig *pConfig;
2.初始化IAMStreamConfig Interface
hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,pCap,IID_IAMStreamConfig,(void **)&pConfig);
// 这pBuild是一个ICaptureGraphBuilder2 Interface.
  if( hr != NOERROR )
  {
   hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pCap,IID_IAMStreamConfig,(void **)&pConfig);
   if(hr == NOERROR)
    AfxMessageBox("load config filter succeed!");
   else
   {
    AfxMessageBox("load config filter failed!");
    return;
   }
  }
3.设置参数(取原来的参数,修改想要改变的部分)
AM_MEDIA_TYPE * mmt;
pConfig->GetFormat(&mmt);    //取得默认参数
VIDEOINFOHEADER * vvih = (VIDEOINFOHEADER*) mmt->pbFormat;
AM_MEDIA_TYPE * pmt = mmt;
VIDEOINFOHEADER * pvih = (VIDEOINFOHEADER*) pmt->pbFormat;
pvih->bmiHeader.biHeight=288;  //修改采集视频的高为288
pvih->bmiHeader.biWidth=352;   //修改采集视频的宽为352
pmt->pbFormat = (unsigned char *) pvih;
pConfig->SetFormat(pmt);   //重新设置参数
这样,DirectShow采集的视频的Data Flow被设置为宽为352,高为288..

怎样改变DirectShow中采集的视频大小. <script language=javascript type=text/javascript> document.title="怎样改变DirectShow中采集的视频大小. - "+document.title </script>
在利用Directshow采集视频的过程中,一般初始化时我们要给Capture Graph视频参数..比如它的长和宽,亮度什么的...当然,如果你什么都不给,DirectShow会为你分配一个系统默认的值..这里介绍如何在初始化时改变采集的视频的长和宽..
1.定义IAMStreamConfig Interface
IAMStreamConfig *pConfig;
2.初始化IAMStreamConfig Interface
hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Interleaved,pCap,IID_IAMStreamConfig,(void **)&pConfig);
// 这pBuild是一个ICaptureGraphBuilder2 Interface.
  if( hr != NOERROR )
  {
   hr = pBuild->FindInterface(&PIN_CATEGORY_CAPTURE,&MEDIATYPE_Video,pCap,IID_IAMStreamConfig,(void **)&pConfig);
   if(hr == NOERROR)
    AfxMessageBox("load config filter succeed!");
   else
   {
    AfxMessageBox("load config filter failed!");
    return;
   }
  }
3.设置参数(取原来的参数,修改想要改变的部分)
AM_MEDIA_TYPE * mmt;
pConfig->GetFormat(&mmt);    //取得默认参数
VIDEOINFOHEADER * vvih = (VIDEOINFOHEADER*) mmt->pbFormat;
AM_MEDIA_TYPE * pmt = mmt;
VIDEOINFOHEADER * pvih = (VIDEOINFOHEADER*) pmt->pbFormat;
pvih->bmiHeader.biHeight=288;  //修改采集视频的高为288
pvih->bmiHeader.biWidth=352;   //修改采集视频的宽为352
pmt->pbFormat = (unsigned char *) pvih;
pConfig->SetFormat(pmt);   //重新设置参数
这样,DirectShow采集的视频的Data Flow被设置为宽为352,高为288..

 

提取DirectShow中视频采集的数据. <script language=javascript type=text/javascript> document.title="提取DirectShow中视频采集的数据. - "+document.title </script>
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中的数据.

 四

提取DirectShow中视频采集的数据. <script language=javascript type=text/javascript> document.title="提取DirectShow中视频采集的数据. - "+document.title </script>
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中的数据.

提取DirectShow中视频采集的数据. <script language=javascript type=text/javascript> document.title="提取DirectShow中视频采集的数据. - "+document.title </script>
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中的数据.

 
  • 0
    点赞
  • 0
    评论
  • 0
    收藏
  • 一键三连
    一键三连
  • 扫一扫,分享海报

内容非常详尽,是一个公司的内部培训资料,详细说明了如何使用DirectShow开发视频。绝对超值!!! 1 ABOUT DIRECTSHOW 基础..............................................................................................................7 1.1 设置DSHOW的开发环境.................................................................................................................7 1.2 先演示一下DSHOW 使用的一个例子.............................................................................................8 1.3 DIRECSHOW概述...............................................................................................................................8 1.4 FILTER GRAPH 及其组成...................................................................................................................8 1.5 构建一个FILTER GRAPH 图............................................................................................................15 1.6 数据流在FILTER GRAPH 里的流动(DATA FLOW) .....................................................................15 1.7 事件通知机制(EVENT NOTIFICATION).......................................................................................19 1.8DIRECTSHOW中的时钟(TIME AND CLOCKS IN DSHOW).............................................................21 1.9 动态删除或增加FILTER(DYNAMIC GRAPH BUILDING).............................................................23 1.10 PLUG-IN DISTRIBUTORS .................................................................................................................25 2 DIRECTSHOW 的应用(USING DIRECTSHOW)......................................................................25 2.1 在GRAPHEDIT 中模拟构建GRAPH(SIMULATING GRAPH BUILDING) .......................................25 2.2DIRECTSHOW基本应用(BASIC TASKS).......................................................................................33 2.2.1 视频提交(Video Rendering) ...............................................................................................33 2.2.2 如何处理事件通知(Event Notification) ............................................................................36 2.2.3 如何枚举系统的设备和过虑器..............................................................................................37 2.2.4 如何枚举Graph 图中的对象(filter,pin) .........................................................................41 2.2.5 构建Graph 图常用技术.........................................................................................................43 2.2.5.1 如何根据CLSID 向graph 中添加filter..............................................................................43 2.2.5.2 如何查找filter 空闲的pin。...............................................................................................44 2.2.5.3 如何连接两个Filter.............................................................................................................45 2.2.5.4 如何获得filter 或者pin 的接口指针..................................................................................47 2.2.5.5 如何查找和某个filter 的上下相连的filter.........................................................................49 2.2.5.6 如何删除graph 中的所有filter...........................................................................................52 2.2.5.7 如何利用Capture Graph Builder 构建Graph 图表...........................................................53 2.2.6 Seeking Filter graph.................................................................................................................55 2.2.7 如何设置Graph 时钟(Setting Graph Clock) ....................................................................57 2.2.8 在Dshow 中如何调试.............................................................................................................58 2.3 音频的捕捉....................................................................................................................................58 2.4 视频的捕捉(VIDEO CAPTURE)...................................................................................................59 2.4.1 关于视频捕捉(About Video Capture in Dshow).................................................................59 2.4.2 选择一个视频捕捉设备(Select capture device) ................................................................63 2.4.3 预览视频(Previewing Video) ..............................................................................................65 2.4.4 如何捕捉视频流并保存到文件(Capture video to File) ....................................................65 2.4.5 如何控制Capture Graph(Controlling Capture Graph) .....................................................69 2.4.6 视频捕捉的任务(Video Capture Tasks) .............................................................................71 2.4.6.1 如何配置一个视频捕捉设备...............................................................................................71 2.4.6.2Working With Crossbars .........................................................................................................74 DirectShow SDK 学习笔记作者:智慧的鱼 中华视频网整理 - 3 - 2.4.6.3 将设备从系统中移走时的事件通知(Device remove Notify) .........................................74 2.4.6.4 从静止图像pin 中捕捉图片................................................................................................75 2.4.7 数字视频DV(Digital Video in Direcshow) ........................................................................78 2.4.7.1 关于Directshow 中的DV 应用...........................................................................................78 2.4.7.2 如何将DV 捕捉到一个文件中............................................................................................78 2.4.7.3 如何将文件中的DV 读入到盘中........................................................................................78 2.4.7.4 DVINFO Field Settings in the MSDV Driver ........................................................................78 2.4.8 如何控制DV 便携式摄像机(Controlling a DV Camcorder) ...........................................78 2.4.9 模拟电视的视频捕捉(Analog Television)..........................................................................78 2.4.10 视频捕捉的高级话题............................................................................................................78 2.4.10.1 处理视频重画事件.............................................................................................................78 2.4.10.2 如何确定pin 的种类(Pin Categories) ..........................................................................79 2.4.10.3 如何使用一个SmartTee Filer ............................................................................................81 2.4.10.4 如何使用一个重叠混合器(Overlay Mixer in Video Capture) ......................................81 2.4.10.5Video Port Pins.....................................................................................................................81 2.4.10.6VideoInfo2 Format Type .......................................................................................................81 2.4.10.7 手动添加WDM类驱动filter.............................................................................................81 2.4.10.8 如何创建内核filter ............................................................................................................83 2.5DIRECTSHOW EDITING SERVICES ......................................................................................................85 2.6DVD 应用(DVDAPPLICATION) ..................................................................................................85 2.7MPEP_2 支持.................................................................................................................................85 2.8WINDOWS MEDIA 应用.....................................................................................................................85 2.9 TV 应用..........................................................................................................................................85 2.10 使用视频混合RENDER.................................................................................................................86 2.11 USING THE STREAM BUFFER ENGINE .............................................................................................86 2.12 开发自己的FILTER.......................................................................................................................86 1 如何开发自己的filter ..................................................................................................................86 2filter 的连接...................................................................................................................................95 3filter 间的数据流动........................................................................................................................98 4pin 连接时数据格式的动态改变.................................................................................................101 4 Threads and Critical Sections ......................................................................................................101 5 质量控制管理..............................................................................................................................107 6dshow 和com...............................................................................................................................107 7 如何写Transform Filter ..............................................................................................................120 8 如何写视频播放过滤器Video Renderer Filter ..........................................................................131 9 如何写捕捉filter(源) .............................................................................................................137 10 创建filter 属性页.....................................................................................................................141 11 capture and compression formats ...............................................................................................148 12Graph 如何定位filter 的位置并加载........................................................................................150 2.13 ENCODER AND DECODER 开发.....................................................................................................150 3DIRECTSHOW 的基类学习..............................................................................................................150 3.1 DSHOW的基类简介......................................................................................................................150 3.2 FILTER 和PIN 的基类....................................................................................................................153 3.2.1CBaseFilter .............................................................................................................................153 DirectShow SDK 学习笔记作者:智慧的鱼 中华视频网整理 - 4 - 3.2.2CBasePin................................................................................................................................159 3.2.3CBaseInputPin ........................................................................................................................168 3.2.4CBaseOutputPin.....................................................................................................................172 3.3 几种常用FILTER 的基类..............................................................................................................176 3.3.1CSource ..................................................................................................................................176 3.3.2CSourceStream.......................................................................................................................178 3.3.3CTransformFilter ....................................................................................................................182 3.3.4CTransformInputPin...............................................................................................................188 3.3.5CTransformOutputPin............................................................................................................189 3.3.6CTransInPlaceFilter...............................................................................................................191 3.3.7 CTransInPlaceInputPin..........................................................................................................193 3.3.8CTransInPlaceOutputPin.......................................................................................................193 3.3.4CVideoTransformFilter ...........................................................................................................193 3.3.9CBaseRenderer.......................................................................................................................194 3.3.10CRendererInputPin ...............................................................................................................205 3.3.11CBaseVideoRenderer .............................................................................................................206 3.3.12 CBaseAllocator ....................................................................................................................210 3.3.13 CMediaSample .....................................................................................................................212 3.4FILTER 和PIN 经常用到的类.........................................................................................................214 3.4.1CPullPin.................................................................................................................................214 3.4.2COutputQueue........................................................................................................................216 3.4.3CSourceSeeking......................................................................................................................216 3.4.4CEnumPins.............................................................................................................................216 3.4.5CEnumMediaTypes.................................................................................................................216 3.4.6CMemAllocator .......................................................................................................................216 3.4.7CMediaSample ........................................................................................................................216 3.4.8CBaseReferenceClock .............................................................................................................219 3.4.9CMediaType ............................................................................................................................219 3.5 几个比较重要的类.......................................................................................................................219 4DIRECSHOW 提供的接口学习.........................................................................................................220 5DIRECTSHOW TUTORIALS...........................................................................................................220 5.1IMPLEMENTING A SEEK BAR............................................................................................................220 5.2DISPLAYING A FILTER'S PROPERTY PAGES .......................................................................................220 5.3GRABBING A POSTER FRAME...........................................................................................................220 5.4USING THE SAMPLE GRABBER ........................................................................................................220 5.5RECOMPRESSING AN AVI FILE.........................................................................................................220 6C++在电视开发中的应用....................................................................................................................220 6.1TV RATINGS REFERENCE ................................................................................................................220 6.2VIDEO CONTROL C++ REFERENCE..................................................................................................220 6.3MICROSOFT UNIFIED TUNING MODEL C++ REFERENCE .................................................................220 6.4TRANSPORT INFORMATION INTERFACES ..........................................................................................220 6.5BDAFILTER INTERFACES................................................................................................................220 DirectShow SDK 学习笔记作者:智慧的鱼 中华视频网整理 - 5 - 6.6MPEG-2 SECTIONS AND TABLES FILTER REFERENCE .....................................................................220 7DIRECSHOW 提供的FILTER .........................................................................................................220
©️2021 CSDN 皮肤主题: 大白 设计师:CSDN官方博客 返回首页
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值