目录
前言
不同项目不同需求,有些客户接受平台限制的音视频解码格式,但如果作为外销,那就需要支持更多的,因此扩展音视频支持的格式。
引入第三方的so库有如下几种方式:
- APP直接使用第三方开源的so库
- 在framework层进行集成
第一种方式简单,开源的也比较多,比如bilibili的ijkplayer,google的ExoPlayer,以及还有VLC-Android,各有优缺点;至于用第二种方式,这个就比较麻烦些,目前我没有移植过,后续可能会尝试一下。
本文主要是简单的介绍记录一下,编译bilibili/ijkPlayer,编译教程官方上都有详细描述。
编译环境:Ubuntu 18.3
正文
ijkplayer 官方
官方GitHub的仓库:https://github.com/bilibili/ijkplayer
编译ijkplayer
搭建Ubuntu
如果你有现成的Ubuntu,那就跳过。
我是用Workstation 14 Pro虚拟机(自己百度)。
Ubuntu下载链接:http://old-releases.ubuntu.com/releases/
安装编译环境
- 安装git 这个就不多说了 都懂的
- 安装JDK
sudo apt-get install openjdk-8-jdk
配置环境变量
sudo gedit /etc/profile # 末尾加入如下内容 export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
一般情况,为了刷新更改的配置,可以使用如下命令
source /etc/profile
- 安装SDK
下载Linux版的SDK:
两个都可以下载,速度都很快。
上传到Ubuntu并解压,然后配置一下/etc/profile。
sudo gedit /etc/profile # 末尾加入如下内容 export ANDROID_SDK=/home/water/AndroidPlayer/sdk_ndk/android-sdk-linux export PATH=${PATH}:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools
PS: 记得修改为你自己的路径咯。
一般情况,为了刷新更改的配置,可以使用如下命令
source /etc/profile
- 安装NDK
google官方下载NDK,由于IJKPlayer编译不需要最新的NDK,因此我们需要下载历史的NDK版本。
NDK链接:https://developer.android.google.cn/ndk/downloads/older_releases
上面链接中有各种版本,但我们需要下载android-ndk-r14b,这个版本我是编译ok的。
上传到Ubuntu并解压,然后配置一下/etc/profile。
sudo gedit /etc/profile # 末尾加入如下内容 export ANDROID_NDK=/home/water/AndroidPlayer/sdk_ndk/android-ndk-r14b export PATH=$ANDROID_NDK:$PATH
PS: 记得修改为你自己的路径咯。
一般情况,为了刷新更改的配置,可以使用如下命令
source /etc/profile
综合上诉,我们的环境都配置完成了,下面展示我配置的完整文件。
...... //开头的略 #JDK export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64 #SDK export ANDROID_SDK=/home/water/AndroidPlayer/sdk_ndk/android-sdk-linux export PATH=${PATH}:$ANDROID_SDK/tools:$ANDROID_SDK/platform-tools #NDK export ANDROID_NDK=/home/water/AndroidPlayer/sdk_ndk/android-ndk-r14b export PATH=$ANDROID_NDK:$PATH
下载ijkplayer-android
在需要创建仓库的目录执行如下命令
- 下载ijkplayer-android
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
执行后会出现一个ijkplayer-android目录
- 初始化FFmpeg和IjkPlayer代码
# 进入刚才拉取的仓库 cd ijkplayer-android # 拉取代码 ./init-android.sh
拉取代码看网速,有时候很快有时候很慢。
./init-android.sh: line 37: cd: android/contrib/ffmpeg-armv7a: No such file or directory
如果类似上诉的提示出错(基本是网络问题),那就一直使用init-android.sh初始化,直到拉取完成。
- 配置ffmpeg信息
cd config
默认的配置如下:
module-default.sh module-lite-hevc.sh module-lite.sh module.sh -> module-lite.sh
从上面知道,module.sh是软引用文件,用的module-lite.sh,这个是比较小的一种配置。
如果你需要修改,可以用下面命令修改:
# 删除之前的软引用 rm -r module.sh # 新创建软引用 ln -s module-default.sh module.sh
编译 ffmpeg 代码
接着上面,由于我们之前在config目录,因此需要回退一下,在进入对应的编译目录。
cd .. cd android/contrib/ # 一般先clean,再编译对应的so库,我们这里只armv7a ./compile-ffmpeg.sh clean ./compile-ffmpeg.sh armv7a
执行上面就可以编译了,直到提示编译ok。
下面讲解一下./compile-ffmpeg.sh所有的命令可带的参数:
compile-ffmpeg.sh armv5|armv7a|arm64|x86|x86_64 compile-ffmpeg.sh all|all32 compile-ffmpeg.sh all64 compile-ffmpeg.sh clean compile-ffmpeg.sh check
编译ijkplayer so库
在上面基础上,回退到android目录
cd .. # 上面只编译armv7a ./compile-ijk.sh armv7a
提示成功,就编译完成了。
我们编译成功的so库就在:
android/ijkplayer/ijkplayer-armv7a/src/main/libs/armeabi-v7a/
由于我们编译的是默认的配置,因此so库都比较大。
使用so库
PS: 我这里只使用so库,IjkPlayer的demo我就不导入AS了。
把armeabi-v7a整个目录复制到对应工程的libs中。
然后在build.gradle中配置一下:
android { //...... sourceSets { main { jniLibs.srcDirs = ['libs'] } } }
编译时遇到的问题
下面就简单的列举我遇到的问题。
问题一: Failed to create toolchain.
build on Linux x86_64 ANDROID_NDK=/home/water/ijkdir/ndk-sdk-tool/android-ndk-r14b IJK_NDK_REL=14.1.3816874 NDKr14.1.3816874 detected HOST_OS=linux HOST_EXE= HOST_ARCH=x86_64 HOST_TAG=linux-x86_64 HOST_NUM_CPUS=4 BUILD_NUM_CPUS=8 Auto-config: --arch=arm ERROR: Failed to create toolchain.
解决方式:
apt-get install python
然后重新编译即可
问题二:disable-ffserver
开始编译FFmpeg时出现:
/home/water/AndroidPlayer/ijkplayer-dir/ttt/ijkplayer-android/android/contrib/build/ffmpeg-armv7a/toolchain/bin//arm-linux-androideabi-gcc Unknown option "--disable-ffserver". See ./configure --help for available options.
解决方式:
修改config中软引用的配置文件,从上面知道我们使用的是默认的编译文件module-default.sh
修改后,git diff module-default.sh 时显示的,注释掉[--disable-ffserver]
-export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver" +# delete water +#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver"
问题三:--disable-vda
修改上面问题后,重新编译时
/home/liuys/AndroidPlayer/ijkplayer-dir/ttt/ijkplayer-android/android/contrib/build/ffmpeg-armv7a/toolchain/bin//arm-linux-androideabi-gcc Unknown option "--disable-vda". See ./configure --help for available options.
解决方式跟上面一下,也是注释掉[--disable-vda]
git diff module-default.sh 时显示的
-export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vda" +# water delete +#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vda"
问题四first use in this function
上面我们只编译armv7a就出现上面问题,但如果我编译all时,还出现如下问题(日志节选):
/home/water/AndroidPlayer/ijkplayer-dir/ijkplayer-android/android/contrib/build/ffmpeg-arm64/toolchain/sysroot/usr/include/asm-generic/termbits.h:142:0: note: this is the location of the previous definition #define B0 0000000 libavcodec/hevc_mvs.c:208:15: error: 'y0000000' undeclared (first use in this function) libavcodec/hevc_mvs.c:207:15: error: 'x0000000' undeclared (first use in this function)
上面提示了B0已经在termbits.h中宏定义了。所以FFmpeg中B0就变成了0000000。
参考网上的,有两种方式解决问题。
- 把\ijkplayer-master\android\contrib\ffmpeg-arm64\libavcodec的opus_pvq.c和hevc_mvs.c,将B0替换成b0 (我选用的是这种方式,编译通过)
- 将系统文件里面的#B0注释掉之后再编译 (没有验证,但不建议)
参考文章
- 《ijkplayer》
- 《Android JNI 篇 - 编译 bilibili/ijkPlayer》
- 《ijkplayer遇到的问题合集》
- 《编译ijkplayer时出现Failed to create toolchain》