Android NDK開發(三) 在Linux環境下編譯FFmpeg

FFmpeg是一套可以用來記錄、轉換數字音頻、視頻,並能將其轉化爲流的開源計算機程序。它提供了錄製、轉換以及流化音視頻的完整解決方案。

1.環境搭建

操作系統:Ubuntu 16.04 64bit

NDK版本:android-ndk-r14b-linux-x86_64

FFmpeg版本:3.4.2

NDK 下載地址

FFmpeg 下載地址

將NDK和FFmpeg源碼解壓至指定目錄,文中解壓在了Home > ffmpeg目錄下,注意NDK的版本一定要選擇Linux版的,在編譯的時候我就犯了這個錯誤,使用了Windows版的NDK,一直報錯也找不到原因,切記切記!

2.編譯FFmpeg

在ffmpeg-3.4.2目錄下創建build_android.sh編譯腳本,文件名可以隨便取,這個腳本是本文中最關鍵的內容,一起來看下:

#!/bin/bash

# 設置臨時文件夾,需要提前手動創建
export TMPDIR="/home/yangle/ffmpeg/ffmpeg-3.4.2/ffmpegtemp"

# 設置NDK路徑
NDK=~/ffmpeg/android-ndk-r14b

# 設置編譯針對的平臺,可以根據實際需求進行設置
# 當前設置爲最低支持android-14版本,arm架構
SYSROOT=$NDK/platforms/android-14/arch-arm

# 設置編譯工具鏈,4.9爲版本號
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64

function build_one
{
./configure \
    --enable-cross-compile \
    --enable-shared \
    --disable-static \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-avdevice \
    --disable-doc \
    --disable-symver \
    --prefix=$PREFIX \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --target-os=android \
    --arch=arm \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \

$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install
}

# 設置編譯後文件的輸出目錄
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one

前四項配置按照你本機的實際路徑修改就可以了,注意ffmpegtemp這個臨時文件夾需要提前手動創建,【~/】 在Linux上代表 【/home/用戶名/】,看下build_one這個方法,enable、disable分別代表打開和關閉一些功能,重點看下下面幾個配置:

--enable-shared
--disable-static

編譯動態庫,shared和static的開關是相對的。

--prefix=$PREFIX

CPU=arm
PREFIX=$(pwd)/android/$CPU

設置編譯後文件的輸出目錄,$(pwd)代表當前目錄,所以文件的輸出路徑爲:ffmpeg-3.4.2/android/arm

--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi-

設置交叉編譯器,按照實際路徑修改就可以了。

--target-os=android

設置編譯針對的系統,網上查到很多資料說編譯前需要修改configure文件,設置這項後就不用修改了,系統會自動爲我們修改,效果一樣。

--arch=arm

設置編譯so庫的架構,當前設置爲arm,可以根據實際需求修改。

--sysroot=$SYSROOT

設置編譯針對的平臺,可以根據實際需求進行設置,當前設置爲最低支持android-14版本,arm架構。

--extra-cflags="-Os -fpic $ADDI_CFLAGS" 

ADDI_CFLAGS="-marm"

還沒有完全理解這幾個參數的作用,有知道的同學可以給我留言啊,謝謝!

到這裏,編譯腳本就寫完了,在當前目錄下打開終端窗口,執行腳本,加上管理員權限,以防權限不足:

$ sudo ./build_android.sh

回車提示輸入密碼,密碼不會顯示出來或者顯示成*號,直接輸完然後回車就可以了,看下執行效果:

編譯中:

如果一切順利的話,大概十多分鐘就可以編譯完成:

編譯完成後,在當前目錄下(ffmpeg-3.4.2)會生成一個android目錄,so文件就在android > arm > lib目錄下:

看下生成的so包是做什麼用的:

  • libavcodec:用於各種類型聲音、圖像編解碼。

  • libavformat:用於各種音視頻封裝格式的生成和解析,讀取音視頻幀等功能。

  • libavutil:包含一些公共的工具函數。

  • libavfilter:提供了各種音視頻過濾器。

  • libswresample:用於音頻重採樣,採樣格式轉換和混合。

  • libswscale:用於視頻場景比例縮放、色彩映射轉換。

3.將FFmpeg編譯成一個so文件

在上文中我們成功的編譯了FFmpeg,但是編譯出來的so文件一共有6個,如果覺的使用起來比較麻煩,可以編譯成一個so文件,下面我們來修改下腳本:

#!/bin/bash

# 設置臨時文件夾,需要提前手動創建
export TMPDIR="/home/yangle/ffmpeg/ffmpeg-3.4.2/ffmpegtemp"

# 設置NDK路徑
NDK=~/ffmpeg/android-ndk-r14b

# 設置編譯針對的平臺,可以根據自己的需求進行設置
# 當前設置爲最低支持android-14版本,arm架構
SYSROOT=$NDK/platforms/android-14/arch-arm

# 設置編譯工具鏈,4.9爲版本號
TOOLCHAIN=$NDK/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64

function build_one
{
./configure \
    --enable-cross-compile \
    --enable-static \
    --disable-shared \
    --disable-doc \
    --disable-ffmpeg \
    --disable-ffplay \
    --disable-ffprobe \
    --disable-ffserver \
    --disable-avdevice \
    --disable-doc \
    --disable-symver \
    --prefix=$PREFIX \
    --cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
    --target-os=android \
    --arch=arm \
    --sysroot=$SYSROOT \
    --extra-cflags="-Os -fpic $ADDI_CFLAGS" \

$ADDITIONAL_CONFIGURE_FLAG
make clean
make
make install

# 合併生成的靜態庫
$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$SYSROOT/usr/lib \
-L$SYSROOT/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
    libavcodec/libavcodec.a \
    libavfilter/libavfilter.a \
    libswresample/libswresample.a \
    libavformat/libavformat.a \
    libavutil/libavutil.a \
    libswscale/libswscale.a \
    -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
    $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a
}

# 設置編譯後的文件輸出目錄
CPU=arm
PREFIX=$(pwd)/android/$CPU
ADDI_CFLAGS="-marm"
build_one

看下和編譯單個so文件的腳本有什麼區別:

生成靜態庫:

--disable-static
--enable-shared

修改爲:

--enable-static
--disable-shared

增加下面的指令,將生成的靜態庫合併成一個動態庫:

$TOOLCHAIN/bin/arm-linux-androideabi-ld \
-rpath-link=$SYSROOT/usr/lib \
-L$SYSROOT/usr/lib \
-L$PREFIX/lib \
-soname libffmpeg.so -shared -nostdlib -Bsymbolic --whole-archive --no-undefined -o \
$PREFIX/libffmpeg.so \
    libavcodec/libavcodec.a \
    libavfilter/libavfilter.a \
    libswresample/libswresample.a \
    libavformat/libavformat.a \
    libavutil/libavutil.a \
    libswscale/libswscale.a \
    -lc -lm -lz -ldl -llog --dynamic-linker=/system/bin/linker \
    $TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a

重點看下下面兩個配置:

-soname libffmpeg.so

指定動態庫,也就是so文件的名稱。

$TOOLCHAIN/lib/gcc/arm-linux-androideabi/4.9.x/libgcc.a

設置編譯器的路徑,根據實際路徑進行修改,編譯前一定要檢查一遍路徑是否正確!

腳本中還涉及到一些編譯指令,都可以在網上查到作用,在這裏就不再一一說明了,OK,開始執行編譯腳本:

$ sudo ./build_android_all.sh

編譯完成後,生成的libffmpeg.so就在android > arm目錄下:

4.遇到的問題

NDK路徑錯誤

遇到這個錯誤仔細檢查一遍設置的路徑有沒有問題,我就栽在了這個坑裏:

android文件夾帶鎖

編譯成功後,android文件夾是帶鎖的,執行下面的命令就可以解鎖:

sudo chown 用戶名 android/ -R

5.寫在最後

第一次使用Linux系統和編譯FFmpeg,一直在網上查命令和各種報錯的解決方案,這篇文章前前後後寫了一個多月,如有錯誤的地方,可以給我留言指正,多謝!

文中用到的FFmpeg源碼、編譯腳本以及編譯生成的so文件已經上傳至GitHub,後續還會更新,歡迎Start、Fork!

GitHub傳送門

本篇文章到這裏就結束了,下一篇文章將會繼續介紹如何在Android項目中使用FFmepg,敬請期待!

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