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

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

1.環境搭建

操做系統:Ubuntu 16.04 64bitlinux

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

FFmpeg版本:3.4.2git

NDK 下載地址github

FFmpeg 下載地址bash

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

2.編譯FFmpeg

在ffmpeg-3.4.2目錄下建立build_android.sh編譯腳本,文件名能夠隨便取,這個腳本是本文中最關鍵的內容,一塊兒來看下:ide

#!/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文件

看下生成的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目錄下:

將FFmpeg編譯成一個so文件

4.遇到的問題

NDK路徑錯誤

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

NDK路徑錯誤

android文件夾帶鎖

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

sudo chown 用戶名 android/ -R
複製代碼

5.寫在最後

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

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

GitHub傳送門

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

相關文章
相關標籤/搜索