Android-通過cmake整合ffmpeg

爾以發表於2018-11-05

今天給大家介紹把上次編譯出來的ffmpeg檔案整合到Android中。本文使用的cmake構建的ndk環境。

準備ffmpeg庫檔案

通過上篇文章Android-ffmpeg編譯so檔案,相信大家已經編譯出來ffmpeg的標頭檔案和so檔案了。

Android-通過cmake整合ffmpeg
如果大家沒編譯出來也不影響,大家可以點選下載ffmpeg庫檔案

cmake構建當前專案的NKD環境,同時整合ffmpeg

把我們當前的專案通過cmake構建一個NDK環境出來

  1. 在當前專案moudle下建立一個CMakeLists.txt檔案
  2. 在當前moudle的build檔案中新增以下內容
android{
    ...
    defaultConfig{
        externalNativeBuild {
            cmake {
                cppFlags ""
            }
            ndk {
                abiFilters "armeabi" #我當前編譯的是arm版本,所以此處指填寫arm
            }
        }
    }
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}
複製程式碼
  1. 把ffmpeg庫檔案匯入專案,同時建立自己的C++原始檔native-lib.cpp,如圖所示

Android-通過cmake整合ffmpeg
4. 編輯CMakeLists.txt 檔案

# 設定最小使用版本
cmake_minimum_required(VERSION 3.4.1)

# 新增本地so庫 native-lib:這個是宣告引用so庫的名稱 SHARED:表示共享so庫檔案
# 構建so庫的原始檔
add_library(
    native-lib
    SHARED
    src/main/cpp/native-lib.cpp
)
# 使用系統ndk 提供的庫,如 log庫
# log-lib 這個指定的是在NDK庫中每個型別的庫會存放一個特定的位置,而log庫存放
# 在log-lib中
# log 指定使用log庫
find_library(
    log-lib
    log
)
#----------------------ffmpeg的庫檔案------------
# 載入標頭檔案
include_directories(src/main/cpp/include)

# 載入avcodec-57庫
add_library( avcodec-57
             SHARED
             IMPORTED)
set_target_properties( avcodec-57
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavcodec-57.so)

add_library( avdevice-57
             SHARED
             IMPORTED)
set_target_properties( avdevice-57
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavdevice-57.so)
add_library( avfilter-6
                SHARED
                IMPORTED)
set_target_properties( avfilter-6
                          PROPERTIES IMPORTED_LOCATION
                          ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavfilter-6.so)
add_library( avformat-57
             SHARED
             IMPORTED)
set_target_properties( avformat-57
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavformat-57.so)
add_library( avutil-55
             SHARED
             IMPORTED)
set_target_properties( avutil-55
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libavutil-55.so)
add_library( swresample-2
             SHARED
             IMPORTED)
set_target_properties( swresample-2
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libswresample-2.so)
add_library( swscale-4
             SHARED
             IMPORTED)
set_target_properties( swscale-4
                       PROPERTIES IMPORTED_LOCATION
                       ${CMAKE_SOURCE_DIR}/src/main/jniLibs/armeabi/libswscale-4.so)
#----------------------end-----------------------

# 如果你本地的庫(native-lib)想要呼叫log庫的方法,
# 那麼就需要配置這個屬性,意思是把NDK庫關聯到本地庫。
# 第一個參數列示本地的庫 native-lib 要呼叫到log庫的方法,即要被關聯的庫名稱,log-lib 要關聯的庫名稱
target_link_libraries(
    native-lib
    #ffmpeg------start----------
    avcodec-57
    avdevice-57
    avfilter-6
    avformat-57
    avutil-55
    swresample-2
    swscale-4
    #ffmpeg------end------------
    ${log-lib}
)
複製程式碼
  1. 編譯一下專案,這個時候就整合成功了

測試一下

  1. Java層,建立一個native方法,同時載入native-lib
public class MainActivity extends AppCompatActivity {

    static {
        System.loadLibrary("native-lib");
    }
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        TextView text = (TextView) findViewById(R.id.text);
        text.setText(helloNDK("你好 C++ \n"));
    }
    public native String helloNDK(String msg);
}
複製程式碼
  1. C++層,對應建立helloNDK的方法
#include <jni.h>
#include <android/log.h>
extern "C"{
#include <libavformat/avformat.h>
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_example_ffmpeg_1test_MainActivity_helloNDK(JNIEnv* env,jobject,jstring msg){
    char* chello = (char *) env->GetStringUTFChars(msg, JNI_FALSE);
    __android_log_print(ANDROID_LOG_ERROR,"tag","c : %s",chello);#log日誌列印
    __android_log_print(ANDROID_LOG_ERROR,"tag","編碼器配置: %s",avcodec_configuration());#log日誌列印
    char * newstr = strcat(chello,avcodec_configuration());#將java傳過來的字串和編碼器配置資訊拼接起來並返回去
    return env->NewStringUTF(newstr);
}
複製程式碼
  1. 執行得到以下結果

Android-通過cmake整合ffmpeg

Android-通過cmake整合ffmpeg

相關文章