一、FFmpeg 相關術語
1. 容器/文件(Container/File):即特定格式的多媒體文件,比如MP4,flv,mov等。
2. 媒體流(Stream):表示在時間軸上的一段連續的數據,比如一段聲音數據、一段視頻數據或者一段字母數據,可以是壓縮的,也可以是非壓縮的,壓縮的數據需要關聯特定的編解碼器。
3. 數據幀/數據包(Frame/Packet):通常一個媒體流是由大量的數據幀組成的,對於壓縮數據,幀對應着編解碼器的最小處理單元,分屬於不同媒體流的數據幀交錯存儲與容器之中。
4. 編解碼器:編解碼器是以幀為單位實現壓縮數據和原始數據之間的相互轉換的。
前面介紹的術語,就是FFmpeg中抽象出來的概念。其中:
1. AVFormatContext:就是對容器或者媒體文件層次的抽象。
2. AVStream:在文件中(容器里面)包含了多路流(音頻流、視頻流、字幕流),AVStream 就是對流的抽象。
3. AVCodecContext 與 AVCodec:在每一路流中都會描述這路流的編碼格式,對編解碼器格式以及編解碼器的抽象就是AVCodecContext 與 AVCodec。
4. AVPacket 與 AVFrame:對於編碼器或者解碼器的輸入輸出部分,也就是壓縮數據以及原始數據的抽象就是AVPacket與AVFrame。
5. AVFilter:除了編解碼之外,對音視頻的處理肯定是針對於原始數據的處理,也就是針對AVFrame的處理,使用的就是AVFilter。
二、FFmpeg 通用 API 分析
1. av_register_all 分析
在最開始編譯FFmpeg的時候,我們做了一個configure的配置,其中開啟或者關閉了很多選項。configure的配置會生成兩個文件:config.mk和config.h。
- config.mk:就是makefile文件需要包含進去的子模塊,會作用在編譯階段,幫助開發者編譯出正確的庫。
- config.h:作用在運行階段,主要是確定需要注冊那些容器及編解碼格式到FFmpeg框架中。
調用 av_register_all 就可以注冊config.h里面開發的編解碼器,然后會注冊所有的Muxer和Demuxer(封裝格式),最后注冊所有的Protocol(協議)。
這樣在configure時開啟或者關閉的選項就作用到了運行時,該函數的源碼分析設計的源碼文件包括:url.c、allformats.c、mux.c、format.c 等文件。已經將這幾個源碼文件單獨提出來了,並放在百度網盤上了,地址:https://pan.baidu.com/s/1p8-ish6oeRTaUs84juQtHg。
2. av_find_codec 分析
這個方法包含了兩部分的內容:一部分是尋找解碼器,一部分是尋找編碼器。其實在av_register_all的函數執行時,就已經把編碼器和解碼器都存放到一個鏈表中了。這里尋找編解碼器就是從上一步構造的鏈表中遍歷,通過Codec的ID或者name進行條件匹配,最終返回對於的Codec。
3. avcodec_open2 分析
該函數是打開編解碼器(Codec)的函數,無論是編碼過程還是解碼過程,都會用到這個函數。該函數的輸入參數有三個:第一個是AVCodecContext,解碼過程由FFmpeg引擎填充,編碼過程由開發者自己構造,如果想傳入私有參數,則為它的priv_data設置參數;第二個參數是上一步通過av_find_codec尋找出來的編解碼器(Codec);第三個參數一般傳NULL。
4. avcodec_close 分析
如果理解了avcodec_open,那么對應的close就是一個逆過程,找到對應的實現文件中的close函數指針所只指向的函數,然后該函數會調用對應第三方庫的API來關閉掉對應的編碼庫。
三、總結
本文主要是講述了FFmpeg的相關術語,並講解了一下通用的API的分析,不難看出其實FFmpeg所做的事情就是透明化所有的編解碼庫,用自己的封裝來為開發者提供統一的接口。開發者使用不同的編碼庫時,只需要指明要用哪一個即可,這也充分體現了面向對象編程中的封裝特性