Устройство вывода (sink) — это элемент для вывода сигнала куда-либо, будь то звуковая карта, файл, видеокарта или сетевой интерфейс. По своей сути, устройство вывода — это полная противоположность источника данных, и в отличие от источников данных, устройства вывода имеют только один pad — sink.
Рассмотрим устройства вывода подробнее.
Поехали
1. fakesink
Данное устройство по своему смыслу аналогично fakesrc — оно ничего не делает. fakesink используется для вывода сигнала «в пустоту».
Честно говоря, я сам не могу придумать, где его можно использовать, посему особой полезности в данном устройстве я не нахожу.
Пример использования:
gst-launch-1.0 fakesrc ! fakesink
2. fdsink
Устройство fdsink используется для вывода потока в файловый дескриптор, оно, как и fdsrc, имеет только один параметр — fd, который должен содержать номер файлового дескриптора. По-умолчанию выводит поток в STDOUT. Естественно, пользы от данного элемента мало, и применять его в реальных проектах особого смысла нет.
Пример использования:
gst-launch-1.0 filesrc location=/foo/bar.mp3 ! fdsink | gst-launch-1.0 fdsrc ! decodebin ! autoaudiosink
3. alsasink, pulsesink, oss4sink/osssink, jackaudiosink, autoaudiosink
Эти элементы используются для вывода потока на звуковую карту посредством использования необходимой аудио-подсистемы. Из параметров можно отметить только device — он должен содержать в себе идентификатор звуковой карты, на которую в свою очередь будет выведен поток. Из вышеперечисленного списка модулей только autoaudiosink стоит в стороне и обладает одной особенностью — он автоматически выбирает, куда и через какую звуковую подсистему выводить поток, поэтому он не имеет параметра device.
Примеры использования:
gst-launch-1.0 filesrc location=/foo/bar.mp3 ! decodebin ! alsasink device="hw:0" gst-launch-1.0 filesrc location=/foo/bar.mp3 ! decodebin ! pulsesink gst-launch-1.0 filesrc location=/foo/bar.mp3 ! decodebin ! autoaudiosink
4. filesink
Как вы, наверное, уже догадались, данное устройство используется для вывода потока в файл. Его можно использовать для разных целей, например: записывать радиопоток, записывать видеопоток с web-камеры, а также аудиопоток со звуковой карты. Ко всему прочему, данное устройство просто необходимо в случае использования GStreamer как инструмента для конвертации файлов.
Подробно рассматривать свойства данного элемента мы не будем, т. к. они аналогичны свойствам элемента filesrc, с которым мы познакомились в прошлой статье. Одно отличие — у filesink имеется параметр append. Параметр append используется для дописывания потока в конец существующего файла вместо перезаписи его с начала.
Пример использования:
gst-launch-1.0 v4l2src num-buffers=1 ! jpegenc ! filesink location=/tmp/capture1.jpeg
Данный пример иллюстрирует создание фотографии первым устройством, поддерживающим v4l2, и последующее сохранение снимка в /tmp/capture1.jpeg.
5. multifilesink
Элемент multifilesink — полная противоположность элементу multifilesrc, с которым мы познакомились в прошлой статье, и используется он для вывода потока в разные файлы. Параметры данного элемента аналогичны параметрам multifilesrc, поэтому на них мы останавливаться не будем.
Пример использования:
gst-launch-1.0 v4l2src num-buffers=10 ! jpegenc ! multifilesink location=/tmp/capture%d.jpeg
Данный пример иллюстрирует создание 10 фотографий и сохранение их в файлы capture0.jpeg-capture9.jpeg.
6. giosink
И этот элемент является полной противоположностью элементу giosrc — он используется для вывода потока в файл через GIO. Как и giosrc, giosink имеет параметр location, содержащий путь к файлу, в который необходимо записать поток.
Пример использования:
gst-launch-1.0 location ! giosink location=file:///foo/bar.raw
7. ximagesink и xvimagesink
Данные элементы используются для вывода видеосигнала посредством X-сервера. Эти элементы могут использоваться как для просмотра видео «в консоли», так и для реализации вывода видео в приложениях. Разница между элементами небольшая, но есть, и она заключается в двух моментах — ximagesink использует только X-сервер для вывода, а xvimagesink — libxv. Так же xvimagesink имеет чуть больше параметров. Рассмотрим их:
display
Имя X-дисплея, например :0, :1, :2…
pixel-aspect-ratio
Данный параметр указывает соотношение сторон, например 2/1. По умолчанию имеет значение 1/1.
force-aspect-ratio
В некоторых случаях явное указывание pixel-aspect-ratio может не сработать (в случае если «переговоры» между элементами привели к тому, что нужно оставить оригинальный pixel-apect-ratiio), и данное свойство исправляет эту «проблему».
Далее перечисляются свойства, имеющиеся только у xvimagesink.
brightness, contrast, hue, saturation
Переведя на русский язык названия этих свойств («яркость-контрастность-оттенок-насыщенность), можно понять их назначение. Значения могут располагаться в диапазоне от -1000 до 1000.
device
Порядковый номер видеокарты, с помощью которой необходимо выводить видео.
double-buffer
Данное свойство включает и выключает использование двойной буферизации.
colorkey, autopaint-colorkey
Данные свойства используются для управления цветом оверлея, на котором рисуется видео. Colorkey должно в себе содержать gint с кодом цвета, а autopaint-colorkey включает «заливку» оверлея этим цветом.
Примечание:
В документации отсутствуют пояснения по поводу того, что из себя представляет цвет, но, скорее всего, цвет указывается в RGB формате, по формуле ((RR & 0xff) << 16) | ((GG & 0xff) << 8 ) | (BB & 0xff).
draw-borders
Данное свойство включает или отключает отрисовку черной обводки в местах, где образовалась «пустота» при применении force-aspect-ratio.
Примеры использования:
gst-launch-1.0 videotestsrc ! ximagesink gst-launch-1.0 videotestsrc ! xvimagesink
8. aasink и cacasink
Эти элементы уже, наверно, не актуальны, и могут использоваться либо «олдфагами», либо теми, кто хочет показать «что могут линуксы», хотя, возможно, я и ошибаюсь. Оба этих элемента позволяют выводить видео посредством библиотек libaa и libcaca, то есть выводить видео в виде ASCII-арта. Различие между ними только одно: libaa выводит черно-белые символы, а libcaca — цветные.
Останавливаться на параметрах данных элементов мы не будем, т. к. практической пользы от них (ИМХО) нет.
Примеры использования:
gst-launch-1.0 videotestsrc ! aasink gst-launch-1.0 videotestsrc ! aacasink
9. gdkpixbufsink
Данный элемент выводит видеопоток в объект GdkPixbuf, который доступен через read-only свойство last-pixbuf. Для чего это нужно — я даже не могу представить.
Примеры
В качестве примера мы будем использовать плеер из прошлой статьи, но с добавлением новой возможности — записью потока в файл.
#env python2 # coding=utf-8 import gi gi.require_version("Gst", "1.0") gi.require_version("Gtk", "3.0") from gi.repository import Gst from gi.repository import Gtk from gi.repository import GObject import os import signal import argparse Gst.init("") signal.signal(signal.SIGINT, signal.SIG_DFL) GObject.threads_init() def parse_args(): parser = argparse.ArgumentParser(prog='example1.py') parser.add_argument('--volume', help='Указать громкость (0-100) (default: 100)', type=int, default=100) parser.add_argument('--output', help='Путь к файлу в который нужно сохранить поток (default: /tmp/out.ogg)', type=str, default='/tmp/out.ogg') parser.add_argument('location') args = parser.parse_args() return args class RecorderBin(Gst.Bin): def __init__(self, name=None): super(RecorderBin, self).__init__(name=name) self.vorbisenc = Gst.ElementFactory.make("vorbisenc", "vorbisenc") self.oggmux = Gst.ElementFactory.make("oggmux", "oggmux") self.filesink = Gst.ElementFactory.make("filesink", "filesink") self.add(self.vorbisenc) self.add(self.oggmux) self.add(self.filesink) self.vorbisenc.link(self.oggmux) self.oggmux.link(self.filesink) self.sink_pad = Gst.GhostPad.new("sink", self.vorbisenc.get_static_pad("sink")) self.add_pad(self.sink_pad) def set_location(self, location): self.filesink.set_property("location", location) class Player(): def __init__(self, args): self.pipeline = self.create_pipeline(args) self.args = args ## получаем шину по которой рассылаются сообщения ## и вешаем на нее обработчик message_bus = self.pipeline.get_bus() message_bus.add_signal_watch() message_bus.connect('message', self.message_handler) ## устанавливаем громкость self.pipeline.get_by_name('volume').set_property('volume', args.volume / 100.) def create_source(self, location): """create_source(str) -> Gst.Element""" if not location.startswith('http') and not os.path.exists(location): raise IOError("File %s doesn't exists" % location) if location.startswith('http'): source = Gst.ElementFactory.make('souphttpsrc', 'source') else: source = Gst.ElementFactory.make('filesrc', 'source') source.set_property('location', location) return source def create_pipeline(self, args): """create_pipeline() -> Gst.Pipeline""" pipeline = Gst.Pipeline() ## Создаем нужные элементы для плеера source = self.create_source(args.location) decodebin = Gst.ElementFactory.make('decodebin', 'decodebin') audioconvert = Gst.ElementFactory.make('audioconvert', 'audioconvert') volume = Gst.ElementFactory.make('volume', 'volume') audiosink = Gst.ElementFactory.make('autoaudiosink', 'autoaudiosink') ## Элемент tee используется для мультиплексирования потока tee = Gst.ElementFactory.make('tee', 'tee') ## decodebin имеет динамические pad'ы, которые так же динамически ## необходимо линковать def on_pad_added(decodebin, pad): pad.link(audioconvert.get_static_pad('sink')) decodebin.connect('pad-added', on_pad_added) ## добавляем все созданные элементы в pipeline elements = [source, decodebin, audioconvert, volume, audiosink, tee] [pipeline.add(k) for k in elements] ## линкуем элементы между собой по схеме: ## +-> volume -> autoaudiosink ## *src* -> (decodebin + audioconvert) -> tee -> | ## [ +-> vorbisenc -> oggmux -> filesink ] source.link(decodebin) audioconvert.link_pads('src', tee, 'sink') tee.link_pads('src_0', volume, 'sink') volume.link(audiosink) return pipeline def play(self): self.pipeline.set_state(Gst.State.PLAYING) recorder = RecorderBin('recorder') self.pipeline.add(recorder) self.pipeline.get_by_name('tee').link_pads('src_1', recorder, 'sink') recorder.set_location(self.args.output) def message_handler(self, bus, message): """Обработчик сообщений""" struct = message.get_structure() if message.type == Gst.MessageType.EOS: print('Воспроизведение окончено.') Gtk.main_quit() elif message.type == Gst.MessageType.TAG and message.parse_tag() and struct.has_field('taglist'): print('GStreamer обнаружил в потоке мета-теги') taglist = struct.get_value('taglist') for x in range(taglist.n_tags()): name = taglist.nth_tag_name(x) print(' %s: %s' % (name, taglist.get_string(name)[1])) else: pass if __name__ == "__main__": args = parse_args() player = Player(args) player.play() Gtk.main()
Примечание:
Данный пример (как и пример из прошлой статьи), не работает в Ubuntu 13.10, падая с segfault (см. lp:1198375).
Рассмотрим, что тут происходит. Для удобства и логического разделения создаем контейнер RecorderBin, в который помещаем три элемента — vorbisenc, oggmux и filesink. Элементы vorbisenc и oggmux необходимы для кодирования RAW-потока в формат vorbis и для заворачивания его в контейнер ogg соответственно. Подробно на контейнерах (bin) мы останавливаться не будем, напомню только то, что контейнеры являются законченными элементами, которые выполняют какое-либо действие в pipeline.
В RecorderBin все три элемента линкуются между собой последовательно, по схеме:
vorbisenc → oggmux → filesink
Далее мы создаем элемент tee, необходимый для мультиплексирования потока, т. к. большинство элементов, как вы помните, зачастую имеют только один вход и один выход, а элемент tee решает проблему, возникающую, когда нужно «разделить» сигнал и отправить его в две разных точки (звуковая карта и файл в нашем случае).
После этого мы линкуем выход src_0 элемента tee с входом sink элемента volume, а в методе play, после установки статуса PLAYING, добавляем в pipeline наш RecorderBin и линкуем выход src_1 элемента tee с sink RecorderBin-а.
По логике, слинковать все можно было бы и в create_pipeline, но в GStreamer по какой-то причине блокируется весь pipeline при добавлении еще одного sink-элемента до установки статуса PLAYING, и решения данной проблемы я так и не смог найти.
Заключение
Сегодня мы рассмотрели практически все имеющиеся устройства для вывода потока. В последующих статьях мы рассмотрим т. н. фильтры — элементы, которые выполняют различную работу, связанную с обработкой потоков. К фильтрам относятся различные энкодеры и декодеры, де/мультиплексоры, различные аудио/видео фильтры и прочие служебные элементы.
Литература
- GStreamer Application Development Manual
- GStreamer Core Plugins Reference Manual
- GStreamer Base Plugins Reference Manual
- GStreamer Good Plugins Reference Manual
ссылка на оригинал статьи http://habrahabr.ru/post/204014/
Добавить комментарий