环境:
mac os :1.0.9.4
ndk版本:android-ndk-r10e
ide:eclipse
参考博客:http://blog.yikuyiku.com/?p=4533 参考到第七步编译ffmpeg的so库文件
1、ndk下载
需要翻墙下载:我用的是android-ndk-r10e-darwin-x86_64.bin
2、解压ndk,修改权限,执行解压缩
3、设置ndk环境变量
打开终端输入open -e .bash_profile 打开环境变量配置文件,在文件最后加入环境变量
执行:source .bash_profile 载入
4、下载ffmpeg
我用的版本是ffmpeg-2.6.3.tar.bz2当前的最新版本
5、解压
6、修改ffmpeg-2.6.3目录下的configure文件
原文:
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)'
目的是去掉默认生成的.SO文件后面的数字
7、在ffmpeg-2.6.3目录下创建build_android.sh,内容如下
#!/bin/bash
NDK=/Users/WangJian/wangjian/development/developformac/adt-bundle-mac-x86_64-20140702/android-ndk-r10e
SYSROOT=$NDK/platforms/android-21/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
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
配置自己ndk的路径
8、执行编译
sudo chmod +x build_android.sh
./build_android.sh
9、我去吃饭了,没看到中间过程,会来后编译好的目录结构如下
ffmpeg-2.6.3/android/arm
/include
/lib
lib目录下放的是so库文件
include放的是一些头文件
10、新建android工程,新建jni文件夹,工程的目录结构如图:
11、在jni目录下新建Android.mk ,内容如下
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE:= avcodec-56
LOCAL_SRC_FILES:=libavcodec-56.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:=avformat-56
LOCAL_SRC_FILES:= libavformat-56.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= swscale-3
LOCAL_SRC_FILES:= libswscale-3.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= avutil-54
LOCAL_SRC_FILES:= libavutil-54.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= avfilter-5
LOCAL_SRC_FILES:= libavfilter-5.so
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE:= swresample-1
LOCAL_SRC_FILES:= libswresample-1.so
LOCAL_WHOLE_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := native
LOCAL_SRC_FILES := native.c
LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid
LOCAL_SHARED_LIBRARIES := avformat-56 avcodec-56 swresample-1 avutil-54
include $(BUILD_SHARED_LIBRARY)
其中LOCAL_MODULE 为模块名称,并且前面不要加lib 否则不能正确load so库文件
load过程 System.loadLibrary("avformat-56");时候会再在名称前面加lib字符串,然后load libavformat-56.so 文件
我在这儿坑了好半天,祝你好运
native.c 负责调用ffmpeg功能模块,然后给java提供接口
其中
LOCAL_LDLIBS := -llog -ljnigraphics -lz -landroid
LOCAL_SHARED_LIBRARIES := avformat-56 avcodec-56 swresample-1 avutil-54 这个模块的顺序不能变,否则编译不通过
12、最重要的要给项目配置一个ndk builder
右击项目--》properties --》弹出窗口 点击Builders--》new 一个builder
我的ndk_builder界面如下:
其中location 中需要选择文件 苹果电脑需要选择nkd目录下的ndk-build 文件
13、最后native.c ,主要是测试
内容如下:
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include <android/log.h>
#include "libavformat/avformat.h"
#include "libavcodec/avcodec.h"
#include "libavutil/avutil.h"
#include "libswscale/swscale.h"
//#define LOG_TAG "FFMPEGSample"
//#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)
//#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)
JNIEXPORT jint JNICALL Java_cn_wangjianlog_ffmpegtest_ffmpegnative_FFmpegNative_getffmpegv()
{
//LOGI("getffmpegv");
// return avformat_version();avcodec_version()
av_register_all();
return avcodec_version();
}
java 代码
/**
* @author wangjian
*/
package cn.wangjianlog.ffmpegtest.ffmpegnative;
/**
* @author WangJian
*
*/
public class FFmpegNative {
static {
System.loadLibrary("avformat-56");
System.loadLibrary("avcodec-56");
System.loadLibrary("swscale-3");
System.loadLibrary("avutil-54");
System.loadLibrary("avfilter-5");
System.loadLibrary("swresample-1");
System.loadLibrary("native");
}
public native int getffmpegv();
}
<span style="font-family: Arial, Helvetica, sans-serif;">
</span>
<pre name="code" class="java"><span style="font-family: Arial, Helvetica, sans-serif;">package cn.wangjianlog.ffmpegtest;</span>
import cn.wangjianlog.ffmpegtest.ffmpegnative.FFmpegNative;import android.app.Activity;import android.os.Bundle;public class MainActivity extends Activity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); FFmpegNative mpeg = new FFmpegNative(); int aa = mpeg.getffmpegv(); System.out.println("aa:"+aa); } }