ffmpeg裁剪移植 Android
-- by flyyang
注:版权所有,如若转载请注明出处!http://blog.csdn.net/flyyang123456789/article/details/41076331
对ffmpeg Android的移植 必须裁剪 否则生成库会很大从而造成APP很大。我是移植的ffmpeg-2.4 版本。在Android工程中可以直接使用可执行文件命令行方式,
我是更改的源码,将生成ffmpeg工具的源码中的main函数改成我自己的借口 然后我自己写函数配置参数调用此接口。
先说下我的大体思路,完全在linux下操作包括jni都是在linux下完成的直接在linux生成so库在Android工程中直接使用,不用在Android工程下写jni。
我是经过 三成 封装的,原因在第三层将所有的静态库再次封装成一个动态库的时候生成的动态库变小很多。
第一层:我先编译成静态库的,先写脚本build_android.sh(在网上直接下载的)把此脚本放到ffmpeg源码根目录下 ,配置裁剪configure 参数 脚本内容如下:
#!/bin/bash
NDK=/mnt/android-ndk-r8d
SYSROOT=$NDK/platforms/android-14/arch-arm
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.7/prebuilt/linux-x86
function build_one
{
./configure \
--enable-small \
--disable-yasm \
--prefix=$PREFIX \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--target-os=linux \
--arch=arm \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_LDFLAGS " \
$ADDITIONAL_CONFIGURE_FLAG
}
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one
以上脚本ndk要改成自己ndk的路径 configure后面是跟的裁剪配置参数 ,完成后进入ffmpeg根目录下使用 chmod 777 build_android.sh 给可执行权限。
然后 ./build_android.sh
make
make install
会在ffmpeg根目录下生成android 目录 里面 lib里就是库文件(我使用静态库),include 下是头文件 到此第一层完成。
第二层:第二层 我还是生成静态库。
更改ffmpeg 的 main函数改成自己的接口。将有关ffmpeg 生成的 源文件 拷贝到新建的目录下 再建 jni目录 然后把 第一层生成的include下的所有和lib下的静态库拷贝到新建的目录下的jni目录下,然后开始写android.mk 编译 和 Application.mk 如下:
LOCAL_PATH:= $(call my-dir)#libiconv.so
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/jni \
/media/sf_public/andiord/android-ndk-r8d/platforms/android-14/arch-arm/usr/include
LOCAL_CFLAGS := \
-I /opt/jni/
LOCAL_LDFLAGS :=-L . -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lmp3lame
LOCAL_LDFLAGS += -llog
LOCAL_SRC_FILES := \
cmdutils.c \
ffmpeg.c \
ffmpeg_filter.c \
ffmpeg_opt.c \
LOCAL_MODULE := libffconvertinclude $(BUILD_STATIC_LIBRARY)
以上是android.mk
LOCAL_CFLAGS ffmpeg 头文件路径,LOCAL_CFLAGS ffmpeg 生成的include头文件,LOCAL_LDFLAGS Android系统库,LOCAL_SRC_FILES 又增加的源码,LOCAL_MODULE 生成的 库名字,BUILD_STATIC_LIBRARY 生成静态库。
Application.mk文件:
APP_MODULES := libffconvert
在jni目录下 输入:
ndk-build
然后会在新建的目录下的 /obj/local/armeabi 生成 静态库 大概7个库文件。第二层完成。
第三层:第三层是要生成最终的so库,Android上可以直接使用的。在这层就要自己写jni接口了 。
jni.c
#include <jni.h>
#include "convert.h" // 接口函数头文件
#ifdef __cplusplus
extern "C" {
#endif
#include <android/log.h>
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG , "FFmpegConvertGM", __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR , "FFmpegConvertGM", __VA_ARGS__)
jint Java_cn_ffmpeg_NativeFFmpeg_FFmpegConvertGMp4AndLogo( JNIEnv *env, jobject obj, jstring jinfile,jstring jaddogo, jstring joutfile)
{
const char *infile,*outfile,*addlogo;
jboolean isCopy;
infile = (*env)->GetStringUTFChars(env,jinfile,&isCopy);
outfile = (*env)->GetStringUTFChars(env,joutfile,&isCopy);
addlogo = (*env)->GetStringUTFChars(env,jaddlogo,&isCopy);
int ret = convertMp4AndLogo((char*)infile,(char*)addlogo,(char*)outfile); // 调用底层函数接口
(*env)->ReleaseStringUTFChars(env,jinfile,infile);
(*env)->ReleaseStringUTFChars(env,joutfile,outfile);
(*env)->ReleaseStringUTFChars(env,jaddlogo,addlogo);
return ret;
}
#ifdef __cplusplus
}
#endif
然后写 android.mk 文件 把第一层生成的7个库和第二层生成的1各库都加进来。
LOCAL_PATH:= $(call my-dir)
#libiconv.so
include $(CLEAR_VARS)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/jni \
/media/sf_public/andiord/android-ndk-r8d/platforms/android-14/arch-arm/usr/include
LOCAL_CFLAGS := \
-I /opt/ffmp/jni/
LOCAL_LDFLAGS :=-L . -lffconvert -lavdevice -lavfilter -lavformat -lavcodec -lswresample -lswscale -lavutil -lmp3lame
LOCAL_LDFLAGS += -llog -lz
LOCAL_SRC_FILES := \
jni.c \
LOCAL_MODULE := libconvert
include $(BUILD_SHARED_LIBRARY)
完
BUILD_SHARED_LIBRARY 生成动态库.
然后进入jni目录下 执行 ndk-build 然后会在 /libs/armeabi 下会生成 libconvert.so 动态库文件,这个库是android 下可以直接使用的库
然后android 测试:
创建包,创建java文件
package cn.ffmpeg
publicclass NativeFFmpeg {
static {
System.loadLibrary(“ffconvert”);
}
public native int FFmpegConvertp4AndLogo(Stringjinfile,String jaddlogo, String joutfile);
注意:包名 ,类名,一定要和第三层 jni.c 里面的一致。
然后,就可以在 android工程中 直接调用 接口。
完!