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