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");修改后再运行。

至此,结束。