x86-Version von JavaCV fuer Android*

JavaCV ist ein Wrapper, der hauptsächlich aus OpenCV- und ffmpeg-Bibliotheken besteht. Diese Bibliotheken sind zwar durchgehend mit dem x86-Flavor von Android kompatibel, allerdings bietet JavaCV weder Build-Skripts noch eine Integration mit den x86-Binaries.

Geeignete x86-Versionen von JavaCV-Paketen lassen sich ohne großen Aufwand kompilieren, aber wenn Sie es eilig haben, können Sie diese Dateien verwenden:

Schauen wir uns an, wie diese Versionen erstellt wurden. Zuerst einmal benötigen Sie die üblichen Build-Tools (GCC, Make usw.) und Maven*. Als Erstes müssen Sie cppjars neu kompilieren.

cppjars neu kompilieren (OpenCV und ffmpeg)
Mithilfe der im cppjars-Release-Paket enthaltenen Build-Skripts lässt sich dies einfach bewerkstelligen:

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

Die Build-Skripts für Android sind build_opencv-android-arm.sh und build_ffmpeg-android-arm.sh. Hiervon müssen wir nun die entsprechenden build_opencv-android-x86.sh- und build_ffmpeg-android-x86.sh-Versionen erstellen.

Kopieren Sie zuerst diese Skripts. Ersetzen Sie anschließend in der x86-Version Folgendes:

  • arm-linux-androideabi- durch i686-linux-android- (Präfix für Toolchain-Binaries)
  • arm-linux-androideabi- durch x86- (Toolchain)
  • -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mfpu=neon… durch -mtune=atom -mssse3 -mfpmath=sse (Compiler-Flags)
  • arm-linux durch i686-linux
  • weitere -arm-Suffixe durch -x86

Sie sollten diesen Schritt nicht blindlings durchführen, sondern verstehen, was genau passiert. 
Hier ist mein Code für 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 ../

In diesem Fall entspricht ffmpeg-$FFMPEG_VERSION-android-x86.patch exakt der ARM-Version und kann daher kopiert werden. 
Für 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 ../../

Hier habe ich den Aufruf an den -arm-Patch, der eine andere android.mk-Datei genierte, gelöscht und verlasse mich direkt auf platforms/android/android.toolchain.cmake. Diese Datei wird von OpenCV bereitgestellt. Zur Optimierung habe ich einige Flags hinzugefügt:

-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"

Rufen Sie jetzt Folgendes auf:

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

Dieser Aufruf generiert ffmpeg-2.1.1-android-x86.jar und opencv-2.4.8-android-x86.jar. Im nächsten Schritt können Sie nun das JavaCV-Paket erstellen. 

Paketierung der x86-Version von JavaCV 
Zuerst muss JavaCPP abgerufen und installiert werden:

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

Anschließend benötigen Sie den JavaCV-Quellcode:

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

Jetzt können Sie die Android-x86-Version von JavaCV paketieren, indem Sie die android-x86-Eigenschaft auf JavaCPP festlegen:

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"

Die Pakete erhalten Sie in 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

x86-Version zu Ihrer Anwendung hinzufügen

Aus den zu Beginn dieses Artikels erwähnten oder den gerade von Ihnen erstellten Paketen können Sie nun die generierten .so-Dateien, die sich in javacv-android-x86.jar, ffmpeg-2.1.1-android-x86.jar und opencv-2.4.8-android-x86.jar befinden, in den /lib/x86/-Ordner Ihres Android-Pakets kopieren, und zwar auf dieselbe Art wie die ARM-Versionen in /lib/armeabi-v7a/.

Wenn Sie mehr über die Verwendung von .so-Dateien und APKs erfahren möchten, lesen Sie diese beiden bereits früher veröffentlichten Artikel:

Dieser Beitrag ist eine Übersetzung des Artikels Getting an x86-Version of JavaCV for Android der zuerst auf der privaten Webseite des Intel Mitarbeiters Xavier Hallade veröffentlicht wurde: http://ph0b.com/getting-an-x86-version-of-javacv-for-android/#more-110