CBasePin对拥有过滤器的增量引用。循环参考?

时间:2018-09-18 23:40:50

标签: c++ com directshow

最后,我鼓起勇气尝试首次构建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();
    }

我无法决定为什么子引脚需要增加拥有的过滤器的引用计数(实际上是创建循环引用)。

我应该将拥有的别针的引用保留在哑指针上,并且不管引用计数如何都将其删除?

1 个答案:

答案 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管理引脚。预期的方式在同一段代码中显示:newdelete用于引脚对象,并将原始指针直接指向过滤器代码中的引脚。外部代码通过其COM接口指针与引脚进行通信。