Поделиться через


Динамическое повторное подключение

[Функция, связанная с этой страницей DirectShow, является устаревшей функцией. Он был заменен MediaPlayer, IMFMediaEngine, и аудио/ видео захвата в Media Foundation. Эти функции оптимизированы для Windows 10 и Windows 11. Корпорация Майкрософт настоятельно рекомендует использовать в новом коде MediaPlayer, IMFMediaEngine и аудио/видеозахват в Media Foundation вместо DirectShow, когда это возможно. Корпорация Майкрософт предлагает переписать существующий код, в котором используются устаревшие API, чтобы по возможности использовать новые API.]

В большинстве фильтров DirectShow контакты не могут быть повторно подключены, пока граф активно выполняет потоковую передачу данных. Приложение должно остановить граф перед повторным подключением контактов. Однако некоторые фильтры поддерживают повторное подключение контактов во время выполнения графа, что называется динамическим повторным подключением. Это можно сделать с помощью приложения или фильтра в графе.

В качестве примера рассмотрим график на следующем рисунке.

схема динамического построения графа

Одним из сценариев динамического повторного подключения может быть удаление фильтра 2 из графа во время работы графа и его замена другим фильтром. Чтобы этот сценарий работал, необходимо выполнить следующее:

  • Контакт ввода в фильтре 3 (контакт D) должен поддерживать интерфейс IPinConnection . Этот интерфейс позволяет повторно подключить контакт без остановки фильтра.
  • Выходной контакт в фильтре 1 (контакт A) должен иметь возможность блокировать поток данных мультимедиа во время повторного подключения. Данные не могут перемещаться между контактами A и D во время повторного подключения. Как правило, это означает, что выходной контакт должен поддерживать интерфейс IPinFlowControl . Однако если фильтр 1 является фильтром, который инициирует повторное подключение, он может иметь внутренний механизм для блокировки собственного потока данных.

Динамическое повторное подключение будет включать следующие шаги.

  1. Блокировать поток данных из контакта A.
  2. Повторно подключите контакт A к закреплению D, возможно, с помощью нового промежуточного фильтра.
  3. Разблокируйте закрепление A, чтобы данные снова начинались.

Шаг 1. Блокировка потока данных

Чтобы заблокировать поток данных, вызовите IPinFlowControl::Block при закреплении A. Этот метод может вызываться асинхронно или синхронно. Чтобы вызвать метод асинхронно, создайте объект события Win32 и передайте дескриптор события в метод Block . Метод возвращается немедленно. Дождитесь передачи сигнала о событии с помощью такой функции, как WaitForSingleObject. Закрепление сигнализирует о событии, когда оно заблокировало поток данных. Пример:

// Create an event
HANDLE hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
if (hEvent != NULL)
{
    // Block the data flow.
    hr = pFlowControl->Block(AM_PIN_FLOW_CONTROL_BLOCK, hEvent); 
    if (SUCCEEDED(hr))
    {
        // Wait for the pin to finish.
        DWORD dwRes = WaitForSingleObject(hEvent, dwMilliseconds);
    }
}

Чтобы вызвать метод синхронно, просто передайте значение NULL вместо дескриптора события. Теперь метод будет блокироваться до завершения операции. Это может не произойти, пока контакт не будет готов к доставке нового примера. Если фильтр приостановлен, это может занять произвольное время. Поэтому не выполняйте синхронный вызов из потока приложения main. Используйте рабочий поток или вызовите метод асинхронно.

Шаг 2. Повторное подключение контактов

Чтобы повторно подключить контакты, запросите у диспетчера фильтров Graph интерфейс IGraphConfig и вызовите IGraphConfig::Reconnect или IGraphConfig::Reconfigure. Метод Reconnect проще в использовании; Он выполняет следующие действия:

  • Останавливает промежуточные фильтры (фильтр 2 в примере) и удаляет их из графа.
  • При необходимости добавляет новые промежуточные фильтры.
  • Подключает все контакты.
  • Приостанавливает или запускает новые фильтры в соответствии с состоянием графа.

Метод Reconnect имеет несколько необязательных параметров, которые можно использовать для указания типа носителя для контактного соединения и промежуточного фильтра. Пример:

pGraph->AddFilter(pNewFilter, L"New Filter for the Graph");
pConfig->Reconnect(
    pPinA,      // Reconnect this output pin...
    pPinD,      // ... to this input pin.
    pMediaType, // Use this media type.
    pNewFilter, // Connect them through this filter.
    NULL, 
    0);     

Дополнительные сведения см. на справочной странице. Если метод Reconnect недостаточно гибок, можно использовать метод Reconfigure , который вызывает определяемый приложением метод обратного вызова для повторного подключения контактов. Чтобы использовать этот метод, реализуйте интерфейс IGraphConfigCallback в приложении.

Перед вызовом Reconfigure заблокируйте поток данных из выходного контакта, как описано выше. Затем отправьте все данные, которые все еще находятся в состоянии ожидания, в разделе графа, который выполняется повторное подключение, следующим образом:

  1. Вызовите метод IPinConnection::NotifyEndOfStream на входном контакте, который является самым нисходящим в цепочке повторного подключения (в примере закрепление D). Передайте дескриптор в событие Win32.
  2. Вызовите метод IPin::EndOfStream для входного контакта, который находится непосредственно вниз от выходного контакта, в котором вы заблокировали поток данных. (В этом примере поток данных был заблокирован при закреплении A, поэтому вы можете вызвать EndOfStream для контакта B.)
  3. Дождитесь передачи сигнала о событии. Пин-код ввода (пин-код D) сигнализирует о событии при получении уведомления об окончании потока. Это означает, что данные не перемещается между контактами и что вызывающий объект может безопасно переподключить контакты.

Обратите внимание, что метод IGraphConfig::Reconnect автоматически обрабатывает предыдущие шаги. Эти действия необходимо выполнить только при использовании метода Reconfigure .

После передачи данных через граф вызовите Reconfigure и передайте указатель на интерфейс обратного вызова IGraphConfigCallback . Диспетчер фильтров графов вызовет предоставленный вами метод IGraphConfigCallback::Reconfigure .

Шаг 3. Разблокировка Поток данных

После повторного подключения контактов разблокируйте поток данных, вызвав метод IPinFlowControl::Block со значением, равным нулю для первого параметра.

Примечание

Если динамическое повторное подключение выполняется фильтром, необходимо учитывать некоторые проблемы потоков. Если диспетчер графа фильтров пытается остановить фильтр, он может заблокироваться, так как граф ожидает остановки фильтра, в то время как в то же время фильтр может ожидать передачи данных через граф. Чтобы предотвратить возможную взаимоблокировку, некоторые методы, описанные в этом разделе, принимают дескриптор события Win32. Фильтр должен сигнализировать о событии, если диспетчер фильтров graph пытается остановить фильтр. Дополнительные сведения см. в разделах IGraphConfig и IPinConnection.

 

Построение динамического графа