ffmpeg on Android – adding Vmware and Ubuntu to best practice

I wanted to work with FFMPEG libs on android ICS and found the excellent prior work by “roman10″ here and here. Note that roman’s source will be required from item 5 in the 2nd of the above links. Alot of associated forum traffic links to roman’s how-to with compile questions/errors or problems with specific cross toolchains. In order to distill the build process and to add a bit to the earlier work, heres my experience on Windows 64 platform where i added Vmware and Ubuntu (64 bit with additional i386 libs compatible with the 32 bit NDK )  specifically for work with ffmpeg on android. Im a veteran windows cygwin / MingW user but this time, rather than to use MingW and native windows I chose a vm based on what i learned from others in the forums. With some minor tweeks, the VM approach using following work OK:

  • VMPlayer
  • Ubuntu 12.04
  • open java-jdk
  • Ant
  • android SDK
  • android NDK

At the end of the build you will have an android apk including the libffmpeg.so and the so for the jni c-file of roman10.
I believe that libffmpeg.so has the following linked statically:


-o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a 

I used the following steps:

INSTALL VMWare Player and link it to ISO with Ubuntu 12.04

Vmware player app is free and needs a separate Ubuntu ISO image. After install of the player on windows , you can install the ISO and will then have Linux version running in the VM.

Get the iso for Ubuntu 12.04 (64 bit) here

Get the VMPLAYER app. here

Install vmplayer. Start it up.

Find menu for “create new virtual machine” in the player app.

Select the ISO file, finish the dialog and you will have a new VM environment for Ubuntu.

UPDATE Ubuntu

RTFM on “apt-get” if needed. Docs on open JDK here.

start a terminal shell in Ubuntu by using the “Dash” icon at the top of the left-hand list of icons in the Ubuntu “unity” GUI.

  1. sudo apt-get update    // this updates repo data used by the package manager
  2. sudo apt-get install curl // needed for downloads
  3. sudo apt-get  install openjdk-6-jdk // installs the jdk needed by Ant and by Android SDK
  4. sudo apt-get -u install ant  // Ant will be needed for building Android projects
  5. cd ~/       // this will get you to your home directory
  6. mkdir src   // create a child in your home path for source code
  7. unix home dir will look like below:
   
 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Desktop 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Documents 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Downloads 
-rw-r--r-- 1 rob rob 8445 Jun 15 09:25 examples.desktop 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Music 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Pictures 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Public 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 src 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Templates 
drwxr-xr-x 2 rob rob 4096 Jun 15 09:36 Videos 

read about the “ialibs” here. Instead of the sledgehammer ialabs approach, install much smaller “i386″ libs in the list:

   
 
sudo apt-get install libgcc1:i386 
sudo apt-get install zlib1g:i386 
sudo apt-get install tzdata:i386 
sudo apt-get install libstdc++6:i386 
sudo apt-get install libncurses5-dev:i386 

Your linux env should now have libs required for 32 bit cross toolchains.

Install SDK and NDK

   
 
$ curl -#LO http://dl.google.com/android/android-sdk_r18-linux.tgz //get sdk 
$ cd src src$ tar -xzf ../android-sdk_r18-linux.tgz //unpack sdk in src dir 
$ curl -#LO http://dl.google.com/android/ndk/android-ndk-r8-linux-x86.tar.bz2 // get NDK 
$ cd src $ tar -xvf ../android-ndk-r8-linux-x86.tar.bz2 //unpack ndk in src dir 

edit the file ~/.bashrc // adding following ENV 
$export PATH=$PATH:/home/rob/src/android-sdk-linux/platform-tools // add the location of the SDK's tools to Path 
$export PATH=$PATH:/home/rob/src/android-sdk-linux/tools //add the location of the SDK's tools to Path 
$export JAVA_HOME=/usr/lib/jvm/java-6-openjdk-amd64 //add java to path if not there 
$export NDK=/home/rob/src/android-ndk-r8 // add ndk to path 

Read the docs in the $ndk/docs directory.

Run the script to make the standalone toolchain from the NDK .

   
 
$NDK/build/tools/make-standalone-toolchain.sh --arch=arm --ndk-dir=$NDK --platform=android-14 --install-dir=/tmp/my-android-toolchain 

Auto-config: --toolchain=arm-linux-androideabi-4.4.3 
Copying prebuilt binaries... 
Copying sysroot headers and libraries... 
Copying libstdc++ headers and libraries... 
Copying files to: /tmp/my-android-toolchain 

Install Roman10 source for Android FFmpeg

   
 
$ curl -#LO http://www.roman10.net/src/ffmpegtest.tar.gz //get ffmpeg 
$ cd src src
$ tar -xzf ../ffmpegtest.tar.gz //unpack sdk in src dir ~/src/FFmpegTest is home of roman10 project 

Integrate Ant with the Android project FFmpegTest
Update the android project with ant wrapper files:


$ cd ~/src
$ android create project -n FFmpegTest -t 1 -p FFmpegTest -k roman10.ffmpegTest -a FFmpegView

add a required ant xml file described below:

<?xml version=”1.0″ encoding=”UTF-8″?>
<project name=”FFmpegTest”>
<target name=”-pre-build”>
<exec executable=”${ndk.dir}/ndk-build” failonerror=”true”/>
</target>

<target name=”clean” depends=”android_rules.clean”>
<exec executable=”${ndk.dir}/ndk-build” failonerror=”true”>
<arg value=”clean”/>
</exec>
</target>
</project>

Put the xml above into file ./FFMpegTest/custom_rules.xml where it will get picked up by the ant build. Note that eclipse is not being used in this example ( not necessary). 

Update ./FFmpegTest/jni/ffmpeg-0.8/build_android.sh

Note that i already set the ENV for $NDK and that i want armv7-a without neon , so the following changes in build_android.sh are necessary.


 

#NDK=~/Desktop/android/android-ndk-r5b
PLATFORM=$NDK/platforms/android-14/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.4.3/prebuilt/linux-x86

...

#arm v7n
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp  -marm -march=$CPU -mtune=cortex-a8"
PREFIX=./android/$CPU 
ADDITIONAL_CONFIGURE_FLAG=
build_one

Build the Project

run the build_android.sh

you should have the following in ./jni/ffmpeg-0.8:


 
rob@ubuntu:ffmpeg-0.8$ ls -l android/armv7-a/
total 5684
drwxrwxr-x 2 rob rob    4096 Jun 16 11:37 bin
drwxrwxr-x 6 rob rob    4096 Jun 16 11:11 include
drwxrwxr-x 3 rob rob    4096 Jun 16 11:37 lib
-rwxrwxr-x 1 rob rob 5800015 Jun 16 11:37 libffmpeg.so
drwxrwxr-x 3 rob rob    4096 Jun 16 11:11 share

run ant in the project root where the build.xml file is.


ant -Dndk.dir=/home/rob/src/android-ndk-r8 -verbose -logfile ./build.log  debug

content bin dir should be below:


 
rob@ubuntu:FFmpegTest$ ls -l bin
total 1692
-rw-rw-r-- 1 rob rob    179 Jun 16 11:50 build.prop
drwxrwxr-x 4 rob rob   4096 Jun 16 11:50 classes
-rw-rw-r-- 1 rob rob  27560 Jun 16 11:50 classes.dex
-rw-rw-r-- 1 rob rob   2626 Jun 16 11:50 classes.dex.d
-rw-rw-r-- 1 rob rob  41452 Jun 16 11:50 FFmpegTest.ap_
-rw-rw-r-- 1 rob rob   2012 Jun 16 11:50 FFmpegTest.ap_.d
-rw-rw-r-- 1 rob rob 812849 Jun 16 11:50 FFmpegTest-debug.apk
-rw-rw-r-- 1 rob rob 812828 Jun 16 11:50 FFmpegTest-debug-unaligned.apk
-rw-rw-r-- 1 rob rob    340 Jun 16 11:50 FFmpegTest-debug-unaligned.apk.d
-rw-rw-r-- 1 rob rob    119 Jun 16 11:50 jarlist.cache

About these ads

3 thoughts on “ffmpeg on Android – adding Vmware and Ubuntu to best practice

  1. hello
    I want to compile ffmpeg or libogg for android live streaming app..
    I al using mac os x and new NDK r8b.. i want to compile ffmpeg or libogg for android . i tried to compile it by using romain tutorial but it failes on executing script config.sh . i have made changes according prebuild and platform but it wont work…
    it shows ” /Users/swapnil/android-ndk/toolchains/x86-4.6/prebuilt/darwin-x86/bin/i686-linux-android-gccgcc is unable to create an executable file.
    C compiler test failed. ”

    and my script is this …

    #!/bin/bash
    ######################################################
    # Usage:
    # put this script in top of FFmpeg source tree
    # ./build_android
    #
    # It generates binary for following architectures:
    # ARMv6
    # ARMv6+VFP
    # ARMv7+VFPv3-d16 (Tegra2)
    # ARMv7+Neon (Cortex-A8)
    #
    # Customizing:
    # 1. Feel free to change ./configure parameters for more features
    # 2. To adapt other ARM variants
    # set $CPU and $OPTIMIZE_CFLAGS
    # call build_one
    ######################################################
    #change these three lines if you want to build using different vesion of Android ndk
    #build_one is for ndk 5, and build_one_r6 is for ndk 6
    NDK=~/android-ndk
    PLATFORM=$NDK/platforms/android-14/arch-arm/
    PREBUILT=$NDK/toolchains/x86-4.6/prebuilt/darwin-x86
    function build_one_r6
    {
    ./configure \
    –disable-shared \
    –enable-static \
    –enable-gpl \
    –enable-version3 \
    –enable-nonfree \
    –disable-doc \
    –disable-ffmpeg \
    –disable-ffplay \
    –disable-ffprobe \
    –disable-ffserver \
    –disable-avdevice \
    –disable-avfilter \
    –disable-postproc \
    –enable-small \
    –cross-prefix=$PREBUILT/bin/i686-linux-android-gcc \
    –enable-cross-compile \
    –target-os=linux \
    –extra-cflags=”-I$PLATFORM/usr/include” \
    –extra-ldflags=”-L$PLATFORM/usr/lib -nostdlib” \
    –arch=arm \
    –disable-symver \
    –disable-debug \
    –disable-stripping \
    $ADDITIONAL_CONFIGURE_FLAG
    sed -i ‘s/HAVE_LRINT 0/HAVE_LRINT 1/g’ config.h
    sed -i ‘s/HAVE_LRINTF 0/HAVE_LRINTF 1/g’ config.h
    sed -i ‘s/HAVE_ROUND 0/HAVE_ROUND 1/g’ config.h
    sed -i ‘s/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g’ config.h
    sed -i ‘s/HAVE_TRUNC 0/HAVE_TRUNC 1/g’ config.h
    sed -i ‘s/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g’ config.h
    make clean
    make -j4 install
    $PREBUILT/bin/i686-linux-android-ar d libavcodec/libavcodec.a inverse.o
    $PREBUILT/bin/i686-linux-android-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -soname libffmpeg.so -shared -nostdlib -z,noexecstack -Bsymbolic –whole-archive –no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a -lc -lm -lz -ldl -llog –warn-once –dynamic-linker=/system/bin/linker $PREBUILT/lib/gcci686-linux-android/4.6.x-google/libgcc.a
    }
    function build_one_r6_2
    {
    $PREBUILT/bin/i686-linux-android-ar d libavcodec/libavcodec.a inverse.o
    $PREBUILT/bin/i686-linux-android-ld -rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -soname libffmpeg.so -shared -nostdlib -z,noexecstack -Bsymbolic –whole-archive –no-undefined -o $PREFIX/libffmpeg.so libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a -lc -lm -lz -ldl -llog –warn-once –dynamic-linker=/system/bin/linker $PREBUILT/lib/gcc/i686-linux-android/4.6.x-google/libgcc.a
    }
    #arm v6
    #CPU=armv6
    #OPTIMIZE_CFLAGS=”-marm -march=$CPU”
    #PREFIX=./android/$CPU
    #ADDITIONAL_CONFIGURE_FLAG=
    #build_one
    #arm v7vfpv3
    CPU=armv7-a
    OPTIMIZE_CFLAGS=”-mfloat-abi=softfp -mfpu=vfpv3-d16 -marm -march=$CPU ”
    PREFIX=./android/$CPU
    ADDITIONAL_CONFIGURE_FLAG=
    #build_one
    build_one_r6
    #arm v7vfp
    #CPU=armv7-a
    #OPTIMIZE_CFLAGS=”-mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU ”
    #PREFIX=./android/$CPU-vfp
    #ADDITIONAL_CONFIGURE_FLAG=
    #build_one
    #arm v7n
    #CPU=armv7-a
    #OPTIMIZE_CFLAGS=”-mfloat-abi=softfp -mfpu=neon -marm -march=$CPU -mtune=cortex-a8″
    #PREFIX=./android/$CPU
    #ADDITIONAL_CONFIGURE_FLAG=–enable-neon
    #build_one
    #arm v6+vfp
    #CPU=armv6
    #OPTIMIZE_CFLAGS=”-DCMP_HAVE_VFP -mfloat-abi=softfp -mfpu=vfp -marm -march=$CPU”
    #PREFIX=./android/${CPU}_vfp
    #ADDITIONAL_CONFIGURE_FLAG=
    #build_one

    please Share your New working script for NDK r8b and Mac os

  2. Hi, Rob. I’d like to talk to you about some Android/Java/ffmpeg work. Based on your VOIP experience, and comments on Stack Overflow, I think you’ll at least find it an interesting conversation (though this isn’t a telephony app). If it’s not for you, maybe you can point me to someone else. Contact me at karl [at] lautman [dot] cmo (deliberately misspelled).

    - Karl (founder)

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s