TS 檔案格式解析
https://blog.csdn.net/cabbage2008/article/details/49281729
TS 流都是固定等長的188位元組包
如下圖所示 用UltraEdit開啟的一個TS流,我們發現每隔188個位元組就有一個47(可以看做是包頭)
TS的包頭佔用四個位元組
以第一個包為例:
47 60 00 10 00 00 B0 0D 00 00 C1 00 00 00 01 E0
81 0C 8C BE 32 FF FF ……………………………..
………………………………………………………
………………………………………………………
………………………………….FF
我們將其按照位進行劃分 (0~31位,共4個位元組 32位)
1. 0~7 位: 同步位置 第一個位元組 如 十六進位制 47 (01000111)
2. 8~10 位: 第9位是有效載荷單元起始符:(1表示起始符 0 表示後續資料) 一個TS包是188位元組 而一幀資料遠遠大於188位元組 所以一幀資料被拆分成多個TS包。
起始符為1 的表示該幀的第一個TS包 裡面含有當前幀的描述資訊 PTS(Presentation Time
Stamp)表示該幀資料的時間位置以及當前幀含有的資料量(TS包個數,大部分不描述
用0代替)
起始符為0的TS包 存放當前幀的剩餘資訊
0: 二進位制 0000 (有效載荷單元起始符 為0) 這裡借用了PID一位
4: 二進位制 0100 (有效載荷單元起始符 為1) 這裡借用了PID一位
6: 二進位制 0110 (有效載荷單元起始符 為1) 這裡借用了PID一位
3. 11~23位:PID(packet ID) 是每個節目的唯一標識 如當前為 0 0 0 (第一個包為 000)(除了pid=000 標識第一個包 其它數字都是隨機可選的 無須按某種序列排序)
4. 24~27位:四位剛好可以用一個16進位制數字標識 這裡表示其負載型別 (其存放有效資料) 當前為1 表示負載中只有有效載荷
0:保留值,供未來使用 (碰到丟棄即可)
1:負載中只有有效載荷
2:負載中只有自適應欄位
3:先有自適應欄位,再有有效載荷
自適應欄位長度, 佔一個位元組
自適應欄位內容,佔得位元組由長度自適應欄位長度決定,多餘的位元組用0xFF填充
5.28~31位:無須考慮 直接跳過 簡單理解為相同PID的順序碼
PES (Packetized Elementary Stream) 打包的元流 簡單說一個個PES包去掉PES包頭剩下的就是一幀幀的資料
有效載荷單元起始符 為1 的TS包會含有部分PES包頭
一個TS流由一組組188位元組的包組成
所有的事務都是有始有終,如何尋找第一個TS包將是我們本節的主題。
如圖所示,一般來說第一個TS包一般在第一個位置,本例舉出一個特殊情況
在尋找第一個TS包時,不斷讀取TS包,直到找到pid=000的位置,並將讀取過的TS包置入緩衝區
本節將粗略講述在確定好第一個包位置後如何找後續包
一個TS流如下圖所示:
第一個TS包
47 60 00 10 00 00 B0 0D 00 00 C1 00 00 00 01E0
81 0C 8C BE 32 FF FF ……………………………..
………………………………………………………
………………………………………………………
………………………………….FF
包頭:47 60 00 10
指標:00
tableid:00
固定值:B
section_length:0 0D(值:13)
transport_stream_id:00 00
version number & current_next_indicator:C1
section_number:00
last_section_number:00
program_number:00 01
program_map_PID:E081 (PMT的pid為081 前三位為保留位)
CRC_32:0C 8C BE 32
第二個TS包
47 60 81 10 (47 同步位元組 6 說明資料正確 pid = 081 1 負載中只含有有效載荷)
00 02 B0 17 00 01 C1 00 00 E8 10 F0 00 1B E8 10F0 00 03 E8 14 F0 00 66 74 A4 2D FF FF FF FF FF
...................................................................................
...................................................................................
...................................................................................
.......................................................................FF
包頭:47 60 81 10 (47 同步位元組 6 說明資料正確 pid = 081 1 負載中只含有有效載荷)
指標:00
tableid:02
固定值:B
section_length:0 17(值:23 表示到後面FF總共有23個位元組)program_number:00 01
reserved&version_number¤t_next_indicator:C1
section_number:00
last_section_number:00
PCR_PID:E8 10
program_info_length: F0 00 (前四位不算 後12位表示後面節目描述資訊長度 此處無)
此時剩餘23-9=14位元組-4位元組(CRC) = 10位元組/5 = 2 N=2 此處有兩個流型別
第一流型別:
stream_type: 1B H264流
elementary_PID:E8 10 前3位為保留位取後13位 則PID=810 表示此PID的都是H264流
ES_info_length:F0 00 前4位為保留位 後12位為描述資訊長度 此處為0
第二流型別:
stream_type: 03 音訊流
elementary_PID:E8 14 前3位為保留位取後13位 則PID=814 表示此PID的都是音訊流
ES_info_length:F0 00 前4位為保留位 後12位為描述資訊長度 此處為0
CRC: 66 74 A4 2D
03 E8 14 : 03 表示流是音訊流 MP3 格式 814 表示 pid=814 的TS包儲存的是MP3格式的音訊流
1B E8 10: 1B表示流是視訊流h264格式 810 表示 pid=810 的TS包儲存的是h264格式的視訊流
第一個TS包 一般叫做 PAT (Program Association Table,節目相關表)
第二個TS包 一般叫做PMT (Program Map Table,節目對映表)
第三個TS包
00000170h: 47 48 14 10 00 00 01 C0 (PTD 為814 前面 4 說明含有有效載荷起始符為1 含有PES包頭)
00000180h: 01 88 80 80 05 21 00 01 96 07 FF FD 85 00 33 22
00000190h: 22 11 22 11 11 11 11 11 11 24 82 41 00 90 40 00
000001a0h: 00 00 00 00 40 00 .................................................
...............................................................................
................................................................................
00000220h: 70 34 5B CE 64 B7 D2 F5 4E 07 50 8E 11 1E 60 61
00000230h: 21 32 11 59
第四個TS包
00000230h: 47 08 14 11 68 4D 8C CB A7 24 92 45 (PTD 為814 前面為 0 說明有效載荷起始符為0 不含有PES包頭)
00000240h: B8 EE A7 1C C4 ……………………………….
…………………………………………………………………….
…………………………………………………………………….
000002e0h:C8 31 B5 59 8C B7 3A 7B 53 9D AB 73 54 E6 D8 0D
47(同步位元組)0(0 說明有效載荷起始符為0 不含有PES包頭)
814PID 1 (負載中只有有效載荷,沒有自適應欄位,後面的都是一幀資料 本例為MP3(由第二個TS包知道))
第五個TS包
000002f0h:47 08 14 32 99 00 FF FF FF FF FF FF FF FF FF FF
00000300h:FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF FF
…………………………………………………………………….
…………………………………………………………………….
…………………………………………………………………….
00000380h:FF FF FF FF FF FF FF FF FF FF FF FF FF FF 52 DE
00000390h:E6 B5 D0 76 CD CB B2 24 B3 92 AD 4E CD 19 D2 CC
000003a0h:82 D4 78 10 80 6C 0E 99 49 A4 59 C0
47(同步位元組)0(0 說明有效載荷起始符為0 不含有PES包頭)
814PID 3 (先有自適應欄位,再有有效載荷)
自適應欄位長度: 0x 99 表示佔用 153個位元組
00: 各個指示器都為0 表示不含其它資訊
跳到第153個位元組 到52 開始時真正的幀資料
第六個TS包
000003a0h: 47 48 14 13
000003b0h:00 00 01 C0 01 88 80 80 05 21 00 01 A6 E7 FF FD
000003c0h:85 00 54 44 22 22 34 21 12 11 22 22 21 48 90 00
....................................................................................................
....................................................................................................
....................................................................................................
00000460h:B4 12 54 02 48 19 F3 D8
47(同步位元組)4(4 說明含有有效載荷起始符為1 含有PES包頭)
814PID 1 (負載中只有有效載荷,沒有自適應欄位,後面的都是一幀資料 本例為MP3(由第二個TS包知道))
注意: 本TS包 又包含PES頭資訊 說明開始下一幀
第七個TS包
00000460h: 47 48 10 30 07 10 00 00
00000470h:01 0F 7E 88 00 00 01 E0 00 00 80 C0 0A 31 00 01
00000480h:96 07 11 00 01 7E 91 00 00 00 01 67 4D 40 1E 96
…………………………………………………………………
…………………………………………………………………
…………………………………………………………………
00000520h:D2 99 71 F3
47(同步位元組)4(4 說明含有有效載荷起始符為1 含有PES包頭)
810PID 3 (先有自適應欄位,再有有效載荷,後面的都是一幀資料 本例為h264(由第二個TS包知道) 流ID E0
自適應欄位長度, 0x07 說明後面7個位元組後為PES包頭或者h264資料
第八個TS包
00000520h: 47 08 10 11 64 C9 FC 5A 40 40 BD 8C
……………………………………………………………………
……………………………………………………………………
…………………………………………………………………….
000005d0h:18 91 2F 18 98 2D B2 AF EE 0E 3D 53 FB B2 91 FE
47(同步位元組)0(0 說明有效載荷起始符為0 不含有PES包頭)
810PID 1 (負載中只有有效載荷,沒有自適應欄位,後面的都是一幀資料 本例為h264(由第二個TS包知道))
1. 首先找到PID為0x00的TS包,找到裡面的節目對映表(PMT)PID,因為可能有幾個節目資訊。所以可能有幾個PMT_PID,以一個為例
2.接著查詢該PMT_PID的TS包,通常就緊接著。在該PMT包中找音訊和視訊的PID。以視訊為例。
3.開始提取一幀ES資料“
3.1 查詢視訊PID的TS包
3.2 找PES包頭,方法:TS包頭第2個位元組的高6位(有效載荷單元起始指示符)為1的TS包,跳過自適應欄位,找到PES包頭,提取時間戳,再跳至ES資料,這就是一幀ES資料的開始部分。
3.3 查詢有效載荷單元起始指示符為0的TS包。跳過TS包頭,跳過自適應欄位,提取後面的ES資料
3.4 同3.3接著查詢
3.5 當碰到有效載荷單元起始指示符又變為1的視訊TS包,就知道這是下一幀的開始了,將前面的所有ES資料組合成一幀資料。開始下一輪組幀。