FFmpeg是一套可以用来记录、转换数字音频、视频,并能将其转化为流的开源计算机程序。采用LGPL或GPL许可证。它提供了录制、转换以及流化音视频的完整解决方案。它包含了非常先进的音频/视频编解码库libavcodec
接下来介绍一下分别在Windows和Linux下编译出android需要的动态库文件
一、windows下编译
1、准备工具
2、安装MinGW
安装MinGW比较简单,只需一步一步下去即可,如果中间出现安装失败等原因,重新安装即可。
安装完成以后打开MinGW Installation Manager界面,选择左侧的“Basic Setup”,然后选择右侧的“mingw32-gcc-data”,“msys-base”进行安装。
安装过程中可能会出现有些文件下载失败的情况,此时不用管它,等其他的安装完成后,点击叉按钮关闭时会出现提醒,此时再按照提示继续安装,直到文件全部安装完毕,MinGW Installation Manager界面会自动退出。
等到安装结束后需要配置系统环境变量,MinGW默认安装C盘根目录如:C:\MinGW。将C:\MinGW\bin配置到环境变量的Path中。一切弄完后进入到C:\MinGW\msys\1.0 双击msys.bat启动,可能会稍微需要等一会儿
3、 编写脚本文件
将下载的NDK和FFmpeg解压到文件夹下如:D:\testFFmpeg下。之后打开D:\testFFmpeg\ffmpeg-3.3.8文件夹
<1> 修改FFmpeg的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)'
<2> 新建一个ffmpegTemp的空文件夹(不知道有什么用,但必须有)
<3> 新建一个build_android.sh的文件,内容如下:
#!/bin/bash
export TMPDIR=D:/testFFmpeg/ffmpeg-3.3.8/ffmpegTemp
NDK=D:/testFFmpeg/android-ndk-r14b
SYSROOT=$NDK/platforms/android-19/arch-arm/
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/windows-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
4、 编译脚本
启动MinGW中的C:\MinGW\msys\1.0\msys.bat批处理文件(需要等会儿),切换(cd)到D:\testFFmpeg\ffmpeg-3.3.8文件夹下。输入命令:
chmod +x build_android.sh (授予权限)
./build_android.sh(编译文件。途中会有一些warning,和deprecated api,但不会影响结果)
编译完成后会在D:\testFFmpeg\ffmpeg-3.3.8文件夹下生成一个android的文件夹,打开D:\testFFmpeg\ffmpeg-3.3.8\android\arm可以看到。里面包含include和lib两个文件夹。include中包含是一些头文件,lib中包含是一些so文件。
二、Linux下编译
1、准备工具
Android NDK r14b Linux 64版本
FFmpeg 3.3.8版本
虚拟机virtualBox
Linux系统Ubuntu桌面版
2、安装virtualBox
安装virtualBox比较简单,只需一步一步下去即可。
安装完成后点击新建,创建一个Linux 64位的虚拟电脑,一步一步即可。
有些电脑没有64位的选项,是因为没有开启硬件虚拟化,这时就需要重启进入到BIOS设置界面,找到Intel ® Virtualization Technology设置为enable即可。
创建成功后启动该虚拟电脑,会让选择安装系统选择之前下载好的Ubuntu桌面版ios文件即可进行系统安装。
系统安装成功后有时候需要虚拟机和主机之前进行文件的复制黏贴,操作如下:
<1> 找到菜单栏的“设备”。点击打开看到“共享文件夹”、“共享粘贴板”、“拖放”。将“共享粘贴板”、“拖放”设置为双向, “共享文件夹”打开右边有一个添加的按钮,打开会让选择共享文件夹路径,选择一个比如: D:\share,然后将自动挂载和固定分配选上。
<2> 在菜单栏“设备”下会有一个"安装增强功能",选择安装
<3> 安装完成之后右键打开终端,输入命令:sudo mount -t vboxsf share(就是上面设置的共享文件夹) /home/cheng(虚拟电脑名称)/sharefile(自己创建的文件夹名称),回车。
这样就可以实现主机中的D:\share文件夹中和/home/cheng/sharefile文件夹中的文件相互可见,并可复制黏贴。
3、 编写脚本文件
将下载的NDK和FFmpeg通过虚拟机的共享文件夹的形式,copy到虚拟机的/home/cheng/ffmpeg文件夹下,并解压
<1> 修改FFmpeg的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)'
<2> 新建一个build_android.sh的文件,内容如下:
#!/bin/bash
#填写你具体的ndk解压目录
export NDK=/home/cheng/ffmpeg/android-ndk-r14b
export SYSROOT=$NDK/platforms/android-19/arch-arm/
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
export CPU=arm
#编译后的文件会放置在 当前路径下的android/arm/下
export PREFIX=$(pwd)/android/$CPU
export ADDI_CFLAGS="-marm"
#./configure 即为ffmpeg 根目录下的可执行文件configure
#你可以在ffmpeg根目录下使用./configure --hellp 查看 ./configure后可填入的参数。
./configure --target-os=linux \
--prefix=$PREFIX --arch=arm \
--disable-doc \
--enable-shared \
--disable-static \
--disable-yasm \
--disable-symver \
--enable-gpl \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffprobe \
--disable-ffserver \
--disable-doc \
--disable-symver \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--enable-cross-compile \
--sysroot=$SYSROOT \
--extra-cflags="-Os -fpic $ADDI_CFLAGS" \
--extra-ldflags="$ADDI_CFLAGS" \
$ADDITIONAL_CONFIGURE_FLAG
4、 编译脚本
右键打开终端,切换(cd)到/home/cheng/ffmpeg/ffmpeg-3.3.8文件夹下
输入命令:chmod +x build_android.sh (授予权限)
./build_android.sh(编译文件。途中会有warning,不影响)
make clean
make
make install
编译会需要一些时间
编译完成后会在/home/cheng/ffmpeg/ffmpeg-3.3.8文件夹下生成一个android的文件夹。里面包含include和lib两个文件夹。include中包含是一些头文件,lib中包含是一些so文件。将android文件夹压缩打包copy到/home/cheng/sharefile文件夹中,在D:\share文件夹中就可以看到并copy到其他地方。
那么到这儿,在Windows和Linux下编译FFmpeg动态库就完成了。但是要使用到 Android 项目中,还需要 jni
三、使用
1、新建一个Android Studio项目,勾选Include C++ support复选框。
将so文件和头文件放在libs目录下。
在libs新建一个平台名字文件夹将so文件放入,比如libs/arm64-v8a下。将头文件include文件夹直接放在libs下即可。
2、编写CMakeLists.txt脚本
#设置CMake最小版本号
cmake_minimum_required(VERSION 3.4.1)
#设置最后生成so文件路径
set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
#添加c源文件
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/native-lib.cpp
)
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log
)
#定义变量distribution_DIR
set(distribution_DIR ../../../../libs)
#添加FFmpeg动态库文件
add_library( avcodec-57
SHARED
IMPORTED)
set_target_properties( avcodec-57
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/arm64-v8a/libavcodec-57.so)
add_library( avfilter-6
SHARED
IMPORTED)
set_target_properties( avfilter-6
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/arm64-v8a/libavfilter-6.so)
add_library( avformat-57
SHARED
IMPORTED)
set_target_properties( avformat-57
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/arm64-v8a/libavformat-57.so)
add_library( avutil-55
SHARED
IMPORTED)
set_target_properties( avutil-55
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/arm64-v8a/libavutil-55.so)
add_library( swresample-2
SHARED
IMPORTED)
set_target_properties( swresample-2
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/arm64-v8a/libswresample-2.so)
add_library( swscale-4
SHARED
IMPORTED)
set_target_properties( swscale-4
PROPERTIES IMPORTED_LOCATION
${distribution_DIR}/arm64-v8a/libswscale-4.so)
#设置FFmpeg头文件路径
include_directories(libs/include)
#链接库文件
target_link_libraries( # Specifies the target library.
native-lib
avcodec-57
avfilter-6
avformat-57
avutil-55
swresample-2
swscale-4
# Links the target library to the log library
# included in the NDK.
${log-lib}
)
3、在app/build.gradle文件中添加
sourceSets {
main {
jniLibs.srcDirs = ['libs']
}
}
如果是针对单平台CPU的库文件,还需要添加:
ndk {
abiFilters "arm64-v8a"
}
4、编写C++代码native-lib.cpp
//引入FFmpeg头文件
extern "C" {
//编码
#include "libavcodec/avcodec.h"
//封装格式处理
#include "libavformat/avformat.h"
//像素处理
#include "libswscale/swscale.h"
#include "libavfilter/avfilter.h"
}
extern "C"
//循环输出AVInputFormat、AVOutputFormat信息到info中,并将信息返回
JNIEXPORT jstring JNICALL Java_com_test_chinamobile_MainActivity_avformatinfo
(JNIEnv *env, jobject obj)
{
char info[40000] = { 0 };
av_register_all();
AVInputFormat *if_temp = av_iformat_next(NULL);
AVOutputFormat *of_temp = av_oformat_next(NULL);
//Input
while(if_temp!=NULL){
sprintf(info, "%s[In ][%10s]\n", info, if_temp->name);
if_temp=if_temp->next;
}
//Output
while (of_temp != NULL){
sprintf(info, "%s[Out][%10s]\n", info, of_temp->name);
of_temp = of_temp->next;
}
//LOGE("%s", info);
return env->NewStringUTF(info);
}
5、调用C++代码
//注册动态代码库
static {
System.loadLibrary("native-lib");
System.loadLibrary("avcodec-57");
System.loadLibrary("avfilter-6");
System.loadLibrary("avformat-57");
System.loadLibrary("avutil-55");
System.loadLibrary("swresample-2");
System.loadLibrary("swscale-4");
}
//声明一个本地方法
public native String avformatinfo();
//调用显示返回的信息
textView.setText(avformatinfo());