准备:
1. Android Studio
2. FFmpeg-2.8.4
3. android-ndk-r10e
一、ndk编译ffmpeg
1.下载ffmpeg和ndk
ffmpeg下载地址:http://ffmpeg.org/download.html 我下载的是2.8.4版本
ndk 官网下载,这个我就不说了,自备梯子翻越长城。。我下载的是 android-ndk-r10e
2.解压ffmpeg和ndk
将解压的ffmpeg文件夹复制到 android-ndk-r10e ->sources 目录中
修改文件夹ffmpeg-2.8.4中configure脚本,由于编译出来的动态库文件名的版本号在.so之后(例如“libavcodec.so.5.100.1”),而android平台不能识别这样文件名,所以需要修改这种文件名。在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)'
3.配置编译脚本
在文件夹ffmpeg-2.8.4中新建脚本 build_android.sh
#!/bin/bash
export NDK=/Users/huxing/Downloads/android-ndk-r10e
export PREBUILT=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt
export PLATFORM=$NDK/platforms/android-21/arch-arm
export PREFIX=../simplefflib
build_one(){
./configure --target-os=linux --prefix=$PREFIX \
--enable-cross-compile \
--enable-runtime-cpudetect \
--disable-asm \
--arch=arm \
--cc=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-gcc \
--cross-prefix=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi- \
--disable-stripping \
--nm=$PREBUILT/darwin-x86_64/bin/arm-linux-androideabi-nm \
--sysroot=$PLATFORM \
--enable-gpl --enable-shared --disable-static --enable-small \
--disable-ffprobe --disable-ffplay --disable-ffmpeg --disable-ffserver --disable-debug \
--extra-cflags="-fPIC -DANDROID -D__thumb__ -mthumb -Wfatal-errors -Wno-deprecated -mfloat-abi=softfp -marm -march=armv7-a"
}
build_one
make
make install
注意的是前面三个路径替换成自己的路径,还有一些不同版本ndk路径的取名不同比如darwin-x86_64有的是linux-x86_64,自己注意一下路径名称
4.编译ffmpeg
使用命令cd到脚本目录下,首先 chmod a+x build_android.sh 授权,然后 ./build_android.sh 运行脚本。
编译需要花一些时间,编译完成之后就会在android-ndk-r10e -> source 目录下多出一个 simplefflib 目录
(还有8个.so文件被我删除了)
二、Android Studio 部分
1.新建 Android Studio工程
新建AS工程,在main目录下新建一个jni目录,在gradle.properties配置中添加 android.useDeprecatedNdk = true,在Project Structure中配置ndk location,指向你下载ndk的路径
再将编译的FFmpeg文件复制到jni目录中。
再将编译的FFmpeg文件复制到jni目录中。
2.配置build.gradle
取消自动编译,添加 :
sourceSets.main.jni.srcDirs = []
添加ndk配置:
ndk {
moduleName "helloffmpeg"
abiFilter "armeabi"
ldLibs "log", "z", "m", "jnigraphics", "android"
}
全部配置为如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 23
buildToolsVersion "23.0.0"
sourceSets.main.jni.srcDirs = []
defaultConfig {
applicationId "hxing.com.myffmpeg"
minSdkVersion 19
targetSdkVersion 23
versionCode 1
versionName "1.0"
ndk {
moduleName "helloffmpeg"
abiFilter "armeabi"
ldLibs "log", "z", "m", "jnigraphics", "android"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
3.生成头文件
在MainActivity.class中添加Native方法和调用库文件,如下:
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("helloffmpeg");
System.loadLibrary("avutil-54");
System.loadLibrary("avcodec-56");
System.loadLibrary("avformat-56");
System.loadLibrary("avdevice-56");
System.loadLibrary("swresample-1");
System.loadLibrary("swscale-3");
System.loadLibrary("postproc-53");
System.loadLibrary("avfilter-5");
}
public native String getffmpegFromJNI();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView textView = (TextView) findViewById(R.id.text);
textView.setText(getffmpegFromJNI());
}
}
打开as的Terminal窗口,默认路径是当前项目根路径,输入以下命令:
cd app/src/main/java
javah -d ../jni hxing.com.myffmpeg.MainActivity
进入java目录下 使用javah命令在jni目录下生成头文件,然后再在jni目录下建立对应的c文件,c文件代码如下:
//
// Created by 胡醒 on 15/12/31.
//
#include <jni.h>
#include "libavcodec/avcodec.h"
JNIEXPORT jstring JNICALL Java_hxing_com_myffmpeg_MainActivity_getffmpegFromJNI
(JNIEnv * env, jobject thiz){
char info[10000] = { 0 };
sprintf(info, "%s\n", avcodec_configuration());
return (*env)->NewStringUTF(env, info);
}
4.在jni目录下建立Android.mk文件
LOCAL_PATH := $(call my-dir)
# FFmpeg library
include $(CLEAR_VARS)
LOCAL_MODULE := avcodec
LOCAL_SRC_FILES := lib/libavcodec-56.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avdevice
LOCAL_SRC_FILES := lib/libavdevice-56.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avfilter
LOCAL_SRC_FILES := lib/libavfilter-5.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avformat
LOCAL_SRC_FILES := lib/libavformat-56.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := avutil
LOCAL_SRC_FILES := lib/libavutil-54.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := postproc
LOCAL_SRC_FILES := lib/libpostproc-53.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swresample
LOCAL_SRC_FILES := lib/libswresample-1.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := swscale
LOCAL_SRC_FILES := lib/libswscale-3.so
include $(PREBUILT_SHARED_LIBRARY)
# Program
include $(CLEAR_VARS)
LOCAL_MODULE := helloffmpeg
LOCAL_SRC_FILES := hxing_com_myffmpeg_MainActivity.c
LOCAL_C_INCLUDES += $(LOCAL_PATH)/include
LOCAL_LDLIBS := -llog -lz
LOCAL_SHARED_LIBRARIES := avcodec avdevice avfilter avformat avutil postproc swresample swscale
include $(BUILD_SHARED_LIBRARY)
还可以在当前目录下建立Application.mk,这个文件用来指定编译的平台,我这里只指定armeabi
APP_ABI := armeabi
5.编译ffmpeg.so文件
进入Terminal窗口,输入命令 “ cd ../jni” 返回到jni目录中,在输入命令:
/Users/huxing/Downloads/android-ndk-r10e/ndk-build NDK_PROJECT_PATH=null APP_BUILD_SCRIPT=/Users/huxing/Documents/myFFmpeg2/app/src/main/jni/Android.mk APP_PLATFORM=android-21 NDK_OUT=/Users/huxing/Documents/myFFmpeg2/app/build/intermediates/ndk/debug/obj NDK_LIBS_OUT=/Users/huxing/Documents/myFFmpeg2/app/build/intermediates/ndk/debug/lib APP_ABI=armeabi
/Users/huxing/Downloads/android-ndk-r10e/ndk-build :你安装的ndk目录中的ndk-build命令
APP_BUILD_SCRIPT :工程中jni目录下的android.mk的路径
NDK_OUT : 输出路径
NDK_LIBS_OUT :库文件输出路径
APP_ABI : 输出平台
NDK_OUT : 输出路径
NDK_LIBS_OUT :库文件输出路径
APP_ABI : 输出平台
改成自己工程对应的目录
6.运行工程
成功调用ffmpeg方法输出信息