第三章 FFmpeg的介紹與使用

FFmpeg名稱中的mpeg來自視頻編碼標(biāo)準(zhǔn)MPEG岛抄,而前綴FF是Fast Forward的首字母縮寫别惦。

目錄

一 FFmpeg的主體結(jié)構(gòu)
二 FFmpeg命令行工具的使用
三 FFmpeg API的介紹與使用

一 FFmpeg的主體結(jié)構(gòu)
image.png

默認(rèn)的編譯會(huì)生成4個(gè)可執(zhí)行文件和8個(gè)靜態(tài)庫》蛲郑可執(zhí)行文件包括用于轉(zhuǎn)碼掸掸、推流、Dump媒體文件的ffmpeg、用于播放媒體文件的ffplay扰付、 用于獲取媒體文件信息的ffprobe堤撵,以及作為簡單流媒體服務(wù)器的ffserver

8個(gè)靜態(tài)庫其實(shí)就是FFmpeg的8個(gè)模塊羽莺,具體包括如下內(nèi)容实昨。

  • AVUtil 核心工具庫,該模塊是最基礎(chǔ)的模塊之一盐固,下面的許多
    其他模塊都會(huì)依賴該庫做一些基本的音視頻處理操作荒给。

  • AVFormat 文件格式和協(xié)議庫,該模塊是最重要的模塊之一刁卜,封 裝了Protocol層和Demuxer志电、Muxer層,使得協(xié)議和格式對于開發(fā)者來說是透明的蛔趴。

  • AVCodec 編解碼庫挑辆,該模塊也是最重要的模塊之一,封裝了 Codec層孝情,但是有一些Codec是具備自己的License的鱼蝉,F(xiàn)Fmpeg是不會(huì)默認(rèn)添加像libx264、FDK-AAC咧叭、lame等庫的蚀乔,但是FFmpeg就像一個(gè)平臺 一樣,可以將其他的第三方的Codec以插件的方式添加進(jìn)來菲茬,然后為開 發(fā)者提供統(tǒng)一的接口吉挣。

  • AVFilter 音視頻濾鏡庫,該模塊提供了包括音頻特效和視頻特效的處理婉弹,在使用FFmpeg的API進(jìn)行編解碼的過程中睬魂,直接使用該模塊為音視頻數(shù)據(jù)做特效處理是非常方便同時(shí)也非常高效的一種方式。

  • AVDevice 輸入輸出設(shè)備庫镀赌,比如氯哮,需要編譯出播放聲音或者視頻的工具ffplay,就需要確保該模塊是打開的商佛,同時(shí)也需要libSDL的預(yù)先編譯喉钢,因?yàn)樵撛O(shè)備模塊播放聲音與播放視頻使用的都是libSDL庫。

  • SwrRessample 該模塊可用于音頻重采樣良姆,可以對數(shù)字音頻進(jìn)行聲道數(shù)肠虽、數(shù)據(jù)格式、采樣率等多種基本信息的轉(zhuǎn)換玛追。

  • SWScale 該模塊是將圖像進(jìn)行格式轉(zhuǎn)換的模塊税课,比如闲延,可以將 YUV的數(shù)據(jù)轉(zhuǎn)換為RGB的數(shù)據(jù)。

  • PostProc 該模塊可用于進(jìn)行后期處理韩玩,當(dāng)我們使用AVFilter的時(shí)候需要打開該模塊的開關(guān)垒玲,因?yàn)镕ilter中會(huì)使用到該模塊的一些基礎(chǔ)函數(shù)。

比如AAC編碼找颓,常見的有兩種封裝格式

  • 一種是ADTS格式的流合愈,是AAC定義在MPEG2里面的格式
  • 另外一種是封裝在MPEG4里面的格式,這種格式會(huì)在每一幀前面拼接一個(gè)用聲道叮雳、采樣率等信息組成的頭想暗。

AACbit stream filter常常應(yīng)用在編碼的過程中。

與音頻的AAC編碼格式相對應(yīng)的是視頻中的H264編碼帘不,它也有兩種封裝格式

  • 一種是 MP4封裝的格式
  • 一種是裸的H264格式(一般稱為annexb封裝格式)

FFmpeg中也提供了對應(yīng)的bit stream filter,稱H264_mp4toannexb杨箭,可以將MP4封裝格式的H264數(shù)據(jù)包轉(zhuǎn)換為annexb封裝格式的H264數(shù)據(jù) (其實(shí)就是裸的H264的數(shù)據(jù))包寞焙。

H264bit stream filter常常應(yīng)用于視頻解碼過程中。

二 FFmpeg命令行工具的使用

ffmpeg是進(jìn)行媒體文件轉(zhuǎn)碼的命令行工具
ffprobe是用于查看媒體 文件頭信息的工具
ffplay則是用于播放媒體文件的工具

2.1 ffprobe

1.首先用ffprobe查看一個(gè)音頻的文件

ffprobe ~/Desktop/32037.mp3

2.輸出格式信息format_name互婿、時(shí)間長度duration捣郊、文件 大小size、比特率bit_rate慈参、流的數(shù)目nb_streams等呛牲。

ffprobe -show_format 32037.mp4

3.以JSON格式的形式輸出具體每一個(gè)流最詳細(xì)的信息

ffprobe -print_format json -show_streams 32037.mp4

4.顯示幀信息的命令如下:

ffprobe -show_frames sample.mp4

5.查看包信息的命令如下:

ffprobe -show_packets sample.mp4
2.2 ffplay

ffplay是以FFmpeg框架為基礎(chǔ),外加渲染音視頻 的庫libSDL來構(gòu)建的媒體文件播放器驮配。

業(yè)界內(nèi)開源的ijkPlayer其實(shí)就是基于ffplay進(jìn)行改造的播放器娘扩,當(dāng)然其做了硬件解碼以及很多兼容性的工作。

音視頻同步

在 ffplay中音畫同步的實(shí)現(xiàn)方式其實(shí)有三種壮锻。分別是

  • 音頻為主時(shí)間軸 作為同步源
  • 視頻為主時(shí)間軸作為同步源
  • 外部時(shí)鐘為主時(shí)間軸作為同步源

并且在ffplay中默認(rèn)的對齊方式也是以音頻為基準(zhǔn)進(jìn)行對齊的琐旁。

首先要聲明的是,播放器接收到的視頻幀或者音頻幀猜绣,內(nèi)部都會(huì)有時(shí)間戳(PTS時(shí)鐘)來標(biāo)識它實(shí)際應(yīng)該在什么時(shí)刻進(jìn)行展示灰殴。

實(shí)際的對齊策略如下:比較視頻當(dāng)前的播放時(shí)間和音頻當(dāng)前的播放時(shí)間

  1. 如果視頻播放過快,則通過加大延遲或者重復(fù)播放來降低視頻播放速度;
  2. 如果視頻播放慢了掰邢,則通過減小延遲或者丟幀來追趕音頻播放的時(shí)間點(diǎn)牺陶。

關(guān)鍵就在于音視頻時(shí)間的比較以及延遲的計(jì)算,當(dāng)然在比較的過程中會(huì)設(shè) 置一個(gè)閾值(Threshold)辣之,若超過預(yù)設(shè)的閾值就應(yīng)該做調(diào)整(丟幀渲染 或者重復(fù)渲染)掰伸,這就是整個(gè)對齊策略。

2.3 ffmpeg

ffmpeg就是強(qiáng)大的媒體文件轉(zhuǎn)換工具召烂。它可以轉(zhuǎn)換任何格式的媒體文件碱工,并且還可以用自己的AudioFilter以及VideoFilter進(jìn)行處理和編輯。

  1. 從MP4文件中抽取視頻流導(dǎo)出為裸H264數(shù)據(jù)
ffmpeg -i output.mp4 -an -vcodec copy -bsf:v h264_mp4toannexb output.h264
  1. 使用AAC音頻數(shù)據(jù)和H264的視頻生成MP4文件
ffmpeg -i test.aac -i test.h264 -acodec copy -bsf:a aac_adtstoasc -vcodec copy -f mp4 output.mp4
  1. 從WAV音頻文件中導(dǎo)出PCM裸數(shù)據(jù)
ffmpeg -i input.wav -acodec pcm_s16le -f s16le output.pcm
  1. 將兩路聲音進(jìn)行合并,比如要給一段聲音加上背景音樂
ffmpeg -i vocal.wav -i accompany.wav -filter_complex
           amix=inputs=2:duration=shortest output.wav
  1. 為視頻增加水印效果
ffmpeg -i input.mp4 -i changba_icon.png -filter_complex
           '[0:v][1:v]overlay=main_w-overlay_w-10:10:1[out]' -map '[out]' output.mp4
  1. 將一個(gè)YUV格式表示的數(shù)據(jù)轉(zhuǎn)換為JPEG格式的圖片
ffmpeg -f rawvideo -pix_fmt yuv420p -s 480*480 -i texture.yuv -f image2-vcodec mjpeg output.jpg
三 FFmpeg API的介紹與使用
3.1 術(shù)語
  • 容器/文件(Conainer/File) 即特定格式的多媒體文件,比如MP4flv伯襟、mov等沪蓬。

  • 媒體流(Stream) 表示時(shí)間軸上的一段連續(xù)數(shù)據(jù),如一段聲音數(shù) 據(jù)蚓庭、一段視頻數(shù)據(jù)或一段字幕數(shù)據(jù),可以是壓縮的,也可以是非壓縮的春弥,壓縮的數(shù)據(jù)需要關(guān)聯(lián)特定的編解碼器

  • 數(shù)據(jù)幀/數(shù)據(jù)包(Frame/Packet) 通常叠荠,一個(gè)媒體流是由大量的數(shù)據(jù)幀組成的匿沛,對于壓縮數(shù)據(jù),對應(yīng)著編解碼器的最小處理單元榛鼎,分屬于不同媒體流的數(shù)據(jù)幀交錯(cuò)存儲于容器之中逃呼。

  • 編解碼器 編解碼器是以為單位實(shí)現(xiàn)壓縮數(shù)據(jù)原始數(shù)據(jù)之間的相互轉(zhuǎn)換的。

3.2 名詞介紹
  • AVFormatContext就是對容器或者說媒體文件層次的一個(gè)抽象者娱。
  • AVStream 對流的抽象
  • AVCodecContextAVCodec對編解碼格式以及編解碼器的抽象
  • AVPacketAVFrame對于編碼器或者解碼器的輸入輸出部分抡笼,也就是壓縮數(shù)據(jù)以及原始數(shù)據(jù)的抽象。
  • AVFilter對于音視頻的處理肯定是針對于原始數(shù)據(jù)的處理黄鳍,也就是針對于AVFrame的處理推姻。
3.3 實(shí)例

接下來介紹一個(gè)解碼的實(shí)例,該實(shí)例實(shí)現(xiàn)的功能非常單一框沟,就是把一個(gè)視頻文件解碼成單獨(dú)的音頻PCM文件和視頻YUV文件藏古。

  1. 引用頭文件
  2. 注冊協(xié)議、格式與編解碼器
avformat_network_init();
av_register_all();
  1. 打開媒體文件源街望,并設(shè)置超時(shí)回調(diào)
  2. 尋找各個(gè)流校翔,并且打開對應(yīng)的解碼器
  3. 初始化解碼后數(shù)據(jù)的結(jié)構(gòu)體
    分配出解碼之后的數(shù)據(jù)所存放的內(nèi)存空間,以及進(jìn)行格式轉(zhuǎn)換需要用到的對象
  4. 讀取流內(nèi)容并且解碼
    打開了解碼器之后灾前,就可以讀取一部分流中的數(shù)據(jù)(壓縮數(shù)據(jù))防症,然后將壓縮數(shù)據(jù)作為解碼器的輸入,解碼器將其解碼為原始數(shù)據(jù)(裸數(shù)據(jù))哎甲,之后就可以將原始數(shù)據(jù)寫入文件了蔫敲。
  5. 處理解碼后的裸數(shù)據(jù)
    解碼之后會(huì)得到裸數(shù)據(jù),音頻就是PCM數(shù)據(jù)炭玫,視頻就是YUV數(shù)據(jù)
  6. 關(guān)閉所有資源
四 FFmpeg源碼結(jié)構(gòu)
4.1 libavformat
image.png

AVFormatContext是API層直接接觸到的結(jié)構(gòu)體奈嘿,它會(huì)進(jìn)行格式的封 裝與解封裝。

4.2 libavcodec
image.png

該結(jié)構(gòu)體包含的就是與實(shí)際的編解碼有關(guān)的部分吞加。

3.3 FFmpeg通用API分析

3.3.1 av_register_all
所以該函數(shù)的內(nèi)部實(shí)現(xiàn)會(huì)先調(diào)用avcodec_register_all來注冊所有config.h里面開放的編解碼器裙犹,然后會(huì)注冊所有的MuxerDemuxer(也就是封裝格式)尽狠,最后注冊所有的Protocol(即協(xié)議層的東西)。

3.3.2 av_find_codec
這里面其實(shí)包含了兩部分的內(nèi)容:一部分是尋找解碼器叶圃,一部分是尋找編碼器袄膏。

3.3.3 avcodec_open2
該函數(shù)是打開編解碼器(Codec)的函數(shù),無論是編碼過程還是解碼過程掺冠,都會(huì)用到該函數(shù)沉馆。

3.4 調(diào)用FFmpeg解碼時(shí)用到的函數(shù)分析

avformat_open_input
根據(jù)所提供的文件路徑判斷文件的格 式,其實(shí)就是通過這一步來決定使用的到底是哪一個(gè)Demuxer德崭。

avformat_find_stream_info
該方法的作用就是把所有StreamMetaData信息填充好斥黑。

av_read_frame
使用該方法讀取出來的數(shù)據(jù)是AVPacket

對于音頻流眉厨,一個(gè)AVPacket可能包含個(gè)AVFrame锌奴,但是對于視頻流,一個(gè)AVPacket只包含個(gè)AVFrame憾股,該函數(shù)最終只會(huì)返回一個(gè)AVPacket結(jié)構(gòu)體缨叫。

avcodec_decode
該方法包含了兩部分內(nèi)容:一部分是解碼視頻,一部分是解碼音頻荔燎,解碼是會(huì)委托給對應(yīng)的解碼器來實(shí)施的。

avformat_close_input
該函數(shù)負(fù)責(zé)釋放對應(yīng)的資源销钝。

3.5 調(diào)用FFmpeg編碼時(shí)用到的函數(shù)分析

avformat_alloc_output_context2
該函數(shù)內(nèi)部需要調(diào)用方法avformat_alloc_context來分配一個(gè) AVFormatContext結(jié)構(gòu)體有咨。

avio_open2
編碼的階段了,開發(fā)者需要將手動(dòng)封裝好的AVFrame結(jié)構(gòu)體蒸健,作為avcodec_encode_video方法的輸入座享,將其編碼成為AVPacket,然后調(diào)用av_write_frame方法輸出到媒體文件中似忧。


本文參考音視頻開發(fā)進(jìn)階指南


項(xiàng)目源碼地址 - FFmpegDecoder


最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末渣叛,一起剝皮案震驚了整個(gè)濱河市,隨后出現(xiàn)的幾起案子盯捌,更是在濱河造成了極大的恐慌淳衙,老刑警劉巖,帶你破解...
    沈念sama閱讀 212,884評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件饺著,死亡現(xiàn)場離奇詭異箫攀,居然都是意外死亡,警方通過查閱死者的電腦和手機(jī)幼衰,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,755評論 3 385
  • 文/潘曉璐 我一進(jìn)店門靴跛,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人渡嚣,你說我怎么就攤上這事梢睛》视。” “怎么了?”我有些...
    開封第一講書人閱讀 158,369評論 0 348
  • 文/不壞的土叔 我叫張陵绝葡,是天一觀的道長深碱。 經(jīng)常有香客問我,道長挤牛,這世上最難降的妖魔是什么莹痢? 我笑而不...
    開封第一講書人閱讀 56,799評論 1 285
  • 正文 為了忘掉前任,我火速辦了婚禮墓赴,結(jié)果婚禮上竞膳,老公的妹妹穿的比我還像新娘。我一直安慰自己诫硕,他們只是感情好坦辟,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,910評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著章办,像睡著了一般锉走。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上藕届,一...
    開封第一講書人閱讀 50,096評論 1 291
  • 那天挪蹭,我揣著相機(jī)與錄音,去河邊找鬼休偶。 笑死梁厉,一個(gè)胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的踏兜。 我是一名探鬼主播词顾,決...
    沈念sama閱讀 39,159評論 3 411
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼碱妆!你這毒婦竟也來了肉盹?” 一聲冷哼從身側(cè)響起,我...
    開封第一講書人閱讀 37,917評論 0 268
  • 序言:老撾萬榮一對情侶失蹤疹尾,失蹤者是張志新(化名)和其女友劉穎上忍,沒想到半個(gè)月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體航棱,經(jīng)...
    沈念sama閱讀 44,360評論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡睡雇,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,673評論 2 327
  • 正文 我和宋清朗相戀三年,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了饮醇。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片它抱。...
    茶點(diǎn)故事閱讀 38,814評論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡,死狀恐怖朴艰,靈堂內(nèi)的尸體忽然破棺而出观蓄,到底是詐尸還是另有隱情混移,我是刑警寧澤,帶...
    沈念sama閱讀 34,509評論 4 334
  • 正文 年R本政府宣布侮穿,位于F島的核電站歌径,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏亲茅。R本人自食惡果不足惜回铛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,156評論 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望克锣。 院中可真熱鬧茵肃,春花似錦、人聲如沸袭祟。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,882評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽巾乳。三九已至您没,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間胆绊,已是汗流浹背氨鹏。 一陣腳步聲響...
    開封第一講書人閱讀 32,123評論 1 267
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留压状,地道東北人喻犁。 一個(gè)月前我還...
    沈念sama閱讀 46,641評論 2 362
  • 正文 我出身青樓,卻偏偏與公主長得像何缓,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個(gè)殘疾皇子还栓,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,728評論 2 351

推薦閱讀更多精彩內(nèi)容