第八部分---FFmpeg移植到Android

最近这几天一直在搞FFmpeg的Android移植,我的目标是在Linux上对FFmpeg进行交叉编译最终得到可以push到Android目录下执行的ffmpeg可执行文件。

为了达到这个目的,完成对FFmpeg的移植,我可以说是查遍了几乎所有网络文章,试遍了网上的各种方法,但最终还是出现各种各样的错误,真是蛋蛋碎了一地阿!

刚刚开始试验的时候,在编译的时候小心脏还加速跳呢害怕失败出错,到后来试的多了,失败的多了直接没感觉了,想着反正没打算通过,很淡定了。说实话这活还是很让人纠结着急上火的。为什么人家可以顺利编译通过我就不行了呢。


好了,步入正题~~~~~~~~~~~~~~~

1、在此特意非常感谢网友Livingstone,感谢他的耐心帮助和指导。

没有Livingstone提供配置文件的话,我不可能在今天完成编译移植。

2、通过查阅网上的各种教程,我发现大家移植的最终目标大多数是要得到.so文件,然后将其放到Android工程中去,然后通过JNI调用FFmpeg的各种方法,在Android应用层上面调用FFmpeg的各种方法完成各种任务,比如视频格式转换等。

但是我目前的目标还没有定到通过JNI来调用FFmpeg的方法来完成相应的功能,我只是要得到能够在Android目录下用命令行可以执行的ffmpeg可执行文件就可以了,JNI包装的事情之后再讲。

根据这个目标我查看了一篇博文

FFmpeg在Android上的移植优化步骤 

这篇文章达到的效果和我想要的基本是一样的,所以我就一步步按照他的方法来做,出现了一个个的错误,可能是我的环境问题还是什么的最终我没有按照他的方法成功。

由于他实现的效果和我想要的一样,我就一遍一遍的修改配置文件一遍一遍的试验用了好长的时间还是失败。有同样需求的可以参考这篇文章,感觉写的不错,没准你按照他的方法通过了呢。

3、昨天下午我在讨论群FFMPEG+Live555=H.264里问了下这个问题,好心的网友Livingstone曾经做过相似的工作,发给我一个他曾经用过的配置文件,经过我修改过NDK路径后如下build_bin_ffmpeg_1.sh:

NDK=/home/wangrui/java/android-ndk-r9d
PLATFORM=$NDK/platforms/android-9/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86
CPU=armv7-a
OPTIMIZE_CFLAGS="-mfloat-abi=softfp -marm -mcpu=cortex-a8"
PREFIX=./android/$CPU
./configure --target-os=linux \
    --prefix=$PREFIX \
    --enable-cross-compile \
    --arch=arm \
    --enable-nonfree \
    --enable-asm \
    --cpu=cortex-a8 \
    --cc=$PREBUILT/bin/arm-linux-androideabi-gcc \
    --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
    --nm=$PREBUILT/bin/arm-linux-androideabi-nm \
    --sysroot=$PLATFORM \
    --extra-cflags=" -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 $OPTIMIZE_CFLAGS " \

    --disable-shared \
    --enable-static \
    --extra-ldflags="-Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib  -nostdlib -lc -lm -lz -ldl -llog -lavcodec -lavformat -lswscale -lavutil -lswresample" \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --enable-swscale \
    --disable-swresample \
    --enable-avformat \
    --enable-avcodec \
    --disable-optimizations \
    --disable-debug \
    --disable-doc \
    --disable-stripping \
    --enable-pthreads \
    --disable-yasm \
    --enable-zlib \
    --enable-pic \
    --enable-small

make clean
make  -j4 install

$PREBUILT/bin/arm-linux-androideabi-ar d libavcodec/libavcodec.a inverse.o

$PREBUILT/bin/arm-linux-androideabi-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 --dynamic-linker=/system/bin/linker $PREBUILT/lib/gcc/arm-linux-androideabi/4.8/libgcc.a

他当时移植的FFmpeg版本是2.5.3,我也用的这个版本,但结果又让我失望了:

libavcodec/opusdec.c:376: error: undefined reference to 'swr_is_initialized'
libavcodec/opusdec.c:222: error: undefined reference to 'swr_is_initialized'
libavcodec/opusdec.c:163: error: undefined reference to 'swr_init'
libavcodec/opusdec.c:169: error: undefined reference to 'swr_convert'
libavcodec/opusdec.c:236: error: undefined reference to 'swr_convert'
libavcodec/opusdec.c:117: error: undefined reference to 'swr_convert'
libavcodec/opusdec.c:408: error: undefined reference to 'swr_close'
libavcodec/opusdec.c:563: error: undefined reference to 'swr_close'
libavcodec/opusdec.c:585: error: undefined reference to 'swr_free'
libavcodec/opusdec.c:638: error: undefined reference to 'swr_alloc'

Livingstone他自己也遇到过这个问题,最终也没有解决,我想可能是FFmpeg版本的问题。

他介绍说FFmpeg的2.0版本的前后的编译移植方法可能不同,我想这也许就是试验网上的一些教程不成功的原因吧。NDK版本、FFmpeg版本都有可能影响到结果,所以要灵活点。

4、最后使用了一个开源项目的FFmpeg-android源码+上面的配置文件进行编译,居然没有出错误,真是激动的不行了。

开源项目地址是:

FFmpeg for Android

我记得之前查资料的时候看过这个项目也下载过,但是看了半天就是不知道该怎么用,后来就搁置了。没想到这次居然用到了。

(1)下载FFmpeg for Android项目的源码,地址http://sourceforge.net/projects/ffmpeg4android/files/20140318/我选择的是ffmpeg-2.1.4.android这个版本。

(2)将上面的build_bin_ffmpeg_1.sh文件内容copy到ffmpeg-2.1.4.android目录下。

(3)修改build_bin_ffmpeg_1.sh文件的权限

chmod 755 build_bin_ffmpeg_1.sh

(4)执行配置文件

./build_bin_ffmpeg_1.sh

(5)不出错的话,等待几分钟后会出现下面的画面:

打开ffmpeg-2.1.4.android目录,会发现多了个android目录,里面有个armv7-a文件夹里面有bin、include、lib、share和libffmpeg.so文件。

我们需要的是bin目录下的ffmpeg可执行文件,用file命令可以查看它的属性:

wangrui@wangrui:~/345/ffmpeg-2.1.4.android/android/armv7-a/bin$ file ffmpeg 
ffmpeg: ELF 32-bit LSB  executable, ARM, EABI5 version 1 (SYSV), dynamically linked (uses shared libs), stripped

可以看出其是ARM下的可执行文件,大小9.1M。

(6)将bin目录下的可执行文件push到Android的/data/misc/目录下

wangrui@wangrui:~$ adb push /home/wangrui/345/ffmpeg-2.1.4.android/android/armv7-a/bin/ffmpeg  /data/misc/ffmpeg

可以看到在/data/misc目录下有ffmpeg文件,说明push成功

root@android:/ # cd data/misc/                                                 
root@android:/data/misc # ll
drwxrwxr-x root     root              2015-03-04 18:52 -r
drwxrwxr-x root     root              2015-03-04 18:52 -rf
drwxrwx--- system   system            2000-01-01 08:02 bluetooth
drwxrwx--- bluetooth bluetooth          2000-01-01 08:00 bluetoothd
drwxrwx--- dhcp     dhcp              2015-03-10 17:12 dhcp
<span style="color:#FF0000;">-rwxrwxrwx root     root      9145536 2015-03-10 10:48 ffmpeg</span>
drwx------ nobody   root              2015-03-05 18:04 hls
drwxrwxr-x root     root              2015-03-04 18:52 html
drwxrwx--x system   system            2000-01-01 08:00 keychain
drwx------ keystore keystore          2000-01-01 08:00 keystore
drwxrwxr-x root     root              2015-03-04 18:52 logs
drwxrwxrwx root     root              2015-03-04 19:15 nginx
drwxrwxr-x root     root              2015-03-05 18:04 nginx-rtmp
drwx------ system   system            2000-01-01 08:00 systemkeys
drwxrwx--- system   vpn               2000-01-01 08:00 vpn
drwxrwxrwx wifi     wifi              2000-03-13 16:55 wifi

(7)执行ffmpeg文件

./ffmpeg

显示如下:

root@android:/data/misc # ./ffmpeg                                             
ffmpeg version 2.1.4 Copyright (c) 2000-2014 the FFmpeg developers
  built on Mar 10 2015 10:48:10 with gcc 4.8 (GCC)
  configuration: --target-os=linux --prefix=./android/armv7-a --enable-cross-compile --arch=arm --enable-nonfree --enable-asm --cpu=cortex-a8 --cc=/home/wangrui/java/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-linux-androideabi-gcc --cross-prefix=/home/wangrui/java/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-linux-androideabi- --nm=/home/wangrui/java/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86/bin/arm-linux-androideabi-nm --sysroot=/home/wangrui/java/android-ndk-r9d/platforms/android-9/arch-arm/ --extra-cflags=' -O3 -fpic -DANDROID -DHAVE_SYS_UIO_H=1 -mfloat-abi=softfp -marm -mcpu=cortex-a8 '
  libavutil      52. 48.101 / 52. 48.101
  libavcodec     55. 39.101 / 55. 39.101
  libavformat    55. 19.104 / 55. 19.104
  libavdevice    55.  5.100 / 55.  5.100
  libavfilter     3. 90.100 /  3. 90.100
  libswscale      2.  5.101 /  2.  5.101
  libswresample   0. 17.104 /  0. 17.104
Hyper fast Audio and Video encoder
usage: ffmpeg [options] [[infile options] -i infile]... {[outfile options] outfile}...

Use -h to get full help or, even better, run 'man ffmpeg'

5、最后我将我编译出来的可执行文件上传了,有需要的话可以下载试试看。

http://download.csdn.net/detail/xdwyyan/8488351


6、总结

FFmpeg的移植工作可以说费了我非常大的精力,经历了一遍一遍的失败,一遍一遍的尝试,好在最终成功。

网上的一些教程可能是根据自己的环境配置进行的,对于其他人并不一定行的通,包括我这个方法别人也可能会编译出错,但是这没什么。多试验几次,多尝试下相信最终还是会成功的。


Logo

更多推荐