Android项目导入FFmpeg

2,107 阅读2分钟

学习和记录如何在项目中使用FFmpeg。

通过交叉编译生成FFmpeg动态库之后,就是导入到项目中。这里我们导入到现有项目的步骤。

1、创建Android Library

image.png 在创建了ffmpeg Library库,右击ffmpeg组件,弹出下面弹框,选择 Add C++ to Module,避免手动创建相关文件麻烦。

image.png 会自动在目录新增下面文件。

image.png

2、拷贝FFmpeg

我们将交叉编译生成的so文件拷贝到libs目录下,和头文件所在文件夹拷贝到cpp目录下。

2.1 拷贝目标so文件

我们将交叉编译生成的ffmpeg的7个so文件拷贝到libs目录下。

image.png 目标文件夹,如图所示:

image.png

将头文件拷贝到cpp目录下。

image.png

目标文件如图所示:

image.png

3、配置相关文件

3.1 配置build.gradle


android {
    ...
    defaultConfig {
       ...
       
       externalNativeBuild {
            cmake {
                cppFlags ''
                abiFilters "arm64-v8a"
            }
        }

        ndk { //过滤CPU abi arm64-v8a
            abiFilters "arm64-v8a"
        }
    }

    externalNativeBuild { //自动生成
        cmake {
            path file('src/main/cpp/CMakeLists.txt')
            version '3.22.1'
        }
    }
    sourceSets { //新增
        main {
            // 指定jni库的存放目录为libs
            jniLibs.srcDirs = ['libs']
        }
    }
}

3.2 配置CMakeList.txt

image.png 第一部分可以直接复制导入,配置资源。

include_directories("${CMAKE_SOURCE_DIR}/include")
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -L${CMAKE_SOURCE_DIR}../../../../libs/${ANDROID_ABI}")

第二部分连接到目标ffmpeg的so库,如果填写,但资源不存在,会报错。

target_link_libraries( # Specifies the target library.
        ffmpeg
        avcodec
        avdevice
        avfilter
        avformat
        avutil
        swresample
        swscale
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

4、检查配置结果

通过获取FFmpeg的版本号,来判断是否配置成功。

image.png 在kotlin文件下调用JNI,我们新建了一个FFmpegJni的object对象,并定义了getVersion方法,注意关键字是external不是native.通过Android Studio的提示,我们可以快捷的在ffmpeg.cpp文件下生成对应方法。

image.png av_version_info()函数是avcodec.so的方法,我们先引入其头文件libavcodec/avcodec.h就可以引用了。

    #include <jni.h>
    #include <string>

    extern  "C" {
    #include "libavcodec/avcodec.h"
    }

    extern "C"
    JNIEXPORT jstring JNICALL
    Java_com_xxm_ffmpeg_FFmpegJni_getVersion(JNIEnv *env, jobject thiz) {
        return env->NewStringUTF(av_version_info());
    }

5、加载ffmpeg

这里为了方便,我们再抽离出FFmpegManager类,这里调用相关方法,System.loadLibrary也会被初始化。然后activity调用getFFmpegVersion函数,不出意外,就可以获得对应的FFmpege版本

class FFmpegManager {

    init {
        System.loadLibrary("ffmpeg")
    }

    fun getFFmpegVersion():String{
        return FFmpegJni.getVersion()
    }
}

源码地址:gitee.com/zhangws_ohu…