现在ijkplayer播放器应用的非常广泛,很多播放器基本上都是基于ijkplayer二次迭代开发的,众所周知,ijkplayer是基于ffplay的,所以要使用ijkplayer,就必须使用三个so库。
- jeffmony@JeffMonydeMacBook-Pro arm64-v8a % ls -hl
- total 21240
- -rwxr-xr-x 1 jeffmony staff 9.6M 4 30 00:25 libijkffmpeg.so
- -rwxr-xr-x 1 jeffmony staff 348K 4 30 00:25 libijkplayer.so
- -rwxr-xr-x 1 jeffmony staff 474K 4 30 00:25 libijksdl.so
其中一个libijkffmpeg.so库非常大,有近9.6M,这个非常吓人了,当然你可以裁剪一些不用的库。
但是ijkplayer毕竟只是播放视频才用到的。但是ijkplayer底层是基于ffmpeg的ffplay播放框架,也就是说ffmpeg也集成到了libijkffmpeg.so中了。
这就有点意思了,那我们需要引用ffmpeg中的一些方法就不用额外的编译库了,直接使用libijkffmpeg.so中的文件就可以的。
1.节省了空间大小,防止重复编译ffmpeg导致的包体积增大。
2.native接口不用和ijkplayer的上层写在一起,可以单独写,完全不影响。
看一下这个提交: github.com/JeffMony/Pl…
1.复用libijkffmpeg.so
2.引入ffmpeg头文件
3.编译生成新的so

具体的build_ffmpeg.sh如下:
- #!/bin/bash
- export NDK_ROOT=/Users/jeffmony/tools/android-ndk-r14b # 修改自己本地的ndk路径
-
- build() {
- API=24
- ARCH=$1
- PLATFORM=$2
- SYSROOT=$NDK_ROOT/platforms/android-$API/arch-$ARCH/
- CROSS_PREFIX=$NDK_ROOT/toolchains/$PLATFORM-4.9/prebuilt/darwin-x86_64/bin/$PLATFORM-
- PREFIX=$(pwd)/android/$ARCH #自己指定一个输出目录
- rm -rf $(pwd)/android/$ARCH
-
- echo "开始编译ffmpeg $ARCH so"
- ./configure \
- --prefix=$PREFIX \
- --disable-doc \
- --enable-shared \
- --disable-static \
- --disable-x86asm \
- --disable-asm \
- --disable-symver \
- --disable-devices \
- --disable-avdevice \
- --enable-gpl \
- --disable-ffmpeg \
- --disable-ffplay \
- --disable-ffprobe \
- --enable-small \
- --enable-cross-compile \
- --cross-prefix=$CROSS_PREFIX \
- --target-os=android \
- --arch=$ARCH \
- --sysroot=$SYSROOT
- }
-
- # build armv7a
- build arm arm-linux-androideabi
- make clean
- make -j4
- make install
-
- echo "完成ffmpeg $ARCH 编译..."
-
-
- # build armv8a
- build arm64 aarch64-linux-android
- make clean
- make -j4
- make install
-
- echo "完成ffmpeg $ARCH 编译..."
文末名片免费领取音视频开发学习资料,内容包括(C/C++,Linux 服务器开发,FFmpeg ,webRTC ,rtmp ,hls ,rtsp ,ffplay ,srs)以及音视频学习路线图等等。
生成的目录中./android/arm/include 就是头文件

如果项目中使用到了ijkplayer库,也恰好需要使用ffmpeg库的功能,这时候不需要额外引入ffmpeg库了,可以直接使用ijkplayer提供的ffmpeg库,那就需要我们在编译的时候简单改造一下,使得libijkffmpeg.so可以被开发者复用。

主要的操作步骤如下:
新建一个cpp文件夹,将include文件夹拷贝到cpp下面
新建CMakeLists.txt和jeffmony.cpp,jeffmony.cpp就是自定义的native方法
修改build.gradle编译
build.gradle修改如下:

CMakeLists.txt修改如下:
- # For more information about using CMake with Android Studio, read the
- # documentation: https://d.android.com/studio/projects/add-native-code.html
-
- # Sets the minimum version of CMake required to build the native library.
-
- cmake_minimum_required(VERSION 3.4.1)
-
- ## libijkffmpeg.so
- add_library(ffmpeg SHARED IMPORTED)
- set_target_properties(ffmpeg PROPERTIES IMPORTED_LOCATION ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI}/libijkffmpeg.so)
-
- include_directories(./include)
-
- # Creates and names a library, sets it as either STATIC
- # or SHARED, and provides the relative paths to its source code.
- # You can define multiple libraries, and CMake builds them for you.
- # Gradle automatically packages shared libraries with your APK.
-
- add_library( # Sets the name of the library.
- jeffmony
-
- # Sets the library as a shared library.
- SHARED
-
- # Provides a relative path to your source file(s).
- jeffmony.cpp)
-
- # Searches for a specified prebuilt library and stores the path as a
- # variable. Because CMake includes system libraries in the search path by
- # default, you only need to specify the name of the public NDK library
- # you want to add. CMake verifies that the library exists before
- # completing its build.
-
- find_library( # Sets the name of the path variable.
- log-lib
-
- # Specifies the name of the NDK library that
- # you want CMake to locate.
- log)
-
- # Specifies libraries CMake should link to your target library. You
- # can link multiple libraries, such as libraries you define in this
- # build script, prebuilt third-party libraries, or system libraries.
-
- target_link_libraries( # Specifies the target library.
- jeffmony
- ffmpeg
- # Links the target library to the log library
- # included in the NDK.
- ${log-lib})
编译运行,生成了一个libjeffmony.so库。
具体的项目代码见:github.com/JeffMony/Pl…
- ln -s $FF_PREFIX/include $FF_PREFIX/shared/include
- ln -s $FF_PREFIX/libijkffmpeg.so $FF_PREFIX/shared/lib/libijkffmpeg.so
- cp $FF_PREFIX/lib/pkgconfig/*.pc $FF_PREFIX/shared/lib/pkgconfig
- 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'
- done
可以保证libijkffmpeg的链接顺序是正确的。
音视频开发中使用ffmpeg的地方非常多, 播放场景/音视频编辑场景, 其中使用到ffmpeg核心模块是共通的, 本文的介绍就是告诉大家, 我们可以将不同的功能模块封在同一个ffmpeg库中, 帮我们节省空间。