1. 程式人生 > >TS流檔案分析流程

TS流檔案分析流程

轉載自:http://blog.csdn.net/a1875566250/article/details/40615473

1、查詢PAT表,從PAT表裡面找到所有的PMT表的map_id。

 - 注意1:PAT表並不一定在檔案的起始位置,TS流這種對於電視直播的Live流需要保證在任何時間開啟電視你都能看到畫面,所以PAT表是被隨機插到TS流的Packet中的,比如間隔10幀插一個PAT表和PMT表。所以TS流檔案的第一個TS Packet可能是一個PES包,但是這個PES包更可能是續包,它沒有解碼器需要的Header,所以這種包可以在播放中被忽略,因為它可能是錄製前一幀的I、P、B包的一個斷包,根本解碼不出資料;

 - 注意2:記得檢測current_next_indicator這個flag,如果這個flag被置1,則忽略本次讀到的這個PAT包,繼續往下搜尋PAT包;
 - 注意3:如果PAT包因為容納的PMT的map_id很多,一個TS Packet的188個位元組或許放不完,則last_section_number不是0了,你得根據當前的section_number(第一個是0),然後不斷的搜尋下去,把TS Packet去掉頭後的資料組合成一個完整的PAT表;

2、查詢PMT表,建立流id表。
 在通過PAT表找到所有的PMT表的id後,則需要開始繼續跑檔案,查詢PMT表了,一般情況下,PMT表在TS檔案中的位置跟在PAT表的後面,但是也有不同
,所以我推薦在查詢PAT表完成後,把指標Seek到檔案的0位置,從頭開始查詢PMT表。這樣可能能更快的找到PMT表也說不定,當然你用當前的位置繼續向下找PMT表也是沒問題的。
 - 注意1:PMT表也有跟PAT表一樣的分段特性,一樣檢查last_section_number這個是不是有情況。也有current_next_indicator的特性,都得檢查;
 - 注意2:當PAT表裡提供了多張PMT表的id後,則表明檔案是一個多視訊、多音訊流混合的檔案;

3、通過流id,查詢檔案中的TS Packet。
 在搜尋完所有PMT表後,儲存其中的流型別和流id,此時我們有一張表,表裡儲存了所有的視訊流id和音訊流id,下面我們把檔案指標Seek到0,我們開始一點點的查詢TS Packet。在這之前有一些需要注意的地方:

 - 確定你要播放的視訊和音訊流:因為檔案中可能有多個視訊、音訊流,並且這些流的編碼也不同,比如日本的電視在播放時會用1080i的MPEG2和240P+360P的H264同時傳輸,這樣錄製下來的TS流則會有3個視訊流(id),並且音訊也是傳輸3條,也就是有6條流,但是我們在PC或者碟機中播放的時候,一般都是播放一條視訊和一條音訊,則我們必需根據使用者選擇播放那條視訊和音訊(如果你希望讓使用者選擇的話),比如我們希望播放MPEG2的視訊,所以在不斷的跑讀TS Packet的過程中,我們要忽略掉除了MPEG2流的視訊id,那些全部Skip即可,音訊同理。
 - 如何查詢一個音訊\視訊幀的頭,以及它的長度:這個問題也比較簡單,在跑TS Packet的過程中,找到PES包,如果TS頭表明payload_unit_start_indicator為1,則這個PES包此流id的某一幀起始包,去掉PES頭後的ES流就是編碼後的流的起始資料。而後面的針對這條流的PES包,只要沒有payload_unit_start_indicator標誌,都是這個包的續包,這些續包把頭去掉後,跟上一個包的資料組合起來,就一個編碼後的ES資料。
   這裡有一個需要注意的,在找到一個包表明它是payload_unit_start_indicator後,往下查詢可能會查詢到其他流id的payload_unit_start_indicator的PES包。。。要分別組合。

4、如何計算TS流的PTS\DTS。
 PES\PCR中的PTS(DTS) / 90000即可。

5、如何計算TS檔案的時間長度。
 (最後一個PCR的Time - 第一個PCR的Time) / 90000。

6、如何在TS檔案中進行隨機訪問播放。
 計算出時間後,再計算rate,然後對Io進行Seek,Seek後,查詢流的PES包,確定這個包是起始包(payload_unit_start_indicator),然後最重要的,確定這個包是I幀,不是的話繼續查詢下一個PES包。

7、如何得到TS檔案中ES流的視訊資訊、音訊資訊。
 視訊:解析H264的SPS,解析MPGE2的Header等。
 音訊:解析AAC的ADTS,解析LPCM的HDMV Header等。
 也就是說,要想知道這些流的資訊,最好的辦法就是把他們的第一幀扔給解碼器,但是這樣是一個浪費時間的活,而我們只需要解析他們的頭就能知道資訊,所以自己加一個輕量的Parser即可,或者從解碼器的程式碼裡面摳。