blob: d55ad017ff6191280936c09876f35972483ba00a [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
nissecae45d02017-04-24 05:53:20 -070019#include "webrtc/call/rtp_transport_controller_send_interface.h"
tommidea489f2017-03-03 03:20:24 -080020#include "webrtc/common_types.h"
21#include "webrtc/common_video/include/video_bitrate_allocator.h"
mflodman0e7e2592015-11-12 21:02:42 -080022#include "webrtc/modules/bitrate_controller/include/bitrate_controller.h"
nisse559af382017-03-21 06:41:12 -070023#include "webrtc/modules/congestion_controller/include/send_side_congestion_controller.h"
sprang89c4a7e2017-06-30 13:27:40 -070024#include "webrtc/modules/pacing/alr_detector.h"
Henrik Kjellander0b9e29c2015-11-16 11:12:24 +010025#include "webrtc/modules/pacing/packet_router.h"
Peter Boström9c017252016-02-26 16:26:20 +010026#include "webrtc/modules/rtp_rtcp/include/rtp_rtcp.h"
erikvarga27883732017-05-17 05:08:38 -070027#include "webrtc/modules/rtp_rtcp/source/rtp_sender.h"
Peter Boströme4499152016-02-05 11:13:28 +010028#include "webrtc/modules/utility/include/process_thread.h"
perkj600246e2016-05-04 11:26:51 -070029#include "webrtc/modules/video_coding/utility/ivf_file_writer.h"
Edward Lemurc20978e2017-07-06 19:44:34 +020030#include "webrtc/rtc_base/checks.h"
31#include "webrtc/rtc_base/file.h"
32#include "webrtc/rtc_base/location.h"
33#include "webrtc/rtc_base/logging.h"
34#include "webrtc/rtc_base/trace_event.h"
35#include "webrtc/rtc_base/weak_ptr.h"
michaelta3328772016-11-29 09:25:03 -080036#include "webrtc/system_wrappers/include/field_trial.h"
Peter Boström7623ce42015-12-09 12:13:30 +010037#include "webrtc/video/call_stats.h"
nisseb8f9a322017-03-27 05:36:15 -070038#include "webrtc/video/payload_router.h"
pbos@webrtc.org16e03b72013-10-28 16:32:01 +000039#include "webrtc/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000040
41namespace webrtc {
mflodman949c2f02015-10-16 02:31:11 -070042
Per83d09102016-04-15 14:59:13 +020043static const int kMinSendSidePacketHistorySize = 600;
Per83d09102016-04-15 14:59:13 +020044namespace {
45
nisse284542b2017-01-10 08:58:32 -080046// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
47const size_t kPathMTU = 1500;
48
Per83d09102016-04-15 14:59:13 +020049std::vector<RtpRtcp*> CreateRtpRtcpModules(
50 Transport* outgoing_transport,
51 RtcpIntraFrameObserver* intra_frame_callback,
52 RtcpBandwidthObserver* bandwidth_callback,
nisseb8f9a322017-03-27 05:36:15 -070053 RtpTransportControllerSendInterface* transport,
Per83d09102016-04-15 14:59:13 +020054 RtcpRttStats* rtt_stats,
brandtre950cad2016-11-15 05:25:41 -080055 FlexfecSender* flexfec_sender,
Per83d09102016-04-15 14:59:13 +020056 SendStatisticsProxy* stats_proxy,
asapersson35151f32016-05-02 23:44:01 -070057 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -070058 RtcEventLog* event_log,
sprangcd349d92016-07-13 09:11:28 -070059 RateLimiter* retransmission_rate_limiter,
michaelta3328772016-11-29 09:25:03 -080060 OverheadObserver* overhead_observer,
sprang168794c2017-07-06 04:38:06 -070061 size_t num_modules,
62 RtpKeepAliveConfig keepalive_config) {
kwibergaf476c72016-11-28 15:21:39 -080063 RTC_DCHECK_GT(num_modules, 0);
Per83d09102016-04-15 14:59:13 +020064 RtpRtcp::Configuration configuration;
Per83d09102016-04-15 14:59:13 +020065 configuration.audio = false;
66 configuration.receiver_only = false;
brandtre950cad2016-11-15 05:25:41 -080067 configuration.flexfec_sender = flexfec_sender;
Per83d09102016-04-15 14:59:13 +020068 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;
sprang168794c2017-07-06 04:38:06 -070085 configuration.keepalive_config = keepalive_config;
Per83d09102016-04-15 14:59:13 +020086 std::vector<RtpRtcp*> modules;
87 for (size_t i = 0; i < num_modules; ++i) {
88 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
89 rtp_rtcp->SetSendingStatus(false);
90 rtp_rtcp->SetSendingMediaStatus(false);
91 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
92 modules.push_back(rtp_rtcp);
93 }
94 return modules;
95}
96
brandtre950cad2016-11-15 05:25:41 -080097// TODO(brandtr): Update this function when we support multistream protection.
98std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
brandtr48d21a22017-05-30 02:32:12 -070099 const VideoSendStream::Config& config,
100 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
brandtr3d200bd2017-01-16 06:59:19 -0800101 if (config.rtp.flexfec.payload_type < 0) {
brandtre950cad2016-11-15 05:25:41 -0800102 return nullptr;
103 }
brandtr3d200bd2017-01-16 06:59:19 -0800104 RTC_DCHECK_GE(config.rtp.flexfec.payload_type, 0);
105 RTC_DCHECK_LE(config.rtp.flexfec.payload_type, 127);
106 if (config.rtp.flexfec.ssrc == 0) {
brandtre950cad2016-11-15 05:25:41 -0800107 LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
108 "Therefore disabling FlexFEC.";
109 return nullptr;
110 }
111 if (config.rtp.flexfec.protected_media_ssrcs.empty()) {
112 LOG(LS_WARNING) << "FlexFEC is enabled, but no protected media SSRC given. "
113 "Therefore disabling FlexFEC.";
114 return nullptr;
115 }
116
117 if (config.rtp.ssrcs.size() > 1) {
118 LOG(LS_WARNING) << "Both FlexFEC and simulcast are enabled. This "
119 "combination is however not supported by our current "
120 "FlexFEC implementation. Therefore disabling FlexFEC.";
121 return nullptr;
122 }
123
124 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) {
125 LOG(LS_WARNING)
126 << "The supplied FlexfecConfig contained multiple protected "
127 "media streams, but our implementation currently only "
128 "supports protecting a single media stream. "
129 "To avoid confusion, disabling FlexFEC completely.";
130 return nullptr;
131 }
132
brandtr48d21a22017-05-30 02:32:12 -0700133 const RtpState* rtp_state = nullptr;
134 auto it = suspended_ssrcs.find(config.rtp.flexfec.ssrc);
135 if (it != suspended_ssrcs.end()) {
136 rtp_state = &it->second;
137 }
138
brandtre950cad2016-11-15 05:25:41 -0800139 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
140 return std::unique_ptr<FlexfecSender>(new FlexfecSender(
brandtr3d200bd2017-01-16 06:59:19 -0800141 config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc,
brandtre950cad2016-11-15 05:25:41 -0800142 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions,
brandtr48d21a22017-05-30 02:32:12 -0700143 RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock()));
brandtre950cad2016-11-15 05:25:41 -0800144}
145
Per83d09102016-04-15 14:59:13 +0200146} // namespace
147
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000148std::string
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000149VideoSendStream::Config::EncoderSettings::ToString() const {
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000150 std::stringstream ss;
151 ss << "{payload_name: " << payload_name;
152 ss << ", payload_type: " << payload_type;
Peter Boström74f6e9e2016-04-04 17:56:10 +0200153 ss << ", encoder: " << (encoder ? "(VideoEncoder)" : "nullptr");
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000154 ss << '}';
155 return ss.str();
156}
157
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000158std::string VideoSendStream::Config::Rtp::Rtx::ToString()
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000159 const {
160 std::stringstream ss;
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000161 ss << "{ssrcs: [";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000162 for (size_t i = 0; i < ssrcs.size(); ++i) {
163 ss << ssrcs[i];
164 if (i != ssrcs.size() - 1)
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000165 ss << ", ";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000166 }
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000167 ss << ']';
andrew@webrtc.org8f27fcc2015-01-09 20:22:46 +0000168
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000169 ss << ", payload_type: " << payload_type;
170 ss << '}';
171 return ss.str();
172}
173
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000174std::string VideoSendStream::Config::Rtp::ToString() const {
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000175 std::stringstream ss;
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000176 ss << "{ssrcs: [";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000177 for (size_t i = 0; i < ssrcs.size(); ++i) {
178 ss << ssrcs[i];
179 if (i != ssrcs.size() - 1)
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000180 ss << ", ";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000181 }
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000182 ss << ']';
Taylor Brandstetter5f0b83b2016-03-18 15:02:07 -0700183 ss << ", rtcp_mode: "
184 << (rtcp_mode == RtcpMode::kCompound ? "RtcpMode::kCompound"
185 : "RtcpMode::kReducedSize");
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000186 ss << ", max_packet_size: " << max_packet_size;
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000187 ss << ", extensions: [";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000188 for (size_t i = 0; i < extensions.size(); ++i) {
189 ss << extensions[i].ToString();
190 if (i != extensions.size() - 1)
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000191 ss << ", ";
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000192 }
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000193 ss << ']';
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000194
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000195 ss << ", nack: {rtp_history_ms: " << nack.rtp_history_ms << '}';
brandtrb5f2c3f2016-10-04 23:28:39 -0700196 ss << ", ulpfec: " << ulpfec.ToString();
brandtr3d200bd2017-01-16 06:59:19 -0800197
198 ss << ", flexfec: {payload_type: " << flexfec.payload_type;
199 ss << ", ssrc: " << flexfec.ssrc;
200 ss << ", protected_media_ssrcs: [";
201 for (size_t i = 0; i < flexfec.protected_media_ssrcs.size(); ++i) {
202 ss << flexfec.protected_media_ssrcs[i];
203 if (i != flexfec.protected_media_ssrcs.size() - 1)
204 ss << ", ";
205 }
brandtr3b941be2017-03-17 07:02:46 -0700206 ss << "]}";
brandtr3d200bd2017-01-16 06:59:19 -0800207
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000208 ss << ", rtx: " << rtx.ToString();
209 ss << ", c_name: " << c_name;
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000210 ss << '}';
211 return ss.str();
212}
213
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000214std::string VideoSendStream::Config::ToString() const {
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000215 std::stringstream ss;
216 ss << "{encoder_settings: " << encoder_settings.ToString();
217 ss << ", rtp: " << rtp.ToString();
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000218 ss << ", pre_encode_callback: "
nisse76bc8e82017-02-07 09:37:41 -0800219 << (pre_encode_callback ? "(VideoSinkInterface)" : "nullptr");
Peter Boström74f6e9e2016-04-04 17:56:10 +0200220 ss << ", post_encode_callback: "
221 << (post_encode_callback ? "(EncodedFrameObserver)" : "nullptr");
pbos@webrtc.org32e85282015-01-15 10:09:39 +0000222 ss << ", render_delay_ms: " << render_delay_ms;
223 ss << ", target_delay_ms: " << target_delay_ms;
224 ss << ", suspend_below_min_bitrate: " << (suspend_below_min_bitrate ? "on"
225 : "off");
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +0000226 ss << '}';
227 return ss.str();
228}
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000229
asapersson2e5cfcd2016-08-11 08:41:18 -0700230std::string VideoSendStream::Stats::ToString(int64_t time_ms) const {
231 std::stringstream ss;
232 ss << "VideoSendStream stats: " << time_ms << ", {";
233 ss << "input_fps: " << input_frame_rate << ", ";
234 ss << "encode_fps: " << encode_frame_rate << ", ";
235 ss << "encode_ms: " << avg_encode_time_ms << ", ";
236 ss << "encode_usage_perc: " << encode_usage_percent << ", ";
237 ss << "target_bps: " << target_media_bitrate_bps << ", ";
238 ss << "media_bps: " << media_bitrate_bps << ", ";
Pera48ddb72016-09-29 11:48:50 +0200239 ss << "preferred_media_bitrate_bps: " << preferred_media_bitrate_bps << ", ";
asapersson2e5cfcd2016-08-11 08:41:18 -0700240 ss << "suspended: " << (suspended ? "true" : "false") << ", ";
241 ss << "bw_adapted: " << (bw_limited_resolution ? "true" : "false");
242 ss << '}';
243 for (const auto& substream : substreams) {
asaperssona6a699a2016-11-25 03:52:46 -0800244 if (!substream.second.is_rtx && !substream.second.is_flexfec) {
asapersson2e5cfcd2016-08-11 08:41:18 -0700245 ss << " {ssrc: " << substream.first << ", ";
246 ss << substream.second.ToString();
247 ss << '}';
248 }
249 }
250 return ss.str();
251}
252
253std::string VideoSendStream::StreamStats::ToString() const {
254 std::stringstream ss;
255 ss << "width: " << width << ", ";
256 ss << "height: " << height << ", ";
257 ss << "key: " << frame_counts.key_frames << ", ";
258 ss << "delta: " << frame_counts.delta_frames << ", ";
259 ss << "total_bps: " << total_bitrate_bps << ", ";
260 ss << "retransmit_bps: " << retransmit_bitrate_bps << ", ";
261 ss << "avg_delay_ms: " << avg_delay_ms << ", ";
262 ss << "max_delay_ms: " << max_delay_ms << ", ";
263 ss << "cum_loss: " << rtcp_stats.cumulative_lost << ", ";
264 ss << "max_ext_seq: " << rtcp_stats.extended_max_sequence_number << ", ";
265 ss << "nack: " << rtcp_packet_type_counts.nack_packets << ", ";
266 ss << "fir: " << rtcp_packet_type_counts.fir_packets << ", ";
267 ss << "pli: " << rtcp_packet_type_counts.pli_packets;
268 return ss.str();
269}
270
Peter Boströme4499152016-02-05 11:13:28 +0100271namespace {
272
Peter Boström39593972016-02-15 11:27:15 +0100273bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
deadbeefc964d0b2017-04-03 10:03:35 -0700274 rtc::Optional<VideoCodecType> codecType =
275 PayloadNameToCodecType(payload_name);
276 if (codecType &&
277 (*codecType == kVideoCodecVP8 || *codecType == kVideoCodecVP9)) {
perkj26091b12016-09-01 01:17:40 -0700278 return true;
deadbeefc964d0b2017-04-03 10:03:35 -0700279 }
280 RTC_DCHECK((codecType && *codecType == kVideoCodecH264) ||
281 payload_name == "FAKE")
perkj26091b12016-09-01 01:17:40 -0700282 << "unknown payload_name " << payload_name;
Peter Boström39593972016-02-15 11:27:15 +0100283 return false;
284}
285
Per512ecb32016-09-23 15:52:06 +0200286int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
287 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700288 bool pad_to_min_bitrate) {
289 int pad_up_to_bitrate_bps = 0;
290 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200291 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700292 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200293 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700294 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200295 for (size_t i = 0; i < streams.size() - 1; ++i)
296 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700297 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200298 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700299 }
300
301 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200302 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700303
304 return pad_up_to_bitrate_bps;
305}
306
michaelt192132e2017-01-26 09:05:27 -0800307uint32_t CalculateOverheadRateBps(int packets_per_second,
308 size_t overhead_bytes_per_packet,
309 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800310 uint32_t overhead_bps =
311 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
312 return std::min(overhead_bps, max_overhead_bps);
313}
314
315int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
316 size_t packet_size_bits = 8 * packet_size_bytes;
317 // Ceil for int value of bitrate_bps / packet_size_bits.
318 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
319 packet_size_bits);
320}
321
Peter Boströme4499152016-02-05 11:13:28 +0100322} // namespace
323
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000324namespace internal {
perkj26091b12016-09-01 01:17:40 -0700325
326// VideoSendStreamImpl implements internal::VideoSendStream.
327// It is created and destroyed on |worker_queue|. The intent is to decrease the
328// need for locking and to ensure methods are called in sequence.
329// Public methods except |DeliverRtcp| must be called on |worker_queue|.
330// DeliverRtcp is called on the libjingle worker thread or a network thread.
331// An encoder may deliver frames through the EncodedImageCallback on an
332// arbitrary thread.
333class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800334 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700335 public webrtc::VCMProtectionCallback,
mflodmancc3d4422017-08-03 08:27:51 -0700336 public VideoStreamEncoder::EncoderSink,
sprang1a646ee2016-12-01 06:34:11 -0800337 public VideoBitrateAllocationObserver {
perkj26091b12016-09-01 01:17:40 -0700338 public:
339 VideoSendStreamImpl(SendStatisticsProxy* stats_proxy,
340 rtc::TaskQueue* worker_queue,
341 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700342 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700343 BitrateAllocator* bitrate_allocator,
344 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700345 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700346 RtcEventLog* event_log,
347 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200348 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700349 std::map<uint32_t, RtpState> suspended_ssrcs,
sprange5c4a812017-07-11 03:44:17 -0700350 VideoEncoderConfig::ContentType content_type,
351 const RtpKeepAliveConfig& keepalive_config);
perkj26091b12016-09-01 01:17:40 -0700352 ~VideoSendStreamImpl() override;
353
354 // RegisterProcessThread register |module_process_thread| with those objects
355 // that use it. Registration has to happen on the thread were
356 // |module_process_thread| was created (libjingle's worker thread).
357 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
358 // maybe |worker_queue|.
359 void RegisterProcessThread(ProcessThread* module_process_thread);
360 void DeRegisterProcessThread();
361
362 void SignalNetworkState(NetworkState state);
363 bool DeliverRtcp(const uint8_t* packet, size_t length);
364 void Start();
365 void Stop();
366
perkj26091b12016-09-01 01:17:40 -0700367 VideoSendStream::RtpStateMap GetRtpStates() const;
368
palmkviste75f2042016-09-28 06:19:48 -0700369 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
370 size_t byte_limit);
371
nisse284542b2017-01-10 08:58:32 -0800372 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800373
perkj26091b12016-09-01 01:17:40 -0700374 private:
375 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200376 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700377
378 // Implements BitrateAllocatorObserver.
379 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
380 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800381 int64_t rtt,
382 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700383
384 // Implements webrtc::VCMProtectionCallback.
385 int ProtectionRequest(const FecProtectionParams* delta_params,
386 const FecProtectionParams* key_params,
387 uint32_t* sent_video_rate_bps,
388 uint32_t* sent_nack_rate_bps,
389 uint32_t* sent_fec_rate_bps) override;
390
michaelta3328772016-11-29 09:25:03 -0800391 // Implements OverheadObserver.
392 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
393
Per512ecb32016-09-23 15:52:06 +0200394 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
395 int min_transmit_bitrate_bps) override;
396
perkj26091b12016-09-01 01:17:40 -0700397 // Implements EncodedImageCallback. The implementation routes encoded frames
398 // to the |payload_router_| and |config.pre_encode_callback| if set.
399 // Called on an arbitrary encoder callback thread.
400 EncodedImageCallback::Result OnEncodedImage(
401 const EncodedImage& encoded_image,
402 const CodecSpecificInfo* codec_specific_info,
403 const RTPFragmentationHeader* fragmentation) override;
404
sprang1a646ee2016-12-01 06:34:11 -0800405 // Implements VideoBitrateAllocationObserver.
406 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
407
perkj26091b12016-09-01 01:17:40 -0700408 void ConfigureProtection();
409 void ConfigureSsrcs();
410 void SignalEncoderTimedOut();
411 void SignalEncoderActive();
412
elad.alon0fe12162017-01-31 05:48:37 -0800413 const bool send_side_bwe_with_overhead_;
414
perkj26091b12016-09-01 01:17:40 -0700415 SendStatisticsProxy* const stats_proxy_;
416 const VideoSendStream::Config* const config_;
417 std::map<uint32_t, RtpState> suspended_ssrcs_;
418
419 ProcessThread* module_process_thread_;
420 rtc::ThreadChecker module_process_thread_checker_;
421 rtc::TaskQueue* const worker_queue_;
422
423 rtc::CriticalSection encoder_activity_crit_sect_;
424 CheckEncoderActivityTask* check_encoder_activity_task_
425 GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200426
perkj26091b12016-09-01 01:17:40 -0700427 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700428 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700429 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700430
brandtr3b941be2017-03-17 07:02:46 -0700431 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800432 std::unique_ptr<FlexfecSender> flexfec_sender_;
433
palmkviste75f2042016-09-28 06:19:48 -0700434 rtc::CriticalSection ivf_writers_crit_;
435 std::unique_ptr<IvfFileWriter> file_writers_[kMaxSimulcastStreams] GUARDED_BY(
436 ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700437
438 int max_padding_bitrate_;
439 int encoder_min_bitrate_bps_;
440 uint32_t encoder_max_bitrate_bps_;
441 uint32_t encoder_target_rate_bps_;
442
mflodmancc3d4422017-08-03 08:27:51 -0700443 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700444 EncoderRtcpFeedback encoder_feedback_;
perkj26091b12016-09-01 01:17:40 -0700445 ProtectionBitrateCalculator protection_bitrate_calculator_;
446
447 const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
448 // RtpRtcp modules, declared here as they use other members on construction.
449 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
450 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700451
452 // |weak_ptr_| to our self. This is used since we can not call
453 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
454 // an existing WeakPtr.
455 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
456 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
457 // invalidated before any other members are destroyed.
458 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800459
460 rtc::CriticalSection overhead_bytes_per_packet_crit_;
461 size_t overhead_bytes_per_packet_ GUARDED_BY(overhead_bytes_per_packet_crit_);
462 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700463};
464
465// TODO(tommi): See if there's a more elegant way to create a task that creates
466// an object on the correct task queue.
467class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
468 public:
469 ConstructionTask(std::unique_ptr<VideoSendStreamImpl>* send_stream,
470 rtc::Event* done_event,
471 SendStatisticsProxy* stats_proxy,
mflodmancc3d4422017-08-03 08:27:51 -0700472 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700473 ProcessThread* module_process_thread,
474 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700475 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700476 BitrateAllocator* bitrate_allocator,
477 SendDelayStats* send_delay_stats,
perkj26091b12016-09-01 01:17:40 -0700478 RtcEventLog* event_log,
479 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200480 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700481 const std::map<uint32_t, RtpState>& suspended_ssrcs,
sprange5c4a812017-07-11 03:44:17 -0700482 VideoEncoderConfig::ContentType content_type,
483 const RtpKeepAliveConfig& keepalive_config)
perkj26091b12016-09-01 01:17:40 -0700484 : send_stream_(send_stream),
485 done_event_(done_event),
486 stats_proxy_(stats_proxy),
mflodmancc3d4422017-08-03 08:27:51 -0700487 video_stream_encoder_(video_stream_encoder),
perkj26091b12016-09-01 01:17:40 -0700488 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700489 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700490 bitrate_allocator_(bitrate_allocator),
491 send_delay_stats_(send_delay_stats),
perkj26091b12016-09-01 01:17:40 -0700492 event_log_(event_log),
493 config_(config),
Per512ecb32016-09-23 15:52:06 +0200494 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
sprang89c4a7e2017-06-30 13:27:40 -0700495 suspended_ssrcs_(suspended_ssrcs),
sprange5c4a812017-07-11 03:44:17 -0700496 content_type_(content_type),
497 keepalive_config_(keepalive_config) {}
perkj26091b12016-09-01 01:17:40 -0700498
499 ~ConstructionTask() override { done_event_->Set(); }
500
501 private:
502 bool Run() override {
503 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700504 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
mflodmancc3d4422017-08-03 08:27:51 -0700505 bitrate_allocator_, send_delay_stats_, video_stream_encoder_,
506 event_log_, config_, initial_encoder_max_bitrate_,
507 std::move(suspended_ssrcs_), content_type_, keepalive_config_));
perkj26091b12016-09-01 01:17:40 -0700508 return true;
509 }
510
511 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
512 rtc::Event* const done_event_;
513 SendStatisticsProxy* const stats_proxy_;
mflodmancc3d4422017-08-03 08:27:51 -0700514 VideoStreamEncoder* const video_stream_encoder_;
perkj26091b12016-09-01 01:17:40 -0700515 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700516 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700517 BitrateAllocator* const bitrate_allocator_;
518 SendDelayStats* const send_delay_stats_;
perkj26091b12016-09-01 01:17:40 -0700519 RtcEventLog* const event_log_;
520 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200521 int initial_encoder_max_bitrate_;
perkj26091b12016-09-01 01:17:40 -0700522 std::map<uint32_t, RtpState> suspended_ssrcs_;
sprang89c4a7e2017-06-30 13:27:40 -0700523 const VideoEncoderConfig::ContentType content_type_;
sprange5c4a812017-07-11 03:44:17 -0700524 const RtpKeepAliveConfig& keepalive_config_;
perkj26091b12016-09-01 01:17:40 -0700525};
526
527class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
528 public:
529 DestructAndGetRtpStateTask(VideoSendStream::RtpStateMap* state_map,
530 std::unique_ptr<VideoSendStreamImpl> send_stream,
531 rtc::Event* done_event)
532 : state_map_(state_map),
533 send_stream_(std::move(send_stream)),
534 done_event_(done_event) {}
535
536 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
537
538 private:
539 bool Run() override {
540 send_stream_->Stop();
541 *state_map_ = send_stream_->GetRtpStates();
542 send_stream_.reset();
543 done_event_->Set();
544 return true;
545 }
546
547 VideoSendStream::RtpStateMap* state_map_;
548 std::unique_ptr<VideoSendStreamImpl> send_stream_;
549 rtc::Event* done_event_;
550};
551
552// CheckEncoderActivityTask is used for tracking when the encoder last produced
553// and encoded video frame. If the encoder has not produced anything the last
554// kEncoderTimeOutMs we also want to stop sending padding.
555class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
556 public:
557 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700558 explicit CheckEncoderActivityTask(
559 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
560 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700561
562 void Stop() {
563 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700564 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700565 }
566
567 void UpdateEncoderActivity() {
568 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
569 // whatever thread the real encoder implementation run on. In the case of
570 // hardware encoders, there might be several encoders
571 // running in parallel on different threads.
572 rtc::AtomicOps::ReleaseStore(&activity_, 1);
573 }
574
575 private:
576 bool Run() override {
577 RTC_CHECK(task_checker_.CalledSequentially());
578 if (!send_stream_)
579 return true;
580 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
581 if (!timed_out_) {
582 send_stream_->SignalEncoderTimedOut();
583 }
584 timed_out_ = true;
585 } else if (timed_out_) {
586 send_stream_->SignalEncoderActive();
587 timed_out_ = false;
588 }
589 rtc::AtomicOps::ReleaseStore(&activity_, 0);
590
591 rtc::TaskQueue::Current()->PostDelayedTask(
592 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
593 // Return false to prevent this task from being deleted. Ownership has been
594 // transferred to the task queue when PostDelayedTask was called.
595 return false;
596 }
597 volatile int activity_;
598
599 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700600 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700601 bool timed_out_;
602};
603
Per512ecb32016-09-23 15:52:06 +0200604class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700605 public:
perkj8ff860a2016-10-03 00:30:04 -0700606 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200607 std::vector<VideoStream> streams,
608 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700609 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200610 streams_(std::move(streams)),
611 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700612
613 private:
614 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700615 if (send_stream_)
616 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
617 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700618 return true;
619 }
620
perkj8ff860a2016-10-03 00:30:04 -0700621 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200622 std::vector<VideoStream> streams_;
623 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700624};
625
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000626VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200627 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200628 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700629 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200630 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700631 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800632 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700633 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700634 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700635 VideoSendStream::Config config,
636 VideoEncoderConfig encoder_config,
sprange5c4a812017-07-11 03:44:17 -0700637 const std::map<uint32_t, RtpState>& suspended_ssrcs,
638 const RtpKeepAliveConfig& keepalive_config)
perkj26091b12016-09-01 01:17:40 -0700639 : worker_queue_(worker_queue),
640 thread_sync_event_(false /* manual_reset */, false),
641 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800642 config,
643 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800644 config_(std::move(config)),
645 content_type_(encoder_config.content_type) {
mflodmancc3d4422017-08-03 08:27:51 -0700646 video_stream_encoder_.reset(
647 new VideoStreamEncoder(num_cpu_cores, &stats_proxy_,
648 config_.encoder_settings,
649 config_.pre_encode_callback,
650 config_.post_encode_callback,
651 std::unique_ptr<OveruseFrameDetector>()));
perkj26091b12016-09-01 01:17:40 -0700652 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
mflodmancc3d4422017-08-03 08:27:51 -0700653 &send_stream_, &thread_sync_event_, &stats_proxy_,
654 video_stream_encoder_.get(), module_process_thread, call_stats, transport,
655 bitrate_allocator, send_delay_stats, event_log, &config_,
656 encoder_config.max_bitrate_bps, suspended_ssrcs,
657 encoder_config.content_type, keepalive_config)));
perkj26091b12016-09-01 01:17:40 -0700658
659 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
660 // |module_process_thread| must be registered and deregistered on the thread
661 // it was created on.
662 thread_sync_event_.Wait(rtc::Event::kForever);
663 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800664 // TODO(sprang): Enable this also for regular video calls if it works well.
665 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
666 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700667 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800668 }
mflodmancc3d4422017-08-03 08:27:51 -0700669 video_stream_encoder_->RegisterProcessThread(module_process_thread);
perkj26091b12016-09-01 01:17:40 -0700670
671 ReconfigureVideoEncoder(std::move(encoder_config));
672}
673
674VideoSendStream::~VideoSendStream() {
675 RTC_DCHECK_RUN_ON(&thread_checker_);
676 RTC_DCHECK(!send_stream_);
677}
678
679void VideoSendStream::Start() {
680 RTC_DCHECK_RUN_ON(&thread_checker_);
681 LOG(LS_INFO) << "VideoSendStream::Start";
682 VideoSendStreamImpl* send_stream = send_stream_.get();
683 worker_queue_->PostTask([this, send_stream] {
684 send_stream->Start();
685 thread_sync_event_.Set();
686 });
687
688 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700689 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
690 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700691 thread_sync_event_.Wait(rtc::Event::kForever);
692}
693
694void VideoSendStream::Stop() {
695 RTC_DCHECK_RUN_ON(&thread_checker_);
696 LOG(LS_INFO) << "VideoSendStream::Stop";
697 VideoSendStreamImpl* send_stream = send_stream_.get();
698 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
699}
700
perkja49cbd32016-09-16 07:53:41 -0700701void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700702 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
703 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700704 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700705 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700706}
707
708void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700709 // TODO(perkj): Some test cases in VideoSendStreamTest call
710 // ReconfigureVideoEncoder from the network thread.
711 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800712 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700713 video_stream_encoder_->ConfigureEncoder(std::move(config),
714 config_.rtp.max_packet_size,
715 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700716}
717
718VideoSendStream::Stats VideoSendStream::GetStats() {
719 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
720 // a network thread. See comment in Call::GetStats().
721 // RTC_DCHECK_RUN_ON(&thread_checker_);
722 return stats_proxy_.GetStats();
723}
724
725void VideoSendStream::SignalNetworkState(NetworkState state) {
726 RTC_DCHECK_RUN_ON(&thread_checker_);
727 VideoSendStreamImpl* send_stream = send_stream_.get();
728 worker_queue_->PostTask(
729 [send_stream, state] { send_stream->SignalNetworkState(state); });
730}
731
732VideoSendStream::RtpStateMap VideoSendStream::StopPermanentlyAndGetRtpStates() {
733 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700734 video_stream_encoder_->Stop();
735 video_stream_encoder_->DeRegisterProcessThread();
perkj26091b12016-09-01 01:17:40 -0700736 VideoSendStream::RtpStateMap state_map;
737 send_stream_->DeRegisterProcessThread();
738 worker_queue_->PostTask(
739 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
740 &state_map, std::move(send_stream_), &thread_sync_event_)));
741 thread_sync_event_.Wait(rtc::Event::kForever);
742 return state_map;
743}
744
nisse284542b2017-01-10 08:58:32 -0800745void VideoSendStream::SetTransportOverhead(
746 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800747 RTC_DCHECK_RUN_ON(&thread_checker_);
748 VideoSendStreamImpl* send_stream = send_stream_.get();
749 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
750 send_stream->SetTransportOverhead(transport_overhead_per_packet);
751 });
752}
753
perkj26091b12016-09-01 01:17:40 -0700754bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
755 // Called on a network thread.
756 return send_stream_->DeliverRtcp(packet, length);
757}
758
palmkviste75f2042016-09-28 06:19:48 -0700759void VideoSendStream::EnableEncodedFrameRecording(
760 const std::vector<rtc::PlatformFile>& files,
761 size_t byte_limit) {
762 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
763}
764
perkj26091b12016-09-01 01:17:40 -0700765VideoSendStreamImpl::VideoSendStreamImpl(
766 SendStatisticsProxy* stats_proxy,
767 rtc::TaskQueue* worker_queue,
768 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700769 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700770 BitrateAllocator* bitrate_allocator,
771 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700772 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700773 RtcEventLog* event_log,
774 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200775 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700776 std::map<uint32_t, RtpState> suspended_ssrcs,
sprange5c4a812017-07-11 03:44:17 -0700777 VideoEncoderConfig::ContentType content_type,
778 const RtpKeepAliveConfig& keepalive_config)
sprangc1b57a12017-02-28 08:50:47 -0800779 : send_side_bwe_with_overhead_(
780 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800781 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000782 config_(config),
perkj26091b12016-09-01 01:17:40 -0700783 suspended_ssrcs_(std::move(suspended_ssrcs)),
784 module_process_thread_(nullptr),
785 worker_queue_(worker_queue),
786 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200787 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700788 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100789 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700790 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700791 max_padding_bitrate_(0),
792 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200793 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700794 encoder_target_rate_bps_(0),
mflodmancc3d4422017-08-03 08:27:51 -0700795 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700796 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700797 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700798 video_stream_encoder),
Per69b332d2016-06-02 15:45:42 +0200799 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
nisseb8f9a322017-03-27 05:36:15 -0700800 bandwidth_observer_(transport->send_side_cc()
801 ->GetBitrateController()
802 ->CreateRtcpBandwidthObserver()),
803 rtp_rtcp_modules_(CreateRtpRtcpModules(
804 config_->send_transport,
805 &encoder_feedback_,
806 bandwidth_observer_.get(),
807 transport,
808 call_stats_->rtcp_rtt_stats(),
809 flexfec_sender_.get(),
810 stats_proxy_,
811 send_delay_stats,
812 event_log,
813 transport->send_side_cc()->GetRetransmissionRateLimiter(),
814 this,
sprang168794c2017-07-06 04:38:06 -0700815 config_->rtp.ssrcs.size(),
sprange5c4a812017-07-11 03:44:17 -0700816 keepalive_config)),
perkj26091b12016-09-01 01:17:40 -0700817 payload_router_(rtp_rtcp_modules_,
perkj8ff860a2016-10-03 00:30:04 -0700818 config_->encoder_settings.payload_type),
michaelta3328772016-11-29 09:25:03 -0800819 weak_ptr_factory_(this),
820 overhead_bytes_per_packet_(0),
821 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700822 RTC_DCHECK_RUN_ON(worker_queue_);
823 LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700824 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700825 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100826
perkj26091b12016-09-01 01:17:40 -0700827 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100828 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700829 RTC_DCHECK(transport_);
830 RTC_DCHECK(transport_->send_side_cc());
mflodman949c2f02015-10-16 02:31:11 -0700831
sprang89c4a7e2017-06-30 13:27:40 -0700832 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
833 rtc::Optional<AlrDetector::AlrExperimentSettings> alr_settings =
834 AlrDetector::ParseAlrSettingsFromFieldTrial();
835 if (alr_settings) {
836 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
837 transport->send_side_cc()->pacer()->SetPacingFactor(
838 alr_settings->pacing_factor);
839 transport->send_side_cc()->pacer()->SetQueueTimeLimit(
840 alr_settings->max_paced_queue_time);
841 }
842 }
843
844 if (config_->periodic_alr_bandwidth_probing) {
845 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
846 }
sergeyu80ed35e2016-11-28 13:11:13 -0800847
Per83d09102016-04-15 14:59:13 +0200848 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800849
850 // We add the highest spatial layer first to ensure it'll be prioritized
851 // when sending padding, with the hope that the packet rate will be smaller,
852 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700853 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
854 constexpr bool remb_candidate = true;
855 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
856 }
mflodman949c2f02015-10-16 02:31:11 -0700857
perkj26091b12016-09-01 01:17:40 -0700858 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
859 const std::string& extension = config_->rtp.extensions[i].uri;
860 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200861 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700862 RTC_DCHECK_GE(id, 1);
863 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100864 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
ilnikcf705c52017-06-08 06:18:53 -0700865 if (StringToRtpExtensionType(extension) == kRtpExtensionVideoContentType &&
866 !field_trial::IsEnabled("WebRTC-VideoContentTypeExtension")) {
867 continue;
868 }
Peter Boström9c017252016-02-26 16:26:20 +0100869 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
870 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
871 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000872 }
873 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000874
Per83d09102016-04-15 14:59:13 +0200875 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000876 ConfigureSsrcs();
877
Peter Boström723ead82016-02-22 15:14:01 +0100878 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700879 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800880
Peter Boström723ead82016-02-22 15:14:01 +0100881 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700882 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
883 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800884 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100885 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700886 config_->encoder_settings.payload_type,
887 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100888 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000889
perkj26091b12016-09-01 01:17:40 -0700890 RTC_DCHECK(config_->encoder_settings.encoder);
891 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
892 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000893
mflodmancc3d4422017-08-03 08:27:51 -0700894 video_stream_encoder_->SetStartBitrate(
895 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700896
897 // Only request rotation at the source when we positively know that the remote
898 // side doesn't support the rotation extension. This allows us to prepare the
899 // encoder in the expectation that rotation is supported - which is the common
900 // case.
901 bool rotation_applied =
902 std::find_if(config_->rtp.extensions.begin(),
903 config_->rtp.extensions.end(),
904 [](const RtpExtension& extension) {
905 return extension.uri == RtpExtension::kVideoRotationUri;
906 }) == config_->rtp.extensions.end();
907
mflodmancc3d4422017-08-03 08:27:51 -0700908 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000909}
910
perkj26091b12016-09-01 01:17:40 -0700911void VideoSendStreamImpl::RegisterProcessThread(
912 ProcessThread* module_process_thread) {
913 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
914 RTC_DCHECK(!module_process_thread_);
915 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100916
perkj26091b12016-09-01 01:17:40 -0700917 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800918 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700919}
Peter Boströmca835252016-02-11 15:59:46 +0100920
perkj26091b12016-09-01 01:17:40 -0700921void VideoSendStreamImpl::DeRegisterProcessThread() {
922 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
923 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
924 module_process_thread_->DeRegisterModule(rtp_rtcp);
925}
Peter Boströma4c76882016-03-03 16:29:02 +0100926
perkj26091b12016-09-01 01:17:40 -0700927VideoSendStreamImpl::~VideoSendStreamImpl() {
928 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800929 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700930 << "VideoSendStreamImpl::Stop not called";
931 LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000932
Per83d09102016-04-15 14:59:13 +0200933 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700934 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200935 delete rtp_rtcp;
936 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000937}
938
perkj26091b12016-09-01 01:17:40 -0700939bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
940 // Runs on a network thread.
941 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700942 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
943 rtp_rtcp->IncomingRtcpPacket(packet, length);
944 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000945}
946
perkj26091b12016-09-01 01:17:40 -0700947void VideoSendStreamImpl::Start() {
948 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700949 LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800950 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100951 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200952 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800953 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700954
955 bitrate_allocator_->AddObserver(
956 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
957 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
958
959 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700960 {
perkj26091b12016-09-01 01:17:40 -0700961 rtc::CritScope lock(&encoder_activity_crit_sect_);
962 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700963 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700964 worker_queue_->PostDelayedTask(
965 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
966 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700967 }
perkj26091b12016-09-01 01:17:40 -0700968
mflodmancc3d4422017-08-03 08:27:51 -0700969 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000970}
971
perkj26091b12016-09-01 01:17:40 -0700972void VideoSendStreamImpl::Stop() {
973 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700974 LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800975 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100976 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200977 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800978 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700979 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700980 {
perkj26091b12016-09-01 01:17:40 -0700981 rtc::CritScope lock(&encoder_activity_crit_sect_);
982 check_encoder_activity_task_->Stop();
983 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700984 }
mflodmancc3d4422017-08-03 08:27:51 -0700985 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -0700986 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000987}
988
perkj26091b12016-09-01 01:17:40 -0700989void VideoSendStreamImpl::SignalEncoderTimedOut() {
990 RTC_DCHECK_RUN_ON(worker_queue_);
991 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
992 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
993 // if a camera stops producing frames.
994 if (encoder_target_rate_bps_ > 0) {
995 LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
996 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100997 }
998}
999
sprang1a646ee2016-12-01 06:34:11 -08001000void VideoSendStreamImpl::OnBitrateAllocationUpdated(
1001 const BitrateAllocation& allocation) {
1002 payload_router_.OnBitrateAllocationUpdated(allocation);
1003}
1004
perkj26091b12016-09-01 01:17:40 -07001005void VideoSendStreamImpl::SignalEncoderActive() {
1006 RTC_DCHECK_RUN_ON(worker_queue_);
1007 LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
1008 bitrate_allocator_->AddObserver(
1009 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
1010 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
1011}
1012
Per512ecb32016-09-23 15:52:06 +02001013void VideoSendStreamImpl::OnEncoderConfigurationChanged(
1014 std::vector<VideoStream> streams,
1015 int min_transmit_bitrate_bps) {
1016 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +02001017 worker_queue_->PostTask(
1018 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -07001019 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +02001020 return;
1021 }
1022 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
1023 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
1024 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -07001025 RTC_DCHECK_RUN_ON(worker_queue_);
1026
1027 const int kEncoderMinBitrateBps = 30000;
1028 encoder_min_bitrate_bps_ =
Per512ecb32016-09-23 15:52:06 +02001029 std::max(streams[0].min_bitrate_bps, kEncoderMinBitrateBps);
perkj26091b12016-09-01 01:17:40 -07001030 encoder_max_bitrate_bps_ = 0;
Per512ecb32016-09-23 15:52:06 +02001031 for (const auto& stream : streams)
perkj26091b12016-09-01 01:17:40 -07001032 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Per512ecb32016-09-23 15:52:06 +02001033 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
1034 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -07001035
1036 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +02001037 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -07001038 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001039 }
perkj26091b12016-09-01 01:17:40 -07001040
1041 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +02001042 streams.back().temporal_layer_thresholds_bps.size() + 1;
perkj26091b12016-09-01 01:17:40 -07001043 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +02001044 streams[0].width, streams[0].height, number_of_temporal_layers,
1045 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -07001046
sprang1a646ee2016-12-01 06:34:11 -08001047 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -07001048 // The send stream is started already. Update the allocator with new bitrate
1049 // limits.
1050 bitrate_allocator_->AddObserver(
1051 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
1052 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
1053 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001054}
1055
perkj26091b12016-09-01 01:17:40 -07001056EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001057 const EncodedImage& encoded_image,
1058 const CodecSpecificInfo* codec_specific_info,
1059 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -07001060 // Encoded is called on whatever thread the real encoder implementation run
1061 // on. In the case of hardware encoders, there might be several encoders
1062 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -08001063 size_t simulcast_idx = 0;
1064 if (codec_specific_info->codecType == kVideoCodecVP8) {
1065 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
1066 }
perkj26091b12016-09-01 01:17:40 -07001067 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -08001068 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
1069 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
1070 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -07001071 }
perkj26091b12016-09-01 01:17:40 -07001072 {
1073 rtc::CritScope lock(&encoder_activity_crit_sect_);
1074 if (check_encoder_activity_task_)
1075 check_encoder_activity_task_->UpdateEncoderActivity();
1076 }
sergeyu37ad3372016-06-14 15:29:37 -07001077
Per69b332d2016-06-02 15:45:42 +02001078 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001079 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001080 encoded_image, codec_specific_info, fragmentation);
1081
palmkviste75f2042016-09-28 06:19:48 -07001082 RTC_DCHECK(codec_specific_info);
1083
1084 int layer = codec_specific_info->codecType == kVideoCodecVP8
1085 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1086 : 0;
1087 {
1088 rtc::CritScope lock(&ivf_writers_crit_);
1089 if (file_writers_[layer].get()) {
1090 bool ok = file_writers_[layer]->WriteFrame(
1091 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001092 RTC_DCHECK(ok);
1093 }
1094 }
1095
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001096 return result;
perkjbc75d972016-05-02 06:31:25 -07001097}
1098
perkj26091b12016-09-01 01:17:40 -07001099void VideoSendStreamImpl::ConfigureProtection() {
1100 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001101
brandtre950cad2016-11-15 05:25:41 -08001102 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1103 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1104
1105 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001106 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1107 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001108 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001109
1110 // Shorthands.
1111 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001112 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001113 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1114 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1115
brandtre950cad2016-11-15 05:25:41 -08001116 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1117 if (flexfec_enabled) {
1118 // We can safely disable RED here, because if the remote supports FlexFEC,
1119 // we know that it has a receiver without the RED/RTX workaround.
1120 // See http://crbug.com/webrtc/6650 for more information.
1121 if (IsRedEnabled()) {
1122 LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
1123 DisableRed();
1124 }
1125 if (IsUlpfecEnabled()) {
1126 LOG(LS_INFO)
1127 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1128 DisableUlpfec();
1129 }
1130 }
1131
Per83d09102016-04-15 14:59:13 +02001132 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001133 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1134 // is a waste of bandwidth since FEC packets still have to be transmitted.
1135 // Note that this is not the case with FlexFEC.
1136 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001137 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001138 config_->encoder_settings.payload_name)) {
brandtre6f98c72016-11-11 03:28:30 -08001139 LOG(LS_WARNING)
1140 << "Transmitting payload type without picture ID using "
1141 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1142 "also have to be retransmitted. Disabling ULPFEC.";
1143 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001144 }
1145
brandtre6f98c72016-11-11 03:28:30 -08001146 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001147 //
brandtre6f98c72016-11-11 03:28:30 -08001148 // Due to how old receivers work, we need to always send RED if it has been
1149 // negotiated. This is a remnant of an old RED/RTX workaround, see
1150 // https://codereview.webrtc.org/2469093003.
1151 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1152 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1153 // no point in using RED without ULPFEC.
1154 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001155 RTC_DCHECK_GE(red_payload_type, 0);
1156 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001157 }
brandtre6f98c72016-11-11 03:28:30 -08001158 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001159 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1160 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001161 if (!IsRedEnabled()) {
1162 LOG(LS_WARNING)
1163 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1164 DisableUlpfec();
1165 }
Per83d09102016-04-15 14:59:13 +02001166 }
1167
1168 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1169 // Set NACK.
1170 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001171 true,
Per83d09102016-04-15 14:59:13 +02001172 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001173 // Set RED/ULPFEC information.
Per83d09102016-04-15 14:59:13 +02001174 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrf1bb4762016-11-07 03:05:06 -08001175 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001176 }
1177 }
1178
brandtre950cad2016-11-15 05:25:41 -08001179 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1180 // so enable that logic if either of those FEC schemes are enabled.
1181 protection_bitrate_calculator_.SetProtectionMethod(
1182 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001183}
1184
perkj26091b12016-09-01 01:17:40 -07001185void VideoSendStreamImpl::ConfigureSsrcs() {
1186 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001187 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001188 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1189 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001190 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1191 rtp_rtcp->SetSSRC(ssrc);
1192
1193 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001194 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001195 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001196 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001197 }
1198
Peter Boström723ead82016-02-22 15:14:01 +01001199 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001200 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001201 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001202
Peter Boström723ead82016-02-22 15:14:01 +01001203 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001204 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1205 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1206 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001207 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1208 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001209 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001210 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001211 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001212 }
1213
Peter Boström723ead82016-02-22 15:14:01 +01001214 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001215 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001216 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001217 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1218 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001219 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1220 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001221 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1222 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001223 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001224 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1225 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001226 }
Stefan Holmer10880012016-02-03 13:29:59 +01001227 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001228}
1229
perkj26091b12016-09-01 01:17:40 -07001230std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1231 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001232 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001233
perkj26091b12016-09-01 01:17:40 -07001234 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1235 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001236 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1237 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001238 }
1239
perkj26091b12016-09-01 01:17:40 -07001240 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1241 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001242 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001243 }
1244
brandtr48d21a22017-05-30 02:32:12 -07001245 if (flexfec_sender_) {
1246 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1247 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1248 }
1249
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001250 return rtp_states;
1251}
1252
perkj26091b12016-09-01 01:17:40 -07001253void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1254 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001255 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001256 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001257 : RtcpMode::kOff);
1258 }
1259}
1260
perkj26091b12016-09-01 01:17:40 -07001261uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1262 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001263 int64_t rtt,
1264 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001265 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001266 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001267 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001268
michaelt192132e2017-01-26 09:05:27 -08001269 // Substract overhead from bitrate.
1270 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001271 uint32_t payload_bitrate_bps = bitrate_bps;
1272 if (send_side_bwe_with_overhead_) {
1273 payload_bitrate_bps -= CalculateOverheadRateBps(
1274 CalculatePacketRate(bitrate_bps,
1275 config_->rtp.max_packet_size +
1276 transport_overhead_bytes_per_packet_),
1277 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1278 bitrate_bps);
1279 }
michaelta3328772016-11-29 09:25:03 -08001280
Per69b332d2016-06-02 15:45:42 +02001281 // Get the encoder target rate. It is the estimated network rate -
1282 // protection overhead.
perkj26091b12016-09-01 01:17:40 -07001283 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001284 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1285 rtt);
1286
elad.alon0fe12162017-01-31 05:48:37 -08001287 uint32_t encoder_overhead_rate_bps =
1288 send_side_bwe_with_overhead_
1289 ? CalculateOverheadRateBps(
1290 CalculatePacketRate(encoder_target_rate_bps_,
1291 config_->rtp.max_packet_size +
1292 transport_overhead_bytes_per_packet_ -
1293 overhead_bytes_per_packet_),
1294 overhead_bytes_per_packet_ +
1295 transport_overhead_bytes_per_packet_,
1296 bitrate_bps - encoder_target_rate_bps_)
1297 : 0;
michaelt192132e2017-01-26 09:05:27 -08001298
1299 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1300 // protection_bitrate includes overhead.
1301 uint32_t protection_bitrate =
1302 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001303
perkj26091b12016-09-01 01:17:40 -07001304 encoder_target_rate_bps_ =
1305 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001306 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1307 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001308 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001309 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001310}
1311
palmkviste75f2042016-09-28 06:19:48 -07001312void VideoSendStreamImpl::EnableEncodedFrameRecording(
1313 const std::vector<rtc::PlatformFile>& files,
1314 size_t byte_limit) {
1315 {
1316 rtc::CritScope lock(&ivf_writers_crit_);
1317 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1318 if (i < files.size()) {
1319 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1320 } else {
1321 file_writers_[i].reset();
1322 }
1323 }
1324 }
1325
1326 if (!files.empty()) {
1327 // Make a keyframe appear as early as possible in the logs, to give actually
1328 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001329 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001330 }
1331}
1332
perkj26091b12016-09-01 01:17:40 -07001333int VideoSendStreamImpl::ProtectionRequest(
1334 const FecProtectionParams* delta_params,
1335 const FecProtectionParams* key_params,
1336 uint32_t* sent_video_rate_bps,
1337 uint32_t* sent_nack_rate_bps,
1338 uint32_t* sent_fec_rate_bps) {
1339 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001340 *sent_video_rate_bps = 0;
1341 *sent_nack_rate_bps = 0;
1342 *sent_fec_rate_bps = 0;
1343 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1344 uint32_t not_used = 0;
1345 uint32_t module_video_rate = 0;
1346 uint32_t module_fec_rate = 0;
1347 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001348 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001349 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1350 &module_nack_rate);
1351 *sent_video_rate_bps += module_video_rate;
1352 *sent_nack_rate_bps += module_nack_rate;
1353 *sent_fec_rate_bps += module_fec_rate;
1354 }
1355 return 0;
1356}
1357
michaelta3328772016-11-29 09:25:03 -08001358void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1359 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1360 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1361}
1362
michaelt79e05882016-11-08 02:50:09 -08001363void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001364 size_t transport_overhead_bytes_per_packet) {
1365 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
1366 LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
1367 return;
1368 }
1369
michaelta3328772016-11-29 09:25:03 -08001370 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001371
nisseb8f9a322017-03-27 05:36:15 -07001372 transport_->send_side_cc()->SetTransportOverhead(
1373 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001374
1375 size_t rtp_packet_size =
1376 std::min(config_->rtp.max_packet_size,
1377 kPathMTU - transport_overhead_bytes_per_packet_);
1378
michaelta3328772016-11-29 09:25:03 -08001379 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001380 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001381 }
michaelt79e05882016-11-08 02:50:09 -08001382}
1383
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001384} // namespace internal
1385} // namespace webrtc