谷歌在android studio 2.2以后集成了CMake这个工具,关于这个工具和NDK开发的对比请看CMAKE和NDK的区别

在之前我们已经学会了使用在ndk环境下搭建ffmepg的开发环境,现在我们使用Cmake来搭建ffmepg开发环境

CMake官方教程网站(有墙)


首先,在android studio 2.2下新建一个工程,新建工程时候勾选 include C++ Support ,然后一路默认,AS就会默认给我们开启CMake

android studio 编译Read timed out Android studio 编译cmake_ffmepg


进入工程后,先看到工程会比之前的NDK项目多了几项不同的地方,在APP的build.gradle目录下多了一项CMAKE的配置

其中abiFilters"armeabi" 是生成arm架构的so库的配置 此外在工程的目录下还生成了CMakeLists.txt这个文件(重要),该文件的作用和NDK的Android.mk功能类似,用来

配置我们ffmepg生成的的so库路径和设置我们JNI C/C++文件要生成的库

android studio 编译Read timed out Android studio 编译cmake_android studio_02


然后在app/src/main目录下创建一个jniLibs文件夹,将ffmepg的 SO文件,H头文件都分别放在这个文件夹里

android studio 编译Read timed out Android studio 编译cmake_ffmepg_03

在app的build.gradle文件下添加配置

sourceSets.main{


jniLibs.srcDirs = ['libs']
    jni.srcDirs = []
}



最后我们来编写CMakeLists.txt

先上完整的代码


# Sets the minimum version of CMake required to build the native
# library. You should either keep the default value or only pass a
# value of 3.4.0 or lower.

cmake_minimum_required(VERSION 3.4.1)

set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)
add_library( avutil-55
             SHARED
             IMPORTED )
set_target_properties( avutil-55
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libavutil-55.so )

add_library( swresample-2
             SHARED
             IMPORTED )
set_target_properties( swresample-2
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libswresample-2.so )
add_library( avcodec-57
             SHARED
             IMPORTED )
set_target_properties( avcodec-57
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libavcodec-57.so )
add_library( avfilter-6
             SHARED
             IMPORTED)
set_target_properties( avfilter-6
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libavfilter-6.so )
add_library( swscale-4
             SHARED
             IMPORTED)
set_target_properties( swscale-4
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libswscale-4.so )
add_library( avdevice-57
             SHARED
             IMPORTED)
set_target_properties( avdevice-57
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libavdevice-57.so )
add_library( avformat-57
             SHARED
             IMPORTED)
set_target_properties( avformat-57
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libavformat-57.so )
add_library( x2641
             SHARED
             IMPORTED)
set_target_properties( x2641
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi/libx2641.so )

set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
include_directories(libs/include)
add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )



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 )

target_link_libraries( native-lib swresample-2 avcodec-57 avfilter-6 swscale-4 avdevice-57 avformat-57 x2641
                       ${log-lib} )

此处需要注意一点的是

add_library( native-lib
             SHARED
             src/main/cpp/native-lib.cpp )

这一句是把JNI文件编译成SO库,由于我们的JNI的C++文件是先引用到我们ffmepg的库的,所以我们必须要先添加ffmepg的库,才能够进行编译,所以这一句必须放在最后,否则编译会出错


下面来介绍下这些配置的意思



cmake_minimum_required(VERSION 3.4.1) 表示要求CMAKE的最低版本


set(distribution_DIR ${CMAKE_SOURCE_DIR}/../../../../libs)表示CMAKE的资源目录
#include <jni.h>
#include <string>

extern "C"
{
  #include <libavcodec/avcodec.h>
  #include <libavformat/avformat.h>
  #include <libavfilter/avfilter.h>
    jstring
    Java_com_example_wenxi_myapplication_MainActivity_stringFromJNI(
            JNIEnv *env,
            jobject /* this */) {
//        std::string hello = "Hello from C++";
//        return env->NewStringUTF(hello.c_str());
        char info[40000] = {0};
        avfilter_register_all();

        AVFilter *f_temp = (AVFilter *)avfilter_next(NULL);
        while(f_temp != NULL) {
            sprintf(info, "%s%s\n", info, f_temp->name);
            f_temp = f_temp->next;
        }
        return env->NewStringUTF(info);
    }
}