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

一些概念

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:14字節

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);

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單元。
SODB:(String of Data Bits)最原始的編碼數據,無任何附加數據。
RBSP:在SODB的基礎上增加了rbsp_stop_ont_bit(bit值爲1)並用0按字節補位對齊。基本結構是在原始編碼數據的後面添加了結尾比特。一個bit"1",若干比特"0",以便字節對齊。
每個NAL單元包括NAL頭+RBSP。NAL單元序列如下:
 
典型的RBSP單元如下: 
現在來具體的說明下NAL頭和RBSP。
NAL頭結構爲:|0|1|2|3|4|5|6|7|   |F|NRI|  Type   |
NAL頭說明:
  
 
可以看到NAL的單元有SPS、PPS、SEI、IDR_SLICE等。NAL單元裏面的頭也顯示了,頭結構裏面的nal_unit_type表示了RBSP是什麼類型。NAL_Size的大小是不包括起始碼startcode大小的。
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,有的沒有,對播放並無影響。
 
 (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信息。
 
 (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需要用逗號分隔開來.

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 後就可以了。

 

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