Pull to refresh
0

Перекомпиляция Android библиотек под х86. JavaCV и Alljoyn

Reading time 8 min
Views 6.6K
Android смартфоны на базе процессоров Intel Atom уже перестали быть экзотикой, и тема оптимизации библиотек и приложений под х86 платформу перешла из теоретической плоскости в чисто практическую: софт, одинаково хорошо работающий и на ARM, и на х86 в конечном счете будет иметь преимущество перед тем, что оптимизирован только под одну архитектуру. В связи с этим мы посчитали полезным перевести две статьи инженера Intel Ксавье Алляда (Xavier Hallade), описывающие практические примеры перекомпиляции Android библиотек под х86.

Получение х86 версии JavaCV под Android

JavaCV представляет собой обертку (wrapper) для библиотек OpenCV и ffmpeg. В то время как эти библиотеки отлично совместимы с х86 версией Android, JavaCV не имеет соответствующих скриптов сборки и не интегрирован в бинарники х86.
Хотя компиляция подходящих х86 версий пакетов JavaCV и не займет много времени, для самых торопливых сразу же приведем ссылки:

Теперь давайте посмотрим, что нам потребовалось для сборки. Вам понадобятся традиционные средства сборки (gcc, make, …), а также maven.
Для начала необходимо перекомпилировать cppjars

Перекомпилирование cppjars (OpenCV и ffmpeg)
Этого легко достичь, используя скрипты сборки, прилагаемые к пакету cppjars:

wget https://javacv.googlecode.com/files/javacv-0.7-cppjars.zip
unzip javacv-0.7-cppjars.zip
cd javacv-cppjars

Скрипты сборки для Android: build_opencv-android-arm.sh и build_ffmpeg-android-arm.sh. Нам нужно создать эквивалентные build_opencv-android-x86.sh и build_ffmpeg-android-x86.sh. Для этого в -х86 копиях заменим:
  • arm-linux-androideabi- на i686-linux-android- (префикс бинарника toolchain)
  • arm-linux-androideabi- на x86- (toolchain)
  • -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mfpu=neon… на -mtune=atom -mssse3 -mfpmath=sse (флаги компилятора)
  • arm-linux на i686-linux
  • прочие суффиксы -arm на -x86

Не делайте этого вслепую – все будет работать лучше, если вы понимаете, что делаете :)

Вот что в результате у меня получилось в файле build_ffmpeg-android-x86.sh:

ANDROID_BIN=$ANDROID_NDK/toolchains/x86-4.8/prebuilt/linux-x86_64/bin
ANDROID_ROOT=$ANDROID_NDK/platforms/android-14/arch-x86
tar -xjvf ffmpeg-$FFMPEG_VERSION.tar.bz2
mv ffmpeg-$FFMPEG_VERSION ffmpeg-$FFMPEG_VERSION-android-x86
cd ffmpeg-$FFMPEG_VERSION-android-x86
tar -xjvf ../last_stable_x264.tar.bz2
X264=`echo x264-snapshot-*`
cd $X264
./configure --enable-static --enable-pic --disable-cli --disable-opencl --cross-prefix=$ANDROID_BIN/i686-linux-android- --sysroot=$ANDROID_ROOT --host=i686-linux --extra-cflags="-fpic -pipe -DANDROID -DNDEBUG -mtune=atom -mssse3 -ffast-math -mfpmath=sse -fomit-frame-pointer -fstrict-aliasing -funswitch-loops -finline-limit=300" --extra-ldflags="-lm -lz -Wl,--no-undefined -Wl,-z,noexecstack"
make -j8
cd ../
patch -p1 < ../ffmpeg-$FFMPEG_VERSION-android-x86.patch
./configure --prefix=$ANDROID_NDK/../ --enable-shared --enable-gpl --enable-version3 --enable-libx264 \
 --disable-static --disable-symver --disable-doc --disable-ffplay --disable-ffmpeg --disable-ffprobe --disable-ffserver --disable-encoders --disable-muxers --disable-devices --disable-demuxer=sbg --disable-demuxer=dts --disable-parser=dca --disable-decoder=dca --disable-decoder=svq3 --enable-network --enable-version3 --disable-amd3dnow --disable-amd3dnowext --disable-outdev=sdl\
 --extra-cflags="-I$X264" --extra-ldflags="-L$X264" --enable-cross-compile --cc=$ANDROID_BIN/i686-linux-android-gcc --sysroot=$ANDROID_ROOT --target-os=linux --arch=x86 --cpu=i686 \
--enable-asm --enable-yasm --enable-pic --extra-cflags="-DANDROID -DNDEBUG -fPIC -pipe -mtune=atom -mssse3 -ffast-math -mfpmath=sse" \
--extra-ldflags="-lm -lz -Wl,--no-undefined -Wl,-z,noexecstack" --disable-stripping --disable-symver --disable-programs

make -j8
LIBS="libavcodec/libavcodec.so libavdevice/libavdevice.so libavfilter/libavfilter.so libavformat/libavformat.so libavutil/libavutil.so libpostproc/libpostproc.so libswresample/libswresample.so libswscale/libswscale.so"
$ANDROID_NDK/toolchains/x86-4.8/prebuilt/linux-x86_64/bin/i686-linux-android-strip $LIBS
mkdir -p com/googlecode/javacv/cpp/android-x86/
cp $LIBS com/googlecode/javacv/cpp/android-x86/
jar cvf ../ffmpeg-$FFMPEG_VERSION-android-x86.jar com/
rm -Rf com/
cd ../

Здесь ffmpeg-$FFMPEG_VERSION-android-x86.patch точно тот же самый, что и в arm версии, можете его просто скопировать.
А вот файл build_opencv-android-x86.sh:

tar -xzvf opencv-$OPENCV_VERSION.tar.gz
mkdir opencv-$OPENCV_VERSION/build_android-x86
cd opencv-$OPENCV_VERSION
cd build_android-x86
ANDROID_BIN=$ANDROID_NDK/toolchains/x86-4.6/prebuilt/linux-x86_64/bin/ \
ANDROID_CPP=$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/ \
ANDROID_ROOT=$ANDROID_NDK/platforms/android-9/arch-x86/ \
cmake -DCMAKE_TOOLCHAIN_FILE=platforms/android/android.toolchain.cmake -DANDROID_ABI=x86 -DOPENCV_EXTRA_C_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse" -DOPENCV_EXTRA_CXX_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse" -DCMAKE_INSTALL_PREFIX=$ANDROID_NDK/../ -DBUILD_SHARED_LIBS=ON -DBUILD_TESTS=OFF -DBUILD_PERF_TESTS=OFF -DBUILD_ANDROID_EXAMPLES=OFF -DBUILD_JASPER=ON -DBUILD_JPEG=ON -DBUILD_OPENEXR=ON -DBUILD_PNG=ON -DBUILD_TBB=ON -DBUILD_TIFF=ON -DBUILD_ZLIB=ON -DBUILD_opencv_java=OFF -DBUILD_opencv_python=OFF -DENABLE_PRECOMPILED_HEADERS=OFF -DWITH_1394=OFF -DWITH_FFMPEG=OFF -DWITH_GSTREAMER=OFF -DWITH_TBB=ON -DWITH_CUDA=OFF -DWITH_OPENCL=OFF ..
make -j8
LIBS="lib/x86/libopencv*.so lib/x86/libtbb.so"
$ANDROID_NDK/toolchains/x86-4.6/prebuilt/linux-x86_64/bin/i686-linux-android-strip $LIBS
mkdir -p com/googlecode/javacv/cpp/android-x86/
cp $LIBS com/googlecode/javacv/cpp/android-x86/
jar cvf ../../opencv-$OPENCV_VERSION-android-x86.jar com/
rm -Rf com/
cd ../../

Здесь я удалил вызов -arm патча, который генерировал другой android.mk файл и положился на platforms/android/android.toolchain.cmake, предоставляемый OpenCV, а также добавил некоторые специфичные флаги для большей оптимизации:

-DANDROID_ABI=x86 -DOPENCV_EXTRA_C_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse" -DOPENCV_EXTRA_CXX_FLAGS="-O3 -ffast-math -mtune=atom -mssse3 -mfpmath=sse"

Теперь если вы выполните:

sh ./build_all.sh android-x86
cd ..

То получите ffmpeg-2.1.1-android-x86.jar и opencv-2.4.8-android-x86.jar.
Теперь мы, наконец, можем собрать пакет JavaCV.

Сборка х86 версии JavaCV
Сначала скачайте и установите JavaCPP:

git clone https://code.google.com/p/javacpp/
cd javacpp/
git checkout 0.6
mvn install
cd ..

После скачайте исходники JavaCV:

git clone https://code.google.com/p/javacv/
cd javacv
git checkout 0.7

Теперь вы можете собрать android-x86 версию JavaCV, установив свойство android-x86 в JavaCPP:

mvn package -Pffmpeg -Djavacpp.options="-properties android-x86 -Dplatform.root=$ANDROID_NDK -Dcompiler.path=$ANDROID_NDK/toolchains/x86-4.6/prebuilt/linux-x86_64/bin/i686-linux-android-g++ -Dcompiler.includepath=$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/include\
:$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/x86/include\
:../javacv-cppjars/opencv-2.4.8/build_android-x86/\
:../javacv-cppjars/opencv-2.4.8/modules/core/include\
:../javacv-cppjars/opencv-2.4.8/modules/androidcamera/include\
:../javacv-cppjars/opencv-2.4.8/modules/flann/include\
:../javacv-cppjars/opencv-2.4.8/modules/imgproc/include\
:../javacv-cppjars/opencv-2.4.8/modules/highgui/include\
:../javacv-cppjars/opencv-2.4.8/modules/features2d/include\
:../javacv-cppjars/opencv-2.4.8/modules/calib3d/include\
:../javacv-cppjars/opencv-2.4.8/modules/ml/include\
:../javacv-cppjars/opencv-2.4.8/modules/video/include\
:../javacv-cppjars/opencv-2.4.8/modules/legacy/include\
:../javacv-cppjars/opencv-2.4.8/modules/objdetect/include\
:../javacv-cppjars/opencv-2.4.8/modules/photo/include\
:../javacv-cppjars/opencv-2.4.8/modules/gpu/include\
:../javacv-cppjars/opencv-2.4.8/modules/nonfree/include\
:../javacv-cppjars/opencv-2.4.8/modules/contrib/include\
:../javacv-cppjars/opencv-2.4.8/modules/stitching/include\
:../javacv-cppjars/opencv-2.4.8/modules/ts/include\
:../javacv-cppjars/opencv-2.4.8/modules/videostab/include\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86 \
-Dcompiler.linkpath=$ANDROID_NDK/sources/cxx-stl/gnu-libstdc++/4.6/libs/x86\
:../javacv-cppjars/opencv-2.4.8/build_android-x86/lib/x86\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libswscale\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavcodec\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libswresample\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libpostproc\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavfilter\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavformat\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavutil\
:../javacv-cppjars/ffmpeg-2.1.1-android-x86/libavdevice"

Вы найдете собранные пакеты в папке target/:

2.7M Jan 15 19:09 javacv-android-x86.jar
3.6M Jan 15 19:09 javacv-bin.zip
747K Jan 15 19:09 javacv-src.zip
734K Jan 15 19:09 javacv.jar

Добавление х86 версии в ваше приложение
Из пакетов, скачанных по ссылкам в начале статьи или из тех, что вы только что собрали, вы можете скопировать сгенерированные файлы .so, находящиеся внутри javacv-android-x86.jar, ffmpeg-2.1.1-android-x86.jar и opencv-2.4.8-android-x86.jar в папку /lib/x86/ вашего Android пакета, точно так же, как и arm версии в папку /lib/armeabi-v7a/.

х86 версия Alljoyn для Android

Alljoyn – это кросс-платформенная библиотека для peer-to-peer связи между различными устройствами с использованием различных транспортов.
Библиотека имеет открытый исходный код (лицензия Apache), изначально она создана в Qualcomm Innovation Center. Проект присоединился к AllSeen Alliance и теперь хостится здесь.
Даже в том случае, если прекомпилированная х86 версия отсутствует на официальном вебсайте, компилирование из исходников прекрасно поддерживается.
Когда вы скачаете пакет под Android, то увидите следующее:

cpp/    core AllJoyn functionality, implemented in C++
          - built from Git projects alljoyn_core and common
          - required for all AllJoyn applications
java/   optional Java language binding          (built from alljoyn_java)
          - required for Android apps
c/      optional ANSI C language binding        (built from alljoyn_c)
          - required by Unity binding
unity/  optional Unity language binding         (built from alljoyn_unity)
about/  implements AllJoyn About Feature. (built from about.git/(cpp and java))

Если вы используете Java обвязку alljoyn.jar, то обнаружите liballjoyn_java.so в каталоге lib/armeabi/. Бинарники (файлы .so/.a) из этого пакета предназначены только для ARMv5, но отлично собираются из исходников под другие платформы.
По этой ссылке вы можете скачать х86 версию, которую я скомпилировал для вас. Она имеет ту же архитектуру, что и версия для ARMv5.
Если вы просто используете AllJoyn .jar под Android, вы можете взять liballjoyn_java.so и поместить его в каталог lib/x86 вашего Android приложения.
Если же вы желаете сами скомпилировать бинарник и узнать больше об этом процессе, вот описание того, что я сделал.

Компиляция Alljoyn для x86 платформы под Android
Первым делом скачайте исходники:

git clone https://git.allseenalliance.org/gerrit/core/alljoyn
cd alljoyn

Затем возьмите libcrypto.so и libssl.so с реального x86 устройства или x86 эмулятора и поместите их в папку build/android/x86/release/dist/cpp/lib/:

mkdir -p build/android/x86/release/dist/cpp/lib/
adb pull /system/lib/libcrypto.so build/android/x86/release/dist/cpp/lib/
adb pull /system/lib/libssl.so build/android/x86/release/dist/cpp/lib/

Теперь вы можете собрать библиотеку для х86, как описано в документации; самое скучное в этом процессе – необходимость иметь копию исходников AOSP:

export CLASSPATH=/usr/share/java/junit.jar
scons OS=android CPU=x86 ANDROID_NDK=/opt/android-ndk ANDROID_SDK=/opt/android-sdk ANDROID_SRC=/home/ph0b/android-build VARIANT=release BINDINGS=cpp,c,java,unity


Оригиналы статей:
Tags:
Hubs:
+11
Comments 3
Comments Comments 3

Articles

Information

Website
www.intel.ru
Registered
Founded
Employees
5,001–10,000 employees
Location
США
Representative
Анастасия Казантаева