利用Directshow开发源Filter[1]

[入库:2005年8月19日] [更新:2007年3月24日]

本文简介:选择自 aoosang 的 blog

摘要:
我们一般不推荐自己开发音频或者视频捕捉过滤器,因为diectshow对于音视频的捕捉设备以经提供了支持。所以,这篇文档,对于某些用户需要从特定设备捕捉一些数据提供一些帮助。这篇文档主要包括以下内容。
1捕捉filter 对pin的要求
2如何完成一个预览pin
3如何产生源数据

1 对pin的要求pin requirements for capture filters
pin的名字
你可以给你的filter起任何名字,如果你的pin的名字以~符号开头,那么当应用程序调用igraphbuilder::renderfile方法时,filter图表管理器不会自动render这个pin的。例如,如果一个filter具有一个捕捉pin和预览pin,相应的你给他们命名为”~capture”和“preview”。如果一个应用程序在graph中render这个filter ,那么预览pin就会自动和它缺省的render相连接,但是,capture pin上却不连接任何东西,这是一个合理的缺省行为。这个也可以应用到那些传输不准备被rendered数据的pin,也可以应用到需要属性设置的pin上。
注:名字中含有~符号的pin是可以手动连接的。
pin的种类
一个捕捉filter通常用一个捕捉pin,也许还有一个预览pin。一些捕捉filter除了这两种pin之外还有其他的pin,用来传递其他的数据,例如控制信息。每一个输出pin都必须暴露ikspropertyset接口,应用程序通过这些接口来判断pin的种类,pin一般都会返回pin_category_capture or pin_category_preview。下面的例子演示了一个捕捉pin如何通过ikspropertyset来返回pin的种类
// set: cannot set any properties.
hresult cmycapturepin::set(refguid guidpropset, dword dwid,
void *pinstancedata, dword cbinstancedata, void *ppropdata,
dword cbpropdata)
{
return e_notimpl;
}

// get: return the pin category (our only property).
hresult cmycapturepin::get(
refguid guidpropset, // which property set.
dword dwpropid, // which property in that set.
void *pinstancedata, // instance data (ignore).
dword cbinstancedata, // size of the instance data (ignore).
void *ppropdata, // buffer to receive the property data.
dword cbpropdata, // size of the buffer.
dword *pcbreturned // return the size of the property.
)
{
if (guidpropset != ampropsetid_pin)
return e_prop_set_unsupported;
if (dwpropid != amproperty_pin_category)
return e_prop_id_unsupported;
if (ppropdata == null && pcbreturned == null)
return e_pointer;
if (pcbreturned)
*pcbreturned = sizeof(guid);
if (ppropdata == null) // caller just wants to know the size.
return s_ok;
if (cbpropdata < sizeof(guid)) // the buffer is too small.
return e_unexpected;
*(guid *)ppropdata = pin_category_capture;
return s_ok;
}

// querysupported: query whether the pin supports the specified property.
hresult cmycapturepin::querysupported(refguid guidpropset, dword dwpropid,
dword *ptypesupport)
{
if (guidpropset != ampropsetid_pin)
return e_prop_set_unsupported;
if (dwpropid != amproperty_pin_category)
return e_prop_id_unsupported;
if (ptypesupport)
// we support getting this property, but not setting it.
*ptypesupport = ksproperty_support_get;
return s_ok;
}

2如何完成一个预览pin implementing a preview pin (optional)
如果你的filter有一个预览pin,预览pin发送的数据是捕捉pin传递的数据的拷贝。预览pin发送的数据不会降低捕捉pin的桢率,捕捉pin比预览pin有优先权。
捕捉pin和预览pin必须发送一个相同格式的数据。这样,他们连接都是通过同一种媒体数据类型,如果捕捉pin先连接,预览pin应该提供相同的媒体类型,对于其他类型的数据媒体,则拒绝。如果预览pin先连接,然后,如果捕捉pin以另一种媒体类型和其他pin连接,那么预览pin就应该用新的媒体类型重新连接,如果和filter的预览pin连接的下游filter拒绝新的数据类型,捕捉pin应该拒绝新的媒体类型。可以通过ipin::queryaccept方法察看filter的预览pin连接的下游filter连接的数据媒体,然后通过ifiltergraph::reconnect方法重新连接pin。
这条规则也适用于图表管理器重新连接捕捉pin。
下面的代码大体上描述了上面的过程
// override cbasepin::checkmediatype.
ccapturepin::checkmediatype(cmediatype *pmt)
{
if (m_pmypreviewpin->isconnected())
{
// the preview pin is already connected, so query the pin it is
// connected to. if the other pin rejects it, so do we.
hr = m_pmypreviewpin->getconnected()->queryaccept(pmt);
if (hr != s_ok)
{
// the preview pin cannot reconnect with this media type.
return e_invalidarg;
}
// the preview pin will reconnect when setmediatype is called.
}
// decide whether the capture pin accepts the format.
bool facceptthistype = ... // (not shown.)
return (facceptthistype? s_ok : e_fail);
}

// override cbasepin::setmediatype.
ccapturepin::setmediatype(cmediatype *pmt);
{
if (m_pmypreviewpin->isconnected())
{
// the preview pin is already connected, so it must reconnect.
if (m_pmypreviewpin->getconnected()->queryaccept(pmt) == s_ok)
{
// the downstream pin will accept the new type, so it's safe
// to reconnect.
m_pfilter->m_pgraph->reconnect(m_pmypreviewpin);
}
else
{
return vfw_e_invalidmediatype;
}
}
// now do anything that the capture pin needs to set the type.
hr = myinternalsetmediatype(pmt);

// and finally, call the base-class method.
return cbasepin::setmediatype(pmt);
}

cpreviewpin::checkmediatype(cmediatype *pmt)
{
if (m_pmycapturepin->isconnected())
{
// the preview pin must connect with the same type.
cmediatype cmt = m_pmycapturepin->m_mt;
return (*pmt == cmt ? s_ok : vfw_e_invalidmediatype);
}
// decide whether the preview pin accepts the format. you can use your
// knowledge of which types the capture pin will accept. regardless,
// when the capture pin connects, the preview pin will reconnect.
return (facceptthistype? s_ok : e_fail);
}

本文关键:利用Directshow开发源Filter
 

本站最佳浏览方式为 分辨率 1024x768 IE 6.0(或更高版本的 IE浏览器)

go top