Введение в разработку приложений на платформе Atom/MeeGo. Граничин О.Н - 148 стр.

UptoLike

148
затем скомлировать код
gcc v4l2grab.c -o v4l2grab -ljpeg
и проверить, что утилита работает
./v4l2grab -d /dev/video0 -o image.jpg
в image.jpg должен появиться кадр с камеры. В случае дешевой камеры кадр может быть плохого
качества, так как камере перед работой требуется «разогрев» несколько секунд, а захват происходит
сразу.
Утилита v4l2grab оказалась слишком простым решением, поэтому давайте все-таки попробуем
решить ту же задачу другим способомиспользуя библиотеку gStreamer. Ее основная концепция
состоит в использовании конвейеров (pipelines, широко используемое в Linux понятие), элементами
которых могут быть источники, приемники и фильтры, последние совмещают функциональность
первых двух. Например, видеокамера может быть источником, кодек или конвертер фильтром, а окно
на экранеприемником, на практике цепочки могут ветвиться и быть гораздо длиннее. На конвейере
обрабатывается мультимедиа-поток. Главная задача программиста в этой моделисоставление
правильного конвейера для своей задачи, объединение его со своим приложением с помощью
сообщений и обратных вызовов и при необходимостисоздание собственных элементов, если не
хватает штатных.
Обратимся к нашему приложению gstgrab. В нем мы решаем 3 подзадачи
o построение конвейера, извлекающего видеопоток из вебкамеры,
o получение кадра из элемента конвейера в наш обработчик и
o последующее сохранение кадра в файл в формате JPG.
Сначала мы создаем конвейер функцией gst_pipeline_new() и его элементы функцией
gst_element_factory_make(). У всех объектов должны быть уникальные имена, при создании
элементов мы также указываем их тип. Потребуется три элемента: источник-видеокамера имеет в
gStreamer тип «v4l2src», в качестве приемника выступит фиктивный приемник «fakesink». Приемник
фиктивный, потому что мы не хотим обрабатывать весь видеопоток, нам достаточно получить доступ
к одному кадру. Если бы мы хотели не только захватить кадр, но и параллельно отобразить поток на
экране, то нужно было бы разветвить поток на два и отображать на экран через настоящий приемник
«ximagesink».
Если мы попробуем запустить конвейер всего из этих двух элементов («v4l2src» и «ximagesink»),
то получим сообщение о несовпадении форматов. Это напоминает о том, что gStreamer библиотека
достаточно низкого уровня и многие вещи программист должен делать сам. Третьим элементом будет
фильтр «ffmpegcolorspace», конвертирующий видео в формат RGB888 640x480.
Добавляем все элементы в конвейер функцией gst_bin_add_many() и связываем их в цепочку
вызовами gst_element_link_many() и gst_element_link_filtered(). Теперь конвейер настроен и
готов к запуску.
Чтобы получить кадр от фиктивного приемника, нужно назначить обработчик на его сигнал
«handoff». Это делается фунцией библиотеки GTK g_signal_connect(), сигналы GTK используются
в gStreamer и этот механизм является прообразом слотов и сигналов в QT. Наш обработчик
называется capture_callback() и одним из агрументов он получает ссылку на буфер с данными
«fakesink». В обработчике нужно сохранить буфер в файл и сообщить gStreamer о том, что мы больше
не нуждаемся в его услугах.
Для сохранения буфера в файл используется функция create_jpeg(), в нейтипичный пример
применения библиотеки libjpeg, которая даже в файл записывает сама, программисту не надо
выделять для этого дополнительный буфер. Но зато очень важно, чтобы параметры сжатия строго
совпадали с тем форматом видео, который был задан фильтром «ffmpegcolorspace». У библиотеки нет
никакой дополнительной информации, чтобы проверить корректность входного буфера. Результатом
ошибки будет испорченное изображение или даже сбой всей программы. Это еще одно напоминание,
что мы ведем работу на достаточно низком уровне.