Наши партнеры

UnixForum





Библиотека сайта rus-linux.net

Фреймворк GStreamer. Руководство разработчика плагинов. Предварительно созданные базовые классы

Оригинал: GStreamer Plugin Writer's Guide
Авторы: Richard John Boulton, Erik Walthinsen, Steve Baker, Leif Johnson, Ronald S. Bultje, Stefan Kost, Tim-Philipp Muller, Wim Taymans
Дата публикации: 19 июля 2014 г.
Перевод: А.Панин
Дата перевода: 29 июля 2014 г.

Часть IV. Создание элементов специальных типов

На данный момент мы рассмотрели практически все механизмы, которые могут быть использованы в ходе реализации элемента фреймворка GStreamer. Эти механизмы были преимущественно низкоуровневым, поэтому при их рассмотрении также удалось рассмотреть принцип работы некоторых внутренних механизмов фреймворка GStreamer. К счастью, фреймворк GStreamer содержит несколько более простых в использовании интерфейсов, предназначенных для создания элементов определенных типов. Для ознакомления с ними мы подробнее рассмотрим типы элементов, для которых фреймворк GStreamer предоставляет базовые классы (элементы для ввода данных, элементы для вывода данных и элементы для преобразования мультимедийного потока). Также мы подробнее рассмотрим некоторые типы элементов, которые не требуют разработки специфичного кода, такого, как код для управления ходом планирования работы элемента или процессом передачи данных, но требуют специфичного управления работой конвейера (например, элементы для объединения мультимедийных потоков по схеме N-к-1 и элементы управления).

Глава 23. Предварительно созданные базовые классы

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

23.1. Разработка элемента для вывода данных

Элементы для вывода данных являются специальными элементами фреймворка GStreamer. Главным образом такое положение вещей обусловлено тем, что элементам для вывода данных приходится заботиться о подготовке конвейера (preroll), являющейся процессом, в ходе которого должны быть выполнены все необходимые действия для того, чтобы элементы, переведенные в состояние "пауза" (GST_STATE_PAUSED), имели доступ к готовым буферам данных сразу же после изменения их состояний. В результате такие элементы смогут начать обработку данных немедленно после перехода в состояние "воспроизведение" (GST_STATE_PLAYING) без необходимости в затратах некоторого времени на инициализацию устройств для вывода данных и настройку декодеров; все эти операции выполняются перед тем, как успешно завершается переход к состоянию "пауза" (GST_STATE_PAUSED).

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

В рамках базового класса реализована большая часть логики синхронизации, которая должна выполняться элементом для вывода данных.

При этом базовый класс GstBaseSink накладывает несколько ограничений на элементы для вывода данных:
  • Он требует, чтобы элемент для вывода данных имел всего лишь одну входную точку соединения. Элементы для вывода данных, которым требуется более одной входной точки соединения, должны создать элемент управления с множеством элементов для вывода данных на основе базового класса GstBaseSink в нем.
Классы элементов для вывода данных могут наследоваться от класса GstBaseSink с помощью обычного вспомогательно макроса объектной модели GObject G_DEFINE_TYPE ():
G_DEFINE_TYPE (GstMySink, gst_my_sink, GST_TYPE_BASE_SINK);

[..]

static void
gst_my_sink_class_init (GstMySinkClass * klass)
{
  klass->set_caps = [..];
  klass->render = [..];
[..]
}
Существует множество преимуществ наследования класса элемента от базового класса GstBaseSink:
  • Унаследованные реализации практически не должны заботиться о подготовке конвейера и не должны обладать какой-либо информацией о технической реализации и требованиях используемого механизма подготовки конвейера. Вся сложная работа выполняется базовым классом.
  • Объем кода, необходимый для разработки элемента на основе унаследованного класса, значительно меньше, а объем разделяемого между элементами кода - больше (поэтому ошибки в разделяемом между элементами коде будут исправляться централизовано).

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

23.1.1. Разработка элемента для вывода аудиоданных

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

Существуют два базовых класса элемента для вывода аудиопотока, поэтому вы можете выбрать тот класс, от которого будет наследоваться класс вашего элемента, в зависимости от ваших потребностей: GstAudioBaseSink и GstAudioSink. Класс GstAudioBaseSink предоставляет полный контроль над процессами синхронизации и планирования работы элемента благодаря использованию кольцевого буфера, который контролируется и предоставляется унаследованным классом. Базовый класс элемента для вывода аудиопотоков GstAudioSink унаследован от класса GstAudioBaseSink и реализует стандартный кольцевой буфер и стандартный механизм синхронизации, а также предоставляет стандартный таймер, использующий сэмплы аудиопотока. Унаследованные от этого базового класса классы всего лишь должны предоставлять реализации функций _open (), _close () и _write (), а также реализации некоторых необязательных функций. Этого набора функций должно быть достаточно для многих элементов, осуществляющих вывод аудиопотоков с помощью звуковых серверов и даже для большинства интерфейсов. Такие предъявляющие более жесткие требования аудиосистемы, как Jack, могут потребовать использования базового класса GstAudioBaseSink.

Базовый класс GstAudioBaseSink практически не накладывает ограничений на результирующий элемент и в теории должен подходить для реализации любого элемента, но с ним тяжело работать. С другой стороны, базовый класс GstAudioSink подходит исключительно для реализации элементов, работающих с системами, которым хватает простого API, включающего функции open () / close () / write () (таковыми являются практически все существующие системы), но его преимущество заключается в том, что с ним гораздо проще работать. Достоинств у второго базового класса достаточно много:
  • Предоставляет возможность автоматической синхронизации без какого-либо кода в унаследованном классе.
  • Также созданный на основе класса элемент автоматически предоставляет таймер, поэтому остальные элементы для вывода данных (например в случае проигрывания мультимедийного потока, состоящего из аудио- и видеопотока) могут осуществлять синхронизацию.
  • Дополнительные функции могут быть добавлены во все элементы для вывода аудиопотоков путем изменения базового класса, что упрощает обслуживание элементов.
  • Наследуемые классы должны реализовывать только три небольших функции, а также шаблонный код, встречающийся во всех программных компонентах, использующих объектную модель GObject.

В дополнение к реализации виртуальных функций базового класса элемента для вывода аудиопотоков, унаследованные классы могут (и должны) также реализовывать виртуальные функции базового класса элемента для вывода данных GstBaseSink с именами set_caps () и get_caps (), предназначенные для согласования возможностей элементов.

23.1.2. Элемент для вывода видеоданных

Разработка элемента для вывода видеопотоков может осуществляться на основе базового класса GstVideoSink, который наследуется от класса GstBaseSink. На данный момент он не делает ничего кроме добавления новой зависимости времени компиляции, поэтому унаследованные от него классы должны будут реализовать все виртуальные функции класса GstBaseSink. При корректной реализации этих функций базовый класс окажет позитивное воздействие на пользовательские качества элемента для вывода видеопотоков:
  • Благодаря реализации механизма подготовки конвейера (и виртуальной функции preroll ()) имеется возможность вывода кадра видео уже при переходе в состояние "пауза" (GST_STATE_PAUSED).
  • Имеется возможность добавления новых расширений элементов для вывода данных, которые будут оказывать влияние на работу всех подобных элементов и должны реализовываться однократно путем добавления новых функций в класс GstVideoSink, что в значительной степени упрощает сопровождение элементов.

23.2. Разработка элемента для ввода данных

В предыдущей части, а именно в разделе под названием "Предоставление возможности осуществления произвольного доступа", мы узнали о том, что некоторые типы элементов могут позволять осуществлять произвольный доступ к данным. Это утверждение наиболее явно относится к элементам для ввода данных, читающим данные из источников с возможностью произвольного доступа к данным, таким, как файловые источники данных. Однако, другие элементы для ввода данных являются элементами для ввода данных из источников реального времени, таких, как источник данных, работающий с веб-камерой, аудиокартой и аналогичных; эти источники данных не позволяют осуществлять перемещение в рамках мультимедийного потока, а также не предоставляют доступ к данным этого потока с точностью до байт. Для всех описанных вариантов работы элемента фреймворк GStreamer предоставляет два базовых класса: GstBaseSrc для реализации базовых функций элемента для ввода данных и GstPushSrc, который является базовым классом для элементов, не предоставляющих доступ с точностью до байт к получаемым данным. Сам базовый класс GstPushSrc также наследуется от базового класса GstBaseSrc и, следовательно, все приемы работы с классом GstBaseSrc применимы также и при работе с классом GstPushSrc.

Базовый класс GstBaseSrc выполняет некоторые операции для унаследованных классов автоматически, поэтому вам больше не придется беспокоиться о них:
  • Исправления ошибок базового класса GstBaseSrc будут автоматически доступны всем унаследованным от него классам.
  • Обработка активации точек соединения, как и создание задач в том случае, если мы самостоятельно установили функцию создания самой задачи, выполняются автоматически.
При этом базовый класс GstBaseSrc может не являться оптимальным во всех случаях; он имеет следующие ограничения:
  • Может использоваться одна и только одна выходная точка соединения. Элементы для ввода данных, от которых требуется предоставление нескольких выходных точек соединения, должны либо реализовывать управляющий контейнер и использовать с помощью внутренних механизмов множество элементов для ввода данных, либо создавать элемент управления, который будет использовать элемент для ввода данных и демультиплексор.

Имеется возможность использования специальных фрагментов памяти, таких, как фрагменты памяти, используемые при работе с сервером оконной системы X или фрагменты памяти, созданные путем вызова функции отображения файла в память mmap () в форме указателей на данные в буферах, возвращаемых из виртуальной функции create().

23.2.1. Разработка элемента для ввода аудиоданных

Элемент для ввода аудиоданных является не более, чем частным случаем элемента для ввода данных на основе класса GstPushSrc. Элементы для ввода аудиоданных могут быть любыми элементами, которые читают аудиоданные, такими, как элементы для приема аудиоданных от звукового сервера, интерфейса ядра операционной системы (такого, как ALSA) или элементы для генерации тестового звука/сигнала. Фреймворк GStreamer предоставляет два базовых класса, аналогичных двум базовым классам, используемым при создании элементов для вывода аудиоданных и описанным в разделе под названием "Разработка элемента для вывода аудиоданных"; один из классов использует кольцевой буфер и требует использования средств унаследованного класса для планирования своей работы, синхронизации и аналогичных целей. Другой основывается на классе GstAudioBaseSrc, носит имя GstAudioSrc и предоставляет минималистичный интерфейс, состоящий из функций open (), close () и read (), который достаточно просто реализовать и которого достаточно для получения аудиоданных от большинства существующих звуковых серверов и звуковых интерфейсов (т.е., ALSA или OSS).

Базовый класс GstAudioSrc обладает несколькими преимуществами, которые могут быть использованы при создании унаследованных классов и объединены с преимуществами базового класса GstPushSrc, на котором он основан:
  • Выполняет синхронизацию и предоставляет таймер.
  • Новые функции могут добавлены непосредственно в этот класс, после чего они автоматически будут доступны для всех унаследованных классов.

23.3. Разработка элемента для преобразования мультимедийного потока

Третьим базовым классом, который предлагает фреймворк GStreamer, является класс GstBaseTransform. Это базовый класс для элементов с одной выходной точкой соединения и одной входной точкой соединения, которые работают как фильтры какого-либо типа, выполняя такие функции, как изменение уровня звука, изменение частоты дискретизации, преобразование формата аудиопотока, и.т.д. Существует множество стандартных механизмов, которые подобные элементы должны задействовать для того, чтобы выполнять такие операции, как обработка данных с резервированием новых буферов данных, пропуск буферов с данными, непосредственная обработка данных из получаемых буферов, а также другие операции, необходимые для корректной работы элемента. Упомянутый базовый класс использует все эти механизмы за вас, поэтому вам придется всего лишь заниматься непосредственной обработкой данных.

Так как класс GstBaseTransform базируется на модели для фильтров 1-к-1, он может не лучшим образом подходить для реализации таких элементов, как декодеры, которые могут извлекать значения различных параметров из потока данных. Также данный класс не подойдет для реализации элементов, которым требуется более одной выходной или входной точки соединения.


Следующий раздел : Разработка демультиплексора или элемента для разбора мультимедийного потока.