blob: 24e7e8968848ab44951f299f1bcccda4df4a5328 [file] [log] [blame]
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001/*
2 * Copyright (c) 2013 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 */
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000010#include "webrtc/video/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000011
pbos@webrtc.orgdde16f12014-08-05 23:35:43 +000012#include <algorithm>
hbos706a45e2016-11-30 01:53:10 -080013#include <cmath>
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +000014#include <sstream>
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000015#include <string>
perkj71ee44c2016-06-15 00:47:53 -070016#include <utility>
pbos@webrtc.org29d58392013-05-16 12:08:03 +000017#include <vector>
18
pbos@webrtc.org2b4ce3a2015-03-23 13:12:24 +000019#include "webrtc/base/checks.h"
palmkviste75f2042016-09-28 06:19:48 -070020#include "webrtc/base/file.h"
tommidea489f2017-03-03 03:20:24 -080021#include "webrtc/base/location.h"
Peter Boström415d2cd2015-10-26 11:35:17 +010022#include "webrtc/base/logging.h"
tommie4f96502015-10-20 23:00:48 -070023#include "webrtc/base/trace_event.h"
perkj8ff860a2016-10-03 00:30:04 -070024#include "webrtc/base/weak_ptr.h"
nisseb8f9a322017-03-27 05:36:15 -070025#include "webrtc/call/rtp_transport_controller_send.h"
tommidea489f2017-03-03 03:20:24 -080026#include "webrtc/common_types.h"
27#include "webrtc/common_video/include/video_bitrate_allocator.h"
mflodman0e7e2592015-11-12 21:02:42 -080028#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
nisse559af382017-03-21 06:41:12 -070029#include "webrtc/modules/congestion_controller/include/send_side_congestion_controller.h"
Henrik Kjellander0b9e29c2015-11-16 11:12:24 +010030#include "webrtc/modules/pacing/packet_router.h"
Peter Boström9c017252016-02-26 16:26:20 +010031#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
Peter Boströme4499152016-02-05 11:13:28 +010032#include "webrtc/modules/utility/include/process_thread.h"
perkj600246e2016-05-04 11:26:51 -070033#include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
michaelta3328772016-11-29 09:25:03 -080034#include "webrtc/system_wrappers/include/field_trial.h"
Peter Boström7623ce42015-12-09 12:13:30 +010035#include "webrtc/video/call_stats.h"
nisseb8f9a322017-03-27 05:36:15 -070036#include "webrtc/video/payload_router.h"
Stefan Holmer58c664c2016-02-08 14:31:30 +010037#include "webrtc/video/vie_remb.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000038#include "webrtc/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000039
40namespace webrtc {
mflodman949c2f02015-10-16 02:31:11 -070041
Per83d09102016-04-15 14:59:13 +020042static const int kMinSendSidePacketHistorySize = 600;
Per83d09102016-04-15 14:59:13 +020043namespace {
44
nisse284542b2017-01-10 08:58:32 -080045// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
46const size_t kPathMTU = 1500;
47
Per83d09102016-04-15 14:59:13 +020048std::vector<RtpRtcp*> CreateRtpRtcpModules(
49 Transport* outgoing_transport,
50 RtcpIntraFrameObserver* intra_frame_callback,
51 RtcpBandwidthObserver* bandwidth_callback,
nisseb8f9a322017-03-27 05:36:15 -070052 RtpTransportControllerSendInterface* transport,
Per83d09102016-04-15 14:59:13 +020053 RtcpRttStats* rtt_stats,
brandtre950cad2016-11-15 05:25:41 -080054 FlexfecSender* flexfec_sender,
Per83d09102016-04-15 14:59:13 +020055 SendStatisticsProxy* stats_proxy,
asapersson35151f32016-05-02 23:44:01 -070056 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -070057 RtcEventLog* event_log,
sprangcd349d92016-07-13 09:11:28 -070058 RateLimiter* retransmission_rate_limiter,
michaelta3328772016-11-29 09:25:03 -080059 OverheadObserver* overhead_observer,
Per83d09102016-04-15 14:59:13 +020060 size_t num_modules) {
kwibergaf476c72016-11-28 15:21:39 -080061 RTC_DCHECK_GT(num_modules, 0);
Per83d09102016-04-15 14:59:13 +020062 RtpRtcp::Configuration configuration;
63 ReceiveStatistics* null_receive_statistics = configuration.receive_statistics;
64 configuration.audio = false;
65 configuration.receiver_only = false;
brandtre950cad2016-11-15 05:25:41 -080066 configuration.flexfec_sender = flexfec_sender;
Per83d09102016-04-15 14:59:13 +020067 configuration.receive_statistics = null_receive_statistics;
68 configuration.outgoing_transport = outgoing_transport;
69 configuration.intra_frame_callback = intra_frame_callback;
tereliusadafe0b2016-05-26 01:58:40 -070070 configuration.bandwidth_callback = bandwidth_callback;
nisseb8f9a322017-03-27 05:36:15 -070071 configuration.transport_feedback_callback =
72 transport->transport_feedback_observer();
Per83d09102016-04-15 14:59:13 +020073 configuration.rtt_stats = rtt_stats;
74 configuration.rtcp_packet_type_counter_observer = stats_proxy;
nisseb8f9a322017-03-27 05:36:15 -070075 configuration.paced_sender = transport->packet_sender();
Per83d09102016-04-15 14:59:13 +020076 configuration.transport_sequence_number_allocator =
nisseb8f9a322017-03-27 05:36:15 -070077 transport->packet_router();
Per83d09102016-04-15 14:59:13 +020078 configuration.send_bitrate_observer = stats_proxy;
79 configuration.send_frame_count_observer = stats_proxy;
80 configuration.send_side_delay_observer = stats_proxy;
asapersson35151f32016-05-02 23:44:01 -070081 configuration.send_packet_observer = send_delay_stats;
tereliusadafe0b2016-05-26 01:58:40 -070082 configuration.event_log = event_log;
sprangcd349d92016-07-13 09:11:28 -070083 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
michaelta3328772016-11-29 09:25:03 -080084 configuration.overhead_observer = overhead_observer;
Per83d09102016-04-15 14:59:13 +020085 std::vector<RtpRtcp*> modules;
86 for (size_t i = 0; i < num_modules; ++i) {
87 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
88 rtp_rtcp->SetSendingStatus(false);
89 rtp_rtcp->SetSendingMediaStatus(false);
90 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
91 modules.push_back(rtp_rtcp);
92 }
93 return modules;
94}
95
brandtre950cad2016-11-15 05:25:41 -080096// TODO(brandtr): Update this function when we support multistream protection.
97std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
98 const VideoSendStream::Config& config) {
brandtr3d200bd2017-01-16 06:59:19 -080099 if (config.rtp.flexfec.payload_type < 0) {
brandtre950cad2016-11-15 05:25:41 -0800100 return nullptr;
101 }
brandtr3d200bd2017-01-16 06:59:19 -0800102 RTC_DCHECK_GE(config.rtp.flexfec.payload_type, 0);
103 RTC_DCHECK_LE(config.rtp.flexfec.payload_type, 127);
104 if (config.rtp.flexfec.ssrc == 0) {
brandtre950cad2016-11-15 05:25:41 -0800105 LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
106 "Therefore disabling FlexFEC.";
107 return nullptr;
108 }
109 if (config.rtp.flexfec.protected_media_ssrcs.empty()) {
110 LOG(LS_WARNING) << "FlexFEC is enabled, but no protected media SSRC given. "
111 "Therefore disabling FlexFEC.";
112 return nullptr;
113 }
114
115 if (config.rtp.ssrcs.size() > 1) {
116 LOG(LS_WARNING) << "Both FlexFEC and simulcast are enabled. This "
117 "combination is however not supported by our current "
118 "FlexFEC implementation. Therefore disabling FlexFEC.";
119 return nullptr;
120 }
121
122 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) {
123 LOG(LS_WARNING)
124 << "The supplied FlexfecConfig contained multiple protected "
125 "media streams, but our implementation currently only "
126 "supports protecting a single media stream. "
127 "To avoid confusion, disabling FlexFEC completely.";
128 return nullptr;
129 }
130
131 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
132 return std::unique_ptr<FlexfecSender>(new FlexfecSender(
brandtr3d200bd2017-01-16 06:59:19 -0800133 config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc,
brandtre950cad2016-11-15 05:25:41 -0800134 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions,
135 Clock::GetRealTimeClock()));
136}
137
Per83d09102016-04-15 14:59:13 +0200138} // namespace
139
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000140std::string
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000141VideoSendStream::Config::EncoderSettings::ToString() const {
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000142 std::stringstream ss;
143 ss << "{payload_name: " << payload_name;
144 ss << ", payload_type: " << payload_type;
Peter Boström74f6e9e2016-04-04 17:56:10 +0200145 ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr");
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000146 ss << '}';
147 return ss.str();
148}
149
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000150std::string VideoSendStream::Config::Rtp::Rtx::ToString()
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000151 const {
152 std::stringstream ss;
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000153 ss << "{ssrcs: [";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000154 for (size_t i = 0; i < ssrcs.size(); ++i) {
155 ss << ssrcs[i];
156 if (i != ssrcs.size() - 1)
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000157 ss << ", ";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000158 }
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000159 ss << ']';
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000160
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000161 ss << ", payload_type: " << payload_type;
162 ss << '}';
163 return ss.str();
164}
165
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000166std::string VideoSendStream::Config::Rtp::ToString() const {
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000167 std::stringstream ss;
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000168 ss << "{ssrcs: [";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000169 for (size_t i = 0; i < ssrcs.size(); ++i) {
170 ss << ssrcs[i];
171 if (i != ssrcs.size() - 1)
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000172 ss << ", ";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000173 }
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000174 ss << ']';
Taylor Brandstetter5f0b83b2016-03-18 15:02:07 -0700175 ss << ", rtcp_mode: "
176 << (rtcp_mode == RtcpMode::kCompound ? "RtcpMode::kCompound"
177 : "RtcpMode::kReducedSize");
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000178 ss << ", max_packet_size: " << max_packet_size;
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000179 ss << ", extensions: [";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000180 for (size_t i = 0; i < extensions.size(); ++i) {
181 ss << extensions[i].ToString();
182 if (i != extensions.size() - 1)
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000183 ss << ", ";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000184 }
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000185 ss << ']';
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000186
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000187 ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}';
brandtrb5f2c3f2016-10-04 23:28:39 -0700188 ss << ", ulpfec: " << ulpfec.ToString();
brandtr3d200bd2017-01-16 06:59:19 -0800189
190 ss << ", flexfec: {payload_type: " << flexfec.payload_type;
191 ss << ", ssrc: " << flexfec.ssrc;
192 ss << ", protected_media_ssrcs: [";
193 for (size_t i = 0; i < flexfec.protected_media_ssrcs.size(); ++i) {
194 ss << flexfec.protected_media_ssrcs[i];
195 if (i != flexfec.protected_media_ssrcs.size() - 1)
196 ss << ", ";
197 }
brandtr3b941be2017-03-17 07:02:46 -0700198 ss << "]}";
brandtr3d200bd2017-01-16 06:59:19 -0800199
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000200 ss << ", rtx: " << rtx.ToString();
201 ss << ", c_name: " << c_name;
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000202 ss << '}';
203 return ss.str();
204}
205
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000206std::string VideoSendStream::Config::ToString() const {
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000207 std::stringstream ss;
208 ss << "{encoder_settings: " << encoder_settings.ToString();
209 ss << ", rtp: " << rtp.ToString();
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000210 ss << ", pre_encode_callback: "
nisse76bc8e82017-02-07 09:37:41 -0800211 << (pre_encode_callback ? "(VideoSinkInterface)" : "nullptr");
Peter Boström74f6e9e2016-04-04 17:56:10 +0200212 ss << ", post_encode_callback: "
213 << (post_encode_callback ? "(EncodedFrameObserver)" : "nullptr");
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000214 ss << ", render_delay_ms: " << render_delay_ms;
215 ss << ", target_delay_ms: " << target_delay_ms;
216 ss << ", suspend_below_min_bitrate: " << (suspend_below_min_bitrate ? "on"
217 : "off");
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000218 ss << '}';
219 return ss.str();
220}
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000221
asapersson2e5cfcd2016-08-11 08:41:18 -0700222std::string VideoSendStream::Stats::ToString(int64_t time_ms) const {
223 std::stringstream ss;
224 ss << "VideoSendStream stats: " << time_ms << ", {";
225 ss << "input_fps: " << input_frame_rate << ", ";
226 ss << "encode_fps: " << encode_frame_rate << ", ";
227 ss << "encode_ms: " << avg_encode_time_ms << ", ";
228 ss << "encode_usage_perc: " << encode_usage_percent << ", ";
229 ss << "target_bps: " << target_media_bitrate_bps << ", ";
230 ss << "media_bps: " << media_bitrate_bps << ", ";
Pera48ddb72016-09-29 11:48:50 +0200231 ss << "preferred_media_bitrate_bps: " << preferred_media_bitrate_bps << ", ";
asapersson2e5cfcd2016-08-11 08:41:18 -0700232 ss << "suspended: " << (suspended ? "true" : "false") << ", ";
233 ss << "bw_adapted: " << (bw_limited_resolution ? "true" : "false");
234 ss << '}';
235 for (const auto& substream : substreams) {
asaperssona6a699a2016-11-25 03:52:46 -0800236 if (!substream.second.is_rtx && !substream.second.is_flexfec) {
asapersson2e5cfcd2016-08-11 08:41:18 -0700237 ss << " {ssrc: " << substream.first << ", ";
238 ss << substream.second.ToString();
239 ss << '}';
240 }
241 }
242 return ss.str();
243}
244
245std::string VideoSendStream::StreamStats::ToString() const {
246 std::stringstream ss;
247 ss << "width: " << width << ", ";
248 ss << "height: " << height << ", ";
249 ss << "key: " << frame_counts.key_frames << ", ";
250 ss << "delta: " << frame_counts.delta_frames << ", ";
251 ss << "total_bps: " << total_bitrate_bps << ", ";
252 ss << "retransmit_bps: " << retransmit_bitrate_bps << ", ";
253 ss << "avg_delay_ms: " << avg_delay_ms << ", ";
254 ss << "max_delay_ms: " << max_delay_ms << ", ";
255 ss << "cum_loss: " << rtcp_stats.cumulative_lost << ", ";
256 ss << "max_ext_seq: " << rtcp_stats.extended_max_sequence_number << ", ";
257 ss << "nack: " << rtcp_packet_type_counts.nack_packets << ", ";
258 ss << "fir: " << rtcp_packet_type_counts.fir_packets << ", ";
259 ss << "pli: " << rtcp_packet_type_counts.pli_packets;
260 return ss.str();
261}
262
Peter Boströme4499152016-02-05 11:13:28 +0100263namespace {
264
Peter Boström39593972016-02-15 11:27:15 +0100265bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
deadbeefc964d0b2017-04-03 10:03:35 -0700266 rtc::Optional<VideoCodecType> codecType =
267 PayloadNameToCodecType(payload_name);
268 if (codecType &&
269 (*codecType == kVideoCodecVP8 || *codecType == kVideoCodecVP9)) {
perkj26091b12016-09-01 01:17:40 -0700270 return true;
deadbeefc964d0b2017-04-03 10:03:35 -0700271 }
272 RTC_DCHECK((codecType && *codecType == kVideoCodecH264) ||
273 payload_name == "FAKE")
perkj26091b12016-09-01 01:17:40 -0700274 << "unknown payload_name " << payload_name;
Peter Boström39593972016-02-15 11:27:15 +0100275 return false;
276}
277
Per512ecb32016-09-23 15:52:06 +0200278int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
279 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700280 bool pad_to_min_bitrate) {
281 int pad_up_to_bitrate_bps = 0;
282 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200283 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700284 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200285 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700286 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200287 for (size_t i = 0; i < streams.size() - 1; ++i)
288 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700289 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200290 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700291 }
292
293 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200294 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700295
296 return pad_up_to_bitrate_bps;
297}
298
michaelt192132e2017-01-26 09:05:27 -0800299uint32_t CalculateOverheadRateBps(int packets_per_second,
300 size_t overhead_bytes_per_packet,
301 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800302 uint32_t overhead_bps =
303 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
304 return std::min(overhead_bps, max_overhead_bps);
305}
306
307int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
308 size_t packet_size_bits = 8 * packet_size_bytes;
309 // Ceil for int value of bitrate_bps / packet_size_bits.
310 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
311 packet_size_bits);
312}
313
Peter Boströme4499152016-02-05 11:13:28 +0100314} // namespace
315
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000316namespace internal {
perkj26091b12016-09-01 01:17:40 -0700317
318// VideoSendStreamImpl implements internal::VideoSendStream.
319// It is created and destroyed on |worker_queue|. The intent is to decrease the
320// need for locking and to ensure methods are called in sequence.
321// Public methods except |DeliverRtcp| must be called on |worker_queue|.
322// DeliverRtcp is called on the libjingle worker thread or a network thread.
323// An encoder may deliver frames through the EncodedImageCallback on an
324// arbitrary thread.
325class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800326 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700327 public webrtc::VCMProtectionCallback,
sprang1a646ee2016-12-01 06:34:11 -0800328 public ViEEncoder::EncoderSink,
329 public VideoBitrateAllocationObserver {
perkj26091b12016-09-01 01:17:40 -0700330 public:
331 VideoSendStreamImpl(SendStatisticsProxy* stats_proxy,
332 rtc::TaskQueue* worker_queue,
333 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700334 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700335 BitrateAllocator* bitrate_allocator,
336 SendDelayStats* send_delay_stats,
337 VieRemb* remb,
338 ViEEncoder* vie_encoder,
339 RtcEventLog* event_log,
340 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200341 int initial_encoder_max_bitrate,
perkj26091b12016-09-01 01:17:40 -0700342 std::map<uint32_t, RtpState> suspended_ssrcs);
343 ~VideoSendStreamImpl() override;
344
345 // RegisterProcessThread register |module_process_thread| with those objects
346 // that use it. Registration has to happen on the thread were
347 // |module_process_thread| was created (libjingle's worker thread).
348 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
349 // maybe |worker_queue|.
350 void RegisterProcessThread(ProcessThread* module_process_thread);
351 void DeRegisterProcessThread();
352
353 void SignalNetworkState(NetworkState state);
354 bool DeliverRtcp(const uint8_t* packet, size_t length);
355 void Start();
356 void Stop();
357
perkj26091b12016-09-01 01:17:40 -0700358 VideoSendStream::RtpStateMap GetRtpStates() const;
359
palmkviste75f2042016-09-28 06:19:48 -0700360 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
361 size_t byte_limit);
362
nisse284542b2017-01-10 08:58:32 -0800363 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800364
perkj26091b12016-09-01 01:17:40 -0700365 private:
366 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200367 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700368
369 // Implements BitrateAllocatorObserver.
370 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
371 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800372 int64_t rtt,
373 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700374
375 // Implements webrtc::VCMProtectionCallback.
376 int ProtectionRequest(const FecProtectionParams* delta_params,
377 const FecProtectionParams* key_params,
378 uint32_t* sent_video_rate_bps,
379 uint32_t* sent_nack_rate_bps,
380 uint32_t* sent_fec_rate_bps) override;
381
michaelta3328772016-11-29 09:25:03 -0800382 // Implements OverheadObserver.
383 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
384
Per512ecb32016-09-23 15:52:06 +0200385 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
386 int min_transmit_bitrate_bps) override;
387
perkj26091b12016-09-01 01:17:40 -0700388 // Implements EncodedImageCallback. The implementation routes encoded frames
389 // to the |payload_router_| and |config.pre_encode_callback| if set.
390 // Called on an arbitrary encoder callback thread.
391 EncodedImageCallback::Result OnEncodedImage(
392 const EncodedImage& encoded_image,
393 const CodecSpecificInfo* codec_specific_info,
394 const RTPFragmentationHeader* fragmentation) override;
395
sprang1a646ee2016-12-01 06:34:11 -0800396 // Implements VideoBitrateAllocationObserver.
397 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
398
perkj26091b12016-09-01 01:17:40 -0700399 void ConfigureProtection();
400 void ConfigureSsrcs();
401 void SignalEncoderTimedOut();
402 void SignalEncoderActive();
403
elad.alon0fe12162017-01-31 05:48:37 -0800404 const bool send_side_bwe_with_overhead_;
405
perkj26091b12016-09-01 01:17:40 -0700406 SendStatisticsProxy* const stats_proxy_;
407 const VideoSendStream::Config* const config_;
408 std::map<uint32_t, RtpState> suspended_ssrcs_;
409
410 ProcessThread* module_process_thread_;
411 rtc::ThreadChecker module_process_thread_checker_;
412 rtc::TaskQueue* const worker_queue_;
413
414 rtc::CriticalSection encoder_activity_crit_sect_;
415 CheckEncoderActivityTask* check_encoder_activity_task_
416 GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200417
perkj26091b12016-09-01 01:17:40 -0700418 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700419 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700420 BitrateAllocator* const bitrate_allocator_;
421 VieRemb* const remb_;
422
brandtr3b941be2017-03-17 07:02:46 -0700423 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800424 std::unique_ptr<FlexfecSender> flexfec_sender_;
425
palmkviste75f2042016-09-28 06:19:48 -0700426 rtc::CriticalSection ivf_writers_crit_;
427 std::unique_ptr<IvfFileWriter> file_writers_[kMaxSimulcastStreams] GUARDED_BY(
428 ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700429
430 int max_padding_bitrate_;
431 int encoder_min_bitrate_bps_;
432 uint32_t encoder_max_bitrate_bps_;
433 uint32_t encoder_target_rate_bps_;
434
435 ViEEncoder* const vie_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700436 EncoderRtcpFeedback encoder_feedback_;
perkj26091b12016-09-01 01:17:40 -0700437 ProtectionBitrateCalculator protection_bitrate_calculator_;
438
439 const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
440 // RtpRtcp modules, declared here as they use other members on construction.
441 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
442 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700443
444 // |weak_ptr_| to our self. This is used since we can not call
445 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
446 // an existing WeakPtr.
447 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
448 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
449 // invalidated before any other members are destroyed.
450 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800451
452 rtc::CriticalSection overhead_bytes_per_packet_crit_;
453 size_t overhead_bytes_per_packet_ GUARDED_BY(overhead_bytes_per_packet_crit_);
454 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700455};
456
457// TODO(tommi): See if there's a more elegant way to create a task that creates
458// an object on the correct task queue.
459class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
460 public:
461 ConstructionTask(std::unique_ptr<VideoSendStreamImpl>* send_stream,
462 rtc::Event* done_event,
463 SendStatisticsProxy* stats_proxy,
464 ViEEncoder* vie_encoder,
465 ProcessThread* module_process_thread,
466 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700467 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700468 BitrateAllocator* bitrate_allocator,
469 SendDelayStats* send_delay_stats,
470 VieRemb* remb,
471 RtcEventLog* event_log,
472 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200473 int initial_encoder_max_bitrate,
perkj26091b12016-09-01 01:17:40 -0700474 const std::map<uint32_t, RtpState>& suspended_ssrcs)
475 : send_stream_(send_stream),
476 done_event_(done_event),
477 stats_proxy_(stats_proxy),
478 vie_encoder_(vie_encoder),
479 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700480 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700481 bitrate_allocator_(bitrate_allocator),
482 send_delay_stats_(send_delay_stats),
483 remb_(remb),
484 event_log_(event_log),
485 config_(config),
Per512ecb32016-09-23 15:52:06 +0200486 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
perkj26091b12016-09-01 01:17:40 -0700487 suspended_ssrcs_(suspended_ssrcs) {}
488
489 ~ConstructionTask() override { done_event_->Set(); }
490
491 private:
492 bool Run() override {
493 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700494 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
495 bitrate_allocator_, send_delay_stats_, remb_, vie_encoder_, event_log_,
496 config_, initial_encoder_max_bitrate_, std::move(suspended_ssrcs_)));
perkj26091b12016-09-01 01:17:40 -0700497 return true;
498 }
499
500 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
501 rtc::Event* const done_event_;
502 SendStatisticsProxy* const stats_proxy_;
503 ViEEncoder* const vie_encoder_;
504 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700505 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700506 BitrateAllocator* const bitrate_allocator_;
507 SendDelayStats* const send_delay_stats_;
508 VieRemb* const remb_;
509 RtcEventLog* const event_log_;
510 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200511 int initial_encoder_max_bitrate_;
perkj26091b12016-09-01 01:17:40 -0700512 std::map<uint32_t, RtpState> suspended_ssrcs_;
513};
514
515class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
516 public:
517 DestructAndGetRtpStateTask(VideoSendStream::RtpStateMap* state_map,
518 std::unique_ptr<VideoSendStreamImpl> send_stream,
519 rtc::Event* done_event)
520 : state_map_(state_map),
521 send_stream_(std::move(send_stream)),
522 done_event_(done_event) {}
523
524 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
525
526 private:
527 bool Run() override {
528 send_stream_->Stop();
529 *state_map_ = send_stream_->GetRtpStates();
530 send_stream_.reset();
531 done_event_->Set();
532 return true;
533 }
534
535 VideoSendStream::RtpStateMap* state_map_;
536 std::unique_ptr<VideoSendStreamImpl> send_stream_;
537 rtc::Event* done_event_;
538};
539
540// CheckEncoderActivityTask is used for tracking when the encoder last produced
541// and encoded video frame. If the encoder has not produced anything the last
542// kEncoderTimeOutMs we also want to stop sending padding.
543class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
544 public:
545 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700546 explicit CheckEncoderActivityTask(
547 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
548 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700549
550 void Stop() {
551 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700552 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700553 }
554
555 void UpdateEncoderActivity() {
556 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
557 // whatever thread the real encoder implementation run on. In the case of
558 // hardware encoders, there might be several encoders
559 // running in parallel on different threads.
560 rtc::AtomicOps::ReleaseStore(&activity_, 1);
561 }
562
563 private:
564 bool Run() override {
565 RTC_CHECK(task_checker_.CalledSequentially());
566 if (!send_stream_)
567 return true;
568 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
569 if (!timed_out_) {
570 send_stream_->SignalEncoderTimedOut();
571 }
572 timed_out_ = true;
573 } else if (timed_out_) {
574 send_stream_->SignalEncoderActive();
575 timed_out_ = false;
576 }
577 rtc::AtomicOps::ReleaseStore(&activity_, 0);
578
579 rtc::TaskQueue::Current()->PostDelayedTask(
580 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
581 // Return false to prevent this task from being deleted. Ownership has been
582 // transferred to the task queue when PostDelayedTask was called.
583 return false;
584 }
585 volatile int activity_;
586
587 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700588 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700589 bool timed_out_;
590};
591
Per512ecb32016-09-23 15:52:06 +0200592class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700593 public:
perkj8ff860a2016-10-03 00:30:04 -0700594 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200595 std::vector<VideoStream> streams,
596 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700597 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200598 streams_(std::move(streams)),
599 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700600
601 private:
602 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700603 if (send_stream_)
604 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
605 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700606 return true;
607 }
608
perkj8ff860a2016-10-03 00:30:04 -0700609 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200610 std::vector<VideoStream> streams_;
611 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700612};
613
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000614VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200615 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200616 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700617 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200618 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700619 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800620 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700621 SendDelayStats* send_delay_stats,
mflodman86aabb22016-03-11 15:44:32 +0100622 VieRemb* remb,
tereliusadafe0b2016-05-26 01:58:40 -0700623 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700624 VideoSendStream::Config config,
625 VideoEncoderConfig encoder_config,
Peter Boström45553ae2015-05-08 13:54:38 +0200626 const std::map<uint32_t, RtpState>& suspended_ssrcs)
perkj26091b12016-09-01 01:17:40 -0700627 : worker_queue_(worker_queue),
628 thread_sync_event_(false /* manual_reset */, false),
629 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800630 config,
631 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800632 config_(std::move(config)),
633 content_type_(encoder_config.content_type) {
perkj803d97f2016-11-01 11:45:46 -0700634 vie_encoder_.reset(new ViEEncoder(
635 num_cpu_cores, &stats_proxy_, config_.encoder_settings,
636 config_.pre_encode_callback, config_.post_encode_callback));
perkj26091b12016-09-01 01:17:40 -0700637 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
638 &send_stream_, &thread_sync_event_, &stats_proxy_, vie_encoder_.get(),
nisseb8f9a322017-03-27 05:36:15 -0700639 module_process_thread, call_stats, transport, bitrate_allocator,
640 send_delay_stats, remb, event_log, &config_,
perkjfa10b552016-10-02 23:45:26 -0700641 encoder_config.max_bitrate_bps, suspended_ssrcs)));
perkj26091b12016-09-01 01:17:40 -0700642
643 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
644 // |module_process_thread| must be registered and deregistered on the thread
645 // it was created on.
646 thread_sync_event_.Wait(rtc::Event::kForever);
647 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800648 // TODO(sprang): Enable this also for regular video calls if it works well.
649 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
650 // Only signal target bitrate for screenshare streams, for now.
651 vie_encoder_->SetBitrateObserver(send_stream_.get());
652 }
perkj26091b12016-09-01 01:17:40 -0700653 vie_encoder_->RegisterProcessThread(module_process_thread);
654
655 ReconfigureVideoEncoder(std::move(encoder_config));
656}
657
658VideoSendStream::~VideoSendStream() {
659 RTC_DCHECK_RUN_ON(&thread_checker_);
660 RTC_DCHECK(!send_stream_);
661}
662
663void VideoSendStream::Start() {
664 RTC_DCHECK_RUN_ON(&thread_checker_);
665 LOG(LS_INFO) << "VideoSendStream::Start";
666 VideoSendStreamImpl* send_stream = send_stream_.get();
667 worker_queue_->PostTask([this, send_stream] {
668 send_stream->Start();
669 thread_sync_event_.Set();
670 });
671
672 // It is expected that after VideoSendStream::Start has been called, incoming
673 // frames are not dropped in ViEEncoder. To ensure this, Start has to be
674 // synchronized.
675 thread_sync_event_.Wait(rtc::Event::kForever);
676}
677
678void VideoSendStream::Stop() {
679 RTC_DCHECK_RUN_ON(&thread_checker_);
680 LOG(LS_INFO) << "VideoSendStream::Stop";
681 VideoSendStreamImpl* send_stream = send_stream_.get();
682 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
683}
684
perkja49cbd32016-09-16 07:53:41 -0700685void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700686 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
687 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700688 RTC_DCHECK_RUN_ON(&thread_checker_);
perkj803d97f2016-11-01 11:45:46 -0700689 vie_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700690}
691
692void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700693 // TODO(perkj): Some test cases in VideoSendStreamTest call
694 // ReconfigureVideoEncoder from the network thread.
695 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800696 RTC_DCHECK(content_type_ == config.content_type);
asapersson5f7226f2016-11-25 04:37:00 -0800697 vie_encoder_->ConfigureEncoder(std::move(config), config_.rtp.max_packet_size,
698 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700699}
700
701VideoSendStream::Stats VideoSendStream::GetStats() {
702 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
703 // a network thread. See comment in Call::GetStats().
704 // RTC_DCHECK_RUN_ON(&thread_checker_);
705 return stats_proxy_.GetStats();
706}
707
708void VideoSendStream::SignalNetworkState(NetworkState state) {
709 RTC_DCHECK_RUN_ON(&thread_checker_);
710 VideoSendStreamImpl* send_stream = send_stream_.get();
711 worker_queue_->PostTask(
712 [send_stream, state] { send_stream->SignalNetworkState(state); });
713}
714
715VideoSendStream::RtpStateMap VideoSendStream::StopPermanentlyAndGetRtpStates() {
716 RTC_DCHECK_RUN_ON(&thread_checker_);
717 vie_encoder_->Stop();
718 vie_encoder_->DeRegisterProcessThread();
719 VideoSendStream::RtpStateMap state_map;
720 send_stream_->DeRegisterProcessThread();
721 worker_queue_->PostTask(
722 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
723 &state_map, std::move(send_stream_), &thread_sync_event_)));
724 thread_sync_event_.Wait(rtc::Event::kForever);
725 return state_map;
726}
727
nisse284542b2017-01-10 08:58:32 -0800728void VideoSendStream::SetTransportOverhead(
729 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800730 RTC_DCHECK_RUN_ON(&thread_checker_);
731 VideoSendStreamImpl* send_stream = send_stream_.get();
732 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
733 send_stream->SetTransportOverhead(transport_overhead_per_packet);
734 });
735}
736
perkj26091b12016-09-01 01:17:40 -0700737bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
738 // Called on a network thread.
739 return send_stream_->DeliverRtcp(packet, length);
740}
741
palmkviste75f2042016-09-28 06:19:48 -0700742void VideoSendStream::EnableEncodedFrameRecording(
743 const std::vector<rtc::PlatformFile>& files,
744 size_t byte_limit) {
745 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
746}
747
perkj26091b12016-09-01 01:17:40 -0700748VideoSendStreamImpl::VideoSendStreamImpl(
749 SendStatisticsProxy* stats_proxy,
750 rtc::TaskQueue* worker_queue,
751 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700752 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700753 BitrateAllocator* bitrate_allocator,
754 SendDelayStats* send_delay_stats,
755 VieRemb* remb,
756 ViEEncoder* vie_encoder,
757 RtcEventLog* event_log,
758 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200759 int initial_encoder_max_bitrate,
perkj26091b12016-09-01 01:17:40 -0700760 std::map<uint32_t, RtpState> suspended_ssrcs)
sprangc1b57a12017-02-28 08:50:47 -0800761 : send_side_bwe_with_overhead_(
762 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800763 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000764 config_(config),
perkj26091b12016-09-01 01:17:40 -0700765 suspended_ssrcs_(std::move(suspended_ssrcs)),
766 module_process_thread_(nullptr),
767 worker_queue_(worker_queue),
768 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200769 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700770 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100771 bitrate_allocator_(bitrate_allocator),
Stefan Holmer58c664c2016-02-08 14:31:30 +0100772 remb_(remb),
brandtre950cad2016-11-15 05:25:41 -0800773 flexfec_sender_(MaybeCreateFlexfecSender(*config_)),
perkj26091b12016-09-01 01:17:40 -0700774 max_padding_bitrate_(0),
775 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200776 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700777 encoder_target_rate_bps_(0),
perkj26091b12016-09-01 01:17:40 -0700778 vie_encoder_(vie_encoder),
perkj600246e2016-05-04 11:26:51 -0700779 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700780 config_->rtp.ssrcs,
781 vie_encoder),
Per69b332d2016-06-02 15:45:42 +0200782 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
nisseb8f9a322017-03-27 05:36:15 -0700783 bandwidth_observer_(transport->send_side_cc()
784 ->GetBitrateController()
785 ->CreateRtcpBandwidthObserver()),
786 rtp_rtcp_modules_(CreateRtpRtcpModules(
787 config_->send_transport,
788 &encoder_feedback_,
789 bandwidth_observer_.get(),
790 transport,
791 call_stats_->rtcp_rtt_stats(),
792 flexfec_sender_.get(),
793 stats_proxy_,
794 send_delay_stats,
795 event_log,
796 transport->send_side_cc()->GetRetransmissionRateLimiter(),
797 this,
798 config_->rtp.ssrcs.size())),
perkj26091b12016-09-01 01:17:40 -0700799 payload_router_(rtp_rtcp_modules_,
perkj8ff860a2016-10-03 00:30:04 -0700800 config_->encoder_settings.payload_type),
michaelta3328772016-11-29 09:25:03 -0800801 weak_ptr_factory_(this),
802 overhead_bytes_per_packet_(0),
803 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700804 RTC_DCHECK_RUN_ON(worker_queue_);
805 LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700806 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700807 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100808
perkj26091b12016-09-01 01:17:40 -0700809 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100810 RTC_DCHECK(call_stats_);
Stefan Holmer58c664c2016-02-08 14:31:30 +0100811 RTC_DCHECK(remb_);
nisseb8f9a322017-03-27 05:36:15 -0700812 RTC_DCHECK(transport_);
813 RTC_DCHECK(transport_->send_side_cc());
mflodman949c2f02015-10-16 02:31:11 -0700814
nisseb8f9a322017-03-27 05:36:15 -0700815 transport->send_side_cc()->EnablePeriodicAlrProbing(
sergeyu80ed35e2016-11-28 13:11:13 -0800816 config_->periodic_alr_bandwidth_probing);
817
Per83d09102016-04-15 14:59:13 +0200818 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800819
820 // We add the highest spatial layer first to ensure it'll be prioritized
821 // when sending padding, with the hope that the packet rate will be smaller,
822 // and that it's more important to protect than the lower layers.
823 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
nissefdbfdc92017-03-31 05:44:52 -0700824 transport->packet_router()->AddSendRtpModule(rtp_rtcp);
mflodman949c2f02015-10-16 02:31:11 -0700825
perkj26091b12016-09-01 01:17:40 -0700826 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
827 const std::string& extension = config_->rtp.extensions[i].uri;
828 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200829 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700830 RTC_DCHECK_GE(id, 1);
831 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100832 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
833 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
834 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
835 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000836 }
837 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000838
Peter Boström723ead82016-02-22 15:14:01 +0100839 remb_->AddRembSender(rtp_rtcp_modules_[0]);
840 rtp_rtcp_modules_[0]->SetREMBStatus(true);
mflodman@webrtc.org92c27932013-12-13 16:36:28 +0000841
Per83d09102016-04-15 14:59:13 +0200842 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000843 ConfigureSsrcs();
844
Peter Boström723ead82016-02-22 15:14:01 +0100845 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700846 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800847
Peter Boström723ead82016-02-22 15:14:01 +0100848 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700849 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
850 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800851 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100852 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700853 config_->encoder_settings.payload_type,
854 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100855 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000856
perkj26091b12016-09-01 01:17:40 -0700857 RTC_DCHECK(config_->encoder_settings.encoder);
858 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
859 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000860
perkj26091b12016-09-01 01:17:40 -0700861 vie_encoder_->SetStartBitrate(bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700862
863 // Only request rotation at the source when we positively know that the remote
864 // side doesn't support the rotation extension. This allows us to prepare the
865 // encoder in the expectation that rotation is supported - which is the common
866 // case.
867 bool rotation_applied =
868 std::find_if(config_->rtp.extensions.begin(),
869 config_->rtp.extensions.end(),
870 [](const RtpExtension& extension) {
871 return extension.uri == RtpExtension::kVideoRotationUri;
872 }) == config_->rtp.extensions.end();
873
874 vie_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000875}
876
perkj26091b12016-09-01 01:17:40 -0700877void VideoSendStreamImpl::RegisterProcessThread(
878 ProcessThread* module_process_thread) {
879 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
880 RTC_DCHECK(!module_process_thread_);
881 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100882
perkj26091b12016-09-01 01:17:40 -0700883 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800884 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700885}
Peter Boströmca835252016-02-11 15:59:46 +0100886
perkj26091b12016-09-01 01:17:40 -0700887void VideoSendStreamImpl::DeRegisterProcessThread() {
888 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
889 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
890 module_process_thread_->DeRegisterModule(rtp_rtcp);
891}
Peter Boströma4c76882016-03-03 16:29:02 +0100892
perkj26091b12016-09-01 01:17:40 -0700893VideoSendStreamImpl::~VideoSendStreamImpl() {
894 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800895 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700896 << "VideoSendStreamImpl::Stop not called";
897 LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000898
Peter Boström723ead82016-02-22 15:14:01 +0100899 rtp_rtcp_modules_[0]->SetREMBStatus(false);
900 remb_->RemoveRembSender(rtp_rtcp_modules_[0]);
mflodman949c2f02015-10-16 02:31:11 -0700901
Per83d09102016-04-15 14:59:13 +0200902 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700903 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200904 delete rtp_rtcp;
905 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000906}
907
perkj26091b12016-09-01 01:17:40 -0700908bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
909 // Runs on a network thread.
910 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700911 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
912 rtp_rtcp->IncomingRtcpPacket(packet, length);
913 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000914}
915
perkj26091b12016-09-01 01:17:40 -0700916void VideoSendStreamImpl::Start() {
917 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700918 LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800919 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100920 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200921 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800922 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700923
924 bitrate_allocator_->AddObserver(
925 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
926 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
927
928 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700929 {
perkj26091b12016-09-01 01:17:40 -0700930 rtc::CritScope lock(&encoder_activity_crit_sect_);
931 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700932 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700933 worker_queue_->PostDelayedTask(
934 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
935 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700936 }
perkj26091b12016-09-01 01:17:40 -0700937
938 vie_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000939}
940
perkj26091b12016-09-01 01:17:40 -0700941void VideoSendStreamImpl::Stop() {
942 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700943 LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800944 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100945 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200946 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800947 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700948 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700949 {
perkj26091b12016-09-01 01:17:40 -0700950 rtc::CritScope lock(&encoder_activity_crit_sect_);
951 check_encoder_activity_task_->Stop();
952 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700953 }
perkj26091b12016-09-01 01:17:40 -0700954 vie_encoder_->OnBitrateUpdated(0, 0, 0);
955 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000956}
957
perkj26091b12016-09-01 01:17:40 -0700958void VideoSendStreamImpl::SignalEncoderTimedOut() {
959 RTC_DCHECK_RUN_ON(worker_queue_);
960 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
961 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
962 // if a camera stops producing frames.
963 if (encoder_target_rate_bps_ > 0) {
964 LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
965 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100966 }
967}
968
sprang1a646ee2016-12-01 06:34:11 -0800969void VideoSendStreamImpl::OnBitrateAllocationUpdated(
970 const BitrateAllocation& allocation) {
971 payload_router_.OnBitrateAllocationUpdated(allocation);
972}
973
perkj26091b12016-09-01 01:17:40 -0700974void VideoSendStreamImpl::SignalEncoderActive() {
975 RTC_DCHECK_RUN_ON(worker_queue_);
976 LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
977 bitrate_allocator_->AddObserver(
978 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
979 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
980}
981
Per512ecb32016-09-23 15:52:06 +0200982void VideoSendStreamImpl::OnEncoderConfigurationChanged(
983 std::vector<VideoStream> streams,
984 int min_transmit_bitrate_bps) {
985 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200986 worker_queue_->PostTask(
987 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700988 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200989 return;
990 }
991 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
992 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
993 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700994 RTC_DCHECK_RUN_ON(worker_queue_);
995
996 const int kEncoderMinBitrateBps = 30000;
997 encoder_min_bitrate_bps_ =
Per512ecb32016-09-23 15:52:06 +0200998 std::max(streams[0].min_bitrate_bps, kEncoderMinBitrateBps);
perkj26091b12016-09-01 01:17:40 -0700999 encoder_max_bitrate_bps_ = 0;
Per512ecb32016-09-23 15:52:06 +02001000 for (const auto& stream : streams)
perkj26091b12016-09-01 01:17:40 -07001001 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Per512ecb32016-09-23 15:52:06 +02001002 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
1003 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -07001004
1005 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +02001006 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -07001007 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001008 }
perkj26091b12016-09-01 01:17:40 -07001009
1010 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +02001011 streams.back().temporal_layer_thresholds_bps.size() + 1;
perkj26091b12016-09-01 01:17:40 -07001012 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +02001013 streams[0].width, streams[0].height, number_of_temporal_layers,
1014 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -07001015
sprang1a646ee2016-12-01 06:34:11 -08001016 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -07001017 // The send stream is started already. Update the allocator with new bitrate
1018 // limits.
1019 bitrate_allocator_->AddObserver(
1020 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
1021 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
1022 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001023}
1024
perkj26091b12016-09-01 01:17:40 -07001025EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001026 const EncodedImage& encoded_image,
1027 const CodecSpecificInfo* codec_specific_info,
1028 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -07001029 // Encoded is called on whatever thread the real encoder implementation run
1030 // on. In the case of hardware encoders, there might be several encoders
1031 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -08001032 size_t simulcast_idx = 0;
1033 if (codec_specific_info->codecType == kVideoCodecVP8) {
1034 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
1035 }
perkj26091b12016-09-01 01:17:40 -07001036 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -08001037 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
1038 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
1039 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -07001040 }
perkj26091b12016-09-01 01:17:40 -07001041 {
1042 rtc::CritScope lock(&encoder_activity_crit_sect_);
1043 if (check_encoder_activity_task_)
1044 check_encoder_activity_task_->UpdateEncoderActivity();
1045 }
sergeyu37ad3372016-06-14 15:29:37 -07001046
Per69b332d2016-06-02 15:45:42 +02001047 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001048 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001049 encoded_image, codec_specific_info, fragmentation);
1050
palmkviste75f2042016-09-28 06:19:48 -07001051 RTC_DCHECK(codec_specific_info);
1052
1053 int layer = codec_specific_info->codecType == kVideoCodecVP8
1054 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1055 : 0;
1056 {
1057 rtc::CritScope lock(&ivf_writers_crit_);
1058 if (file_writers_[layer].get()) {
1059 bool ok = file_writers_[layer]->WriteFrame(
1060 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001061 RTC_DCHECK(ok);
1062 }
1063 }
1064
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001065 return result;
perkjbc75d972016-05-02 06:31:25 -07001066}
1067
perkj26091b12016-09-01 01:17:40 -07001068void VideoSendStreamImpl::ConfigureProtection() {
1069 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001070
brandtre950cad2016-11-15 05:25:41 -08001071 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1072 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1073
1074 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001075 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1076 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001077 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001078
1079 // Shorthands.
1080 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001081 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001082 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1083 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1084
brandtre950cad2016-11-15 05:25:41 -08001085 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1086 if (flexfec_enabled) {
1087 // We can safely disable RED here, because if the remote supports FlexFEC,
1088 // we know that it has a receiver without the RED/RTX workaround.
1089 // See http://crbug.com/webrtc/6650 for more information.
1090 if (IsRedEnabled()) {
1091 LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
1092 DisableRed();
1093 }
1094 if (IsUlpfecEnabled()) {
1095 LOG(LS_INFO)
1096 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1097 DisableUlpfec();
1098 }
1099 }
1100
Per83d09102016-04-15 14:59:13 +02001101 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001102 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1103 // is a waste of bandwidth since FEC packets still have to be transmitted.
1104 // Note that this is not the case with FlexFEC.
1105 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001106 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001107 config_->encoder_settings.payload_name)) {
brandtre6f98c72016-11-11 03:28:30 -08001108 LOG(LS_WARNING)
1109 << "Transmitting payload type without picture ID using "
1110 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1111 "also have to be retransmitted. Disabling ULPFEC.";
1112 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001113 }
1114
brandtre6f98c72016-11-11 03:28:30 -08001115 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001116 //
brandtre6f98c72016-11-11 03:28:30 -08001117 // Due to how old receivers work, we need to always send RED if it has been
1118 // negotiated. This is a remnant of an old RED/RTX workaround, see
1119 // https://codereview.webrtc.org/2469093003.
1120 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1121 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1122 // no point in using RED without ULPFEC.
1123 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001124 RTC_DCHECK_GE(red_payload_type, 0);
1125 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001126 }
brandtre6f98c72016-11-11 03:28:30 -08001127 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001128 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1129 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001130 if (!IsRedEnabled()) {
1131 LOG(LS_WARNING)
1132 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1133 DisableUlpfec();
1134 }
Per83d09102016-04-15 14:59:13 +02001135 }
1136
1137 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1138 // Set NACK.
1139 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001140 true,
Per83d09102016-04-15 14:59:13 +02001141 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001142 // Set RED/ULPFEC information.
Per83d09102016-04-15 14:59:13 +02001143 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrf1bb4762016-11-07 03:05:06 -08001144 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001145 }
1146 }
1147
brandtre950cad2016-11-15 05:25:41 -08001148 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1149 // so enable that logic if either of those FEC schemes are enabled.
1150 protection_bitrate_calculator_.SetProtectionMethod(
1151 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001152}
1153
perkj26091b12016-09-01 01:17:40 -07001154void VideoSendStreamImpl::ConfigureSsrcs() {
1155 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001156 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001157 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1158 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001159 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1160 rtp_rtcp->SetSSRC(ssrc);
1161
1162 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001163 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001164 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001165 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001166 }
1167
Peter Boström723ead82016-02-22 15:14:01 +01001168 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001169 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001170 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001171
Peter Boström723ead82016-02-22 15:14:01 +01001172 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001173 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1174 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1175 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001176 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1177 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001178 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001179 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001180 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001181 }
1182
Peter Boström723ead82016-02-22 15:14:01 +01001183 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001184 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001185 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001186 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1187 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001188 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1189 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001190 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1191 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001192 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001193 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1194 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001195 }
Stefan Holmer10880012016-02-03 13:29:59 +01001196 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001197}
1198
perkj26091b12016-09-01 01:17:40 -07001199std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1200 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001201 std::map<uint32_t, RtpState> rtp_states;
perkj26091b12016-09-01 01:17:40 -07001202 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1203 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001204 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1205 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001206 }
1207
perkj26091b12016-09-01 01:17:40 -07001208 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1209 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001210 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001211 }
1212
1213 return rtp_states;
1214}
1215
perkj26091b12016-09-01 01:17:40 -07001216void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1217 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001218 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001219 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001220 : RtcpMode::kOff);
1221 }
1222}
1223
perkj26091b12016-09-01 01:17:40 -07001224uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1225 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001226 int64_t rtt,
1227 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001228 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001229 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001230 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001231
michaelt192132e2017-01-26 09:05:27 -08001232 // Substract overhead from bitrate.
1233 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001234 uint32_t payload_bitrate_bps = bitrate_bps;
1235 if (send_side_bwe_with_overhead_) {
1236 payload_bitrate_bps -= CalculateOverheadRateBps(
1237 CalculatePacketRate(bitrate_bps,
1238 config_->rtp.max_packet_size +
1239 transport_overhead_bytes_per_packet_),
1240 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1241 bitrate_bps);
1242 }
michaelta3328772016-11-29 09:25:03 -08001243
Per69b332d2016-06-02 15:45:42 +02001244 // Get the encoder target rate. It is the estimated network rate -
1245 // protection overhead.
perkj26091b12016-09-01 01:17:40 -07001246 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001247 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1248 rtt);
1249
elad.alon0fe12162017-01-31 05:48:37 -08001250 uint32_t encoder_overhead_rate_bps =
1251 send_side_bwe_with_overhead_
1252 ? CalculateOverheadRateBps(
1253 CalculatePacketRate(encoder_target_rate_bps_,
1254 config_->rtp.max_packet_size +
1255 transport_overhead_bytes_per_packet_ -
1256 overhead_bytes_per_packet_),
1257 overhead_bytes_per_packet_ +
1258 transport_overhead_bytes_per_packet_,
1259 bitrate_bps - encoder_target_rate_bps_)
1260 : 0;
michaelt192132e2017-01-26 09:05:27 -08001261
1262 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1263 // protection_bitrate includes overhead.
1264 uint32_t protection_bitrate =
1265 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001266
perkj26091b12016-09-01 01:17:40 -07001267 encoder_target_rate_bps_ =
1268 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
1269 vie_encoder_->OnBitrateUpdated(encoder_target_rate_bps_, fraction_loss, rtt);
1270 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001271 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001272}
1273
palmkviste75f2042016-09-28 06:19:48 -07001274void VideoSendStreamImpl::EnableEncodedFrameRecording(
1275 const std::vector<rtc::PlatformFile>& files,
1276 size_t byte_limit) {
1277 {
1278 rtc::CritScope lock(&ivf_writers_crit_);
1279 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1280 if (i < files.size()) {
1281 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1282 } else {
1283 file_writers_[i].reset();
1284 }
1285 }
1286 }
1287
1288 if (!files.empty()) {
1289 // Make a keyframe appear as early as possible in the logs, to give actually
1290 // decodable output.
1291 vie_encoder_->SendKeyFrame();
1292 }
1293}
1294
perkj26091b12016-09-01 01:17:40 -07001295int VideoSendStreamImpl::ProtectionRequest(
1296 const FecProtectionParams* delta_params,
1297 const FecProtectionParams* key_params,
1298 uint32_t* sent_video_rate_bps,
1299 uint32_t* sent_nack_rate_bps,
1300 uint32_t* sent_fec_rate_bps) {
1301 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001302 *sent_video_rate_bps = 0;
1303 *sent_nack_rate_bps = 0;
1304 *sent_fec_rate_bps = 0;
1305 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1306 uint32_t not_used = 0;
1307 uint32_t module_video_rate = 0;
1308 uint32_t module_fec_rate = 0;
1309 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001310 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001311 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1312 &module_nack_rate);
1313 *sent_video_rate_bps += module_video_rate;
1314 *sent_nack_rate_bps += module_nack_rate;
1315 *sent_fec_rate_bps += module_fec_rate;
1316 }
1317 return 0;
1318}
1319
michaelta3328772016-11-29 09:25:03 -08001320void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1321 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1322 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1323}
1324
michaelt79e05882016-11-08 02:50:09 -08001325void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001326 size_t transport_overhead_bytes_per_packet) {
1327 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
1328 LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
1329 return;
1330 }
1331
michaelta3328772016-11-29 09:25:03 -08001332 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001333
nisseb8f9a322017-03-27 05:36:15 -07001334 transport_->send_side_cc()->SetTransportOverhead(
1335 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001336
1337 size_t rtp_packet_size =
1338 std::min(config_->rtp.max_packet_size,
1339 kPathMTU - transport_overhead_bytes_per_packet_);
1340
michaelta3328772016-11-29 09:25:03 -08001341 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001342 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001343 }
michaelt79e05882016-11-08 02:50:09 -08001344}
1345
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001346} // namespace internal
1347} // namespace webrtc