最后,我鼓起勇气尝试首次构建DirectShow过滤器。这可能是一个愚蠢的问题,但我很困惑。
我的滤波器是从CBaseFilter
派生的,并拥有一个从CBaseInputPin
派生的输出引脚。 CComPtr
智能指针保存输出引脚的成员引用。构建输出引脚后,我注意到它在哑指针上存储了对“所有者”过滤器的引用。对我来说很有意义,因为我们不想创建循环引用。
但是,当CComPtr
成员向输入引脚添加引用时,就会调用CBasePin::NonDelegatingAddRef()
方法。
这是该方法的源代码
/* Override to increment the owning filter's reference count */
STDMETHODIMP_(ULONG)
CBasePin::NonDelegatingAddRef()
{
ASSERT(InterlockedIncrement(&m_cRef) > 0);
return m_pFilter->AddRef();
}
我无法决定为什么子引脚需要增加拥有的过滤器的引用计数(实际上是创建循环引用)。
我应该将拥有的别针的引用保留在哑指针上,并且不管引用计数如何都将其删除?
答案 0 :(得分:2)
过滤器和引脚是COM对象,但是它们没有单独的生存期。它们只有一个参考计数-过滤器的。引脚引用和取消引用有效地增加和减少了过滤器的计数器,并在到达零过滤器时销毁了所有引脚。
外部代码以通常的方式处理COM指针。在内部,许多过滤器示例向您展示了这种方式,您可以在完成操作后删除引脚,例如(random pick):
//
// CSource::Destructor
//
CSource::~CSource()
{
/* Free our pins and pin array */
while (m_iPins != 0) {
// deleting the pins causes them to be removed from the array...
delete m_paStreams[m_iPins - 1];
}
ASSERT(m_paStreams == NULL);
}
在大多数情况下,引脚是静态的,并在过滤器的析构函数中删除。当它们是动态的时,在旅途中删除它们是不安全的,因为它们的接口指针可能仍被要删除的对象上的暂挂IUnknown::Release
引用。但是,如果只是将其保存在过滤器内部的边列表中,以在删除过滤器时推迟删除操作,那将是安全的。
此外,您不应该在过滤器内使用CComPtr
管理引脚。预期的方式在同一段代码中显示:new
和delete
用于引脚对象,并将原始指针直接指向过滤器代码中的引脚。外部代码通过其COM接口指针与引脚进行通信。