Windows下編譯FFmpeg連結第三方庫libRtmp,生成FFplay
PS: 前段時間一直在研究ffmpeg的編譯,網上也是各種方法(其實大部分都只是編譯了FFmpeg),但是能夠連結成功libRtmp並生成FFplay的方法卻很少能行的通。踩了好多坑,記錄下,希望對大家有所幫助。
一、安裝環境準備
1.在windows下需要安裝MinGw環境。直接在https://sourceforge.net/projects/mingw/files/中點選
就行。下載完成之後點選安裝,一路預設即可。直到配置安裝選項這裡,在BasicSetup中全部選中吧(左鍵點選彈出選單)。 然後在All Packages 中選中 Perl,因為我們編譯 openssl 需要Perl環境。
完成之後點選Installation,然後Apply。稍等片刻。完成之後在 C:\MinGW\msys\1.0 下新建home\username 目錄儲存來放我們需要的第三方庫(也可以不放在這裡主要是為了方便)。
二、準備第三方庫
1、librtmp2.3 下載地址 http://rtmpdump.mplayerhq.hu/
下載rtmpdump-2.3.tgz版本,這個版本中有原始碼和Makefile。稍後我們進行編譯,因為librtmp依賴於zlib和openssl,所以要先編譯兩個庫。
2、zlib 1.2.11 下載地址 http://zlib.net/
解壓完成之後執行 C:\MinGW\msys\1.0\ 下的 msys.bat 切換到zlib原始碼目錄。如圖:
然後一次執行:
make -f win32/Makefile.gcc
cp -iv zlib1.dll /mingw/bin
cp -iv zconf.h zlib.h /mingw/include
cp -iv libz.a /mingw/lib
cp win32/Makefile.gcc Makefile.gcc
ffmpeg編譯引數:–enable-zlib
2、OpenSSl1.0.1 下載地址 http://www.openssl.org/
OpenSSL可能需要管理員身份進行解壓不然會報錯。 解壓完成之後切換到OpenSSL原始碼目錄。如圖:
然後
./configure mingw –prefix=pwd
make -j 8
make install
注意: 編譯完成後,把當前目錄的win32libs子資料夾下的include和lib分別拷貝到C:\MinGW\mingw32\下,以供後面librtmp使用
ffmpeg編譯引數:–enable-nonfree –enable libopenssl
make的時候報錯了:
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xdb0): undefined reference to `BN_clear_free'
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xdbc): undefined reference to `BN_clear_free'
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xe03): undefined reference to `BN_num_bits'
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xe31): undefined reference to `RAND_bytes'
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xe4b): undefined reference to `BN_bin2bn'
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xe61): undefined reference to `OPENSSL_cleanse'
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xe83): undefined reference to `SRP_Calc_A'
../libssl.a(tls_srp.o):tls_srp.c:(.text+0xed4): undefined reference to `SRP_check_known_gN_param'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0xe8): undefined reference to `ERR_put_error'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x198): undefined reference to `ERR_put_error'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x1d8): undefined reference to `ERR_put_error'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x358): undefined reference to `ERR_put_error'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x4b8): undefined reference to `ERR_put_error'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x508): more undefined references to `ERR_put_error' follow
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x54c): undefined reference to `OpenSSLDie'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x57c): undefined reference to `OpenSSLDie'
../libssl.a(t1_reneg.o):t1_reneg.c:(.text+0x5e8): undefined reference to `ERR_put_error'
collect2.exe: error: ld returned 1 exit status
make[2]: *** [link_app.] Error 1
make[2]: Leaving directory `/home/guo/openssl-1.0.1/openssl-1.0.1/apps'
make[1]: *** [openssl.exe] Error 2
make[1]: Leaving directory `/home/guo/openssl-1.0.1/openssl-1.0.1/apps'
make: *** [build_apps] Error 1
一大堆未定義的引用錯誤。
解決方法:
1、修改MakeFile,將
build_all: build_libs build_apps build_tests build_tools
修改為:
build_all: build_libs
將
DIRS= crypto ssl engines apps test tools
修改為:
DIRS= crypto ssl engines
2、在mysys命令列中輸入 mingw-get upgrade “w32api<5.0.2” 命令。然後重新編譯即可。
編譯libRtmp
以次輸入:
make SYS=mingw
make SYS=mingw install
編譯FFmpeg
1、下載ffmpeg原始碼, git clone git://source.ffmpeg.org/ffmpeg.git, 可能會比較慢。
2、ffplay顯示需要SDL2,下載SDL2庫(MinGW版本)。
我在編譯的過程中SDl庫一直自動檢測不到,因此手動指定下。將SDL的include目錄下的SDL2目錄和SDL的lib目錄拷貝到C:\MinGW\msys\1.0\local\ 對應的include和lib目錄。
配置FFmpeg:
./configure --enable-static --disable-shared --arch=x86 --target-os=mingw32 --pkg-config=pkg-config --disable-debug --enable-gpl
--enable-zlib --enable-openssl --enable-librtmp --enable-nonfree --extra-ldflags=-L/local/lib --extra-cflags=-I/local/include
--extra-libs='-lwsock32 -lrtmp -lssl -lcrypto -lws2_32 -lgdi32 -lcrypt32 -lm -lz -lpsapi -lwinmm -lSDL2 -lSDL2main' --enable-ffplay
可能會報錯: ERROR: librtmp not found using pkg-config
修改下configure檔案:註釋掉 enabled librtmp (不知道為啥通過pkconfig就是找不到,註釋掉吧)
重新配置,配置時間有點長,完成之後檢視一下ffmpeg原始碼目錄下的ffbuild目錄下的config.mak檔案,檢視配置結果:
!CONFIG_SDL2=yes
...
!CONFIG_FFPLAY=yes
...
CONFIG_LIBRTMP_PROTOCOL=yes
CONFIG_LIBRTMPE_PROTOCOL=yes
CONFIG_LIBRTMPS_PROTOCOL=yes
CONFIG_LIBRTMPT_PROTOCOL=yes
CONFIG_LIBRTMPTE_PROTOCOL=yes
可以看到librtmp找到並配置完成了,但是SDL2找不到,這樣是沒法生成ffplay的。
解決辦法:
官網下載原始碼,自己編譯: https://www.libsdl.org/download-2.0.php
./configure
make -j 8
make install
ps: make install如果儲存找不到bin資料夾,手動擋建立一下。
編譯完成之後將 libSDL2.a libSDL2.dll.a libSDL2main.a 拷貝到C:\MinGW\mingw32\lib下重新配置:
./configure --enable-gpl --enable-version3 --enable-static --disable-shared --arch=x86 --target-os=mingw32 --pkg-conf
ig=pkg-config --disable-debug --enable-gpl --enable-zlib --enable-openssl --enable-librtmp --enable-nonfree --extra-ldf
lags=-L/local/lib --extra-cflags=-I/local/include --extra-libs='-lwsock32 -lrtmp -lssl -lcrypto -lws2_32 -lgdi32 -lcryp
t32 -lm -lz -lpsapi -lwinmm' --enable-ffplay
注意:此時我們不需要手動指定SDL庫了。
之後
make -j 8
又報錯了( ╯□╰ )
ffbuild/common.mak:174: *** missing separator. Stop.
解決辦法:
輸入以下指令
Git config --global core.autocrlf false
git rm --cached -r .
git reset --hard
然後重新配置下,記得註釋掉:
#enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket
configure完成之後 make -j 8
make install
編譯過程過還可能遇到錯誤:
...
In file included from c:\mingw\include\windows.h:80:0,
from libavutil/time.c:33:
c:\mingw\include\winsock2.h:109:8: error: redefinition of 'struct timeval'
struct timeval {
^~~~~~~
In file included from libavutil/time.c:27:0:
c:\mingw\include\sys\time.h:55:8: note: originally defined here
struct timeval
...
解決辦法:
修改ffmpeg原始碼檔案 time.c 包含
#if HAVE_UNISTD_H
#include <unistd.h>
#endif
#if HAVE_WINDOWS_H
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#endif
至此編譯安裝完成。可以在/usr/local/bin/ 目錄下檢視生成檔案。