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


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

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

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

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

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

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

  • Входной пин-код фильтра 3 (pin D) должен поддерживать интерфейс IPinConnection. Этот интерфейс позволяет повторно подключить пин-код без остановки фильтра.
  • Выходной пин-код фильтра 1 (pin A) должен блокировать поток данных мультимедиа во время повторного подключения. Никакие данные не могут перемещаться между закреплением A и pin 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 вместо дескриптора событий. Теперь метод будет блокироваться до завершения операции. Это может не произойти до тех пор, пока пин-код не будет готов к доставке нового примера. Если фильтр приостановлен, это может занять произвольное время. Поэтому не выполняйте синхронный вызов из основного потока приложения. Используйте рабочий поток или вызовите метод асинхронно.

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

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

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

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

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);     

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

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

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

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

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

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

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

Заметка

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

 

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