blob: b35e598403bedeb226e2f16376478ad8da0b782b [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
spranga8ae6f22017-09-04 14:23:5616#include <limits>
kwiberg84be5112016-04-27 08:19:5817#include <memory>
danilchap74110612016-10-02 17:54:2918#include <utility>
spranga8ae6f22017-09-04 14:23:5619#include <vector>
mflodmanfcf54bd2015-04-14 19:28:0820
Karl Wiberg918f50c2018-07-05 09:40:3321#include "absl/memory/memory.h"
Niels Mölleraa3c1cc2018-11-02 09:54:5622#include "absl/strings/match.h"
Benjamin Wright192eeec2018-10-18 00:27:2523#include "api/crypto/frameencryptorinterface.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3124#include "modules/rtp_rtcp/include/rtp_rtcp_defines.h"
25#include "modules/rtp_rtcp/source/byte_io.h"
26#include "modules/rtp_rtcp/source/rtp_format_video_generic.h"
27#include "modules/rtp_rtcp/source/rtp_format_vp8.h"
28#include "modules/rtp_rtcp/source/rtp_format_vp9.h"
philipelb3e42a42018-09-13 08:57:1429#include "modules/rtp_rtcp/source/rtp_generic_frame_descriptor_extension.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3130#include "modules/rtp_rtcp/source/rtp_header_extensions.h"
31#include "modules/rtp_rtcp/source/rtp_packet_to_send.h"
32#include "rtc_base/checks.h"
33#include "rtc_base/logging.h"
Mirko Bonadei92ea95e2017-09-15 04:47:3134#include "rtc_base/trace_event.h"
ilniked9b9ff2017-06-02 14:30:2035
niklase@google.com470e71d2011-07-07 08:21:2536namespace webrtc {
Sergey Ulanovec4f0682016-07-28 22:19:1037
brandtr6631e8a2016-09-13 10:23:2938namespace {
39constexpr size_t kRedForFecHeaderLength = 1;
spranga8ae6f22017-09-04 14:23:5640constexpr int64_t kMaxUnretransmittableFrameIntervalMs = 33 * 4;
danilchap74110612016-10-02 17:54:2941
42void BuildRedPayload(const RtpPacketToSend& media_packet,
43 RtpPacketToSend* red_packet) {
44 uint8_t* red_payload = red_packet->AllocatePayload(
45 kRedForFecHeaderLength + media_packet.payload_size());
46 RTC_DCHECK(red_payload);
47 red_payload[0] = media_packet.PayloadType();
danilchap96c15872016-11-21 09:35:2948
49 auto media_payload = media_packet.payload();
50 memcpy(&red_payload[kRedForFecHeaderLength], media_payload.data(),
51 media_payload.size());
danilchap74110612016-10-02 17:54:2952}
Danil Chapovalove4f8b382018-09-07 15:30:2653
54void AddRtpHeaderExtensions(const RTPVideoHeader& video_header,
55 FrameType frame_type,
56 bool set_video_rotation,
Johannes Krond0b69a82018-12-03 13:18:5357 bool set_color_space,
Danil Chapovalove4f8b382018-09-07 15:30:2658 bool first_packet,
59 bool last_packet,
60 RtpPacketToSend* packet) {
Johannes Krond0b69a82018-12-03 13:18:5361 // Color space requires two-byte header extensions if HDR metadata is
62 // included. Therefore, it's best to add this extension first so that the
63 // other extensions in the same packet are written as two-byte headers at
64 // once.
65 if (last_packet && set_color_space && video_header.color_space)
66 packet->SetExtension<ColorSpaceExtension>(video_header.color_space.value());
67
Danil Chapovalove4f8b382018-09-07 15:30:2668 if (last_packet && set_video_rotation)
69 packet->SetExtension<VideoOrientation>(video_header.rotation);
70
71 // Report content type only for key frames.
72 if (last_packet && frame_type == kVideoFrameKey &&
73 video_header.content_type != VideoContentType::UNSPECIFIED)
74 packet->SetExtension<VideoContentTypeExtension>(video_header.content_type);
75
76 if (last_packet &&
77 video_header.video_timing.flags != VideoSendTiming::kInvalid)
78 packet->SetExtension<VideoTimingExtension>(video_header.video_timing);
philipelb3e42a42018-09-13 08:57:1479
80 if (video_header.generic) {
81 RtpGenericFrameDescriptor generic_descriptor;
82 generic_descriptor.SetFirstPacketInSubFrame(first_packet);
83 generic_descriptor.SetLastPacketInSubFrame(last_packet);
84 generic_descriptor.SetFirstSubFrameInFrame(true);
85 generic_descriptor.SetLastSubFrameInFrame(true);
86
87 if (first_packet) {
88 generic_descriptor.SetFrameId(
89 static_cast<uint16_t>(video_header.generic->frame_id));
90 for (int64_t dep : video_header.generic->dependencies) {
91 generic_descriptor.AddFrameDependencyDiff(
92 video_header.generic->frame_id - dep);
93 }
94
95 uint8_t spatial_bimask = 1 << video_header.generic->spatial_index;
96 for (int layer : video_header.generic->higher_spatial_layers) {
97 RTC_DCHECK_GT(layer, video_header.generic->spatial_index);
98 RTC_DCHECK_LT(layer, 8);
99 spatial_bimask |= 1 << layer;
100 }
101 generic_descriptor.SetSpatialLayersBitmask(spatial_bimask);
102
103 generic_descriptor.SetTemporalLayer(video_header.generic->temporal_index);
philipelfab91292018-10-17 12:36:08104
105 if (frame_type == kVideoFrameKey) {
106 generic_descriptor.SetResolution(video_header.width,
107 video_header.height);
108 }
philipelb3e42a42018-09-13 08:57:14109 }
110 packet->SetExtension<RtpGenericFrameDescriptorExtension>(
111 generic_descriptor);
112 }
Danil Chapovalove4f8b382018-09-07 15:30:26113}
114
Danil Chapovalov84ffb352018-09-25 16:59:09115bool MinimizeDescriptor(const RTPVideoHeader& full, RTPVideoHeader* minimized) {
116 if (full.codec == VideoCodecType::kVideoCodecVP8) {
117 minimized->codec = VideoCodecType::kVideoCodecVP8;
118 const auto& vp8 = absl::get<RTPVideoHeaderVP8>(full.video_type_header);
119 // Set minimum fields the RtpPacketizer is using to create vp8 packets.
120 auto& min_vp8 = minimized->video_type_header.emplace<RTPVideoHeaderVP8>();
121 min_vp8.InitRTPVideoHeaderVP8();
122 min_vp8.nonReference = vp8.nonReference;
123 return true;
124 }
125 // TODO(danilchap): Reduce vp9 codec specific descriptor too.
126 return false;
127}
128
Johannes Krond0b69a82018-12-03 13:18:53129bool IsBaseLayer(const RTPVideoHeader& video_header) {
130 switch (video_header.codec) {
131 case kVideoCodecVP8: {
132 const auto& vp8 =
133 absl::get<RTPVideoHeaderVP8>(video_header.video_type_header);
134 return (vp8.temporalIdx == 0 || vp8.temporalIdx == kNoTemporalIdx);
135 }
136 case kVideoCodecVP9: {
137 const auto& vp9 =
138 absl::get<RTPVideoHeaderVP9>(video_header.video_type_header);
139 return (vp9.temporal_idx == 0 || vp9.temporal_idx == kNoTemporalIdx);
140 }
141 case kVideoCodecH264:
142 // TODO(kron): Implement logic for H264 once WebRTC supports temporal
143 // layers for H264.
144 break;
145 default:
146 break;
147 }
148 return true;
149}
150
brandtr6631e8a2016-09-13 10:23:29151} // namespace
niklase@google.com470e71d2011-07-07 08:21:25152
brandtrdbdb3f12016-11-10 13:04:48153RTPSenderVideo::RTPSenderVideo(Clock* clock,
154 RTPSender* rtp_sender,
Benjamin Wright192eeec2018-10-18 00:27:25155 FlexfecSender* flexfec_sender,
156 FrameEncryptorInterface* frame_encryptor,
157 bool require_frame_encryption)
Sergey Ulanovec4f0682016-07-28 22:19:10158 : rtp_sender_(rtp_sender),
sprangcd349d92016-07-13 16:11:28159 clock_(clock),
Niels Möller520ca4e2018-06-04 09:14:38160 video_type_(kVideoCodecGeneric),
spranga8ae6f22017-09-04 14:23:56161 retransmission_settings_(kRetransmitBaseLayer |
162 kConditionallyRetransmitHigherLayers),
brandtrd8048952016-11-07 10:08:51163 last_rotation_(kVideoRotation_0),
Johannes Krond0b69a82018-12-03 13:18:53164 transmit_color_space_next_frame_(false),
brandtrd8048952016-11-07 10:08:51165 red_payload_type_(-1),
brandtrf1bb4762016-11-07 11:05:06166 ulpfec_payload_type_(-1),
brandtrdbdb3f12016-11-10 13:04:48167 flexfec_sender_(flexfec_sender),
brandtrd8048952016-11-07 10:08:51168 delta_fec_params_{0, 1, kFecMaskRandom},
169 key_fec_params_{0, 1, kFecMaskRandom},
sprangcd349d92016-07-13 16:11:28170 fec_bitrate_(1000, RateStatistics::kBpsScale),
Benjamin Wright192eeec2018-10-18 00:27:25171 video_bitrate_(1000, RateStatistics::kBpsScale),
172 frame_encryptor_(frame_encryptor),
173 require_frame_encryption_(require_frame_encryption) {}
niklase@google.com470e71d2011-07-07 08:21:25174
Sergey Ulanovec4f0682016-07-28 22:19:10175RTPSenderVideo::~RTPSenderVideo() {}
niklase@google.com470e71d2011-07-07 08:21:25176
Niels Möller520ca4e2018-06-04 09:14:38177void RTPSenderVideo::SetVideoCodecType(enum VideoCodecType video_type) {
Sergey Ulanovec4f0682016-07-28 22:19:10178 video_type_ = video_type;
niklase@google.com470e71d2011-07-07 08:21:25179}
180
Niels Möller520ca4e2018-06-04 09:14:38181VideoCodecType RTPSenderVideo::VideoCodecType() const {
Sergey Ulanovec4f0682016-07-28 22:19:10182 return video_type_;
niklase@google.com470e71d2011-07-07 08:21:25183}
184
mflodmanfcf54bd2015-04-14 19:28:08185// Static.
186RtpUtility::Payload* RTPSenderVideo::CreateVideoPayload(
Niels Möllerf418bcb2018-11-05 12:27:35187 absl::string_view payload_name,
Sergey Ulanovec4f0682016-07-28 22:19:10188 int8_t payload_type) {
Niels Möller520ca4e2018-06-04 09:14:38189 enum VideoCodecType video_type = kVideoCodecGeneric;
Niels Mölleraa3c1cc2018-11-02 09:54:56190 if (absl::EqualsIgnoreCase(payload_name, "VP8")) {
Niels Möller520ca4e2018-06-04 09:14:38191 video_type = kVideoCodecVP8;
Niels Mölleraa3c1cc2018-11-02 09:54:56192 } else if (absl::EqualsIgnoreCase(payload_name, "VP9")) {
Niels Möller520ca4e2018-06-04 09:14:38193 video_type = kVideoCodecVP9;
Niels Mölleraa3c1cc2018-11-02 09:54:56194 } else if (absl::EqualsIgnoreCase(payload_name, "H264")) {
Niels Möller520ca4e2018-06-04 09:14:38195 video_type = kVideoCodecH264;
Niels Mölleraa3c1cc2018-11-02 09:54:56196 } else if (absl::EqualsIgnoreCase(payload_name, "I420")) {
Niels Möller520ca4e2018-06-04 09:14:38197 video_type = kVideoCodecGeneric;
Niels Mölleraa3c1cc2018-11-02 09:54:56198 } else if (absl::EqualsIgnoreCase(payload_name, "stereo")) {
Niels Möller520ca4e2018-06-04 09:14:38199 video_type = kVideoCodecGeneric;
pwestin@webrtc.org95cf4792012-01-20 06:59:06200 } else {
Niels Möller520ca4e2018-06-04 09:14:38201 video_type = kVideoCodecGeneric;
pwestin@webrtc.org95cf4792012-01-20 06:59:06202 }
Karl Wiberg83d3ec12017-09-28 17:54:38203 VideoPayload vp;
204 vp.videoCodecType = video_type;
205 return new RtpUtility::Payload(payload_name, PayloadUnion(vp));
niklase@google.com470e71d2011-07-07 08:21:25206}
207
danilchap74110612016-10-02 17:54:29208void RTPSenderVideo::SendVideoPacket(std::unique_ptr<RtpPacketToSend> packet,
mflodmanfcf54bd2015-04-14 19:28:08209 StorageType storage) {
danilchap74110612016-10-02 17:54:29210 // Remember some values about the packet before sending it away.
211 size_t packet_size = packet->size();
212 uint16_t seq_num = packet->SequenceNumber();
danilchap74110612016-10-02 17:54:29213 if (!rtp_sender_->SendToNetwork(std::move(packet), storage,
Sergey Ulanov525df3f2016-08-03 00:46:41214 RtpPacketSender::kLowPriority)) {
Mirko Bonadei675513b2017-11-09 10:09:25215 RTC_LOG(LS_WARNING) << "Failed to send video packet " << seq_num;
Sergey Ulanov525df3f2016-08-03 00:46:41216 return;
mflodmanfcf54bd2015-04-14 19:28:08217 }
Sergey Ulanov525df3f2016-08-03 00:46:41218 rtc::CritScope cs(&stats_crit_);
danilchap74110612016-10-02 17:54:29219 video_bitrate_.Update(packet_size, clock_->TimeInMilliseconds());
mflodmanfcf54bd2015-04-14 19:28:08220}
niklase@google.com470e71d2011-07-07 08:21:25221
brandtr131bc492016-11-10 13:01:11222void RTPSenderVideo::SendVideoPacketAsRedMaybeWithUlpfec(
danilchap74110612016-10-02 17:54:29223 std::unique_ptr<RtpPacketToSend> media_packet,
224 StorageType media_packet_storage,
brandtr131bc492016-11-10 13:01:11225 bool protect_media_packet) {
danilchap74110612016-10-02 17:54:29226 uint16_t media_seq_num = media_packet->SequenceNumber();
227
228 std::unique_ptr<RtpPacketToSend> red_packet(
229 new RtpPacketToSend(*media_packet));
230 BuildRedPayload(*media_packet, red_packet.get());
231
brandtr74811e52016-08-10 07:51:50232 std::vector<std::unique_ptr<RedPacket>> fec_packets;
mflodmanfcf54bd2015-04-14 19:28:08233 StorageType fec_storage = kDontRetransmit;
mflodmanfcf54bd2015-04-14 19:28:08234 {
235 // Only protect while creating RED and FEC packets, not when sending.
danilchap7c9426c2016-04-14 10:05:31236 rtc::CritScope cs(&crit_);
danilchap74110612016-10-02 17:54:29237 red_packet->SetPayloadType(red_payload_type_);
brandtr131bc492016-11-10 13:01:11238 if (ulpfec_enabled()) {
239 if (protect_media_packet) {
240 ulpfec_generator_.AddRtpPacketAndGenerateFec(
241 media_packet->data(), media_packet->payload_size(),
242 media_packet->headers_size());
243 }
244 uint16_t num_fec_packets = ulpfec_generator_.NumAvailableFecPackets();
245 if (num_fec_packets > 0) {
246 uint16_t first_fec_sequence_number =
247 rtp_sender_->AllocateSequenceNumber(num_fec_packets);
248 fec_packets = ulpfec_generator_.GetUlpfecPacketsAsRed(
Rasmus Brandt393e2662018-01-22 11:52:36249 red_payload_type_, ulpfec_payload_type_, first_fec_sequence_number);
brandtr131bc492016-11-10 13:01:11250 RTC_DCHECK_EQ(num_fec_packets, fec_packets.size());
251 if (retransmission_settings_ & kRetransmitFECPackets)
252 fec_storage = kAllowRetransmission;
253 }
mflodmanfcf54bd2015-04-14 19:28:08254 }
255 }
danilchap74110612016-10-02 17:54:29256 // Send |red_packet| instead of |packet| for allocated sequence number.
257 size_t red_packet_size = red_packet->size();
258 if (rtp_sender_->SendToNetwork(std::move(red_packet), media_packet_storage,
259 RtpPacketSender::kLowPriority)) {
sprangcd349d92016-07-13 16:11:28260 rtc::CritScope cs(&stats_crit_);
danilchap74110612016-10-02 17:54:29261 video_bitrate_.Update(red_packet_size, clock_->TimeInMilliseconds());
mflodmanfcf54bd2015-04-14 19:28:08262 } else {
Mirko Bonadei675513b2017-11-09 10:09:25263 RTC_LOG(LS_WARNING) << "Failed to send RED packet " << media_seq_num;
mflodmanfcf54bd2015-04-14 19:28:08264 }
brandtr74811e52016-08-10 07:51:50265 for (const auto& fec_packet : fec_packets) {
brandtr869e7cd2016-10-31 12:27:07266 // TODO(danilchap): Make ulpfec_generator_ generate RtpPacketToSend to avoid
danilchap74110612016-10-02 17:54:29267 // reparsing them.
268 std::unique_ptr<RtpPacketToSend> rtp_packet(
269 new RtpPacketToSend(*media_packet));
270 RTC_CHECK(rtp_packet->Parse(fec_packet->data(), fec_packet->length()));
271 rtp_packet->set_capture_time_ms(media_packet->capture_time_ms());
272 uint16_t fec_sequence_number = rtp_packet->SequenceNumber();
273 if (rtp_sender_->SendToNetwork(std::move(rtp_packet), fec_storage,
274 RtpPacketSender::kLowPriority)) {
sprangcd349d92016-07-13 16:11:28275 rtc::CritScope cs(&stats_crit_);
276 fec_bitrate_.Update(fec_packet->length(), clock_->TimeInMilliseconds());
mflodmanfcf54bd2015-04-14 19:28:08277 } else {
Mirko Bonadei675513b2017-11-09 10:09:25278 RTC_LOG(LS_WARNING) << "Failed to send ULPFEC packet "
279 << fec_sequence_number;
brandtr131bc492016-11-10 13:01:11280 }
281 }
282}
283
284void RTPSenderVideo::SendVideoPacketWithFlexfec(
285 std::unique_ptr<RtpPacketToSend> media_packet,
286 StorageType media_packet_storage,
287 bool protect_media_packet) {
288 RTC_DCHECK(flexfec_sender_);
289
290 if (protect_media_packet)
291 flexfec_sender_->AddRtpPacketAndGenerateFec(*media_packet);
292
293 SendVideoPacket(std::move(media_packet), media_packet_storage);
294
295 if (flexfec_sender_->FecAvailable()) {
296 std::vector<std::unique_ptr<RtpPacketToSend>> fec_packets =
297 flexfec_sender_->GetFecPackets();
298 for (auto& fec_packet : fec_packets) {
brandtr81eab612017-01-24 12:06:09299 size_t packet_length = fec_packet->size();
brandtr131bc492016-11-10 13:01:11300 uint16_t seq_num = fec_packet->SequenceNumber();
301 if (rtp_sender_->SendToNetwork(std::move(fec_packet), kDontRetransmit,
302 RtpPacketSender::kLowPriority)) {
brandtr81eab612017-01-24 12:06:09303 rtc::CritScope cs(&stats_crit_);
304 fec_bitrate_.Update(packet_length, clock_->TimeInMilliseconds());
brandtr131bc492016-11-10 13:01:11305 } else {
Mirko Bonadei675513b2017-11-09 10:09:25306 RTC_LOG(LS_WARNING) << "Failed to send FlexFEC packet " << seq_num;
brandtr131bc492016-11-10 13:01:11307 }
stefan@webrtc.orgfbea4e52011-10-27 16:08:29308 }
stefan@webrtc.orge0d6fa42012-03-20 22:10:56309 }
niklase@google.com470e71d2011-07-07 08:21:25310}
311
brandtrf1bb4762016-11-07 11:05:06312void RTPSenderVideo::SetUlpfecConfig(int red_payload_type,
brandtrd8048952016-11-07 10:08:51313 int ulpfec_payload_type) {
brandtrf1bb4762016-11-07 11:05:06314 // Sanity check. Per the definition of UlpfecConfig (see config.h),
315 // a payload type of -1 means that the corresponding feature is
316 // turned off.
317 RTC_DCHECK_GE(red_payload_type, -1);
brandtrd8048952016-11-07 10:08:51318 RTC_DCHECK_LE(red_payload_type, 127);
brandtrf1bb4762016-11-07 11:05:06319 RTC_DCHECK_GE(ulpfec_payload_type, -1);
brandtrd8048952016-11-07 10:08:51320 RTC_DCHECK_LE(ulpfec_payload_type, 127);
321
danilchap7c9426c2016-04-14 10:05:31322 rtc::CritScope cs(&crit_);
brandtrd8048952016-11-07 10:08:51323 red_payload_type_ = red_payload_type;
brandtrf1bb4762016-11-07 11:05:06324 ulpfec_payload_type_ = ulpfec_payload_type;
325
326 // Must not enable ULPFEC without RED.
Kári Tristan Helgason798ee752018-07-11 14:04:57327 RTC_DCHECK(!(red_enabled() ^ ulpfec_enabled()));
brandtrd8048952016-11-07 10:08:51328
brandtr131bc492016-11-10 13:01:11329 // Reset FEC parameters.
Sergey Ulanovec4f0682016-07-28 22:19:10330 delta_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
331 key_fec_params_ = FecProtectionParams{0, 1, kFecMaskRandom};
niklase@google.com470e71d2011-07-07 08:21:25332}
333
brandtrf1bb4762016-11-07 11:05:06334void RTPSenderVideo::GetUlpfecConfig(int* red_payload_type,
brandtrd8048952016-11-07 10:08:51335 int* ulpfec_payload_type) const {
danilchap7c9426c2016-04-14 10:05:31336 rtc::CritScope cs(&crit_);
brandtrd8048952016-11-07 10:08:51337 *red_payload_type = red_payload_type_;
brandtrf1bb4762016-11-07 11:05:06338 *ulpfec_payload_type = ulpfec_payload_type_;
niklase@google.com470e71d2011-07-07 08:21:25339}
340
danilchap2a615fc2016-11-11 10:27:35341size_t RTPSenderVideo::CalculateFecPacketOverhead() const {
brandtr131bc492016-11-10 13:01:11342 if (flexfec_enabled())
343 return flexfec_sender_->MaxPacketOverhead();
344
stefan8f4c77f2016-06-03 07:16:45345 size_t overhead = 0;
brandtrf1bb4762016-11-07 11:05:06346 if (red_enabled()) {
brandtr131bc492016-11-10 13:01:11347 // The RED overhead is due to a small header.
348 overhead += kRedForFecHeaderLength;
349 }
350 if (ulpfec_enabled()) {
351 // For ULPFEC, the overhead is the FEC headers plus RED for FEC header
352 // (see above) plus anything in RTP header beyond the 12 bytes base header
353 // (CSRC list, extensions...)
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55354 // This reason for the header extensions to be included here is that
355 // from an FEC viewpoint, they are part of the payload to be protected.
356 // (The base RTP header is already protected by the FEC header.)
brandtr131bc492016-11-10 13:01:11357 overhead += ulpfec_generator_.MaxPacketOverhead() +
358 (rtp_sender_->RtpHeaderLength() - kRtpHeaderSize);
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55359 }
stefan8f4c77f2016-06-03 07:16:45360 return overhead;
niklase@google.com470e71d2011-07-07 08:21:25361}
362
brandtr1743a192016-11-07 11:36:05363void RTPSenderVideo::SetFecParameters(const FecProtectionParams& delta_params,
364 const FecProtectionParams& key_params) {
danilchap7c9426c2016-04-14 10:05:31365 rtc::CritScope cs(&crit_);
brandtr131bc492016-11-10 13:01:11366 delta_fec_params_ = delta_params;
367 key_fec_params_ = key_params;
marpan@google.com80c5d7a2011-07-15 21:32:40368}
369
Danil Chapovalovd264df52018-06-14 10:59:38370absl::optional<uint32_t> RTPSenderVideo::FlexfecSsrc() const {
brandtr9dfff292016-11-14 13:14:50371 if (flexfec_sender_) {
Oskar Sundbom3419cf92017-11-16 09:55:48372 return flexfec_sender_->ssrc();
brandtr9dfff292016-11-14 13:14:50373 }
Danil Chapovalovd264df52018-06-14 10:59:38374 return absl::nullopt;
brandtr9dfff292016-11-14 13:14:50375}
376
Niels Möller520ca4e2018-06-04 09:14:38377bool RTPSenderVideo::SendVideo(enum VideoCodecType video_type,
Sergey Ulanov525df3f2016-08-03 00:46:41378 FrameType frame_type,
379 int8_t payload_type,
danilchape5b41412016-08-22 10:39:23380 uint32_t rtp_timestamp,
Sergey Ulanov525df3f2016-08-03 00:46:41381 int64_t capture_time_ms,
382 const uint8_t* payload_data,
383 size_t payload_size,
384 const RTPFragmentationHeader* fragmentation,
spranga8ae6f22017-09-04 14:23:56385 const RTPVideoHeader* video_header,
386 int64_t expected_retransmission_time_ms) {
Sergey Ulanov525df3f2016-08-03 00:46:41387 if (payload_size == 0)
388 return false;
Danil Chapovalovf7f8a1f2018-08-28 17:45:31389 RTC_CHECK(video_header);
niklase@google.com470e71d2011-07-07 08:21:25390
danilchap2a615fc2016-11-11 10:27:35391 size_t fec_packet_overhead;
392 bool red_enabled;
393 int32_t retransmission_settings;
Danil Chapovalove4f8b382018-09-07 15:30:26394 bool set_video_rotation;
Johannes Krond0b69a82018-12-03 13:18:53395 bool set_color_space = false;
danilchap2a615fc2016-11-11 10:27:35396 {
kthelgason917a4ee2016-11-10 14:22:17397 rtc::CritScope cs(&crit_);
danilchap2a615fc2016-11-11 10:27:35398 // According to
399 // http://www.etsi.org/deliver/etsi_ts/126100_126199/126114/12.07.00_60/
400 // ts_126114v120700p.pdf Section 7.4.5:
401 // The MTSI client shall add the payload bytes as defined in this clause
402 // onto the last RTP packet in each group of packets which make up a key
403 // frame (I-frame or IDR frame in H.264 (AVC), or an IRAP picture in H.265
404 // (HEVC)). The MTSI client may also add the payload bytes onto the last RTP
405 // packet in each group of packets which make up another type of frame
406 // (e.g. a P-Frame) only if the current value is different from the previous
407 // value sent.
Danil Chapovalovf7f8a1f2018-08-28 17:45:31408 // Set rotation when key frame or when changed (to follow standard).
409 // Or when different from 0 (to follow current receiver implementation).
Danil Chapovalove4f8b382018-09-07 15:30:26410 set_video_rotation = frame_type == kVideoFrameKey ||
411 video_header->rotation != last_rotation_ ||
412 video_header->rotation != kVideoRotation_0;
413 last_rotation_ = video_header->rotation;
danilchap2a615fc2016-11-11 10:27:35414
Johannes Krond0b69a82018-12-03 13:18:53415 // Send color space when changed or if the frame is a key frame. Keep
416 // sending color space information until the first base layer frame to
417 // guarantee that the information is retrieved by the receiver.
418 if (video_header->color_space != last_color_space_) {
419 last_color_space_ = video_header->color_space;
420 set_color_space = true;
421 transmit_color_space_next_frame_ = !IsBaseLayer(*video_header);
422 } else {
423 set_color_space =
424 frame_type == kVideoFrameKey || transmit_color_space_next_frame_;
425 transmit_color_space_next_frame_ = transmit_color_space_next_frame_
426 ? !IsBaseLayer(*video_header)
427 : false;
428 }
429
danilchap2a615fc2016-11-11 10:27:35430 // FEC settings.
431 const FecProtectionParams& fec_params =
432 frame_type == kVideoFrameKey ? key_fec_params_ : delta_fec_params_;
433 if (flexfec_enabled())
434 flexfec_sender_->SetFecParameters(fec_params);
435 if (ulpfec_enabled())
436 ulpfec_generator_.SetFecParameters(fec_params);
437
438 fec_packet_overhead = CalculateFecPacketOverhead();
439 red_enabled = this->red_enabled();
440 retransmission_settings = retransmission_settings_;
danilchapc1600c52016-10-26 10:33:11441 }
danilchap74110612016-10-02 17:54:29442
Danil Chapovalove4f8b382018-09-07 15:30:26443 // Maximum size of packet including rtp headers.
444 // Extra space left in case packet will be resent using fec or rtx.
Danil Chapovalovfa5ec8d2018-09-07 08:57:26445 int packet_capacity = rtp_sender_->MaxRtpPacketSize() - fec_packet_overhead -
446 (rtp_sender_->RtxStatus() ? kRtxHeaderSize : 0);
Danil Chapovalove4f8b382018-09-07 15:30:26447
Danil Chapovalov6026f052018-10-16 14:22:33448 std::unique_ptr<RtpPacketToSend> single_packet =
449 rtp_sender_->AllocatePacket();
450 RTC_DCHECK_LE(packet_capacity, single_packet->capacity());
451 single_packet->SetPayloadType(payload_type);
452 single_packet->SetTimestamp(rtp_timestamp);
453 single_packet->set_capture_time_ms(capture_time_ms);
Danil Chapovalove4f8b382018-09-07 15:30:26454
Danil Chapovalov6026f052018-10-16 14:22:33455 auto first_packet = absl::make_unique<RtpPacketToSend>(*single_packet);
456 auto middle_packet = absl::make_unique<RtpPacketToSend>(*single_packet);
457 auto last_packet = absl::make_unique<RtpPacketToSend>(*single_packet);
Danil Chapovalove4f8b382018-09-07 15:30:26458 // Simplest way to estimate how much extensions would occupy is to set them.
459 AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
Johannes Krond0b69a82018-12-03 13:18:53460 set_color_space, /*first=*/true, /*last=*/true,
461 single_packet.get());
Danil Chapovalov6026f052018-10-16 14:22:33462 AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
Johannes Krond0b69a82018-12-03 13:18:53463 set_color_space, /*first=*/true, /*last=*/false,
464 first_packet.get());
Danil Chapovalove4f8b382018-09-07 15:30:26465 AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
Johannes Krond0b69a82018-12-03 13:18:53466 set_color_space, /*first=*/false, /*last=*/false,
467 middle_packet.get());
Danil Chapovalove4f8b382018-09-07 15:30:26468 AddRtpHeaderExtensions(*video_header, frame_type, set_video_rotation,
Johannes Krond0b69a82018-12-03 13:18:53469 set_color_space, /*first=*/false, /*last=*/true,
470 last_packet.get());
Danil Chapovalove4f8b382018-09-07 15:30:26471
Danil Chapovalov6026f052018-10-16 14:22:33472 RTC_DCHECK_GT(packet_capacity, single_packet->headers_size());
Danil Chapovalove4f8b382018-09-07 15:30:26473 RTC_DCHECK_GT(packet_capacity, first_packet->headers_size());
474 RTC_DCHECK_GT(packet_capacity, middle_packet->headers_size());
ilnik7a3006b2017-05-23 16:34:21475 RTC_DCHECK_GT(packet_capacity, last_packet->headers_size());
Danil Chapovalovfa5ec8d2018-09-07 08:57:26476 RtpPacketizer::PayloadSizeLimits limits;
Danil Chapovalove4f8b382018-09-07 15:30:26477 limits.max_payload_len = packet_capacity - middle_packet->headers_size();
Danil Chapovalovfa5ec8d2018-09-07 08:57:26478
Danil Chapovalov6026f052018-10-16 14:22:33479 RTC_DCHECK_GE(single_packet->headers_size(), middle_packet->headers_size());
480 limits.single_packet_reduction_len =
481 single_packet->headers_size() - middle_packet->headers_size();
482
Danil Chapovalove4f8b382018-09-07 15:30:26483 RTC_DCHECK_GE(first_packet->headers_size(), middle_packet->headers_size());
484 limits.first_packet_reduction_len =
485 first_packet->headers_size() - middle_packet->headers_size();
486
487 RTC_DCHECK_GE(last_packet->headers_size(), middle_packet->headers_size());
Danil Chapovalovfa5ec8d2018-09-07 08:57:26488 limits.last_packet_reduction_len =
Danil Chapovalove4f8b382018-09-07 15:30:26489 last_packet->headers_size() - middle_packet->headers_size();
danilchap74110612016-10-02 17:54:29490
Danil Chapovalov84ffb352018-09-25 16:59:09491 RTPVideoHeader minimized_video_header;
492 const RTPVideoHeader* packetize_video_header = video_header;
Benjamin Wright192eeec2018-10-18 00:27:25493 rtc::ArrayView<const uint8_t> generic_descriptor_raw =
494 first_packet->GetRawExtension<RtpGenericFrameDescriptorExtension>();
495 if (!generic_descriptor_raw.empty()) {
496 if (MinimizeDescriptor(*video_header, &minimized_video_header)) {
497 packetize_video_header = &minimized_video_header;
498 }
499 }
500
501 // TODO(benwright@webrtc.org) - Allocate enough to always encrypt inline.
502 rtc::Buffer encrypted_video_payload;
503 if (frame_encryptor_ != nullptr) {
504 if (generic_descriptor_raw.empty()) {
505 return false;
506 }
507
508 const size_t max_ciphertext_size =
509 frame_encryptor_->GetMaxCiphertextByteSize(cricket::MEDIA_TYPE_VIDEO,
510 payload_size);
511 encrypted_video_payload.SetSize(max_ciphertext_size);
512
513 size_t bytes_written = 0;
514 if (frame_encryptor_->Encrypt(
515 cricket::MEDIA_TYPE_VIDEO, first_packet->Ssrc(),
516 /*additional_data=*/nullptr,
517 rtc::MakeArrayView(payload_data, payload_size),
518 encrypted_video_payload, &bytes_written) != 0) {
519 return false;
520 }
521
522 encrypted_video_payload.SetSize(bytes_written);
523 payload_data = encrypted_video_payload.data();
524 payload_size = encrypted_video_payload.size();
525 } else if (require_frame_encryption_) {
526 RTC_LOG(LS_WARNING)
527 << "No FrameEncryptor is attached to this video sending stream but "
528 << "one is required since require_frame_encryptor is set";
Danil Chapovalov84ffb352018-09-25 16:59:09529 }
530
Danil Chapovalovf7f8a1f2018-08-28 17:45:31531 std::unique_ptr<RtpPacketizer> packetizer = RtpPacketizer::Create(
532 video_type, rtc::MakeArrayView(payload_data, payload_size), limits,
Danil Chapovalov84ffb352018-09-25 16:59:09533 *packetize_video_header, frame_type, fragmentation);
spranga8ae6f22017-09-04 14:23:56534
Danil Chapovalovf7f8a1f2018-08-28 17:45:31535 const uint8_t temporal_id = GetTemporalId(*video_header);
spranga8ae6f22017-09-04 14:23:56536 StorageType storage = GetStorageType(temporal_id, retransmission_settings,
537 expected_retransmission_time_ms);
Danil Chapovalovf7f8a1f2018-08-28 17:45:31538 size_t num_packets = packetizer->NumPackets();
ilnik7a3006b2017-05-23 16:34:21539
540 if (num_packets == 0)
541 return false;
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55542
danilchap2a615fc2016-11-11 10:27:35543 bool first_frame = first_frame_sent_();
ilnik7a3006b2017-05-23 16:34:21544 for (size_t i = 0; i < num_packets; ++i) {
Danil Chapovalove4f8b382018-09-07 15:30:26545 std::unique_ptr<RtpPacketToSend> packet;
546 int expected_payload_capacity;
547 // Choose right packet template:
548 if (num_packets == 1) {
Danil Chapovalov6026f052018-10-16 14:22:33549 packet = std::move(single_packet);
Danil Chapovalovfcebe0e2018-10-12 15:51:22550 expected_payload_capacity =
551 limits.max_payload_len - limits.single_packet_reduction_len;
Danil Chapovalove4f8b382018-09-07 15:30:26552 } else if (i == 0) {
553 packet = std::move(first_packet);
554 expected_payload_capacity =
555 limits.max_payload_len - limits.first_packet_reduction_len;
556 } else if (i == num_packets - 1) {
557 packet = std::move(last_packet);
558 expected_payload_capacity =
559 limits.max_payload_len - limits.last_packet_reduction_len;
560 } else {
561 packet = absl::make_unique<RtpPacketToSend>(*middle_packet);
562 expected_payload_capacity = limits.max_payload_len;
563 }
564
ilnik7a3006b2017-05-23 16:34:21565 if (!packetizer->NextPacket(packet.get()))
Sergey Ulanov525df3f2016-08-03 00:46:41566 return false;
Danil Chapovalove4f8b382018-09-07 15:30:26567 RTC_DCHECK_LE(packet->payload_size(), expected_payload_capacity);
danilchap74110612016-10-02 17:54:29568 if (!rtp_sender_->AssignSequenceNumber(packet.get()))
569 return false;
570
spranga8ae6f22017-09-04 14:23:56571 // No FEC protection for upper temporal layers, if used.
572 bool protect_packet = temporal_id == 0 || temporal_id == kNoTemporalIdx;
573
ilnik04f4d122017-06-19 14:18:55574 // Put packetization finish timestamp into extension.
ilnike4350192017-06-29 09:27:44575 if (packet->HasExtension<VideoTimingExtension>()) {
ilnik04f4d122017-06-19 14:18:55576 packet->set_packetization_finish_time_ms(clock_->TimeInMilliseconds());
ilnik10894992017-06-21 15:23:19577 // TODO(ilnik): Due to webrtc:7859, packets with timing extensions are not
578 // protected by FEC. It reduces FEC efficiency a bit. When FEC is moved
579 // below the pacer, it can be re-enabled for these packets.
580 // NOTE: Any RTP stream processor in the network, modifying 'network'
581 // timestamps in the timing frames extension have to be an end-point for
582 // FEC, otherwise recovered by FEC packets will be corrupted.
583 protect_packet = false;
ilnik04f4d122017-06-19 14:18:55584 }
585
brandtr131bc492016-11-10 13:01:11586 if (flexfec_enabled()) {
587 // TODO(brandtr): Remove the FlexFEC code path when FlexfecSender
588 // is wired up to PacedSender instead.
589 SendVideoPacketWithFlexfec(std::move(packet), storage, protect_packet);
590 } else if (red_enabled) {
591 SendVideoPacketAsRedMaybeWithUlpfec(std::move(packet), storage,
592 protect_packet);
mflodmanfcf54bd2015-04-14 19:28:08593 } else {
danilchap74110612016-10-02 17:54:29594 SendVideoPacket(std::move(packet), storage);
stefan@webrtc.org2ec56062014-07-31 14:59:24595 }
skvlad98bb6642016-04-07 22:36:45596
597 if (first_frame) {
ilnik7a3006b2017-05-23 16:34:21598 if (i == 0) {
Mirko Bonadei675513b2017-11-09 10:09:25599 RTC_LOG(LS_INFO)
skvlad98bb6642016-04-07 22:36:45600 << "Sent first RTP packet of the first video frame (pre-pacer)";
601 }
Danil Chapovalove4f8b382018-09-07 15:30:26602 if (i == num_packets - 1) {
Mirko Bonadei675513b2017-11-09 10:09:25603 RTC_LOG(LS_INFO)
skvlad98bb6642016-04-07 22:36:45604 << "Sent last RTP packet of the first video frame (pre-pacer)";
605 }
606 }
stefan@webrtc.org2ec56062014-07-31 14:59:24607 }
pbos@webrtc.orgb5e6bfc2014-09-12 11:05:55608
Sergey Ulanovec4f0682016-07-28 22:19:10609 TRACE_EVENT_ASYNC_END1("webrtc", "Video", capture_time_ms, "timestamp",
danilchape5b41412016-08-22 10:39:23610 rtp_timestamp);
Sergey Ulanov525df3f2016-08-03 00:46:41611 return true;
mflodmanfcf54bd2015-04-14 19:28:08612}
613
pbos@webrtc.org2f446732013-04-08 11:08:41614uint32_t RTPSenderVideo::VideoBitrateSent() const {
sprangcd349d92016-07-13 16:11:28615 rtc::CritScope cs(&stats_crit_);
616 return video_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgfbea4e52011-10-27 16:08:29617}
618
pbos@webrtc.org2f446732013-04-08 11:08:41619uint32_t RTPSenderVideo::FecOverheadRate() const {
sprangcd349d92016-07-13 16:11:28620 rtc::CritScope cs(&stats_crit_);
621 return fec_bitrate_.Rate(clock_->TimeInMilliseconds()).value_or(0);
stefan@webrtc.orgd0bdab02011-10-14 14:24:54622}
623
stefan@webrtc.org6a4bef42011-12-22 12:52:41624int RTPSenderVideo::SelectiveRetransmissions() const {
danilchap7c9426c2016-04-14 10:05:31625 rtc::CritScope cs(&crit_);
Sergey Ulanovec4f0682016-07-28 22:19:10626 return retransmission_settings_;
stefan@webrtc.org6a4bef42011-12-22 12:52:41627}
628
mflodmanfcf54bd2015-04-14 19:28:08629void RTPSenderVideo::SetSelectiveRetransmissions(uint8_t settings) {
danilchap7c9426c2016-04-14 10:05:31630 rtc::CritScope cs(&crit_);
Sergey Ulanovec4f0682016-07-28 22:19:10631 retransmission_settings_ = settings;
stefan@webrtc.org6a4bef42011-12-22 12:52:41632}
633
spranga8ae6f22017-09-04 14:23:56634StorageType RTPSenderVideo::GetStorageType(
635 uint8_t temporal_id,
636 int32_t retransmission_settings,
637 int64_t expected_retransmission_time_ms) {
638 if (retransmission_settings == kRetransmitOff)
639 return StorageType::kDontRetransmit;
640 if (retransmission_settings == kRetransmitAllPackets)
641 return StorageType::kAllowRetransmission;
642
643 rtc::CritScope cs(&stats_crit_);
644 // Media packet storage.
645 if ((retransmission_settings & kConditionallyRetransmitHigherLayers) &&
646 UpdateConditionalRetransmit(temporal_id,
647 expected_retransmission_time_ms)) {
648 retransmission_settings |= kRetransmitHigherLayers;
649 }
650
651 if (temporal_id == kNoTemporalIdx)
652 return kAllowRetransmission;
653
654 if ((retransmission_settings & kRetransmitBaseLayer) && temporal_id == 0)
655 return kAllowRetransmission;
656
657 if ((retransmission_settings & kRetransmitHigherLayers) && temporal_id > 0)
658 return kAllowRetransmission;
659
660 return kDontRetransmit;
661}
662
663uint8_t RTPSenderVideo::GetTemporalId(const RTPVideoHeader& header) {
Philip Eliassond52a1a62018-09-07 13:03:55664 struct TemporalIdGetter {
665 uint8_t operator()(const RTPVideoHeaderVP8& vp8) { return vp8.temporalIdx; }
666 uint8_t operator()(const RTPVideoHeaderVP9& vp9) {
667 return vp9.temporal_idx;
668 }
669 uint8_t operator()(const RTPVideoHeaderH264&) { return kNoTemporalIdx; }
670 uint8_t operator()(const absl::monostate&) { return kNoTemporalIdx; }
671 };
672 return absl::visit(TemporalIdGetter(), header.video_type_header);
spranga8ae6f22017-09-04 14:23:56673}
674
675bool RTPSenderVideo::UpdateConditionalRetransmit(
676 uint8_t temporal_id,
677 int64_t expected_retransmission_time_ms) {
678 int64_t now_ms = clock_->TimeInMilliseconds();
679 // Update stats for any temporal layer.
680 TemporalLayerStats* current_layer_stats =
681 &frame_stats_by_temporal_layer_[temporal_id];
682 current_layer_stats->frame_rate_fp1000s.Update(1, now_ms);
683 int64_t tl_frame_interval = now_ms - current_layer_stats->last_frame_time_ms;
684 current_layer_stats->last_frame_time_ms = now_ms;
685
686 // Conditional retransmit only applies to upper layers.
687 if (temporal_id != kNoTemporalIdx && temporal_id > 0) {
688 if (tl_frame_interval >= kMaxUnretransmittableFrameIntervalMs) {
689 // Too long since a retransmittable frame in this layer, enable NACK
690 // protection.
691 return true;
692 } else {
693 // Estimate when the next frame of any lower layer will be sent.
694 const int64_t kUndefined = std::numeric_limits<int64_t>::max();
695 int64_t expected_next_frame_time = kUndefined;
696 for (int i = temporal_id - 1; i >= 0; --i) {
697 TemporalLayerStats* stats = &frame_stats_by_temporal_layer_[i];
Danil Chapovalovd264df52018-06-14 10:59:38698 absl::optional<uint32_t> rate = stats->frame_rate_fp1000s.Rate(now_ms);
spranga8ae6f22017-09-04 14:23:56699 if (rate) {
700 int64_t tl_next = stats->last_frame_time_ms + 1000000 / *rate;
701 if (tl_next - now_ms > -expected_retransmission_time_ms &&
702 tl_next < expected_next_frame_time) {
703 expected_next_frame_time = tl_next;
704 }
705 }
706 }
707
708 if (expected_next_frame_time == kUndefined ||
709 expected_next_frame_time - now_ms > expected_retransmission_time_ms) {
710 // The next frame in a lower layer is expected at a later time (or
711 // unable to tell due to lack of data) than a retransmission is
712 // estimated to be able to arrive, so allow this packet to be nacked.
713 return true;
714 }
715 }
716 }
717
718 return false;
719}
720
pbos@webrtc.orgd900e8b2013-07-03 15:12:26721} // namespace webrtc