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

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

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

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

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

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

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

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

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

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

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

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

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