blob: 532e06950ce229f0c2634adf18f200895c33d43d [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:251/*
pwestin@webrtc.orgf6bb77a2012-01-24 17:16:592 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:253 *
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
Mirko Bonadei92ea95e2017-09-15 04:47:3111#include "modules/rtp_rtcp/source/rtp_sender_video.h"
niklase@google.com470e71d2011-07-07 08:21:2512
pbos@webrtc.orga048d7c2013-05-29 14:27:3813#include <stdlib.h>
14#include <string.h>
niklase@google.com470e71d2011-07-07 08:21:2515
Erik Språng56e611b2020-02-06 16:10:0816#include <algorithm>
spranga8ae6f22017-09-04 14:23:5617#include <limits>
kwiberg84be5112016-04-27 08:19:5818#include <memory>
Elad Alon8b60e8b2019-04-08 12:14:0519#include <string>
danilchap74110612016-10-02 17:54:2920#include <utility>
mflodmanfcf54bd2015-04-14 19:28:0821
Danil Chapovalov670af262020-01-30 15:28:5322#include "absl/memory/memory.h"
Niels Mölleraa3c1cc2018-11-02 09:54:5623#include "absl/strings/match.h"
Steve Anton10542f22019-01-11 17:11:0024#include "api/crypto/frame_encryptor_interface.h"
Danil Chapovalov670af262020-01-30 15:28:5325#include "api/transport/rtp/dependency_descriptor.h"
Niels Möller59ab1cf2019-02-06 21:48:1126#include "modules/remote_bitrate_estimator/test/bwe_test_logging.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3127#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
Minyue Li5bb9adc2020-01-22 12:02:3428#include "modules/rtp_rtcp/source/absolute_capture_time_sender.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3129#include "modules/rtp_rtcp/source/byte_io.h"
Danil Chapovalov670af262020-01-30 15:28:5330#include "modules/rtp_rtcp/source/rtp_dependency_descriptor_extension.h"
Mirta Dvornicicfe68daa2019-05-23 11:21:1231#include "modules/rtp_rtcp/source/rtp_format.h"
philipelb3e42a42018-09-13 08:57:1432#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3133#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
34#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
Minyue Li5bb9adc2020-01-22 12:02:3435#include "modules/rtp_rtcp/source/time_util.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3136#include "rtc_base/checks.h"
37#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3138#include "rtc_base/trace_event.h"
ilniked9b9ff2017-06-02 14:30:2039
niklase@google.com470e71d2011-07-07 08:21:2540namespace webrtc {
Sergey Ulanovec4f0682016-07-28 22:19:1041
brandtr6631e8a2016-09-13 10:23:2942namespace {
43constexpr size_t kRedForFecHeaderLength = 1;
spranga8ae6f22017-09-04 14:23:5644constexpr int64_t kMaxUnretransmittableFrameIntervalMs = 33 * 4;
danilchap74110612016-10-02 17:54:2945
Anton Sukhanov1a13c8f2019-07-25 21:36:4146// This is experimental field trial to exclude transport sequence number from
47// FEC packets and should only be used in conjunction with datagram transport.
48// Datagram transport removes transport sequence numbers from RTP packets and
49// uses datagram feedback loop to re-generate RTCP feedback packets, but FEC
50// contorol packets are calculated before sequence number is removed and as a
51// result recovered packets will be corrupt unless we also remove transport
52// sequence number during FEC calculation.
53//
54// TODO(sukhanov): We need to find find better way to implement FEC with
55// datagram transport, probably moving FEC to datagram integration layter. We
56// should also remove special field trial once we switch datagram path from
57// RTCConfiguration flags to field trial and use the same field trial for FEC
58// workaround.
59const char kExcludeTransportSequenceNumberFromFecFieldTrial[] =
60 "WebRTC-ExcludeTransportSequenceNumberFromFec";
61
danilchap74110612016-10-02 17:54:2962void BuildRedPayload(const RtpPacketToSend& media_packet,
63 RtpPacketToSend* red_packet) {
64 uint8_t* red_payload = red_packet->AllocatePayload(
65 kRedForFecHeaderLength + media_packet.payload_size());
66 RTC_DCHECK(red_payload);
67 red_payload[0] = media_packet.PayloadType();
danilchap96c15872016-11-21 09:35:2968
69 auto media_payload = media_packet.payload();
70 memcpy(&red_payload[kRedForFecHeaderLength], media_payload.data(),
71 media_payload.size());
danilchap74110612016-10-02 17:54:2972}
Danil Chapovalove4f8b382018-09-07 15:30:2673
Minyue Li5bb9adc2020-01-22 12:02:3474void AddRtpHeaderExtensions(
75 const RTPVideoHeader& video_header,
76 const absl::optional<PlayoutDelay>& playout_delay,
77 const absl::optional<AbsoluteCaptureTime>& absolute_capture_time,
Danil Chapovalov670af262020-01-30 15:28:5378 FrameDependencyStructure* video_structure,
Minyue Li5bb9adc2020-01-22 12:02:3479 bool set_video_rotation,
80 bool set_color_space,
81 bool set_frame_marking,
82 bool first_packet,
83 bool last_packet,
84 RtpPacketToSend* packet) {
Johannes Krond0b69a82018-12-03 13:18:5385 // Color space requires two-byte header extensions if HDR metadata is
86 // included. Therefore, it's best to add this extension first so that the
87 // other extensions in the same packet are written as two-byte headers at
88 // once.
89 if (last_packet && set_color_space && video_header.color_space)
90 packet->SetExtension<ColorSpaceExtension>(video_header.color_space.value());
91
Danil Chapovalove4f8b382018-09-07 15:30:2692 if (last_packet && set_video_rotation)
93 packet->SetExtension<VideoOrientation>(video_header.rotation);
94
95 // Report content type only for key frames.
Danil Chapovalov51bf2002019-10-11 08:53:2796 if (last_packet &&
97 video_header.frame_type == VideoFrameType::kVideoFrameKey &&
Danil Chapovalove4f8b382018-09-07 15:30:2698 video_header.content_type != VideoContentType::UNSPECIFIED)
99 packet->SetExtension<VideoContentTypeExtension>(video_header.content_type);
100
101 if (last_packet &&
102 video_header.video_timing.flags != VideoSendTiming::kInvalid)
103 packet->SetExtension<VideoTimingExtension>(video_header.video_timing);
philipelb3e42a42018-09-13 08:57:14104
Niels Möller6893f3c2019-01-31 07:56:26105 // If transmitted, add to all packets; ack logic depends on this.
106 if (playout_delay) {
107 packet->SetExtension<PlayoutDelayLimits>(*playout_delay);
108 }
Johnny Lee1a1c52b2019-02-08 19:25:40109
Minyue Li5bb9adc2020-01-22 12:02:34110 if (first_packet && absolute_capture_time) {
111 packet->SetExtension<AbsoluteCaptureTimeExtension>(*absolute_capture_time);
112 }
113
Johnny Lee1a1c52b2019-02-08 19:25:40114 if (set_frame_marking) {
115 FrameMarking frame_marking = video_header.frame_marking;
116 frame_marking.start_of_frame = first_packet;
117 frame_marking.end_of_frame = last_packet;
118 packet->SetExtension<FrameMarkingExtension>(frame_marking);
119 }
120
philipelb3e42a42018-09-13 08:57:14121 if (video_header.generic) {
Danil Chapovalov670af262020-01-30 15:28:53122 bool extension_is_set = false;
123 if (video_structure != nullptr) {
124 DependencyDescriptor descriptor;
125 descriptor.first_packet_in_frame = first_packet;
126 descriptor.last_packet_in_frame = last_packet;
127 descriptor.frame_number = video_header.generic->frame_id & 0xFFFF;
128 descriptor.frame_dependencies.spatial_id =
129 video_header.generic->spatial_index;
130 descriptor.frame_dependencies.temporal_id =
131 video_header.generic->temporal_index;
philipelb3e42a42018-09-13 08:57:14132 for (int64_t dep : video_header.generic->dependencies) {
Danil Chapovalov670af262020-01-30 15:28:53133 descriptor.frame_dependencies.frame_diffs.push_back(
philipelb3e42a42018-09-13 08:57:14134 video_header.generic->frame_id - dep);
135 }
Danil Chapovalov670af262020-01-30 15:28:53136 descriptor.frame_dependencies.decode_target_indications =
137 video_header.generic->decode_target_indications;
138 RTC_DCHECK_EQ(
139 descriptor.frame_dependencies.decode_target_indications.size(),
140 video_structure->num_decode_targets);
philipelb3e42a42018-09-13 08:57:14141
Danil Chapovalov670af262020-01-30 15:28:53142 // To avoid extra structure copy, temporary share ownership of the
143 // video_structure with the dependency descriptor.
144 if (video_header.frame_type == VideoFrameType::kVideoFrameKey &&
145 first_packet) {
146 descriptor.attached_structure = absl::WrapUnique(video_structure);
philipelfab91292018-10-17 12:36:08147 }
Danil Chapovalov670af262020-01-30 15:28:53148 extension_is_set = packet->SetExtension<RtpDependencyDescriptorExtension>(
149 *video_structure, descriptor);
150
151 // Remove the temporary shared ownership.
152 descriptor.attached_structure.release();
philipelb3e42a42018-09-13 08:57:14153 }
philipel59c85692019-03-15 14:26:31154
Danil Chapovalov670af262020-01-30 15:28:53155 // Do not use v0/v1 generic frame descriptor when v2 is stored.
156 if (!extension_is_set) {
157 RtpGenericFrameDescriptor generic_descriptor;
158 generic_descriptor.SetFirstPacketInSubFrame(first_packet);
159 generic_descriptor.SetLastPacketInSubFrame(last_packet);
160 generic_descriptor.SetDiscardable(video_header.generic->discardable);
161
162 if (first_packet) {
163 generic_descriptor.SetFrameId(
164 static_cast<uint16_t>(video_header.generic->frame_id));
165 for (int64_t dep : video_header.generic->dependencies) {
166 generic_descriptor.AddFrameDependencyDiff(
167 video_header.generic->frame_id - dep);
168 }
169
170 uint8_t spatial_bimask = 1 << video_header.generic->spatial_index;
171 generic_descriptor.SetSpatialLayersBitmask(spatial_bimask);
172
173 generic_descriptor.SetTemporalLayer(
174 video_header.generic->temporal_index);
175
176 if (video_header.frame_type == VideoFrameType::kVideoFrameKey) {
177 generic_descriptor.SetResolution(video_header.width,
178 video_header.height);
179 }
180 }
181
182 if (!packet->SetExtension<RtpGenericFrameDescriptorExtension01>(
183 generic_descriptor)) {
184 packet->SetExtension<RtpGenericFrameDescriptorExtension00>(
185 generic_descriptor);
186 }
Elad Alonccb9b752019-02-19 12:01:31187 }
philipelb3e42a42018-09-13 08:57:14188 }
Danil Chapovalove4f8b382018-09-07 15:30:26189}
190
Danil Chapovalov51bf2002019-10-11 08:53:27191bool MinimizeDescriptor(RTPVideoHeader* video_header) {
192 if (auto* vp8 =
193 absl::get_if<RTPVideoHeaderVP8>(&video_header->video_type_header)) {
Danil Chapovalov84ffb352018-09-25 16:59:09194 // Set minimum fields the RtpPacketizer is using to create vp8 packets.
Danil Chapovalov51bf2002019-10-11 08:53:27195 // nonReference is the only field that doesn't require extra space.
196 bool non_reference = vp8->nonReference;
197 vp8->InitRTPVideoHeaderVP8();
198 vp8->nonReference = non_reference;
Danil Chapovalov84ffb352018-09-25 16:59:09199 return true;
200 }
201 // TODO(danilchap): Reduce vp9 codec specific descriptor too.
202 return false;
203}
204
Johannes Krond0b69a82018-12-03 13:18:53205bool IsBaseLayer(const RTPVideoHeader& video_header) {
206 switch (video_header.codec) {
207 case kVideoCodecVP8: {
208 const auto& vp8 =
209 absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
210 return (vp8.temporalIdx == 0 || vp8.temporalIdx == kNoTemporalIdx);
211 }
212 case kVideoCodecVP9: {
213 const auto& vp9 =
214 absl::get<RTPVideoHeaderVP9>(video_header.video_type_header);
215 return (vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
216 }
217 case kVideoCodecH264:
218 // TODO(kron): Implement logic for H264 once WebRTC supports temporal
219 // layers for H264.
220 break;
221 default:
222 break;
223 }
224 return true;
225}
226
Doudou Kisabaka2dec4962019-11-28 13:24:31227#if RTC_TRACE_EVENTS_ENABLED
Niels Möller87e2d782019-03-07 09:18:23228const char* FrameTypeToString(VideoFrameType frame_type) {
Niels Möller59ab1cf2019-02-06 21:48:11229 switch (frame_type) {
Niels Möller8f7ce222019-03-21 14:43:58230 case VideoFrameType::kEmptyFrame:
Niels Möller59ab1cf2019-02-06 21:48:11231 return "empty";
Niels Möller8f7ce222019-03-21 14:43:58232 case VideoFrameType::kVideoFrameKey:
Niels Möller59ab1cf2019-02-06 21:48:11233 return "video_key";
Niels Möller8f7ce222019-03-21 14:43:58234 case VideoFrameType::kVideoFrameDelta:
Niels Möller59ab1cf2019-02-06 21:48:11235 return "video_delta";
236 default:
237 RTC_NOTREACHED();
238 return "";
239 }
240}
Doudou Kisabaka2dec4962019-11-28 13:24:31241#endif
Niels Möller59ab1cf2019-02-06 21:48:11242
Erik Språng56e611b2020-02-06 16:10:08243bool IsNoopDelay(const PlayoutDelay& delay) {
244 return delay.min_ms == -1 && delay.max_ms == -1;
245}
246
brandtr6631e8a2016-09-13 10:23:29247} // namespace
niklase@google.com470e71d2011-07-07 08:21:25248
brandtrdbdb3f12016-11-10 13:04:48249RTPSenderVideo::RTPSenderVideo(Clock* clock,
250 RTPSender* rtp_sender,
Benjamin Wright192eeec2018-10-18 00:27:25251 FlexfecSender* flexfec_sender,
Niels Möller5fe95102019-03-04 15:49:25252 PlayoutDelayOracle* playout_delay_oracle,
Benjamin Wright192eeec2018-10-18 00:27:25253 FrameEncryptorInterface* frame_encryptor,
Per Kjellandere11b7d22019-02-21 06:55:59254 bool require_frame_encryption,
Andrei Dumitru09872732019-08-29 19:00:29255 bool enable_retransmit_all_layers,
Per Kjellandere11b7d22019-02-21 06:55:59256 const WebRtcKeyValueConfig& field_trials)
Erik Språngdc34a252019-10-04 13:17:29257 : RTPSenderVideo([&] {
258 Config config;
259 config.clock = clock;
260 config.rtp_sender = rtp_sender;
261 config.flexfec_sender = flexfec_sender;
Erik Språngdc34a252019-10-04 13:17:29262 config.frame_encryptor = frame_encryptor;
263 config.require_frame_encryption = require_frame_encryption;
Erik Språngdc34a252019-10-04 13:17:29264 config.enable_retransmit_all_layers = enable_retransmit_all_layers;
265 config.field_trials = &field_trials;
266 return config;
267 }()) {}
268
269RTPSenderVideo::RTPSenderVideo(const Config& config)
270 : rtp_sender_(config.rtp_sender),
271 clock_(config.clock),
Andrei Dumitru09872732019-08-29 19:00:29272 retransmission_settings_(
Erik Språngdc34a252019-10-04 13:17:29273 config.enable_retransmit_all_layers
Andrei Dumitru09872732019-08-29 19:00:29274 ? kRetransmitAllLayers
275 : (kRetransmitBaseLayer | kConditionallyRetransmitHigherLayers)),
brandtrd8048952016-11-07 10:08:51276 last_rotation_(kVideoRotation_0),
Johannes Krond0b69a82018-12-03 13:18:53277 transmit_color_space_next_frame_(false),
Erik Språng56e611b2020-02-06 16:10:08278 current_playout_delay_{-1, -1},
279 playout_delay_pending_(false),
Erik Språngdc34a252019-10-04 13:17:29280 red_payload_type_(config.red_payload_type),
281 ulpfec_payload_type_(config.ulpfec_payload_type),
282 flexfec_sender_(config.flexfec_sender),
brandtrd8048952016-11-07 10:08:51283 delta_fec_params_{0, 1, kFecMaskRandom},
284 key_fec_params_{0, 1, kFecMaskRandom},
sprangcd349d92016-07-13 16:11:28285 fec_bitrate_(1000, RateStatistics::kBpsScale),
Benjamin Wright192eeec2018-10-18 00:27:25286 video_bitrate_(1000, RateStatistics::kBpsScale),
Erik Språng482b3ef2019-01-08 15:19:11287 packetization_overhead_bitrate_(1000, RateStatistics::kBpsScale),
Erik Språngdc34a252019-10-04 13:17:29288 frame_encryptor_(config.frame_encryptor),
289 require_frame_encryption_(config.require_frame_encryption),
Benjamin Wright168456c2018-12-07 19:31:25290 generic_descriptor_auth_experiment_(
Erik Språngdc34a252019-10-04 13:17:29291 config.field_trials->Lookup("WebRTC-GenericDescriptorAuth")
292 .find("Enabled") == 0),
Anton Sukhanov1a13c8f2019-07-25 21:36:41293 exclude_transport_sequence_number_from_fec_experiment_(
Erik Språngdc34a252019-10-04 13:17:29294 config.field_trials
295 ->Lookup(kExcludeTransportSequenceNumberFromFecFieldTrial)
Minyue Li5bb9adc2020-01-22 12:02:34296 .find("Enabled") == 0),
Erik Språng56e611b2020-02-06 16:10:08297 absolute_capture_time_sender_(config.clock) {}
niklase@google.com470e71d2011-07-07 08:21:25298
Sergey Ulanovec4f0682016-07-28 22:19:10299RTPSenderVideo::~RTPSenderVideo() {}
niklase@google.com470e71d2011-07-07 08:21:25300
Erik Språngf1e97b92019-09-26 10:48:47301void RTPSenderVideo::AppendAsRedMaybeWithUlpfec(
danilchap74110612016-10-02 17:54:29302 std::unique_ptr<RtpPacketToSend> media_packet,
Erik Språngf1e97b92019-09-26 10:48:47303 bool protect_media_packet,
304 std::vector<std::unique_ptr<RtpPacketToSend>>* packets) {
danilchap74110612016-10-02 17:54:29305 std::unique_ptr<RtpPacketToSend> red_packet(
306 new RtpPacketToSend(*media_packet));
307 BuildRedPayload(*media_packet, red_packet.get());
Danil Chapovalov0deef722019-10-14 12:20:20308 red_packet->SetPayloadType(*red_payload_type_);
danilchap74110612016-10-02 17:54:29309
brandtr74811e52016-08-10 07:51:50310 std::vector<std::unique_ptr<RedPacket>> fec_packets;
Danil Chapovalov0deef722019-10-14 12:20:20311 if (ulpfec_enabled()) {
312 if (protect_media_packet) {
313 if (exclude_transport_sequence_number_from_fec_experiment_) {
314 // See comments at the top of the file why experiment
315 // "WebRTC-kExcludeTransportSequenceNumberFromFec" is needed in
316 // conjunction with datagram transport.
317 // TODO(sukhanov): We may also need to implement it for flexfec_sender
318 // if we decide to keep this approach in the future.
319 uint16_t transport_senquence_number;
320 if (media_packet->GetExtension<webrtc::TransportSequenceNumber>(
321 &transport_senquence_number)) {
322 if (!media_packet->RemoveExtension(
323 webrtc::TransportSequenceNumber::kId)) {
324 RTC_NOTREACHED()
325 << "Failed to remove transport sequence number, packet="
326 << media_packet->ToString();
Anton Sukhanov1a13c8f2019-07-25 21:36:41327 }
328 }
Danil Chapovalov0deef722019-10-14 12:20:20329 }
Anton Sukhanov1a13c8f2019-07-25 21:36:41330
Danil Chapovalov0deef722019-10-14 12:20:20331 ulpfec_generator_.AddRtpPacketAndGenerateFec(
332 media_packet->Buffer(), media_packet->headers_size());
333 }
334 uint16_t num_fec_packets = ulpfec_generator_.NumAvailableFecPackets();
335 if (num_fec_packets > 0) {
336 uint16_t first_fec_sequence_number =
337 rtp_sender_->AllocateSequenceNumber(num_fec_packets);
338 fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed(
339 *red_payload_type_, *ulpfec_payload_type_, first_fec_sequence_number);
340 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
mflodmanfcf54bd2015-04-14 19:28:08341 }
342 }
Erik Språngf1e97b92019-09-26 10:48:47343
danilchap74110612016-10-02 17:54:29344 // Send |red_packet| instead of |packet| for allocated sequence number.
Björn Terelius31d0f7c2020-02-06 15:35:46345 red_packet->set_packet_type(RtpPacketMediaType::kVideo);
Erik Språng70768f42019-08-27 16:16:26346 red_packet->set_allow_retransmission(media_packet->allow_retransmission());
Erik Språngf1e97b92019-09-26 10:48:47347 packets->emplace_back(std::move(red_packet));
348
brandtr74811e52016-08-10 07:51:50349 for (const auto& fec_packet : fec_packets) {
brandtr869e7cd2016-10-31 12:27:07350 // TODO(danilchap): Make ulpfec_generator_ generate RtpPacketToSend to avoid
danilchap74110612016-10-02 17:54:29351 // reparsing them.
352 std::unique_ptr<RtpPacketToSend> rtp_packet(
353 new RtpPacketToSend(*media_packet));
354 RTC_CHECK(rtp_packet->Parse(fec_packet->data(), fec_packet->length()));
355 rtp_packet->set_capture_time_ms(media_packet->capture_time_ms());
Björn Terelius31d0f7c2020-02-06 15:35:46356 rtp_packet->set_packet_type(RtpPacketMediaType::kForwardErrorCorrection);
Erik Språng70768f42019-08-27 16:16:26357 rtp_packet->set_allow_retransmission(false);
Erik Språngf1e97b92019-09-26 10:48:47358 RTC_DCHECK_EQ(fec_packet->length(), rtp_packet->size());
359 packets->emplace_back(std::move(rtp_packet));
brandtr131bc492016-11-10 13:01:11360 }
361}
362
Erik Språngf1e97b92019-09-26 10:48:47363void RTPSenderVideo::GenerateAndAppendFlexfec(
364 std::vector<std::unique_ptr<RtpPacketToSend>>* packets) {
brandtr131bc492016-11-10 13:01:11365 RTC_DCHECK(flexfec_sender_);
366
brandtr131bc492016-11-10 13:01:11367 if (flexfec_sender_->FecAvailable()) {
368 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
369 flexfec_sender_->GetFecPackets();
370 for (auto& fec_packet : fec_packets) {
Björn Terelius31d0f7c2020-02-06 15:35:46371 fec_packet->set_packet_type(RtpPacketMediaType::kForwardErrorCorrection);
Erik Språng70768f42019-08-27 16:16:26372 fec_packet->set_allow_retransmission(false);
Erik Språngf1e97b92019-09-26 10:48:47373 packets->emplace_back(std::move(fec_packet));
stefan@webrtc.orgfbea4e52011-10-27 16:08:29374 }
stefan@webrtc.orge0d6fa42012-03-20 22:10:56375 }
niklase@google.com470e71d2011-07-07 08:21:25376}
377
Erik Språngf1e97b92019-09-26 10:48:47378void RTPSenderVideo::LogAndSendToNetwork(
379 std::vector<std::unique_ptr<RtpPacketToSend>> packets,
380 size_t unpacketized_payload_size) {
Erik Språng08a9f982019-09-30 10:48:14381 int64_t now_ms = clock_->TimeInMilliseconds();
Erik Språngf1e97b92019-09-26 10:48:47382#if BWE_TEST_LOGGING_COMPILE_TIME_ENABLE
383 for (const auto& packet : packets) {
Björn Terelius31d0f7c2020-02-06 15:35:46384 if (packet->packet_type() == RtpPacketMediaType::kForwardErrorCorrection) {
Erik Språng67ac9e82019-10-25 13:24:15385 const uint32_t ssrc = packet->Ssrc();
386 BWE_TEST_LOGGING_PLOT_WITH_SSRC(1, "VideoFecBitrate_kbps", now_ms,
387 FecOverheadRate() / 1000, ssrc);
388 }
Erik Språngf1e97b92019-09-26 10:48:47389 }
Niels Möller59ab1cf2019-02-06 21:48:11390#endif
Erik Språngf1e97b92019-09-26 10:48:47391
392 {
393 rtc::CritScope cs(&stats_crit_);
394 size_t packetized_payload_size = 0;
395 for (const auto& packet : packets) {
396 switch (*packet->packet_type()) {
Björn Terelius31d0f7c2020-02-06 15:35:46397 case RtpPacketMediaType::kVideo:
Erik Språngf1e97b92019-09-26 10:48:47398 video_bitrate_.Update(packet->size(), now_ms);
399 packetized_payload_size += packet->payload_size();
400 break;
Björn Terelius31d0f7c2020-02-06 15:35:46401 case RtpPacketMediaType::kForwardErrorCorrection:
Erik Språngf1e97b92019-09-26 10:48:47402 fec_bitrate_.Update(packet->size(), clock_->TimeInMilliseconds());
403 break;
404 default:
405 continue;
406 }
407 }
Danil Chapovalov0682ca92019-11-28 15:50:02408 // AV1 packetizer may produce less packetized bytes than unpacketized.
409 if (packetized_payload_size >= unpacketized_payload_size) {
410 packetization_overhead_bitrate_.Update(
411 packetized_payload_size - unpacketized_payload_size,
412 clock_->TimeInMilliseconds());
413 }
Erik Språngf1e97b92019-09-26 10:48:47414 }
415
Erik Språngfc78aac2019-10-24 10:55:30416 rtp_sender_->EnqueuePackets(std::move(packets));
Niels Möller59ab1cf2019-02-06 21:48:11417}
418
Danil Chapovalov0deef722019-10-14 12:20:20419size_t RTPSenderVideo::FecPacketOverhead() const {
brandtr131bc492016-11-10 13:01:11420 if (flexfec_enabled())
421 return flexfec_sender_->MaxPacketOverhead();
422
stefan8f4c77f2016-06-03 07:16:45423 size_t overhead = 0;
brandtrf1bb4762016-11-07 11:05:06424 if (red_enabled()) {
brandtr131bc492016-11-10 13:01:11425 // The RED overhead is due to a small header.
426 overhead += kRedForFecHeaderLength;
427 }
428 if (ulpfec_enabled()) {
429 // For ULPFEC, the overhead is the FEC headers plus RED for FEC header
430 // (see above) plus anything in RTP header beyond the 12 bytes base header
431 // (CSRC list, extensions...)
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55432 // This reason for the header extensions to be included here is that
433 // from an FEC viewpoint, they are part of the payload to be protected.
434 // (The base RTP header is already protected by the FEC header.)
brandtr131bc492016-11-10 13:01:11435 overhead += ulpfec_generator_.MaxPacketOverhead() +
436 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize);
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55437 }
stefan8f4c77f2016-06-03 07:16:45438 return overhead;
niklase@google.com470e71d2011-07-07 08:21:25439}
440
brandtr1743a192016-11-07 11:36:05441void RTPSenderVideo::SetFecParameters(const FecProtectionParams& delta_params,
442 const FecProtectionParams& key_params) {
danilchap7c9426c2016-04-14 10:05:31443 rtc::CritScope cs(&crit_);
brandtr131bc492016-11-10 13:01:11444 delta_fec_params_ = delta_params;
445 key_fec_params_ = key_params;
marpan@google.com80c5d7a2011-07-15 21:32:40446}
447
Danil Chapovalovd264df52018-06-14 10:59:38448absl::optional<uint32_t> RTPSenderVideo::FlexfecSsrc() const {
brandtr9dfff292016-11-14 13:14:50449 if (flexfec_sender_) {
Oskar Sundbom3419cf92017-11-16 09:55:48450 return flexfec_sender_->ssrc();
brandtr9dfff292016-11-14 13:14:50451 }
Danil Chapovalovd264df52018-06-14 10:59:38452 return absl::nullopt;
brandtr9dfff292016-11-14 13:14:50453}
454
Danil Chapovalov670af262020-01-30 15:28:53455void RTPSenderVideo::SetVideoStructure(
456 const FrameDependencyStructure* video_structure) {
457 RTC_DCHECK_RUNS_SERIALIZED(&send_checker_);
458 if (video_structure == nullptr) {
459 video_structure_ = nullptr;
460 return;
461 }
462 // Simple sanity checks video structure is set up.
463 RTC_DCHECK_GT(video_structure->num_decode_targets, 0);
464 RTC_DCHECK_GT(video_structure->templates.size(), 0);
465
466 int structure_id = 0;
467 if (video_structure_) {
468 if (*video_structure_ == *video_structure) {
469 // Same structure (just a new key frame), no update required.
470 return;
471 }
472 // When setting different video structure make sure structure_id is updated
473 // so that templates from different structures do not collide.
474 static constexpr int kMaxTemplates = 64;
475 structure_id =
476 (video_structure_->structure_id + video_structure_->templates.size()) %
477 kMaxTemplates;
478 }
479
480 video_structure_ =
481 std::make_unique<FrameDependencyStructure>(*video_structure);
482 video_structure_->structure_id = structure_id;
483 // TODO(bugs.webrtc.org/10342): Support chains.
484 video_structure_->num_chains = 0;
485}
486
Elad Alonb64af4b2019-06-05 09:39:37487bool RTPSenderVideo::SendVideo(
Danil Chapovalov51bf2002019-10-11 08:53:27488 int payload_type,
489 absl::optional<VideoCodecType> codec_type,
490 uint32_t rtp_timestamp,
491 int64_t capture_time_ms,
492 rtc::ArrayView<const uint8_t> payload,
493 const RTPFragmentationHeader* fragmentation,
494 RTPVideoHeader video_header,
495 absl::optional<int64_t> expected_retransmission_time_ms) {
Doudou Kisabaka2dec4962019-11-28 13:24:31496 #if RTC_TRACE_EVENTS_ENABLED
Niels Möller59ab1cf2019-02-06 21:48:11497 TRACE_EVENT_ASYNC_STEP1("webrtc", "Video", capture_time_ms, "Send", "type",
Danil Chapovalov51bf2002019-10-11 08:53:27498 FrameTypeToString(video_header.frame_type));
Doudou Kisabaka2dec4962019-11-28 13:24:31499 #endif
Erik Språng6cf554e2019-10-02 18:55:39500 RTC_CHECK_RUNS_SERIALIZED(&send_checker_);
Niels Möller59ab1cf2019-02-06 21:48:11501
Danil Chapovalov51bf2002019-10-11 08:53:27502 if (video_header.frame_type == VideoFrameType::kEmptyFrame)
Niels Möller59ab1cf2019-02-06 21:48:11503 return true;
504
Danil Chapovalov51bf2002019-10-11 08:53:27505 if (payload.empty())
Sergey Ulanov525df3f2016-08-03 00:46:41506 return false;
niklase@google.com470e71d2011-07-07 08:21:25507
Erik Språng6cf554e2019-10-02 18:55:39508 int32_t retransmission_settings = retransmission_settings_;
509 if (codec_type == VideoCodecType::kVideoCodecH264) {
510 // Backward compatibility for older receivers without temporal layer logic.
511 retransmission_settings = kRetransmitBaseLayer | kRetransmitHigherLayers;
512 }
513
Jonas Olssona4d87372019-07-05 17:08:33514 bool set_frame_marking =
Danil Chapovalov51bf2002019-10-11 08:53:27515 video_header.codec == kVideoCodecH264 &&
516 video_header.frame_marking.temporal_id != kNoTemporalIdx;
Niels Möller6893f3c2019-01-31 07:56:26517
Erik Språng56e611b2020-02-06 16:10:08518 MaybeUpdateCurrentPlayoutDelay(video_header);
519 if (video_header.frame_type == VideoFrameType::kVideoFrameKey &&
520 !IsNoopDelay(current_playout_delay_)) {
521 // Force playout delay on key-frames, if set.
522 playout_delay_pending_ = true;
523 }
Niels Möller6893f3c2019-01-31 07:56:26524 const absl::optional<PlayoutDelay> playout_delay =
Erik Språng56e611b2020-02-06 16:10:08525 playout_delay_pending_
526 ? absl::optional<PlayoutDelay>(current_playout_delay_)
527 : absl::nullopt;
Erik Språng6cf554e2019-10-02 18:55:39528
529 // According to
530 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
531 // ts_126114v120700p.pdf Section 7.4.5:
532 // The MTSI client shall add the payload bytes as defined in this clause
533 // onto the last RTP packet in each group of packets which make up a key
534 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265
535 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP
536 // packet in each group of packets which make up another type of frame
537 // (e.g. a P-Frame) only if the current value is different from the previous
538 // value sent.
539 // Set rotation when key frame or when changed (to follow standard).
540 // Or when different from 0 (to follow current receiver implementation).
Danil Chapovalov51bf2002019-10-11 08:53:27541 bool set_video_rotation =
542 video_header.frame_type == VideoFrameType::kVideoFrameKey ||
543 video_header.rotation != last_rotation_ ||
544 video_header.rotation != kVideoRotation_0;
545 last_rotation_ = video_header.rotation;
Erik Språng6cf554e2019-10-02 18:55:39546
547 // Send color space when changed or if the frame is a key frame. Keep
548 // sending color space information until the first base layer frame to
549 // guarantee that the information is retrieved by the receiver.
550 bool set_color_space;
Danil Chapovalov51bf2002019-10-11 08:53:27551 if (video_header.color_space != last_color_space_) {
552 last_color_space_ = video_header.color_space;
Erik Språng6cf554e2019-10-02 18:55:39553 set_color_space = true;
Danil Chapovalov51bf2002019-10-11 08:53:27554 transmit_color_space_next_frame_ = !IsBaseLayer(video_header);
Erik Språng6cf554e2019-10-02 18:55:39555 } else {
Danil Chapovalov51bf2002019-10-11 08:53:27556 set_color_space =
557 video_header.frame_type == VideoFrameType::kVideoFrameKey ||
558 transmit_color_space_next_frame_;
Erik Språng6cf554e2019-10-02 18:55:39559 transmit_color_space_next_frame_ =
Danil Chapovalov51bf2002019-10-11 08:53:27560 transmit_color_space_next_frame_ ? !IsBaseLayer(video_header) : false;
Erik Språng6cf554e2019-10-02 18:55:39561 }
562
Danil Chapovalov0deef722019-10-14 12:20:20563 if (flexfec_enabled() || ulpfec_enabled()) {
kthelgason917a4ee2016-11-10 14:22:17564 rtc::CritScope cs(&crit_);
danilchap2a615fc2016-11-11 10:27:35565 // FEC settings.
566 const FecProtectionParams& fec_params =
Danil Chapovalov51bf2002019-10-11 08:53:27567 video_header.frame_type == VideoFrameType::kVideoFrameKey
568 ? key_fec_params_
569 : delta_fec_params_;
danilchap2a615fc2016-11-11 10:27:35570 if (flexfec_enabled())
571 flexfec_sender_->SetFecParameters(fec_params);
572 if (ulpfec_enabled())
573 ulpfec_generator_.SetFecParameters(fec_params);
danilchapc1600c52016-10-26 10:33:11574 }
danilchap74110612016-10-02 17:54:29575
Danil Chapovalove4f8b382018-09-07 15:30:26576 // Maximum size of packet including rtp headers.
577 // Extra space left in case packet will be resent using fec or rtx.
Danil Chapovalov0deef722019-10-14 12:20:20578 int packet_capacity = rtp_sender_->MaxRtpPacketSize() - FecPacketOverhead() -
Danil Chapovalovfa5ec8d2018-09-07 08:57:26579 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0);
Danil Chapovalove4f8b382018-09-07 15:30:26580
Danil Chapovalov6026f052018-10-16 14:22:33581 std::unique_ptr<RtpPacketToSend> single_packet =
582 rtp_sender_->AllocatePacket();
583 RTC_DCHECK_LE(packet_capacity, single_packet->capacity());
584 single_packet->SetPayloadType(payload_type);
585 single_packet->SetTimestamp(rtp_timestamp);
586 single_packet->set_capture_time_ms(capture_time_ms);
Danil Chapovalove4f8b382018-09-07 15:30:26587
Minyue Li5bb9adc2020-01-22 12:02:34588 const absl::optional<AbsoluteCaptureTime> absolute_capture_time =
589 absolute_capture_time_sender_.OnSendPacket(
590 AbsoluteCaptureTimeSender::GetSource(single_packet->Ssrc(),
591 single_packet->Csrcs()),
592 single_packet->Timestamp(), kVideoPayloadTypeFrequency,
593 Int64MsToUQ32x32(single_packet->capture_time_ms() + NtpOffsetMs()),
594 /*estimated_capture_clock_offset=*/absl::nullopt);
595
Mirko Bonadei317a1f02019-09-17 15:06:18596 auto first_packet = std::make_unique<RtpPacketToSend>(*single_packet);
597 auto middle_packet = std::make_unique<RtpPacketToSend>(*single_packet);
598 auto last_packet = std::make_unique<RtpPacketToSend>(*single_packet);
Danil Chapovalove4f8b382018-09-07 15:30:26599 // Simplest way to estimate how much extensions would occupy is to set them.
Minyue Li5bb9adc2020-01-22 12:02:34600 AddRtpHeaderExtensions(video_header, playout_delay, absolute_capture_time,
Danil Chapovalov670af262020-01-30 15:28:53601 video_structure_.get(), set_video_rotation,
602 set_color_space, set_frame_marking,
Johnny Lee1a1c52b2019-02-08 19:25:40603 /*first=*/true, /*last=*/true, single_packet.get());
Minyue Li5bb9adc2020-01-22 12:02:34604 AddRtpHeaderExtensions(video_header, playout_delay, absolute_capture_time,
Danil Chapovalov670af262020-01-30 15:28:53605 video_structure_.get(), set_video_rotation,
606 set_color_space, set_frame_marking,
Johnny Lee1a1c52b2019-02-08 19:25:40607 /*first=*/true, /*last=*/false, first_packet.get());
Minyue Li5bb9adc2020-01-22 12:02:34608 AddRtpHeaderExtensions(video_header, playout_delay, absolute_capture_time,
Danil Chapovalov670af262020-01-30 15:28:53609 video_structure_.get(), set_video_rotation,
610 set_color_space, set_frame_marking,
Johnny Lee1a1c52b2019-02-08 19:25:40611 /*first=*/false, /*last=*/false, middle_packet.get());
Minyue Li5bb9adc2020-01-22 12:02:34612 AddRtpHeaderExtensions(video_header, playout_delay, absolute_capture_time,
Danil Chapovalov670af262020-01-30 15:28:53613 video_structure_.get(), set_video_rotation,
614 set_color_space, set_frame_marking,
Johnny Lee1a1c52b2019-02-08 19:25:40615 /*first=*/false, /*last=*/true, last_packet.get());
616
Danil Chapovalov6026f052018-10-16 14:22:33617 RTC_DCHECK_GT(packet_capacity, single_packet->headers_size());
Danil Chapovalove4f8b382018-09-07 15:30:26618 RTC_DCHECK_GT(packet_capacity, first_packet->headers_size());
619 RTC_DCHECK_GT(packet_capacity, middle_packet->headers_size());
ilnik7a3006b2017-05-23 16:34:21620 RTC_DCHECK_GT(packet_capacity, last_packet->headers_size());
Danil Chapovalovfa5ec8d2018-09-07 08:57:26621 RtpPacketizer::PayloadSizeLimits limits;
Danil Chapovalove4f8b382018-09-07 15:30:26622 limits.max_payload_len = packet_capacity - middle_packet->headers_size();
Danil Chapovalovfa5ec8d2018-09-07 08:57:26623
Danil Chapovalov6026f052018-10-16 14:22:33624 RTC_DCHECK_GE(single_packet->headers_size(), middle_packet->headers_size());
625 limits.single_packet_reduction_len =
626 single_packet->headers_size() - middle_packet->headers_size();
627
Danil Chapovalove4f8b382018-09-07 15:30:26628 RTC_DCHECK_GE(first_packet->headers_size(), middle_packet->headers_size());
629 limits.first_packet_reduction_len =
630 first_packet->headers_size() - middle_packet->headers_size();
631
632 RTC_DCHECK_GE(last_packet->headers_size(), middle_packet->headers_size());
Danil Chapovalovfa5ec8d2018-09-07 08:57:26633 limits.last_packet_reduction_len =
Danil Chapovalove4f8b382018-09-07 15:30:26634 last_packet->headers_size() - middle_packet->headers_size();
danilchap74110612016-10-02 17:54:29635
Elad Alonccb9b752019-02-19 12:01:31636 rtc::ArrayView<const uint8_t> generic_descriptor_raw_00 =
637 first_packet->GetRawExtension<RtpGenericFrameDescriptorExtension00>();
638 rtc::ArrayView<const uint8_t> generic_descriptor_raw_01 =
639 first_packet->GetRawExtension<RtpGenericFrameDescriptorExtension01>();
640
641 if (!generic_descriptor_raw_00.empty() &&
642 !generic_descriptor_raw_01.empty()) {
643 RTC_LOG(LS_WARNING) << "Two versions of GFD extension used.";
644 return false;
645 }
646
Danil Chapovalov51bf2002019-10-11 08:53:27647 // Minimiazation of the vp8 descriptor may erase temporal_id, so save it.
648 const uint8_t temporal_id = GetTemporalId(video_header);
Benjamin Wright192eeec2018-10-18 00:27:25649 rtc::ArrayView<const uint8_t> generic_descriptor_raw =
Elad Alonccb9b752019-02-19 12:01:31650 !generic_descriptor_raw_01.empty() ? generic_descriptor_raw_01
651 : generic_descriptor_raw_00;
Benjamin Wright192eeec2018-10-18 00:27:25652 if (!generic_descriptor_raw.empty()) {
Danil Chapovalov51bf2002019-10-11 08:53:27653 MinimizeDescriptor(&video_header);
Benjamin Wright192eeec2018-10-18 00:27:25654 }
655
Erik Språng56e611b2020-02-06 16:10:08656 if (video_header.frame_type == VideoFrameType::kVideoFrameKey ||
657 (IsBaseLayer(video_header) &&
658 !(video_header.generic.has_value() ? video_header.generic->discardable
659 : false))) {
660 // This frame has guaranteed delivery, no need to populate playout
661 // delay extensions until it changes again.
662 playout_delay_pending_ = false;
663 }
664
Benjamin Wright192eeec2018-10-18 00:27:25665 // TODO(benwright@webrtc.org) - Allocate enough to always encrypt inline.
666 rtc::Buffer encrypted_video_payload;
667 if (frame_encryptor_ != nullptr) {
668 if (generic_descriptor_raw.empty()) {
669 return false;
670 }
671
672 const size_t max_ciphertext_size =
673 frame_encryptor_->GetMaxCiphertextByteSize(cricket::MEDIA_TYPE_VIDEO,
Danil Chapovalov51bf2002019-10-11 08:53:27674 payload.size());
Benjamin Wright192eeec2018-10-18 00:27:25675 encrypted_video_payload.SetSize(max_ciphertext_size);
676
677 size_t bytes_written = 0;
Benjamin Wright168456c2018-12-07 19:31:25678
679 // Only enable header authentication if the field trial is enabled.
680 rtc::ArrayView<const uint8_t> additional_data;
681 if (generic_descriptor_auth_experiment_) {
682 additional_data = generic_descriptor_raw;
683 }
684
Benjamin Wright192eeec2018-10-18 00:27:25685 if (frame_encryptor_->Encrypt(
Benjamin Wright168456c2018-12-07 19:31:25686 cricket::MEDIA_TYPE_VIDEO, first_packet->Ssrc(), additional_data,
Danil Chapovalov51bf2002019-10-11 08:53:27687 payload, encrypted_video_payload, &bytes_written) != 0) {
Benjamin Wright192eeec2018-10-18 00:27:25688 return false;
689 }
690
691 encrypted_video_payload.SetSize(bytes_written);
Danil Chapovalov51bf2002019-10-11 08:53:27692 payload = encrypted_video_payload;
Benjamin Wright192eeec2018-10-18 00:27:25693 } else if (require_frame_encryption_) {
694 RTC_LOG(LS_WARNING)
695 << "No FrameEncryptor is attached to this video sending stream but "
Jonas Olssonb2b20312020-01-14 11:11:31696 "one is required since require_frame_encryptor is set";
Danil Chapovalov84ffb352018-09-25 16:59:09697 }
698
Danil Chapovalovf7f8a1f2018-08-28 17:45:31699 std::unique_ptr<RtpPacketizer> packetizer = RtpPacketizer::Create(
Danil Chapovalov51bf2002019-10-11 08:53:27700 codec_type, payload, limits, video_header, fragmentation);
spranga8ae6f22017-09-04 14:23:56701
Elad Alonb64af4b2019-06-05 09:39:37702 // TODO(bugs.webrtc.org/10714): retransmission_settings_ should generally be
703 // replaced by expected_retransmission_time_ms.has_value(). For now, though,
704 // only VP8 with an injected frame buffer controller actually controls it.
Erik Språng70768f42019-08-27 16:16:26705 const bool allow_retransmission =
Elad Alonb64af4b2019-06-05 09:39:37706 expected_retransmission_time_ms.has_value()
Erik Språng70768f42019-08-27 16:16:26707 ? AllowRetransmission(temporal_id, retransmission_settings,
708 expected_retransmission_time_ms.value())
709 : false;
Elad Alon8b60e8b2019-04-08 12:14:05710 const size_t num_packets = packetizer->NumPackets();
ilnik7a3006b2017-05-23 16:34:21711
Erik Språng482b3ef2019-01-08 15:19:11712 size_t unpacketized_payload_size;
713 if (fragmentation && fragmentation->fragmentationVectorSize > 0) {
714 unpacketized_payload_size = 0;
715 for (uint16_t i = 0; i < fragmentation->fragmentationVectorSize; ++i) {
716 unpacketized_payload_size += fragmentation->fragmentationLength[i];
717 }
718 } else {
Danil Chapovalov51bf2002019-10-11 08:53:27719 unpacketized_payload_size = payload.size();
Erik Språng482b3ef2019-01-08 15:19:11720 }
Erik Språng482b3ef2019-01-08 15:19:11721
ilnik7a3006b2017-05-23 16:34:21722 if (num_packets == 0)
723 return false;
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55724
danilchap2a615fc2016-11-11 10:27:35725 bool first_frame = first_frame_sent_();
Erik Språngf1e97b92019-09-26 10:48:47726 std::vector<std::unique_ptr<RtpPacketToSend>> rtp_packets;
ilnik7a3006b2017-05-23 16:34:21727 for (size_t i = 0; i < num_packets; ++i) {
Danil Chapovalove4f8b382018-09-07 15:30:26728 std::unique_ptr<RtpPacketToSend> packet;
729 int expected_payload_capacity;
730 // Choose right packet template:
731 if (num_packets == 1) {
Danil Chapovalov6026f052018-10-16 14:22:33732 packet = std::move(single_packet);
Danil Chapovalovfcebe0e2018-10-12 15:51:22733 expected_payload_capacity =
734 limits.max_payload_len - limits.single_packet_reduction_len;
Danil Chapovalove4f8b382018-09-07 15:30:26735 } else if (i == 0) {
736 packet = std::move(first_packet);
737 expected_payload_capacity =
738 limits.max_payload_len - limits.first_packet_reduction_len;
739 } else if (i == num_packets - 1) {
740 packet = std::move(last_packet);
741 expected_payload_capacity =
742 limits.max_payload_len - limits.last_packet_reduction_len;
743 } else {
Mirko Bonadei317a1f02019-09-17 15:06:18744 packet = std::make_unique<RtpPacketToSend>(*middle_packet);
Danil Chapovalove4f8b382018-09-07 15:30:26745 expected_payload_capacity = limits.max_payload_len;
746 }
747
Erik Språng3663f942020-02-07 09:05:15748 packet->set_first_packet_of_frame(i == 0);
749
ilnik7a3006b2017-05-23 16:34:21750 if (!packetizer->NextPacket(packet.get()))
Sergey Ulanov525df3f2016-08-03 00:46:41751 return false;
Danil Chapovalove4f8b382018-09-07 15:30:26752 RTC_DCHECK_LE(packet->payload_size(), expected_payload_capacity);
danilchap74110612016-10-02 17:54:29753 if (!rtp_sender_->AssignSequenceNumber(packet.get()))
754 return false;
755
spranga8ae6f22017-09-04 14:23:56756 // No FEC protection for upper temporal layers, if used.
757 bool protect_packet = temporal_id == 0 || temporal_id == kNoTemporalIdx;
758
Erik Språng70768f42019-08-27 16:16:26759 packet->set_allow_retransmission(allow_retransmission);
760
ilnik04f4d122017-06-19 14:18:55761 // Put packetization finish timestamp into extension.
ilnike4350192017-06-29 09:27:44762 if (packet->HasExtension<VideoTimingExtension>()) {
ilnik04f4d122017-06-19 14:18:55763 packet->set_packetization_finish_time_ms(clock_->TimeInMilliseconds());
764 }
765
Danil Chapovalov0deef722019-10-14 12:20:20766 if (red_enabled()) {
Erik Språngf1e97b92019-09-26 10:48:47767 AppendAsRedMaybeWithUlpfec(std::move(packet), protect_packet,
768 &rtp_packets);
mflodmanfcf54bd2015-04-14 19:28:08769 } else {
Björn Terelius31d0f7c2020-02-06 15:35:46770 packet->set_packet_type(RtpPacketMediaType::kVideo);
Erik Språngf1e97b92019-09-26 10:48:47771 const RtpPacketToSend& media_packet = *packet;
772 rtp_packets.emplace_back(std::move(packet));
773 if (flexfec_enabled()) {
774 // TODO(brandtr): Remove the FlexFEC code path when FlexfecSender
775 // is wired up to PacedSender instead.
776 if (protect_packet) {
777 flexfec_sender_->AddRtpPacketAndGenerateFec(media_packet);
778 }
779 GenerateAndAppendFlexfec(&rtp_packets);
780 }
stefan@webrtc.org2ec56062014-07-31 14:59:24781 }
skvlad98bb6642016-04-07 22:36:45782
783 if (first_frame) {
ilnik7a3006b2017-05-23 16:34:21784 if (i == 0) {
Mirko Bonadei675513b2017-11-09 10:09:25785 RTC_LOG(LS_INFO)
skvlad98bb6642016-04-07 22:36:45786 << "Sent first RTP packet of the first video frame (pre-pacer)";
787 }
Danil Chapovalove4f8b382018-09-07 15:30:26788 if (i == num_packets - 1) {
Mirko Bonadei675513b2017-11-09 10:09:25789 RTC_LOG(LS_INFO)
skvlad98bb6642016-04-07 22:36:45790 << "Sent last RTP packet of the first video frame (pre-pacer)";
791 }
792 }
stefan@webrtc.org2ec56062014-07-31 14:59:24793 }
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55794
Erik Språngf1e97b92019-09-26 10:48:47795 LogAndSendToNetwork(std::move(rtp_packets), unpacketized_payload_size);
Erik Språng482b3ef2019-01-08 15:19:11796
Sergey Ulanovec4f0682016-07-28 22:19:10797 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp",
danilchape5b41412016-08-22 10:39:23798 rtp_timestamp);
Sergey Ulanov525df3f2016-08-03 00:46:41799 return true;
mflodmanfcf54bd2015-04-14 19:28:08800}
801
pbos@webrtc.org2f446732013-04-08 11:08:41802uint32_t RTPSenderVideo::VideoBitrateSent() const {
sprangcd349d92016-07-13 16:11:28803 rtc::CritScope cs(&stats_crit_);
804 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgfbea4e52011-10-27 16:08:29805}
806
pbos@webrtc.org2f446732013-04-08 11:08:41807uint32_t RTPSenderVideo::FecOverheadRate() const {
sprangcd349d92016-07-13 16:11:28808 rtc::CritScope cs(&stats_crit_);
809 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgd0bdab02011-10-14 14:24:54810}
811
Erik Språng482b3ef2019-01-08 15:19:11812uint32_t RTPSenderVideo::PacketizationOverheadBps() const {
813 rtc::CritScope cs(&stats_crit_);
814 return packetization_overhead_bitrate_.Rate(clock_->TimeInMilliseconds())
815 .value_or(0);
816}
817
Erik Språng70768f42019-08-27 16:16:26818bool RTPSenderVideo::AllowRetransmission(
spranga8ae6f22017-09-04 14:23:56819 uint8_t temporal_id,
820 int32_t retransmission_settings,
821 int64_t expected_retransmission_time_ms) {
822 if (retransmission_settings == kRetransmitOff)
Erik Språng70768f42019-08-27 16:16:26823 return false;
spranga8ae6f22017-09-04 14:23:56824
825 rtc::CritScope cs(&stats_crit_);
826 // Media packet storage.
827 if ((retransmission_settings & kConditionallyRetransmitHigherLayers) &&
828 UpdateConditionalRetransmit(temporal_id,
829 expected_retransmission_time_ms)) {
830 retransmission_settings |= kRetransmitHigherLayers;
831 }
832
833 if (temporal_id == kNoTemporalIdx)
Erik Språng70768f42019-08-27 16:16:26834 return true;
spranga8ae6f22017-09-04 14:23:56835
836 if ((retransmission_settings & kRetransmitBaseLayer) && temporal_id == 0)
Erik Språng70768f42019-08-27 16:16:26837 return true;
spranga8ae6f22017-09-04 14:23:56838
839 if ((retransmission_settings & kRetransmitHigherLayers) && temporal_id > 0)
Erik Språng70768f42019-08-27 16:16:26840 return true;
spranga8ae6f22017-09-04 14:23:56841
Erik Språng70768f42019-08-27 16:16:26842 return false;
spranga8ae6f22017-09-04 14:23:56843}
844
845uint8_t RTPSenderVideo::GetTemporalId(const RTPVideoHeader& header) {
Philip Eliassond52a1a62018-09-07 13:03:55846 struct TemporalIdGetter {
847 uint8_t operator()(const RTPVideoHeaderVP8& vp8) { return vp8.temporalIdx; }
848 uint8_t operator()(const RTPVideoHeaderVP9& vp9) {
849 return vp9.temporal_idx;
850 }
851 uint8_t operator()(const RTPVideoHeaderH264&) { return kNoTemporalIdx; }
Danil Chapovalovb6bf0b22020-01-28 17:36:57852 uint8_t operator()(const RTPVideoHeaderLegacyGeneric&) {
853 return kNoTemporalIdx;
854 }
Philip Eliassond52a1a62018-09-07 13:03:55855 uint8_t operator()(const absl::monostate&) { return kNoTemporalIdx; }
856 };
Johnny Lee1a1c52b2019-02-08 19:25:40857 switch (header.codec) {
858 case kVideoCodecH264:
859 return header.frame_marking.temporal_id;
860 default:
861 return absl::visit(TemporalIdGetter(), header.video_type_header);
862 }
spranga8ae6f22017-09-04 14:23:56863}
864
865bool RTPSenderVideo::UpdateConditionalRetransmit(
866 uint8_t temporal_id,
867 int64_t expected_retransmission_time_ms) {
868 int64_t now_ms = clock_->TimeInMilliseconds();
869 // Update stats for any temporal layer.
870 TemporalLayerStats* current_layer_stats =
871 &frame_stats_by_temporal_layer_[temporal_id];
872 current_layer_stats->frame_rate_fp1000s.Update(1, now_ms);
873 int64_t tl_frame_interval = now_ms - current_layer_stats->last_frame_time_ms;
874 current_layer_stats->last_frame_time_ms = now_ms;
875
876 // Conditional retransmit only applies to upper layers.
877 if (temporal_id != kNoTemporalIdx && temporal_id > 0) {
878 if (tl_frame_interval >= kMaxUnretransmittableFrameIntervalMs) {
879 // Too long since a retransmittable frame in this layer, enable NACK
880 // protection.
881 return true;
882 } else {
883 // Estimate when the next frame of any lower layer will be sent.
884 const int64_t kUndefined = std::numeric_limits<int64_t>::max();
885 int64_t expected_next_frame_time = kUndefined;
886 for (int i = temporal_id - 1; i >= 0; --i) {
887 TemporalLayerStats* stats = &frame_stats_by_temporal_layer_[i];
Danil Chapovalovd264df52018-06-14 10:59:38888 absl::optional<uint32_t> rate = stats->frame_rate_fp1000s.Rate(now_ms);
spranga8ae6f22017-09-04 14:23:56889 if (rate) {
890 int64_t tl_next = stats->last_frame_time_ms + 1000000 / *rate;
891 if (tl_next - now_ms > -expected_retransmission_time_ms &&
892 tl_next < expected_next_frame_time) {
893 expected_next_frame_time = tl_next;
894 }
895 }
896 }
897
898 if (expected_next_frame_time == kUndefined ||
899 expected_next_frame_time - now_ms > expected_retransmission_time_ms) {
900 // The next frame in a lower layer is expected at a later time (or
901 // unable to tell due to lack of data) than a retransmission is
902 // estimated to be able to arrive, so allow this packet to be nacked.
903 return true;
904 }
905 }
906 }
907
908 return false;
909}
910
Erik Språng56e611b2020-02-06 16:10:08911void RTPSenderVideo::MaybeUpdateCurrentPlayoutDelay(
912 const RTPVideoHeader& header) {
913 if (IsNoopDelay(header.playout_delay)) {
914 return;
915 }
916
917 PlayoutDelay requested_delay = header.playout_delay;
918
919 if (requested_delay.min_ms > PlayoutDelayLimits::kMaxMs ||
920 requested_delay.max_ms > PlayoutDelayLimits::kMaxMs) {
921 RTC_DLOG(LS_ERROR)
922 << "Requested playout delay values out of range, ignored";
923 return;
924 }
925 if (requested_delay.max_ms != -1 &&
926 requested_delay.min_ms > requested_delay.max_ms) {
927 RTC_DLOG(LS_ERROR) << "Requested playout delay values out of order";
928 return;
929 }
930
931 if (!playout_delay_pending_) {
932 current_playout_delay_ = requested_delay;
933 playout_delay_pending_ = true;
934 return;
935 }
936
937 if ((requested_delay.min_ms == -1 ||
938 requested_delay.min_ms == current_playout_delay_.min_ms) &&
939 (requested_delay.max_ms == -1 ||
940 requested_delay.max_ms == current_playout_delay_.max_ms)) {
941 // No change, ignore.
942 return;
943 }
944
945 if (requested_delay.min_ms == -1) {
946 RTC_DCHECK_GE(requested_delay.max_ms, 0);
947 requested_delay.min_ms =
948 std::min(current_playout_delay_.min_ms, requested_delay.max_ms);
949 }
950 if (requested_delay.max_ms == -1) {
951 requested_delay.max_ms =
952 std::max(current_playout_delay_.max_ms, requested_delay.min_ms);
953 }
954
955 current_playout_delay_ = requested_delay;
956 playout_delay_pending_ = true;
957}
958
pbos@webrtc.orgd900e8b2013-07-03 15:12:26959} // namespace webrtc