准备材料:ffmpeg源码,NDK环境
去ffmpeg官网下载ffmpeg源码。我的为ffmpeg-2.6.2。进入ffmpeg的目录。编写编译脚本文件android_ffmpeg.sh.内容如下
NDK=/home/hxl/bin/android-ndk-r10d SYSROOT=$NDK/platforms/android-9/arch-arm/ TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64 function build_one { ./configure \ --prefix=$PREFIX \ --enable-nonfree \ --enable-shared \ --enable-gpl \ --enable-static \ --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 -j$THREAD_COUNT make install } CPU=arm PREFIX=$(pwd)/android/$CPU ADDI_CFLAGS="-marm" build_one
然后chmod 777 android_ffmpeg.sh 给该文件添加权限。最后执行./android_ffmpeg.sh 就进行编译了。编译完成后进入ffmpeg目录你会发现多出来一个android文件夹,在android/arm/lib下面就是编译出来的.a的静态库和.so的分享库。我的编译过程也是参考网上的给出的编译脚本代码完成的。需要注意的一点是如果直接copy脚本代码有可能会有一些格式上面的问题而导致编译失败。最后我会将脚本文件直接上传,有需要的可以下载。
参考网址:http://blog.csdn.net/gobitan/article/details/22750719
这样编出来的so包的名字存在像这样avcodec.so.54这样的文件,也存在不带数字的.so文件,android识别不出来。解决办法如下:
将ffmpeg的config文件的以下四行:
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结尾了,原来的avcodec.so.54这样的文件变为了avcodec.54.so这样的文件,但有点疑问的是在mk文件中引用的都是带数字的so包,使用不带数字的so包编译出来的会提示dlopen failed: could not load library "libavutil-54.so" needed by "libswresample.so"; caused by library "libavutil-54.so" not found 的error,都换为带数字的so文件时就可以正正确使用啦。不明白原因,有知道的希望能给留言赐教。
现在写一个android项目测试下是否编译成功。
具体步骤仿照文章:
我贴下我的代码Android.mk文件
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE :=avcodec-prebuilt LOCAL_SRC_FILES :=prebuilt/libavcodec-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE :=avdevice-prebuilt LOCAL_SRC_FILES :=prebuilt/libavdevice-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE :=avfilter-prebuilt LOCAL_SRC_FILES :=prebuilt/libavfilter-5.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE :=avformat-prebuilt LOCAL_SRC_FILES :=prebuilt/libavformat-56.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE :=swresample-prebuilt LOCAL_SRC_FILES :=prebuilt/libswresample-1.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := avutil-prebuilt LOCAL_SRC_FILES :=prebuilt/libavutil-54.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := postproc-prebuilt LOCAL_SRC_FILES :=prebuilt/libpostproc-53.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := swscale-prebuilt LOCAL_SRC_FILES :=prebuilt/libswscale-3.so include $(PREBUILT_SHARED_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE :=ffmpeg_lily_codec LOCAL_SRC_FILES :=com_lily_testffmpeg_FFmpegExample.c \ LOCAL_LDLIBS :=-llog -ljnigraphics -lz -landroid LOCAL_SHARED_LIBRARIES:= avcodec-prebuilt avdevice-prebuilt avfilter-prebuilt avformat-prebuilt avutil-prebuilt swscale-prebuilt swresample-prebuilt include $(BUILD_SHARED_LIBRARY)
对于这段mk文件的解释,感谢:http://blog.csdn.net/smfwuxiao/article/details/8523479
预编译模块不需要编译。该预编译模块会被拷贝到 $PROJECT/obj/local 下面,还会被拷贝到 $PROJECT/libs/<abi> 下面(这里的库被strip过)。
在依赖该预编译库的模块对应的Android.mk中,将预编译库的名字(前面取的)加入到 LOCAL_STATIC_LIBRARIES 或 LOCAL_SHARED_LIBRARIES 声明中。例如,一个使用上面libfoo.so的简单例子如下:
FFmpegExample.java
package com.lily.testffmpeg; public class FFmpegExample { static{ System.loadLibrary("swresample-1"); System.loadLibrary("avcodec-56"); System.loadLibrary("avdevice-56"); System.loadLibrary("avfilter-5"); System.loadLibrary("avformat-56"); System.loadLibrary("avutil-54"); System.loadLibrary("postproc-53"); System.loadLibrary("swscale-3"); System.loadLibrary("ffmpeg_lily_codec"); } public native int lilyavcodec_findcodec(int id); }
com_lily_testffmpeg_FFmpegExample.h
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_lily_testffmpeg_FFmpegExample */ #ifndef _Included_com_lily_testffmpeg_FFmpegExample #define _Included_com_lily_testffmpeg_FFmpegExample #ifdef __cplusplus extern "C" { #endif /* * Class: com_lily_testffmpeg_FFmpegExample * Method: lilyavcodec_findcodec * Signature: (I)I */ JNIEXPORT jint JNICALL Java_com_lily_testffmpeg_FFmpegExample_lilyavcodec_1findcodec (JNIEnv * env, jobject obj, jint id); #ifdef __cplusplus } #endif #endif
com_lily_testffmpeg_FFmpegExample.c
#include "com_lily_testffmpeg_FFmpegExample.h" #include <math.h> #include <libavutil/opt.h> #include <libavcodec/avcodec.h> #include <libavutil/channel_layout.h> #include <libavutil/common.h> #include <libavutil/imgutils.h> #include <libavutil/mathematics.h> #ifdef __cplusplus extern "C" { #endif /* * Class: cn_dennishucd_FFmpegNative * Method: avcodec_find_decoder * Signature: (I)I */ JNIEXPORT jint JNICALL Java_com_lily_testffmpeg_FFmpegExample_lilyavcodec_1findcodec (JNIEnv * env, jobject obj, jint id) { AVCodec *codec = NULL; /* register all formats and codecs */ av_register_all(); codec = avcodec_find_decoder(id); if (codec != NULL) { return 0; } else { return -1; } } #ifdef __cplusplus } #endif
MainActivity.java
package com.lily.testffmpeg; import com.example.testandroidsp.R; import android.support.v7.app.ActionBarActivity; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.view.TextureView; import android.widget.TextView; public class MainActivity extends ActionBarActivity { @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView tv=(TextView) findViewById(R.id.tv); FFmpegExample fFmpegExample = new FFmpegExample(); int codecID = 28; //28 is the H264 Codec ID int res = fFmpegExample.lilyavcodec_findcodec(codecID); if(res ==0) { tv.setText("Success!"); } else{ tv.setText("Failed!"); } } }
特别鸣谢:http://blog.csdn.net/gobitan/article/details/22750719
编译脚本文件http://download.csdn.net/detail/u010095768/8703265
例子源码:http://download.csdn.net/detail/u010095768/8703311