天天看點

Windows編譯和使用ffmpeg

作者:音視訊流媒體技術

一、ffmpeg編譯選項說明

ffmpeg是一套可以用來記錄、轉換數字音頻、視訊,并能将其轉化為流的開源計算機程式。其實 ffmpeg 隻是對該架構的通俗稱呼,該架構本質上為 libav,ffmpeg 也隻是基于 libav 開發的一套工具。libav 架構可以編譯在其他平台進行使用,在下載下傳的源碼中,包含有 configure 程式來進行編譯工作,但是單純的運作該程式進行編譯,編譯生成的包體積是非常大的,是以需要進行一些配置來減小編譯包的大小。

1、增加編譯選項

首先可以增加一些正常編譯選項來減小最終編譯包的大小。可以使用 ./configure -h 指令來列出 configure 程式支援的編譯選項,每一項編譯選項後都有對應的解釋,其中能夠直接減小編譯包大小的指令有如下幾個:

--enable-small: 使用編譯速度來換取編譯包大小
--disable-runtime-cpudetect: 禁止運作時檢測CPU性能,可以編出較小的包
--disable-doc: 禁止編譯文檔,可以避免将文檔編譯入包中
--disable-htmlpages: 禁止編譯html文檔,可以避免将文檔編譯入包中
--disable-manpages: 禁止編譯man文檔,可以避免将文檔編譯入包中
--disable-podpages: 禁止編譯pod文檔,可以避免将文檔編譯入包中
--disable-txtpages: 禁止編譯txt文檔,可以避免将文檔編譯入包中
           

2、減少不必要的工具

最開始介紹了 ffmpeg 是基于 libav 開發的一套工具,除了 ffmpeg 之外,基于 libav 開發的工具還有:ffplay、ffprobe以及ffserver。這些不必要的工具是可以禁止掉的,相關選項為:

--disable-programs: 禁止編譯指令行工具
--disable-ffmpeg: 禁止編譯ffmpeg工具
--disable-ffplay: 禁止編譯ffplay工具
--disable-ffprobe: 禁止編譯ffprobe工具
--disable-ffserver: 禁止編譯ffserver工具
           

3、減少不必要的子產品

libav 包含以下幾個子產品:(1)libavdevice,該子產品主要負責與硬體裝置的互動,若無需該子產品,可使用 --disable-avdevice 禁止編譯;(2)libavcodec,該子產品主要負責解碼與編碼,若無需該子產品,可使用 --disable-avcodec 禁止編譯,不過該子產品為 libav 核心子產品,非特殊情況最好不要禁止;(3)libavformat,該子產品主要負責解封裝與封裝,若無需該子產品,可使用 --disable-avformat 禁止編譯,不過該子產品為 libav 核心子產品,非特殊情況最好不要禁止;(4)libswresample,該子產品主要負責對原始音頻資料進行格式轉換,若無需該子產品,可使用 --disable-swresample 禁止編譯;(5)libswscale,該子產品主要負責對原始視訊資料進行場景轉換、色彩映射以及格式轉換,若無需該子產品,可使用 --disable-swscale 禁止編譯;(6)libpostproc,該子產品主要負責對音視訊進行後期處理,若無需該子產品,可使用 --disable-postproc 禁止編譯;(7)libavfilter,該子產品主要負責音視訊的過濾,包括裁剪、位置、水印等,若無需該子產品,可使用 --disable-avfilter 禁止編譯;(8)libavresample,該子產品主要負責音視訊封裝編解碼格式預設,該子產品預設不編譯,若要進行編譯,使用 --enable-avresample。

4、減少不必要裝置的編譯

libav 可以從硬體裝置中擷取輸入,同時也可以輸出至硬體裝置。可以指定支援的輸入輸出裝置來避免不必要的編譯:

--disable-devices: 禁止所有裝置的編譯
--disable-indevs: 禁止所有輸入裝置的編譯
--disable-indev=NAME: 禁止特定輸入裝置的編譯
--enable-indev=NAME: 允許特定輸入裝置的編譯,搭配–disable-indevs可以實作單純指定支援的輸入裝置
--disable-outdevs: 禁止所有輸出裝置的編譯
--disable-outdev=NAME: 禁止特定輸出裝置的編譯
--enable-outdev=NAME: 允許特定輸出裝置的編譯,搭配–disable-outdevs可以實作單純指定支援的輸出裝置
           

關于 libav 支援的輸入輸出裝置名稱,可以使用 ./configure --list-indevs 和 ./configure --list-outdevs 指令擷取

5、減少不必要解析器的編譯

libav 可以對輸入的資料進行格式檢測,該功能由解析器(parser)負責。可以指定支援的解析器來避免不必要的編譯:

--disable-parsers: 禁止所有解析器的編譯
--disable-parser=NAME: 禁止特定解析器的編譯
--enable-parser=NAME: 允許特定解析器的編譯,搭配 --disable-parsers 可以實作單純指定支援的解析器
           

關于 libav 支援的解析器名稱,可以使用 ./configure --list-parsers 指令擷取。

6、減少不必要的二進制流過濾器的編譯

libav 可以将輸入的資料轉為二進制資料,同時可以對二進制資料進行特殊的處理,該功能由二進制流過濾器(bit stream filter)負責。可以指定支援的二進制流過濾器來避免不必要的編譯:

--disable-bsfs: 禁止所有二進制流過濾器的編譯
--disable-bsf=NAME: 禁止特定二進制流過濾器的編譯
--enable-bsf=NAME: 允許特定二進制流過濾器的編譯,搭配 –disable-bsfs 可以實作單純指定支援的二進制流過濾器
           

關于 libav 支援二進制流過濾器名稱,可以使用 ./configure --list-bsfs 指令擷取。

7、減少不必要的協定編譯

libav 對于如何讀入資料及輸出資料制定了一套協定,同時 libav 内置了一些滿足協定的方式,這些方式可以通過 ./configure --list-protocols 列出。可以指定支援的輸入輸出方式來避免不必要的編譯:

--disable-protocols: 禁止所有輸入輸出方式的編譯
--disable-protocol=NAME: 禁止特定輸入輸出方式的編譯
--enable-protocol=NAME: 允許特定輸入輸出方式的編譯,搭配 –disable-protocols 可以實作單純指定支援的輸入輸出方式
           

必須指定至少一種輸入輸出方式,通常通過使用 --disable-protocols 搭配 --enable-protocol=NAME 來完成。

8、減少不必要元件的編譯

先簡單介紹一下 libav 處理音視訊的流程,以将 FLV 格式(H264視訊+AAC音頻) 轉換為 AVI 格式(MPEG2視訊+MP3音頻) 為例,流程圖如下:

Windows編譯和使用ffmpeg

在該過程中,負責解封裝的是分離器(demuxer)、負責封裝的是複用器(muxer)、負責音視訊解碼的為解碼器(decoder)、負責編碼的為編碼器(encoder)。可以從libav所支援的四個元件的類型來減少不必要的編譯。可以使用以下指令擷取元件所支援的類型:、

./configure --list-demuxers
./configure --list-muxers
./configure --list-decoders
./configure --list-encoders
           

(1)分離器:

--disable-demuxers: 禁止所有分離器的編譯
--disable-demuxer=NAME: 禁止特定分離器的編譯
--enable-demuxer=NAME: 允許特定分離器的編譯,搭配–disable-demuxers
           

(2)複用器:

--disable-muxers: 禁止所有複用器的編譯
--disable-muxer=NAME: 禁止特定複用器的編譯
--enable-muxer=NAME: 允許特定複用器的編譯,搭配 --disable-muxers
           

(3)解碼器:

--disable-decoders: 禁止所有解碼器的編譯
--disable-decoder=NAME: 禁止特定解碼器的編譯
--enable-decoder=NAME: 允許特定解碼器的編譯,搭配 --disable-decoders
           

(4)編碼器:

--disable-encoders: 禁止所有編碼器的編譯
--disable-encoder=NAME: 禁止特定編碼器的編譯
--enable-encoder=NAME: 允許特定編碼器的編譯,搭配–disable-encoders
           

至此,通過對項目的特殊定制,可以最大化的減小編譯包的大小,避免編譯包太大造成最終産品體積過大的問題。

相關學習資料推薦,點選下方連結免費報名,先碼住不迷路~】

【免費分享】音視訊學習資料包、大廠面試題、技術視訊和學習路線圖,資料包括(C/C++,Linux,FFmpeg webRTC rtmp hls rtsp ffplay srs 等等)有需要的可以點選加群免費領取~

Windows編譯和使用ffmpeg

二、編譯和使用

ffmpeg 可以用 mingw 編譯,但有時候将編出來的 ffmpeg 靜态庫檔案給 vs 工程連結使用,會出現編譯錯誤,因為 mingw 的庫和 vs 的庫沖突了,是以 ffmpeg 可以直接使用 vs 的 msvc 編譯,不依賴 mingw 的庫。下面提供兩種編譯 ffmpeg 的方式。

1、基于 mingw 的庫編譯

(1)32位電腦使用 MinGW32

首先将 /MinGW32/msys/1.0/etc 裡面的 fstab.sample 複制一份且将其更名為 fstab,打開 fstab,将其中相應的内容改為 MinGW32 的安裝目錄,如 D:/MinGW32;然後在 /MinGW32/msys/1.0/msys.bat 檔案開頭加上:

call "D:\soft\work_soft\vs\VC\bin\vcvars32.bat"  #vs2010或其他版本vs的安裝目錄
           

添加環境變量 path,如:D:\MinGW32\bin;輕按兩下打開 /MinGW32/msys/1.0/msys.bat,開始編譯。編譯過程報錯可以在工程的configure日志檢視相關報錯資訊。預設編譯指令:

./configure --enable-shared --enable-static --enable-memalign-hack --arch=x86_32 --host-os=win64 --disable-debug --disable-yasm --extra-cflags=-I/mingw/include --extra-ldflags=-L/mingw/lib --prefix=./output
           

如果要求編出來的庫比較小,比如給我公司的OCX網頁插件使用,可以裁剪編譯 (支援 h264 mjpeg h265), 指令:

./configure --enable-static --disable-everything --disable-debug --extra-cflags="-I/mingw/include" --extra-ldflags=-L/mingw/lib --prefix=./output --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-decoders --enable-decoder=h264 --enable-decoder=mjpeg --enable-decoder=hevc --disable-encoders --disable-avfilter --disable-avdevice --disable-swscale --disable-demuxers --enable-demuxer=h264 --enable-demuxer=hevc --enable-demuxer=mjpeg --disable-iconv --disable-filters --disable-bsfs --disable-muxers --enable-muxer=avi --disable-protocols --enable-protocol=file --disable-parsers --disable-devices --enable-asm --enable-inline-asm --enable-hardcoded-tables --enable-hwaccel=h264_dxva2 --disable-network --cpu=i686 --arch=x86_32 --enable-small
           

或者比如給我公司的另一個程式HsPlayer.exe使用,裁剪編譯 (支援 h264 mjpeg h265) 指令:

./configure --enable-static --disable-everything --disable-debug --extra-cflags="-I/mingw/include" --extra-ldflags=-L/mingw/lib --prefix=./output --disable-doc --disable-htmlpages --disable-manpages --disable-podpages --disable-txtpages --disable-programs --disable-ffmpeg --disable-ffplay --disable-ffprobe --disable-decoders --enable-decoder=h264 --enable-decoder=mjpeg --enable-decoder=hevc --disable-encoders --disable-avfilter --disable-avdevice --disable-swscale --disable-demuxers --enable-demuxer=h264 --enable-demuxer=hevc --enable-demuxer=mjpeg --enable-demuxer=avi --enable-demuxer=mov --enable-demuxer=mpegps --disable-iconv --disable-filters --disable-bsfs --disable-muxers --enable-muxer=avi --disable-protocols --enable-protocol=file --disable-parsers --enable-parser=h264 --enable-parser=hevc --enable-parser=mjpeg --disable-devices --enable-asm --enable-inline-asm --enable-hardcoded-tables --enable-hwaccel=h264_dxva2 --disable-network --cpu=i686 --arch=x86_32
           

(2)64位電腦使用 MinGW64

首先将 /MinGW64/msys/1.0/etc 裡面的 fstab.sample 複制一份且将其更名為 fstab,打開 fstab,将其中相應的内容改為 MinGW64 的安裝目錄,如 D:/MinGW64;然後在 /MinGW64/msys/1.0/msys.bat 檔案開頭加上:

call "D:\soft\work_soft\vs2015\VC\bin\amd64\vcvars64.bat"  #vs2015或其他版本vs的安裝目錄
           

添加環境變量 path,如:D:\MinGW64\bin;輕按兩下打開 /MinGW64/msys/1.0/msys.bat,開始編譯。編譯指令同32位基本一樣,隻需将 --arch=x86_32 改成 --arch=x86_64。編譯過程報錯可以在工程的configure日志檢視相關報錯資訊。

2、不依賴 mingw 的庫

(1)32位電腦使用 MinGW32

首先将 /MinGW32/msys/1.0/etc 裡面的 fstab.sample 複制一份且将其更名為 fstab,打開 fstab,将其中相應的内容改為 MinGW32 的安裝目錄,如 D:/MinGW32;然後在 /MinGW32/msys/1.0/msys.bat 檔案開頭加上:

call "D:\soft\work_soft\vs\VC\bin\vcvars32.bat"  #vs2010或其他版本vs的安裝目錄
           

添加環境變量 path,如:D:\MinGW32\bin;重命名 D:/MinGW32/msys/1.0/bin/link.exe 為 D:/MinGW32/msys/1.0/bin/link.bak,避免和 MSVC 的 link.exe 抵觸;去開始菜單找到 vs2015 的工具,即 “VS2015 x86 本機工具指令提示符”,打開之後運作:

D:\soft\work_soft\MinGW32\msys\1.0\msys.bat
           

在新彈出的視窗中輸入指令,檢視是否使用 vs2015 的庫(下圖實際上是編譯64位時的截圖):

Windows編譯和使用ffmpeg

運作 ./configure,指令同上基本一樣,加上 --toolchain=msvc --host-os=win64,去掉 --extra-cflags="-I/mingw/include" --extra-ldflags=-L/mingw/lib。修改 config.mak 檔案,删除其中的

-Dsnprintf=_snprintf
-Dsnprintf=avpriv_snprintf
-D_snprintf=avpriv_snprintf
-Dvsnprintf=avpriv_vsnprintf
           

否則出現如下錯誤:

C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt\stdio.h(1419):
note: 指令行參數: 參見前面的“vsnprintf”定義
C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt\stdio.h(1421):
fatal error C1189: #error:  Macro definition of vsnprintf conflicts with Standa
d Library function declaration
           

修改 ffmpeg 源碼的 compat\msvcrt\snprintf.c,添加:

#include "snprintf.h"
           

否則出現如下錯誤:

CC libavutil/../compat/msvcrt/snprintf.o
snprintf.c
libavutil/../compat/msvcrt/snprintf.c(41): error C4013: “avpriv_vsnprintf”未定
義;假設外部傳回 int
make: *** [libavutil/../compat/msvcrt/snprintf.o] Error 2
           

修改 ffmpeg.c,檔案中#elif HAVE_KBHIT改成#elif 0 //HAVE_KBHIT,有兩處,都需要改。否則出現如下錯誤:

ffmpeg.c(395): error C2039: “_cnt”: 不是“_iobuf”的成員
C:\Program Files (x86)\Windows Kits\10\include\10.0.10150.0\ucrt\corecrt_wstdio.
h(26): note: 參見“_iobuf”的聲明
           

行 make clean && make (注意要先make clean,否則編譯出來的庫可能會有上次編譯的殘留)。編譯過程會有很多警告,忽略即可,執行 make install。注意:不要用 vs2008 以下編譯,vs2010沒試過。vs2008 标準是C98标準,好多文法不識别,vs2015用的C99标準,就可以了。編譯出的庫要在 vs2015 中使用,不要用其他版本的vs。

(2)64位電腦使用 MinGW64

使用MinGW64,步驟同32位基本一樣,不同點:在 /MinGW64/msys/1.0/msys.bat 檔案開頭加上:

call "D:\soft\work_soft\vs2015\VC\bin\amd64\vcvars64.bat"
           

打開的是 “VS2015 x64 本機工具指令提示符”。--arch=x86_32 改成 --arch=x86_64,加上 --toolchain=msvc --host-os=win64,去掉 --extra-cflags="-I/mingw/include" --extra-ldflags=-L/mingw/lib。

3、H265的支援

某些版本的 ffmpeg 不支援 h265 流封裝成 avi 檔案,需要修改 ffmpeg 源碼,在源碼中添加 h265 類型:

Windows編譯和使用ffmpeg

4、ffplay的支援

首先解壓 SDL-devel-1.2.11-mingw32.rar,将lib、include複制到mingw32下;将 bin 下的 i386-mingw32msvc-sdl-config 複制到 mingw32/bin 下,重命名為sdl-config;将 bin 下的 SDL.dll 複制到 mingw32/bin 下;vim config.mak 確定 line 544為:CONFIG_FFPLAY=yes(ffplay4.0版本預設前面有!)。

5、常見錯誤

libavformat/os_support.c: In function 'ff_gai_strerror':
libavformat/os_support.c:194:10: error: 'ERROR_NOT_ENOUGH_MEMORY' undeclared (first use in this function)
           

解決:打開libavformat/os_support.h 檔案,在其中增加#include <winerror.h>。

libavformat/rtsp.c: In function 'rtsp_send_cmd_with_content_async': 
libavformat/rtsp.c:1322:16: error: 'ENOTCONN' undeclared (first use in this function) return ENOTCONN;
           

解決:将ENOTCONN修改成126。

6、使用

基于mingw的庫編譯的ffmpeg使用時,要先連結 mingw 的 libgcc.a、libmingwex.a、libcoldname.a 等,沒有基于 mingw的庫編譯的直接連結 ffmpeg 編出來的庫即可。

#ifdef __cplusplus
extern "C" {
#endif
#include "libavutil/imgutils.h"
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
#include "libswscale/swscale.h"
#include "libavutil/opt.h"

#ifdef __cplusplus
}
//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libgcc.a")
//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libmingwex.a")
//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libcoldname.a")

#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libavcodec.a")
#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libavformat.a")
#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libavutil.a")
#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/all/libswresample.a")

//#pragma comment(lib, "../ThirdParty/ffmpeg3.4.8_64/lib/libz.a")           

原文 Windows編譯和使用ffmpeg_windows ffmpeg_心願許得無限大的部落格-CSDN部落格

繼續閱讀