android studio 使用CMAKE 編譯ffmepg

谷歌在android studio 2.2以後集成了CMake這個工具,關於這個工具和NDK開發的對比請看CMAKE和NDK的區別

在之前我們已經學會了使用在ndk環境下搭建ffmepg的開發環境,現在我們使用Cmake來搭建ffmepg開發環境

CMake官方教程網站(有牆)


首先,在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源碼地址




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章