2013年1月27日 星期日

FFMPEG -- 編譯 ffmpeg library for iOS

本篇介紹如何在 MAC 環境下編譯 FFMPEG,並且使用 iphone simulator 進行測試。

文章中使用的軟體版本皆是 2013/01/27 時的最新版本:
  • Virtual Box 4.2.6 r82870
  • Mac OS X 10.8.2
  • Xcode 4.5.2
  • git 1.7.10.2
  • FFMPEG, checkout the latest version of Jan 27, 2013 
  • iFrameExtractor, checkout the latest version of Oct 21, 2012



測試步驟如下:

1. 建立 iOS 的開發環境
若是MAC的使用者,可以直接使用appstore安裝Xcode。
若是 Windows 使用者,則可以參考 weiphone 文章 http://bbs.weiphone.com/read-htm-tid-5329046.html, 先使用 VirtualBox 安裝 Mac OS X 10.8,並升級至 10.8.2,接著才在 Mac OS 安裝 xcode 4.5.2。筆者分別在兩種環境下皆測試無誤,但是建議還是直接使用 MAC 開發為佳。
後續進行步驟都是在 OS X 10.8.2 下完成。
2. 安裝 git 以下載 open source
http://git-scm.com/
3. 下載 ffmpeg
git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
4. 新增. profile 並設定路徑
$vi ~/.profile
  export PATH=/Applications/Xcode.app/Contents/Developer/usr/bin:$PATH
若要增加其他環境變數,可參考 http://www.tech-recipes.com/rx/2621/os_x_change_path_environment_variable/

5. 編寫 build.sh ,利用 configure 產生 makefile

./configure --disable-doc --disable-ffmpeg --disable-ffplay --disable-ffserver --disable-debug --disable-encoders --enable-cross-compile --disable-decoders --disable-armv5te --enable-decoder=h264 --enable-pic --cc=/Applications/Xcode.app/Contents//Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc --as='gas-preprocessor/gas-preprocessor.pl /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc' --extra-ldflags=-L/Applications/Xcode.app/Contents//Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/lib/system --sysroot=/Applications/Xcode.app/Contents//Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk --target-os=darwin --arch=i386 --cpu=i386 --extra-cflags='-arch i386' --extra-ldflags='-arch i386' --disable-asm --enable-swresample --enable-gpl --enable-postproc --prefix=compiled/i386
以下是 iFrameExtrator 建議的編譯選項,會編譯所有codec,library會大很多。 ./configure \ --cc=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc \ --as='/usr/local/bin/gas-preprocessor.pl /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/usr/bin/gcc' \ --sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk \ --target-os=darwin \ --arch=i386 \ --cpu=i386 \ --extra-cflags='-arch i386' \ --extra-ldflags='-arch i386 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator5.1.sdk' \ --prefix=compiled/i386 \ --enable-cross-compile \ --enable-nonfree \ --enable-gpl \ --disable-armv5te \ --disable-swscale-alpha \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-asm \ --disable-debug                                                          
此處編譯選項是針對 iFrameExtractor 設計,若是自行撰寫程式控制 ffmpeg,則可以省略。  

6. 執行 build.sh 產生 makfile
若此步驟發生問題,可以檢視 config.log 確認問題。

7. 執行 make


8. 執行 make install,此時會將編譯好的 library 複製到 ffmpeg/compiled/i386/lib,建立此目錄是為了區別之後可能會編譯 arm7的library。

9. 接著便可以自行使用 ffmpeg library。
為了容易使用,我直接先套用一個現成的library "iFrameExtractor"。
git clone git://github.com/lajos/iFrameExtractor.git 
下載成功後,雙擊 iFrameExtractor.xcodeproj即可,因為此專案是使用 Xcode 4.5 開發的,因此會自動下載 Xcode 4.5 Developer Library。
這部分我是直接取消,Xcode會詢問是否要轉換到新的設定,此時選擇YES即可將其套用到 Xcode 4.5.2 ,接著需要修改 ffmpeg 的 include 與 lib 路徑,使其指向正確路徑,並且將編譯的target選擇 iOS 6.0。

10. 執行成功,畫面如下所示。



10. 若要測試 RTSP Stream, 將 initWithVideo 所帶的路徑更改為URL即可。
例如: 
self.video =[[VideoFrameExtractor alloc] initWithVideo:@"rtsp://192.168.0.10:554/livestream"];

11. 若要使用 ARM 的 NEON 功能,則在編譯時要加入 "--enable-asm  --enable-neon"
./configure \ --cc=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc \ --as='/user/local/bin/gas-preprocessor.pl /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/gcc' \ --sysroot=/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk \ --target-os=darwin \ --enable-asm \ --enable-neon \ --enable-pic \ --disable-thumb \ --arch=armv7 \ --cpu=cortex-a9 \ --extra-cflags='-arch armv7 -mfpu=neon -mfloat-abi=softfp' \ --extra-ldflags='-arch armv7 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS6.1.sdk' \ --prefix=compiled/armv7-neon \ --enable-cross-compile \ --enable-nonfree \ --enable-gpl \ --disable-armv5te \ --disable-swscale-alpha \ --disable-doc \ --disable-ffmpeg \ --disable-ffplay \ --disable-ffprobe \ --disable-ffserver \ --disable-debug

12. 若是執行 ffmpeg 時出現問題,建議編譯成 debug library追蹤問題。
將上述的 --disable-debug 改為 --enable-debug --disable-stripping即可就我使用的經驗,step11 編譯出的 library 其大小約 10.1MB,enable debug後編譯出的 library 其大小約 69 MB,大小真的差異很大。
我個人的偏好作法是 i386 library enable debug, arm library disable debug。

13. 若升級至新版 xcode 5.0,則需要修改路徑才能正常編譯,
以編譯 armv7s 為例,使用 Xcode 5.0 需要修改下列幾個參數 --cc=/Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang --as='/usr/local/bin/gas-preprocessor.pl /Applications/XCode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/clang' --sysroot=/Applications/XCode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk --extra-ldflags='-arch armv7s -isysroot /Applications/XCode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS7.0.sdk'

以編譯 i386 為例,使用 Xcode 5.0.2 需要進行以下修改,參考此篇
設定路徑至正確的Toolchains. 
export PATH=/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xct‌​oolchain/usr/bin:/Applications/Xcode.app/Contents/Developer/usr/bin:$PATH 
針對 xclang 加入參數 "-miphoneos-version-min=7.0" --extra-cflags='-arch i386 -miphoneos-version-min=7.0' \ --extra-ldflags='-arch i386 -miphoneos-version-min=7.0 -isysroot /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator7.0.sdk' \
14. 若升級至新版 xcode 5.1,可直接使用下列Script,此Script同時還支援 arm64的編譯方式

https://github.com/kewlbear/FFmpeg-iOS-build-script/blob/master/build-ffmpeg.sh


參考資料:
  • 模拟器与真机下ffmpeg的编译方法(总结版
    • http://www.cnblogs.com/rothwell/archive/2012/04/01/2427903.html
  • 使用Xcode4.5 编译运行 iFrameExtractor 
    • http://bashell.sinaapp.com/archives/build-iframeextractor-with-xcode-4_5.html
  • Record RTSP stream with FFmpeg libavformat 
    • http://stackoverflow.com/questions/9251747/record-rtsp-stream-with-ffmpeg-libavformat
  • gas-preprocessor
    • git://github.com/yuvi/gas-preprocessor.git
    • git://github.com/mansr/gas-preprocessor.git
  • http://bbs.csdn.net/topics/390347236