WEBRTC 接收H264 RTP數據流小結


WEBRTC 接收H264 RTP數據流小結

這篇文章是對webrtc 中,接收H264 RTP包的一個總結,主要分為兩個部分:
第一部分,介紹H264打包成RTP包的規范,以及WEBRTC中目前正在使用的幾種格式。
第二部分,介紹WEBRTC的數據流,從接收RTP包,到拼裝成H264 Frame,最終送入Decoder,獲取YUV數據。

第一部分:RTP Payload Format for H.264 Video閱讀筆記

參考鏈接:rfc6184

RTP Payload Format

具體RTP 的協議格式,可以參考RFC 3550

1.RTP Header

    0                   1                   2                   3
   0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |V=2|P|X|  CC   |M|     PT      |       sequence number         |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |                           timestamp                           |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  |           synchronization source (SSRC) identifier            |
  +=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+=+
  |            contributing source (CSRC) identifiers             |
  |                             ....                              |
  +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

  Figure 1.  RTP header according to RFC 3550

2.Payload Structures

定義了三種不同的Playload結構類型

  1. Single NAL Unit Packet

    在一個RTP Playload中,只包含一個Nal Unit 。

  2. Single NAL Unit Packet

    在一個RTP Playload中,聚合了多個Nal Unit。大致包含以下幾種:

    • STAP-A:
    • STAP-B
    • MTAP-16
    • MTAP-24
  3. Fragmentation Unit

    把一個Nal Unit 進行拆分,打包到多個RTP 包中。

    • FU-A
    • FU-B
      Table 1.  Summary of NAL unit types and the corresponding packet
                types

      NAL Unit  Packet    Packet Type Name               Section
      Type      Type
      -------------------------------------------------------------
      0        reserved                                     -
      1-23     NAL unit  Single NAL unit packet             5.6
      24       STAP-A    Single-time aggregation packet     5.7.1
      25       STAP-B    Single-time aggregation packet     5.7.1
      26       MTAP16    Multi-time aggregation packet      5.7.2
      27       MTAP24    Multi-time aggregation packet      5.7.2
      28       FU-A      Fragmentation unit                 5.8
      29       FU-B      Fragmentation unit                 5.8
      30-31    reserved                                     -

2.1 NAL Unit Header

--
+---------------+
|0|1|2|3|4|5|6|7|
+-+-+-+-+-+-+-+-+
|F|NRI| Type |
+---------------+

  • F:0表示payload 內容沒有錯誤,1表示payload中的內容可能有錯誤內容或語法錯誤。
  • NRI:00表示沒有參考幀。
  • Type:1-23

2.1.1 Packetization Modes

  • Single Nal unit mode:
  • Non-interleaved mode:
  • Interleaved mode:

--

      Table 3.  Summary of allowed NAL unit types for each packetization
            mode (yes = allowed, no = disallowed, ig = ignore)

  Payload Packet    Single NAL    Non-Interleaved    Interleaved
  Type    Type      Unit Mode           Mode             Mode
  -------------------------------------------------------------
  0      reserved      ig               ig               ig
  1-23   NAL unit     yes              yes               no
  24     STAP-A        no              yes               no
  25     STAP-B        no               no              yes
  26     MTAP16        no               no              yes
  27     MTAP24        no               no              yes
  28     FU-A          no              yes              yes
  29     FU-B          no               no              yes
  30-31  reserved      ig               ig               ig

2.2 Single NAL Unit Packet

在一個rtp'包中,只包含有一個完整的Nal Unit(視頻幀)。

例: 如有一個 H.264 的 NALU 是這樣的:
[00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]
這是一個序列參數集 NAL 單元. [00 00 00 01] 是四個字節的開始碼, 67 是 NALU 頭, 42 開始的數據是 NALU 內容.

封裝成 RTP 包將如下:

[ F|NRI| Type ] [ 67 42 A0 1E 23 56 0E 2F ]

a single NAL unit :[ 67 42 A0 1E 23 56 0E 2F ], 即只要去掉 4 個字節的開始碼就可以了.

--
0 1 2 3
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|F|NRI| Type | |
+-+-+-+-+-+-+-+-+ |
| |
| Bytes 2..n of a single NAL unit |
| |
| +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| :...OPTIONAL RTP padding |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 2.  RTP payload format for single NAL unit packet

2.3 Aggregation Packets

在一個rtp包中,會有多個Nul Unit(一個rtp包帶多個視頻幀)。這種情況會在視頻幀比較小的時候采用。

  1. Single-time aggregation packet (STAP):
    • STAP-A: without DON

例:

如有一個 H.264 的 NALU 是這樣的:

[00 00 00 01 67 42 A0 1E 23 56 0E 2F ... ]
[00 00 00 01 68 42 B0 12 58 6A D4 FF ... ]

封裝成 RTP 包將如下:

[ STAP-A NAL HDR ] [78 (STAP-A頭,占用1個字節)] [第一個NALU長度 (占用兩個字節)] [ 67 42 A0 1E 23 56 0E 2F ] [第二個NALU長度 (占用兩個字節)] [68 42 B0 12 58 6A D4 FF ... ]

		  0                   1                   2                   3
		 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|                          RTP Header                           |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|STAP-A NAL HDR |         NALU 1 Size           | NALU 1 HDR    |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|                         NALU 1 Data                           |
		:                                                               :
		+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|               | NALU 2 Size                   | NALU 2 HDR    |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|                         NALU 2 Data                           |
		:                                                               :
		|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|                               :...OPTIONAL RTP padding        |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
			
		Figure 7.  An example of an RTP packet including an STAP-A
		           containing two single-time aggregation units
	           
	           
		<!---->
       
* STAP-B: including DON

	<!---->


		 0                   1                   2                   3
		 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|                          RTP Header                           |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|STAP-B NAL HDR | DON                           | NALU 1 Size   |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		| NALU 1 Size   | NALU 1 HDR    | NALU 1 Data                   |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
		:                                                               :
		+               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|               | NALU 2 Size                   | NALU 2 HDR    |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|                       NALU 2 Data                             |
		:                                                               :
		|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
		|                               :...OPTIONAL RTP padding        |
		+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
			
		Figure 8.  An example of an RTP packet including an STAP-B
		           containing two single-time aggregation units


<!---->
  1. Multi-time aggregation packet (MTAP):

    這兩種MAPS的區別在於 timestamp offset 的長度不同。

    • MTAP16:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                          RTP Header                           |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |MTAP16 NAL HDR |  decoding order number base   | NALU 1 Size   |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |  NALU 1 Size  |  NALU 1 DOND  |       NALU 1 TS offset        |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |  NALU 1 HDR   |  NALU 1 DATA                                  |
        +-+-+-+-+-+-+-+-+                                               +
        :                                                               :
        +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |               | NALU 2 SIZE                   |  NALU 2 DOND  |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |       NALU 2 TS offset        |  NALU 2 HDR   |  NALU 2 DATA  |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+               |
        :                                                               :
        |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                               :...OPTIONAL RTP padding        |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        
        Figure 12.  An RTP packet including a multi-time aggregation
        			    packet of type MTAP16 containing two multi-time
        			    aggregation units
      
    • MTAP24:

        0                   1                   2                   3
        0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                          RTP Header                           |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |MTAP24 NAL HDR |  decoding order number base   | NALU 1 Size   |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |  NALU 1 Size  |  NALU 1 DOND  |       NALU 1 TS offs          |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |NALU 1 TS offs |  NALU 1 HDR   |  NALU 1 DATA                  |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               +
        :                                                               :
        +               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |               | NALU 2 SIZE                   |  NALU 2 DOND  |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |       NALU 2 TS offset                        |  NALU 2 HDR   |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |  NALU 2 DATA                                                  |
        :                                                               :
        |                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        |                               :...OPTIONAL RTP padding        |
        +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
        
        Figure 13.  An RTP packet including a multi-time aggregation
        		    packet of type MTAP24 containing two multi-time
        		    aggregation units
      

--

2.4 Fragmentation Units

一個Nal Unit會被分割成,通過多個rtp包進行發送,這樣便於傳輸和以后做fec處理。

  • FU-A:
 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator  |   FU header   |                               |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+                               |
|                                                               |
|                         FU payload                            |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :...OPTIONAL RTP padding        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 14.  RTP payload format for FU-A
  • FU-B:

 0                   1                   2                   3
 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
| FU indicator  |   FU header   |               DON             |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-|
|                                                               |
|                         FU payload                            |
|                                                               |
|                               +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|                               :...OPTIONAL RTP padding        |
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+

Figure 15.  RTP payload format for FU-B

The FU indicator octet has the following format:

   +---------------+
   |0|1|2|3|4|5|6|7|
   +-+-+-+-+-+-+-+-+
   |F|NRI|  Type   |
   +---------------+

The FU header has the following format:

  • S:1表示第一包
  • E:1表示是最后一個包
  • R:1表示中間
  • Type:類型
  +---------------+
  |0|1|2|3|4|5|6|7|
  +-+-+-+-+-+-+-+-+
  |S|E|R|  Type   |
  +---------------+

目前webrtc中使用的打包代碼如下:

	void RtpPacketizerH264::GeneratePackets() {
	  LOG(LS_VERBOSE) << "RtpPacketizerH264::GeneratePackets packetization_mode "
	                  << (int)packetization_mode_
	                  << " max_payload_len "
	                  << max_payload_len_
	                  ;
	
	  for (size_t i = 0; i < input_fragments_.size();) {
	    switch (packetization_mode_) {
	      case H264PacketizationMode::SingleNalUnit:
	        PacketizeSingleNalu(i);
	        ++i;
	        break;
	      case H264PacketizationMode::NonInterleaved:
	        size_t fragment_len = input_fragments_[i].length;
	        if (i + 1 == input_fragments_.size()) {
	          // Pretend that last fragment is larger instead of making last packet
	          // smaller.
	          fragment_len += last_packet_reduction_len_;
	        }
	        if (fragment_len > max_payload_len_) {
	          PacketizeFuA(i);
	          ++i;
	        } else {
	          i = PacketizeStapA(i);
	        }
	        break;
	    }
	  }
	}

第二部分:接收端的數據流處理

先看一下整理的類圖

這里寫圖片描述

處理流程如下

  1. 首先在cricket::WebRtcVideoChannel中的OnPacketReceived函數中,我們會收到RTP包。這個是通過ICE 建立的UDP鏈接傳來的數據。
  2. RTP數據包一直走到webrtc::RtpVideoStreamReceiver的OnPacketReceived函數中,調用webrtc::RtpReceiverImpl的IncomingRtpPacket進行rtp 包解析。
  3. 解析完之后的數據,會通過OnReceivedPayloadData回調上來,webrtc::RtpVideoStreamReceiver會將接收到的rtp包數據,打包成VCMPacket的形式,插入到PacketBuffer中。
  4. PacketBuffer的主要工作就是收集rtp包,並且判斷這些rtp包能否組裝成一個完整的H264的Frame。主要的實現邏輯就是每次在InsertPacket的最后,都調用FindFrames函數去查是否有合適的幀組成。
  5. 如果發現一個完整的幀,PacketBuffer會通過OnReceivedFrame把frame數據回調給webrtc::RtpVideoStreamReceiver。然后再通過video_coding::RtpFrameReferenceFinder的ManageFrame來查找,是否有合適的幀可以送給Decoder解碼。這里的合適主要分一下幾點:
    • 判斷幀是否連續
    • 判斷參考幀是有沒有丟失
    • 是否是IFRAME
  6. 找到decodeble的幀后,video_coding::RtpFrameReferenceFinder通過OnCompleteFrame把frame交給internal::VideoReceiveStream,它會把frame插入到FrameBuffer中。
  7. 這里的FrameBuffer,就是以前版本的jitter buffer。在新的webrtc中已經更名。
  8. internal::VideoReceiveStream內部有一個decode 線程,這個線程會定期問是否有合適的Frame可以送給decode解碼。如果有,則把它送到vcm::VideoReceiver去解碼。
  9. vcm::VideoReceiver中持有decode的外部類,VCMGenericDecoder。我們把數據送給他,如果有decode解碼完的YUV數據,他會把數據通過FrameToRender 回調webrtc::VideoStreamDecoder。
  10. 最終,webrtc::VideoStreamDecoder把YUV數據通過OnFrame回調給internal::VideoReceiveStream。在這里,webrtc就會把YUV數據傳給之前注冊的Render。

小結

整體的數據流程在上面的已經做了一個簡單的描述,其中比較主要的是還標黃色的幾個類。由於時間有限,還是會有很多具體的細節沒有擴展,比如packet buffer的拼frame的邏輯,FrameBuffer找decodable frame的邏輯。這些可以在下次的文章中再和大家分享。


喜歡的同學可以掃碼進群討論:
這里寫圖片描述


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM