每當心情好或不好的時候,我喜歡一個人欣賞這種畫面。期待哪一天能實現或期待可以隨心所欲的過這種生活。
為了這個夢,這不又在拼命的工作中。最近工作中需要用到FFmpeg,就在這里總結下通過shell腳本編譯FFmpeg的過程與集成中遇到的問題。(mac平臺)
shell腳本編譯FFmpeg
1、前期準備
新建一個FFmpeg_iOS的文件夾,FFmpeg_iOS文件夾里面新建一個cache的文件夾(這個文件名寫死,后面shell腳本里面會用)。新建ffmpeg-download.sh與ffmpeg-build.sh兩個腳本文件在FFmpeg_iOS文件夾中。最后文件如下圖:
2、下載并配置gas-preprocessor
gas-preprocessor是我們需要編譯的ffmpeg的所需要的腳本文件。
1)我們將其解壓后,發現內部只有簡單的 4 個文件,如下圖:
2)將gas-preprocessor.pl文件復制粘貼到 /usr/sbin/ 目錄下(按commd+G快捷鍵,復制此路徑) ,若是根本就不能將這個文件復制到這個路徑,我們需要換一個路徑,/usr/local/bin/ 目錄下,然后為文件開啟可執行權限,打開終端輸入以下命令行。
-
如果,報錯
1476596-80c78ca1367140ed.jpg
chmod 777 /usr/sbin/gas-preprocessor.pl
或者
chmod 777 /usr/local/bin/gas-preprocessor.pl
如果還是不行,可以確定是權限問題,,那么執行之前加上
cp -R /Users/mical_lf/Desktop/gas-preprocessor.pl /usr/local/bin
3、腳本編寫
3.1 ffmpeg-download.sh腳本編寫(腳本作用下載ffmpeg)
#!/bin/bash
#庫名稱
source="ffmpeg-3.4"
#下載這個庫
if [ ! -r $source ]
then
#沒有下載,那么我需要執行下載操作
echo "沒有FFmpeg庫,我們需要下載….."
#下載:怎么下載?
#"curl"命令表示:它可以通過Http\ftp等等這樣的網絡方式下載和上傳文件(它是一個強大網絡工具)
#基本格式:curl 地址
#指定下載版本
#下載完成之后,那么我們需要解壓(通過自動解壓)
#"tar"命令:表示解壓和壓縮(打包)
#基本語法:tar options
#例如:tar xj
#options選項分為很多中類型
#-x 表示:解壓文件選項
#-j 表示:是否需要解壓bz2壓縮包(壓縮包格式類型有很多:zip、bz2等等…)
curl http://ffmpeg.org/releases/${source}.tar.bz2 | tar xj || exit 1
fi
以上直接復制到ffmpeg-download.sh即可。ffmpeg-download.sh就算編寫完成
3.2 ffmpeg-build.sh腳本編寫(編譯ffmpeg的iOS版)
#!/bin/bash
#1、首先:定義下載的庫名稱
#ffmpeg-3.4是我們通過ffmpeg-download.sh腳本下載的ffmpeg的文件名
source="ffmpeg-3.4"
#2、其次:定義".h/.m/.c"文件編譯的結果目錄
#目錄作用:用于保存.h/.m/.c文件編譯后的結果.o文件
cache="cache"
#3、定義".a"靜態庫保存目錄
#pwd命令:表示獲取當前目錄
staticdir=`pwd`/"my-ffmpeg-iOS"
#4、添加FFmpeg配置選項->默認配置
#Toolchain options:工具鏈選項(指定我么需要編譯平臺CPU架構類型,例如:arm64、x86等等…)
#--enable-cross-compile: 交叉編譯
#Developer options:開發者選項
#--disable-debug: 禁止使用調試模式
#Program options選項
#--disable-programs:禁用程序(不允許建立命令行程序)
#Documentation options:文檔選項
#--disable-doc:不需要編譯文檔
#Toolchain options:工具鏈選項
#--enable-pic:允許建立與位置無關代碼
configure_flags="--enable-cross-compile --disable-debug --disable-programs --disable-doc --enable-pic"
#核心庫(編解碼->最重要的庫):avcodec
configure_flags="$configure_flags --enable-avdevice --enable-avcodec --enable-avformat"
configure_flags="$configure_flags --enable-swresample --enable-swscale --disable-postproc"
configure_flags="$configure_flags --enable-avfilter --enable-avutil --enable-avresample "
#5、定義默認CPU平臺架構類型
#arm64 armv7->真機->CPU架構類型
#x86_64 i386->模擬器->CPU架構類型
archs="arm64 armv7 x86_64 i386"
#6、指定我們的這個庫編譯系統版本->iOS系統下的7.0以及以上版本使用這個靜態庫
targetversion="7.0"
#7、接受命令后輸入參數
#我是動態接受命令行輸入CPU平臺架構類型(輸入參數:編譯指定的CPU庫)
if [ "$*" ]
then
#存在輸入參數,也就說:外部指定需要編譯CPU架構類型
archs="$*"
fi
#8、安裝匯編器->yasm
#判斷一下是否存在這個匯編器
#目的:通過軟件管理器(Homebrew),然后下載安裝(或者更新)我的匯編器
#一個命令就能夠幫助我們完成所有的操作
#錯誤一:`which` yasm
#正確一:`which yasm`
#`which yasm`->檢測是否安裝了yasm程序
if [ ! `which yasm` ]
then
#Homebrew:軟件管理器
#下載一個軟件管理器:安裝、卸載、更新、搜索等等...
#錯誤二:`which` brew
#正確二:`which brew`
#`which brew`->檢測是否安裝了軟件管理器(Homebrew)
if [ ! `which brew` ]
then
echo "安裝brew"
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" || exit 1
fi
echo "安裝yasm"
#成功了
#下載安裝這個匯編器
#exit 1->安裝失敗了,那么退出程序
brew install yasm || exit 1
fi
echo "循環編譯"
#9、for循環編譯FFmpeg靜態庫
currentdir=`pwd`
for arch in $archs
do
echo "開始編譯"
#9.1、創建目錄
#在編譯結果目錄下-創建對應的平臺架構類型
mkdir -p "$cache/$arch"
#9.2、進入這個目錄
cd "$cache/$arch"
#9.3、配置編譯CPU架構類型->指定當前編譯CPU架構類型
#錯誤三:"--arch $arch"
#正確三:"-arch $arch"
archflags="-arch $arch"
#9.4、判定一下你到底是編譯的是模擬器.a靜態庫,還是真機.a靜態庫
if [ "$arch" = "i386" -o "$arch" = "x86_64" ]
then
#模擬器
platform="iPhoneSimulator"
#支持最小系統版本->iOS系統
archflags="$archflags -mios-simulator-version-min=$targetversion"
else
#真機(mac、iOS都支持)
platform="iPhoneOS"
#支持最小系統版本->iOS系統
archflags="$archflags -mios-version-min=$targetversion -fembed-bitcode"
#注意:優化處理(可有可無)
#如果架構類型是"arm64",那么
if [ "$arch" = "arm64" ]
then
#GNU匯編器(GNU Assembler),簡稱為GAS
#GASPP->匯編器預處理程序
#解決問題:分段錯誤
#通俗一點:就是程序運行時,變量訪問越界一類的問題
EXPORT="GASPP_FIX_XCODE5=1"
fi
fi
#10、正式編譯
#tr命令可以對來自標準輸入的字符進行替換、壓縮和刪除
#'[:upper:]'->將小寫轉成大寫
#'[:lower:]'->將大寫轉成小寫
#將platform->轉成大寫或者小寫
XCRUN_SDK=`echo $platform | tr '[:upper:]' '[:lower:]'`
#編譯器->編譯平臺
CC="xcrun -sdk $XCRUN_SDK clang"
#架構類型->arm64
if [ "$arch" = "arm64" ]
then
#音視頻默認一個編譯命令
#preprocessor.pl幫助我們編譯FFmpeg->arm64位靜態庫
AS="gas-preprocessor.pl -arch aarch64 -- $CC"
else
#默認編譯平臺
AS="$CC"
fi
echo "執行到了1"
#目錄找到FFmepg編譯源代碼目錄->設置編譯配置->編譯FFmpeg源碼
#--target-os:目標系統->darwin(mac系統早起版本名字)
#darwin:是mac系統、iOS系統祖宗
#--arch:CPU平臺架構類型
#--cc:指定編譯器類型選項
#--as:匯編程序
#$configure_flags最初配置
#--extra-cflags
#--prefix:靜態庫輸出目錄
TMPDIR=${TMPDIR/%\/} $currentdir/$source/configure \
--target-os=darwin \
--arch=$arch \
--cc="$CC" \
--as="$AS" \
$configure_flags \
--extra-cflags="$archflags" \
--extra-ldflags="$archflags" \
--prefix="$staticdir/$arch" \
|| exit 1
echo "執行了"
#解決問題->分段錯誤問題
#安裝->導出靜態庫(編譯.a靜態庫)
#執行命令
#將-j設置為支持多核心/線程
make -j3 install $EXPORT || exit 1
#回到了我們的腳本文件目錄
cd $currentdir
done
以上直接復制到ffmpeg-build.sh即可。ffmpeg-build.sh就算編寫完成
注意事項:source="ffmpeg-3.4"中ffmpeg-3.4是我們通過ffmpeg-download.sh腳本下載的ffmpeg的文件名
4、編譯
4.1 下載ffmpeg
打開終端
4.1.1 cd到FFmpeg_iOS。
4.1.2 輸入 ./ffmpeg-download.sh (回車后開始下載)
./ffmpeg-download.sh
4.2 解決與Xcode的兼容
如果直接編譯下載的ffmpeg可能會有如下錯誤
報錯信息:Typedef 'AVMediaType' cannot be referenced with a enum specifier xxx....
解決方法:將FFmpeg的源碼中的AVMediaType改個名字之后重新編譯FFmpeg再導入工程即可編譯通過。
具體方法可以在zhong duan使用linux下的sed命令,示例:
sed -i '' "s/原字符串/修改字符串/g" grep -rl 原字符串 搜索路徑
本人將AVMediaType更改為FFMAVMediaType即
sed -i '' "s/AVMediaType/FFMAVMediaType/g" grep -rl AVMediaType ./ffmpeg-*
這里要注意的是Mac上的sed如果參數有-i就必須加上備份指令,即-i后添加任意字符,那些字符就作為備份文件的后綴名,寫''即可。
如果報錯:
sed: RE error: illegal byte sequence
缺少環境變量,在shell輸入:
export LC_COLLATE='C'
export LC_CTYPE='C'
4.3 編譯ffmpeg
4.3.1 cd到FFmpeg_iOS。
4.3.2 輸入 ./ffmpeg-build.sh (回車后開始編譯)
注意:這里編譯可以編譯多種格式的
有arm64
armv7
x86_64
i386
格式
arm64 armv7->真機->CPU架構類型
x86_64 i386->模擬器->CPU架構類型
如果編譯真機版
./ffmpeg-build.sh arm64
如果編譯模擬器版
./ffmpeg-build.sh x86_64 i386
編譯成功如圖
5、Xcode集成FFmpeg
1.將編譯的ffmpeg中的include與lib拖到工程中
2.在需要用到ffmpeg的地方引入相應的頭文件
//引入頭文件
//核心庫->音視頻編解碼庫
#import <libavcodec/avcodec.h>
//導入封裝格式庫
#import <libavformat/avformat.h>
3.解決報錯
在
BuildSetting
中搜索Header Search Paths
,添加include的引入。然后編譯,OK,報錯解決
寫在最后:
希望這篇文章對您有幫助。當然如果您發現有可以優化的地方,希望您能慷慨的提出來。最后祝您工作愉快!