ijkPlayer主要包含了android, extra, ijkmedia, ios几个核心源码目录
android 目录包括了android 平台上层接口提供、用例等等
----ijkplayer:android 测试用例,直接导入android studio后可以使用(但需要事先先编译好so库)
----compile-ijk.sh:ijkplayer总的编译脚本文件,生成libijksdl.so和libijkplayer.so文件,并同时将这两文件及相应平台的libijkffmpeg.so拷贝到android-ijkplayer-ijkplayer-xxx目录下,拷贝目录是android-contrib-ffmpeg-xxx(下面会介绍到)
----contrib----compile-ffmpeg.sh:ffmpeg总的编译脚本文件,最终调用的是tools下的do-compile-ffmpeg.sh,执行后在会contrib目录下升成一个build文件夹,在该文件夹下生成各个平台的的so库文件。编译时可以选择只编译相应用平台。
----contrib----ffmpeg-xxx:不同平台的ffmpeg的源码目录
----contrib----tools:ffmpeg的编译脚本所需的工具,包括了ndk版本要求检查
----config:ffmpeg的module配置目录,可以对ffmpeg进行裁剪优化等等,这个裁剪包括了支持哪些编解码器、流媒体协议等等
----extra:这个目录只是用来备份相关源码,如ffmpeg、libyuv等等,如contrib-ffmpeg-xxx不同平台的源码就是从这拷贝过去的
----ijkmedia:最主要的核心代码
----ijkmedia----ijkplayer核心代码实现,其中包括与android上层交互的实现、基本的解协议、编解码的基本流程。
----ijkmedia----ijksdl:音视频渲染相关,ijksdk依赖了第三方开源库libyuv
----ijkmedia----ijkj4a:这个和音频的输出有关
----ios:ios平台开发相关的
除了上面提到compile-ijk.sh和compile-ffmpeg.sh外还有一个也很重要的脚本文件init-android.sh,其实这个应该先介绍的,从执行顺序来讲。
----init-android.sh:拉取ffmpeg的源代码到extra中,并依次拷贝到android-contrib-ffmpeg-xxx里,接着执行以下脚本文件
./init-config.sh 配置ffmpeg的module,可以对ffmpeg进行定制
./init-android-libyuv.sh 拉取libyuv的源码到extra,并拷贝到ijkmedia
./init-android-soundtouch.sh 拉取soundtouch的源码到extra,并拷贝到ijkmedia
然后我们来简单理一下流程
1、执行init-config.sh脚本,接取ffmpeg及相关源码
2、执行compile-ffmpeg.sh,编译得到libijkffpeg.so库
3、执行compile-ijk.sh,编译得到libijkijkplayer.so和libijksdl.so库
刚好遇到一个需求修改so库的名称
初看可能会觉得这需求有点奇怪,好好的为什么要修改so库的名称呢?
其实是因为在开发过程中我们遇到了这样的现象:前提,我们为上层提供定制的播放器,在提供了正确的so库后,但上层反馈回来的日志打印的ijk及ffmpeg的版本却是错的?实步排除了so没有正确替换的可能性,经排查,原为上层app是内置app,内置app的lib库是需要统一拷贝到/system/lib下的,那在这种情况下会出现同名覆盖的情况,所以出现了这样的需求。
刚好可以拿着这个来熟悉上面的流程
第一个自然要修改是的libijkffmpeg.so的名字了,第一步是拉取源码,所以走第二步,从上面可以知道编译ffmpeg最终调用的是android-contrib-tools-do-compile-ffmpeg.sh脚本,打开后搜索ijkffmpeg关键字(表示我也不是很懂这块的囧)
$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
编译so的命令-soname 这不是so的名字嘛,-o,文件输出,很大胆的先改了再说。接着链接文件
ln -s $FF_PREFIX/include $FF_PREFIX/shared/include
ln -s $FF_PREFIX/libijkffmpeg.so $FF_PREFIX/shared/lib/libijkffmpeg.so
输出文件改了,后续自然也要改着改。
还有最后一处,替换字符串,自然也要修改了
for 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'
修改好后,
执行
init-config.sh脚本,成功后我们可以在android-contrib-build文件夹下找相应用平台编译出来的so库,名字也改成了libxxxffmpeg.so(按原先规范来改)
接着是libijkplayer.so和libijksdl.so,一样从上面我们可以知道是执行compile-ijk.sh后生成的,player包括了与andorid上层交互,即jni,而我们在ijkmedia里的ijkplayer和ijksdl源码目录gh各自找到了熟悉Android.mk
ijkplayer要依赖于ijksdl,所以我们先看ijksdl
LOCAL_SHARED_LIBRARIES := ijkffmpeg
LOCAL_STATIC_LIBRARIES := cpufeatures yuv_static ijkj4a
LOCAL_MODULE := ijksdl
LOCAL_SHARED_LIBRARIES:要链接到本模块的动态库
LOCAL_MODULE:模块名称
二话不说直接改了
最后是ijkplayer,一样的
LOCAL_SHARED_LIBRARIES := ijkffmpeg ijksdl
LOCAL_STATIC_LIBRARIES := android-ndk-profiler ijksoundtouch
LOCAL_MODULE := ijkplayer
然后很开心的去编译了./
compile-ijk.sh
然后霹雳啪啦的报错了,漏了一个地方
根据报错信息,我们很容易定位到了android/ijkplayer/ijkplayer-xxx/src/main/jni/ffmpeg/Android.mk
LOCAL_MODULE := ijkffmpeg
LOCAL_SRC_FILES := $(MY_APP_FFMPEG_OUTPUT_PATH)/libijkffmpeg.so
将所有平台下的信息修改后好了,编译,success!
最后记得将demo里的libLoader.loadLibrary("name");修改后再运行。
至此,结束。