編譯FFmpeg,一個古老的話題,但我仍是介紹一遍,就當記錄。以前介紹怎麼給視頻添加水印時,就已經提到FFmpeg的編譯,而且在編譯時指定了濾鏡的功能。html
可是,在手機盛行的時代,你可能更須要的是能在iOS或Android平臺上運行的FFmpeg,而對於命令行的ffmpeg,你能夠在我的電腦上面使用(由於它簡潔易操做),也能夠在服務程序中使用(安裝FFmpeg後直接調用ffmpeg命令),好比小程常常在本身的mac機上使用ffmpeg命令。android
本文介紹怎樣編譯出iOS或Android平臺使用的FFmpeg連接庫。git
正如編譯macos平臺使用的FFmpeg同樣,編譯iOS或Android平臺使用的FFmpeg,主線也是先configure再make,只不過,有更多的細節須要考慮。github
我使用的是macos系統,如下介紹的就是在mac上交叉編譯,編譯出移動平臺使用的FFmpeg。macos
FFmpeg在編譯時常用到第三方庫(好比x26四、rtmp等),編譯器在查找這些第三方庫的頭文件與庫文件時,須要使用到程序pkg-config。xcode
pkg-conifig給編譯器提供路徑與連接選項。第三方庫在make install時會生成pc後綴的文件並拷貝到系統目錄,而pkg-config就是從這個pc文件讀取出路徑信息。架構
能夠設置PKG_CONFIG_PATH這個環境變量,指定目錄,讓pkg-config到這個目錄下面去找pc文件,若是不設置,則默認在/usr/local/lib/pkgconfig目錄下面查找,好比某個時刻個人pkgconfig目錄下面是這樣的一堆pc文件:
app
這樣安裝pkg-config:工具
brew install pkg-config
安裝pkg-config後,能夠這樣獲取第三方庫的路徑信息:性能
pkg-config --cflags --libs freetype2
如下是對於pkg-config命令的一個載圖:
須要注意,雖然pkg-config查找到的pc文件裏面有記錄到第三方靜態庫的路徑,但實際在編譯FFmpeg靜態庫時,並不會連接上這個第三方庫,並且在FFmpeg的編譯腳本中能夠指定第三方庫的路徑。
此項只在使用濾鏡功能時須要安裝。
若是編譯時遇到這樣的提示:freetype2 not found using pkg-config,那說明尚未安裝freetype,這樣安裝便可:
brew install freetype
此項只在編譯iOS平臺的FFmpeg時才須要。
由於個人mac機已經安裝過xcode,因此clang已經存在。若是你的mac尚未安裝clang的話,那建議把xcode安裝好。
此項只在編譯iOS平臺的FFmpeg時才須要。
x264或FFmpeg等,都有彙編代碼,編譯這些彙編代碼,須要使用更先進的編譯腳原本處理,而mac系統沒有這樣的腳本。
這個腳本是gas-preprocessor.pl。
能夠這樣下載並使用gas-preprocessor.pl:
git clone git://github.com/mansr/gas-preprocessor.git sudo cp -f gas-preprocessor/gas-preprocessor.pl /usr/local/bin/ chmod +x /usr/local/bin/gas-preprocessor.pl
另外一個須要的工具是yasm彙編編譯器,能夠這樣安裝:
brew install yasm
此項只在編譯Android平臺的FFmpeg時才須要。
可使用ndk-r9d版本,或者最新的版本,來編譯FFmpeg,下載地址: https://developer.android.goo...
git clone git://source.ffmpeg.org/ffmpeg.git ffmpeg
沒必要本身重寫了,找開源的項目過來修改一下(注意開源協議)就能夠了,好比參考這個開源項目: https://github.com/yixia/FFmp...
在這個項目裏面,有編譯Android跟iOS平臺的相應腳本,並且有相應的優化處理。在移動平臺使用的庫都很注重兩個東西,一個是性能,另外一個是體積大小。一個好的腳本,既要根據不一樣的硬件類型做編譯上的優化,也要根據軟件需求裁剪FFmpeg的功能使得出來的庫儘量小(畢竟FFmpeg的功能並不是所有都用上)。
小程先介紹一下腳本里面的一些關鍵參數,這些參數並不是平臺通用。
指定指令集:
--extra-cflags='-arch armv7s' --extra-ldflags='-arch armv7s'
指定cpu類型:
--arch=arm --cpu=cortex-a9
注意,應該根據不一樣的指令集使用不一樣的cpu優化;--arch=arm64,像這樣指定具體指令架構也是能夠的。
指定系統:
--target-os=darwin
指定sdk:
--sysroot=/Applications/Xcode.app/.../xxx.sdk
指定編譯器:
--cc=xxx/clang
指定庫生成目錄:
--prefix=build
指定使用的muxer/demuxer/encoder/decoder等:
--enable-muxer=mp4
基本上使用上面介紹的腳本就能夠編譯了,但有時候也能夠做一些修改,好比要加入第三方庫時,或者要對某個指令集做優化時,等等。
小程再提一些注意點,有可能幫你解決編譯過程當中遇到的問題:
--sysroot須要指定。iOS平臺爲....sdk/,不包括usr/inclue;Android平臺是編譯鏈的目錄。 extra-cflags跟extra-ldflags要指定-arch(iOS)或-march(Android)。 在xcode8.3.2(sdk爲10.3)上,armv7/armv7s/arm64不能使用"-mfloat-abi=hard"選項,而且arm64要指定-mcpu=cortex-a53。 在xcode9.2(sdk爲11.2)上,須要--disable-asm。
對於實際項目來講,FFmpeg的編譯是關鍵的一步,應該多花時間去研究一些關鍵的細節--功能、性能跟體積大小都很重要。
運行腳本便可。最終會生成二進制庫,好比iOS通常爲靜態庫(.a文件),而Android通常爲動態庫(.so文件)。
在編譯獲得FFmpeg的連接庫後,就能夠調用它,讓它運行起來。這時,須要寫本身的調用程序。在這裏給出一個簡單的調用示例,而且不作代碼解釋,只是讓有須要的讀者有一個感知。
extern "C" { #include "libavcodec/avcodec.h" #include "libavformat/avformat.h" } void dump_file_format(const char* filepath) { av_register_all(); av_log_set_level(AV_LOG_DEBUG); AVFormatContext* formatContext = avformat_alloc_context(); AVCodecContext* codecContext = NULL; int status = 0; bool success = false; int audioindex = -1; status = avformat_open_input(&formatContext, filepath, NULL, NULL); if (status == 0) { status = avformat_find_stream_info(formatContext, NULL); if (status >= 0) { for (int i = 0; i < formatContext->nb_streams; i ++) { if (formatContext->streams[i]->codec->codec_type == AVMEDIA_TYPE_AUDIO) { audioindex = i; break; } } if (audioindex > -1) { codecContext = formatContext->streams[audioindex]->codec; AVCodec* codec = avcodec_find_decoder(codecContext->codec_id); if (codec) { status = avcodec_open2(codecContext, codec, NULL); if (status == 0) { success = true; } } } } } if (success) { av_dump_format(formatContext, 0, filepath, false); av_log(NULL, AV_LOG_DEBUG, "format and decoder sucessful, and now in decoding each frame\n"); printf("sample_rate=%d, channels=%d\n", codecContext->sample_rate, codecContext->channels); } avformat_free_context(formatContext); } int main(int argc, const char *argv[]) { const char filepath[] = "test2.mp3"; dump_file_format(filepath); return 0; }
好了,總結一下,本文介紹了在macos上,編譯出iOS平臺或Android平臺的FFmpeg的連接庫的過程,涉及到編譯環境的準備、編譯腳本的理解與定製等內容。有緣再見,see you.