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


Обзор потока данных в DirectShow

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

В этом разделе представлен широкий обзор работы потока данных в DirectShow. Подробные сведения см. в других разделах документации.

Данные хранятся в буферах, которые являются просто массивами байтов. Каждый буфер упаковывается COM-объектом, называемым медиаобразцом , который реализует интерфейс IMediaSample. Примеры создаются другим типом объекта, который называется распределителем, который реализует интерфейс IMemAllocator. Для каждого пин-подключения назначается распределитель, хотя два или более таких подключения могут использовать один и тот же распределитель. На следующем рисунке показан этот процесс.

буферы, примеры и распределители

Каждый распределитель создает пул примеров мультимедиа и выделяет буферы для каждого примера. Каждый раз, когда фильтру нужно заполнить буфер с данными, он запрашивает образец из распределителя путем вызова IMemAllocator::GetBuffer. Если у распределителя есть какие-либо образцы, которые в настоящее время не используются другим фильтром, метод GetBuffer немедленно возвращает указатель на образец. Если все примеры распределителя используются, метод блокируется до тех пор, пока не станет доступен пример. Когда метод возвращает семпл, фильтр помещает данные в буфер, устанавливает соответствующие флаги на семпле (обычно включая метку времени) и передает семпл дальше по потоку.

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

декодировщик ожидает свободного медиапримера

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

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

два фильтра, ожидающие примеров

Когда средство отрисовки выпускает свой образец, ожидающий вызов декодера на GetBuffer возвращается. Затем декодер может декодировать сжатый видеокадр и освободить удерживаемый им образец, тем самым разблокируя ожидающий вызова GetBuffer анализатор.

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