GStreamer И Android (GStreamer Android Studio Windows)

About: Вот, увлёкся Ардуино, Raspberry Pi, android.

Версия библиотек GStreamer 1.15.2, версия Android Studio 3.3.2, ОС Windows 7 x86-64.

Teacher Notes

Teachers! Did you use this instructable in your classroom?
Add a Teacher Note to share how you incorporated it into your lesson.

Step 1: GStreamer На Raspbian (Debian Stretch)

Установка gstreamer (https://gstreamer.freedesktop.org/documentation/installing/index.html) на Raspberry Pi:

  1. выполняем команду «aptitude search gstreamer1.0» она выведет доступные к установке пакеты;
  2. необходимо как минимум установить следующие пакеты: «gstreamer1.0-tools», «gstreamer1.0-plugins-good», «gstreamer1.0-plugins-good-doc», «gstreamer1.0-plugins-base», «gstreamer1.0-doc», «libgstreamer1.0-0», «gstreamer1.0-rtsp», «libgstreamer-plugins-base1.0-dev», «gstreamer1.0-plugins-base-apps», «gstreamer1.0-plugins-bad» и все зависимости. Команда будет «sudo apt-get install gstreamer1.0-tools gstreamer1.0-plugins-good gstreamer1.0-plugins-good-doc gstreamer1.0-plugins-base gstreamer1.0-doc libgstreamer1.0-0 gstreamer1.0-rtsp libgstreamer-plugins-base1.0-dev gstreamer1.0-plugins-base-apps gstreamer1.0-plugins-bad»;
  3. для включения gstreamer в код,необходимо включить «#include », при компиляции программы необходимо добавлять «`pkg-config --cflags --libs gstreamer-1.0`», получится так «gcc `pkg-config --cflags --libs gstreamer-1.0` basic-tutorial-1.c -o basic-tutorial-1»;
  4. для получения исходников примеров gstreamer можно выполнить команду «git clone https://gitlab.freedesktop.org/gstreamer/gst-docs».

Для получения изображения с камеры RPI через gstreamer по сети с использованием плагина udpsink необходимо в консоли ввести команду: «raspivid -t 999999 -h 1080 -w 1920 -fps 25 -hf -vf -b 6000000 -o - | gst-launch-1.0 -v fdsrc ! h264parse ! rtph264pay config-interval=1 pt=96 ! udpsink host=192.168.1.223 port=5000», где host — ip-адрес получателя потока (смартфон на андроид), что делает каждый плагин (fdsrc, h264parse, rtph264pay, ...) Вы можете узнать с помощью команды «gst-inspect-1.0 fdsrc», «gst-inspect-1.0 h264parse» и т.д.

Для получения видео потока на винде (после установки gstreamer) по сети с использованием плагина udpsrc необходимо в консоли ввести команду: «c:\gstreamer\1.0\x86_64\bin\gst-launch-1.0 -v udpsrc port=5000 ! application/x-rtp,encoding-name=H264 ! rtph264depay ! avdec_h264 ! videoconvert ! autovideosink sync=false» (у меня Windows 7 64 бит, GStreamer установлен в «c:\gstreamer\»).

Забегая вперёд скажу что для Samsung S7 получение видео потока на android (конвейер с использованием udpsrc) «udpsrc port=5000 ! application/x-rtp,encoding-name=H264 ! rtph264depay ! h264parse ! amcviddec-omxexynosavcdec ! videoconvert ! autovideosink».

Step 2: Android. Введение. Создание Приложения С NDK, JNI, Компиляция Ndk-build

Для начала нужно чтобы нормально создавалось приложение с NDK, JNI с компиляцией с помощью ndk-build (https://developer.android.com/ndk/guides, https://habr.com/ru/post/203014/):

  • устанавливаем в Windows переменную среды «GSTREAMER_ROOT_ANDROID», значение - путь до каталога с распакованными (установленными) библиотеками gstreamer (prebuilt) https://gstreamer.freedesktop.org/data/pkg/android/1.15.2/ (в моём случае это «C:\gstreamer», последний слэш ставить не нужно);
  • устанавливаем NDK, CMake, LLDB (тут только галочки расставить);
  • создаём новое приложение с типом «Native C++» (самый нижний правый угол для Android Studio 3.3.2), дожидаемся пока все процессы завершатся;
  • в левом окне выбираем вид «Project» (выпадающий список в левом верхнем углу), раскрываем ветку до каталога «app» включительно, нажимаем по «app» правой клавишей мыши и выбираем пункт меню «New->Folder->JNI Folder», в появившемся окне ставим галочку «Change Folder Location», в появившейся строке «New Folder Location» оставляем строку «jni/», нажимаем кнопку «Finish», в каталоге «app» появится элемент «jni»;
  • жмём правой клавишей мыши по элементу «jni», выбираем пункт меню «New->C/C++ Source File», в появившемся окне выбираем расширение файла, и вводим название (если пока ничего не планируется то можно, например дать имя «dummy»), нажимаем кнопку «OK» и будет создан файл;
  • жмём правой клавишей мыши по элементу «jni», выбираем пункт меню «New->File», в появившемся окне вводим имя «Android.mk», минимальное содержимое, если вы создали «dummy.c» может быть таким:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_MODULE := dummy LOCAL_SRC_FILES := dummy.c include $(BUILD_SHARED_LIBRARY)
  • жмём правой клавишей мыши по элементу «jni», выбираем пункт меню «New->File», в появившемся окне вводим имя «Application.mk», минимальное содержимое может быть таким:
APP_ABI := all

теперь в левом окне выбираем вид «Android» (выпадающий список в левом верхнем углу), раскрываем ветку «Gradle Scripts» и открываем файл «build.gradle Module: app», в файле удаляем оба включения таких строк:

ExternalNativeBuild {
CMake... }
  • сохраняемся и жмём «sync gradle» в верхнем правом углу, ждём когда процесс спокойно завершится;
  • после всех этих процедур нам необходимо нажать правой клавишей мыши на элемент «app» и наконец то в меню появится так нужный нам пункт меню «Link C++ Project with Gradle», нажимаем на него.
  • Появится окно, в нём в пункте «Build System» вместо «CMake» нужно в списке выбрать «ndk-build», после чего в «Project Path» указать путь до файла «Android.mk» (в окне выбора файла нажимаем комбинацию клавиш «Ctrl + 2», разворачиваем каталог проекта, далее «app/jni», выбираем созданный нами файл «Android.mk», нажимаем «ОК»), ждём пока завершится процесс синхронизации, либо инициируем его «File->Sync Project with Gradle Files».
  • В нашем дереве, в каталоге «cpp» появятся добавленные нами файлы, но самое главное — это то, что теперь проект нормально соберётся, если у Вас в коде ошибок нет (урок для начинающих: https://developer.android.com/ndk/samples/sample_hellojni#java).

Step 3: Прикручиваем GStreamer.

Процесс прикручивания библиотеки gstreamer (версия библиотек 1.15.2, версия Android Studio 3.3.2):

  • перво наперво необходимо 1 раз внести изменения в файлы библиотек (для установки в Windows 7):

- в файлах «include\gmp.h» («C:\gstreamer\armv7\include/gmp.h», «C:\gstreamer\armv64\include\gmp.h» и остальных, если gstreamer установлен в «C:\gstreamer») всех платформ меняем «-fuse-ld=gold» на «-fuse-ld=gold.exe» (встречается только 1 раз),я вносил изменения с помощью программы Notepad++;

- в файлах «gstreamer-1.0.mk» («C:\gstreamer\armv7\share\gst-android\ndk-build\gstreamer-1.0.mk» и остальных, если gstreamer установлен в «C:\gstreamer») всех платформ меняем в 168 строке «$(call assert-defined, SYSROOT_LINK)» на «SYSROOT_LINK := $(NDK_PLATFORMS_ROOT)/$(TARGET_PLATFORM)/arch-$(TARGET_ARCH)» (со строки 174).

  • Создаём проект с NDK, JNI, компиляция ndk-build (Step 2).
  • Содержимое «Android.mk» взято из «tutorial_1» примеров gstreamer и модифицировано, я распаковал библиотеки для андроид в каталог «C:\gstreamer\», файл на языке си я назвал (и предварительно добавил в папку «jni» проекта) «gst_tut_01.c», соответственно shared-библиотеку (которая будет собрана из этого файла) я назвал «gst_tut_01» (сам файл библиотеки, соответственно будет называться «libgst_tut_01.so»).
/LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_MODULE := gst_tut_01 LOCAL_SRC_FILES := gst_tut_01.c LOCAL_SHARED_LIBRARIES := gstreamer_android LOCAL_LDLIBS := -llog include $(BUILD_SHARED_LIBRARY) ifeq ($(TARGET_ARCH_ABI), armeabi-v7a) GSTREAMER_ROOT := C:/gstreamer/armv7 GSTREAMER_NDK_BUILD_PATH := C:/gstreamer/armv7/share/gst-android/ndk-build/ else ifeq ($(TARGET_ARCH_ABI), arm64-v8a) GSTREAMER_ROOT := C:/gstreamer/arm64 GSTREAMER_NDK_BUILD_PATH := C:/gstreamer/arm64/share/gst-android/ndk-build/ else ifeq ($(TARGET_ARCH_ABI), x86) GSTREAMER_ROOT := C:/gstreamer/x86 GSTREAMER_NDK_BUILD_PATH := C:/gstreamer/x86/share/gst-android/ndk-build else ifeq ($(TARGET_ARCH_ABI), x86_64) GSTREAMER_ROOT := C:/gstreamer/x86_64 GSTREAMER_NDK_BUILD_PATH := C:/gstreamer/x86_64/share/gst-android/ndk-build/ endif GSTREAMER_PLUGINS := coreelements GSTREAMER_EXTRA_LIBS := -liconv include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk

Обращаю внимание, что в «Android.mk», не зависимо от платформы (Windows, Linux), путь прописывается через «/».

  • Нужно создать блок «externalNativeBuild {...}» в файле «build.gradle Module: app» в ветке «defaultConfig» (показано с начала блока, чтобы было видно куда вставлять).
defaultConfig {
applicationId "com.example.test_gst_01" minSdkVersion 23 targetSdkVersion 28 versionCode 1 versionName "1.0" testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" externalNativeBuild { ndkBuild { def gstRoot if (project.hasProperty('gstAndroidRoot')) gstRoot = project.gstAndroidRoot else gstRoot = System.env.GSTREAMER_ROOT_ANDROID arguments "NDK_APPLICATION_MK=jni/Application.mk", "GSTREAMER_JAVA_SRC_DIR=src", "GSTREAMER_ROOT_ANDROID=$gstRoot", "GSTREAMER_ASSETS_DIR=src/assets" targets "gst_tut_01" // All archs except MIPS and MIPS64 are supported abiFilters 'armeabi-v7a', 'arm64-v8a', 'x86', 'x86_64' } } }
  1. создаём код на си;
  2. оказывается в общем случае android studio не всегда нормально по умолчанию прилинковывает библиотеку «libc++_shared.so», поэтому лучше если в Вашем «Android.mk» вместо строки «LOCAL_SHARED_LIBRARIES := gstreamer_android» будет «LOCAL_SHARED_LIBRARIES := gstreamer_android c++_shared»;
  3. перед тем как начать писать код на Java, для исключения проблем с импортом «org.freedesktop.gstreamer.GStreamer» каталога с распакованными предварительно собранными библиотеками (у меня это «C:\gstreamer\arm64\share\gst-android\ndk-build\») скопировать файл «GStreamer.java» (эти файлы на всех архитектурах одинаковые) и вставить его в проект в пакет «org.freedesktop.gstreamer», в свою очередь для этого в android studio необходимо переключить вид дерева проектов на «Android», кликаем правой клавишей мыши на элемент «java» и выбираем пункт меню «New->Package», появится диалог «Choose Destination Directory», выбираем «...\app\src\main\java», жмём «ОК», появится диалог «New Package», в строке ввода нужно ввести «org.freedesktop.gstreamer», в дереве появится созданный элемент, теперь необходимо нажать правой клавишей по новому элементу и выбрать пункт меню «Paste». В файле «GStreamer.java» будет куча ошибок, чтобы их исправить нужно удалить все слова вида «@...что то написано...@»;
  4. если планируется использование androidmedia плагина (а это почти 100 %), то необходимо из каталога с распакованными предварительно собранными библиотеками (у меня это «C:\gstreamer\arm64\share\gst-android\ndk-build\») скопировать каталог «android» (в нём 3 файла .java) и вставить его в пакет «org.freedesktop.gstreamer»;
  5. в процессе создания кода на «си» android studio будет ругаться, что не может найти «#include », иногда это решается если выполнить команду «File->Invalidate Caches/Restart», этого достаточно сделать один раз, позже он всё равно будет ругаться на этот «#include » но сборка будет проходить нормально (в общем случае достаточно 1 раз сделать процедуру, после чего забить на ругань android studio на методы из «gst/gst.h»);
  6. если сборка заканчивается ошибкой например «android studio gstreamer make: *** No rule to make target tutorial_02.c, needed by tutorial_02.o», то просто внимательно проверьте ваш «Android.mk» скорее всего в нём лишний символ (в конце строк не должно быть пробелов);
  7. рекомендую ознакомиться с этой статьёй: https://habr.com/ru/post/270479/, в ней приводятся «Методы лечения различных ошибок в Android Studio при разработке проекта».

Step 4: Конвейер GStreamer В Коде *.c Android Studio

Итак, GStreamer вроде заработал, по крайней мере работают tutorial_1 … tutorial_3 (не смотря на то, что в эмуляторе они запустились, мой вариант, основанный на tutorial_3 в эмуляторе вылетает) из документации «GStreamer Android Tutorials».

Но вот с конвейером беда, в соответствии с этой информацией: https://gstreamer.freedesktop.org/documentation/installing/for-android-development.html#using-androidstudio в андроид есть свой декодер видео, называется он «androidmedia» и расположен в категории «GSTREAMER_PLUGINS := $(GSTREAMER_PLUGINS_CODECS)», такой плагин в библиотеке 1.15.2 GStreamer для Android Studio есть, но приложение будет ругаться что найти его (androidmedia) не может.
А не может найти потому что, оказывается называется он немного по другому (http://www.ohandroid.com/67892.html), а именно (в моём случае для телефона Samsung S7) «amcviddec-omxexynosavcdec», где префикс «amcviddec-» всегда один и тот же (для всех телефонов), а вот наименование второй части можно составить исходя из информации в файле «/etc/media_codecs.xml» (файл находится в смартфоне, я смотрел с помощью Total Commander), в частности для моего телефона в файле содержится запись «<MediaCodec name=”OMX.Exynos.avc.dec” type=”video/avc”>»,(avc - это кодек h264, для кодека h265 будет hevc, а для h263 - h263) соответственно убирая из имени кодека точки и записывая всё маленькими буквами получаем «omxexynosavcdec», вот теперь мы и определились с именем плагина — декодера «amcviddec-omxexynosavcdec».

Далее необходимо установить права в манифесте приложения:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.WAKE_LOCK"/> <uses-feature android:glEsVersion="0x00020000"/>

Плагины в «Android.mk»:

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS) LOCAL_MODULE := gstvideoget LOCAL_SRC_FILES := gstvideoget.c LOCAL_SHARED_LIBRARIES := gstreamer_android c++_shared LOCAL_LDLIBS := -llog -landroid include $(BUILD_SHARED_LIBRARY) ifndef GSTREAMER_ROOT_ANDROID $(error GSTREAMER_ROOT_ANDROID is not defined!) endif ifeq ($(TARGET_ARCH_ABI),armeabi-v7a) GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/armv7 else ifeq ($(TARGET_ARCH_ABI),arm64-v8a) GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/arm64 else ifeq ($(TARGET_ARCH_ABI),x86) GSTREAMER_ROOT := $(GSTREAMER_ROOT_ANDROID)/x86 else ifeq ($(TARGET_ARCH_ABI),x86_64) GSTREAMER_ROOT:= $(GSTREAMER_ROOT_ANDROID)/x86_64 else $(error Target arch ABI not supported: $(TARGET_ARCH_ABI)) endif GSTREAMER_NDK_BUILD_PATH := $(GSTREAMER_ROOT)/share/gst-android/ndk-build include $(GSTREAMER_NDK_BUILD_PATH)/plugins.mk GSTREAMER_PLUGINS := $(GSTREAMER_PLUGINS_CORE) $(GSTREAMER_PLUGINS_PLAYBACK) $(GSTREAMER_PLUGINS_CODECS) $(GSTREAMER_PLUGINS_NET) $(GSTREAMER_PLUGINS_SYS) $(GSTREAMER_PLUGINS_CODECS_RESTRICTED) $(GSTREAMER_CODECS_GPL) $(GSTREAMER_PLUGINS_ENCODING) $(GSTREAMER_PLUGINS_VIS) $(GSTREAMER_PLUGINS_EFFECTS) $(GSTREAMER_PLUGINS_NET_RESTRICTED) GSTREAMER_EXTRA_DEPS := gstreamer-player-1.0 gstreamer-video-1.0 glib-2.0 include $(GSTREAMER_NDK_BUILD_PATH)/gstreamer-1.0.mk


Послесловие: возможно плагинов слишком много (при компиляции размер папки проекта вырастает до 1,9 Гбайт), но у меня конвейер не стартует при другом раскладе, может у Вас некоторые плагины окажутся не нужны - надо тестировать.

Be the First to Share

    Recommendations

    • Made with Math Contest

      Made with Math Contest
    • Multi-Discipline Contest

      Multi-Discipline Contest
    • Robotics Contest

      Robotics Contest

    2 Discussions

    None
    YuriMat

    6 months ago

    Вау, русский язык) Статья полезная.

    1 reply
    None
    GerMtYuriMat

    Reply 6 months ago

    Пробовал собрать? Ничего я не забыл?