學習總結——player(播放器)相關知識

聲明:

        前聲明一下,本文屬於個人學習總結,同時也是對自己最近學習的回顧,由於在較短的時間裏我不可能對player有這麼深刻的瞭解,所以如果您發現那裏有錯誤了,請您指正。同時建議對player有興趣的同學可以看一下雷神的CSDN博客,我看的很多內容是從他那裏瞭解到的。他的博客地址爲:https://blog.csdn.net/leixiaohua1020/article/details/15811977

player簡介:

1. 解協議

        我們在很多的時候會用到player,例如我們播放一個視頻,聽一首歌,以及看一些動態的圖片,這些都離不開player。那好我想問一下大家播放的視頻或者歌是從哪裏來的那?或者我們看到的視頻以及歌是從網上直接播放的還是使用本地播放器播放的網絡視頻,還可能是我們在本地播放本地的視頻。而不管是以哪種形式播放視頻都應該知道這種視頻是一種以什麼格式存放的,我們稱之爲容器,即存放視頻(這裏的視頻是廣義的視頻,既包含視頻也包含音頻)的東西。而通過網絡形式觀看的視頻我們在獲得他的文件格式之前還要先確定這個網絡是採用一種什麼樣的協議來傳輸這個視頻文件的,而從網絡文件到視頻文件的這個過程我們稱之爲解協議(可能有些人會驚訝:還要解協議啊,對我的回答是要的)。在網絡中信息的傳遞是以包的形式來傳播的,而在對於信息,每多一層協議他的外面就多一層協議相關的層。我們稱這個過程爲加包,而對於接收方在收到網絡信息後會對其進行解協議的操作,並從中提取發送方要發送的信息。這裏我們從網絡中獲得視頻文件同樣要經歷上面的過程。同時由於網絡中有很多種網絡傳輸的協議而不同的文件協議需要與之對應的方式解協議。而在代碼中則可以表示爲:每種協議對應一種URLProtocol結構體,通過找與網絡文件向對應的URLProtocol結構體來實現對網絡文件的解協議。

2. es,pes,ps,ts

        在MPEG-2系統中,信息複合/分離的過程稱爲系統復接/分接,由視頻,音頻的ES流和輔助數據復接生成的用於實際傳輸的標準信息流稱爲MPEG-2傳送流(TS:TransportStream)。
據傳輸媒體的質量不同,MPEG-2中定義了兩種複合信息流:傳送流(TS)和節目流(PS:ProgramStream)
TS流與PS流的區別在於TS流的包結構是固定長度的,而PS流的包結構是可變長度的。
PS包與TS包在結構上的這種差異,導致了它們對傳輸誤碼具有不同的抵抗能力,因而應用的環境也有所不同。TS碼流由於採用了固定長度的包結構,當傳輸誤碼破壞了某一TS包的同步信息時,接收機可在固定的位置檢測它後面包中的同步信息,從而恢復同步,避免了信息丟失。而PS包由於長度是變化的,一旦某一 PS包的同步信息丟失,接收機無法確定下一包的同步位置,就會造成失步,導致嚴重的信息丟失。因此,在信道環境較爲惡劣,傳輸誤碼較高時,一般採用TS 碼流;而在信道環境較好,傳輸誤碼較低時,一般採用PS碼流。
由於TS碼流具有較強的抵抗傳輸誤碼的能力,因此目前在傳輸媒體中進行傳輸的MPEG-2碼流基本上都採用了TS碼流。

        在數字電視系統中,模擬視音頻信號按照MPEG-2的標準,經過抽樣、量化及壓縮編碼形成基本碼流ES,基本碼流ES是不分段的連續碼流。把基本碼流分割成段,並加上相應的頭文件打包形成的打包基本碼流PES,PES包和包之間可以是不連續的。在傳輸時將PES包再分段打成有固定長度188B 的傳送碼流TS或可變長度的節目流包(PS包)。PES只是PS轉換爲TS或TS轉換爲PS的中間步驟或橋樑,時MPEG-2數據流互換的邏輯結構。TS 和PS這兩種碼流分別適應於不同的場合應用,節目流PS適合在相對出錯較少的環境下使用,其長度是變化的,而傳送流TS能夠把多個節目在基於一個或多個時間標識的基礎上構成一個流,傳送流適合於出錯較多的場合下使用。用數據包傳輸的優點是:網絡中信息可佔用不同的連接線路和簡單暫存。通過數據包交織把多個數據流複用成一個新的數據流。便於解碼器按照相應順序對數據包進行靈活的整理,從而,爲數據流同步和複用奠定了基礎。MPEG-2的結構可分爲壓縮層和系統層,其中ES屬於壓縮層,PES和TS/PS屬於系統層。
在PES層,主要是在PES包頭信息中加入PTS(顯示時間標籤)和DTS(解碼時間標籤)用於視頻、音頻同步。而在TS流中,TS包頭加入了PCR(節目時鐘參考),用於解碼器的系統時鐘恢復。在節目流PS包頭中加入SCR,它的作用與PCR域相似。

 

3.解封裝

        通過上面我們知道在網絡傳輸中常用的是TS,而我在捕捉信息時也捕捉到的是mpegts。所以在下面的文章中我將以TS流爲主向大家講解。而通過上面的解協議之後就得到了視頻文件(這裏講的視頻文件同樣是廣義的),這裏的視頻文件包括我們常用的MP4,flv,以及AVI等不同格式的文件,而我們稱這些不同的視頻文件爲容器,而在這些容器中一定的規格排放着音頻文件和視頻文件(狹義的視頻文件)以及一些與視頻播放相關的信息。

        而解封裝這一步我們要做的就是從這些容器中將音頻相關的信息和視頻相關的信息提取出來,由於各種封裝格式不同,所以會用不同的解封裝方式,所以在程序中每一種封裝格式對應一個AVInputFormat結構體,在該結構體中存放着解封裝的函數。而解完封裝的視音頻信息會以一種流的形式與一種特定的AVStream結構體相對應。而通過將容器中的內容提取並保存到流中的方式稱之爲解封裝。

        在上面我們說到了流,這裏對流做一個解釋流(stream):指時間軸上的一段連續數據,如一段聲音數據,一段視頻數據或一段字幕數據,可以是壓縮的,也可以是非壓縮的,壓縮的數據需要關聯特定的編解碼器

4.視頻音頻壓縮

        上面我們說到了在流中數據可以是壓縮的也可以是非壓縮的,那麼壓縮和非壓縮的數據有什麼樣的差別那?其實最主要的還是體積。就像我們生活中的壓縮餅乾一樣,經過壓縮的數據雖然體積減少了,但是有些重要的信息並不會減少。這就是爲什麼我們要對數據進行壓縮了。那麼壓縮後的數據到底可以縮小到壓縮前的多少那?是可以達到1%的。這也是爲什麼要對數據進行壓縮了。而由於在一個視音頻文件中視頻文件的體積佔了主要的,所以對於音頻文件的體積壓縮就不是那麼重要了。但是音頻數據壓縮還是有的,例如我們常聽到的MP3。

        對於音視頻壓縮的算法,我其實並不瞭解,所以在這裏就不多說了,但是在程序中我們經常會碰到像dts或者pts一些與視頻相關的參數,所以關於這兩個參數我還是講解下。

5.I幀,p幀,b幀,以及dts和pts

以下相關內容轉載自:理解音視頻 PTS 和 DTS

I 幀(Intra coded frames):I 幀圖像採用幀內編碼方式,即只利用了單幀圖像內的空間相關性,而沒有利用時間相關性。I 幀使用幀內壓縮,不使用運動補償,由於 I 幀不依賴其它幀,所以是隨機存取的入點,同時是解碼的基準幀。I 幀主要用於接收機的初始化和信道的獲取,以及節目的切換和插入,I 幀圖像的壓縮倍數相對較低。I 幀圖像是週期性出現在圖像序列中的,出現頻率可由編碼器選擇。
P 幀(Predicted frames):P 幀和 B 幀圖像採用幀間編碼方式,即同時利用了空間和時間上的相關性。P 幀圖像只採用前向時間預測,可以提高壓縮效率和圖像質量。P 幀圖像中可以包含幀內編碼的部分,即 P 幀中的每一個宏塊可以是前向預測,也可以是幀內編碼。
B 幀(Bi-directional predicted frames):B 幀圖像採用雙向時間預測,可以大大提高壓縮倍數。值得注意的是,由於 B 幀圖像採用了未來幀作爲參考,因此 MPEG-2 編碼碼流中圖像幀的傳輸順序和顯示順序是不同的。

        也就是說,一個 I 幀可以不依賴其他幀就解碼出一幅完整的圖像,而 P 幀、B 幀不行。P 幀需要依賴視頻流中排在它前面的幀才能解碼出圖像。B 幀則需要依賴視頻流中排在它前面或後面的幀才能解碼出圖像。

        這就帶來一個問題:在視頻流中,先到來的 B 幀無法立即解碼,需要等待它依賴的後面的 I、P 幀先解碼完成,這樣一來播放時間與解碼時間不一致了,順序打亂了,那這些幀該如何播放呢?這時就需要我們來了解另外兩個概念:DTS 和 PTS。

DTS(Decoding Time Stamp):即解碼時間戳,這個時間戳的意義在於告訴播放器該在什麼時候解碼這一幀的數據。
PTS(Presentation Time Stamp):即顯示時間戳,這個時間戳用來告訴播放器該在什麼時候顯示這一幀的數據。
        需要注意的是:雖然 DTS、PTS 是用於指導播放端的行爲,但它們是在編碼的時候由編碼器生成的。

        當視頻流中沒有 B 幀時,通常 DTS 和 PTS 的順序是一致的。但如果有 B 幀時,就回到了我們前面說的問題:解碼順序和播放順序不一致了。

        比如一個視頻中,幀的顯示順序是:I B B P,現在我們需要在解碼 B 幀時知道 P 幀中信息,因此這幾幀在視頻流中的順序可能是:I P B B,這時候就體現出每幀都有 DTS 和 PTS 的作用了。DTS 告訴我們該按什麼順序解碼這幾幀圖像,PTS 告訴我們該按什麼順序顯示這幾幀圖像。

        上面說了視頻幀、DTS、PTS 相關的概念。我們都知道在一個媒體流中,除了視頻以外,通常還包括音頻。音頻的播放,也有 DTS、PTS 的概念,但是音頻沒有類似視頻中 B 幀,不需要雙向預測,所以音頻幀的 DTS、PTS 順序是一致的。

        音頻視頻混合在一起播放,就呈現了我們常常看到的廣義的視頻。在音視頻一起播放的時候,我們通常需要面臨一個問題:怎麼去同步它們,以免出現畫不對聲的情況。

        要實現音視頻同步,通常需要選擇一個參考時鐘,參考時鐘上的時間是線性遞增的,編碼音視頻流時依據參考時鐘上的時間給每幀數據打上時間戳。在播放時,讀取數據幀上的時間戳,同時參考當前參考時鐘上的時間來安排播放。這裏的說的時間戳就是我們前面說的 PTS。實踐中,我們可以選擇:同步視頻到音頻、同步音頻到視頻、同步音頻和視頻到外部時鐘。

6.解碼

        我們通過上面的操作得到了音視頻的流信息,而對於要將他們播放出來的我們下面要做的就是從上面這個流中提取一幀的數據出來,也就是提取出一張照片。當然這個時候從流中提取出來的信息也是沒有解碼的。而從流中提取出來的一小段信息我們會放在一個AVPacket的結構體中,在這個結構體中保存着一些一幀的信息。而對AVPacket中的信息解碼出來的信息我們會放在一個叫做AVFrame的結構體中,而這個結構體中的數據是沒有被壓縮的,也就是說可以將這裏面的信息發送到顯示器就是顯示出相應的圖像來。

7.input --> probe --> demux  --> decode -->  output 

        而在FFmpeg中我們常用上面這五個步驟來實現對代碼的分析,其實這個步驟與我上面 講解的步驟是相對應的。

        對於input來說其實就是將文件打開並讀入的過程, 不過這裏需要注意的是讀入並不是將整個文件全部的信息讀入,而這裏一般是讀取文件的頭部信息,因爲很多的文件會在其頭部放入很多的識別信息,而在後面放的很多就是真正的數據了,所以只要讀出這裏的信息我們就可以知道後面數據的大小格式一個重要的pts,dts等信息。

        而對上面的信息進行分析主要就是在probe中完成的,而有了上面的信息player就可以更好的找到對應的解協議,解封裝以及解碼的結構體。而當上面這些信息都找全的時候我們就可以對文件進行AV分離了。

        decode即解碼。AV分離後就需要分別對視頻和音頻數據進行解碼操作,而解完碼的數據對於視頻來說很多都是YUV或者RGB形式的,我們需要做的就是將其放到屏幕上。

參考文章:

ES TS PS 流

理解音視頻 PTS 和 DTS

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章