什么是FFmpeg
FFmpeg 既是一款音視頻編解碼工具昆著,同時(shí)也是一組音視頻編解碼開發(fā)套件,作為編解碼開發(fā)套件,它可以為我們提供豐富的音視頻處理的調(diào)用接口佣谐。
FFmpeg 提供了媒體格式的封裝和解封裝提佣,包括音視頻編碼吮蛹、多種協(xié)議的流媒體、色彩格式轉(zhuǎn)換拌屏、采樣率轉(zhuǎn)換潮针、碼率轉(zhuǎn)換等。
FFmpeg 框架提供了多種豐富的插件模塊倚喂,包含封裝與解封裝的插件每篷、編碼與解碼的插件等。
"FFmpeg"中"FF"指的是"Fast Forward"端圈,"mpeg"指的是一種壓縮率比較大的活動(dòng)圖像和聲音的壓縮標(biāo)準(zhǔn)焦读。
命令行工具
- ffmpeg: 包含F(xiàn)Fmpeg的各種功能,如gif枫笛、格式轉(zhuǎn)換吨灭、截圖、編解碼等刑巧。
- ffmpeg-all:包含F(xiàn)Fmpeg工具及FFmpeg組件喧兄。
- ffplay:一個(gè)使用了FFmpeg和SDL庫(kù)的簡(jiǎn)單可移植的媒體播放器。
- ffplay-all:包含ffplay工具及FFmpeg組件啊楚。
- ffprobe:用來查看多媒體文件的信息吠冤。
- ffprobe-all:包含ffprobe工具及FFmpeg組件。
- ffserver:與流媒體服務(wù)器相關(guān)恭理,負(fù)責(zé)響應(yīng)客戶端的流媒體請(qǐng)求拯辙,把流媒體數(shù)據(jù)發(fā)送給客戶端。
- ffserver-all:包含f'fserver工具及FFmpeg組件颜价。
組件
- Utilities:libavutil提供的t通用的features及工具涯保。
- Video scaling and pixel format converter:視頻縮放和像素格式轉(zhuǎn)換器。
- Audio resampler:音頻重新采樣周伦。
- Encoders and decoders(codecs):編碼和解碼夕春。
- Bitstream filters:碼流過濾器。
- Muxers and demuxers(formats):數(shù)據(jù)合成及數(shù)據(jù)分離专挪。
- Protocols:協(xié)議及志。
- Input and output devices:輸入和輸出設(shè)備片排。
- Filters:過濾器。
類庫(kù)
- libavutil:包含一些公共的工具函數(shù)的使用庫(kù)速侈,包括算術(shù)運(yùn)算率寡、字符操作等。
- libswscale:(原始視頻格式轉(zhuǎn)換)用于食品場(chǎng)景比例縮放倚搬、色彩映射轉(zhuǎn)換冶共、圖像顏色空間或格式轉(zhuǎn)換,如RGB565潭枣、RGB888等與YUV420等之間的轉(zhuǎn)換比默。
- libswresample:原始音頻格式轉(zhuǎn)碼。
- libavcodec:用于各種類型聲音/圖像編解碼盆犁。該庫(kù)是音視頻編解碼核心庫(kù)命咐,實(shí)現(xiàn)了市面上可見的絕大部分編解碼器的功能。
- libavformat:用于各種音視頻封裝格式的生成和解析谐岁,包括獲取解碼所需信息以生成解碼上下文結(jié)構(gòu)和讀取音視頻幀等功能醋奠。音視頻的格式解析協(xié)議,為
libavcodec 分析碼流提供獨(dú)立的音頻或視頻碼流源伊佃。- libavdevice:硬件采集窜司、加速、顯示航揉。操作計(jì)算機(jī)中常見的音視頻捕獲或輸出設(shè)備有ALSA塞祈、AUDIO_BEOS、JACK帅涂、OSS议薪、1394、VFW等媳友。
- libavfilter:filter(FileIO斯议、FPS、DrawText)音視頻濾波器的開發(fā)醇锚,如寬高比哼御、裁剪、格式化焊唬、非格式化恋昼、伸縮等。
- libavresample:音視頻封裝編解碼格式預(yù)設(shè)等赶促。
- libpostproc:(同步液肌、時(shí)間計(jì)算的簡(jiǎn)單算法)用于后期效果處理,音視頻應(yīng)用的后處理芳杏,如圖像的去塊效應(yīng)矩屁。
FFmpeg 的編解碼工具-ffmpeg
ffmpeg 是 FFmpeg源碼編譯后生成的可執(zhí)行程序,可以作為命令行工具來使用爵赵。
例如:
./ffmpeg -i input.mp4 output.avi
這是一條簡(jiǎn)單的 ffmpeg 命令吝秕,通過 -i 參數(shù)將 input.mp4 作為輸入源,然后進(jìn)行轉(zhuǎn)碼和轉(zhuǎn)封裝操作空幻,輸出到 output.avi 中烁峭。
上面指令也可以寫成:./ffmpeg -i input.mp4 -f avi output.dat
-f 參數(shù)指定了輸出文件的容器格式,輸出的文件 output.dat 同樣是 avi 格式文件秕铛。(不要光看文件后綴名就斷定文件封裝格式)
ffmpeg 大致處理流程:
1约郁,讀取輸入源
2,解封裝
3但两,解碼
4鬓梅,重新編碼
5,重新封裝
6谨湘,輸出目標(biāo)文件
(具體代碼流程可以查閱ffmpeg源碼)
FFmpeg 的播放器-ffplay
ffplay 也是 FFmpeg 源碼編譯生成的一個(gè)可執(zhí)行程序绽快,通常作為測(cè)試工具來使用。ffplay 提供了音視頻顯示和播放相關(guān)的圖像信息紧阔,音頻的波形信息等坊罢。
播放 input.mp4 文件:
./ffplay input.mp4
FFmpeg 的多媒體分析工具-ffprobe
ffprobe 也是 FFmpeg 源碼編譯生成的一個(gè)可執(zhí)行程序,可以從媒體文件或媒體流中獲取詳細(xì)的媒體信息擅耽,如音視頻的編碼格式活孩、媒體容器的參數(shù)信息等。
查看 input.mp4 中流的信息:
./ffprobe -show_streams input.mp4
linux下編譯FFmpeg
環(huán)境準(zhǔn)備
linux服務(wù)器或虛擬機(jī)(自行解決)
下載linux版ndk(android-ndk-r17c-linux-x86_64.zip)
NDK下載地址
wget https://dl.google.com/android/repository/android-ndk-r17c-linux-x86_64.zip
解壓ndk
unzip android-ndk-r17c-linux-x86_64.zip
下載FFmpeg(ffmpeg-4.2.1.tar.bz2)
wget https://ffmpeg.org/releases/ffmpeg-4.2.1.tar.bz2
解壓FFmpeg
tar -xjvf ffmpeg-4.2.1.tar.bz2
configure文件
configure文件其實(shí)是一個(gè)shell腳本乖仇,用于生成MakeFile文件憾儒,然后可以使用make命令執(zhí)行。我們可以通過執(zhí)行 ./configure --help
來查看編譯相關(guān)信息这敬。
#將help信息輸出到文本中便于查看
$ ./configure --help > ffmpeg_configure_help.txt
#發(fā)送到windows端查看更happy
$ sz ffmpeg_configure_help.txt
最新版本的ffmpeg默認(rèn)使用clang編譯航夺,可以修改configure文件來關(guān)閉:
注釋4210-4213行,簡(jiǎn)單粗暴:
4209
4210 #set_default target_os
4211 #if test "$target_os" = android; then
4212 # cc_default="clang"
4213 #fi
4214
編寫交叉編譯FFmpeg的shell腳本build.sh
#!/bin/bash
#NDK_ROOT 變量指向ndk目錄
NDK_ROOT=/root/android-ndk-r17c
#TOOLCHAIN 變量指向ndk中的交叉編譯gcc所在的目錄
TOOLCHAIN=$NDK_ROOT/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64
#指定android api版本
ANDROID_API=17
#此變量用于編譯完成之后的庫(kù)與頭文件存放在哪個(gè)目錄
PREFIX=./android/armeabi-v7a
#執(zhí)行configure腳本崔涂,用于生成makefile
#--prefix : 安裝目錄
#--enable-small : 優(yōu)化大小
#--disable-programs : 不編譯ffmpeg程序(命令行工具)阳掐,我們是需要獲得靜態(tài)(動(dòng)態(tài))庫(kù)。
#--disable-avdevice : 關(guān)閉avdevice模塊冷蚂,此模塊在android中無用
#--disable-encoders : 關(guān)閉所有編碼器 (播放不需要編碼)
#--disable-muxers : 關(guān)閉所有復(fù)用器(封裝器)缭保,不需要生成mp4這樣的文件,所以關(guān)閉
#--disable-filters :關(guān)閉視頻濾鏡
#--enable-cross-compile : 開啟交叉編譯
#--cross-prefix: gcc的前綴 xxx/xxx/xxx-gcc 則給xxx/xxx/xxx-
#disable-shared enable-static 不寫也可以蝙茶,默認(rèn)就是這樣的艺骂。
#--sysroot:
#--extra-cflags: 會(huì)傳給gcc的參數(shù)
#--arch --target-os : 必須要給
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/arm-linux-androideabi- \
--disable-shared \
--enable-static \
--sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-arm \
--extra-cflags="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC" \
--arch=arm \
--target-os=android
#上面運(yùn)行腳本生成makefile之后,使用make執(zhí)行腳本
make clean
make install
執(zhí)行編譯腳本build.sh
- 首先需要給腳本加上可執(zhí)行權(quán)限:
chmod +x build.sh
- 執(zhí)行shell腳本:
./build.sh
- 編譯結(jié)束后會(huì)將編譯的靜態(tài)庫(kù)放在 android/armeabi-v7a 目錄下隆夯。
也可以將靜態(tài)庫(kù)打包成一個(gè)so庫(kù)
cd lib export CC=/root/android-ndk-r17c/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-gcc export AA="--sysroot=/root/android-ndk-r17c/platforms/android-17/arch-arm/" $CC $AA -shared -o libffmpeg.so -Wl,--whole-archive *.a -Wl,--no-whole-archive
編譯集成librtmp
下載編譯librtmp
源碼下載此處省略钳恕,編譯librtmp的腳本如下:
#!/bin/bash
NDK_ROOT=/root/android-ndk-r17c
CPU=arm-linux-androideabi
TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64
export XCFLAGS="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=17"
export XLDFLAGS="--sysroot=${NDK_ROOT}/platforms/android-17/arch-arm "
export CROSS_COMPILE=$TOOLCHAIN/bin/arm-linux-androideabi-
make install SYS=android prefix=`pwd`/install CRYPTO= SHARED= XDEF=-DNO_SSL
由于ffmpeg 默認(rèn)開啟librtmp需要pkgconfig别伏,這里我們手動(dòng)關(guān)閉,修改ffmpeg的configure文件:
注釋掉6256行忧额,簡(jiǎn)單粗暴:
6254 enabled libpulse && require_pkg_config libpulse libpulse pulse/pulseaudio.h pa_context_new
6255 enabled librsvg && require_pkg_config librsvg librsvg-2.0 librsvg-2.0/librsvg/rsvg.h rsvg_handle_render_cairo
6256 #enabled librtmp && require_pkg_config librtmp librtmp librtmp/rtmp.h RTMP_Socket
6257 enabled librubberband && require_pkg_config librubberband "rubberband >= 1.8.1" rubberband/rubberband-c.h rubberband_new -lstdc++ && app end librubberband_extralibs "-lstdc++"
修改ffmpeg編譯腳本厘肮,這里將前面腳本copy一份重命名 build_ffmpeg_with_librtmp.sh
來進(jìn)行修改:
#!/bin/bash
NDK_ROOT=/root/android-ndk-r17c
CPU=arm-linux-androideabi
TOOLCHAIN=$NDK_ROOT/toolchains/$CPU-4.9/prebuilt/linux-x86_64
ANDROID_API=17
PREFIX=./build_outputs/armeabi-v7a/ffmpeg_rtmp
#rtmp路徑
RTMP=/root/he/ffmpeg/librtmp/install
./configure \
--prefix=$PREFIX \
--enable-small \
--disable-programs \
--disable-avdevice \
--disable-encoders \
--disable-muxers \
--disable-filters \
--enable-librtmp \
--enable-cross-compile \
--cross-prefix=$TOOLCHAIN/bin/$CPU- \
--disable-shared \
--enable-static \
--sysroot=$NDK_ROOT/platforms/android-$ANDROID_API/arch-arm \
--extra-cflags="-isysroot $NDK_ROOT/sysroot -isystem $NDK_ROOT/sysroot/usr/include/arm-linux-androideabi -D__ANDROID_API__=$ANDROID_API -U_FILE_OFFSET_BITS -DANDROID -ffunction-sections -funwind-tables -fstack-protector-strong -no-canonical-prefixes -march=armv7-a -mfloat-abi=softfp -mfpu=vfpv3-d16 -mthumb -Wa,--noexecstack -Wformat -Werror=format-security -O0 -fPIC -I$RTMP/include" \
--extra-ldflags="-L$RTMP/lib" \
--extra-libs="-lrtmp" \
--arch=arm \
--target-os=android
make clean
make install