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


Обзор Поток данных в 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 средства синтаксического анализа.

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