1. 程式人生 > >Windows下編譯FFmpeg連結第三方庫libRtmp,生成FFplay

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

/win32libs -DL_ENDIAN -DOPENSSL_NO_HW
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/ 目錄下檢視生成檔案。

PS: 如果沒有別的要求,儘量使用我文章中使用的第三方庫的版本。