company_banner

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

    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
    


    Оригиналы статей:
    • +11
    • 5.7k
    • 3
    Intel
    133.46
    Company
    Share post

    Comments 3

      0
      Перестали быть экзотикой? А какие из популярных моделей используют этот процессор?

    Only users with full accounts can post comments. Log in, please.