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


Состояния фильтра

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

Фильтры имеют три возможных состояния: остановлено, приостановлено и запущено. Приостановленное состояние предназначено для получения подсказки данных в графе, чтобы команда выполнения немедленно реагировала. Диспетчер графов фильтров управляет всеми переходами состояния. Когда приложение вызывает IMediaControl::Run, IMediaControl::P ause или IMediaControl::Stop, диспетчер фильтра Graph вызывает соответствующий метод IMediaFilter для всех фильтров. Переходы между остановленным и запущенным всегда проходят через приостановленное состояние, поэтому, если приложение вызывает выполнение в остановленном графе, диспетчер фильтров графа приостанавливает граф перед его запуском.

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

Отрисовщик преобразования > источника >

Предположим, что исходный фильтр не является источником динамической записи. Когда исходный фильтр приостанавливается, он создает поток, который создает новые данные и записывает их в примеры мультимедиа как можно быстрее. Поток "отправляет" образцы вниз, вызывая IMemInputPin::Receive на входной контакт фильтра преобразования. Фильтр преобразования получает примеры в потоке исходного фильтра. Он может использовать рабочий поток для доставки примеров в отрисовщик, но обычно он доставляет их в том же потоке. Пока отрисовщик приостановлен, он ожидает получения примера. Получив его, он блокирует и удерживает этот образец на неопределенный срок. Если это отрисовщик видео, он отображает образец в виде плаката, при необходимости перерисовывая изображение.

На этом этапе поток полностью настроен и готов к отрисовке. Если граф остается приостановленным, примеры будут "накапливаться" в графе за первым примером, пока каждый фильтр не будет заблокирован в Receive или IMemAllocator::GetBuffer. Однако данные не теряются. После разблокирования исходного потока он просто возобновляется с той точки, где он заблокирован.

Исходный фильтр и фильтр преобразования игнорируют переход от приостановленного к выполнению. Они просто продолжают обрабатывать данные как можно быстрее. Но при запуске отрисовщика он начинает отрисовку примеров. Сначала отрисовывается образец, который был приостановлен. Затем каждый раз, когда он получает новый образец, он вычисляет время презентации примера. (Дополнительные сведения см. в разделе Время и часы в DirectShow.) Отрисовщик хранит каждый образец до момента представления, после чего он отрисовывает образец. Пока он ожидает время презентации, он либо блокируется в методе Receive , либо получает новые примеры в рабочем потоке с очередью. Фильтры, вышестоящий от отрисовщика, не участвуют в планировании.

Динамические источники, такие как устройства записи, являются исключением из этой общей архитектуры. При использовании динамического источника не рекомендуется заранее подсказывать какие-либо данные. Приложение может приостановить работу графа, а затем подождать в течение длительного времени, прежде чем запустить его. Граф не должен отображать "устаревшие" примеры. Таким образом, динамический источник не создает выборки во время приостановки, только во время выполнения. Чтобы сообщить об этом диспетчеру графов фильтров, метод IMediaFilter::GetState исходного фильтра возвращает VFW_S_CANT_CUE. Этот код возврата указывает, что фильтр переключился в приостановленное состояние, даже если отрисовщик не получил никаких данных.

Когда фильтр останавливается, он отклоняет все доставляемые ему образцы. Исходные фильтры завершают потоки потоковой передачи, а другие фильтры завершают работу всех рабочих потоков, которые они могли создать. Булавки выводят из эксплуатации свои распределители.

Переходы состояния

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

  • Остановлено до приостановки. По мере приостановки каждого фильтра он становится готовым к получению примеров из следующего фильтра. Исходный фильтр приостанавливается последним. Он создает поток потоковой передачи и начинает доставку примеров. Так как все подчиненные фильтры приостановлены, ни один фильтр не отклоняет какие-либо примеры. Диспетчер графов фильтров не завершает переход, пока каждый отрисовщик в графе не получит пример (за исключением динамических источников, как описано ранее).
  • Приостановлено до остановлено. Когда фильтр останавливается, он освобождает все хранящееся в нем образцы, что разблокирует все вышестоящий фильтры, ожидающие в GetBuffer. Если фильтр ожидает ресурса в методе Receive , он перестает ожидать и возвращается из receive, что разблокирует вызывающий фильтр. Поэтому, когда диспетчер графа фильтров останавливает следующий фильтр вышестоящий, этот фильтр не блокируется в GetBuffer или Receive и может отвечать на команду stop. Фильтр вышестоящий может предоставить несколько дополнительных примеров, прежде чем он получит команду stop, но подчиненный фильтр просто отклоняет их, так как он уже остановлен.

Поток данных в графе фильтров