illumium.org

Главная › Блоги › Блог snegovick

Быстрая разработка плугина для gstreamer

snegovick — Ср, 29/09/2010 - 15:44

Gstreamer — классная библиотека, позволяющая формировать цепочки обработки потоковых данных. Gstreamer построен на базе gobject, что дает ему introspection (удобный механизм работы со свойствами объектов в runtime) и сигналы.

Начало

По поводу написания плугинов для gstreamer есть очень хороший мануал http://www.gstreamer.net/data/doc/gstreamer/head/pwg/html/index.html.

Приведу здесь краткое руководство.

Во-первых необходимо заполучить исходники шаблона:

git clone git://anongit.freedesktop.org/gstreamer/gst-template.git


В директории gst-template/gst-plugin/tools находится утилита make_element, которая создает шаблон для плугина, достаточно указать ей название:

gst-plugin/src$../tools/make_element FilterName


На выходе будут файлы gstfiltername.c и gstfiltername.h

Я назвал свой плугин gstocv.

К сожалению Makefile.am утилитка не правит, поэтому придется сделать это вручную, заменив имя плугина с дефолтного на желаемое.
После этого можно попробовать собрать плугин:

gst-plugin$ bash ./autogen.sh

gst-plugin$ make && make install

Можно, однако, между вызовом autogen.sh и make выполнить промежуточный шаг, указав путь, который будет использован при установке плугина (configure --prefix=…). Если этого не сделать, то по умолчанию используется /usr/local. Путь с префиксом отличным от /usr придется добавлять в переменную окружения GST_PLUGIN_PATH.

После установки с плугином можно немного поиграться. Например использовать возможности introspection:

$ gst-inspect ocv

В ответ получим развернутую характеристику шаблонного плугина:

Factory Details:
  Long name:	ocv
  Class:	FIXME:Generic
  Description:	FIXME:Generic Template Element
  Author(s):	snegovick <<user@hostname.org>>
  Rank:		none (0)

Plugin Details:
  Name:			ocv
  Description:		Template ocv
  Filename:		/usr/local/lib/gstreamer-0.10/libgstocv.so
  Version:		0.10.0
  License:		LGPL
  Source module:	my-plugin-package
  Binary package:	GStreamer
  Origin URL:		http://gstreamer.net/

GObject
 +----GstObject
       +----GstElement
             +----Gstocv

Pad Templates:
  SINK template: 'sink'
    Availability: Always
    Capabilities:
      ANY

  SRC template: 'src'
    Availability: Always
    Capabilities:
      ANY


Element Flags:
  no flags set

Element Implementation:
  Has change_state() function: gst_element_change_state_func
  Has custom save_thyself() function: gst_element_save_thyself
  Has custom restore_thyself() function: gst_element_restore_thyself

Element has no clocking capabilities.
Element has no indexing capabilities.
Element has no URI handling capabilities.

Pads:
  SRC: 'src'
    Implementation:
    Pad Template: 'src'
  SINK: 'sink'
    Implementation:
      Has chainfunc(): gst_ocv_chain
    Pad Template: 'sink'

Element Properties:
  name                : The name of the object
                        flags: readable, writable
                        String. Default: null Current: "ocv0"
  silent              : Produce verbose output ?
                        flags: readable, writable
                        Boolean. Default: false Current: false

В частности sink и src capabilities показывают, что сейчас наш плугин принимает все что угодно и отдает все что угодно. Наш плугин будет делать преобразование canny над серой картинкой с глубиной цвета 1 байт. Поэтому в gstocv.c необходимо заменить

static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
    );

static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("ANY")
    );

на

static GstStaticPadTemplate sink_factory = GST_STATIC_PAD_TEMPLATE ("sink",
    GST_PAD_SINK,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("video/x-raw-gray, bpp=8")
    );

static GstStaticPadTemplate src_factory = GST_STATIC_PAD_TEMPLATE ("src",
    GST_PAD_SRC,
    GST_PAD_ALWAYS,
    GST_STATIC_CAPS ("video/x-raw-gray, bpp=8")
    );

Теперь можно пересобрать плугин и попробовать погонять через него видео поток.

Специально для тестов я написал небольшой скриптик, который конструирует конвеер (pipeline) гстримера таким образом, чтобы можно было смотреть видеопоток до нового плугина и после него в разных окнах.

gst-launch v4l2src device=/dev/video0 ! 'video/x-raw-yuv,width=640,height=480,framerate=30/1' ! tee name=t_vid \
 ! queue ! xvimagesink sync=false t_vid. \
 ! queue ! ffmpegcolorspace ! ocv ! ffmpegcolorspace ! sdlvideosink

Замечу, что ocv обрамлен в конвеере элементами ffmpegcolorspace ввиду того, что необходимо преобразовать исходный поток, который в моем случае состоит из YUV кадров в поток grayscale кадров. Назначение второго ffmpegcolorspace заключается в преобразовании серых кадров в формат, принимаемый элементом sdlvideosink. Почти всегда конвеер может выбрать правильные цветовые форматы сам, основываясь на требованиях sink и src pad`ов элементов. При подборе элементов полезно пользоваться опцией -vvv утилиты gst-launch, которая позволяет отслеживать проблемы и цветовые форматы различных элементов.

В результате получается следующая картинка:

screenshot.png

OpenCV

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

Сначала я решил попробовать добавить преобразование Canny, цель которого — выделение границ областей.

Неприятный момент, связанный с OpenCV заключается в том, что эта библиотека написана на C++, но тут ничего не сделаешь.

Итак, для начала необходимо научить autotools собирать плугин с помощью компилятора g++:

в файле configure.ac необходимо заменить

AC_PROG_CC

на

AC_PROG_CXX

Cменить расширения исходных исходных файлов плугина на что-то соответствующее компилятору, скажем cxx.

Заменить

libgstocv_la_CFLAGS = $(GST_CFLAGS)

на

libgstocv_la_CXXFLAGS = $(GST_CFLAGS)

также поправить расширения исходных файлов в src/Makefile.am.

После этого необходимо снова запустить autogen.sh и настроить пути установки плугина, а после этого собрать его и установить с помощью make clean; make && make install. На данном этапе необходимо добиться успешной сборки, чтобы двигаться дальше.

Теперь добавляем библиотеку OpenCV:

в configure.ac:

dnl required version of opencv
OPENCV_REQUIRED=2.1.0

PKG_CHECK_MODULES(OPENCV, [
  opencv >= $OPENCV_REQUIRED
  ], [
  AC_SUBST(OPENCV_CFLAGS)
  AC_SUBST(OPENCV_LIBS)
], [
  AC_MSG_ERROR([
      You need to install or upgrade the OpenCV development
      packages on your system. 
      The minimum version required is $OPENCV_REQUIRED.
  ])
])

В Makefile.am к CXXFLAGS и LDFLAGS дописать соответственно $(OPENCV_CFLAGS) и $(OPENCV_LIBS).

Для осуществления преобразований нам нужно будет знать ширину и высоту картинки. Выяснить эти параметры можно на этапе установки caps`ов потока.

В gstocv.hxx, в struct _Gstocv

 

int width;int height;

в функцию _set_caps:

  GstStructure *structure = gst_caps_get_structure (caps, 0);

  gst_structure_get_int (structure, "width", &filter->width);
  gst_structure_get_int (structure, "height", &filter->height);

Значения, полученные в функции _set_caps будут сохранться в переменных width и height элемента.

в _chain:

  int sz = 0;
  if ((sz = GST_BUFFER_SIZE(buf)) != 0)
  {
    IplImage * src = cvCreateImageHeader(cvSize(filter->width, filter->height), 
                                         8, 
                                         1);
    src->imageData = (char*)GST_BUFFER_DATA(buf);
    src->imageDataOrigin = (char*)GST_BUFFER_DATA(buf);

    GstBuffer *buffer = gst_buffer_new_and_alloc(sz);
    

    IplImage * dst = cvCreateImageHeader(cvSize(filter->width, filter->height), 
                                         8, 
                                         1);
    dst->imageData = (char*)GST_BUFFER_DATA(buffer);
    dst->imageDataOrigin = (char*)GST_BUFFER_DATA(buffer);

    cvCanny( src, dst, 50, 200, 3 );

    gst_buffer_copy_metadata (buffer, buf, (GstBufferCopyFlags)GST_BUFFER_COPY_ALL);
    gst_buffer_unref (buf);
    return gst_pad_push (filter->srcpad, buffer);
  }
  else
    GST_WARNING ("zero sized buffer");

Здесь необходимо обеспечить сопряжение интерфейсов gstreamer и opencv. Для этого воспользуемся функцией cvCreateImageHeader, описанной в документации OpenCV.

В результате получается следующая картинка:

screenshot-1.png

В следующий раз я хочу добавить элемент, который будет сегментировать картинку и искать на ней контрастную полосу и исходя из параметров полосы — выдавать управление робота.

  • Блог пользователя - snegovick

snegovick, спасибо за столь

Timpson (не проверено) — Чт, 21/04/2011 - 12:52

snegovick, спасибо за столь интересную статью.

Я сам недавно сел за разработку плугинов для GStreamer (до этого занимался DirectShow-фильтрами).

И вот, назрел вопрос после некоторых затруднений, связаных с C++.

Мой код был разработан под Windows DirectShow с испоьзованием объектов. Но сам gst-template генерирует .c - файл плагина.

В Линуксе сижу совсем недавно, и хотелось бы спросить ссылочки для настройки Makefile'ов. Потому как мне не помогли методы описанные в статье, make выдаёт:

*** Нет правила для сборки цели `temporal_walsh_hadamard.cpp', требуемой для `libgstplugin_la-temporal_walsh_hadamard.lo'.  Останов.

Тоже происходит и с другими модулями.

При замене в makefile'е .c на .сpp ругается на то что нет .c файла.

Возможно я не сильно глубоко постиг ДАО-make! Smile

  • ответить

Дело в том, что настройка

snegovick — Втр, 03/05/2011 - 22:33

Дело в том, что настройка Makefile.am и Makefile.in к собственно Makefile имеет весьма опосредованное отношение, по automake/autoconf которые используются в этом шаблоне могу рекомендовать http://sourceware.org/autobook/autobook/autobook_toc.html#SEC_Contents .

Если это не особо поможет, то предлагаю вам разместить ваши Makefile.in, Makefile.am на чем-нибудь типа pastebin.com и кинуть сюда ссылки, будем разбираться что неработает.

Вообще я конечно в восторге от концепции конвеера gstreamer и легкости его расширения, надеюсь у вас все получится со временем.

  • ответить

Да, спасибо!С .cpp вроде бы

Timpson (не проверено) — Втр, 17/05/2011 - 18:12

Да, спасибо!

С .cpp вроде бы разобарлся. Нужно было удалять файлы Makefile и Makefile.in и затем перезапускать autogen.sh.

Вот мой скрипт для сборки плагина (использую Ubuntu):

 

cd ~/plugin/myplugin2


sudo make clean


cd ~/plugin/myplugin2/src


sudo rm -f Makefile


sudo rm -f Makefile.in


cd ~/plugin/myplugin2


sudo sh autogen.sh


sudo make


sudo cp src/.libs/myplugin2.so /usr/lib/gstreamer-0.10/myplugin2.so


gst-inspect myplugin2.so

 

В таком варианте плагин собирается, но сейчас встала проблема, что gst-inspect выдаёт  undefined symbol: _Z7getbitsh

Вроде бы и порядок в мейкфайле выстроил как надо, и .h-файлы в нужном порядке, а ругается.

snegovick, нет ли рускоязычных ресурсов по GSreamer? Я сам некотрое время разрабатывал фильтры (плагины) для DirectShow, и есть форум на directshow.wonderu.com, на котором есть описание DirectShow  и примеры, и подскажут - если что. А вот по GStreamer'у не могу найти.

А так конечно, гораздо удобнее с GStreamer'ом работать. Да что уж говорить, он и быстрее!

  • ответить

По поводу русскоязычных

snegovick — Ср, 18/05/2011 - 23:41

По поводу русскоязычных ресурсов к сожалению не могу ничего толком подсказать.

Те команды которые вы привели в своем комментарии несколько избыточны: во-первых нет необходимости использовать sudo в каждой команде - все что вы написали кроме cp должно выполняться с правами пользователя (однако после того как вы первый раз запустили autogen.sh и make под sudo - сгенерированные файлы будут принадлежать пользователю root, поэтому чтобы запускать make и autogen.sh впредь от имени пользователя, придется удалить все сгенерированные файлы. В этом вам поможет make clean; make distclean, однако они удалят не весь мусор autotools, что-то придется удалить руками).

Далее по поводу необходимости удаления *.in файлов - ее нет. После того как вы поменяли файлы configure.ac или Makefile.am - достаточно запустить autogen.sh или, если вы его уже ранее запускали - выполнить autoreconf. Тогда automake/autoconf сгенерируют новые Makefile.in и Makefile с учетом ваших изменений. Копировать файлы вручную в /usr не нужно. Достаточно выполнить make install (директория в которую make установит файлы указывается на этапе configure опцией --prefix, так чтобы установить в /usr - нужно указать ./configure --prefix=/usr . configure выполняется сразу после autogen.sh или autoreconf, перед make).

Ну а проблема с которой вы столкнулись используя gst-inspect скорее всего связана с тем что вы забыли подключить библиотеку в которой содержится указанный символ (или перепутали имя функции и т.д.) на этапе линковки плугина (добавлять библиотеки можно например в файле Makefile.am  в директории вашего плугина, не забудьте перекомпилировать и установить плугин).

Кроме того, я заметил что вы пишете .so в конце имени плугина - в этом нет необходимости. Выведите весь список плугинов которые известны gstreamer и найдите среди них свой - там будет указано имя под которым его знает gstreamer:

gst-inspect | grep myplugin2

  • ответить

При выполнении гайда возникла

Wizzy (не проверено) — Сб, 13/04/2013 - 15:05
При выполнении гайда возникла проблема: gst-inspect пишет, что нету такого элемента как ocv. Не генерится файл .so, в папке src/.libs только gstplugin.so(залил его в usr/lib/gstreamer-1.0 и все равно не находит -_- ). Надо ли что-нибудь менять в make файлах? И в чем моя ошибка?
  • ответить

Давайте разбираться по шагам

snegovick — Сб, 13/04/2013 - 17:53
Давайте разбираться по шагам =) Жизнь стала бы намного легче, если бы вы залили куда-нибудь на github свой проект и дали ссылку. Ну а пока, напишите пожалуйста что вы делали конкретно и как ? В принципе я допускаю что за то время которое прошло с момента публикации в gstreamer что-то могло измениться.
  • ответить

1. Скопировал себе

Wizzy (не проверено) — Втр, 16/04/2013 - 12:38
1. Скопировал себе gst-template со всем что внутри2. Запустил make_element (получил .с и .h файлы)3. Изменил в Makefile.am все gstplugin'ы на свое название типа gstname4. Запустил autogen.sh (на этом пункте меня попросили поставить GStreamer-1.0)5. Запустил make && make install6. Попробовал команду gst-inspect name и на этом моменте пишет, что елемента name нет. =(
  • ответить

Попробуйте перед выполнением

snegovick — Ср, 17/04/2013 - 21:03
Попробуйте перед выполнением make сконфигурировать префикс (выполнить ./configure --prefix=/usr)
  • ответить

Добрый день. А есть

Гость (не проверено) — Пнд, 20/02/2017 - 20:47

Добрый день. А есть исходники, описанные в статье на гитхабе или иных ресурсах? Очень интересно прочитать продолжение.

  • ответить

Отправить комментарий

Содержимое этого поля является приватным и не будет отображаться публично.
  • Доступные HTML теги: <a> <em> <strong> <cite> <code> <ul> <ol> <li> <dl> <dt> <dd>
  • Syntax highlight code surrounded by the {syntaxhighlighter SPEC}...{/syntaxhighlighter} tags, where SPEC is a Syntaxhighlighter options string or "class="OPTIONS" title="the title".

Подробнее о форматировании

CAPTCHA
Этот вопрос задается для того, чтобы выяснить, являетесь ли Вы человеком или представляете из себя автоматическую спам-рассылку.
  _  __  ____                    _____    ___  
| |/ / |___ \ __ _ __ _ |_ _| ( _ )
| ' / __) | / _` | / _` | | | / _ \
| . \ / __/ | (_| | | (_| | | | | (_) |
|_|\_\ |_____| \__,_| \__,_| |_| \___/
Введите код, изображенный в стиле ASCII-арт.
RSS-материал

Навигация

  • Подшивки
  • Фотоальбомы

Работает на Drupal, система с открытым исходным кодом.

(L) 2010, Illumium.Org. All rights reversed ^_~