美文网首页CameraAndroid FFMPEGAndroid ijkplayer
FFmpeg 开源项目分析(十)白嫖ijkplayer库

FFmpeg 开源项目分析(十)白嫖ijkplayer库

作者: 码上就说 | 来源:发表于2020-09-29 00:29 被阅读0次

    FFmpeg 开源项目分析(一)FFmpeg/Openssl/x264编译
    FFmpeg 开源项目分析(二)AVFormatContext解析
    FFmpeg 开源项目分析(三)AVStream解析
    FFmpeg 开源项目分析(四)AVCodecParameters解析
    FFmpeg 开源项目分析(五)PC上实战
    FFmpeg 开源项目分析(六)FFmpeg中文件操作
    FFmpeg 开源项目分析(七)解封、解码
    FFmpeg 开源项目分析(八)修改视频封装格式
    FFmpeg 开源项目分析(九)Android输出av_log
    FFmpeg 开源项目分析(十)白嫖ijkplayer库
    FFmpeg 开源项目分析(十一)FFmpeg代码架构

    我们要引入ijkplayer播放器的时候,发现一个小小的缺陷就是so库太大了,一般有3个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的上层写在一起,可以单独写,完全不影响。

    看一下这个提交:
    https://github.com/JeffMony/PlayerSDK/commit/af1482d1842583772702a953d4612ae50d9a5631

    • 1.复用libijkffmpeg.so
    • 2.引入ffmpeg头文件
    • 3.编译生成新的so

    1.FFmpeg头文件如何生成


    具体的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 编译..."
    

    生成的目录中./android/arm/include 就是头文件


    2.如何复用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库。

    具体的项目代码见:https://github.com/JeffMony/PlayerSDK

    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
    

    阿的萨

    • 音视频开发中使用ffmpeg的地方非常多, 播放场景/音视频编辑场景, 其中使用到ffmpeg核心模块是共通的, 本文的介绍就是告诉大家, 我们可以将不同的功能模块封在同一个ffmpeg库中, 帮我们节省空间

    相关文章

      网友评论

        本文标题:FFmpeg 开源项目分析(十)白嫖ijkplayer库

        本文链接:https://www.haomeiwen.com/subject/lidsuktx.html