1.PS封裝介紹
MPEG2-PS是一種多路復用數字音頻,視頻等的封裝容器。PS是Program Stream(程序流或節目流)的簡稱。程序流
將一個或多個分組但有共同的時間基准的基本數據流(PES)合並成一個整體流。它是為可靠穩定的儲存媒介如光盤
而設計的。
一般來說,采用MPEG2-HD格式的高清數碼攝像機一般以"MPEG2-PS"來保存文件;而采用AVCHD格式的高清攝像機則
通常以".M2TS"或".MTS"保存文件。
此處介紹的PS封裝方式需要支持MPEG2/MPEG4/H.264等視頻和MPEG系列音頻,可以被大部分支持ps和相應元素流解碼
的播放器正常播放,支持在多個層次加入私有數據,方便解碼,拖動和減少延時。
具體可參考《ISO.IEC-13818-1》
1).名詞解釋
PES:Packetized Elementary Stream,封裝元素流,PS數據的基本單位。
GOP:Group Of Picture,圖像組,一般指I幀及其后面依靠該I幀編碼的其他幀。
PSH:Program Stream pack Header ,是PS包的包頭,主要包含系統時間信息。
//PSM:program stream map,節目流映射提供了關於節目流中原始流以及它們之間相互關系的描述。作為一個PES分組出現。
2).PS流的基本結構:
PS GOP|PS GOP|PS GOP
其中PS GOP包含:
Video I Frame|Audio Frames|Private Data|...|Video P/B Frame|...
其中Video I Frame包含:
PSH|PSM|Video PES|Video PES|...
其中Video P/B Frame包含:
PSH|Video PES|Video PES|...
其中Video PES包含:
PES Header|PES Payload
其中Audio Frames包含:
Audio PES|Audio PES|...
3).PS 封裝
PS 封裝按照ISO.IEC-13818-1標准
針對H264 做如下PS 封裝:每個IDR NALU 前一般都會包含SPS、PPS 等NALU,因此將SPS、PPS、IDR 的NALU 封裝為一個PS 包,包括ps 頭,然后加上PS system header,PS system map,PES header+h264 raw data。
所以一個IDR NALU PS 包由外到內順序是:PSheader| PS system header | PS system Map | PES header | h264 raw data。對於其它非關鍵幀的PS 包,就簡單多了,直接加上PS頭和PES 頭就可以了。
順序為:PS header | PES header | h264raw data。以上是對只有視頻video 的情況,如果要把音頻Audio也打包進PS 封裝,也可以。
當有音頻數據時,將數據加上PES header 放到視頻PES 后就可以了。順序如下:PS 包=PS頭|PES(video)|PES(audio),再用RTP 封裝發送就可以了。
GB28181 對RTP 傳輸的數據負載類型有規定(參考GB28181 附錄B),負載類型中96-127,RFC2250 建議96 表示PS 封裝,建議97 為MPEG-4,建議98 為H264
即我們接收到的RTP 包首先需要判斷負載類型,若負載類型為96,則采用PS 解復用,將音視頻分開解碼。若負載類型為98,直接按照H264 的解碼類型解碼。
注:此方法不一定准確,取決於打包格式是否標准
PS 包中的流類型(stream type)的取值如下:
a、 MPEG-4 視頻流: 0x10;
b、 H.264 視頻流: 0x1B;
c、 SVAC 視頻流: 0x80;
d、 G.711 音頻流: 0x90;
e、 G.722.1 音頻流: 0x92;
f、 G.723.1 音頻流: 0x93;
g、 G.729 音頻流: 0x99;
h、 SVAC音頻流: 0x9B。
2.PS 封裝各個部分詳細介紹
1).PSH PSheader
PSheader是一個PS包的包頭,主要包含系統同步時間。
I、 Pack start code:包起始碼字段,值為0x000001BA的位串,用來標志一個包的開始。
II、 System clock reference base,system clock reference extenstion:系統時鍾參考字段。
III、 Pack stuffing length :包填充長度字段,3 位整數,規定該字段后填充字節的個數
如下圖1:
80 60 53 1f 00 94 89 00 00 0000 00 00 00 01 ba €`S..??........?
7e ff 3e fb 44 01 00 5f 6b f8 00 00 01 e0 14 53 ~.>?D.._k?...?.S
80 80 05 2f bf cf bed1 1c 42 56 7b 13 58 0a 1e €€./????.BV{.X..
08 b1 4f 33 69 35 0453 6d 33 a8 04 15 58 d9 21 .?O3i5.Sm3?..X?!
9741 b9 f1 75 3d 94 2b 1f bc 0b b2 b4 97 bf 93 ?A??u=?+.?.?????
前12位是RTP Header,這里不再贅述;
000001ba是包頭起始碼;
接下來的9位包括了SCR,SCRE,MUXRate,具體看上圖
最后一位是保留位(0xf8),定義了是否有擴展,二進制如下
1111 1000
前5位跳過,后3位指示了擴展長度,這里是0.
海康定義的PS流子集中,stuffing_byte為6字節,其后4字節存放當前幀的幀號。
00 00 01 BA 46 9B 4E 47 C4 01 01 47 B3 FE FF FF
00 03 23 EA(幀的幀號)
2).PS system header 系統標題
如下圖2:
Systemheader當且僅當pack是第一個數據包時才存在,即PS包頭之后就是系統標題。取值0x000001BB的位串,指出系統標題的開始,暫時不需要處理,讀取Header Length直接跳過即可。
3).PS system Map 節目映射流(PSM)
Systemheader當且僅當pack是第一個數據包時才存在,即系統標題之后就是節目流映射。取值0x000001BC的位串,指出節目流映射的開始,暫時不需要處理,讀取Header Length直接跳過即可。前5字節的結構同系統標題,見上圖。
取一段碼流分析系統標題和節目映射流
00 00 01 ba 45 a9 d4 5c 34 0100 5f 6b f8 00 00 ...?E??\4.._k?..
01 bb 00 0c 80 cc f5 04 e1 7f e0 e0 e8 c0 c0 20 .?..€??.?.?????
00 00 01 bc 00 1e e1 ff00 00 00 18 1b e0 00 0c ...?..?......?..
2a 0a 7f ff 00 00 0708 1f fe a0 5a 90 c0 00 00 *........??Z??..
00 00 00 00 00 00 01 e0 7f e0 80 80 0521 6a 75 .......?.?€€.!ju
前14個字節是PS包頭(注意,沒有擴展);
接下來的00 00 01 bb是系統標題起始碼;
接下來的00 0c說明了系統標題的長度(不包括起始碼和長度字節本身);
接下來的12個字節是系統標題的具體內容,這里不做解析;
繼續看到00 00 01 bc,這是節目映射流起始碼;
緊接着的00 1e同樣代表長度;
跳過e1 ff,基本沒用;
接下來是00 00,自定義的復合流描述的長度,為0表示后面沒有否則
后面跟着就是自定義的描述內容(海康在這里放入了復合流的私有描述:
兩字節復合流描述字(40 0E)+內容(用於放置全局時間,編碼設備型號等相關信息)+
兩字節復合流描述字(41 12)(可選)+內容(用於描述設備與通道號),
所以長度就不是00 00)
接下來是00 18,代表基本流長度,說明了后面還有24個字節
接下來的1b,stream type 意思是H264編碼格式;
下一個字節e0,意思是視頻流(stream id e0到ef表示視頻);
接下里00 0c,同樣代表接下的長度12個字節,表示的是元素流的自定義描述的長度,接下來
是對應長度的描述內容,這里一般是視頻流的描述,以海康的為例,這里是;
兩字節長度(00 10)+兩字節視頻描述字(42 0E)+內容(用於描述視頻編碼分辨率、幀率、是否場編碼,B幀個數等信息)
跳過這12個字節,看到90,stream type 這是G.711音頻格式;
下一個字節是c0,代表音頻流(stream id c0到df表示音頻);
接下來的00 00同樣代表長度,這里是0,表示元素流的自定義(私有)描述長度,如果不為0后面跟着一般是音頻流描述,;
不為0的情況以海康的為例:
兩字節長度(00 0c)+兩字節音頻描述字(43 0A)+內容(用於描述音頻編碼的采樣率,碼率,幀長度,聲道數等信息)
接下來4個字節是CRC,循環冗余校驗。
到這里節目映射流解析完畢。
PSM節目流映射提供了關於節目流中原始流以及它們之間相互關系的描述:
I、復合流級私有描述(HIK PS私有),用於放置全局時間,編碼設備型號等相關信息
II、元素流級私有描述(HIK PS私有,一般包含視頻描述和音頻描述兩種),用於視頻編碼的分辨率、幀率、
是否場編碼、B幀個數,幀間間隔、以及
音頻編碼的采樣率、碼率、幀長度、聲道數等相關信息。
4).PES header PES分組頭部
PES
Packetised Elementary Stream ,原始流分組。Elementary Stream,原始流,指的是視頻或音頻壓縮編碼后產生的比特數據,
而視頻或音頻原始流分別打包生成視頻PES和音頻PES。一個PES分組只包含一種原始流的編碼數據。
如下圖3:
別被這么長的圖嚇到,其實原理相同,但是,你必須處理其中的每一位。
1)Packet start code prefix:值為0x000001的位串,它和后面的stream id 構成了標識分組開始的分組起始碼,用來標志一個包的開始。
2)Stream id:在節目流中,它規定了基本流的號碼和類型。0x(C0~DF)指音頻,0x(E0~EF)為視頻,bf 私有,be 填充
3)PES packet length:16 位字段,指出了PES 分組中跟在該字段后的字節數目。值為0 表示PES 分組長度要么沒有規定要么沒有限制。這種情況只允許出現在有效負載包含來源於傳輸流分組中某個視頻基本流的字節的PES 分組中。
4)PTS_DTS:2 位字段。當值為'10'時,PTS 字段應出現在PES 分組標題中;當值為'11'時,PTS 字段和DTS 字段都應出現在PES 分組標題中;當值為'00'時,PTS 字段和DTS 字段都不出現在PES分組標題中。值'01'是不允許的。
5)ESCR:1位。置'1'時表示ESCR 基礎和擴展字段出現在PES 分組標題中;值為'0'表示沒有ESCR 字段。
6)ESrate:1 位。置'1'時表示ES rate 字段出現在PES 分組標題中;值為'0'表示沒有ES rate 字段。
7)DSMtrick mode:1 位。置'1'時表示有8 位特技方式字段;值為'0'表示沒有該字段。
8)Additionalinfo:1 位。附加版權信息標志字段。置'1'時表示有附加拷貝信息字段;值為'0'表示沒有該字段。
9)CRC:1 位。置'1'時表示CRC 字段出現在PES 分組標題中;值為'0'表示沒有該字段。
10)Extensionflag:1 位標志。置'1'時表示PES 分組標題中有擴展字段;值為'0'表示沒有該字段。
PES header data length: 8 位。PES 標題數據長度字段。指出包含在PES 分組標題中的可選字段和任何填充字節所占用的總字節數。該字段之前的字節指出了有無可選字段。
老規矩,上碼流:
00 00 01 e0 21 33 80 80 05 2b 5f df 5c 95 71 84 ...?!3€€.+_?\?q?
aa e4 e9 e9 ec 40 cc17 e0 68 7b 23 f6 89 df 90 ?????@?.?h{#????
a9d4 be 74 b9 67 ad 34 6d f0 92 0d 5a 48 dd 13 ???t?g?4m??.ZH?.
00 00 01是起始碼;
e0是視頻流;
21 33 是幀長度;
接下來的兩個80 80見下面的二進制解析;
下一個字節05指出了可選字段的長度,前一字節指出了有無可選字段;
接下來的5字節是PTS;
第7、8字節的二進制如下:
1000 0000 1000 0000
按順序解析:
第7個字節:
10 是標志位,必須是10;
00 是加擾控制字段,‘00’表示沒有加密,剩下的01,10,11由用戶自定義;
0 是優先級,1為高,0為低;
0 是數據對齊指示字段;
0 是版權字段;
0 是原始或拷貝字段。置'1'時表示相關PES分組有效負載的內容是原始的;'0'表示內容是一份拷貝;
第8個字節:
10 是PTS_DTS字段,這里是10,表示有PTS,沒有DTS;
0 是ESCR標志字段,這里為0,表示沒有該段;
0 是ES速率標志字段,,這里為0,表示沒有該段;
0 是DSM特技方式標志字段,,這里為0,表示沒有該段;
0 是附加版權信息標志字段,,這里為0,表示沒有該段;
0 是PESCRC標志字段,,這里為0,表示沒有該段;
0 是PES擴展標志字段,,這里為0,表示沒有該段;
3.私有信息擴展-IVS舉例
PES Header|Private Data Header|Private data
其中,
Private Data Header包括:Private Data Type|Private Data Length
Private data以IVS Info舉例:IVS Info Header|IVS Data
Private data type的定義如下:
0x0000 Reserved
0x0001 Basic Stream Info
0x0002 Codec Info
0x0003 IVS Info
IVS Info Header長度8byte,定義如下:
0x0000 Reserved
0x0001 MetaData
0x0002 EventData
0x0003 RuleData
0x0100 Face Identification
0x0101 Face Identification ATM