tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

rtp_format.cc (5703B)


      1 /*
      2 *  Copyright (c) 2014 The WebRTC project authors. All Rights Reserved.
      3 *
      4 *  Use of this source code is governed by a BSD-style license
      5 *  that can be found in the LICENSE file in the root of the source
      6 *  tree. An additional intellectual property rights grant can be found
      7 *  in the file PATENTS.  All contributing project authors may
      8 *  be found in the AUTHORS file in the root of the source tree.
      9 */
     10 
     11 #include "modules/rtp_rtcp/source/rtp_format.h"
     12 
     13 #include <cstdint>
     14 #include <memory>
     15 #include <optional>
     16 #include <vector>
     17 
     18 #include "api/array_view.h"
     19 #include "api/video/video_codec_type.h"
     20 #include "modules/rtp_rtcp/source/rtp_format_h264.h"
     21 #include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
     22 #include "modules/rtp_rtcp/source/rtp_format_vp8.h"
     23 #include "modules/rtp_rtcp/source/rtp_format_vp9.h"
     24 #include "modules/rtp_rtcp/source/rtp_packetizer_av1.h"
     25 #include "modules/video_coding/codecs/h264/include/h264_globals.h"
     26 #include "modules/video_coding/codecs/vp8/include/vp8_globals.h"
     27 #include "modules/video_coding/codecs/vp9/include/vp9_globals.h"
     28 #include "rtc_base/checks.h"
     29 #ifdef RTC_ENABLE_H265
     30 #include "modules/rtp_rtcp/source/rtp_packetizer_h265.h"
     31 #endif
     32 
     33 namespace webrtc {
     34 
     35 std::unique_ptr<RtpPacketizer> RtpPacketizer::Create(
     36    std::optional<VideoCodecType> type,
     37    ArrayView<const uint8_t> payload,
     38    PayloadSizeLimits limits,
     39    // Codec-specific details.
     40    const RTPVideoHeader& rtp_video_header) {
     41  if (!type) {
     42    // Use raw packetizer.
     43    return std::make_unique<RtpPacketizerGeneric>(payload, limits);
     44  }
     45 
     46  switch (*type) {
     47    case kVideoCodecH264: {
     48      const auto& h264 =
     49          std::get<RTPVideoHeaderH264>(rtp_video_header.video_type_header);
     50      return std::make_unique<RtpPacketizerH264>(payload, limits,
     51                                                 h264.packetization_mode);
     52    }
     53    case kVideoCodecVP8: {
     54      const auto& vp8 =
     55          std::get<RTPVideoHeaderVP8>(rtp_video_header.video_type_header);
     56      return std::make_unique<RtpPacketizerVp8>(payload, limits, vp8);
     57    }
     58    case kVideoCodecVP9: {
     59      const auto& vp9 =
     60          std::get<RTPVideoHeaderVP9>(rtp_video_header.video_type_header);
     61      return std::make_unique<RtpPacketizerVp9>(payload, limits, vp9);
     62    }
     63    case kVideoCodecAV1:
     64      return std::make_unique<RtpPacketizerAv1>(
     65          payload, limits, rtp_video_header.frame_type,
     66          rtp_video_header.is_last_frame_in_picture);
     67 #ifdef RTC_ENABLE_H265
     68    case kVideoCodecH265: {
     69      return std::make_unique<RtpPacketizerH265>(payload, limits);
     70    }
     71 #endif
     72    default: {
     73      return std::make_unique<RtpPacketizerGeneric>(payload, limits,
     74                                                    rtp_video_header);
     75    }
     76  }
     77 }
     78 
     79 std::vector<int> RtpPacketizer::SplitAboutEqually(
     80    int payload_len,
     81    const PayloadSizeLimits& limits) {
     82  RTC_DCHECK_GT(payload_len, 0);
     83  // First or last packet larger than normal are unsupported.
     84  RTC_DCHECK_GE(limits.first_packet_reduction_len, 0);
     85  RTC_DCHECK_GE(limits.last_packet_reduction_len, 0);
     86 
     87  std::vector<int> result;
     88  if (limits.max_payload_len >=
     89      limits.single_packet_reduction_len + payload_len) {
     90    result.push_back(payload_len);
     91    return result;
     92  }
     93  if (limits.max_payload_len - limits.first_packet_reduction_len < 1 ||
     94      limits.max_payload_len - limits.last_packet_reduction_len < 1) {
     95    // Capacity is not enough to put a single byte into one of the packets.
     96    return result;
     97  }
     98  // First and last packet of the frame can be smaller. Pretend that it's
     99  // the same size, but we must write more payload to it.
    100  // Assume frame fits in single packet if packet has extra space for sum
    101  // of first and last packets reductions.
    102  int total_bytes = payload_len + limits.first_packet_reduction_len +
    103                    limits.last_packet_reduction_len;
    104  // Integer divisions with rounding up.
    105  int num_packets_left =
    106      (total_bytes + limits.max_payload_len - 1) / limits.max_payload_len;
    107  if (num_packets_left == 1) {
    108    // Single packet is a special case handled above.
    109    num_packets_left = 2;
    110  }
    111 
    112  if (payload_len < num_packets_left) {
    113    // Edge case where limits force to have more packets than there are payload
    114    // bytes. This may happen when there is single byte of payload that can't be
    115    // put into single packet if
    116    // first_packet_reduction + last_packet_reduction >= max_payload_len.
    117    return result;
    118  }
    119 
    120  int bytes_per_packet = total_bytes / num_packets_left;
    121  int num_larger_packets = total_bytes % num_packets_left;
    122  int remaining_data = payload_len;
    123 
    124  result.reserve(num_packets_left);
    125  bool first_packet = true;
    126  while (remaining_data > 0) {
    127    // Last num_larger_packets are 1 byte wider than the rest. Increase
    128    // per-packet payload size when needed.
    129    if (num_packets_left == num_larger_packets)
    130      ++bytes_per_packet;
    131    int current_packet_bytes = bytes_per_packet;
    132    if (first_packet) {
    133      if (current_packet_bytes > limits.first_packet_reduction_len + 1)
    134        current_packet_bytes -= limits.first_packet_reduction_len;
    135      else
    136        current_packet_bytes = 1;
    137    }
    138    if (current_packet_bytes > remaining_data) {
    139      current_packet_bytes = remaining_data;
    140    }
    141    // This is not the last packet in the whole payload, but there's no data
    142    // left for the last packet. Leave at least one byte for the last packet.
    143    if (num_packets_left == 2 && current_packet_bytes == remaining_data) {
    144      --current_packet_bytes;
    145    }
    146    result.push_back(current_packet_bytes);
    147 
    148    remaining_data -= current_packet_bytes;
    149    --num_packets_left;
    150    first_packet = false;
    151  }
    152 
    153  return result;
    154 }
    155 
    156 }  // namespace webrtc