完成FFmepg的移植,编译ffmpeg4Android
来源:互联网 发布:sqlserver exists in 编辑:程序博客网 时间:2024/06/06 08:44
原:https://righere.github.io/2016/10/10/build-ffmpeg4Android/
本文主要实现了FFmpeg的编译和移植,首先在linux下将官网下载的源码编译成.so文件,然后使用android-studio配合NDK工具,将.so文件移植到android项目当中,简单地介绍了如何一步步完成FFmpeg的编译流程
参考文章:手把手图文并茂教你用Android Studio编译FFmpeg库并移植
下面是我自己在ubuntu下编译
准备的编译工具
Git,NDK
安装git,检查本地git,git --version
直接用命令符安装: sudo apt install git
也可以去官网下载,git官网下载
如果已经有了git,想更新到最新版,可以输入 git clone https://github.com/git/git
,再进行编译安装
然后下载NDK(现在已经有13的版本了),推荐使用android studio安装ndk,下载的ndk路径默认在AndroidSDK的ndk-boudle文件中
配置NDK的环境
使用terminal配置电脑的环境,(个人电脑,我直接以管理员权限配置的系统环境变量)
sudo gedit /etc/profile
打开之后,把我们的ndk路径配置进来,
123
#Android NDKexport ANDROID_NDK=/path/to/ndk(你的ndk解压路径)export PATH=$PATH:$ANDROID_NDK
下载ffmpeg的最新的源码
新建一个ffempeg的工作文件夹,例如 mkdir workplace
git clone https://git.ffmpeg.org/ffmpeg.git
也可以直接去官网下载:ffmpeg官网下载
修改ffmpeg的configure文件
为了保证我们编译出的文件是以.so的后缀名
将文本中的3209-3212这4行:
1234
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)'
修改改为:
1234
SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'LIB_INSTALL_EXTRA_CMD='$$(RANLIB) "$(LIBDIR)/$(LIBNAME)"'SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'SLIB_INSTALL_LINKS='$(SLIBNAME)'
编写编译脚本
写脚本的直观上的好处就是省去了一步步的执行编译命令,通常的在编译之前都需要进行配置,设置相应的环境变量,比如指定编译工具、编译平台等等,查看所有的配置选项可以在ffmpeg目录执行如下命令:
./configure –help
当然此脚本中,我们只需要设置几个我们比较关心的配置。
1. NDK的路径: NDK=/path/to/ndk2. 编译的ndk plaform版本: SYSROOT=$NDK/platforms/android-23/arch-arm/3. 交叉编译工具: TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_644. CPU平台: CPU=arm5. 编译完成后安装目录(当前目录下的android文件夹): PREFIX=./android/$CPU
确定我们需要的配置之后,在ffmpeg的目录下面新建一个脚本 build4android.sh
12345678910111213141516171819202122232425262728293031323334
#!/bin/shNDK=/path/to/ndkSYSROOT=$NDK/platforms/android-23/arch-arm/TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64CPU=armPREFIX=./android/$CPUADDI_CFLAGS="-marm"config_para(){./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_FLAGmake cleanmakemake install}config_para
这里增加一个方便的脚本技巧,便于修改自己的配置,我们将这些configure配置参数写进一个脚本function,建议如下语法:
12345
func_name(){./configure \<---我们的参数配置---/>}
另外一种一种语法(这种可能会报找不到function的错误,不推荐使用):
12345
function func_name{./configure \<---我们的参数配置---/>}
还有就是脚本编辑推荐使用vim非常方便,变量参数一目了然
开始编译
进入我们的FFmpeg的源码目录,执行刚才的脚本:
(先增加执行权限 sudo chmod +x build4android.sh
,以防权限不够)
./build4anroid.sh
脚本执行中:
脚本执行完成:
生成的android/arm/
目录中的文件,图中标出的为链接文件可以删除:
移植我们的.so文件
拷贝.so文件到android-studio工程文件中
在android-studio中切换成project工程目录模式,在app/src/main
目录下面新建一个jni
文件夹,将上面第6步中的include
文件夹拷贝到此文件夹中,再在jni
文件夹中新建一个lib
文件夹,将.so
文件拷贝进来,新建Android.mk
,Application.mk
和c文件目录结构如下:
1234567891011121314151617
├── Android.mk├── Application.mk├── ffmpeg-jni.c├── include│ ├── libavcodec│ ├── libavfilter│ ├── libavformat│ ├── libavutil│ ├── libswresample│ └── libswscale└── lib├── libavcodec-57.so├── libavfilter-6.so├── libavformat-57.so├── libavutil-55.so├── libswresample-2.so└── libswscale-4.so
编写Android.mk文件
12345678910111213141516171819202122232425262728293031323334353637383940414243444546
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE:= libavcodecLOCAL_SRC_FILES:= lib/libavcodec-57.soLOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/includeinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= libavformatLOCAL_SRC_FILES:= lib/libavformat-57.soLOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/includeinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= libswscaleLOCAL_SRC_FILES:= lib/libswscale-4.soLOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/includeinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= libavutilLOCAL_SRC_FILES:= lib/libavutil-55.soLOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/includeinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= libavfilterLOCAL_SRC_FILES:= lib/libavfilter-6.soLOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/includeinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= libswresampleLOCAL_SRC_FILES:= lib/libswresample-2.soLOCAL_EXPORT_C_INCLUDES:= $(LOCAL_PATH)/includeinclude $(PREBUILT_SHARED_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE:= FFmpegCodecLOCAL_SRC_FILES:= ffmpeg-jni.cLOCAL_C_INCLUDES += $(LOCAL_PATH)/includeLOCAL_LDLIBS := -llog -lzLOCAL_SHARED_LIBRARIES := avcodec avfilter avformat avutil swresample swscaleinclude $(BUILD_SHARED_LIBRARY)
编写Application.mk文件
1234
APP_ABI :=armeabi //这里可选armeabi-v7a,x86,mips和all等APP_PLATFORM := android-23APP_OPTIM := release //默认是relaese,也可以设置成debugAPP_STL := gnustl_static //这里是可选,当你编写下面的C文件的时候这里就可以体现出作用,例如你要使用`#include <string>`这个库的时候,默认的system库是没有包含这个的
编写C文件
在上面编写的Android.mk中,我们制定了c文件的名字为ffmpeg-jni.c
,所以c文件的与此保持一致,
函数申明语法:JNIEXPORT jstring Java_包名activity名函数名,包名中间的点号.
全部变成下划线_
例如:我在包名com.righere.ffmpegndkbuild
下面的MainActivity
中要使用avcodecInfo这个函数,
JNIEXPORT jstring Java_com_righere_ffmpegndkbuild_MainActivity_avcodecInfo
123456789101112131415161718192021222324252627282930
#include <stdio.h>#include "libavformat/avformat.h"#include <libavfilter/avfilter.h>#include <jni.h>JNIEXPORT jstring Java_com_righere_ffmpegndkbuild_MainActivity_avcodecInfo(JNIEnv* env, jobject obj){char info[4000] = { 0 };int count = 100; //输出前100个codec名字av_register_all();//初始化所有decoder和encoder,注册所有容器类型和codecAVCodec *c_temp = av_codec_next(NULL);while (c_temp != NULL && count > 0){//输出解码器和编码器if(c_temp->decode != NULL){sprintf(info,"%s[Dec]",info);}else{sprintf(info,"%s[Enc]",info);}sprintf(info,"%s[%10s]\n",info,c_temp->name);c_temp = c_temp->next;count--;}return (*env)->NewStringUTF(env, info);}
修改gradle(修改的是app的build.gradle
)
- 告诉gradle,
.mk
文件的路径(在android{–}里面添加):
12345
externalNativeBuild {ndkBuild {path 'src/main/jni/Android.mk'}}
- 告诉gradle,完成编译之后,我们的生成的
.so
文件在哪个目录下面(在android{–}里面添加):
这里我编译的armeabi
版本的生成的.so
文件自动会放在了’src/main/libs/armeabi’这个目录下面,其他的版本只需要把armeabi
名字变一下就行了
1234
sourceSets.main {jni.srcDirs = [] //disable automatic ndk-buildjniLibs.srcDirs = ['src/main/libs/armeabi']}
- 告诉gradle,ndk-build的时候还要执行哪些附加选项(在defaultConfig{}里面添加):
这一步其实可以看做是对.mk
文件的补充
123456
ndk {abiFilter "armeabi" //在Application.mk里面设置保持一致,如果是编译了多个平台的,可以指定编译多平台的或者moduleName "FFmpegCodec" //jni模块的名字,与android.mk文件保持一致ldLibs "log", "z", "m", "jnigraphics", "android" //这里可以设置ldLibs选项,比如你想调试jni的时候必须添加"log"参数}
执行ndk-build
编译完成main文件夹下会增加libs
和obj
两个文件夹,其中libs/armeabi
下就是我们需要的.so
文件
1234567891011
├── jni│ ├── Android.mk│ ├── Application.mk│ ├── ffmpeg-jni.c│ ├── include│ └── lib├── libs│ └── armeabi├── obj│ └── local└── res
切换回Android结构的工程试图,系统会自动把生成的.so
文件放入jniLibs
中,看到这个FFmpeg的移植基本就成功了
测试FFmpeg移植
在MainActivity中添加测试代码,
1234567891011121314151617181920212223
public class MainActivity extends AppCompatActivity {//jnipublic native String avcodecInfo();static {System.loadLibrary("FFmpegCodec");System.loadLibrary("avcodec-57");System.loadLibrary("avfilter-6");System.loadLibrary("avformat-57");System.loadLibrary("avutil-55");System.loadLibrary("swresample-2");System.loadLibrary("swscale-4");}@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);TextView Codec_info = (TextView) findViewById(R.id.TextView_codec_info);Codec_info.setMovementMethod(ScrollingMovementMethod.getInstance());Codec_info.setText(avcodecInfo());}}
- 第一次完成FFmepg的移植,编译ffmpeg4Android
- 完成FFmepg的移植,编译ffmpeg4Android
- 完成FFmepg的移植,编译ffmpeg4Android
- 第一次完成FFmepg的移植,编译ffmpeg4Android
- 编译完成ffmepg for wince
- ffmepg以及x264的编译
- FFmepg - 编译
- 毕设-02.27 在linux下完成ffmepg+vlc的编译和链接 并成功导入eclipse编译运行
- ffmepg windows平台下编译
- ffmepg的一些命令
- Ubuntu下编译Android版本的ffmepg so库及源码
- android studio 使用CMAKE 编译ffmepg
- ffmepg学习记录:一编译ffmpeg
- ffmepg对avs的支持
- ffmepg.exe使用的例子
- ffmepg中swscale的用法
- 完成ARM Linux的SSHD移植
- 编译阶段完成的工作
- service层处理事务
- python与C#的互相调用
- 搭建Maven私有仓库
- CSS样式的继承详解
- No.7_7 OpenCL 同步——命令队列
- 完成FFmepg的移植,编译ffmpeg4Android
- Oracle 数据库创建、表空间创建、用户创建 步骤
- 获取远程图片的宽、高和大小
- Windows系统下配置gradle的环境变量的简单方式
- HTML5新增元素及属性
- bzoj1572[Usaco2009 Open]工作安排Job 堆
- Java多态中的引用类型转换
- File/IO
- EXP-00026: conflicting modes specified