前言
本文主要講解 FFmpeg 相關知識,以及在 Windows 下編譯 FFmpeg 源碼以及使用。
一、FFmpeg 簡介
ffmpeg 是廣泛使用的多媒體解決方案,既是一款音視頻編解碼工具,同時也是一組音視頻編解碼開發(fā)套件,作為編解碼開發(fā)套件,它為開發(fā)者提供了豐富的音視頻處理的調用接口。
其包括了目前領先的音/視頻編碼庫 libavcodec。
ffmpeg 提供了多種媒體格式的封裝和解封裝,包括多種音視頻編碼,多種協議的流媒體,多種色彩格式轉換,多種采樣率轉換,多種碼率轉換等。ffmpeg 發(fā)展至今,已經被許多開源項目使用。
二、基本組成
ffmpeg 框架的基本組成包含 AVFormat,AVCodec,AVFilter,AVDevice,AVUtil 等。
1、封裝模塊 - AVFormat
AVFormat:文件格式和協議庫,該模塊是最重要的模塊之一,封裝了 Protocol 層和 Demuxer、Muxer 層,使得協議和格式對于開發(fā)者來說是透明的。
AVFormat 中實現了目前多媒體領域中絕大多數媒體封裝格式,包括封裝和解封裝,如 MP4,FLV 等文件封裝格式,RTMP,HLS 等網絡協議封裝格式。ffmpeg 是否支持某種封裝格式,取決于編譯時是否包含了該格式的封裝庫。
應用于各種音視頻封裝格式的生成和解析,包括獲取解碼所需信息以生成解碼上下文結構和讀取音視頻幀等功能;音視頻的格式解析協議,為 libavcodec 分析碼流提供獨立的音頻或視頻碼流源。
2、編解碼模塊 - AVCodec
編解碼庫,該模塊也是最重要的模塊之一,封裝了 Codec 層。
AVCodec 中實現了目前多媒體領域絕大多數常用的編解碼格式,既支持編碼,也支持解碼。AVCodec 除了支持自帶的媒體解碼格式之外,還支持第三方的編解碼器,如 H.264 編碼,需要使用 x264 編碼器;MP3編碼,需要使用libmp3lame 編碼器。如果希望增加自己的編碼格式,或者硬件編解碼,則需要在 AVCodec 中增加相應的編解碼模塊。(有一些 Codec 是具備自己的 License 的,FFmpeg 是不會默認添加像 libx264、FDK-AAC、lame 等庫的,但是 FFmpeg 就像一個平臺 一樣,可以將其他的第三方的 Codec 以插件的方式添加進來,然后為開發(fā)者提供統一的接口)
該庫是音視頻編解碼的核心,avcodec 庫被其他各大解碼器 ffdshow,Mplayer 等所包含或應用。
3、濾鏡模塊 - AVFilter
AVFilter 提供了一個通用的音頻,視頻,字幕等濾鏡處理框架。該模塊提供了包括音頻特效和視頻特效的處理,在使用 FFmpeg 的 API 進行編解碼的過程中,直接使用該模塊為音視頻數據做特效處理是非常方便同時也非常高效的一種方式。
4、視頻圖像轉換計算模塊 - swscale
swscale 模塊提供了高級別的圖像轉換 API,例如它允許進行圖像縮放和像素格式轉換,視頻場景比例縮放、色彩映射轉換;圖像顏色空間或格式轉換,如 gb565、rgb888 與 yuv420 等之間轉換。
5、音頻轉換計算模塊 - swresample
swresample 模塊提供了高級別的音頻重采樣API??梢詫底忠纛l進行聲道數、數據格式、采樣率等多種基本信息的轉換。例如,它允許操作音頻采樣,音頻通道布局轉換與布局調整。
6、AVUtil - 核心工具庫
該模塊是最基礎的模塊之一,許多其他模塊都會依賴該庫做一些基本的音視頻處理操作。
7、AVDevice - 硬件采集,加速,顯示
硬件采集,加速,顯示。輸入輸出設備庫,比如,需要編譯出播放聲音或者視頻的工具 ffplay,就需要確保該模塊是打開的,同時也需要 libSDL 的預先編譯,因為該設備模塊播放聲音與播放視頻使用的都是 libSDL 庫。
三、命令行工具
ffmpeg 已經編譯好了3個常用的工具集 ffmpeg.exe、ffprobe.exe、ffplay.exe. 通過這 3 個工具就可以使用命令去操作一個多媒體文件。
- ffmpeg.exe:ffmpeg 主要用于對音視頻進行處理,比如說剪切、抽取視頻、抽取音頻、增加貼紙水印等等。Hyper fast Audio and Video encoder,音視頻編解碼工具(類似愛剪輯、格式工廠)。
- ffplay.exe:ffplay主要用于播放視頻,幾乎支持所有的本地視頻播放,還能支持流媒體等網絡視頻播放,甚至還能播放YUV視頻,這點在開發(fā)過程中非常好用。Simple media player 簡單媒體播放器。
- ffprobe.exe:ffprobe主要用于查看音視頻文件格式,比如說你要將一個音視頻文件的所有信息以 JSON 格式輸出,ffprobe 這個命令行就很便捷。Simple multimedia streams analyzer,簡單多媒體流分析器。
四、FFmpeg 環(huán)境搭建及初體驗
這里參考一下我前面寫的博客:音視頻開發(fā)常用工具
五、Windows 下編譯 FFmpeg
1、準備編譯環(huán)境
Windows11 64位 需要安裝的軟件和工具:
- Visual Studio 2022(我本地已有)
- MSYS2 + CMake
2、MSYS2
除了需要安裝 VS 之外,還要安裝 MSYS2,這是一款 Windows下模擬 Linux 的軟件。FFmpeg 的編譯就是在該軟件中進行的,而編譯時使用的編譯器(cl.exe)和鏈接器(link.exe)則是由 Visual Studio 提供的。
MSYS2 可以到這里下載: 鏈接:https://pan.baidu.com/s/1fWcS_5Xlxv1Bja4354JnvA
我這里將其安裝到了 D:\msys64 目錄下
3、ffmpeg 源碼
編譯環(huán)境準備好之后,接下來我們需要下載一份最新的 FFmpeg 源碼,可以使用 Git 下載。先將Git命令安裝好,然后執(zhí)行下面的命令。
cd /d/Git-Space
git clone https://git./ffmpeg.git ffmpeg
代碼就被下載到 D:\Git-Space 盤的 ffmpeg 目錄下了
ffmpeg 源碼也可以到這里下載: 鏈接:https://pan.baidu.com/s/1gjsDtEn_E4yCwnbT3TVUWQ 提取碼:dlvx
4、修改 msys64
首先,進入 MSYS2 的安裝目錄,比如我這里將 MSYS2 安裝到了 D:\msys64 目錄下。在該目錄下打開 msys2_shell.cmd 文件,將該文件第 17 行代碼的注釋打開,即去掉 rem 關鍵字,如下所示: 之所以要打開該注釋,是為了讓 MSYS2 可以繼承 Windows 控制臺的環(huán)境變量。
5、安裝其他編譯工具
之后,找到 x64 Native Tools Command Prompt for VS 2022 命令窗口: 在該命令窗口中輸入下面的命令啟動 MSYS2 軟件
# 進入到 MSYS2 目錄下
cd D:\msys64
# 啟動 MSYS2
msys2_shell.cmd
此時,會彈出 MSYS2 的命令窗口。接下來,在該窗口中輸入下面命令,安裝必要的編譯工具:
pacman -S diffutils make pkg-config yasm
其中 pacman 是 MSYS2的 包安裝工具;而 diffutils、make…都是編譯 FFmpeg 時需要用的編譯工具。
6、編譯 FFmepg
當編譯工具安裝好后,在 MSYS2 命令窗中執(zhí)行下面命令,進入到 FFmpeg 源碼目錄下:
cd /d/Git-Space/ffmpeg
緊接著,運行 FFmpeg 源碼目錄中的 configure 腳本生成 Makefile 文件,命令如下:
./configure --prefix=/usr/local/ffmpeg --enable-gpl --enable-nonfree --enable-shared --disable-ffprobe --toolchain=msvc
上述命令的含義是使用 mscv 作為 FFmpeg 的編譯工具鏈;編譯出的 FFmpeg 庫被放到 /usr/local/ffmpeg 目錄下;編譯的庫是動態(tài)庫,在 Windows 下就是 DLL 庫;編譯時不生成 ffprobe 程序。 上述腳本執(zhí)行完成后,你可以在 FFmpeg 源碼目錄下發(fā)現多了一個 Makefile 文件。有了這個文件我們就可以編譯FFmpeg了,編譯命令如下:
make -j4 && make install
出現了很多報錯: fftools/opt_common.c(206): error C2065: “slib”: 未聲明的標識符 fftools/opt_common.c(206): error C2296: “%”: 無效,因為左操作數的類型為“char [138]” 解決辦法: 該問題是因為在 Windows下無法識別 CC_IDENT 導致的,只需將包括 CC_IDENT 關鍵字的那行代碼注釋掉即可。 繼續(xù)編譯
make -j4 && make install
此時編譯通過了 當執(zhí)行完這條命令后,在 D:\MSYS64\usr\local\ffmpeg 目錄下就可以找到編譯好的 FFmpeg 庫和 FFmpeg 命令了。
六、VS 項目中引用 FFmpeg 庫
編譯好 FFmpeg 庫后,下面我們就可以在 VS 中引用它了。
1、創(chuàng)建新項目
2、控制臺應用
3、確定項目名稱及位置
4、點擊創(chuàng)建
5、引入FFmpeg 頭文件
在 項目右鍵 -> 屬性 -> C/C++ -> 常規(guī) -> 附加包含目錄 中添加 FFmpeg 頭文件所在路徑。
6、指定庫文件位置
首先說明一點,我編譯出來的庫文件存在于 D:\msys64\usr\local\ffmpeg\bin 目錄下 在 項目右鍵 -> 屬性 -> 鏈接器 -> 常規(guī) -> 附加庫目錄 中添加 FFmpeg 庫所在路徑。
7、指定使用哪個庫
在 項目右鍵 -> 屬性 -> 鏈接器 -> 輸入 -> 附加依賴項 中指定你所用到的 FFmpeg 庫
指定以下所有庫:
avcodec.lib
avdevice.lib
avfilter.lib
avformat.lib
avutil.lib
postproc.lib
swresample.lib
swscale.lib
8、運行編譯好的程序
當上面這此工作完成后,我們就可以在 main(…) 函數中調用 FFmpeg API 了,如調用 FFmpeg 庫中的日志函數:
#include <iostream>
extern "C" {
#include "libavcodec/avcodec.h"
#include "libavformat/avformat.h"
}
int main()
{
av_log_set_level(AV_LOG_DEBUG);
av_log(NULL, AV_LOG_INFO, "Hello World!\n");
return 0;
}
- 上述代碼中,調用了 FFmpeg 中的兩個 API,分別是 av_log_set_level(…) 以及 av_log(…),這兩個函數都是 FFmpeg avutil 庫中的 API。所以在使用這兩個 API 之前,我們要在 main.c 中需要通過 #include 關鍵字將 libavtuil/log.h 這個頭文件引入進來。
- 此外,由于 FFmpeg 是 C 語言庫,而我們用 VS 創(chuàng)建的是 C++ 工程,所以在引入頭文件時需要加上 extern “C” 關鍵字,否則的話 VS 無法將其成功編譯。
執(zhí)行出現了這樣的報錯,其原因是在運行時無法找到需要的動態(tài)庫。 解決方案一: 將 D:\msys64\usr\local\ffmpeg\bin 目錄下的 avutil-58.dll 文件拷貝到 C:\Windows\System32 目錄下 拷貝結果如下: 再次執(zhí)行程序,可以看到如下的結果 解決方案二: 只需將我們之前編譯好的 FFmpeg 庫,即提示的無法找到的 .dll 庫,拷貝到執(zhí)行程序的同一目錄下,這樣執(zhí)行程序就可以找到該庫并正確執(zhí)行了。
七、編譯 FFmpeg 依賴庫
很多時候我們在編譯 FFmpeg 庫時還要增加一些其它庫,如 SDL、x264 等,如果要將這些庫添加到 FFmpeg 中,首先我們要編譯出 Windows 下可用的對應庫。
1、編譯 SDL
①、下載 SDL 源碼
首先從 github 上獲取 SDL 源碼,命令如下:
git clone https://github.com/libsdl-org/SDL.git
git checkout release-2.26.x
需要注意的是,SDL現在已經發(fā)布了3.0版本,而ffmpeg目前只能用SDL2版本,所以在拉取代碼后,需要切換到2.26這個版本
可以到這里自取 SDL-2.26.x 鏈接:https://pan.baidu.com/s/1n_wMhIsBb9yaDhAL8NHZ8Q 提取碼:qqbh
②、下載 CMake
下載好 SDL2 源碼后,我們需要使用 CMake 為其生成 VS 工程,并將其安裝到 Windows 系統上。
可以到這里自取 CMake 安裝包 鏈接:https://pan.baidu.com/s/1pQ7hh3WA6ES8pdBTpds1_Q 提取碼:et4t
關于安裝 CMake 這里,針對所有用戶把 CMake 目錄安裝到系統目錄 并將其安裝到 D:\CMake\ 目錄下
③、編譯 SDL
之后打開 CMake-GUI,在 CMake-GUI 中指定 SDL 源碼所在路徑(D:/Git-Space/SDL)以及編譯后的輸出路徑(D:/CMake/usr/local/) 隨后執(zhí)行
Configure -> Generate -> Open Project
生成 VS 工程。有了 VS 工程,我們就可以通過 VS2022 來編譯 SDL 了。
分別在 Release 和 Debug 模式下,重新生成一下 All_BUILD 子項目。 沒啥問題的話 SDL 就編譯好了,你可以去 D:\Project\VS_Project\sdl_test\Debug 和 D:\Project\VS_Project\sdl_test\Release 目錄下看看有沒有對應的 lib 文件
D:\CMake\usr\local\sdl\Debug 目錄如下: D:\Project\VS_Project\sdl_test\Release 目錄如下 為了滿足要求,我們需要在指定輸出目錄下創(chuàng)建 lib 目錄,并將 SDL2.lib 和 SDL2.dll 文件拷貝到 lib 目錄下。同時在 lib 目錄下創(chuàng)建 pkgconfig 目錄,將 sdl2.pc 文件拷貝到該目錄中。
最終完整的目錄結構如下所示:
/usr/local/sdl2
|------------ lib
| |-- sdl2.lib
| |-- sdl2.dll
| |-- pkgconfig
| |----- sdl2.pc
|------------ include
此外,我們還要修改 sdl2.pc 中的內容,將其中的庫路徑修改為指定的輸出路徑
2、編譯 x264
x264 庫的編譯還是比較簡單的,與 SDL 一樣我們也要先獲取其源碼,可以通過下面的命令獲取 x264 源碼:
git clone https://code./videolan/x264.git
可以到這里自取 x264 源碼 鏈接:https://pan.baidu.com/s/17HyuJBrka04DXoS4WOa3tQ 提取碼:oqrb
源碼獲取到后,可以直接在 MSYS2 環(huán)境下編譯出 Windows 下可用的動態(tài)庫,具體步驟如下:
# 通過VS X64 Native... 窗口打開MSYS2
cd D:\msys64
msys2_shell.cmd
cd /d/Git-Space/x264/ # 在MSYS2中進入x264源碼目錄
pacman -S automake autoconf libtool # 安裝生成Makefile的工具
CC=cl ./configure --prefix=/usr/local/x264 --enable-shared --disable-asm
make -j 4 && make install
通過上面的命令就可以將 x264 編譯出來了。x264 編譯好后,其輸出的目錄結構與 ffmepg 是一樣的,在 /usr/local/x264 中包括了 include、lib、bin 等目錄。 要特別強調的一點是,我們需要將 lib 目錄下的 libx264.dll.lib 文件名修改為 libx264.lib,否則 ffmpeg 編譯時會報 “無法找到該庫” 的錯誤。
3、編譯 fdk-aac
fdk-aac 的編譯與 SDL 類似,它同樣要使用 CMake 生成 VS 工程文件,之后再通過 VS 編譯該庫。
首先,通下面的的命令獲取 fdk-aac 源碼:
git clone https://github.com/mstorsjo/fdk-aac.git
可以到這里自取 fdk-aac 源碼: 鏈接:https://pan.baidu.com/s/1ViuYEtEFFh71w9ZRgLaesA 提取碼:hwf5
之后打開 CMake-GUI,在 CMake-GUI 中指定 SDL 源碼所在路徑(D:/Git-Space/fdk-aac)以及編譯后的輸出路徑(D:/CMake/usr/local/fdk-aac) 隨后執(zhí)行
Configure -> Generate -> Open Project
生成 VS 工程。有了 VS 工程,我們就可以通過 VS2022 來編譯 FDK-AAC 了。
分別在 Release 和 Debug 模式下,重新生成一下 All_BUILD 子項目。 沒啥問題的話 FDK-AAC 就編譯好了,你可以去 D:\CMake\usr\local\fdk-aac\Debug 和 D:\CMake\usr\local\fdk-aac\Release 目錄下看看有沒有對應的 lib 文件
D:\CMake\usr\local\sdl\Debug 目錄如下: D:\CMake\usr\local\fdk-aac\Release 目錄如下: 為了滿足要求,我們需要在指定輸出目錄下創(chuàng)建 lib 目錄,并將 fdk-aac.lib 和 fdk-aac.dll 文件拷貝到 lib 目錄下。同時在 lib 目錄下創(chuàng)建 pkgconfig 目錄,將 fdk-aac.pc 文件拷貝到該目錄中。
但是這里發(fā)現一個問題,就是目錄下沒有 include 目錄
為了解決這個問題,我又用 MSYS2+mingw 的方式重新編譯了一遍 fdk-aac,這種方式是可以生成 include 頭文件的
①、打開 MSYS2 MINGW64 ②、在 fdk-aac 目錄下執(zhí)行如下命令
pacman -S mingw-w64-x86_64-gcc
./autogen.sh
./configure --prefix=/usr/local/fdk-aac --enable-shared
make -j4
make install
然后將生成的頭文件手動拷貝到了 /usr/local/fdk-aac 目錄下即可。 最終完整的目錄結構如下所示:
/usr/local/fdk-aac
|------------ lib
| |-- fdk-aac.lib
| |-- fdk-aac.dll
| |-- pkgconfig
| |----- fdk-aac.pc
|------------ include
此外,我們還要修改 fdk-aac.pc 中的內容,將其中的庫路徑修改為指定的輸出路徑
八、FFmpeg 使用上述編譯好的庫
首先,我們要設置環(huán)境變量 PKG_CONFIG_PATH,通過它告訴 FFmpeg 上述幾個庫從哪兒可以找到,具體的設置方法如下:
在 MSYS2 窗口中打開 .bashrc
pacman -S vim
vim ~/.bashrc
在 ~/.bashrc 中設置環(huán)境變量
export PKG_CONFIG_PATH=/d/CMake/usr/local/sdl/lib/pkgconfig:/usr/local/x264/lib/pkgconfig:/d/CMake/usr/local/fdk-aac/lib/pkgconfig:$PKG_CONFIG_PATH
:wq #保存并退出vim
讓環(huán)境變是生效
source ~/.bashrc
接下來,重新生成 FFmpeg 的 Makefile 文件,并重新編譯
首先進入到 ffmpeg 源碼目錄,執(zhí)行下列命令
./configure --prefix=/usr/local/ffmpeg --arch=x86_64 --enable-shared --disable-ffprobe --disable-doc --enable-x264 --enable-gpl --enable-fdk-aac --enable-nonfree --toolchain=msvc
make clean
make -j 4 && make install
最后,將 sdl 的 dll、x264 的 dll 以及 fdk-aac 的 dll 拷貝到 ffmpeg 的 bin 目錄下,這樣就可以正確的執(zhí)行 ffmpeg.exe 或 ffplay.exe 命令了。 進入 ffmpeg/bin 目錄下,執(zhí)行以下命令,如果能夠輸出版本信息,則說明正常
./ffmpeg.exe -version
|