WEBRTC 接收H264 RTP資料流小結

jerrysun發表於2021-09-09

WEBRTC 接收H264 RTP資料流小結

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

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

參考連結:

RTP Payload Format

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

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

  1. 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;
        }
      }
    }

第二部分:接收端的資料流處理

先看一下整理的類圖

圖片描述

video_receive_stream.jpg

處理流程如下

  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

找到decodeble的幀後,video_coding::RtpFrameReferenceFinder透過OnCompleteFrame把frame交給internal::VideoReceiveStream,它會把frame插入到FrameBuffer中。

這裡的FrameBuffer,就是以前版本的jitter buffer。在新的webrtc中已經更名。

internal::VideoReceiveStream內部有一個decode 執行緒,這個執行緒會定期問是否有合適的Frame可以送給decode解碼。如果有,則把它送到vcm::VideoReceiver去解碼。

vcm::VideoReceiver中持有decode的外部類,VCMGenericDecoder。我們把資料送給他,如果有decode解碼完的YUV資料,他會把資料透過FrameToRender 回撥webrtc::VideoStreamDecoder。

最終,webrtc::VideoStreamDecoder把YUV資料透過OnFrame回撥給internal::VideoReceiveStream。在這裡,webrtc就會把YUV資料傳給之前註冊的Render。

總結

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



作者:木韋雜貨店
連結:


來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/151/viewspace-2821343/,如需轉載,請註明出處,否則將追究法律責任。

相關文章