Android studio集成ffmpeg

参阅了网上较多的教程,由于各个教程使用Android studio版本存在差异性,照抄后果然出现了大翻车。经过摸索得出了以下亲测无误的方案。
一,ffmpeg存放位置。
ffmpeg有头文件和so库,还有各个CPU指令级对应的so库,网上的方法均均是放在project/module/libs下,这个目录是存在风险的在默认情况下build.gradle会进行以下定义:

dependencies {
...
    implementation fileTree(dir: "libs", include: ["*.jar"])
    ..
    }

即会将libs下的*.jar文件打包至项目,个人觉得放置在此处不太合适。所以我选择了放置在了project\module\src\main\ffmpeg下。其目录结构如下

so存放相关目录
-arm64-v8a
 --xxx.so
-armeabi-v7a
 --xxx.so
...
#头文件存放相关目录
-libavcodec
-libavdevice
...

尝试过存在在jniLibs目录,但这个目录会与cmake文件中的相关定义冲突导致重复引入so,以致编译失败。

二,CMakeLists.txt文件定义。
文件内容如下

cmake_minimum_required(VERSION 3.10.2)
#引入头文件
include_directories(${CMAKE_SOURCE_DIR}/../ffmpeg/)
#引入so路径
set(DIR ${CMAKE_SOURCE_DIR}/../ffmpeg)
# Declares and names the project.

project("ffmpeg")

add_library(
             native-lib

             SHARED

             native-lib.cpp )

#添加库
add_library(
        avcodec
        SHARED
        IMPORTED
)
#${DIR}为上面定义的so路径,${ANDROID_ABI}为cpu指令路径
set_target_properties(
        avcodec
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/${ANDROID_ABI}/libavcodec.so)

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

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

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

add_library(
        avutil
        SHARED
        IMPORTED
)
set_target_properties(
        avutil
        PROPERTIES IMPORTED_LOCATION
        ${DIR}/${ANDROID_ABI}/libavutil.so
)

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

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

find_library(
              log-lib

              log )
#链接库
target_link_libraries(
                       native-lib
                       avcodec
                       avdevice
                       avfilter
                       avformat
                       avutil
                       swresample
                       swscale
                       ${log-lib} )

需要注意的是引入头文件步骤中${CMAKE_SOURCE_DIR}变量这个变量表示CMakeLists.txt所在的目录,引入头文件在自己编写的cpp文件中才能引入头文件不报错。
还需要注意${ANDROID_ABI}这个变量,这个变量指的是编译时的CPU指令级参数,项目中一般情况下需要兼容多种指令集,而set_target_properties不能重复映入不同指令集so的,需要通过参数进行引入。

三,cpp文件引入头文件和方法调用

#include <jni.h>
#include <string>
extern "C"{
//cpp必须使用该方法导入第三方头文件
#include "libavcodec/avcodec.h"
}

extern "C" JNIEXPORT jstring JNICALL
Java_top_foxhome_demo_ffmpeg_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = avcodec_configuration();
    return env->NewStringUTF(hello.c_str());
}

需要将头文件放置在extern "C"{...}内,否则编译会出错,也无法进行方法调用。

四,build.gradle需要指明编译后生成的指令级。

        externalNativeBuild {
            cmake {
                cppFlags ''
                //添加cpu支持
                abiFilters 'armeabi-v7a','arm64-v8a','x86','x86_64'
            }
        }

abiFilters中的值需要与project\module\src\main\ffmpeg支持的指令集对应,编译时CMakeLists.txt文件中${ANDROID_ABI}也与之对应。

代码阅读链接

https://github.com/JunjieHuang945/helloFFMPEG

发表回复

CAPTCHAis initialing...