1. 程式人生 > >使用Android Studio開發FFmpeg的正確姿勢

使用Android Studio開發FFmpeg的正確姿勢

原文地址:https://www.jianshu.com/p/0a7f3175c1b9

2018-04-21: 更新至 ffmpeg-4.0

使用AndroidStudio 開發 FFmpeg
Keywords: gradle, cmake
關鍵步驟,編譯FFmpeg,Android Studio 整合。

abi support: armeabi armeabi-v7a arm64-v8a x86 x86_64
ndk version android-ndk-r14b

export NDK_HOME=/opt/android/android-ndk-r14b
export NDK_HOST_PLATFORM=linux-x86_64

第一步,編譯ffmpeg


首先下載並解壓

wget https://ffmpeg.org/releases/ffmpeg-4.0.tar.bz2
tar xvf ffmpeg-4.0.tar.bz2

然後編寫編譯指令碼

#!/bin/sh

PREFIX=android-build

COMMON_OPTIONS="\
    --prefix=android/ \
    --target-os=android \
    --disable-static \
    --enable-shared \
    --enable-small \
    --disable-programs \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-doc \
    --disable-symver \
    --disable-asm \
    "

function build_android {
    ./configure \
    --libdir=${PREFIX}/libs/armeabi-v7a \
    --incdir=${PREFIX}/includes/armeabi-v7a \
    --pkgconfigdir=${PREFIX}/pkgconfig/armeabi-v7a \
    --arch=arm \
    --cpu=armv7-a \
    --cross-prefix="${NDK_HOME}/toolchains/arm-linux-androideabi-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/arm-linux-androideabi-" \
    --sysroot="${NDK_HOME}/platforms/android-19/arch-arm/" \
    --extra-cflags="-march=armv7-a -mfloat-abi=softfp -mfpu=neon" \
    --extra-ldexeflags=-pie \
    ${COMMON_OPTIONS}
    make clean
    make -j8 && make install

    ./configure \
    --libdir=${PREFIX}/libs/arm64-v8a \
    --incdir=${PREFIX}/includes/arm64-v8a \
    --pkgconfigdir=${PREFIX}/pkgconfig/arm64-v8a \
    --arch=aarch64 \
    --cpu=armv8-a \
    --cross-prefix="${NDK_HOME}/toolchains/aarch64-linux-android-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/aarch64-linux-android-" \
    --sysroot="${NDK_HOME}/platforms/android-21/arch-arm64/" \
    --extra-ldexeflags=-pie \
    ${COMMON_OPTIONS} 
    make clean
    make -j8 && make install

    ./configure \
    --libdir=${PREFIX}/libs/x86 \
    --incdir=${PREFIX}/includes/x86 \
    --pkgconfigdir=${PREFIX}/pkgconfig/x86 \
    --arch=x86 \
    --cpu=i686 \
    --cross-prefix="${NDK_HOME}/toolchains/x86-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/i686-linux-android-" \
    --sysroot="${NDK_HOME}/platforms/android-19/arch-x86/" \
    --extra-ldexeflags=-pie \
    ${COMMON_OPTIONS} 
    make clean
    make -j8 && make install

    ./configure \
    --libdir=${PREFIX}/libs/x86_64 \
    --incdir=${PREFIX}/includes/x86_64 \
    --pkgconfigdir=${PREFIX}/pkgconfig/x86_64 \
    --arch=x86_64 \
    --cpu=x86_64 \
    --cross-prefix="${NDK_HOME}/toolchains/x86_64-4.9/prebuilt/${NDK_HOST_PLATFORM}/bin/x86_64-linux-android-" \
    --sysroot="${NDK_HOME}/platforms/android-21/arch-x86_64/" \
    --extra-ldexeflags=-pie \
    ${COMMON_OPTIONS}
    make clean
    make -j8 && make install

};

build_android

此指令碼實現了armeabi-v7a,arm64-v8a,x86,x86_64 4個平臺的編譯。

  • 需要新增系統環境變數 $NDK_PATH
  • --target-os=android指定android平臺。
  • make install-libs 表示只安裝so檔案

編譯完成結果:

 

ffmpeg

第二步,專案整合


  • 新建專案,增加C++支援。手動建立jniLibs資料夾
  • 然後將上一步生成的所有檔案複製到jniLibs資料夾下面
    最終目錄結構:

 

project


然後修改CMakeLists.txt

檔案,整合so

 

cmake_minimum_required(VERSION 3.4.1)

find_library(log-lib log)

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

set(JNI_LIBS_DIR ${CMAKE_SOURCE_DIR}/src/main/jniLibs)

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

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

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

add_library(avcodec
            SHARED
            IMPORTED )
set_target_properties(avcodec
                      PROPERTIES IMPORTED_LOCATION
                      ${JNI_LIBS_DIR}/${ANDROID_ABI}/libavcodec.so )

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

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

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

include_directories(${JNI_LIBS_DIR}/includes)

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

簡要說明:

最後再放出效果圖:

 

FFPlayerDemo

示例程式碼:https://github.com/coopsrc/FFPlayerDemo



作者:Coopsrc
連結:https://www.jianshu.com/p/0a7f3175c1b9
來源:簡書
簡書著作權歸作者所有,任何形式的轉載都請聯絡作者獲得授權並註明出處。

 

個人補充說明:

加添標頭檔案的時候,要注意一下,不然會報undefined reference to `avcodec_configuration()'的錯誤。

因為ffmpeg是用C寫的,所以在引用它的標頭檔案的時候,需要用extern "c"包起來。

下面是具體的例子:

#include <jni.h>
#include <string>
#ifdef __cplusplus
    extern "C" {
#endif
    #include "libavcodec/avcodec.h"
#ifdef __cplusplus
    }
#endif

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