webrtc代码走读十三(RTPSenderVideo::SendVideo视频打包)

一、编码到发包函数调用图

二、编码函数代码走读

encoded_image_缓存的是编码后的数据。frag_header是NALS组信息。

encoded_image_缓存数据格式为:4个字节起始码+NALHead+date+4个字节起始码+NALHead+date.......

RTPFragmentationHeader* frag_header参数fragmentationOffset和fragmentationLength含义如下:

三、发包函数代码走读

RTPSenderVideo::SendVideo函数四个变量比较绕,整理含义如下(该图没有包含FEC_head):

rtp_sender_->MaxRtpPacketSize()=kVideoMtu:报文最大长度。

packet_capacity:报文去掉RtxHeader后的长度。

max_data_payload_length:名称虽然是总净荷长度,但是实际上这个长度中包含了extension字段。

last_packet_reduction_len:新增extension字段组总长度。如下三个extension长度。

关于extension字段介绍连接如下:webrtc代码走读七(rtp包格式)_CrystalShaw的博客-CSDN博客_webrtc 代码走读

备注说明:

last_packet_reduction_len通过last_packet->headers_size() - rtp_header->headers_size()计算得出。

rtp_header->headers_size()的计算流程是:

->rtp_sender_->AllocatePacket()

->packet->SetCsrcs

->payload_offset_ = kFixedHeaderSize + 4 * csrcs.size();

->rtp_sender_->AllocatePacket()

->packet->ReserveExtension()

->packet->AllocateExtension()

->packet->AllocateRawExtension()

->payload_offset_ = extensions_offset + 4 * extensions_words;

last_packet->headers_size()的计算流程是:

->packet->SetExtension()

->packet->AllocateExtension()

->packet->AllocateRawExtension()

->payload_offset_ = extensions_offset + 4 * extensions_words;

四、备注说明

1、RTX格式定义

根据RFC4588格式定义:RFC 4588 - RTP Retransmission Payload Format

const size_t kRtxHeaderSize = 2;

kRtxHeaderSize是两个字节的OSN。封装RTX代码函数为:std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket

std::unique_ptr<RtpPacketToSend> RTPSender::BuildRtxPacket(
    const RtpPacketToSend& packet) {
  std::unique_ptr<RtpPacketToSend> rtx_packet;

  // Add original RTP header.
  {
    MutexLock lock(&send_mutex_);
    if (!sending_media_)
      return nullptr;

    RTC_DCHECK(rtx_ssrc_);

    // Replace payload type.
    auto kv = rtx_payload_type_map_.find(packet.PayloadType());
    if (kv == rtx_payload_type_map_.end())
      return nullptr;

    rtx_packet = std::make_unique<RtpPacketToSend>(&rtp_header_extension_map_,
                                                   max_packet_size_);

    rtx_packet->SetPayloadType(kv->second);

    // Replace sequence number.
    rtx_packet->SetSequenceNumber(sequence_number_rtx_++);

    // Replace SSRC.
    rtx_packet->SetSsrc(*rtx_ssrc_);

    CopyHeaderAndExtensionsToRtxPacket(packet, rtx_packet.get());

    // RTX packets are sent on an SSRC different from the main media, so the
    // decision to attach MID and/or RRID header extensions is completely
    // separate from that of the main media SSRC.
    //
    // Note that RTX packets must used the RepairedRtpStreamId (RRID) header
    // extension instead of the RtpStreamId (RID) header extension even though
    // the payload is identical.
    if (always_send_mid_and_rid_ || !rtx_ssrc_has_acked_) {
      // These are no-ops if the corresponding header extension is not
      // registered.
      if (!mid_.empty()) {
        rtx_packet->SetExtension<RtpMid>(mid_);
      }
      if (!rid_.empty()) {
        rtx_packet->SetExtension<RepairedRtpStreamId>(rid_);
      }
    }
  }
  RTC_DCHECK(rtx_packet);

  uint8_t* rtx_payload =
      rtx_packet->AllocatePayload(packet.payload_size() + kRtxHeaderSize);
  if (rtx_payload == nullptr)
    return nullptr;

  // Add OSN (original sequence number).
  ByteWriter<uint16_t>::WriteBigEndian(rtx_payload, packet.SequenceNumber());

  // Add original payload data.
  auto payload = packet.payload();
  memcpy(rtx_payload + kRtxHeaderSize, payload.data(), payload.size());

  // Add original application data.
  rtx_packet->set_application_data(packet.application_data());
  rtx_packet->set_additional_data(packet.additional_data());

  // Copy capture time so e.g. TransmissionOffset is correctly set.
  rtx_packet->set_capture_time_ms(packet.capture_time_ms());

  return rtx_packet;
}

打上一个新的RTX头,然后把原始报文的序列号填写在OSN这里,附在载荷前面。但是载荷会加密,所以我们在wireshark抓包这里,可能看不到恢复后的原始报文序列号。

webrtc的RTX目前音频和视频使用的是同一个SSRC,音视频混用一套SequenceNum。只是PT值有区分。

 

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值