mac系统 ijk(Android)编译
ijk github地址:ijk github
按照github
文档说的,如果不想自己编译ijk
库,Android
可通过gradle
依赖现有的库
# required
allprojects {
repositories {
jcenter()
}
}
dependencies {
# required, enough for most devices.
compile 'tv.danmaku.ijk.media:ijkplayer-java:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-armv7a:0.8.8'
# Other ABIs: optional
compile 'tv.danmaku.ijk.media:ijkplayer-armv5:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-arm64:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-x86:0.8.8'
compile 'tv.danmaku.ijk.media:ijkplayer-x86_64:0.8.8'
# ExoPlayer as IMediaPlayer: optional, experimental
compile 'tv.danmaku.ijk.media:ijkplayer-exo:0.8.8'
}
这种依赖方式gradle3.0
之前的版本的依赖方式,gardle3.0
之后的版本,按需请将compile
换成implementation
或api
如果自己编译ijk
库需要参照下面的流程
1、安装 homebrew, git, yasm
先安装homebrew
,打开homebrew官网,可以看到安装方法
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
然后通过homebrew
安装git
、yasm
brew install git
brew install yasm
接下来需要安装配置Android
的编译环境,分别下载安装
JDK
、Android Studio
、Android SDK
、Android NDK
,并在~/.bash_profile
中完成环境变量设置。安装配置Android
的编译环境的时候需要注意以下两点:
-
ijk
官方编译的时候,使用的Android NDK
版本是 NDK r10e -
~/.bash_profile
中一定要声明ANDROID_SDK
和ANDROID_NDK
变量,并指向SDK
和NDK
路径,比如这样:
...
export ANDROID_SDK=/Users/lb/Library/Android/sdk
export ANDROID_NDK=/Users/lb/developer/android-ndk-r10b
...
声明 ANDROID_SDK
和 ANDROID_NDK
变量,是因为ijk
的编译脚本中是按照这两个变量名去系统中查找SDK
和NDK
的。
2、下载编译Android ijk
下载源码
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
表示新建文件夹ijkplayer-android
,并下载ijkplayer
源码到该文件夹
cd ijkplayer-android
进入文件夹ijkplayer-android
,可以看到这里面不只有Android
源码,还有iOS
源码,整个项目文件结构如下:
ijkplayer-android/
├── COPYING.GPLv2
...
├── README.md
├── android
│ ├── android-ndk-prof -> ../../../../../../ijkprof/android-ndk-profiler-dummy/jni
│ ├── build-on-travis.sh
│ ├── compile-ijk.sh
│ ├── contrib
│ │ ├── compile-ffmpeg.sh
│ │ ├── compile-libsoxr.sh
│ │ ├── compile-openssl.sh
│ │ ├── setup-as-commiter.sh
│ │ ├── sync-mirrors.sh
│ │ └── tools
│ │ ├── do-compile-ffmpeg.sh
│ │ ├── do-compile-libsoxr.sh
│ │ ├── do-compile-openssl.sh
│ │ └── do-detect-env.sh
│ ├── ijk-addr2line.sh
│ ├── ijk-ndk-stack.sh
│ ├── ijkplayer
│ │ ├── build.gradle
│ │ ├── gradle
...
│ │ ├── gradle.properties
│ │ ├── gradlew
│ │ ├── gradlew.bat
│ │ ├── ijkplayer-arm64
│ │ │ ├── build.gradle
│ │ │ ├── gradle.properties
│ │ │ ├── proguard-rules.pro
│ │ │ └── src
│ │ │ ├── androidTest
...
│ │ │ └── main
...
│ │ ├── ijkplayer-example
│ │ │ ├── build.gradle
│ │ │ ├── proguard-rules.pro
│ │ │ └── src
│ │ │ ├── androidTest
....
│ │ │ └── main
│ │ │ ├── AndroidManifest.xml
│ │ │ ├── java
│ │ │ │ └── tv
│ │ │ │ └── danmaku
│ │ │ │ └── ijk
│ │ │ │ └── media
│ │ │ │ └── example
│ │ │ │ ├── activities
│ │ │ │ │ ├── FileExplorerActivity.java
...
│ │ ├── ijkplayer-exo
...
├── compile-android-j4a.sh
├── config
│ ├── module-default.sh
│ ├── module-lite-hevc.sh
│ ├── module-lite.sh
│ └── module.sh -> module-lite.sh
├── doc
│ └── preflight_checklist.md
├── extra
│ └── init-extra.sh
├── ijkmedia
│ ├── Android.mk
│ ├── ijkj4a
│ │ ├── Android.mk
│ │ ├── Makefile
│ │ ├── j4a
│ │ │ ├── class
│ │ │ │ ├── android
│ │ │ │ │ ├── media
│ │ │ │ │ │ ├── AudioTrack.c
│ │ │ │ │ │ ├── AudioTrack.h
...
│ │ │ │ │ └── os
│ │ │ │ │ ├── Build.c
│ │ │ │ │ ├── Build.h
│ │ │ │ │ ├── Build.include.j4a
│ │ │ │ │ ├── Build.loader.j4a
│ │ │ │ │ ├── Bundle.c
│ │ │ │ │ ├── Bundle.h
│ │ │ │ │ ├── Bundle.include.j4a
│ │ │ │ │ └── Bundle.loader.j4a
│ │ │ │ ├── java
│ │ │ │ │ ├── nio
│ │ │ │ │ │ ├── Buffer.c
│ │ │ │ │ │ ├── Buffer.h
│ │ │ │ │ │ ├── Buffer.include.j4a
│ │ │ │ │ │ ├── Buffer.loader.j4a
...
│ │ │ │ └── tv
...
│ ├── ijkplayer
│ │ ├── Android.mk
│ │ ├── android
│ │ │ ├── ffmpeg_api_jni.c
│ │ │ ├── ffmpeg_api_jni.h
...
│ │ └── version.sh
│ └── ijksdl
│ ├── Android.mk
│ ├── android
│ │ ├── android_audiotrack.c
│ │ ├── android_audiotrack.h
│ │ ├── android_nativewindow.c
│ │ ├── android_nativewindow.h
...
├── ijkprof
│ └── android-ndk-profiler-dummy
│ └── jni
│ ├── Android-include.mk
│ ├── Android.mk
│ ├── prof.c
│ └── prof.h
...
├── init-android-exo.sh
├── init-android-j4a.sh
├── init-android-libsoxr.sh
├── init-android-libyuv.sh
├── init-android-openssl.sh
├── init-android-prof.sh
├── init-android-soundtouch.sh
├── init-android.sh
├── init-config.sh
├── init-ios-openssl.sh
├── init-ios.sh
├── ios
│ ├── IJKMediaDemo
...
│ ├── IJKMediaPlayer
│ │ ├── IJKMediaFramework
│ │ │ ├── IJKMediaFramework.h
│ │ │ └── Info.plist
...
│ │ │ └── ijkmedia
│ │ │ ├── ijkplayer
│ │ │ │ └── ios
...
│ │ │ └── ijksdl
│ │ │ └── ios
...
│ ├── IJKMediaPodDemo
│ │ ├── IJKMediaPodDemo
...
└── version.sh
可以看到整个目录大致分为源码、demo、脚本这几个部分
新建本地分支latest
并同步tag
k0.8.8
的源码
git checkout -B latest k0.8.8
执行脚本init-android.sh
./init-android.sh
看下init-android.sh
这个脚本都干了啥?
IJK_FFMPEG_UPSTREAM=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_FORK=https://github.com/Bilibili/FFmpeg.git
IJK_FFMPEG_COMMIT=ff3.4--ijk0.8.7--20180103--001
IJK_FFMPEG_LOCAL_REPO=extra/ffmpeg
set -e
TOOLS=tools
git --version
echo "== pull ffmpeg base =="
sh $TOOLS/pull-repo-base.sh $IJK_FFMPEG_UPSTREAM $IJK_FFMPEG_LOCAL_REPO
通过脚本内容可以看到,init_android.sh
脚本会先调用tools
目录下的脚本pull-repo-base.sh
下载FFmpeg
源码到extra/ffmpeg
目录下,然后同步对应平台的源码到android/contrib/ffmpeg-x
目录下
function pull_fork()
{
echo "== pull ffmpeg fork $1 =="
sh $TOOLS/pull-repo-ref.sh $IJK_FFMPEG_FORK android/contrib/ffmpeg-$1 ${IJK_FFMPEG_LOCAL_REPO}
cd android/contrib/ffmpeg-$1
git checkout ${IJK_FFMPEG_COMMIT} -B ijkplayer
cd -
}
pull_fork "armv5"
pull_fork "armv7a"
pull_fork "arm64"
pull_fork "x86"
pull_fork "x86_64"
脚本执行完之后,可以看到在extra/
目录下多了个ffmpeg
文件夹,在 android/contrib/
目录下,多了ffmpeg-armv5
等文件夹
在init_android.sh
脚本的最后会调用下面三个脚本
./init-config.sh
./init-android-libyuv.sh
./init-android-soundtouch.sh
-
init-config.sh
拷贝config/module-lite.sh
到config/module.sh
-
init-android-libyuv.sh
下载libyuv
到extra/libyuv
-
init-android-soundtouch.sh
下载soundtouch
到extra/soundtouch
3、编译ffmpeg
cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
compile-ffmpeg.sh
根据传入参数all
,会调用tools/do-compile-ffmpeg.sh
all|all64)
echo_archs $FF_ACT_ARCHS_64
for ARCH in $FF_ACT_ARCHS_64
do
sh tools/do-compile-ffmpeg.sh $ARCH $FF_TARGET_EXTRA
done
echo_nextstep_help
;;
执行完成之后会在android/contrib/build/ffmpeg-x/output/
文件夹下生成libijkffmpeg.so
等文件,例如用于armv7a
平台的so
库就会在android/contrib/build/ffmpeg-armv7a/output/
目录下生成。
4、编译ijk
cd ..
./compile-ijk.sh all
compile-ijk.sh
根据传入参数调用方法do_ndk_build
编译
all|all64)
for ABI in $ACT_ABI_64
do
do_ndk_build "$ABI" $REQUEST_SUB_CMD;
done
;;
do_ndk_build
进入目标编译平台代码所在的目录,调用do_sub_cmd
并传入参数
do_ndk_build () {
PARAM_TARGET=$1
PARAM_SUB_CMD=$2
case "$PARAM_TARGET" in
armv5|armv7a)
cd "ijkplayer/ijkplayer-$PARAM_TARGET/src/main/jni"
do_sub_cmd $PARAM_SUB_CMD
cd -
;;
arm64|x86|x86_64)
cd "ijkplayer/ijkplayer-$PARAM_TARGET/src/main/jni"
if [ "$PARAM_SUB_CMD" = 'prof' ]; then PARAM_SUB_CMD=''; fi
do_sub_cmd $PARAM_SUB_CMD
cd -
;;
esac
}
do_sub_cmd
调用NDK
编译
do_sub_cmd () {
SUB_CMD=$1
if [ -L "./android-ndk-prof" ]; then
rm android-ndk-prof
fi
if [ "$PARAM_SUB_CMD" = 'prof' ]; then
echo 'profiler build: YES';
ln -s ../../../../../../ijkprof/android-ndk-profiler/jni android-ndk-prof
else
echo 'profiler build: NO';
ln -s ../../../../../../ijkprof/android-ndk-profiler-dummy/jni android-ndk-prof
fi
case $SUB_CMD in
prof)
$ANDROID_NDK/ndk-build $FF_MAKEFLAGS
;;
clean)
$ANDROID_NDK/ndk-build clean
;;
rebuild)
$ANDROID_NDK/ndk-build clean
$ANDROID_NDK/ndk-build $FF_MAKEFLAGS
;;
*)
$ANDROID_NDK/ndk-build $FF_MAKEFLAGS
;;
esac
}
编译完整之后可以在对应的平台目录下生成libijkplayer.so
和libijksdl.so
,例如用于armv7a
平台的so
就会在android/ijkplayer/ijkplayer-armv7a/src/main/obj/local/armeabi-v7a
目录下生成。
PS:前面配置环境变量的时候,在~/.bash_profile
中配置的变量$ANDROID_NDK
就是用在这里的。
5、Android Studio导入android/ijkplayer/
导入之后可以看到按照芯片架构分成了很多module
运行主module
ijkplayer-example
选择sd
卡中的视频播放,效果如下
总结:ijk player源码的编译步骤如下
#1、下载源码
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-android
cd ijkplayer-android
git checkout -B latest k0.8.8
./init-android.sh
#2、编译ffmpeg
cd android/contrib
./compile-ffmpeg.sh clean
./compile-ffmpeg.sh all
#3、编译ijk
cd ..
./compile-ijk.sh all
然后Android Studio
导入android/ijkplayer/
,选择module
ijkplayer-example
运行,就可以得到一个ijk player
的demo
播放器程序。