音视频开发之旅(四) -----在Android调用ffmpeg so库和.a库

1 .前言

Andorid是支持C++库的,libc++ 的共享库为 libc++_shared.so,静态库为 libc++_static.a

  • 静态库
    如果应用的所有原生代码均位于一个共享库中,这样可让链接器最大限度内联和精简未使用的代码,使应用达到最优化状态且文件最小巧。在链接阶段,会将汇编生成的目标文件.o与引用到的库一起链接打包到可执行文件中。静态库对函数库的链接是放在编译时期完成的。

  • 动态库
    *动态库在程序编译时并不会被连接到目标代码中,而是在程序运行是才被载入。不同的应用程序如果调用相同的库,那么在内存里只需要有一份该共享库的实例,规避了空间浪费问题。

在使用时避免自己使用的so库与其他第三方的so库冲突,不然只有在程序运行到的时候才会发现异常。

1.1 在Android中使用ffmpeg的so库

这里Cmake的 gradle配置可以参考上篇

github代码直通车 里面的ffmpegtest 应用

1.1.1 首先先复制so库和提供的头文件

在这里插入图片描述

1.1.2 CMkeLists修改

cmake_minimum_required(VERSION 3.4.1)

# 设置生成的so动态库最后输出的路径
# set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${PROJECT_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})

# 支持C++11标准和GNU扩展特性
#set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")

# 1. 定义so库和头文件所在目录,方面后面使用
set(ffmpeg_lib_dir ${CMAKE_SOURCE_DIR}/../jniLibs/${ANDROID_ABI})
set(ffmpeg_head_dir ${CMAKE_SOURCE_DIR}/ffmpeg)

message("当前cmakel路径: ${ffmpeg_lib_dir}")

# 2. 添加头文件目录
include_directories(${ffmpeg_head_dir}/include)

# 3. 添加ffmpeg相关的so库
add_library( avutil
        SHARED
        IMPORTED )
set_target_properties( avutil
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavutil.so )

add_library( swresample
        SHARED
        IMPORTED )
set_target_properties( swresample
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswresample.so )

add_library( avcodec
        SHARED
        IMPORTED )
set_target_properties( avcodec
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavcodec.so )

add_library( avfilter
        SHARED
        IMPORTED)
set_target_properties( avfilter
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavfilter.so )

add_library( swscale
        SHARED
        IMPORTED)
set_target_properties( swscale
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libswscale.so )

add_library( avformat
        SHARED
        IMPORTED)
set_target_properties( avformat
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavformat.so )

add_library( avdevice
        SHARED
        IMPORTED)
set_target_properties( avdevice
        PROPERTIES IMPORTED_LOCATION
        ${ffmpeg_lib_dir}/libavdevice.so )

# 查找代码中使用到的系统库
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 )

# 配置目标so库编译信息
add_library( # Sets the name of the library.
        native-lib

        # Sets the library as a shared library.
        SHARED

        # Provides a relative path to your source file(s).
        ffmpeg_lib.cpp

        )

# 指定编译目标库时,cmake要链接的库
target_link_libraries(

        # 指定目标库,native-lib 是在上面 add_library 中配置的目标库
        native-lib

        # 4. 连接 FFmpeg 相关的库
        avutil
        swresample
        avcodec
        avfilter
        swscale
        avformat

        # Links the target library to the log library
        # included in the NDK.
        ${log-lib} )

1.1.3 jni所交互的c++文件 ffmpeg_lib.cpp

在这里调用ffmpeg的版本并显示

#include <jni.h>

extern "C" {
#include <libavcodec/avcodec.h>
#include <libavformat/avformat.h>
#include <libavfilter/avfilter.h>
#include <libavcodec/jni.h>
}


/**
 * 拿到 ffmpeg 当前版本
 * @return
 */
const char *getFFmpegVer() {
    return av_version_info();
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_hugh_ffmpegtest_MainActivity_getFFmpegVersion(JNIEnv *env, jclass type) {
    return env->NewStringUTF(getFFmpegVer());
}

1.1.4 在Acitivity的使用

public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        TextView ffmpegVer = findViewById(R.id.ffmpeg_ver);
        ffmpegVer.setText("当前 FFmpeg 版本为:" + getFFmpegVersion());
    }

    /**
     * @return 返回当前
     */
    public native static String getFFmpegVersion();
}

1.2 在Android中使用ffmpeg的.a库

具体操作都是和用.so一样,只有CMakeLists.txt脚本需要更改
确保所指定的路径(库和头文件)都对就行了,就能一把过了

#指定 Cmake 最低版本
cmake_minimum_required(VERSION 3.4.1)

#找到包含所有的cpp文件
file(GLOB allCpp *.cpp)

#打印当前 cmakeLists 的路径
message("当前cmakel路径: ${CMAKE_SOURCE_DIR} \n cpu架构:${CMAKE_ANDROID_ARCH_ABI}")

add_library(
        ffmpeg_lib

        SHARED

        ${allCpp})

find_library(
        log-lib

        log)

# 引入FFmpeg的头文件
include_directories(${CMAKE_SOURCE_DIR}/include)

# 引入FFmpeg的库文件,设置内部的方式引入,指定库的目录是 -L  指定具体的库-l
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}/${CMAKE_ANDROID_ARCH_ABI}")

target_link_libraries(
        ffmpeg_lib

 
        avformat avcodec avfilter avutil swresample swscale

        ${log-lib})

版权声明:本文为qq_38366777原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。