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


Фильтрация состояний

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

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

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

Средство отрисовки > преобразования исходного >

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

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

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

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

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

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

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

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

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