1. 程式人生 > >RTP PS PES ES H264協議學習

RTP PS PES ES H264協議學習

參考:https://www.cnblogs.com/wainiwann/p/7477794.html

https://blog.csdn.net/chenhande1990chenhan/article/details/78744344

https://blog.csdn.net/H514434485/article/details/52064945

https://blog.csdn.net/appledurian/article/details/73134558

https://blog.csdn.net/leopard21/article/details/24818715 

https://blog.csdn.net/appledurian/article/details/70851428 

https://blog.csdn.net/zjf535214685/article/details/60321345

https://blog.csdn.net/twoconk/article/details/52217493

https://blog.csdn.net/linolzhang/article/details/60885130

一些概念

ES流(Elementary Stream原始流),是音、視訊訊號經過編碼器之後或資料訊號的基本碼流。只包含一種內容。每個ES都由若  幹個存取單元(AU)組成,每個視訊或音訊AU都是由頭部和編碼資料兩部分組成,1個AU相當於編碼的1幅視訊影象或1個  音訊幀  也可以說,每個AU實際上是編碼資料流的顯示單元,即相當於解碼的1幅視訊影象或1個音訊幀的取樣。
PES

(Paketized Elementary Stream)是ES經過打包後的碼流,長度可變。視訊一般一幀一個包,音訊一般不超過64KB. 
PTS--(presentation time stamp)顯示時間戳,表示顯示單元出現在系統目標解碼器(H.264、MJPEG等)的時間。
DTS--(Decoding Time Stamp)解碼時間戳,表示將存取單元全部位元組從解碼快取器移走的時間。
PTS和DTS打在PES包頭內,是解決音視訊同步,防止解碼器輸入快取上溢或下溢的關鍵。每一個pes header都包含pts和dts,是相對SCR(系統參考)的時間戳,以90000為單位,系統時鐘頻率(H264取樣頻率?)為90Khz;所以轉換到秒為PTS/90000;如果是以ms為單位的播放器,ms=pts/90;如果是以時鐘頻率為單位,直接將PTS/DTS送進去解碼即可;如果沒有B幀,PTS和DTS的順序應該是一致的,如果有B幀,則需要先解碼P幀,才能解出來B幀,所以需要PTS和DTS來控制解碼時間和顯示時間;
在解碼時,pes-->es,音視訊的同步,除了使用pts和dts以外,還會用到SCR(system clock reference),
在編碼時,都是由STC(system time clock)生成.
   I(關鍵幀)、P(預測幀)、B(雙向預測幀)的包頭都有一個PTS和DTS。
   I幀和P幀顯示前一定要儲存於視訊解碼器的重新排序快取器中,經過延遲(重新排序)後再顯示,所以一定要分別標明PTS和DTS。無需標出B幀的DTS。

PES包頭說明

(一)Packet start code prefix:包頭起始碼,固定為0x000001,24bit;
(二)Stream id: PES包中的負載流型別,一般視訊為0xe0,音訊為0xc0,8bit;
(三)PES packet length: PES包長度,包括此位元組後的可選包頭和負載的長度,16bit;
(四)Optional PES Header,順序依次為:
 1,’10’欄位:2bit;
 2,PES scrambling control:加密模式,2bit;00未加密,01或10或11由使用者定義;
 3,PES priority:有效負載的優先順序,1bit;1比0的負載優先順序高;
 4,Data alignment indicator:資料定位指示器,1bit;
 5,Copyright:版權資訊,1為有版權,0無版權,1bit;
 6,Original or copy:原始或備份,1為原始,0為備份,1bit;
 7,7個flags:7bit;一般1表示有指定的可選定段,0表示沒有,依次為:
  PTS_flags:DTS_flags:ESCR_flag: ES_rate_flag:
  DSM_trick_mode_flag: Additional_copy_info_flag: PES_CRC_flag: PES_extension_flag: 
 8,PES header data length:PES首部中可選欄位和填充欄位的長度;8bit;
 9,Optional fields:可選欄位的描述資訊區域,其內容由上面的7個flag來控制;
  PTS/DTS欄位: 40bit,時間佔33bit,PTS和DTS的內容是在這40bit中取33位,方式相同,如下:
   start_code:4bit;起始碼 依PTS_DTS_flags變化:

     ‘10’,只有PTS,起始碼為0010;‘11’, PTS的起始碼為0011,DTS的起始碼為0001;

   PTS[32..30];1bit;PTS[29..15];1bit;PTS[14..0];1bit;
   計算方法:PTS/DTS  = (PTS1 & 0x0e) << 29 + (PTS2 & 0xfffe) << 14 + (PTS3 & 0xfffe ) >> 1;
  ESCR欄位:48bit,由33bit的ESCR_base和9bit的ESCR_extension組成,順序:
   Reserved: 2bit;ESCR_1[32..30];1bit;ESCR_2[29..15];1bit;ESCR_3[14..0];1bit;
   ESCR_extension:9bit;週期數,取值範圍0~299;迴圈一次,base+1;1bit;
  ES rate欄位:目標解碼器接收PES分組位元組速率,禁止為0,佔位24bit;
   1bit;ES_rate:22bit;1bit;
  Trick mode control:表示哪種trick mode被應用於相應的視訊流,8bit,
   trick_mode_control佔前3bit,後面5bit內容可變;
        ‘000’ ‘011’:field_id:2bit;intra_slice_refresh:1bit;frequency_truncation:2bit;
     ‘001’ ‘100’: rep_cntrl:5bit;

    ‘010’:field_id:2bit;Reserved:3bit;
  Additional copy info欄位:8bit,表示和版權相關的私有資料; 
   1bit;copy info欄位:7bit;
  Previous PES CRC:16bit,包含CRC值, 
  PES extension:PES擴充套件欄位是否包含的標誌,8bit,1表示有此欄位,0無。 
   PES_private_data_flag;Pack_header_field_flag;
   Program_packet_sequence_counter_flag;P-STD_buffer_flag;
   Reserved:3bit;PES_extension_flag_2;
      Optional fields :PES擴充套件欄位依上述標誌存在的內容順序為:
        PES_private_data:私有資料128bit;
        Pack_header_field:
         Pack_field_length:指定後面的field的長度,8bit;
         pack_header_field();
       Program_packet_sequence_counter:計數器,16bit; 
        1bit;packet_sequence_counter:7bit;1bit;

                    MPEG1_MPEG2_identifier:1bit,PES包負載來源(1 MPEG1流,0 PS流);

                     original_stuff_length:6bit,(PES頭部填充位元組長度);
      P-STD_buffer: 16bit; 
         ’01’欄位:2bit;
         P-STD_buffer_scale:1bit,表示用來解釋後面P-STD_buffer_size欄位的比例因子;
           若stream_id為音訊流,為0;視訊流,為1,其他型別,均可;
         P-STD_buffer_size:13bit;大於或等於所有P-STD輸入緩衝區大小BSn的最大值;
           若P-STD_buffer_scale為0,以128位元組為單位;為1,以1024位元組為單位;
      PES_extension2:擴充套件欄位的擴充套件欄位;N*8bit, 
      1bit;PES_extension_field_length:7bit,表示擴充套件區域的長度;
             Reserved欄位:8*PES_extension_field_length個bit;
 10,Stuffing bytes:填充欄位,固定為0xFF;不能超過32個位元組;
(五)PES_packet_data_byte:PES包負載中的資料,即ES原始流資料;

RTP包頭說明:RTP包最大為1400位元組,包頭固定為12位元組,百度百科上說明如下:

V

P

X

CC

M

PT

序列號

時戳

同步信源(SSRC)識別符號

特約信源(CSRC)識別符號

···

RTP報文由兩部分組成:報頭和有效載荷。RTP報頭格式如圖所示,其中:

V:RTP協議的版本號,佔2位,當前協議版本號為2。

P:填充標誌,佔1位,如果P=1,則在該報文的尾部填充一個或多個額外的八位組,它們不是有效載荷的一部分。

X:擴充套件標誌,佔1位,如果X=1,則在RTP報頭後跟有一個擴充套件報頭。

CC:CSRC計數器,佔4位,指示CSRC 識別符號的個數。

M: 標記,佔1位,不同的有效載荷有不同的含義,對於視訊,標記一幀的結束;對於音訊,標記會話的開始。

同步信源(SSRC)識別符號:佔32位,用於標識同步信源。該識別符號是隨機選擇的,參加同一視訊會議的兩個同步信源不能有相同的SSRC。

 特約信源(CSRC)識別符號:每個CSRC識別符號佔32位,可以有0~15個。每個CSRC標識了包含在該RTP報文有效載荷中的所有特約信源。

PT: 有效載荷型別,佔7位,用於說明RTP報文中有效載荷的型別,如GSM音訊、JPEM影象等。

序列號:佔16位,用於標識傳送者所傳送的RTP報文的序列號,每傳送一個報文,序列號增1。接收者通過序列號來檢測報文丟失情況,重新排序報文,恢復資料。

時戳(Timestamp):佔32位,時戳反映了該RTP報文的第一個八位組的取樣時刻。接收者使用時戳來計算延遲和延遲抖動,並進行同步控制。

負載大於1400時,需要分片處理,具體的分片方法,以H264I幀資料為例:

   當獲取到一幀h264的I幀資料時,先進行PS封裝,在視訊資料前加

                  PS header + PS system header + PS system Map header 

            加PES頭時,由於PES頭的負載長度型別是short,最大65536,所以每65536位元組的資料後都得加一個PES頭,如下: 
                 | PS header | PS system header | PS system Map |PES | data | PES頭 | data | PES頭 | data| 
            這樣PS封裝就完成了剩下的就是把封裝好的資料分包打RTP包,每1300位元組的資料前加一個RTP包頭,然後傳送出去
 

PS包頭說明

PS封裝的幾個頭: 
(1)PS header:14位元組 
pack_start_code : (32b) 起始碼欄位 預設0x000001BA 標誌一個包的開始 。marker_bit :(2b) 標記位欄位,取值’01’。 
system_clock_reference_base[32..30] :(3b)系統時鐘參考欄位 。marker_bit : (1b) 標記位欄位取值’1’ 
system_clock_reference_base[29..15] : (15b) 系統時鐘參考欄位 。marker_bit : (1b) 標記位欄位取值’1’ 
system_clock_reference_base[14..0] : (15b) 系統時鐘參考欄位 。marker_bit : (1b) 標記位欄位取值’1’ 
system_clock_reference_extension : (9b) 系統時鐘參考欄位 。marker_bit : (1b) 標記位欄位取值’1’

program_mux_rate : (22b) 節目複合速率欄位。 marker_bit : (2b) 標記位欄位取值’11’ 。reserved : (5b) 填充欄位 
pack_stuffing_length : (3b) 包填充長度欄位

節目複合速率欄位 program_mux_rate 
一個22位整數,規定P-STD在包含該欄位的包期間接收節目流的速率。其值以50位元組/秒為單位。不允許取0。用於定義P-STD輸入端的位元組到達時間。在節目多路複合流的不同包中取值可能不同。

如下例:
80 60 00 00 00 00 00 00 0d 25 5a a5    /12位元組RTP頭/ 
00 00 01 ba 44 00 05 5f 94 01 00 60 1b f8  /PS 頭/  紅色部分為開始碼

藍色部分為 系統時鐘參考欄位,二進位制:01 000 1 000000000000000 1 010101111110010 1 000000000 1

SCR = 90000/8 = 00000000 00000000 00101011 11110010 (SRC值是累加的,這個是第一幀資料的SRC值) 
000 這三個位段的值是由SCR值的第30-32位填充,參考上述SRC值,故填充3位0 
000000000000000 這15位欄位是由SRC值的第15-29位填充,故填充000000000000000

010101111110010 這15位欄位是由SRC值的第0-14位填充,故填充 0101011 11110010

橙色部分為節目複合速率, 二進位制: 00000000001100000000110 11 11111 000 沒看懂用途,嘗試隨便取值不影響視訊和音訊,不能取0。

(2) PS system header:18位元組,當切僅當第一個資料包時存在。

system_header_start_code : (32b) 開始碼 0x000001BB 
header_length : (16) 該欄位後的系統標題的位元組長度 。 
marker_bit : (1b) 標記位欄位取值’1’,rate_bound : (22b) 速率界限欄位 。marker_bit : (1b) 標記位欄位取值’1’ 
audio_bound : (6b) 音訊界限欄位 ,fixed_flag : (1b) 固定標誌欄位 ,CSPS_flag : (1b) CSPS標誌欄位 
system_audio_lock_flag : (1b) 系統音訊鎖定標誌欄位 
system_video_lock_flag : (1b) 系統視訊鎖定標誌欄位 。marker_bit : (1b) 標記位欄位取值’1’ 
vedio_bound : (5b) 視訊界限欄位 
packet_rate_restriction_flag: (1b) 分組速率限制標誌欄位 。reserved_bits : (7b) 保留位欄位, 值’111 1111’
stream_id : (8b) 流標識欄位 。marker_bit : (2b) 取值’11’ ,
P-STD_buffer_bound_scale : (1b) P-STD緩衝區界限比例,P-STD_buffer_size_bound : (13) P-STD緩衝區大小界限
00 00 01 bb 00 0c 80 1e ff fe e1 7f e0 e0 d8 c0 c0 20 紅色為系統頭開始碼 ,綠色頭長度00 0c : 當前欄位後該頭的長度 12 
粉色速率界限80 1e ff 轉成二進位制: 1 0000000000111101111111 1 ,可被解碼器用於估計是否有能力對整個流解碼
fe e1 7f轉成二進位制: 111111 1 0 1 1 1 00001 0 1111111 
111111: 音訊界限欄位 audio_bound 6位欄位,取值0-32,且不小於節目流中解碼過程同時活動的音訊流的最大數目。本小節中,若STD緩衝區非空或展現單元正在P-STD模型中展現,則音訊流的解碼過程是活動的。 
1 : 固定標誌欄位 fixed_flag 1位標誌位。置’1’時表示位元率恆定的操作;置’0’時,表示操作的位元率可變。 
0 : CSPS標誌欄位 CSPS_flag 1位欄位; 1: 音訊鎖定;1: 視訊鎖定;00001: 視訊界限video_bound 
0: 分組速率限制, packet_rate_restriction_flag 1位標誌位。若CSPS標識為’1’,則該欄位表示哪個限制適用於分組速率。
1111111 : 7位,保留。

e0 e0 d8 c0 c0 20轉成二進位制: 11100000 11 1 0000011011000 11000000 11 0 0000000100000 
11100000 : 流標識欄位 stream_id ,E0是視訊,C0是音訊 ;11: 固定值 
1: 用於解釋P-STD_buffer_size_bound的比例係數。若stream_id表示音訊,值為’0’,則以128位元組為單位來度量緩衝區大小的邊界。視訊流,為’1’,則以1024位元組為單位來度量緩衝區大小的邊界。其它型別未定義。

(3) PS Map Header:30位元組 
packet_start_code_prefix : (24b) 開始碼 0x000001 ;map_stream_id : (8) 對映流標識欄位 值為0xBC 
program_stream_map_length: (16) 節目流對映長度欄位 
current_next_indicator : (1) 當前下一個指示符欄位; reserved : (2);program_stream_map_version: (5) 節目流對映版本 
reserved : (7) ;marker_bit : (1) ;program_stream_info_length : (16) 節目流資訊長度欄位 
elementary_stream_map_length: (16) 基本流對映長度欄位 ;stream_type : (8) 流型別欄位 
elementary_stream_id : (8) 基本流標識欄位 ;elementary_stream_info_length : (16) 基本流資訊長度欄位 
CRC_32 : (32) CRC 32欄位

00 00 01 bc 00 18 e1 ff 00 00 00 08 1b e0 00 00 90 c0 00 00 23 b9 0f 3d;00 00 01 bc 開始碼加固定id ;00 18 頭的長度 
e1 ff 00 00 00 08二進位制: 111 00001 1111111 1 0000000000000000 0000000000001000 
1: current_next_indicator 。置’1’傳送的節目流對映當前是可用的。’0’傳送的節目流對映不可用,將是下一個生效的表。 
11: 填充;00001: 節目流對映版本,表示整個節目流對映的版本號。一旦節目流對映的定義變化,將遞增1,並對32取模。current_next_indicator為’1’時,是當前適用的節目流對映的版本號;為’0’時,是下一個適用的節目流對映的版本號。

1111111: 填充;1填充;0000000000000000: 節目流資訊長度 ,指出緊跟在該欄位後的描述符總長度 ;
0000000000001000: 基本流對映長度,指出在該節目流對映中的所有基本流資訊(只包括stream_type(1B)、elementary_stream_id(1B)和elementary_stream_info_length(2B))的位元組長度。(elementary_stream_map_length/4可得到後面定義了幾個流型別資訊。) 
1b e0 00 00: 流型別,1b是H264視訊流;基本流標識,e0 :指視訊 ;00 00基本流資訊長度,0位元組的視訊描述位元組 
90 c0 00 00: 90是G.711 音訊流:0x90;c0指音訊 ;00 00:0個位元組描述符 
23 b9 0f 3d : 32位欄位,它包含CRC值以在處理完整個節目流對映後在附錄A中定義的解碼器暫存器產生0輸出值。

(4) PS PES Header:(變長),詳見上面的PES頭說明

packet_start_code_prefix : (24b) 分組起始碼字首欄位 packet_start_code_prefix 0x000001 
stream_id : (8) 流標識欄位 stream_id 這個欄位的定義,其中0x(C0~DF)指音訊,0x(E0~EF)為視訊 
PES_packet_length : (16) PES分組長度欄位 PES_packet_length 
‘10’ : (2) ;PES_scrambling_control : (2) PES加擾控制欄位 PES_scrambling_control 
PES_priority : (1) PES優先順序欄位 PES_priority ;data_alignment_indicator : (1) 資料對齊指示符欄位 data_alignment_indicator 
copyright: (1) 版權欄位 copyright ;original_or_copy : (1) 原始或拷貝欄位 original_or_copy 
PTS_DTS_flags : (2) PTS DTS標誌 ;ESCR_flag : (1) ESCR標誌 ;ES_rate_flag : (1) ES速率標誌;
DSM_trick_mode_flag : (1) DSM特技方式標誌;additional_copy_info_flag : (1) 附加版權資訊標誌;
PES_CRC_flag : (1) PES CRC標誌;PES_extension_flag: (1) PES擴充套件標誌;
PES_header_data_length: (8) PES標題資料長度欄位 PES_header_data_length 
‘0011’ : (4) ;PTS[32..30] : (3) 展現時間戳欄位 PTS ;marker_bit: (1) ;PTS[29..15] : (15) ;
marker_bit : (1) ;PTS[14..0] : (15) ;marker_bit : (1);
00 00 01 e0 49 e6 88 80 05 31 00 01 57 e5 00 00 01: 開始碼  e0 : 視訊  49 e6: 視訊資料長度 
88 80 05 :二進位制資料10 00 1 0 0 0 10 0 0 0 0 0 0 00000101 
10 : 固定值 ,00: PES加擾控制 ,1: PES優先順序  ‘1’表示PES分組中有效負載的優先順序高於為’0’的PES分組有效負載 
0: 資料對齊指示符   當值為’0’時,沒有定義。 0: 版權  0: 原始或拷貝  置’1’負載是原始的;’0’負載是一份拷貝

10: PTS DTS標誌 只有’10’時,PTS;當值為’11’時,PTS和DTS都有;’00’時,PTS和DTS都無。值’01’是不允許的。 
0 0 0 0 0 0 六個擴充套件標誌位 置0 
00000101 : 資料長度 5 標明後續有五個位元組 
31 00 01 57 e5:二進位制如下 11 000 1 000000000000000 1 010101111110010 1 
0011: 只有PTS ;PTS = 90000/8 = 11250 二進位制: 10101111110010 
000: PTS第30 -32位填充  000000000000000:  PTS第15 -29位填充  010101111110010:  PTS第0 -14位填充
 

RTP荷載PS流
 一、針對H264視訊video 做如下PS 封裝:
1,每個IDR NALU 前一般都會包含SPS、PPS 等NALU,因此將SPS、PPS、IDR 的NALU 封裝為一個PS 包,包括ps 頭,然後加上PS system 頭,PS system map,PES 頭+h264 raw data。
2,一個IDR NALU PS 包由外到內順序是:PS頭| PS system 頭| PS system Map | PES 頭| h264 raw data。對於其它非關鍵幀的PS 包,直接加上PS頭和PES 頭就可以了。
順序:PS 頭| PES 頭| h264raw data。
二、當有音訊資料時,將資料加上PES header 放到視訊PES 後就可以了。
順序:PS頭|PES(video)|PES(audio),再用RTP 封裝傳送就可以了。
GB28181 對RTP 傳輸的資料負載類型範圍:96-127 。RFC2250 建議:96 ,PS; 97 ,MPEG-4;98 ,H264。
收到的RTP 包首先需要判斷負載型別,若為96,則採用PS 解複用,將音視訊分開解碼。98,直接按照H264 型別解碼

H264格式說明:

1、    H264的功能分為兩層:視訊編碼層(VLC,Video Coding Layer)和網路抽象層(NAL, Network Abstraction Layer)。VLC資料即編碼處理的輸出,表示被壓縮編碼後的視訊資料序列。VCL資料傳輸或儲存之前,這些資料先被對映或封裝進NAL單元。每個NAL單元包括一個原始位元組序列負荷(RBSP, Raw Byte Sequence Payload)、一組對應於視訊編碼的NAL頭資訊。

起始碼startcode:如果NALU對應的Slice為一幀的開始,則4位元組,即0x00000001;否則3位元組,即0x000001。起始碼之後即為NAL單元。NAL_Size的長度不包括起始碼。
SODB:(String of Data Bits)最原始的編碼資料,無任何附加資料。
RBSP:在SODB的基礎上增加了rbsp_stop_ont_bit(bit值為1)並用0按位元組補位對齊。基本結構是在原始編碼資料的後面添加了結尾位元。一個bit"1",若干位元"0",以便位元組對齊。
每個NAL單元包括NAL頭+RBSP。NAL單元序列如下:
 
典型的RBSP單元如下: 
NAL頭結構為:|0|1|2|3|4|5|6|7|   |F|NRI|  Type   |
NAL頭說明:
 

EBSP:(Encapsulation Byte Sequence Packets)在RBSP的基礎上增加了防止偽起始碼位元組(0x03)。為了使NALU的主體不包括起始碼,在編碼的時候每遇到兩個位元組(連續)的0,就插入一個位元組0x03,以便和起始碼相區別,解碼時,則將相應的0x03刪除掉。所以有時候NAL單元有可能是NAL頭+EBSP組成。
NALU主體 編碼時插入0x03如:0x000000  >>>  0x00000300  0x000001  >>>  0x00000301
接下來對應剛剛的H264,其檔案資料表示如下:
 
前面兩個0x00000001對應PPS和SPS,第三個0x000001對應SEI。
2、    SPS、PPS和SEI。
1、SPS即Sequence Paramater Set序列引數集。SPS中儲存了一組編碼視訊序列(Coded video sequence)的全域性引數。所謂的 編碼視訊序列即原始視訊的一幀一幀的畫素資料經過編碼之後的結構組成的序列。一般情況SPS和PPS的NAL Unit通常位於 整個碼流的起始位置。特殊情況下,碼流中間也可能出現這兩種結構,可能為:
      1)解碼器需要在碼流中間開始解碼;
      2)編碼器在編碼的過程中改變了碼流的引數(如影象解析度等);
      在做視訊播放器時,為了讓後續的解碼過程可以使用SPS中包含的引數,必須對其中的資料進行解析。
2、PPS即Picture Paramater Set(PPS) 影象引數集。每一幀編碼後資料所依賴的引數保存於影象引數集PPS中。PPS類似於  SPS,在H.264的裸碼流中單獨儲存在一個NAL Unit中,PPS NAL Unit的nal_unit_type值為8;在封裝格式中,PPS通常與   SPS一起,儲存在視訊檔案的檔案頭中。
   有的檔案每個IDR幀前面都有PPS和SPS,有的只是開頭才有。一般來說:
      1)、直播每個IDR幀前面都應加SPS和PPS,因為觀眾會中途進來觀看。
      2)、本地檔案可在開頭加SPS和PPS,或都加。

3、SEI(Supplemental Enhancement Information):輔助增強資訊。可存放簡介,版權或私有資訊。有的H264檔案有SEI,有的沒 有,對播放並無影響。

PPS說明:


  (1) pic_parameter_set_id當前PPS的id。某個PPS在碼流中會被相應的slice引用,引用方式就是在Slice header中儲存PPS的id值。取值[0,255]。
(2) seq_parameter_set_id當前PPS引用的啟用的SPS的id。這樣PPS中可取到對應SPS中的引數。取值[0,31]。
(3) entropy_coding_mode_flag熵編碼模式標識,表示碼流中熵編碼/解碼選擇的演算法。對於部分語法元素,在不同的編碼配置下,選擇的熵編碼方式不同。例如在一個巨集塊語法元素中,巨集塊型別mb_type的語法元素描述符為“ue(v) | ae(v)”,在baseline profile等設定下采用指數哥倫布編碼,在main profile等設定下采用CABAC編碼。該值為0時,選擇左邊的演算法,通常為指數哥倫布編碼或CAVLC;為1時,選擇右邊的演算法,通常為CABAC。
(4) bottom_field_pic_order_in_frame_present_flag標識位,表示delta_pic_order_cnt_bottom和delta_pic_order_cn是否存在。這兩個語法元素表示了某一幀的底場的POC的計算方法。
(5) num_slice_groups_minus1表示某一幀中slice group的個數。為0時,一幀中所有的slice都屬於一個slice group。slice group是一幀中巨集塊的組合方式,定義在協議文件的3.141部分。
(6) num_ref_idx_10_default_active_minus1、num_ref_idx_11_default_active_minus1表示當Slice Header中的num_ref_idx_active_override_flag標識位為0時,P/SP/B slice的語法元素num_ref_idx_10_active_minus1和num_ref_idx_11_active_minus1的預設值。
(7) weighted_pred_flag標識位,表示在P/SP slice中是否開啟加權預測。
(8) weighted_bipred_idc表示在B Slice中加權預測方法。0預設,1顯式,2隱式。
(9) pic_init_qp_minus26和pic_init_qs_minus26表示初始的量化引數。實際的量化引數由該引數與slice header中的slice_qp_delta/slice_qs_delta計算得到。
(10) chroma_qp_index_offset計算色度分量的量化引數,取值[-12,12]。
(11) deblocking_filter_control_present_flag表示Slice header中是否存在用於去塊濾波器控制的資訊。
(12) constrained_intra_pred_flag為1,表示I巨集塊在進行幀內預測時只能使用來自I和SI型別巨集塊的資訊; 0,表示I巨集塊可使用來自Inter型別巨集塊的資訊。
(13) redundant_pic_cnt_present_flag表示Slice header中是否存在redundant_pic_cnt語法元素。
3 解析SDP中包含的H.264的SPS和PPS串。SDP中的SPS和PPS都是BASE64編碼形式的,需要解析。
RTP傳輸H264的時候,需要用到sdp協議描述,其中需要從H264碼流中獲取到PPS,SPS。H264碼流中,以"0x00 00 01"或"0x00 00 00 0x01"為開始碼,其後的第一個位元組的低5位判斷是否為7(sps)或8(pps),然後對獲取的nal去掉開始碼之後進行base64編碼,得到的資訊就可以用於sdp。sps和pps需要用逗號分隔開來.

SPS說明:


 (1) SPS中,第一個位元組表示profile_idc:標識當前H.264碼流的profile。H.264中定義了三種常用的檔次profile:
基準檔次:baseline=66;主要檔次:main=77;擴充套件檔次:extended=88;
新版標準中,還包括了High、High 10、High 4:2:2、High 4:4:4、High 10 Intra、High 4:2:2 Intra、High 4:4:4 Intra、CAVLC 4:4:4 Intra等,每一種都由不同的profile_idc表示。
constraint_set0_flag ~ constraint_set5_flag是在編碼的檔次方面對碼流增加的限制條件。
(2) level_idc標識當前碼流的Level。定義了某種條件下的最大視訊解析度、最大視訊幀率等引數。
(3) seq_parameter_set_id當前的序列引數集的id。通過該id值,影象引數集pps可以引用其代表的sps中的引數。
(4) log2_max_frame_num_minus4用於計算MaxFrameNum= 2^(log2_max_frame_num_minus4 + 4)。MaxFrameNum是frame_num(影象序號的一種表示方法,在幀間編碼中常用作一種參考幀標記的手段)的上限值。
(5) pic_order_cnt_type表示解碼picture order count(POC)的方法。POC是另一種計量影象序號的方式,與frame_num有著不同的計算方法。該語法元素的取值為0、1或2。
(6) log2_max_pic_order_cnt_lsb_minus4用於計算MaxPicOrderCntLsb = 2^(log2_max_pic_order_cnt_lsb_minus4 + 4),該值表示POC的上限。
 (7) max_num_ref_frames表示參考幀的最大數目。
(8) gaps_in_frame_num_value_allowed_flag標識位,說明frame_num中是否允許不連續的值。
(9) pic_width_in_mbs_minus1用於計算影象的寬度。單位為巨集塊個數。
frame_width = 16 × (pic\_width\_in\_mbs_minus1 + 1);
(10) pic_height_in_map_units_minus1用來度量視訊中一幀影象的高度。圖高並非影象明確的以畫素或巨集塊為單位的高度,需要考慮該巨集塊是幀或場編碼。PicHeightInMapUnits = pic\_height\_in\_map\_units\_minus1 + 1;
(11) frame_mbs_only_flag標識位,說明巨集塊的編碼方式。為0時,巨集塊可能為幀編碼或場編碼 表示一場資料;為1時,所有巨集塊都採用幀編碼,表示一幀資料。
按照巨集塊計算的影象實際高度:FrameHeightInMbs = ( 2 − frame_mbs_only_flag ) * PicHeightInMapUnits
(12) mb_adaptive_frame_field_flag標識位,說明是否採用了巨集塊級的幀場自適應編碼。
為0時,不存在幀、場編碼之間的切換;為1時,巨集塊可能在幀、場編碼模式之間選擇。
(13) direct_8x8_inference_flag標識位,用於B_Skip、B_Direct模式運動向量的推導計算。
(14) frame_cropping_flag標識位,說明是否需要對輸出的影象幀進行裁剪。
(15) vui_parameters_present_flag標識位,說明SPS中是否存在VUI資訊。
 

RTP封裝PS的H264流及音訊流

H264由NALU單元組成,視訊幀起始碼I幀是  00 00 00 01 65  非I幀 00 00 00 01 41

                                            SPS起始碼 00 00 00 01 67     PPS起始碼 00 00 00 01 68           

I幀前面需要增加PS頭+System 頭+ System Map 頭+ PES 頭

非I幀前面增加PS 頭 + PES 頭

當有音訊資料時,將資料加上PES header 放到視訊PES 後就可以了。