由于项目【ijkplayer】提供编译好的库没有支持RTSP,而ijkplayer这个项目比较强大之处就是可以根据需要进行裁剪编译,所以我要自己编译一次Android版本,开启RTSP协议。
一、软件环境
- Ubuntu16.04 Server
- Android SDK
- NDK(不要安装最新的版本,14b版本能用)和cmake
- ijkplayer-k0.8.8 (commit cced91e3ae3730f5c63f3605b00d25eafcf5b97b)
- 其他一些编译c的环境,系统本身就有,就不一样列出。
编译所需软件大概有这些,引用参考文章的
1 | $ sudo apt install vim openssh-server git curl wget tar unzip |
二、配置环境变量
参考[【Android Linux命令行环境变量配置】](../../Android/Android Linux命令行环境变量配置) ,配置:
- android sdk
- android ndk
- java
三、下载ijplayer源码
1 | $ git clone https://github.com/bilibili/ijkplayer.git |
四、初始化
先编辑 init_android.sh
、 init-android-libyuv.sh
、init-android-libyuv.sh
和 init-android-soundtouch.sh
脚本,修改’github.com’ 为 ‘github.com.cnpmjs.org’,否则很慢,下载不了。
如:
1 | #IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git |
执行
1 | $ ./init_android.sh |
五、修改配置
1 | $ vim config/module-lite.sh |
默认支持的协议
1 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocols" |
注释行
1 | #export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-protocol=rtp" |
加入行:RTSP协议
1 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=rtp" |
替换module
1 | $ cd config/ |
六、开始编译
编译ffmpeg(耗时较长)
1
2
3$ cd ijkplayer/android/contrib
$ ./compile-ffmpeg.sh clean
$ ./compile-ffmpeg.sh all编译jikplayer
1
$ ./compile-ijk.sh all
成功
so文件,在项目的libs目录下,如果是开发机上编译,可以直接用Android Studio打开编译后的example项目。
由于我是在服务器上编译,所以,我要下载编译好的so文件,如armv7a,路径是:ijkplayer/android/ijkplayer/ijkplayer-armv7a/src/main/libs
拷贝so文件
将所有平台的文件都拷贝到
/data/ijk-libs-file
目录下:1
2
3
4
5
6
7
8
9
10
11$ cd ijkplayer/android/ijkplayer
$ ls
build.gradle gradle.properties ijkplayer-arm64 ijkplayer-example ijkplayer-x86 tools
cp-libs.sh gradlew ijkplayer-armv5 ijkplayer-exo ijkplayer-x86_64
gradle gradlew.bat ijkplayer-armv7a ijkplayer-java settings.gradle
$ cp -r ijkplayer-armv5/src/main/libs/armeabi/ /data/ijk-libs-file
$ cp -r ijkplayer-arm64/src/main/libs/arme64 /data/ijk-libs-file
$ cp -r ijkplayer-armv7a/src/main/libs/armeabi-v7a/ /data/ijk-libs-file
$ cp -r ijkplayer-x86/src/main/libs/x86/ /data/ijk-libs-file
$ cp -r ijkplayer-x86_64/src/main/libs/x86_64/ /data/ijk-libs-file
七、错误和解决
NDK版本问题
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31$ sh compile-ffmpeg.sh clean
$ sh compile-ffmpeg.sh all
====================
[*] check archs
====================
FF_ALL_ARCHS = armv5 armv7a arm64 x86 x86_64
FF_ACT_ARCHS = armv5 armv7a arm64 x86 x86_64
====================
[*] check env armv5
====================
FF_ARCH=armv5
FF_BUILD_OPT=
--------------------
[*] make NDK standalone toolchain
--------------------
build on Linux x86_64
ANDROID_NDK=/usr/local/androidsdk/ndk/21.3.6528147
IJK_NDK_REL=21.3.6528147
You need the NDKr10e or later
#要求NDK版本大于10,但这里是21。
vim android/contrib$ vim tools/do-detect-env.sh
# 71行加入: |21*
70 case "$IJK_NDK_REL" in
71 11*|12*|13*|14*|21*)重新编译可以跳过这个错误,但是出现 “ERROR: Failed to create toolchain.”,还是老老实实把NDK版本改为 12/13/14其中一个吧。
【下载链接:Android NDK,修订版 14b(2017 年 3 月)Linux 64 位 (x86)】Android 11 64位真机播放网络视频闪退
问题
在64位Android11机器上播放网络视频闪退,本地视频不会闪退,模拟器不会闪退。
原因
【ijkplayer issues/5206】里的开发者分析了,是ffmpeg库ff_ffplay.c里面触发了以上Android11的标志问题。
【Android 11 适配问题】:从 Android 11 开始,对于 64 位进程,所有堆分配都具有一个由实现定义的标记,该标记在具有对 ARM Top-byte Ignore (TBI) 的内核支持的设备上的指针顶部字节中设置。在回收期间检查该标记时,任何修改此标记的应用都会被终止。对于未来支持 ARM 内存标记扩展 (MTE) 的硬件来说,这是必需的。
缓解办法AndroidManifest.xml
文件中添加以下内容:<application android:allowNativeHeapPointerTagging="false">
彻底解决办法
要彻底解决这个问题,得解决改ffmpeg的ff_ffplay.c
,不过ijkplayer的开发者已经修复这个问题,我们升级一下ffmpeg的版本即可,参考下一节【升级FFmpeg4.0】。
八、升级FFmpeg4.0
- 修改ffmpeg版本版本改为
1
2
3
4
5
6
7$ vim ijkplayer/init-android.sh
IJK_FFMPEG_COMMIT=ff4.0--ijk0.8.8--20210426--001
#IJK_FFMPEG_COMMIT=ff3.4--ijk0.8.7--20180103--001
# 下载新版本源码
$ ./init_android.shff4.0--ijk0.8.8--20210426--001
,即4.0版,参考【issues/5290】。 - 修改编译ffmpeg的配置
如果现在编译,肯定报错,由于4.0版本有些东西已经丢弃,所以裁剪的配置文件要变动。这个问题是参考【【ijkplayer issues/4772】1
2
3
4
5
6
7
8
9
10
11
12
13
14$ vim ijkplayer/config/module-lite.sh
# 注释这两行,否则编译会报错
#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-ffserver"
#export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-vda"
# 注释掉以上两项,编译还会出现以下错误:
# ijkplayer/android/contrib/ffmpeg-arm64/libavcodec/eac3_core_bsf.c:39: undefined reference to `ff_ac3_parse_header'
# ijkplayer/android/contrib/ffmpeg-arm64/libavcodec/eac3_core_bsf.c:55: undefined reference to `ff_ac3_parse_header'
# 还需加入以下这一行
export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --disable-bsf=eac3_core"
# 这一行的位置一开始随便放在文件头,结果编译一直没过
# 移到 `./configure --list-bsf` 这个位置,编译就OK。 - 重新编译
1
2
3
4
5
6$ cd ijkplayer/android/contrib
$ ./compile-ffmpeg.sh clean
$ ./compile-ffmpeg.sh all
$ cd ../
$ ./compile-ijk.sh clean
$ ./compile-ijk.sh all