Chinaunix首页 | 论坛 | 博客
  • 博客访问: 16498995
  • 博文数量: 5645
  • 博客积分: 9880
  • 博客等级: 中将
  • 技术积分: 68081
  • 用 户 组: 普通用户
  • 注册时间: 2008-04-28 13:35
文章分类

全部博文(5645)

文章存档

2008年(5645)

我的朋友

分类:

2008-04-28 21:30:53

下载本文示例代码
  Pin的连接  应用程序通过调用filter 图表管理器的方法来连接filter,并不是来调用filter或者pin本身的函数。应用程序可以调用IFilterGraph::ConnectDirect or IGraphBuilder::Connect来指定不同的filter直接连接,也可以通过IGraphBuilder::RenderFile间接连接。  只有两个filter都在graph里,连接才能成功。应用程序可以通过IFilterGraph::AddFilter将filter 添加graph中,当一个filter被添加到graph中时,filter图表管理器通过IBaseFilter::JoinFilterGraph来通知filter。  Pin连接的大致过程如下:  1、图表管理器首先调用输出pin上的IPin::Connect,然后传递一个指针给输入pin。  2、如果输出pin接受连接的邀请,它就调用输入pin上的IPin::ReceiveConnection。  3、如果输入pin也接受连接邀请,那么连接成功,pin之间的连接ok。  当filter处于活动状态的时候,许多pin可以断开连接和重新连接。这种类型的连接称为动态连接。当然,大多数的filter并不支持动态连接。  Filter通常采用从上游到下游的连接顺序。也就是说filter上的输入pin总是比输出pin先连接。Filter应该支持这种连接顺序。然而有许多filter支持相反的连接顺序,输出pin先连接,输入pin后连接。例如:在连接MUX filter的输入pin之前一定要将MUX filter的输出pin和writer filter连接起来。  当pin的Connect or ReceiveConnection方法被调用的时候,pin必须检查一下自己是否支持这个连接。通常要进行下列检查:  1、检查媒体类型是否匹配。  2、就内存的分配达成一致。  3、请求其他pin的其他接口。  媒体类型匹配  当一个filter 图表管理器调用IPin::Connect方法时,可能有下面的几种媒体类型。  1、完整类型  如果媒体类型每一个部分都定义的很完成,那么pin就严格按照定义的类型类型进行连接。如果不匹配,连接失败。  2、部分媒体类型  如果媒体类型的机构中,major type, subtype, or format type的值为GUID_NULL,这个值是一个通配符号。任何类型都可以匹配。  3、没有媒体类型  如果filter图表管理器传递过来一个NULL的指针,这个pin就可以和任意的类型的媒体类型匹配。   一般在连接过程中,都有一个完整的媒体类型。图表管理器传递媒体类型的目的是为了限制连接类型。  一般来说,都是输出pin通过调用输入pin IPin::ReceiveConnection提供一个媒体类型。输入pin可以拒绝也可以接受这个媒体类型。这个过程一直重复,直到输入pin接受了一个类型,或者输出pin枚举完了它支持的所有的媒体类型,连接失败。  输出pin通过调用输入pin上的IPin::EnumMediaTypes枚举输入pin所支持的媒体类型。  看看如何匹配媒体类型的吧。if ((pmt->formattype == FORMAT_VideoInfo) &&(pmt->cbFormat > sizeof(VIDEOINFOHEADER) &&(pbFormat != NULL)){ VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat; // Now you can dereference pVIH.}  Pin连接中的内存分配  当两个pin连接起来后,他们需要一种机制来交换媒体数据。大多数数据交换采用的局部内存交换机制。所有的媒体数据都在主内存中。DirectShow为局部存储器传输定义了两种机制:推模式(push model)和拉模式(pull model)。在推模式中,源过滤器生成数据并提交给下一级过滤器。下一级过滤器被动的接收数据,完成处理后再传送给再下一级过滤器。在拉模式中,源过滤器与一个分析过滤器相连。分析过滤器向源过滤器请求数据后,源过滤器才传送数据以响应请求。推模式使用的是IMemInputPin接口,拉模式使用IAsyncReader接口,推模式比拉模式要更常用。  在局部存储器传输中,负责分配内存的对象称为allocator。每个allocator都支持一个IMemAllocator接口。所有的pin都共享一个allocator。  每个pin都提供一个allocator,但是输出pin选择使用哪个allocator。  输出pin可以设置allocator的属性。比如,分配内存的大小,在IMemInputPin连接中,allocator工作过程如下:  1、首先,输出pin调用IMemInputPin::GetAllocatorRequirements,这个方法检查输入pin对内存的要求,比如内存的队列,一般来说,输出pin要满足输入pin对内存的要求。  2、输出pin然后调用IMemInputPin::GetAllocator.,这个方法从输入pin请求一个allocator。  3、输出pin选择一个allocator,可以是输入pin提供,也可以是自己生产的。  4、输出pin调用IMemAllocator::SetProperties来设置allocator的属性。  5、然后输出pin通过IMemInputPin::NotifyAllocator来通知输入pin,选择的allocator。  6、输入pin通过IMemAllocator::GetProperties来检查是否能够接受allocator的属性。  7、当数据流开始和停止的时候,输出pin负责提交allocator。  在IAsyncReader连接过程如下:  1、输入pin调用输出pin上的IAsyncReader::RequestAllocator,输入pin确定内存的属性,并提供一个allocator。  2、输出pin选择一个allocator  3、输入pin检查   如何提供一个自定义的allocator  这里只讲一下IMemInputPin连接,IAsyncReader类似。  首先,定义一个C 类,你的allocator应该从一个标准的allocator类中派生,比如CBaseAllocator or CMemAllocator,你也可以自己创建一个新的allocator类,如果你是新建的类,你必须支持IMemAllocator接口。  下面看看在输入pin和输出pin中如何使用你定义的allocator。  在输入pin中提供allocator  在输入pin中提供allcator,必须重载CBaseInputPin::GetAllocator方法。在这个方法里,首先检查m_pAllocator是否可用,如果为非空,就表明allocator已经被选中,所以直接返回这个allocator指针即可,如果m_pAllocator为空,表明allocator还没有被选中,所以,就要返回输入pin的allocator,因此,创建一个allcaotor的实例,返回IMemAllocator接口。  看下面的代码把STDMETHODIMP CMyInputPin::GetAllocator(IMemAllocator **ppAllocator){ CheckPointer(ppAllocator, E_POINTER); if (m_pAllocator)  {   // We already have an allocator, so return that one.  *ppAllocator = m_pAllocator;  (*ppAllocator)->AddRef();  return S_OK; } // No allocator yet, so propose our custom allocator. The exact code // here will depend on your custom allocator class definition. HRESULT hr = S_OK; CMyAllocator *pAlloc = new CMyAllocator(&hr); if (!pAlloc) {  return E_OUTOFMEMORY; } if (FAILED(hr)) {  delete pAlloc;  return hr; } // Return the IMemAllocator interface to the caller. return pAlloc->QueryInterface(IID_IMemAllocator, (void**)ppAllocator);}  当输出pin选择一个allocator,它就调用输入pin的IMemInputPin::NotifyAllocator,因此,要重载CBaseInputPin::NotifyAllocator方法来检查allocator的属性。  在输出pin中如何提供一个定制的Allocator  在输出pin中提供一个allcator,要重载CBaseOutputPin::InitAllocator。HRESULT MyOutputPin::InitAllocator(IMemAllocator **ppAlloc){ HRESULT hr = S_OK; CMyAllocator *pAlloc = new CMyAllocator(&hr); if (!pAlloc) {  return E_OUTOFMEMORY; } if (FAILED(hr)) {  delete pAlloc;  return hr; } // Return the IMemAllocator interface. return pAlloc->QueryInterface(IID_IMemAllocator, void**)ppAllocator);}}  缺省情况下CBaseOutputPin首先从输入pin中申请一个allocator。   Pin的连接  应用程序通过调用filter 图表管理器的方法来连接filter,并不是来调用filter或者pin本身的函数。应用程序可以调用IFilterGraph::ConnectDirect or IGraphBuilder::Connect来指定不同的filter直接连接,也可以通过IGraphBuilder::RenderFile间接连接。  只有两个filter都在graph里,连接才能成功。应用程序可以通过IFilterGraph::AddFilter将filter 添加graph中,当一个filter被添加到graph中时,filter图表管理器通过IBaseFilter::JoinFilterGraph来通知filter。  Pin连接的大致过程如下:  1、图表管理器首先调用输出pin上的IPin::Connect,然后传递一个指针给输入pin。  2、如果输出pin接受连接的邀请,它就调用输入pin上的IPin::ReceiveConnection。  3、如果输入pin也接受连接邀请,那么连接成功,pin之间的连接ok。  当filter处于活动状态的时候,许多pin可以断开连接和重新连接。这种类型的连接称为动态连接。当然,大多数的filter并不支持动态连接。  Filter通常采用从上游到下游的连接顺序。也就是说filter上的输入pin总是比输出pin先连接。Filter应该支持这种连接顺序。然而有许多filter支持相反的连接顺序,输出pin先连接,输入pin后连接。例如:在连接MUX filter的输入pin之前一定要将MUX filter的输出pin和writer filter连接起来。  当pin的Connect or ReceiveConnection方法被调用的时候,pin必须检查一下自己是否支持这个连接。通常要进行下列检查:  1、检查媒体类型是否匹配。  2、就内存的分配达成一致。  3、请求其他pin的其他接口。  媒体类型匹配  当一个filter 图表管理器调用IPin::Connect方法时,可能有下面的几种媒体类型。  1、完整类型  如果媒体类型每一个部分都定义的很完成,那么pin就严格按照定义的类型类型进行连接。如果不匹配,连接失败。  2、部分媒体类型  如果媒体类型的机构中,major type, subtype, or format type的值为GUID_NULL,这个值是一个通配符号。任何类型都可以匹配。  3、没有媒体类型  如果filter图表管理器传递过来一个NULL的指针,这个pin就可以和任意的类型的媒体类型匹配。   一般在连接过程中,都有一个完整的媒体类型。图表管理器传递媒体类型的目的是为了限制连接类型。  一般来说,都是输出pin通过调用输入pin IPin::ReceiveConnection提供一个媒体类型。输入pin可以拒绝也可以接受这个媒体类型。这个过程一直重复,直到输入pin接受了一个类型,或者输出pin枚举完了它支持的所有的媒体类型,连接失败。  输出pin通过调用输入pin上的IPin::EnumMediaTypes枚举输入pin所支持的媒体类型。  看看如何匹配媒体类型的吧。if ((pmt->formattype == FORMAT_VideoInfo) &&(pmt->cbFormat > sizeof(VIDEOINFOHEADER) &&(pbFormat != NULL)){ VIDEOINFOHEADER *pVIH = (VIDEOINFOHEADER*)pmt->pbFormat; // Now you can dereference pVIH.}  Pin连接中的内存分配  当两个pin连接起来后,他们需要一种机制来交换媒体数据。大多数数据交换采用的局部内存交换机制。所有的媒体数据都在主内存中。DirectShow为局部存储器传输定义了两种机制:推模式(push model)和拉模式(pull model)。在推模式中,源过滤器生成数据并提交给下一级过滤器。下一级过滤器被动的接收数据,完成处理后再传送给再下一级过滤器。在拉模式中,源过滤器与一个分析过滤器相连。分析过滤器向源过滤器请求数据后,源过滤器才传送数据以响应请求。推模式使用的是IMemInputPin接口,拉模式使用IAsyncReader接口,推模式比拉模式要更常用。  在局部存储器传输中,负责分配内存的对象称为allocator。每个allocator都支持一个IMemAllocator接口。所有的pin都共享一个allocator。  每个pin都提供一个allocator,但是输出pin选择使用哪个allocator。  输出pin可以设置allocator的属性。比如,分配内存的大小,在IMemInputPin连接中,allocator工作过程如下:  1、首先,输出pin调用IMemInputPin::GetAllocatorRequirements,这个方法检查输入pin对内存的要求,比如内存的队列,一般来说,输出pin要满足输入pin对内存的要求。  2、输出pin然后调用IMemInputPin::GetAllocator.,这个方法从输入pin请求一个allocator。  3、输出pin选择一个allocator,可以是输入pin提供,也可以是自己生产的。  4、输出pin调用IMemAllocator::SetProperties来设置allocator的属性。  5、然后输出pin通过IMemInputPin::NotifyAllocator来通知输入pin,选择的allocator。  6、输入pin通过IMemAllocator::GetProperties来检查是否能够接受allocator的属性。  7、当数据流开始和停止的时候,输出pin负责提交allocator。  在IAsyncReader连接过程如下:  1、输入pin调用输出pin上的IAsyncReader::RequestAllocator,输入pin确定内存的属性,并提供一个allocator。  2、输出pin选择一个allocator  3、输入pin检查   如何提供一个自定义的allocator  这里只讲一下IMemInputPin连接,IAsyncReader类似。  首先,定义一个C 类,你的allocator应该从一个标准的allocator类中派生,比如CBaseAllocator or CMemAllocator,你也可以自己创建一个新的allocator类,如果你是新建的类,你必须支持IMemAllocator接口。  下面看看在输入pin和输出pin中如何使用你定义的allocator。  在输入pin中提供allocator  在输入pin中提供allcator,必须重载CBaseInputPin::GetAllocator方法。在这个方法里,首先检查m_pAllocator是否可用,如果为非空,就表明allocator已经被选中,所以直接返回这个allocator指针即可,如果m_pAllocator为空,表明allocator还没有被选中,所以,就要返回输入pin的allocator,因此,创建一个allcaotor的实例,返回IMemAllocator接口。  看下面的代码把STDMETHODIMP CMyInputPin::GetAllocator(IMemAllocator **ppAllocator){ CheckPointer(ppAllocator, E_POINTER); if (m_pAllocator)  {   // We already have an allocator, so return that one.  *ppAllocator = m_pAllocator;  (*ppAllocator)->AddRef();  return S_OK; } // No allocator yet, so propose our custom allocator. The exact code // here will depend on your custom allocator class definition. HRESULT hr = S_OK; CMyAllocator *pAlloc = new CMyAllocator(&hr); if (!pAlloc) {  return E_OUTOFMEMORY; } if (FAILED(hr)) {  delete pAlloc;  return hr; } // Return the IMemAllocator interface to the caller. return pAlloc->QueryInterface(IID_IMemAllocator, (void**)ppAllocator);}  当输出pin选择一个allocator,它就调用输入pin的IMemInputPin::NotifyAllocator,因此,要重载CBaseInputPin::NotifyAllocator方法来检查allocator的属性。  在输出pin中如何提供一个定制的Allocator  在输出pin中提供一个allcator,要重载CBaseOutputPin::InitAllocator。HRESULT MyOutputPin::InitAllocator(IMemAllocator **ppAlloc){ HRESULT hr = S_OK; CMyAllocator *pAlloc = new CMyAllocator(&hr); if (!pAlloc) {  return E_OUTOFMEMORY; } if (FAILED(hr)) {  delete pAlloc;  return hr; } // Return the IMemAllocator interface. return pAlloc->QueryInterface(IID_IMemAllocator, void**)ppAllocator);}}  缺省情况下CBaseOutputPin首先从输入pin中申请一个allocator。 下载本文示例代码


DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接DirectShow学习指南之Filter的连接
阅读(265) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~