最新靠譜可用的 Mac 環(huán)境下 FFmpeg 環(huán)境搭建

大家好,我是光源。

最近在嘗試搭建 FFmpeg 開發(fā)環(huán)境時遇到一個蛋疼的事,Google 了 N 篇文章竟然沒有一篇是可以跑起來的!

少部分教程是給出了自我矛盾的配置(是的,按照貼出來的代碼和配置,他自己都跑不起來),大部分教程是看著挺全但忽略了某幾個關(guān)鍵的點導(dǎo)致跑不起來,更蛋疼的是碰到報錯后錯誤相關(guān)的文章也很少,當(dāng)然還有一些是年代久遠過時了。

于是在成功跑起來后,我將整個搭建過程整理出來,希望可以幫到后面的人。

本文基于 Mac OS X + Android Studio 3.2 + FFmpeg 3.3 + CMake。

文章會分為兩部分,第一部分是總結(jié)一下碰到的幾個坑,這樣只是因為報錯而無法繼續(xù)的朋友可以先看看是否可以解決問題;第二部分是搭建過程的完整描述(我特意用另一臺電腦測試過,可以完美跑起來)。

一、FFmpeg 搭建的常見問題

1. NDK 的問題

在編譯之前,教程都會讓我們修改命令中 NDK 的地址為自己本地的地址,我們當(dāng)然自然而然地改成了 Android Studio 自帶的 ndk-bundle。

然后編譯的時候就發(fā)現(xiàn)會出現(xiàn)errno.h: No such file or directory字樣的error。

這是因為 Android Studio 自帶的 NDK 缺少相關(guān)的 .h 文件,從網(wǎng)上額外下載 NDK 然后編譯時使用就可以解決問題。(基于 FFmpeg 3.3)

2. 編譯命令的問題

報錯信息形如:

ffmpeg_build.sh: line 14: ./configure: No such file or directory

ffmpeg_build.sh: line 20: --extra-cflags=-Os -fpic -marm: command not found

之類的,請檢查一下 Android 編輯腳本的 “/” 后是否有空格。

由于不同系統(tǒng)存在差異,最好找對應(yīng)系統(tǒng)下他人驗證可行的編譯命令。

3. 編譯相關(guān)的版本

編譯過程有 NDK 版本、Android 版本、FFmpeg 版本、Android Studio 版本等,不同版本存在差異,最好是完全使用教程描述時的版本。

比如編譯命令中包含的 Android 版本

export SYSROOT=$NDK/platforms/android-21/arch-arm/

這里的 android-21 改成 26 就不行,因為搜索了這兩個文件夾只有 21 中有需要的 .h 文件。

4. 項目構(gòu)建配置

需要將相關(guān)的 .so 文件和 include 文件夾(里面包含一些頭文件)都放入 libs 文件夾中,并在 gradle 文件夾中指定 jni 目錄,最后編寫 CMake 文件,缺少一步就報錯

二、FFmpeg 環(huán)境配置最佳實踐

1. 下載 FFmpeg 源碼

git clone https://git.ffmpeg.org/ffmpeg.git

再切到 3.3 分支

git checkout -b 3.3 remotes/origin/release/3.3

2. 修改 configure 文件

在下載好的 ffmpeg 文件夾內(nèi)可以找到一個 configure 文件,將其中的:

SLIBNAME_WITH_MAJOR='$(SLIBNAME).$(LIBMAJOR)'  
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'  
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_VERSION)'  
SLIB_INSTALL_LINKS='$(SLIBNAME_WITH_MAJOR)$(SLIBNAME)'

修改成

SLIBNAME_WITH_MAJOR='$(SLIBPREF)$(FULLNAME)-$(LIBMAJOR)$(SLIBSUF)'  
LIB_INSTALL_EXTRA_CMD='$$(RANLIB)"$(LIBDIR)/$(LIBNAME)"'  
SLIB_INSTALL_NAME='$(SLIBNAME_WITH_MAJOR)'  
SLIB_INSTALL_LINKS='$(SLIBNAME)'

3. 下載 NDK

就如上文所述,Android Studio 自帶的 NDK 缺少部分 .h 文件,不確定是否跟 Android Studio 的 版本或者 NDK 版本有關(guān),也不確定是否所有人都這樣。但為了簡單,還是下載吧(下載下來的的這個 NDK 只為了編譯 FFmpeg,不影響之前的 NDK)。

可以選擇去官網(wǎng)下載,我找了個國內(nèi)的 Android NDK下載(r10d r13b r14b)

下載適用于 Mac OS X 的 android-ndk-r14b-darwin-x86_64.zip 文件。

4. 編寫編譯腳本

在 ffmpeg 文件夾根目錄下創(chuàng)建一個 ffmpeg_build.sh 文件(名稱跟配置不相關(guān),想改可以改),具體內(nèi)容如下:

#!/bin/bash
make clean
# NDK的路徑,根據(jù)自己的安裝位置進行設(shè)置
export NDK=/Users/yanzhenghui/Downloads/android-ndk
export SYSROOT=$NDK/platforms/android-21/arch-arm/
export TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/darwin-x86_64
export CPU=arm
export PREFIX=$(pwd)/android/$CPU
export ADDI_CFLAGS="-marm"
function build_one
{
./configure \
    --prefix=$PREFIX \
    --target-os=linux \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --arch=arm \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \
    --extra-ldflags="$ADDI_LDFLAGS" \
    --cc=$TOOLCHAIN/bin/arm-linux-androideabi-gcc \
    --nm=$TOOLCHAIN/bin/arm-linux-androideabi-nm \
    --enable-shared \
    --enable-runtime-cpudetect \
    --enable-gpl \
    --enable-small \
    --enable-cross-compile \
    --disable-debug \
    --disable-static \
    --disable-doc \
    --disable-asm \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --enable-postproc \
    --enable-avdevice \
    --disable-symver \
    --disable-stripping \
$ADDITIONAL_CONFIGURE_FLAG
sed -i '' 's/HAVE_LRINT 0/HAVE_LRINT 1/g' config.h
sed -i '' 's/HAVE_LRINTF 0/HAVE_LRINTF 1/g' config.h
sed -i '' 's/HAVE_ROUND 0/HAVE_ROUND 1/g' config.h
sed -i '' 's/HAVE_ROUNDF 0/HAVE_ROUNDF 1/g' config.h
sed -i '' 's/HAVE_TRUNC 0/HAVE_TRUNC 1/g' config.h
sed -i '' 's/HAVE_TRUNCF 0/HAVE_TRUNCF 1/g' config.h
sed -i '' 's/HAVE_CBRT 0/HAVE_CBRT 1/g' config.h
sed -i '' 's/HAVE_RINT 0/HAVE_RINT 1/g' config.h
make clean
# 這里是定義用幾個CPU編譯,我用4個,一般在5分鐘之內(nèi)編譯完成
make -j4
make install
}
build_one

需要更改的是這個:

# NDK的路徑,根據(jù)自己的安裝位置進行設(shè)置
export NDK=/Users/yanzhenghui/Downloads/android-ndk

改成你本地的路徑。

5.執(zhí)行腳本

從命令行進入 ffmpeg 文件夾后,先執(zhí)行

chmod +x ffmpeg_build.sh

命令給腳本開啟權(quán)限,再執(zhí)行編譯腳本:

./ffmpeg_build.sh

等待編譯完成,即可在 ffmpeg 文件夾內(nèi)看到 android 文件夾,里面包含了我們需要的 .so 文件和對應(yīng)的頭文件

圖一

6.配置 ffmpeg 項目

這部分 Android - FFmpeg & Mac & AndroidStudio & CMake 環(huán)境搭建 這篇文章寫得足夠好,我就不重復(fù)造輪子了,下面摘抄部分權(quán)當(dāng)轉(zhuǎn)載了。(當(dāng)然,我也全部測試過能跑起來)

6.1 新建項目

新建一個以 CMake 方式構(gòu)建的 C++ 項目(記得勾選 Include C++ Support)

屏幕快照 2018-05-13 下午1.26.56.png

6.2 拷貝文件到 libs 目錄下

將編譯好的 .so 和頭文件拷貝到 libs 目錄下:

屏幕快照 2018-05-13 下午7.07.51.png

6.3 指定 jniLibs 路徑

android {
    ...
    sourceSets {
        main {
            jniLibs.srcDirs = ['libs']
        }
    }
}

6.4 配置 abiFilters

因為我們只編譯出 armeabi-v7a 的 so,所以需要特別指定一下 abi

android {
    ...
    defaultConfig {
      ...
      idk {
          abiFilters 'armeabi-v7a'
      }
    }
}

6.5 編寫 CMakeLists

# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
             native-lib
             # Sets the library as a shared library.
             SHARED
             # Provides a relative path to your source file(s).
             src/main/cpp/native-lib.cpp )
add_library( avcodec-57
             SHARED
             IMPORTED )
set_target_properties( avcodec-57
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi-v7a/libavcodec-57.so )
add_library( avfilter-6
             SHARED
             IMPORTED )
set_target_properties( avfilter-6
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi-v7a/libavfilter-6.so )
add_library( avformat-57
             SHARED
             IMPORTED )
set_target_properties( avformat-57
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi-v7a/libavformat-57.so )
add_library( avutil-55
             SHARED
             IMPORTED )
set_target_properties( avutil-55
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi-v7a/libavutil-55.so )
add_library( swresample-2
             SHARED
             IMPORTED )
set_target_properties( swresample-2
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi-v7a/libswresample-2.so )
add_library( swscale-4
             SHARED
             IMPORTED )
set_target_properties( swscale-4
                       PROPERTIES IMPORTED_LOCATION
                       ../../../../libs/armeabi-v7a/libswscale-4.so )
include_directories( libs/include )
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 )
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
                       native-lib
                       avcodec-57
                       avfilter-6
                       avformat-57
                       avutil-55
                       swresample-2
                       swscale-4
                       # Links the target library to the log library
                       # included in the NDK.
                       ${log-lib} )

6.6 Java 引入 so 庫

static {
    System.loadLibrary("native-lib");
    System.loadLibrary("avcodec-57");
    System.loadLibrary("avfilter-6");
    System.loadLibrary("avformat-57");
    System.loadLibrary("avutil-55");
    System.loadLibrary("swresample-2");
    System.loadLibrary("swscale-4");
}

最后運行測試下,即配置完成。

參考資料

  1. Android - FFmpeg & Mac & AndroidStudio & CMake 環(huán)境搭建
  2. FFmpeg-3.3.1移植到Android平臺(Mac編譯)
  3. Mac 環(huán)境下ffmpeg編譯出現(xiàn) errno.h: No such file or directory 錯誤問題
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容