从编译脚本分析ijkplayer详细编译过程
来源:互联网 发布:淘宝上可以卖中药吗 编辑:程序博客网 时间:2024/05/16 02:17
接着之前的一篇简要的ijkplayer的编译过程,这一遍主要是详细描述ijkplayer编译的详细过程,跟着编译的脚本详细分析在ijkplayer从开源库的clone到完整地编译android共享库的过程。
1.下载最新版的源码
git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-androidcd ijkplayer-androidgit checkout -B latest k0.7.9
2.init-android.sh 下载编译所需的库
这一步会用到tools文件夹下面的工具脚本,
2.1 pull ffmpeg base
pull-repo-base.sh
,将ffmpeg
源码clone
到extra/ffmpeg
文件夹,
sh pull-repo-bash.sh https://github.com/Bilibili/FFmpeg.git extra/ffmpeg
pull-repo-base.sh
脚本
REMOTE_REPO=$1LOCAL_WORKSPACE=$2if [ -z $REMOTE_REPO -o -z $LOCAL_WORKSPACE ]; then echo "invalid call pull-repo.sh '$REMOTE_REPO' '$LOCAL_WORKSPACE'"elif [ ! -d $LOCAL_WORKSPACE ]; then git clone $REMOTE_REPO $LOCAL_WORKSPACEelse cd $LOCAL_WORKSPACE git fetch --all --tags cd -fi
简化一下,就是
git clone https://github.com/Bilibili/FFmpeg.git extra/ffmpeg
2.2 pull ffmpeg fork
将上一步clone下来的ffmpeg源码,不同arm处理器架构的(armv5 armv7 arm64 x86 x86_64)的文件相应文件夹下面android/contrib/
,
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"
pull-repo-ref.sh
脚本
REMOTE_REPO=$1LOCAL_WORKSPACE=$2REF_REPO=$3if [ -z $1 -o -z $2 -o -z $3 ]; then echo "invalid call pull-repo.sh '$1' '$2' '$3'"elif [ ! -d $LOCAL_WORKSPACE ]; then git clone --reference $REF_REPO $REMOTE_REPO $LOCAL_WORKSPACE cd $LOCAL_WORKSPACE git repack -aelse cd $LOCAL_WORKSPACE git fetch --all --tags cd -fi
简化一下(以arm64为例),
git clone --reference extra/ffmpeg https://github.com/Bilibili/FFmpeg.git android/contrib/ffmpeg-arm64cd android/contrib/ffmpeg-arm64git repack -a
--reference
的作用就是会clone
之前上一步的仓库缓存,达到节省不必要的clone
时间,
2.3 init-config.sh
cp config/module-lite.sh config/module.sh
这一步是配置编译ffmpeg的参数,配置文件我们可以自己编写,config/
文件夹下面有已经预设的,module-defualt.sh
是ffmpeg官方默认的编译参数,module-lite.sh
包含通用的编译参数,module-lite-hevc.sh
在通用的基础之上添加了hevc解码,也就是俗称的H265
2.4 init-android-libyuv.sh
IJK_LIBYUV_UPSTREAM=https://github.com/Bilibili/libyuv.gitIJK_LIBYUV_FORK=https://github.com/Bilibili/libyuv.gitIJK_LIBYUV_COMMIT=ijk-r0.2.1-devIJK_LIBYUV_LOCAL_REPO=extra/libyuvset -eTOOLS=toolsecho "== pull libyuv base =="sh $TOOLS/pull-repo-base.sh $IJK_LIBYUV_UPSTREAM $IJK_LIBYUV_LOCAL_REPOecho "== pull libyuv fork =="sh $TOOLS/pull-repo-ref.sh $IJK_LIBYUV_FORK ijkmedia/ijkyuv ${IJK_LIBYUV_LOCAL_REPO}cd ijkmedia/ijkyuvgit checkout ${IJK_LIBYUV_COMMIT}cd -
下载libyuv
的库,简单来表述就是:
git clone https://github.com/Bilibili/libyuv.git extra/libyuv
3 compile-ffmpeg.sh 编译ijkffmpeg.so共享库
首先清除源码中可能存在的编译缓存
cd android/contrib./compile-ffmpeg.sh clean./compile-ffmpeg.sh all
然后开始编译ffmpeg
compile-ffmepg.sh
后面的参数代表编译哪个arm建构的版本,默认编译armv7a
,编译选项,后面执行的compile-ijk.sh
后面的选项也是同样的道理。
armv5 armv7a arm64 x86 x86_64(指定编译哪个版本)all32(所有32位处理器版本,包含armv5 armv7a x86)all (所有通用版本,包含armv5 armv7a arm64 x86 x86_64)clean (清除之前编译的缓存)check (检测支持的版本)
编译的过程中,
3.1 check archs
确认编译的相应处理器架构版本
echo "FF_ALL_ARCHS = $FF_ACT_ARCHS_ALL"
echo "FF_ACT_ARCHS = $*"
例如会编译armv7a,输出的确认信息如下:
FF_ALL_ARCHS = armv5 armv7a arm64 x86 x86_64
FF_ACT_ARCHS = armv7a
3.2 执行do-pcompile-ffmeg.sh
开始执行编译,脚本路径:android/contrib/tools/do-compile-ffmepg.sh
以编译arm64
为例,简要表述这一步,
sh tools/do-compile-ffmpeg.sh arm64
3.2.1 check env
这一步会检测,我们执行编译脚本compile-ffmpeg.sh
时,有没有添加all armv5 armv7a arm64 x86 x86_64
等选项,否则会提醒:You must specific an architecture 'arm, armv7a, x86, ...
3.2.2 make NDK standalone toolchain
这一步调用tools/do-detect-env.sh
,脚本路径:android/contrib/tools/do-detect-env.sh
检测编译环境,用于检测NDK是否在环境变量中存在,包括NDK中的gcc版本和arm-linux-androideabi的版本,
会添加一些编译的参数,这里我们会关注一个编译参数,FF_CFG_FLAGS
:编译ffmpeg添加的额外的参数(config/module.sh中已经添加了一部分参数),FF_PREFIX
编译之后输出的文件目录,例如arm64输出目录是:android\contrib\build\ffmpeg-arm64\output
3.2.3 check ffmpeg env
这一步加载fffmpeg的配置文件,这个文件就是我们之前配置的init-config.sh中配置的文件
export COMMON_FF_CFG_FLAGS=. $FF_BUILD_ROOT/../../config/module.sh`
3.2.4 configurate ffmpeg
这一步是配置ffmepg的编译参数,脚本代码块如下:
./configure $FF_CFG_FLAGS \ --extra-cflags="$FF_CFLAGS $FF_EXTRA_CFLAGS" \ --extra-ldflags="$FF_DEP_LIBS $FF_EXTRA_LDFLAGS" make clean
FF_CFG_FLAGS
就是前两步配置的编译参数。
3.2.5 compile ffmpeg
这一步是编译正式开始编译ffmpeg,脚本代码如下:
cp config.* $FF_PREFIXmake $FF_MAKE_FLAGS > /dev/nullmake installmkdir -p $FF_PREFIX/include/libffmpegcp -f config.h $FF_PREFIX/include/libffmpeg/config.h
这一步之后就完成了FFmpeg的编译过程,cp config.* $FF_PREFIX
这一字段,就是在编译之前,把我们的编译的配置信息log都被复制到了相应的moudle文件夹,路径:android/contrib/build/ffmpeg-arm64/output/
3.2.6 link ffmpeg
关键的一步来了,正常情况下,我们编译出来的ffmpeg的包含有libavcodec.a libavfilter.a libavformat.a libavutil.a libswresample.a libswscale.a
,这六个输出库,ijkplayer
将这六个库编译成一个独立libijkffmpeg.so
的共享库,
$CC -lm -lz -shared --sysroot=$FF_SYSROOT -Wl,--no-undefined -Wl,-z,noexecstack $FF_EXTRA_LDFLAGS \ -Wl,-soname,libijkffmpeg.so \ $FF_C_OBJ_FILES \ $FF_ASM_OBJ_FILES \ $FF_DEP_LIBS \ -o $FF_PREFIX/libijkffmpeg.so
以编译arm64版本为例,
aarch64-linux-android-gcc -lm -lz -shared --sysroot=/ijkplayer-android/android/contrib/build/ffmpeg-arm64/toolchain/sysroot -Wl, --no-undefined -Wl,-z, noexecstack -Wl,-soname,libijkffmpeg.so compat/*.o libavcodec/*.o libavfilter/*.o libavformat/*.o libavutil/*.o libswresample/*.o libswscale/*.o libavcodec/aarch64/*.o libavcodec/neon/*.o libavutil/aarch64/*.o libswresample/aarch64/*.o libswscale/aarch64/*.o -o /ijkplayer-android/android/contrib/build/ffmpeg-arm64/output/libijkffmpeg.so
3.2.7 create files for shared ffmpeg
这一步将生成的库文件拷贝到相应的共享文件夹,
mysedi() { f=$1 exp=$2 n=`basename $f` cp $f /tmp/$n sed $exp /tmp/$n > $f rm /tmp/$n}echo ""echo "--------------------"echo "[*] create files for shared ffmpeg"echo "--------------------"rm -rf $FF_PREFIX/sharedmkdir -p $FF_PREFIX/shared/lib/pkgconfigln -s $FF_PREFIX/include $FF_PREFIX/shared/includeln -s $FF_PREFIX/libijkffmpeg.so $FF_PREFIX/shared/lib/libijkffmpeg.socp $FF_PREFIX/lib/pkgconfig/*.pc $FF_PREFIX/shared/lib/pkgconfigfor f in $FF_PREFIX/lib/pkgconfig/*.pc; do # in case empty dir if [ ! -f $f ]; then continue fi cp $f $FF_PREFIX/shared/lib/pkgconfig f=$FF_PREFIX/shared/lib/pkgconfig/`basename $f` # OSX sed doesn't have in-place(-i) mysedi $f 's/\/output/\/output\/shared/g' mysedi $f 's/-lavcodec/-lijkffmpeg/g' mysedi $f 's/-lavfilter/-lijkffmpeg/g' mysedi $f 's/-lavformat/-lijkffmpeg/g' mysedi $f 's/-lavutil/-lijkffmpeg/g' mysedi $f 's/-lswresample/-lijkffmpeg/g' mysedi $f 's/-lswscale/-lijkffmpeg/g'done
mysedi()
函数中注意几个命令的使用方法: bansename $f
表示去掉文件f
的路径和后缀名; sed
表示查找替换功能,sed 's/\output/\/output\/shared/g'
是将/output/
替换成/output/shared/
这一步之后完成了对ffmpeg的编译,并且通过android的standalone-toolchain编译完成了ffmpeg的共享库-libijkffmpeg.so
4. 开始编译ijkplayer.so共享库
cd .../compile-ijk.sh all
这一步进入ijkplayer/
下相应版本的文件夹下面执行ndk-build
命令,将打包编译生成ijkplayer.so
,ndk-build
命令将打包编译三部分的源码: ffmepg
:之前打包编译的SRC_FILES:ijkffmpeg.so
,ffmepg
的include
android-ndk-prof
:编译ijkprof
中的c源码,生成android-ndk-profiler
的静态库,主要作用的打印ndk-build
的log信息。 ijkmedia
:编译ijkmedia/
下面的源码,其中主要包括了ijk4a,jkplayer,ijksdl,ijksoundtouch,ijkyuv
这5个模块
这一步完成之后,ndk
根据上面列出的模块下面的Android.mk
文件进行编译,最后生成ijkplayer
的共享库
- 从编译脚本分析ijkplayer详细编译过程
- Ijkplayer编译 过程
- ijkplayer从编译到使用来播放rtsp过程小结
- ijkplayer 编译so库过程
- 编译ijkplayer
- 编译ijkplayer
- ijkplayer编译
- ijkplayer编译
- ijkplayer编译脚本分析(一)——init-android.sh
- 编译链接过程的详细分析
- Go 编译过程分析(一) -- 编译脚本
- Go 编译过程分析(一) -- 编译脚本
- QGIS编译详细过程
- android-ijkplayer编译记录
- Eclipse编译ijkplayer
- 编译ijkplayer-android
- ijkPlayer的编译
- ijkplayer编译(mac)
- 如何用Intellij IDEA优雅的在GitHub开源项目
- 安卓 集成微信支付和支付宝
- Altium Designer绘制51单片机电路+PCB 3D图展示
- python基础之面向对象01
- 递归函数
- 从编译脚本分析ijkplayer详细编译过程
- 大整数相加--链表结构
- 剑指offer 斐波那契数
- B树和B+树
- mysql 创建索引语句
- iOS~runtime理解
- python之模块之shutil模块
- 交叉熵与相对熵 ---转载
- Caffe学习笔记—Caffe反向传播计算