blob: 5f21d57919ba5f794134603ad0b517e7abc036df [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) {
perkj26091b12016-09-01 01:17:40 -0700266 if (payload_name == "VP8" || payload_name == "VP9")
267 return true;
268 RTC_DCHECK(payload_name == "H264" || payload_name == "FAKE")
269 << "unknown payload_name " << payload_name;
Peter Boström39593972016-02-15 11:27:15 +0100270 return false;
271}
272
Per512ecb32016-09-23 15:52:06 +0200273int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
274 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700275 bool pad_to_min_bitrate) {
276 int pad_up_to_bitrate_bps = 0;
277 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200278 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700279 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200280 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700281 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200282 for (size_t i = 0; i < streams.size() - 1; ++i)
283 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700284 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200285 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700286 }
287
288 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200289 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700290
291 return pad_up_to_bitrate_bps;
292}
293
michaelt192132e2017-01-26 09:05:27 -0800294uint32_t CalculateOverheadRateBps(int packets_per_second,
295 size_t overhead_bytes_per_packet,
296 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800297 uint32_t overhead_bps =
298 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
299 return std::min(overhead_bps, max_overhead_bps);
300}
301
302int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
303 size_t packet_size_bits = 8 * packet_size_bytes;
304 // Ceil for int value of bitrate_bps / packet_size_bits.
305 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
306 packet_size_bits);
307}
308
Peter Boströme4499152016-02-05 11:13:28 +0100309} // namespace
310
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000311namespace internal {
perkj26091b12016-09-01 01:17:40 -0700312
313// VideoSendStreamImpl implements internal::VideoSendStream.
314// It is created and destroyed on |worker_queue|. The intent is to decrease the
315// need for locking and to ensure methods are called in sequence.
316// Public methods except |DeliverRtcp| must be called on |worker_queue|.
317// DeliverRtcp is called on the libjingle worker thread or a network thread.
318// An encoder may deliver frames through the EncodedImageCallback on an
319// arbitrary thread.
320class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800321 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700322 public webrtc::VCMProtectionCallback,
sprang1a646ee2016-12-01 06:34:11 -0800323 public ViEEncoder::EncoderSink,
324 public VideoBitrateAllocationObserver {
perkj26091b12016-09-01 01:17:40 -0700325 public:
326 VideoSendStreamImpl(SendStatisticsProxy* stats_proxy,
327 rtc::TaskQueue* worker_queue,
328 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700329 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700330 BitrateAllocator* bitrate_allocator,
331 SendDelayStats* send_delay_stats,
332 VieRemb* remb,
333 ViEEncoder* vie_encoder,
334 RtcEventLog* event_log,
335 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200336 int initial_encoder_max_bitrate,
perkj26091b12016-09-01 01:17:40 -0700337 std::map<uint32_t, RtpState> suspended_ssrcs);
338 ~VideoSendStreamImpl() override;
339
340 // RegisterProcessThread register |module_process_thread| with those objects
341 // that use it. Registration has to happen on the thread were
342 // |module_process_thread| was created (libjingle's worker thread).
343 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
344 // maybe |worker_queue|.
345 void RegisterProcessThread(ProcessThread* module_process_thread);
346 void DeRegisterProcessThread();
347
348 void SignalNetworkState(NetworkState state);
349 bool DeliverRtcp(const uint8_t* packet, size_t length);
350 void Start();
351 void Stop();
352
perkj26091b12016-09-01 01:17:40 -0700353 VideoSendStream::RtpStateMap GetRtpStates() const;
354
palmkviste75f2042016-09-28 06:19:48 -0700355 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
356 size_t byte_limit);
357
nisse284542b2017-01-10 08:58:32 -0800358 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800359
perkj26091b12016-09-01 01:17:40 -0700360 private:
361 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200362 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700363
364 // Implements BitrateAllocatorObserver.
365 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
366 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800367 int64_t rtt,
368 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700369
370 // Implements webrtc::VCMProtectionCallback.
371 int ProtectionRequest(const FecProtectionParams* delta_params,
372 const FecProtectionParams* key_params,
373 uint32_t* sent_video_rate_bps,
374 uint32_t* sent_nack_rate_bps,
375 uint32_t* sent_fec_rate_bps) override;
376
michaelta3328772016-11-29 09:25:03 -0800377 // Implements OverheadObserver.
378 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
379
Per512ecb32016-09-23 15:52:06 +0200380 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
381 int min_transmit_bitrate_bps) override;
382
perkj26091b12016-09-01 01:17:40 -0700383 // Implements EncodedImageCallback. The implementation routes encoded frames
384 // to the |payload_router_| and |config.pre_encode_callback| if set.
385 // Called on an arbitrary encoder callback thread.
386 EncodedImageCallback::Result OnEncodedImage(
387 const EncodedImage& encoded_image,
388 const CodecSpecificInfo* codec_specific_info,
389 const RTPFragmentationHeader* fragmentation) override;
390
sprang1a646ee2016-12-01 06:34:11 -0800391 // Implements VideoBitrateAllocationObserver.
392 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
393
perkj26091b12016-09-01 01:17:40 -0700394 void ConfigureProtection();
395 void ConfigureSsrcs();
396 void SignalEncoderTimedOut();
397 void SignalEncoderActive();
398
elad.alon0fe12162017-01-31 05:48:37 -0800399 const bool send_side_bwe_with_overhead_;
400
perkj26091b12016-09-01 01:17:40 -0700401 SendStatisticsProxy* const stats_proxy_;
402 const VideoSendStream::Config* const config_;
403 std::map<uint32_t, RtpState> suspended_ssrcs_;
404
405 ProcessThread* module_process_thread_;
406 rtc::ThreadChecker module_process_thread_checker_;
407 rtc::TaskQueue* const worker_queue_;
408
409 rtc::CriticalSection encoder_activity_crit_sect_;
410 CheckEncoderActivityTask* check_encoder_activity_task_
411 GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200412
perkj26091b12016-09-01 01:17:40 -0700413 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700414 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700415 BitrateAllocator* const bitrate_allocator_;
416 VieRemb* const remb_;
417
brandtr3b941be2017-03-17 07:02:46 -0700418 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800419 std::unique_ptr<FlexfecSender> flexfec_sender_;
420
palmkviste75f2042016-09-28 06:19:48 -0700421 rtc::CriticalSection ivf_writers_crit_;
422 std::unique_ptr<IvfFileWriter> file_writers_[kMaxSimulcastStreams] GUARDED_BY(
423 ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700424
425 int max_padding_bitrate_;
426 int encoder_min_bitrate_bps_;
427 uint32_t encoder_max_bitrate_bps_;
428 uint32_t encoder_target_rate_bps_;
429
430 ViEEncoder* const vie_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700431 EncoderRtcpFeedback encoder_feedback_;
perkj26091b12016-09-01 01:17:40 -0700432 ProtectionBitrateCalculator protection_bitrate_calculator_;
433
434 const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
435 // RtpRtcp modules, declared here as they use other members on construction.
436 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
437 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700438
439 // |weak_ptr_| to our self. This is used since we can not call
440 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
441 // an existing WeakPtr.
442 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
443 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
444 // invalidated before any other members are destroyed.
445 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800446
447 rtc::CriticalSection overhead_bytes_per_packet_crit_;
448 size_t overhead_bytes_per_packet_ GUARDED_BY(overhead_bytes_per_packet_crit_);
449 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700450};
451
452// TODO(tommi): See if there's a more elegant way to create a task that creates
453// an object on the correct task queue.
454class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
455 public:
456 ConstructionTask(std::unique_ptr<VideoSendStreamImpl>* send_stream,
457 rtc::Event* done_event,
458 SendStatisticsProxy* stats_proxy,
459 ViEEncoder* vie_encoder,
460 ProcessThread* module_process_thread,
461 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700462 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700463 BitrateAllocator* bitrate_allocator,
464 SendDelayStats* send_delay_stats,
465 VieRemb* remb,
466 RtcEventLog* event_log,
467 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200468 int initial_encoder_max_bitrate,
perkj26091b12016-09-01 01:17:40 -0700469 const std::map<uint32_t, RtpState>& suspended_ssrcs)
470 : send_stream_(send_stream),
471 done_event_(done_event),
472 stats_proxy_(stats_proxy),
473 vie_encoder_(vie_encoder),
474 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700475 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700476 bitrate_allocator_(bitrate_allocator),
477 send_delay_stats_(send_delay_stats),
478 remb_(remb),
479 event_log_(event_log),
480 config_(config),
Per512ecb32016-09-23 15:52:06 +0200481 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
perkj26091b12016-09-01 01:17:40 -0700482 suspended_ssrcs_(suspended_ssrcs) {}
483
484 ~ConstructionTask() override { done_event_->Set(); }
485
486 private:
487 bool Run() override {
488 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700489 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
490 bitrate_allocator_, send_delay_stats_, remb_, vie_encoder_, event_log_,
491 config_, initial_encoder_max_bitrate_, std::move(suspended_ssrcs_)));
perkj26091b12016-09-01 01:17:40 -0700492 return true;
493 }
494
495 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
496 rtc::Event* const done_event_;
497 SendStatisticsProxy* const stats_proxy_;
498 ViEEncoder* const vie_encoder_;
499 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700500 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700501 BitrateAllocator* const bitrate_allocator_;
502 SendDelayStats* const send_delay_stats_;
503 VieRemb* const remb_;
504 RtcEventLog* const event_log_;
505 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200506 int initial_encoder_max_bitrate_;
perkj26091b12016-09-01 01:17:40 -0700507 std::map<uint32_t, RtpState> suspended_ssrcs_;
508};
509
510class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
511 public:
512 DestructAndGetRtpStateTask(VideoSendStream::RtpStateMap* state_map,
513 std::unique_ptr<VideoSendStreamImpl> send_stream,
514 rtc::Event* done_event)
515 : state_map_(state_map),
516 send_stream_(std::move(send_stream)),
517 done_event_(done_event) {}
518
519 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
520
521 private:
522 bool Run() override {
523 send_stream_->Stop();
524 *state_map_ = send_stream_->GetRtpStates();
525 send_stream_.reset();
526 done_event_->Set();
527 return true;
528 }
529
530 VideoSendStream::RtpStateMap* state_map_;
531 std::unique_ptr<VideoSendStreamImpl> send_stream_;
532 rtc::Event* done_event_;
533};
534
535// CheckEncoderActivityTask is used for tracking when the encoder last produced
536// and encoded video frame. If the encoder has not produced anything the last
537// kEncoderTimeOutMs we also want to stop sending padding.
538class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
539 public:
540 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700541 explicit CheckEncoderActivityTask(
542 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
543 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700544
545 void Stop() {
546 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700547 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700548 }
549
550 void UpdateEncoderActivity() {
551 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
552 // whatever thread the real encoder implementation run on. In the case of
553 // hardware encoders, there might be several encoders
554 // running in parallel on different threads.
555 rtc::AtomicOps::ReleaseStore(&activity_, 1);
556 }
557
558 private:
559 bool Run() override {
560 RTC_CHECK(task_checker_.CalledSequentially());
561 if (!send_stream_)
562 return true;
563 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
564 if (!timed_out_) {
565 send_stream_->SignalEncoderTimedOut();
566 }
567 timed_out_ = true;
568 } else if (timed_out_) {
569 send_stream_->SignalEncoderActive();
570 timed_out_ = false;
571 }
572 rtc::AtomicOps::ReleaseStore(&activity_, 0);
573
574 rtc::TaskQueue::Current()->PostDelayedTask(
575 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
576 // Return false to prevent this task from being deleted. Ownership has been
577 // transferred to the task queue when PostDelayedTask was called.
578 return false;
579 }
580 volatile int activity_;
581
582 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700583 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700584 bool timed_out_;
585};
586
Per512ecb32016-09-23 15:52:06 +0200587class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700588 public:
perkj8ff860a2016-10-03 00:30:04 -0700589 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200590 std::vector<VideoStream> streams,
591 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700592 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200593 streams_(std::move(streams)),
594 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700595
596 private:
597 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700598 if (send_stream_)
599 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
600 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700601 return true;
602 }
603
perkj8ff860a2016-10-03 00:30:04 -0700604 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200605 std::vector<VideoStream> streams_;
606 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700607};
608
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000609VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200610 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200611 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700612 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200613 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700614 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800615 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700616 SendDelayStats* send_delay_stats,
mflodman86aabb22016-03-11 15:44:32 +0100617 VieRemb* remb,
tereliusadafe0b2016-05-26 01:58:40 -0700618 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700619 VideoSendStream::Config config,
620 VideoEncoderConfig encoder_config,
Peter Boström45553ae2015-05-08 13:54:38 +0200621 const std::map<uint32_t, RtpState>& suspended_ssrcs)
perkj26091b12016-09-01 01:17:40 -0700622 : worker_queue_(worker_queue),
623 thread_sync_event_(false /* manual_reset */, false),
624 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800625 config,
626 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800627 config_(std::move(config)),
628 content_type_(encoder_config.content_type) {
perkj803d97f2016-11-01 11:45:46 -0700629 vie_encoder_.reset(new ViEEncoder(
630 num_cpu_cores, &stats_proxy_, config_.encoder_settings,
631 config_.pre_encode_callback, config_.post_encode_callback));
perkj26091b12016-09-01 01:17:40 -0700632 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
633 &send_stream_, &thread_sync_event_, &stats_proxy_, vie_encoder_.get(),
nisseb8f9a322017-03-27 05:36:15 -0700634 module_process_thread, call_stats, transport, bitrate_allocator,
635 send_delay_stats, remb, event_log, &config_,
perkjfa10b552016-10-02 23:45:26 -0700636 encoder_config.max_bitrate_bps, suspended_ssrcs)));
perkj26091b12016-09-01 01:17:40 -0700637
638 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
639 // |module_process_thread| must be registered and deregistered on the thread
640 // it was created on.
641 thread_sync_event_.Wait(rtc::Event::kForever);
642 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800643 // TODO(sprang): Enable this also for regular video calls if it works well.
644 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
645 // Only signal target bitrate for screenshare streams, for now.
646 vie_encoder_->SetBitrateObserver(send_stream_.get());
647 }
perkj26091b12016-09-01 01:17:40 -0700648 vie_encoder_->RegisterProcessThread(module_process_thread);
649
650 ReconfigureVideoEncoder(std::move(encoder_config));
651}
652
653VideoSendStream::~VideoSendStream() {
654 RTC_DCHECK_RUN_ON(&thread_checker_);
655 RTC_DCHECK(!send_stream_);
656}
657
658void VideoSendStream::Start() {
659 RTC_DCHECK_RUN_ON(&thread_checker_);
660 LOG(LS_INFO) << "VideoSendStream::Start";
661 VideoSendStreamImpl* send_stream = send_stream_.get();
662 worker_queue_->PostTask([this, send_stream] {
663 send_stream->Start();
664 thread_sync_event_.Set();
665 });
666
667 // It is expected that after VideoSendStream::Start has been called, incoming
668 // frames are not dropped in ViEEncoder. To ensure this, Start has to be
669 // synchronized.
670 thread_sync_event_.Wait(rtc::Event::kForever);
671}
672
673void VideoSendStream::Stop() {
674 RTC_DCHECK_RUN_ON(&thread_checker_);
675 LOG(LS_INFO) << "VideoSendStream::Stop";
676 VideoSendStreamImpl* send_stream = send_stream_.get();
677 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
678}
679
perkja49cbd32016-09-16 07:53:41 -0700680void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700681 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
682 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700683 RTC_DCHECK_RUN_ON(&thread_checker_);
perkj803d97f2016-11-01 11:45:46 -0700684 vie_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700685}
686
687void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700688 // TODO(perkj): Some test cases in VideoSendStreamTest call
689 // ReconfigureVideoEncoder from the network thread.
690 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800691 RTC_DCHECK(content_type_ == config.content_type);
asapersson5f7226f2016-11-25 04:37:00 -0800692 vie_encoder_->ConfigureEncoder(std::move(config), config_.rtp.max_packet_size,
693 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700694}
695
696VideoSendStream::Stats VideoSendStream::GetStats() {
697 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
698 // a network thread. See comment in Call::GetStats().
699 // RTC_DCHECK_RUN_ON(&thread_checker_);
700 return stats_proxy_.GetStats();
701}
702
703void VideoSendStream::SignalNetworkState(NetworkState state) {
704 RTC_DCHECK_RUN_ON(&thread_checker_);
705 VideoSendStreamImpl* send_stream = send_stream_.get();
706 worker_queue_->PostTask(
707 [send_stream, state] { send_stream->SignalNetworkState(state); });
708}
709
710VideoSendStream::RtpStateMap VideoSendStream::StopPermanentlyAndGetRtpStates() {
711 RTC_DCHECK_RUN_ON(&thread_checker_);
712 vie_encoder_->Stop();
713 vie_encoder_->DeRegisterProcessThread();
714 VideoSendStream::RtpStateMap state_map;
715 send_stream_->DeRegisterProcessThread();
716 worker_queue_->PostTask(
717 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
718 &state_map, std::move(send_stream_), &thread_sync_event_)));
719 thread_sync_event_.Wait(rtc::Event::kForever);
720 return state_map;
721}
722
nisse284542b2017-01-10 08:58:32 -0800723void VideoSendStream::SetTransportOverhead(
724 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800725 RTC_DCHECK_RUN_ON(&thread_checker_);
726 VideoSendStreamImpl* send_stream = send_stream_.get();
727 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
728 send_stream->SetTransportOverhead(transport_overhead_per_packet);
729 });
730}
731
perkj26091b12016-09-01 01:17:40 -0700732bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
733 // Called on a network thread.
734 return send_stream_->DeliverRtcp(packet, length);
735}
736
palmkviste75f2042016-09-28 06:19:48 -0700737void VideoSendStream::EnableEncodedFrameRecording(
738 const std::vector<rtc::PlatformFile>& files,
739 size_t byte_limit) {
740 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
741}
742
perkj26091b12016-09-01 01:17:40 -0700743VideoSendStreamImpl::VideoSendStreamImpl(
744 SendStatisticsProxy* stats_proxy,
745 rtc::TaskQueue* worker_queue,
746 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700747 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700748 BitrateAllocator* bitrate_allocator,
749 SendDelayStats* send_delay_stats,
750 VieRemb* remb,
751 ViEEncoder* vie_encoder,
752 RtcEventLog* event_log,
753 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200754 int initial_encoder_max_bitrate,
perkj26091b12016-09-01 01:17:40 -0700755 std::map<uint32_t, RtpState> suspended_ssrcs)
sprangc1b57a12017-02-28 08:50:47 -0800756 : send_side_bwe_with_overhead_(
757 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800758 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000759 config_(config),
perkj26091b12016-09-01 01:17:40 -0700760 suspended_ssrcs_(std::move(suspended_ssrcs)),
761 module_process_thread_(nullptr),
762 worker_queue_(worker_queue),
763 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200764 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700765 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100766 bitrate_allocator_(bitrate_allocator),
Stefan Holmer58c664c2016-02-08 14:31:30 +0100767 remb_(remb),
brandtre950cad2016-11-15 05:25:41 -0800768 flexfec_sender_(MaybeCreateFlexfecSender(*config_)),
perkj26091b12016-09-01 01:17:40 -0700769 max_padding_bitrate_(0),
770 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200771 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700772 encoder_target_rate_bps_(0),
perkj26091b12016-09-01 01:17:40 -0700773 vie_encoder_(vie_encoder),
perkj600246e2016-05-04 11:26:51 -0700774 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700775 config_->rtp.ssrcs,
776 vie_encoder),
Per69b332d2016-06-02 15:45:42 +0200777 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
nisseb8f9a322017-03-27 05:36:15 -0700778 bandwidth_observer_(transport->send_side_cc()
779 ->GetBitrateController()
780 ->CreateRtcpBandwidthObserver()),
781 rtp_rtcp_modules_(CreateRtpRtcpModules(
782 config_->send_transport,
783 &encoder_feedback_,
784 bandwidth_observer_.get(),
785 transport,
786 call_stats_->rtcp_rtt_stats(),
787 flexfec_sender_.get(),
788 stats_proxy_,
789 send_delay_stats,
790 event_log,
791 transport->send_side_cc()->GetRetransmissionRateLimiter(),
792 this,
793 config_->rtp.ssrcs.size())),
perkj26091b12016-09-01 01:17:40 -0700794 payload_router_(rtp_rtcp_modules_,
perkj8ff860a2016-10-03 00:30:04 -0700795 config_->encoder_settings.payload_type),
michaelta3328772016-11-29 09:25:03 -0800796 weak_ptr_factory_(this),
797 overhead_bytes_per_packet_(0),
798 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700799 RTC_DCHECK_RUN_ON(worker_queue_);
800 LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700801 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700802 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100803
perkj26091b12016-09-01 01:17:40 -0700804 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100805 RTC_DCHECK(call_stats_);
Stefan Holmer58c664c2016-02-08 14:31:30 +0100806 RTC_DCHECK(remb_);
nisseb8f9a322017-03-27 05:36:15 -0700807 RTC_DCHECK(transport_);
808 RTC_DCHECK(transport_->send_side_cc());
mflodman949c2f02015-10-16 02:31:11 -0700809
nisseb8f9a322017-03-27 05:36:15 -0700810 transport->send_side_cc()->EnablePeriodicAlrProbing(
sergeyu80ed35e2016-11-28 13:11:13 -0800811 config_->periodic_alr_bandwidth_probing);
812
Per83d09102016-04-15 14:59:13 +0200813 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800814
815 // We add the highest spatial layer first to ensure it'll be prioritized
816 // when sending padding, with the hope that the packet rate will be smaller,
817 // and that it's more important to protect than the lower layers.
818 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
nissefdbfdc92017-03-31 05:44:52 -0700819 transport->packet_router()->AddSendRtpModule(rtp_rtcp);
mflodman949c2f02015-10-16 02:31:11 -0700820
perkj26091b12016-09-01 01:17:40 -0700821 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
822 const std::string& extension = config_->rtp.extensions[i].uri;
823 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200824 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700825 RTC_DCHECK_GE(id, 1);
826 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100827 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
828 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
829 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
830 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000831 }
832 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000833
Peter Boström723ead82016-02-22 15:14:01 +0100834 remb_->AddRembSender(rtp_rtcp_modules_[0]);
835 rtp_rtcp_modules_[0]->SetREMBStatus(true);
mflodman@webrtc.org92c27932013-12-13 16:36:28 +0000836
Per83d09102016-04-15 14:59:13 +0200837 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000838 ConfigureSsrcs();
839
Peter Boström723ead82016-02-22 15:14:01 +0100840 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700841 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800842
Peter Boström723ead82016-02-22 15:14:01 +0100843 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700844 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
845 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800846 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100847 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700848 config_->encoder_settings.payload_type,
849 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100850 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000851
perkj26091b12016-09-01 01:17:40 -0700852 RTC_DCHECK(config_->encoder_settings.encoder);
853 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
854 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000855
perkj26091b12016-09-01 01:17:40 -0700856 vie_encoder_->SetStartBitrate(bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700857
858 // Only request rotation at the source when we positively know that the remote
859 // side doesn't support the rotation extension. This allows us to prepare the
860 // encoder in the expectation that rotation is supported - which is the common
861 // case.
862 bool rotation_applied =
863 std::find_if(config_->rtp.extensions.begin(),
864 config_->rtp.extensions.end(),
865 [](const RtpExtension& extension) {
866 return extension.uri == RtpExtension::kVideoRotationUri;
867 }) == config_->rtp.extensions.end();
868
869 vie_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000870}
871
perkj26091b12016-09-01 01:17:40 -0700872void VideoSendStreamImpl::RegisterProcessThread(
873 ProcessThread* module_process_thread) {
874 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
875 RTC_DCHECK(!module_process_thread_);
876 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100877
perkj26091b12016-09-01 01:17:40 -0700878 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800879 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700880}
Peter Boströmca835252016-02-11 15:59:46 +0100881
perkj26091b12016-09-01 01:17:40 -0700882void VideoSendStreamImpl::DeRegisterProcessThread() {
883 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
884 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
885 module_process_thread_->DeRegisterModule(rtp_rtcp);
886}
Peter Boströma4c76882016-03-03 16:29:02 +0100887
perkj26091b12016-09-01 01:17:40 -0700888VideoSendStreamImpl::~VideoSendStreamImpl() {
889 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800890 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700891 << "VideoSendStreamImpl::Stop not called";
892 LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000893
Peter Boström723ead82016-02-22 15:14:01 +0100894 rtp_rtcp_modules_[0]->SetREMBStatus(false);
895 remb_->RemoveRembSender(rtp_rtcp_modules_[0]);
mflodman949c2f02015-10-16 02:31:11 -0700896
Per83d09102016-04-15 14:59:13 +0200897 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700898 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200899 delete rtp_rtcp;
900 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000901}
902
perkj26091b12016-09-01 01:17:40 -0700903bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
904 // Runs on a network thread.
905 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700906 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
907 rtp_rtcp->IncomingRtcpPacket(packet, length);
908 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000909}
910
perkj26091b12016-09-01 01:17:40 -0700911void VideoSendStreamImpl::Start() {
912 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700913 LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800914 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100915 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200916 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800917 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700918
919 bitrate_allocator_->AddObserver(
920 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
921 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
922
923 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700924 {
perkj26091b12016-09-01 01:17:40 -0700925 rtc::CritScope lock(&encoder_activity_crit_sect_);
926 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700927 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700928 worker_queue_->PostDelayedTask(
929 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
930 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700931 }
perkj26091b12016-09-01 01:17:40 -0700932
933 vie_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000934}
935
perkj26091b12016-09-01 01:17:40 -0700936void VideoSendStreamImpl::Stop() {
937 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700938 LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800939 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100940 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200941 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800942 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700943 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700944 {
perkj26091b12016-09-01 01:17:40 -0700945 rtc::CritScope lock(&encoder_activity_crit_sect_);
946 check_encoder_activity_task_->Stop();
947 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700948 }
perkj26091b12016-09-01 01:17:40 -0700949 vie_encoder_->OnBitrateUpdated(0, 0, 0);
950 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000951}
952
perkj26091b12016-09-01 01:17:40 -0700953void VideoSendStreamImpl::SignalEncoderTimedOut() {
954 RTC_DCHECK_RUN_ON(worker_queue_);
955 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
956 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
957 // if a camera stops producing frames.
958 if (encoder_target_rate_bps_ > 0) {
959 LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
960 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100961 }
962}
963
sprang1a646ee2016-12-01 06:34:11 -0800964void VideoSendStreamImpl::OnBitrateAllocationUpdated(
965 const BitrateAllocation& allocation) {
966 payload_router_.OnBitrateAllocationUpdated(allocation);
967}
968
perkj26091b12016-09-01 01:17:40 -0700969void VideoSendStreamImpl::SignalEncoderActive() {
970 RTC_DCHECK_RUN_ON(worker_queue_);
971 LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
972 bitrate_allocator_->AddObserver(
973 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
974 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
975}
976
Per512ecb32016-09-23 15:52:06 +0200977void VideoSendStreamImpl::OnEncoderConfigurationChanged(
978 std::vector<VideoStream> streams,
979 int min_transmit_bitrate_bps) {
980 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200981 worker_queue_->PostTask(
982 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700983 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200984 return;
985 }
986 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
987 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
988 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700989 RTC_DCHECK_RUN_ON(worker_queue_);
990
991 const int kEncoderMinBitrateBps = 30000;
992 encoder_min_bitrate_bps_ =
Per512ecb32016-09-23 15:52:06 +0200993 std::max(streams[0].min_bitrate_bps, kEncoderMinBitrateBps);
perkj26091b12016-09-01 01:17:40 -0700994 encoder_max_bitrate_bps_ = 0;
Per512ecb32016-09-23 15:52:06 +0200995 for (const auto& stream : streams)
perkj26091b12016-09-01 01:17:40 -0700996 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Per512ecb32016-09-23 15:52:06 +0200997 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
998 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -0700999
1000 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +02001001 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -07001002 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001003 }
perkj26091b12016-09-01 01:17:40 -07001004
1005 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +02001006 streams.back().temporal_layer_thresholds_bps.size() + 1;
perkj26091b12016-09-01 01:17:40 -07001007 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +02001008 streams[0].width, streams[0].height, number_of_temporal_layers,
1009 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -07001010
sprang1a646ee2016-12-01 06:34:11 -08001011 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -07001012 // The send stream is started already. Update the allocator with new bitrate
1013 // limits.
1014 bitrate_allocator_->AddObserver(
1015 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
1016 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
1017 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001018}
1019
perkj26091b12016-09-01 01:17:40 -07001020EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001021 const EncodedImage& encoded_image,
1022 const CodecSpecificInfo* codec_specific_info,
1023 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -07001024 // Encoded is called on whatever thread the real encoder implementation run
1025 // on. In the case of hardware encoders, there might be several encoders
1026 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -08001027 size_t simulcast_idx = 0;
1028 if (codec_specific_info->codecType == kVideoCodecVP8) {
1029 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
1030 }
perkj26091b12016-09-01 01:17:40 -07001031 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -08001032 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
1033 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
1034 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -07001035 }
perkj26091b12016-09-01 01:17:40 -07001036 {
1037 rtc::CritScope lock(&encoder_activity_crit_sect_);
1038 if (check_encoder_activity_task_)
1039 check_encoder_activity_task_->UpdateEncoderActivity();
1040 }
sergeyu37ad3372016-06-14 15:29:37 -07001041
Per69b332d2016-06-02 15:45:42 +02001042 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001043 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001044 encoded_image, codec_specific_info, fragmentation);
1045
palmkviste75f2042016-09-28 06:19:48 -07001046 RTC_DCHECK(codec_specific_info);
1047
1048 int layer = codec_specific_info->codecType == kVideoCodecVP8
1049 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1050 : 0;
1051 {
1052 rtc::CritScope lock(&ivf_writers_crit_);
1053 if (file_writers_[layer].get()) {
1054 bool ok = file_writers_[layer]->WriteFrame(
1055 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001056 RTC_DCHECK(ok);
1057 }
1058 }
1059
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001060 return result;
perkjbc75d972016-05-02 06:31:25 -07001061}
1062
perkj26091b12016-09-01 01:17:40 -07001063void VideoSendStreamImpl::ConfigureProtection() {
1064 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001065
brandtre950cad2016-11-15 05:25:41 -08001066 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1067 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1068
1069 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001070 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1071 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001072 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001073
1074 // Shorthands.
1075 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001076 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001077 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1078 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1079
brandtre950cad2016-11-15 05:25:41 -08001080 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1081 if (flexfec_enabled) {
1082 // We can safely disable RED here, because if the remote supports FlexFEC,
1083 // we know that it has a receiver without the RED/RTX workaround.
1084 // See http://crbug.com/webrtc/6650 for more information.
1085 if (IsRedEnabled()) {
1086 LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
1087 DisableRed();
1088 }
1089 if (IsUlpfecEnabled()) {
1090 LOG(LS_INFO)
1091 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1092 DisableUlpfec();
1093 }
1094 }
1095
Per83d09102016-04-15 14:59:13 +02001096 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001097 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1098 // is a waste of bandwidth since FEC packets still have to be transmitted.
1099 // Note that this is not the case with FlexFEC.
1100 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001101 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001102 config_->encoder_settings.payload_name)) {
brandtre6f98c72016-11-11 03:28:30 -08001103 LOG(LS_WARNING)
1104 << "Transmitting payload type without picture ID using "
1105 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1106 "also have to be retransmitted. Disabling ULPFEC.";
1107 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001108 }
1109
brandtre6f98c72016-11-11 03:28:30 -08001110 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001111 //
brandtre6f98c72016-11-11 03:28:30 -08001112 // Due to how old receivers work, we need to always send RED if it has been
1113 // negotiated. This is a remnant of an old RED/RTX workaround, see
1114 // https://codereview.webrtc.org/2469093003.
1115 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1116 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1117 // no point in using RED without ULPFEC.
1118 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001119 RTC_DCHECK_GE(red_payload_type, 0);
1120 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001121 }
brandtre6f98c72016-11-11 03:28:30 -08001122 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001123 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1124 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001125 if (!IsRedEnabled()) {
1126 LOG(LS_WARNING)
1127 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1128 DisableUlpfec();
1129 }
Per83d09102016-04-15 14:59:13 +02001130 }
1131
1132 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1133 // Set NACK.
1134 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001135 true,
Per83d09102016-04-15 14:59:13 +02001136 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001137 // Set RED/ULPFEC information.
Per83d09102016-04-15 14:59:13 +02001138 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrf1bb4762016-11-07 03:05:06 -08001139 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001140 }
1141 }
1142
brandtre950cad2016-11-15 05:25:41 -08001143 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1144 // so enable that logic if either of those FEC schemes are enabled.
1145 protection_bitrate_calculator_.SetProtectionMethod(
1146 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001147}
1148
perkj26091b12016-09-01 01:17:40 -07001149void VideoSendStreamImpl::ConfigureSsrcs() {
1150 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001151 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001152 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1153 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001154 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1155 rtp_rtcp->SetSSRC(ssrc);
1156
1157 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001158 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001159 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001160 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001161 }
1162
Peter Boström723ead82016-02-22 15:14:01 +01001163 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001164 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001165 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001166
Peter Boström723ead82016-02-22 15:14:01 +01001167 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001168 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1169 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1170 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001171 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1172 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001173 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001174 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001175 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001176 }
1177
Peter Boström723ead82016-02-22 15:14:01 +01001178 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001179 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001180 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001181 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1182 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001183 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1184 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001185 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1186 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001187 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001188 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1189 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001190 }
Stefan Holmer10880012016-02-03 13:29:59 +01001191 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001192}
1193
perkj26091b12016-09-01 01:17:40 -07001194std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1195 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001196 std::map<uint32_t, RtpState> rtp_states;
perkj26091b12016-09-01 01:17:40 -07001197 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1198 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001199 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1200 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001201 }
1202
perkj26091b12016-09-01 01:17:40 -07001203 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1204 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001205 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001206 }
1207
1208 return rtp_states;
1209}
1210
perkj26091b12016-09-01 01:17:40 -07001211void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1212 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001213 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001214 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001215 : RtcpMode::kOff);
1216 }
1217}
1218
perkj26091b12016-09-01 01:17:40 -07001219uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1220 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001221 int64_t rtt,
1222 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001223 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001224 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001225 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001226
michaelt192132e2017-01-26 09:05:27 -08001227 // Substract overhead from bitrate.
1228 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001229 uint32_t payload_bitrate_bps = bitrate_bps;
1230 if (send_side_bwe_with_overhead_) {
1231 payload_bitrate_bps -= CalculateOverheadRateBps(
1232 CalculatePacketRate(bitrate_bps,
1233 config_->rtp.max_packet_size +
1234 transport_overhead_bytes_per_packet_),
1235 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1236 bitrate_bps);
1237 }
michaelta3328772016-11-29 09:25:03 -08001238
Per69b332d2016-06-02 15:45:42 +02001239 // Get the encoder target rate. It is the estimated network rate -
1240 // protection overhead.
perkj26091b12016-09-01 01:17:40 -07001241 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001242 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1243 rtt);
1244
elad.alon0fe12162017-01-31 05:48:37 -08001245 uint32_t encoder_overhead_rate_bps =
1246 send_side_bwe_with_overhead_
1247 ? CalculateOverheadRateBps(
1248 CalculatePacketRate(encoder_target_rate_bps_,
1249 config_->rtp.max_packet_size +
1250 transport_overhead_bytes_per_packet_ -
1251 overhead_bytes_per_packet_),
1252 overhead_bytes_per_packet_ +
1253 transport_overhead_bytes_per_packet_,
1254 bitrate_bps - encoder_target_rate_bps_)
1255 : 0;
michaelt192132e2017-01-26 09:05:27 -08001256
1257 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1258 // protection_bitrate includes overhead.
1259 uint32_t protection_bitrate =
1260 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001261
perkj26091b12016-09-01 01:17:40 -07001262 encoder_target_rate_bps_ =
1263 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
1264 vie_encoder_->OnBitrateUpdated(encoder_target_rate_bps_, fraction_loss, rtt);
1265 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001266 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001267}
1268
palmkviste75f2042016-09-28 06:19:48 -07001269void VideoSendStreamImpl::EnableEncodedFrameRecording(
1270 const std::vector<rtc::PlatformFile>& files,
1271 size_t byte_limit) {
1272 {
1273 rtc::CritScope lock(&ivf_writers_crit_);
1274 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1275 if (i < files.size()) {
1276 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1277 } else {
1278 file_writers_[i].reset();
1279 }
1280 }
1281 }
1282
1283 if (!files.empty()) {
1284 // Make a keyframe appear as early as possible in the logs, to give actually
1285 // decodable output.
1286 vie_encoder_->SendKeyFrame();
1287 }
1288}
1289
perkj26091b12016-09-01 01:17:40 -07001290int VideoSendStreamImpl::ProtectionRequest(
1291 const FecProtectionParams* delta_params,
1292 const FecProtectionParams* key_params,
1293 uint32_t* sent_video_rate_bps,
1294 uint32_t* sent_nack_rate_bps,
1295 uint32_t* sent_fec_rate_bps) {
1296 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001297 *sent_video_rate_bps = 0;
1298 *sent_nack_rate_bps = 0;
1299 *sent_fec_rate_bps = 0;
1300 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1301 uint32_t not_used = 0;
1302 uint32_t module_video_rate = 0;
1303 uint32_t module_fec_rate = 0;
1304 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001305 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001306 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1307 &module_nack_rate);
1308 *sent_video_rate_bps += module_video_rate;
1309 *sent_nack_rate_bps += module_nack_rate;
1310 *sent_fec_rate_bps += module_fec_rate;
1311 }
1312 return 0;
1313}
1314
michaelta3328772016-11-29 09:25:03 -08001315void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1316 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1317 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1318}
1319
michaelt79e05882016-11-08 02:50:09 -08001320void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001321 size_t transport_overhead_bytes_per_packet) {
1322 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
1323 LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
1324 return;
1325 }
1326
michaelta3328772016-11-29 09:25:03 -08001327 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001328
nisseb8f9a322017-03-27 05:36:15 -07001329 transport_->send_side_cc()->SetTransportOverhead(
1330 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001331
1332 size_t rtp_packet_size =
1333 std::min(config_->rtp.max_packet_size,
1334 kPathMTU - transport_overhead_bytes_per_packet_);
1335
michaelta3328772016-11-29 09:25:03 -08001336 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001337 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001338 }
michaelt79e05882016-11-08 02:50:09 -08001339}
1340
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001341} // namespace internal
1342} // namespace webrtc