ubuntu下NDK9交叉编译ffmpeg

废话:

闲来蛋疼地搞起来好久没弄的NDK编程,念头一起想把之前一直没编译的ffmpeg编译一遍。

太久没用,折腾来好久,果然知识都生疏,所以还是整理一下吧。


正文:

先说说自己的环境配置,不同环境下确实还是有不少差别的。

操作系统:ubuntu 12 

NDK版本:r9        ffmpeg版本:2.0.1


资源准备:
1. ffmpeg
直接下载:
       http://www.ffmpeg.org/releases/ 下载对应的版本
GIT下载:
     在终端使用
     git clone git://git.videolan.org/ffmpeg.git
or     
   git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
  (新建一个文件夹并命名为ffmpeg,进入该文件夹下,输入git指令)

2.Android NDK r9
   自己下载

开始编译:
简要总结如下,

1.将下载下来的ffmpeg拷贝到目标路径下($NDK/sources,$NDK为NDK所在的路径)
2.修改configure文件
由于找到以下4行,
SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR) $(SLIBNAME)'

并替换改成
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'
LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'
SLIB_INSTALL_LINKS='$(SLIBNAME)'
理由:为了 libavcodec.so等共享库编译成适用于Android平台的。

3.编写build_android.sh
内容如下:可根据具体需要进行删减。注意中间不要留空行。

编写后,执行
sudo chmod +x build_android.sh
./build_android.sh

build_android.sh的内容尝试了2种方法。
基于NDK9并以android-8为目标版本进行编译,交叉工具链采用NDK中最低版本4.6.

法1:编译生成多个动态库,成功编译后,将在$(pwd)/android/arm生成具体的动态库和头文件
build_android.sh:
#!/bin/bash
NDK=$HOME/Android/android-ndk-r9
SYSROOT=$NDK/platforms/android-8/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86
function build_one
{
./configure \
    --prefix=$PREFIX \
    --enable-shared \
    --disable-static \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-avdevice \
    --disable-doc \
    --disable-symver \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --target-os=linux \
    --arch=arm \
    --enable-cross-compile \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS" \
    $ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
CPU=arm
PREFIX=$(pwd)/android/$CPU 
ADDI_CFLAGS="-marm"
build_one


法2:基本思路就是,先编译成静态库,再将各个静态库编译成一个动态库libffmpeg.so
成功编译后,将在$(pwd)/android/arm生成具体的静态库和头文件,以及libffmpeg动态库。
#!/bin/bash
NDK=$HOME/Android/android-ndk-r9
PLATFORM=$NDK/platforms/android-8/arch-arm/
PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.6/prebuilt/linux-x86
function build_one
{
./configure \
    --prefix=$PREFIX \
    --disable-shared \
    --enable-static \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-avdevice \
    --disable-doc \
    --disable-symver \
    --disable-everything \
    --enable-decoder=h264 \
    --cross-prefix=$PREBUILT/bin/arm-linux-androideabi- \
    --target-os=linux \
    --arch=arm \
    --enable-cross-compile \
    --sysroot=$PLATFORM \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS" \
    $ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}
function build_d
{
$PREBUILT/bin/arm-linux-androideabi-ar d libavcodec/libavcodec.a inverse.o
$PREBUILT/bin/arm-linux-androideabi-ld -rpath-link=$PLATFORM/usr/lib -L$PREBUILT/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 libswresample/libswresample.a -lc -lm -lz -ldl -llog  --warn-once  --dynamic-linker=/system/bin/linker $PREBUILT/lib/gcc/arm-linux-androideabi/4.6/libgcc.a
}
function build_d0
{
$PREBUILT/bin/arm-linux-androideabi-gcc --sysroot=$PLATFORM -shared -o $PREFIX/libffmpeg.so \
	-Wl,--whole-archive libavcodec/libavcodec.a libavformat/libavformat.a libavutil/libavutil.a libswscale/libswscale.a libswresample/libswresample.a \
	-Wl,--no-whole-archive -lm -lz
}
CPU=arm
PREFIX=$(pwd)/android/$CPU 
ADDI_CFLAGS="-marm"
build_one
build_d0


编译成功后如何调用?

1.如果是按法1直接生成多个动态库的话
先在$NDK/sources/ffmpeg-2.0.1/android/arm/Android.mk中声明各个动态库为共享库
Android.mk内容如下:
LOCAL_PATH:= $(call my-dir)
 
include $(CLEAR_VARS)
LOCAL_MODULE:= libavcodec
LOCAL_SRC_FILES:= lib/libavcodec-55.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
 
include $(CLEAR_VARS)
LOCAL_MODULE:= libavformat
LOCAL_SRC_FILES:= lib/libavformat-55.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
 
include $(CLEAR_VARS)
LOCAL_MODULE:= libswscale
LOCAL_SRC_FILES:= lib/libswscale-2.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
 
include $(CLEAR_VARS)
LOCAL_MODULE:= libavutil
LOCAL_SRC_FILES:= lib/libavutil-52.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
 
include $(CLEAR_VARS)
LOCAL_MODULE:= libavfilter
LOCAL_SRC_FILES:= lib/libavfilter-3.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
 
include $(CLEAR_VARS)
LOCAL_MODULE:= libwsresample
LOCAL_SRC_FILES:= lib/libswresample-0.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)

然后,参照 https://github.com/roman10/android-ffmpeg-tutorial例程中进行jni调用。
注意在jni中的Android.mk编写,加入编译出来的动态库,和头文件所在路径等
LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := tutorial01
LOCAL_SRC_FILES := tutorial01.c
LOCAL_LDLIBS := -llog -ljnigraphics -lz 
LOCAL_SHARED_LIBRARIES := libavformat libavcodec libswscale libavutil 
include $(BUILD_SHARED_LIBRARY)
$(call import-module,ffmpeg-2.0.1/android/arm)

经测试,利用法1编写的Android测试项目可以成功运行。

按法2,虽然将多个静态库编译成一个动态库,但应用时似乎函数有所缺失。待测试。


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值