ffmpeg的交叉編譯
『壹』 Ubuntu 9.10下安裝和使用ffmpeg的詳細過程!
ffmpeg的編譯、安裝及使用(for x86,for arm)
http://hi..com/iminway/blog/item/bda2db4e29ced701b2de05f1.html
最新的ffmpeg可以通過svn下載,SVN輔助的軟體有:
SubVersion,從 http://subversion.tigris.org/ 下載,支持linux。
TortoiseSVN,從 http://tortoisesvn.tigris.org/ 下載,是很不錯的SVN客戶端程序,為windows外殼程序集成到windows資源管理器和文件管理系統的Subversion客戶端,用起來很方便。
http://subversion.tigris.org/downloads/subversion-1.3.2.tar.gz
tar zvxf subversion-1.3.2.tar.gz
cd subversion-1.3.2
./configure --with-apr=/usr/local/apr-httpd --with-apr-util=/usr/local/apr-util-httpd/
make
make install
如果安裝了FC6,它已經帶了svn,不用裝了。
ffmpeg的下載:我們就可以通過svn命令獲取最新的ffmpeg,命令如下:
svn checkout svn://svn.mplayerhq.hu/ffmpeg/trunk ffmpeg
xvid的獲取地址如下:
http://www.xvid.org/
wget http://downloads.xvid.org/downloads/xvidcore-1.1.3.tar.gz
配置編譯
for x86
#./configure --prefix=/usr/local
#make
#make install
for arm
#CC=arm-linux-gcc ./configure --prefix=/usr/local/arm/arm-linux --build=i686-pc-linux --host=arm-linux --target=arm-linux
#make
#make install
x264的獲取地址如下:
svn co svn://svn.videolan.org/x264/trunk x264
配置編譯
for x86
#./configure --enable-shared --prefix=/usr/local
#make
#make install
for arm
#CC=arm-linux-gcc ./configure --enable-pthread --enable-shared --host=arm-linux
#make install
lame的獲取地址如下: http://lame.sourceforge.net/index.php
配置編譯
for x86
./configure --enable-shared --prefix=/usr/local
libdts編譯參數
./configure --prefix=/usr
make
make install
http://www.audiocoding.com/moles/mydownloads/,http://prdownloads.sourceforge.net/faac
FAAD2的編譯
cd faad2
autoreconf -vif
./configure --prefix=/usr --with-mp4v2 --enable-shared
make
make install
faac的編譯
cd faac
chmod +x bootstrap
./bootstrap
./configure --prefix=/usr --with-mp4v2 --enable-shared
make
make install
在編譯ffmpeg,在configure時加上--enable-amr_nb --enable-faad --enable-faac參數。
編譯的時候加上--enable-amr_nb --enable-amr_wb參數就行,根據編譯系統的提示,所以我們得下載一些編譯3gp所需得文件。
源碼網址:http://www.3gpp.org/ftp/Specs
wget http://www.3gpp.org/ftp/Specs/archive/26_series/26.204/26204-510.zip
解壓以後把裡面的文件都拷貝到libavcodec/amrwb_float
wget http://www.3gpp.org/ftp/Specs/archive/26_series/26.104/26104-510.zip
解壓以後把裡面的文件都拷貝到libavcodec/amr_float
微軟ASF格式的三個版本,WMV1,WMV2,WMV3分別對應MediaPlayer的版本7,8和9,所以很多時候會稱VC1為WMV3或 WMV9,都是它了,有時候在代碼里,也能看到稱呼它為VC9的。因為微軟還沒有正式公開這種格式,所以當前對VC1的支持還很不完善。本文基本是根據 Multimedia Mike的一篇博客翻譯和完善而來。
(1) 首先要下載 SMPTE VC-1 reference decoder,這個組織是要收費的,可以從這里下載免費的。
(2) 在ffmpeg目錄下的libavcodec目錄下面,建立目錄libvc1。
(3) 將VC1_reference_decoder_release6/decoder/目錄中的*.c和*.h文件全部到libvc1目錄下。
(4) 將VC1_reference_decoder_release6/shared/目錄中的*.c和*.h文件全部到libvc1目錄下。
(5) 將 libvc1-makefile.txt放到libvc1下的Makefile文件。
(6) 將smpte-vc1.c文件放到libavcodec目錄下。
(7) 修改libavcodec目錄下的vc9.c,將文件最後的wmv3_decoder這個AVCodec的structure,用#if 0和#endif包含起來,也就是使它失效了。
(8) 修改libavcodec目錄下的allcodecs.c,將register_avcodec(&wmv3_decoder)上下的注釋去掉,使它發揮作用。
(9) 修改libavcodec目錄下的Makefile,把OBJS的列表中加入smpte-vc1.o。
(10)修改ffmpeg主目錄下的Makefile文件,把-L./libavcodec/libvc1 -lvc1$(BUILDSUF)加入到FFLIBS後面。
(11) 進入ffmpeg/libavcodec/libav1,執行make
(12) 到ffmpeg主目錄下,執行config;make;make install。config時根據實際情況帶參數。
採用ffmpeg轉碼製作FLV文件,和轉碼成其它媒體類型的重要差別是一定要有lame庫支持,因為FLV的聲音編碼採用mp3格式,非lame這個東 東不行。編譯ffmpeg中加入lame庫真是一場災難,特別在windows下,很多參數都不能發揮作用,最後直接手工和改一些文件,記錄如 下:
(1) 如果在Windows下編譯,第一步當然是下載MinGW和MSYS來裝上了。到http://mingw.sourceforge.net/去下載最新版的MinGW-5.0.2.exe和MSYS-1.0.11-2004.04.30-1.exe。
(2) 先安裝MinGW,直接運行MinGW-5.0.2.exe安裝,選擇目錄,譬如選擇D:\MinGW為安裝目錄。安裝時需要選擇gcc和make模塊,安裝文件本身很小,會從網上下載模塊來安裝。
(3) 然後安裝MSYS,也是直接運行MSYS-1.0.11-2004.04.30-1.exe安裝。安裝目錄一般選擇D:\MinGW\bin \1.0。,安裝過程會詢問剛才安裝MinGW的目錄,輸入D:\MinGW,其它都回答'Y'就搞定了。如果不清楚,可以看這個圖片效果。
(4) 運行MSYS,桌面上有個圖標,雙擊就運行了,運行結果是一個模擬unix的命令窗口,後面的編譯都在這種狀態下進行。前面4步在linux不需要。
(5) 到http://lame.sourceforge.net/去下載最新版的lame-3.97b2.tar.gz,到你認為合適的地方,解壓後進入lame解壓出來的目錄中。執行
./configure --prefix=PREFIX
make
make install
(6) 就把編譯出來的include下的lame目錄到/usr/include目錄下,把lib下的幾個庫文件都到/usr/lib目錄 下。這里注意有個變化,如果只 lib目錄下的靜態庫到/usr/lib下,就是只 libmp3lame.a文件,編譯出來的ffmpeg最終就不會對libmp3lame的動態庫有依賴關系,這是因為編譯首先找動態庫,動態庫沒有才找 靜態庫。如果不做這個,後面編譯ffmpeg時無論如何指定參數,都會報錯LAME not found,不知道是哪裡的bug。
(7) 從http://ffmpeg.mplayerhq.hu/取得最新的ffmpeg,現在自由軟體都大量採用SVN了,要先裝一個SVN,可以去http://tortoisesvn.tigris.org/下載windows版的SVN,去http://subversion.tigris.org/下載linux版的SVN。SVN如何編譯安裝這里就省略了。
(8) 如果在windows下,打開解壓後的ffmpeg目錄下的Makefile文件,在FFLIBS的那一行後面加上-lmp3lame$(BUILDSUF)。這個也不知道是哪個bug引起的,搞了好長時間才搞出來,郁悶。Linux下不用這樣。
#./configure --prefix=/usr --enable-gpl --enable-shared --enable-mp3lame --enable-amr_nb --enable-amr_wb --enable-amr_if2 --enable-libogg --enable-vorbis --enable-xvid --enable-a52 --enable-a52bin --enable-faadbin --enable-dts --enable-pp --enable-faad --enable-faac --enable-x264 --enable-pthreads --disable-ffserver --disable-ffplay
make
make install
http://www.3gpp.org/ftp/Specs/archive/26_series/26.073/26073-510.zip
解壓以後把裡面的文件都拷貝到libavcodec/amr目錄下
make
make install
#./configure --prefix=./install --disable-shared --enable-pthreads --enable-libx264 --enable-libxvid --arch=i686 --enable-gpl
#make
#make install
配置編譯
#./configure --prefix=/home/zht/redhatzht/sources/image-colletct/ffmpeg/install --enable-static --disable-shared --enable-libx264 --enable-libxvid --cross-compile --cc=arm-linux-gcc --arch=arm --enable-gpl --disable-strip --disable-network --disable-ipv6 --disable-vhook --disable-audio-beos --disable-audio-oss --disable-mpegaudio-hp --enable-pthreads --enable-small --disable-parsers --disable-debug
#make
#make install
x86上的ldconfig不能在arm上運行,arm上的ldconfig工具是在建立交叉編譯器時,編譯glibc是產生的,可以拷貝到arm-linux中。
(4) 本文大部分內容來自網路,其中xvid,x264的庫,我親手安裝過,ffmpeg的配置編譯for x86的簡易配置,for arm,我親手配置編譯過,並在x86,arm上可用,編譯配置都是採用靜態庫。
ffmpeg作為媒體文件處理軟體,基本用法如下:
ffmpeg -i INPUTfile [OPTI
文章出處:DIY部落(http://www.diybl.com/course/6_system/linux/Linuxjs/20091024/180077.html)
『貳』 請教如何使用cygwin編譯ffmpeg靜態庫
如何使用ndk為ffmpeg編譯rtmp+polarssl靜態庫?這個問題花了我整整一天時間。其中遇到很多小問題,這里記錄一下,方便自己也方便其他人。
1、編譯polarssl,查看其Readme文件即可,不需要configure,只需要make時帶上必要的參數即可,不過要記得在每一次執行make命令時都帶上CC的參數(指向你的arm gcc),因為我試過在make install時沒有帶上CC的參數,雖然能編譯出polarssl但是未能正確被rtmp引用到。
2、因為前面我用的polarssl是當前最新(1.3.7)版本,而librtmp使用的好像是polarssl1.0.0以下版本的api,所以需要修改rtmp部分源碼,讓其調用新版polarssl的api,這里的修改可以參照《Migrating from PolarSSL-1.2 to the PolarSSL 1.3 branch》和《[rtmpmp] branch master updated. a312ac7 Fix compat with PolarSSL >= 1.1.0》。
3、出現 undefined reference to `havege_random』錯誤,這里是因為polarssl默認關閉了havege模塊,需要你手動開啟,主要就是修改include/polarssl/config.h,去掉POLARSSL_HAVEGE_C前的注釋,也就是要定義POLARSSL_HAVEGE_C,如下:
#define POLARSSL_HAVEGE_C
4、在編譯出上面兩個庫之後,可以開始編譯ffmpeg(2.1.1版本)了,如果遇到下面的問題 check_pkg_config librtmp librtmp/rtmp.h RTMP_Socket
ERROR: librtmp not found
這里有三種解決方法:
第一種,因為是網路上傳播最多的,算是比較簡便的方法,就是修改ffmpeg的configure,將以下一行:
enabled librtmp && require_pkg_config librtmp librtmp/rtmp.h RTMP_Socket
改為:
enabled librtmp && require librtmp librtmp/rtmp.h RTMP_Socket -lrtmp -lpolarssl -lz
或者直接注釋掉&& *** 部分,然後再自己加上librtmp的庫路徑也行
第二種,(比較推薦,因為解決了這個會順帶解決大部分找不到庫的錯誤!)因為這里使用了pkg-config工具查找庫,而這個工具ndk並沒有附帶提供,而出現check_pkg_config相關錯誤的話,只要稍加註意,會發現在使用configure配置ffmpeg的交叉編譯時,已經有相應的pkg-config不存在的警告了。我對這個工具不熟悉,所以我只是簡單地加上了一個軟鏈接到系統的pkg-config,如下:
ln -s /usr/bin/pkg-config /home/cidy0106/android-ndk-r9d/toolchains/arm-linux-androideabi-4.8/prebuilt/linux-x86_64/bin/arm-linux-androideabi-pkg-config
這個時候重新configure的話可能會出現找不到polarssl庫的錯誤提示,需要修改一下librtmp安裝目錄里的librtmp.pc,把以下內容:
Libs: -L${libdir} -lrtmp -lz
改為:
Libs: -L${libdir} -lrtmp -lz -lpolarssl
至此,就可以正確編譯出ffmpeg了
『叄』 如何把ffmpeg編譯進motion
ffmpeg編譯
首先解壓ffmpeg-0.5.1.tar.bz2,,執行configure命令如下:
[plain] view plain
./configure --cc=arm-linux-gnueabihf-gcc --host-cc=arm-linux-gnueabihf --prefix=/home/***/iWork/common/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux --enable-cross-compile --arch=arm --disable-yasm
編譯:
[plain] view plain
make
出現錯誤如下:
[plain] view plain
arm-linux-gnueabihf-gcc -DHAVE_AV_CONFIG_H -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE -I. -I"/home/***/iWork/lamobo/motion-3.2.12-arm-project/ffmpeg-0.5.1"
-D_ISOC99_SOURCE -D_POSIX_C_SOURCE=200112 -std=c99 -fomit-frame-pointer -g -Wdeclaration-after-statement -Wall -Wno-switch -Wdisabled-optimization
-Wpointer-arith -Wrendant-decls -Wno-pointer-sign -Wcast-qual -Wwrite-strings -Wtype-limits -Wundef -O3 -fno-math-errno -fno-signed-zeros -c -o
libavcodec/dsputil.o libavcodec/dsputil.c
/tmp/ccOmDdh7.s: Assembler messages:
/tmp/ccOmDdh7.s:51789: Error: thumb conditional instruction should be in IT block -- `movgt fp,r9'
/tmp/ccOmDdh7.s:51790: Error: thumb conditional instruction should be in IT block -- `movgt r9,r8'
/tmp/ccOmDdh7.s:51792: Error: thumb conditional instruction should be in IT block -- `movle r9,r7'
/tmp/ccOmDdh7.s:51794: Error: thumb conditional instruction should be in IT block -- `movgt fp,r9'
/tmp/ccOmDdh7.s:51889: Error: thumb conditional instruction should be in IT block -- `movgt r9,r8'
/tmp/ccOmDdh7.s:51890: Error: thumb conditional instruction should be in IT block -- `movgt r8,ip'
/tmp/ccOmDdh7.s:51892: Error: thumb conditional instruction should be in IT block -- `movle r8,r6'
/tmp/ccOmDdh7.s:51894: Error: thumb conditional instruction should be in IT block -- `movgt r9,r8'
make: *** [libavcodec/dsputil.o] Error 1
這需要修改~/ffmpeg-0.5.1/config.mak,在OPTFLAGS(line:16)選項中添加:
[plain] view plain
-Wa,-mimplicit-it=thumb
加入這句的意思是在使用Thumb ISA指令編譯時自動產生「IT」指令。 繼續編譯,又報錯:
[plain] view plain
strip: Unable to recognise the format of the input file `ffmpeg'
這是strip沒有使用交叉編譯的版本所致,由於此時我們需要的庫文件已經編成,所以這個錯誤可以忽略不計,修改config.mak中的strip為arm-linux-gnueabihf-strip,繼續讓編譯完成
motion編譯
motion中的ffmpeg.c是對ffmpeg api的封裝,向其他模塊提供功能。如在主程序文件motion.c中
[cpp] view plain
//......
#ifdef HAVE_FFMPEG
/* FFMpeg initialization is only performed if FFMpeg support was found
* and not disabled ring the configure phase.
*/
ffmpeg_init();
#endif /* HAVE_FFMPEG */
//......
這里ffmpeg_init就是ffmpeg.c中封裝的方法:
[cpp] view plain
void ffmpeg_init()
{
motion_log(LOG_INFO, 0, "ffmpeg LIBAVCODEC_BUILD %d LIBAVFORMAT_BUILD %d", LIBAVCODEC_BUILD, LIBAVFORMAT_BUILD);
av_register_all();
#if LIBAVCODEC_BUILD > 4680
av_log_set_callback( (void *)ffmpeg_avcodec_log );
#endif
/* Copy the functions to use for the append file protocol from the standard
* file protocol.
*/
mpeg1_file_protocol.url_read = file_protocol.url_read;
mpeg1_file_protocol.url_write = file_protocol.url_write;
mpeg1_file_protocol.url_seek = file_protocol.url_seek;
mpeg1_file_protocol.url_close = file_protocol.url_close;
/* Register the append file protocol. */
#if LIBAVFORMAT_BUILD >= (52<<16 | 31<<8)
av_register_protocol(&mpeg1_file_protocol);
#else
register_protocol(&mpeg1_file_protocol);
#endif
}
我們需要在motion的Makefile中加入對ffmpeg模塊的編譯,並且打開HAVE_FFMPEG等開關。首先執行configure如下:
[plain] view plain
./configure CC=arm-linux-gnueabihf-gcc --host=arm-linux-gnueabihf --prefix=/home/stewart/iWork/common/gcc-linaro-arm-linux-gnueabihf-4.8-2013.10_linux
生成Makefile,在OBJ選項中添加ffmpeg.o:
[plain] view plain
OBJ = ffmpeg.o motion.o conf.o draw.o jpegutils.o $(VIDEO_OBJ) netcam.o \
netcam_ftp.o netcam_jpeg.o netcam_wget.o track.o \
alg.o event.o picture.o rotate.o webhttpd.o \
webcam.o
在CFLAGS選項中添加-DHAVE_FFMPEG -DFFMPEG_NEW_INCLUDES -DHAVE_FFMPEG_NEW的定義,加入libjpeg頭文件搜索目錄
[plain] view plain
libdir = ${prefix}/lib
incdir = ${prefix}/include
[plain] view plain
CFLAGS = -g -O2 -DHAVE_FFMPEG -DFFMPEG_NEW_INCLUDES -DHAVE_FFMPEG_NEW -D_REENTRANT
-DMOTION_V4L2 -DMOTION_V4L2_OLD -DTYPE_32BIT="int" -DHAVE_BSWAP -Wall
-DVERSION=\"3.2.12\" -Dsysconfdir=\"$( sysconfdir)\"
在LIBS中加入對ffmpeg庫的支持:
[plain] view plain
LIBS = -L${libdir} -static -lavformat -lavcodec -lavutil -ljpeg -lm -lpthread
預備工作完成,make,編譯報錯:
[plain] view plain
motion.h:44:28: fatal error: linux/videodev.h: No such file or directory
compilation terminated.
由於linux-2.4以上的內核已經取消了videodev.h文件,需要安裝libv4l-dev,然後將motion.h,video.h中的
[plain] view plain
#include <linux/videodev.h>
修改為
[cpp] view plain
#include <libv4l1-videodev.h>
繼續,又報錯:
[plain] view plain
track.c: In function 『uvc_center』:
track.c:587:29: error: storage size of 『control_s』 isn』t known
track.c:589:24: error: 『V4L2_CID_PRIVATE_BASE』 undeclared (first use in this function)
track.c:589:24: note: each undeclared identifier is reported only once for each function it appears in
track.c:592:24: error: 『VIDIOC_S_CTRL』 undeclared (first use in this function)
track.c:601:31: error: storage size of 『queryctrl』 isn』t known
track.c:605:24: error: 『VIDIOC_QUERYCTRL』 undeclared (first use in this function)
track.c:601:31: warning: unused variable 『queryctrl』 [-Wunused-variable]
track.c:587:29: warning: unused variable 『control_s』 [-Wunused-variable]
track.c:636:25: error: storage size of 『control_s』 isn』t known
track.c:636:25: warning: unused variable 『control_s』 [-Wunused-variable]
track.c: In function 『uvc_move』:
track.c:724:29: error: storage size of 『control_s』 isn』t known
track.c:726:24: error: 『V4L2_CID_PRIVATE_BASE』 undeclared (first use in this function)
track.c:729:24: error: 『VIDIOC_S_CTRL』 undeclared (first use in this function)
track.c:724:29: warning: unused variable 『control_s』 [-Wunused-variable]
track.c:779:25: error: storage size of 『control_s』 isn』t known
track.c:779:25: warning: unused variable 『control_s』 [-Wunused-variable]
make: *** [track.o] Error 1
在track.c中添加:
[plain] view plain
#include <linux/videodev2.h>
繼續,報錯(怎麼還有啊?):
[plain] view plain
gcc -L/usr/local/lib -o motion motion.o conf.o draw.o jpegutils.o video.o video2.o video_common.o netcam.o netcam_ftp.o netcam_jpeg.o netcam_wget.o track.o alg.o event.o picture.o rotate.o webhttpd.o webcam.o ffmpeg.o -lm -lpthread -ljpeg -L/usr/local/lib -lavformat -lavcodec -lavutil -lm -lz
/usr/local/lib/libavformat.a(file.o):(.data+0x60): multiple definition of `file_protocol'
ffmpeg.o:(.data+0x0): first defined here
collect2: ld returned 1 exit status
原來結構體file_protocol在libavformat.a和ffmpeg.o中重復定義了,分別打開兩個定義:
[cpp] view plain
//libavformat/file.c:85
URLProtocol file_protocol = {
"file",
file_open,
file_read,
file_write,
file_seek,
file_close,
};
[cpp] view plain
//ffmpeg.c
URLProtocol file_protocol = {
"file",
file_open,
file_read,
file_write,
file_seek,
file_close,
#if LIBAVFORMAT_BUILD >= (52<<16 | 31<<8)
NULL,
NULL,
NULL,
#endif
};
將libavformat/file.c中的file_protocol定義注掉,重新編譯一份libavformat.a。然後繼續編譯motion,又報錯:
[plain] view plain
/home/xxx/iWork/Thrid_party/ffmpeg-0.5.1/libavformat/matroskadec.c:917: undefined reference to `BZ2_bzDecompressInit'
/home/xxx/iWork/Thrid_party/ffmpeg-0.5.1/libavformat/matroskadec.c:926: undefined reference to `BZ2_bzDecompress'
/home/xxx/iWork/Thrid_party/ffmpeg-0.5.1/libavformat/matroskadec.c:929: undefined reference to `BZ2_bzDecompressEnd'
這個需要libbz2庫,下載地址http://www.bzip.org/downloads.html
編譯安裝libbz2後將-lbz2加入motion的Makefile的LIBS選項:
[plain] view plain
LIBS = -lpthread -ljpeg -L/usr/lib -lavformat -lavcodec -lavutil -lm -lz -lbz2
『肆』 在linux下用bfin-uclinux-gcc交叉編譯ffmpeg報錯,是什麼問題
這個是抱怨沒有main函數的意思
如果你要編譯共享庫,請確認使用了正確的編譯選項
如果要編譯可執行程序,請提供main函數。
『伍』 如何用Android NDK編譯FFmpeg
android的NDK開發需要在linux下進行:
因為需要把C/C++編寫的代碼生成能在arm上運行的.so文件,這就需要用到交叉編譯環境,而交叉編譯需要在linux系統下才能完成。
安裝android-ndk開發包,這個開發包可以在google android 官網下載: 通過這個開發包的工具才能將android jni 的C/C++的代碼編譯成庫
android應用程序開發環境: 包括eclipse、java、 android sdk、 adt等。
NDK編譯步驟:
a.選擇ndk自帶的例子hello-jni,我的位於E:android-ndk-r5sampleshello-jni(根據具體的安裝位置而定) 。
b.運行cygwin,輸入命令cd /cygdrive/e/android-ndk-r5/samples/hello-jni,進入到E:android-ndk-r5sampleshello-jni目錄。
c.輸入$NDK/ndk-build,執行成功後,它會自動生成一個libs目錄,把編譯生成的.so文件放在裡面。($NDK是調用我們之前配置好的環境變數,ndk-build是調用ndk的編譯程序)
d.此時去hello-jni的libs目錄下看有沒有生成的.so文件,如果有,ndk就運行正常啦。
『陸』 ffmpeg交叉編譯android,rtsp協議sdp流播放問題
pthread support is required
這個問題是交叉編譯的時候你沒開啟pthread
也就是編譯時加上
--enable-pthread
第二個問題不是問題是個警告或者提示
字面意思就是:從bitrate估算,可能不準確
『柒』 如何用Android NDK編譯FFmpeg
一、安裝cygwin、配置ndk和下載ffmpeg源碼
這步就不說了,網上很多教程,再次聲明本教程只針對ndk R4這個版本。需要說明的是,本人在cygwin安裝路徑下的.bash_profile文件中指定的NDK路徑如下所示。因為本人裝了好幾個NDK,因此後面的R4隻是個標示。
NDK_R4=/cygdrive/d/android-ndk-r4
export NDK_R4
二、編譯前准備和編譯
1、因為R4這個NDK比較舊,交叉編譯的時候需要在一個Android環境中,那簡單,創建一個Android空項目,把整個項目拷出來,在項目下建立一個文件夾jni,把ffmpeg0.6.6的源碼拷進去。左圖,HelloJni就是我新建的一個項目,Android.mk這時候你還沒有,先不用管。右圖ffmpeg-0.6.6文件夾的內容要跟我一樣,直接就是代碼。我這里的ffmpeg_cywin這個文件夾是隨便建的,放哪裡無所謂的。
2、在ffmpeg-0.6.6下建立一個文件config.sh,內容如下所示。需要注意的是,unix下的換行符和windows下是不一樣,如果直接拷貝到windows下的記事本,後面執行這個config.sh的時候會出問題,這里我用的是notepad++編輯的,在編輯->檔案格式轉換->轉換為UNIX格式。(注意,後面的所有的Android.mk的編輯都有此要求)。
簡單說一下這個config.sh,PREBUILT和PLATFORM根據你安裝ndk的位置而不同,config.sh其實是一個腳本,執行這個腳本的時候又調用了另外一個腳本configure,configure主要是根據編譯選項(下面enable disable那些),生成相應的編譯配置,就是說你想要編譯ffmpeg什麼模塊就自己定製編譯選項的內容。基本上這個文件只要修改一下PREBUILT和PLATFORM就行,其他都不用改。
#!/bin/bash
export PREBUILT=D://android-ndk-r4/build/prebuilt/windows/arm-eabi-4.4.0
export PLATFORM=D://android-ndk-r4/build/platforms/android-8/arch-arm
./configure --target-os=linux \
--arch=arm \
--enable-version3 \
--enable-gpl \
--enable-nonfree \
--disable-stripping \
--disable-ffmpeg \
--disable-ffplay \
--disable-ffserver \
--disable-ffprobe \
--disable-encoders \
--disable-muxers \
--disable-devices \
--disable-protocols \
--enable-protocol=file \
--enable-avfilter \
--disable-network \
--disable-mpegaudio-hp \
--disable-avdevice \
--enable-cross-compile \
--cc=$PREBUILT/bin/arm-eabi-gcc \
--cross-prefix=$PREBUILT/bin/arm-eabi- \
--nm=$PREBUILT/bin/arm-eabi-nm \
--extra-cflags="-fPIC -DANDROID" \
--disable-asm \
--enable-neon \
--enable-armv5te \
--extra-ldflags="-Wl,-T,$PREBUILT/arm-eabi/lib/ldscripts/armelf.x -Wl,-rpath-link=$PLATFORM/usr/lib -L$PLATFORM/usr/lib -nostdlib $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtbegin.o $PREBUILT/lib/gcc/arm-eabi/4.4.0/crtend.o -lc -lm -ldl"
3、修改configure文件,找到下圖的內容,修改成我這樣,這個是用來存放執行腳本過程的臨時文件的,我這里用的是D://NDK,你可以設置其他地方,但是要先創建好這個文件夾,放哪裡無所謂的。
4、然後在cywin中進入ffmpeg0.6.6文件夾,執行chmod -x config.sh,然後執行./config,此過程需要一定的時間。如果這一步出現問題,很有可能是你config.sh中的PREBUILT和PLATFORM的路徑設置不對,或者是你拷貝內容到config.sh的時候沒有在UNIX格式下。執行完如下圖所示。
5、在ffmpeg-0.6.6下會生成一個config.h文件,編輯它,找到#define restrict restrict這一行,把它改成#define restrict
6、在libavutil/libm.h下,把所有static的方法注釋掉或者直接刪掉。
7、修改libavcodec,libavfilter,libavformat,libavutil,libpostproc和libswscale目錄的MakeFile文件,每個文件中,刪除語句
include $( SUBDIR ) ../config.mak 和 include $ (SUBDIR) .. / subdir.mak。
libavcodec下的makefile中搜索inverse.o,把它所在的那一行刪掉,要不編譯的時候會沖突。
8、在ffmpeg-0.6.6文件夾下,創建av.mk文件(UNIX格式),內容如下:
#LOCAL_PATH is one of libavutil, libavcodec, libavformat, or libswscale
#include $(LOCAL_PATH)/../config-$(TARGET_ARCH).mak
include $(LOCAL_PATH)/../config.mak
OBJS :=
OBJS-yes :=
MMX-OBJS-yes :=
include $(LOCAL_PATH)/Makefile
# collect objects
OBJS-$(HAVE_MMX) += $(MMX-OBJS-yes)
OBJS += $(OBJS-yes)
FFNAME := lib$(NAME)
FFLIBS := $(foreach,NAME,$(FFLIBS),lib$(NAME))
FFCFLAGS = -DHAVE_AV_CONFIG_H -Wno-sign-compare -Wno-switch -Wno-pointer-sign
FFCFLAGS += -DTARGET_CONFIG=\"config-$(TARGET_ARCH).h\"
ALL_S_FILES := $(wildcard $(LOCAL_PATH)/$(TARGET_ARCH)/*.S)
ALL_S_FILES := $(addprefix $(TARGET_ARCH)/, $(notdir $(ALL_S_FILES)))
ifneq ($(ALL_S_FILES),)
ALL_S_OBJS := $(patsubst %.S,%.o,$(ALL_S_FILES))
C_OBJS := $(filter-out $(ALL_S_OBJS),$(OBJS))
S_OBJS := $(filter $(ALL_S_OBJS),$(OBJS))
else
C_OBJS := $(OBJS)
S_OBJS :=
endif
C_FILES := $(patsubst %.o,%.c,$(C_OBJS))
S_FILES := $(patsubst %.o,%.S,$(S_OBJS))
FFFILES := $(sort $(S_FILES)) $(sort $(C_FILES))
9、在jni文件夾下,創建Android.mk(UNIX格式),內容如下:
include $(all-subdir-makefiles)
10、在ffmpeg-0.6.6文件夾下,創建Android.mk,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_STATIC_LIBRARIES := libavformat libavcodec libavutil libpostproc libswscale
LOCAL_MODULE := ffmpeg
include $(BUILD_SHARED_LIBRARY)
include $(call all-makefiles-under,$(LOCAL_PATH))
11、在ffmpeg-0.6.6\libavformat下,創建Android.mk,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_CFLAGS += -include "string.h" -Dipv6mr_interface=ipv6mr_ifindex
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
12、在ffmpeg-0.6.6\libavcodec下,創建Android.mk,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_LDLIBS := -lz
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
13、在ffmpeg-0.6.6\libavfilter、libavutil、libpostproc和libswscale下,創建Android.mk,內容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include $(LOCAL_PATH)/../av.mk
LOCAL_SRC_FILES := $(FFFILES)
LOCAL_C_INCLUDES := \
$(LOCAL_PATH) \
$(LOCAL_PATH)/..
LOCAL_CFLAGS += $(FFCFLAGS)
LOCAL_STATIC_LIBRARIES := $(FFLIBS)
LOCAL_MODULE := $(FFNAME)
include $(BUILD_STATIC_LIBRARY)
14、然後在jni目錄下,運行$NDK_R4/ndk-build -B,這里的命令需要根據你自己的情況修改,然後就開始編譯了。過程需要10來分鍾,成功之後,會在libs下生產libffmpeg.so。如果編譯出來的libffmpeg.so只有1.5k,得如下修改一下NDK,再重新編譯。
把下面紅色部分加到NDK的build/core/build-binary.mk里:
LOCAL_STATIC_LIBRARIES := $(call strip-lib-prefix,$(LOCAL_STATIC_LIBRARIES))
LOCAL_STATIC_WHOLE_LIBRARIES := $(call strip-lib-prefix,$(LOCAL_STATIC_WHOLE_LIBRARIES))
...
static_libraries := $(call map,static-library-path,$(LOCAL_STATIC_LIBRARIES))
static_whole_libraries := $(call map,static-library-path,$(LOCAL_STATIC_WHOLE_LIBRARIES))
...
$(call mole-add-static-depends,$(LOCAL_MODULE),$(LOCAL_STATIC_LIBRARIES))
$(call mole-add-static-depends,$(LOCAL_MODULE),$(LOCAL_STATIC_WHOLE_LIBRARIES))
...
$(LOCAL_BUILT_MODULE): $(static_libraries) $(static_whole_libraries) $(shared_libraries)
...
$(LOCAL_BUILT_MODULE): PRIVATE_STATIC_LIBRARIES := $(static_libraries)
$(LOCAL_BUILT_MODULE): PRIVATE_WHOLE_STATIC_LIBRARIES := $(static_whole_libraries)
接著再將最外層ffmpeg/Android.mk裡面的LOCAL_STATIC_LIBRARIES改成LOCAL_STATIC_WHOLE_LIBRARIES