CBasePin инкрементная ссылка на собственный фильтр.Циркуляр - PullRequest
0 голосов
/ 19 сентября 2018

Наконец-то я набрался смелости, чтобы попытаться впервые создать фильтр 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 голосов
/ 19 сентября 2018

Фильтр и выводы являются объектами 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-интерфейса.

...