谷歌在android studio 2.2以後集成了CMake這個工具,關於這個工具和NDK開發的對比請看CMAKE和NDK的區別
在之前我們已經學會了使用在ndk環境下搭建ffmepg的開發環境,現在我們使用Cmake來搭建ffmepg開發環境
首先,在android studio 2.2下新建一個工程,新建工程時候勾選 include C++ Support ,然後一路默認,AS就會默認給我們開啓CMake
進入工程後,先看到工程會比之前的NDK項目多了幾項不同的地方,在APP的build.gradle目錄下多了一項CMAKE的配置
其中abiFilters"armeabi" 是生成arm架構的so庫的配置 此外在工程的目錄下還生成了CMakeLists.txt這個文件(重要),該文件的作用和NDK的Android.mk功能類似,用來
配置我們ffmepg生成的的so庫路徑和設置我們JNI C/C++文件要生成的庫
然後在app/src/main目錄下創建一個jniLibs文件夾,將ffmepg的 SO文件,H頭文件都分別放在這個文件夾裏
在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的資源目錄
add_library( avutil-55 SHARED IMPORTED )將編譯好的SO庫導入到項目中,或者是編譯出SO庫,avutil-55爲編譯好的庫的名稱,SHARED是指動態庫的意思,如果是靜態庫可以用STATIC ,IMPORTED表示只是引用,如果要編譯生成SO庫,則這個參數是C/C++文件的路徑
set_target_properties( avutil-55 PROPERTIES IMPORTED_LOCATION ../../../../libs/armeabi/libavutil-55.so )對於已經編譯好的庫,需要設置這個函數引入,avutil-55 爲庫的名字,然後爲PROPERTIES IMPORTED_LOCATION+庫的路徑
include_directories(libs/include) 將ffmepg的頭文件引入,參數爲頭文件的路徑
target_link_libraries( native-lib swresample-2 avcodec-57 avfilter-6 swscale-4 avdevice-57 avformat-57 x2641 ${log-lib} ) 將所有的庫鏈接到APK文件
最後,編寫JNI的C文件
#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);
}
}
CSDN源碼地址