blob: 765ec424e0cca362ecc1701eb95c380c91e4f73d [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 */
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020010#include "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>
Ying Wang3b790f32018-01-19 17:58:57 +010014#include <set>
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +000015#include <sstream>
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000016#include <string>
perkj71ee44c2016-06-15 00:47:53 -070017#include <utility>
pbos@webrtc.org29d58392013-05-16 12:08:03 +000018#include <vector>
19
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020020#include "call/rtp_transport_controller_send_interface.h"
Sebastian Janssoncabe3832018-01-12 10:54:18 +010021#include "call/video_send_stream.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020022#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020023#include "common_video/include/video_bitrate_allocator.h"
24#include "modules/bitrate_controller/include/bitrate_controller.h"
25#include "modules/congestion_controller/include/send_side_congestion_controller.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020026#include "modules/pacing/packet_router.h"
27#include "modules/rtp_rtcp/include/rtp_rtcp.h"
28#include "modules/rtp_rtcp/source/rtp_sender.h"
29#include "modules/utility/include/process_thread.h"
Ying Wang3b790f32018-01-19 17:58:57 +010030#include "modules/video_coding/fec_controller_default.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020031#include "modules/video_coding/utility/ivf_file_writer.h"
32#include "rtc_base/checks.h"
Sebastian Janssoncabe3832018-01-12 10:54:18 +010033#include "rtc_base/experiments/alr_experiment.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020034#include "rtc_base/file.h"
35#include "rtc_base/location.h"
36#include "rtc_base/logging.h"
37#include "rtc_base/trace_event.h"
38#include "rtc_base/weak_ptr.h"
39#include "system_wrappers/include/field_trial.h"
40#include "video/call_stats.h"
41#include "video/payload_router.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000042
43namespace webrtc {
mflodman949c2f02015-10-16 02:31:11 -070044
Per83d09102016-04-15 14:59:13 +020045static const int kMinSendSidePacketHistorySize = 600;
Ying Wang3b790f32018-01-19 17:58:57 +010046static const int kSendSideSeqNumSetMaxSize = 15000;
47
Per83d09102016-04-15 14:59:13 +020048namespace {
49
nisse284542b2017-01-10 08:58:32 -080050// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
51const size_t kPathMTU = 1500;
52
Per83d09102016-04-15 14:59:13 +020053std::vector<RtpRtcp*> CreateRtpRtcpModules(
54 Transport* outgoing_transport,
55 RtcpIntraFrameObserver* intra_frame_callback,
56 RtcpBandwidthObserver* bandwidth_callback,
nisseb8f9a322017-03-27 05:36:15 -070057 RtpTransportControllerSendInterface* transport,
Per83d09102016-04-15 14:59:13 +020058 RtcpRttStats* rtt_stats,
brandtre950cad2016-11-15 05:25:41 -080059 FlexfecSender* flexfec_sender,
Per83d09102016-04-15 14:59:13 +020060 SendStatisticsProxy* stats_proxy,
asapersson35151f32016-05-02 23:44:01 -070061 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -070062 RtcEventLog* event_log,
sprangcd349d92016-07-13 09:11:28 -070063 RateLimiter* retransmission_rate_limiter,
michaelta3328772016-11-29 09:25:03 -080064 OverheadObserver* overhead_observer,
sprang168794c2017-07-06 04:38:06 -070065 size_t num_modules,
Jiawei Ou3587b832018-01-31 22:08:26 -080066 RtpKeepAliveConfig keepalive_config,
67 RtcpIntervalConfig rtc_interval_config) {
kwibergaf476c72016-11-28 15:21:39 -080068 RTC_DCHECK_GT(num_modules, 0);
Per83d09102016-04-15 14:59:13 +020069 RtpRtcp::Configuration configuration;
Per83d09102016-04-15 14:59:13 +020070 configuration.audio = false;
71 configuration.receiver_only = false;
brandtre950cad2016-11-15 05:25:41 -080072 configuration.flexfec_sender = flexfec_sender;
Per83d09102016-04-15 14:59:13 +020073 configuration.outgoing_transport = outgoing_transport;
74 configuration.intra_frame_callback = intra_frame_callback;
tereliusadafe0b2016-05-26 01:58:40 -070075 configuration.bandwidth_callback = bandwidth_callback;
nisseb8f9a322017-03-27 05:36:15 -070076 configuration.transport_feedback_callback =
77 transport->transport_feedback_observer();
Per83d09102016-04-15 14:59:13 +020078 configuration.rtt_stats = rtt_stats;
79 configuration.rtcp_packet_type_counter_observer = stats_proxy;
nisseb8f9a322017-03-27 05:36:15 -070080 configuration.paced_sender = transport->packet_sender();
Per83d09102016-04-15 14:59:13 +020081 configuration.transport_sequence_number_allocator =
nisseb8f9a322017-03-27 05:36:15 -070082 transport->packet_router();
Per83d09102016-04-15 14:59:13 +020083 configuration.send_bitrate_observer = stats_proxy;
84 configuration.send_frame_count_observer = stats_proxy;
85 configuration.send_side_delay_observer = stats_proxy;
asapersson35151f32016-05-02 23:44:01 -070086 configuration.send_packet_observer = send_delay_stats;
tereliusadafe0b2016-05-26 01:58:40 -070087 configuration.event_log = event_log;
sprangcd349d92016-07-13 09:11:28 -070088 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
michaelta3328772016-11-29 09:25:03 -080089 configuration.overhead_observer = overhead_observer;
sprang168794c2017-07-06 04:38:06 -070090 configuration.keepalive_config = keepalive_config;
Per83d09102016-04-15 14:59:13 +020091 std::vector<RtpRtcp*> modules;
92 for (size_t i = 0; i < num_modules; ++i) {
93 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
94 rtp_rtcp->SetSendingStatus(false);
95 rtp_rtcp->SetSendingMediaStatus(false);
96 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
97 modules.push_back(rtp_rtcp);
98 }
99 return modules;
100}
101
brandtre950cad2016-11-15 05:25:41 -0800102// TODO(brandtr): Update this function when we support multistream protection.
103std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
brandtr48d21a22017-05-30 02:32:12 -0700104 const VideoSendStream::Config& config,
105 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
brandtr3d200bd2017-01-16 06:59:19 -0800106 if (config.rtp.flexfec.payload_type < 0) {
brandtre950cad2016-11-15 05:25:41 -0800107 return nullptr;
108 }
brandtr3d200bd2017-01-16 06:59:19 -0800109 RTC_DCHECK_GE(config.rtp.flexfec.payload_type, 0);
110 RTC_DCHECK_LE(config.rtp.flexfec.payload_type, 127);
111 if (config.rtp.flexfec.ssrc == 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100112 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
113 "Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800114 return nullptr;
115 }
116 if (config.rtp.flexfec.protected_media_ssrcs.empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100117 RTC_LOG(LS_WARNING)
118 << "FlexFEC is enabled, but no protected media SSRC given. "
119 "Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800120 return nullptr;
121 }
122
123 if (config.rtp.ssrcs.size() > 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100124 RTC_LOG(LS_WARNING)
125 << "Both FlexFEC and simulcast are enabled. This "
126 "combination is however not supported by our current "
127 "FlexFEC implementation. Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800128 return nullptr;
129 }
130
131 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100132 RTC_LOG(LS_WARNING)
brandtre950cad2016-11-15 05:25:41 -0800133 << "The supplied FlexfecConfig contained multiple protected "
134 "media streams, but our implementation currently only "
135 "supports protecting a single media stream. "
136 "To avoid confusion, disabling FlexFEC completely.";
137 return nullptr;
138 }
139
brandtr48d21a22017-05-30 02:32:12 -0700140 const RtpState* rtp_state = nullptr;
141 auto it = suspended_ssrcs.find(config.rtp.flexfec.ssrc);
142 if (it != suspended_ssrcs.end()) {
143 rtp_state = &it->second;
144 }
145
brandtre950cad2016-11-15 05:25:41 -0800146 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
147 return std::unique_ptr<FlexfecSender>(new FlexfecSender(
brandtr3d200bd2017-01-16 06:59:19 -0800148 config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc,
brandtre950cad2016-11-15 05:25:41 -0800149 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions,
brandtr48d21a22017-05-30 02:32:12 -0700150 RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock()));
brandtre950cad2016-11-15 05:25:41 -0800151}
152
Erik Språng7c8cca32017-10-24 17:05:18 +0200153bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
154 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
155 return std::find_if(
156 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
157 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
158 }) != extensions.end();
159}
Peter Boströme4499152016-02-05 11:13:28 +0100160
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100161const char kForcedFallbackFieldTrial[] =
162 "WebRTC-VP8-Forced-Fallback-Encoder-v2";
163
164rtc::Optional<int> GetFallbackMinBpsFromFieldTrial() {
165 if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100166 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100167
168 std::string group =
169 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
170 if (group.empty())
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100171 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100172
173 int min_pixels;
174 int max_pixels;
175 int min_bps;
176 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
177 &min_bps) != 3) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100178 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100179 }
180
181 if (min_bps <= 0)
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100182 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100183
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100184 return min_bps;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100185}
186
187int GetEncoderMinBitrateBps() {
188 const int kDefaultEncoderMinBitrateBps = 30000;
189 return GetFallbackMinBpsFromFieldTrial().value_or(
190 kDefaultEncoderMinBitrateBps);
191}
192
Peter Boström39593972016-02-15 11:27:15 +0100193bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
kthelgason1cdddc92017-08-24 03:52:48 -0700194 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
195 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
perkj26091b12016-09-01 01:17:40 -0700196 return true;
deadbeefc964d0b2017-04-03 10:03:35 -0700197 }
Peter Boström39593972016-02-15 11:27:15 +0100198 return false;
199}
200
Per512ecb32016-09-23 15:52:06 +0200201int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
202 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700203 bool pad_to_min_bitrate) {
204 int pad_up_to_bitrate_bps = 0;
205 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200206 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700207 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200208 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700209 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200210 for (size_t i = 0; i < streams.size() - 1; ++i)
211 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700212 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200213 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700214 }
215
216 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200217 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700218
219 return pad_up_to_bitrate_bps;
220}
221
michaelt192132e2017-01-26 09:05:27 -0800222uint32_t CalculateOverheadRateBps(int packets_per_second,
223 size_t overhead_bytes_per_packet,
224 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800225 uint32_t overhead_bps =
226 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
227 return std::min(overhead_bps, max_overhead_bps);
228}
229
230int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
231 size_t packet_size_bits = 8 * packet_size_bytes;
232 // Ceil for int value of bitrate_bps / packet_size_bits.
233 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
234 packet_size_bits);
235}
236
Niels Möller73f29cb2018-01-31 16:09:31 +0100237// TODO(pbos): Lower these thresholds (to closer to 100%) when we handle
238// pipelining encoders better (multiple input frames before something comes
239// out). This should effectively turn off CPU adaptations for systems that
240// remotely cope with the load right now.
241CpuOveruseOptions GetCpuOveruseOptions(const VideoSendStream::Config& config) {
242 CpuOveruseOptions options;
243
244 if (config.encoder_settings.full_overuse_time) {
245 options.low_encode_usage_threshold_percent = 150;
246 options.high_encode_usage_threshold_percent = 200;
247 }
248 if (config.encoder_settings.experiment_cpu_load_estimator) {
249 options.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
250 }
251
252 return options;
253}
254
Peter Boströme4499152016-02-05 11:13:28 +0100255} // namespace
256
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000257namespace internal {
perkj26091b12016-09-01 01:17:40 -0700258
259// VideoSendStreamImpl implements internal::VideoSendStream.
260// It is created and destroyed on |worker_queue|. The intent is to decrease the
261// need for locking and to ensure methods are called in sequence.
262// Public methods except |DeliverRtcp| must be called on |worker_queue|.
263// DeliverRtcp is called on the libjingle worker thread or a network thread.
264// An encoder may deliver frames through the EncodedImageCallback on an
265// arbitrary thread.
266class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800267 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700268 public webrtc::VCMProtectionCallback,
mflodmancc3d4422017-08-03 08:27:51 -0700269 public VideoStreamEncoder::EncoderSink,
Ying Wang3b790f32018-01-19 17:58:57 +0100270 public VideoBitrateAllocationObserver,
271 public webrtc::PacketFeedbackObserver {
perkj26091b12016-09-01 01:17:40 -0700272 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200273 VideoSendStreamImpl(
274 SendStatisticsProxy* stats_proxy,
275 rtc::TaskQueue* worker_queue,
276 CallStats* call_stats,
277 RtpTransportControllerSendInterface* transport,
278 BitrateAllocator* bitrate_allocator,
279 SendDelayStats* send_delay_stats,
280 VideoStreamEncoder* video_stream_encoder,
281 RtcEventLog* event_log,
282 const VideoSendStream::Config* config,
283 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800284 double initial_encoder_bitrate_priority,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200285 std::map<uint32_t, RtpState> suspended_ssrcs,
286 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
Ying Wang3b790f32018-01-19 17:58:57 +0100287 VideoEncoderConfig::ContentType content_type,
288 std::unique_ptr<FecController> fec_controller);
perkj26091b12016-09-01 01:17:40 -0700289 ~VideoSendStreamImpl() override;
290
291 // RegisterProcessThread register |module_process_thread| with those objects
292 // that use it. Registration has to happen on the thread were
293 // |module_process_thread| was created (libjingle's worker thread).
294 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
295 // maybe |worker_queue|.
296 void RegisterProcessThread(ProcessThread* module_process_thread);
297 void DeRegisterProcessThread();
298
299 void SignalNetworkState(NetworkState state);
300 bool DeliverRtcp(const uint8_t* packet, size_t length);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800301 void UpdateActiveSimulcastLayers(const std::vector<bool> active_layers);
perkj26091b12016-09-01 01:17:40 -0700302 void Start();
303 void Stop();
304
perkj26091b12016-09-01 01:17:40 -0700305 VideoSendStream::RtpStateMap GetRtpStates() const;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200306 VideoSendStream::RtpPayloadStateMap GetRtpPayloadStates() const;
perkj26091b12016-09-01 01:17:40 -0700307
palmkviste75f2042016-09-28 06:19:48 -0700308 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
309 size_t byte_limit);
310
nisse284542b2017-01-10 08:58:32 -0800311 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800312
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100313 rtc::Optional<float> configured_pacing_factor_;
314
Ying Wang3b790f32018-01-19 17:58:57 +0100315 // From PacketFeedbackObserver.
316 void OnPacketAdded(uint32_t ssrc, uint16_t seq_num) override;
317 void OnPacketFeedbackVector(
318 const std::vector<PacketFeedback>& packet_feedback_vector) override;
319
perkj26091b12016-09-01 01:17:40 -0700320 private:
321 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200322 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700323
324 // Implements BitrateAllocatorObserver.
325 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
326 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800327 int64_t rtt,
328 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700329
330 // Implements webrtc::VCMProtectionCallback.
331 int ProtectionRequest(const FecProtectionParams* delta_params,
332 const FecProtectionParams* key_params,
333 uint32_t* sent_video_rate_bps,
334 uint32_t* sent_nack_rate_bps,
335 uint32_t* sent_fec_rate_bps) override;
336
michaelta3328772016-11-29 09:25:03 -0800337 // Implements OverheadObserver.
338 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
339
Per512ecb32016-09-23 15:52:06 +0200340 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
341 int min_transmit_bitrate_bps) override;
342
perkj26091b12016-09-01 01:17:40 -0700343 // Implements EncodedImageCallback. The implementation routes encoded frames
344 // to the |payload_router_| and |config.pre_encode_callback| if set.
345 // Called on an arbitrary encoder callback thread.
346 EncodedImageCallback::Result OnEncodedImage(
347 const EncodedImage& encoded_image,
348 const CodecSpecificInfo* codec_specific_info,
349 const RTPFragmentationHeader* fragmentation) override;
350
sprang1a646ee2016-12-01 06:34:11 -0800351 // Implements VideoBitrateAllocationObserver.
352 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
353
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800354 // Starts monitoring and sends a keyframe.
355 void StartupVideoSendStream();
356 // Removes the bitrate observer, stops monitoring and notifies the video
357 // encoder of the bitrate update.
358 void StopVideoSendStream();
359
perkj26091b12016-09-01 01:17:40 -0700360 void ConfigureProtection();
361 void ConfigureSsrcs();
362 void SignalEncoderTimedOut();
363 void SignalEncoderActive();
364
elad.alon0fe12162017-01-31 05:48:37 -0800365 const bool send_side_bwe_with_overhead_;
Ying Wang38a31b02017-12-21 12:26:19 +0000366
perkj26091b12016-09-01 01:17:40 -0700367 SendStatisticsProxy* const stats_proxy_;
368 const VideoSendStream::Config* const config_;
369 std::map<uint32_t, RtpState> suspended_ssrcs_;
370
Ying Wang3b790f32018-01-19 17:58:57 +0100371 std::unique_ptr<FecController> fec_controller_;
perkj26091b12016-09-01 01:17:40 -0700372 ProcessThread* module_process_thread_;
373 rtc::ThreadChecker module_process_thread_checker_;
374 rtc::TaskQueue* const worker_queue_;
375
376 rtc::CriticalSection encoder_activity_crit_sect_;
377 CheckEncoderActivityTask* check_encoder_activity_task_
danilchapa37de392017-09-09 04:17:22 -0700378 RTC_GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200379
perkj26091b12016-09-01 01:17:40 -0700380 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700381 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700382 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700383
brandtr3b941be2017-03-17 07:02:46 -0700384 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800385 std::unique_ptr<FlexfecSender> flexfec_sender_;
386
palmkviste75f2042016-09-28 06:19:48 -0700387 rtc::CriticalSection ivf_writers_crit_;
danilchapa37de392017-09-09 04:17:22 -0700388 std::unique_ptr<IvfFileWriter>
389 file_writers_[kMaxSimulcastStreams] RTC_GUARDED_BY(ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700390
391 int max_padding_bitrate_;
392 int encoder_min_bitrate_bps_;
393 uint32_t encoder_max_bitrate_bps_;
394 uint32_t encoder_target_rate_bps_;
Seth Hampson24722b32017-12-22 09:36:42 -0800395 double encoder_bitrate_priority_;
perkj26091b12016-09-01 01:17:40 -0700396
mflodmancc3d4422017-08-03 08:27:51 -0700397 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700398 EncoderRtcpFeedback encoder_feedback_;
perkj26091b12016-09-01 01:17:40 -0700399
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100400 RtcpBandwidthObserver* const bandwidth_observer_;
perkj26091b12016-09-01 01:17:40 -0700401 // RtpRtcp modules, declared here as they use other members on construction.
402 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
403 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700404
405 // |weak_ptr_| to our self. This is used since we can not call
406 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
407 // an existing WeakPtr.
408 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
409 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
410 // invalidated before any other members are destroyed.
411 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800412
413 rtc::CriticalSection overhead_bytes_per_packet_crit_;
danilchapa37de392017-09-09 04:17:22 -0700414 size_t overhead_bytes_per_packet_
415 RTC_GUARDED_BY(overhead_bytes_per_packet_crit_);
michaelta3328772016-11-29 09:25:03 -0800416 size_t transport_overhead_bytes_per_packet_;
Ying Wang3b790f32018-01-19 17:58:57 +0100417
418 std::set<uint16_t> feedback_packet_seq_num_set_;
419 std::vector<bool> loss_mask_vector_;
perkj26091b12016-09-01 01:17:40 -0700420};
421
422// TODO(tommi): See if there's a more elegant way to create a task that creates
423// an object on the correct task queue.
424class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
425 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200426 ConstructionTask(
427 std::unique_ptr<VideoSendStreamImpl>* send_stream,
428 rtc::Event* done_event,
429 SendStatisticsProxy* stats_proxy,
430 VideoStreamEncoder* video_stream_encoder,
431 ProcessThread* module_process_thread,
432 CallStats* call_stats,
433 RtpTransportControllerSendInterface* transport,
434 BitrateAllocator* bitrate_allocator,
435 SendDelayStats* send_delay_stats,
436 RtcEventLog* event_log,
437 const VideoSendStream::Config* config,
438 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800439 double initial_encoder_bitrate_priority,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200440 const std::map<uint32_t, RtpState>& suspended_ssrcs,
441 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
Ying Wang3b790f32018-01-19 17:58:57 +0100442 VideoEncoderConfig::ContentType content_type,
443 std::unique_ptr<FecController> fec_controller)
perkj26091b12016-09-01 01:17:40 -0700444 : send_stream_(send_stream),
445 done_event_(done_event),
446 stats_proxy_(stats_proxy),
mflodmancc3d4422017-08-03 08:27:51 -0700447 video_stream_encoder_(video_stream_encoder),
perkj26091b12016-09-01 01:17:40 -0700448 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700449 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700450 bitrate_allocator_(bitrate_allocator),
451 send_delay_stats_(send_delay_stats),
perkj26091b12016-09-01 01:17:40 -0700452 event_log_(event_log),
453 config_(config),
Per512ecb32016-09-23 15:52:06 +0200454 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
Seth Hampson24722b32017-12-22 09:36:42 -0800455 initial_encoder_bitrate_priority_(initial_encoder_bitrate_priority),
sprang89c4a7e2017-06-30 13:27:40 -0700456 suspended_ssrcs_(suspended_ssrcs),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200457 suspended_payload_states_(suspended_payload_states),
Ying Wang3b790f32018-01-19 17:58:57 +0100458 content_type_(content_type),
459 fec_controller_(std::move(fec_controller)) {}
perkj26091b12016-09-01 01:17:40 -0700460
461 ~ConstructionTask() override { done_event_->Set(); }
462
463 private:
464 bool Run() override {
465 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700466 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
mflodmancc3d4422017-08-03 08:27:51 -0700467 bitrate_allocator_, send_delay_stats_, video_stream_encoder_,
468 event_log_, config_, initial_encoder_max_bitrate_,
Seth Hampson24722b32017-12-22 09:36:42 -0800469 initial_encoder_bitrate_priority_, std::move(suspended_ssrcs_),
Ying Wang3b790f32018-01-19 17:58:57 +0100470 std::move(suspended_payload_states_), content_type_,
471 std::move(fec_controller_)));
perkj26091b12016-09-01 01:17:40 -0700472 return true;
473 }
474
475 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
476 rtc::Event* const done_event_;
477 SendStatisticsProxy* const stats_proxy_;
mflodmancc3d4422017-08-03 08:27:51 -0700478 VideoStreamEncoder* const video_stream_encoder_;
perkj26091b12016-09-01 01:17:40 -0700479 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700480 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700481 BitrateAllocator* const bitrate_allocator_;
482 SendDelayStats* const send_delay_stats_;
perkj26091b12016-09-01 01:17:40 -0700483 RtcEventLog* const event_log_;
484 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200485 int initial_encoder_max_bitrate_;
Seth Hampson24722b32017-12-22 09:36:42 -0800486 double initial_encoder_bitrate_priority_;
perkj26091b12016-09-01 01:17:40 -0700487 std::map<uint32_t, RtpState> suspended_ssrcs_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200488 std::map<uint32_t, RtpPayloadState> suspended_payload_states_;
sprang89c4a7e2017-06-30 13:27:40 -0700489 const VideoEncoderConfig::ContentType content_type_;
Ying Wang3b790f32018-01-19 17:58:57 +0100490 std::unique_ptr<FecController> fec_controller_;
perkj26091b12016-09-01 01:17:40 -0700491};
492
493class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
494 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200495 DestructAndGetRtpStateTask(
496 VideoSendStream::RtpStateMap* state_map,
497 VideoSendStream::RtpPayloadStateMap* payload_state_map,
498 std::unique_ptr<VideoSendStreamImpl> send_stream,
499 rtc::Event* done_event)
perkj26091b12016-09-01 01:17:40 -0700500 : state_map_(state_map),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200501 payload_state_map_(payload_state_map),
perkj26091b12016-09-01 01:17:40 -0700502 send_stream_(std::move(send_stream)),
503 done_event_(done_event) {}
504
505 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
506
507 private:
508 bool Run() override {
509 send_stream_->Stop();
510 *state_map_ = send_stream_->GetRtpStates();
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200511 *payload_state_map_ = send_stream_->GetRtpPayloadStates();
perkj26091b12016-09-01 01:17:40 -0700512 send_stream_.reset();
513 done_event_->Set();
514 return true;
515 }
516
517 VideoSendStream::RtpStateMap* state_map_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200518 VideoSendStream::RtpPayloadStateMap* payload_state_map_;
perkj26091b12016-09-01 01:17:40 -0700519 std::unique_ptr<VideoSendStreamImpl> send_stream_;
520 rtc::Event* done_event_;
521};
522
523// CheckEncoderActivityTask is used for tracking when the encoder last produced
524// and encoded video frame. If the encoder has not produced anything the last
525// kEncoderTimeOutMs we also want to stop sending padding.
526class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
527 public:
528 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700529 explicit CheckEncoderActivityTask(
530 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
531 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700532
533 void Stop() {
534 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700535 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700536 }
537
538 void UpdateEncoderActivity() {
539 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
540 // whatever thread the real encoder implementation run on. In the case of
541 // hardware encoders, there might be several encoders
542 // running in parallel on different threads.
543 rtc::AtomicOps::ReleaseStore(&activity_, 1);
544 }
545
546 private:
547 bool Run() override {
548 RTC_CHECK(task_checker_.CalledSequentially());
549 if (!send_stream_)
550 return true;
551 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
552 if (!timed_out_) {
553 send_stream_->SignalEncoderTimedOut();
554 }
555 timed_out_ = true;
556 } else if (timed_out_) {
557 send_stream_->SignalEncoderActive();
558 timed_out_ = false;
559 }
560 rtc::AtomicOps::ReleaseStore(&activity_, 0);
561
562 rtc::TaskQueue::Current()->PostDelayedTask(
563 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
564 // Return false to prevent this task from being deleted. Ownership has been
565 // transferred to the task queue when PostDelayedTask was called.
566 return false;
567 }
568 volatile int activity_;
569
570 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700571 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700572 bool timed_out_;
573};
574
Per512ecb32016-09-23 15:52:06 +0200575class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700576 public:
perkj8ff860a2016-10-03 00:30:04 -0700577 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200578 std::vector<VideoStream> streams,
579 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700580 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200581 streams_(std::move(streams)),
582 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700583
584 private:
585 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700586 if (send_stream_)
587 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
588 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700589 return true;
590 }
591
perkj8ff860a2016-10-03 00:30:04 -0700592 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200593 std::vector<VideoStream> streams_;
594 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700595};
596
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000597VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200598 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200599 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700600 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200601 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700602 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800603 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700604 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700605 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700606 VideoSendStream::Config config,
607 VideoEncoderConfig encoder_config,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200608 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Ying Wang3b790f32018-01-19 17:58:57 +0100609 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
610 std::unique_ptr<FecController> fec_controller)
perkj26091b12016-09-01 01:17:40 -0700611 : worker_queue_(worker_queue),
612 thread_sync_event_(false /* manual_reset */, false),
613 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800614 config,
615 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800616 config_(std::move(config)),
617 content_type_(encoder_config.content_type) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100618 video_stream_encoder_ = rtc::MakeUnique<VideoStreamEncoder>(
619 num_cpu_cores, &stats_proxy_,
620 config_.encoder_settings,
621 config_.pre_encode_callback,
622 rtc::MakeUnique<OveruseFrameDetector>(
623 GetCpuOveruseOptions(config_), &stats_proxy_));
624
perkj26091b12016-09-01 01:17:40 -0700625 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
mflodmancc3d4422017-08-03 08:27:51 -0700626 &send_stream_, &thread_sync_event_, &stats_proxy_,
627 video_stream_encoder_.get(), module_process_thread, call_stats, transport,
628 bitrate_allocator, send_delay_stats, event_log, &config_,
Seth Hampson24722b32017-12-22 09:36:42 -0800629 encoder_config.max_bitrate_bps, encoder_config.bitrate_priority,
Ying Wang3b790f32018-01-19 17:58:57 +0100630 suspended_ssrcs, suspended_payload_states, encoder_config.content_type,
631 std::move(fec_controller))));
perkj26091b12016-09-01 01:17:40 -0700632
633 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
634 // |module_process_thread| must be registered and deregistered on the thread
635 // it was created on.
636 thread_sync_event_.Wait(rtc::Event::kForever);
637 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800638 // TODO(sprang): Enable this also for regular video calls if it works well.
639 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
640 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700641 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800642 }
Ying Wang38a31b02017-12-21 12:26:19 +0000643
perkj26091b12016-09-01 01:17:40 -0700644 ReconfigureVideoEncoder(std::move(encoder_config));
645}
646
647VideoSendStream::~VideoSendStream() {
648 RTC_DCHECK_RUN_ON(&thread_checker_);
649 RTC_DCHECK(!send_stream_);
650}
651
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800652void VideoSendStream::UpdateActiveSimulcastLayers(
653 const std::vector<bool> active_layers) {
654 RTC_DCHECK_RUN_ON(&thread_checker_);
655 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
656 VideoSendStreamImpl* send_stream = send_stream_.get();
657 worker_queue_->PostTask([this, send_stream, active_layers] {
658 send_stream->UpdateActiveSimulcastLayers(active_layers);
659 thread_sync_event_.Set();
660 });
661
662 thread_sync_event_.Wait(rtc::Event::kForever);
663}
664
perkj26091b12016-09-01 01:17:40 -0700665void VideoSendStream::Start() {
666 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100667 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 01:17:40 -0700668 VideoSendStreamImpl* send_stream = send_stream_.get();
669 worker_queue_->PostTask([this, send_stream] {
670 send_stream->Start();
671 thread_sync_event_.Set();
672 });
673
674 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700675 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
676 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700677 thread_sync_event_.Wait(rtc::Event::kForever);
678}
679
680void VideoSendStream::Stop() {
681 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100682 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 01:17:40 -0700683 VideoSendStreamImpl* send_stream = send_stream_.get();
684 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
685}
686
perkja49cbd32016-09-16 07:53:41 -0700687void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700688 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
689 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700690 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700691 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700692}
693
694void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700695 // TODO(perkj): Some test cases in VideoSendStreamTest call
696 // ReconfigureVideoEncoder from the network thread.
697 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800698 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700699 video_stream_encoder_->ConfigureEncoder(std::move(config),
700 config_.rtp.max_packet_size,
701 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700702}
703
704VideoSendStream::Stats VideoSendStream::GetStats() {
705 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
706 // a network thread. See comment in Call::GetStats().
707 // RTC_DCHECK_RUN_ON(&thread_checker_);
708 return stats_proxy_.GetStats();
709}
710
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100711rtc::Optional<float> VideoSendStream::GetPacingFactorOverride() const {
712 return send_stream_->configured_pacing_factor_;
713}
714
perkj26091b12016-09-01 01:17:40 -0700715void VideoSendStream::SignalNetworkState(NetworkState state) {
716 RTC_DCHECK_RUN_ON(&thread_checker_);
717 VideoSendStreamImpl* send_stream = send_stream_.get();
718 worker_queue_->PostTask(
719 [send_stream, state] { send_stream->SignalNetworkState(state); });
720}
721
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200722void VideoSendStream::StopPermanentlyAndGetRtpStates(
723 VideoSendStream::RtpStateMap* rtp_state_map,
724 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700725 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700726 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700727 send_stream_->DeRegisterProcessThread();
728 worker_queue_->PostTask(
729 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200730 rtp_state_map, payload_state_map, std::move(send_stream_),
731 &thread_sync_event_)));
perkj26091b12016-09-01 01:17:40 -0700732 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700733}
734
nisse284542b2017-01-10 08:58:32 -0800735void VideoSendStream::SetTransportOverhead(
736 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800737 RTC_DCHECK_RUN_ON(&thread_checker_);
738 VideoSendStreamImpl* send_stream = send_stream_.get();
739 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
740 send_stream->SetTransportOverhead(transport_overhead_per_packet);
741 });
742}
743
perkj26091b12016-09-01 01:17:40 -0700744bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
745 // Called on a network thread.
746 return send_stream_->DeliverRtcp(packet, length);
747}
748
palmkviste75f2042016-09-28 06:19:48 -0700749void VideoSendStream::EnableEncodedFrameRecording(
750 const std::vector<rtc::PlatformFile>& files,
751 size_t byte_limit) {
752 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
753}
754
perkj26091b12016-09-01 01:17:40 -0700755VideoSendStreamImpl::VideoSendStreamImpl(
756 SendStatisticsProxy* stats_proxy,
757 rtc::TaskQueue* worker_queue,
758 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700759 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700760 BitrateAllocator* bitrate_allocator,
761 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700762 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700763 RtcEventLog* event_log,
764 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200765 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800766 double initial_encoder_bitrate_priority,
sprang89c4a7e2017-06-30 13:27:40 -0700767 std::map<uint32_t, RtpState> suspended_ssrcs,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200768 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
Ying Wang3b790f32018-01-19 17:58:57 +0100769 VideoEncoderConfig::ContentType content_type,
770 std::unique_ptr<FecController> fec_controller)
sprangc1b57a12017-02-28 08:50:47 -0800771 : send_side_bwe_with_overhead_(
772 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800773 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000774 config_(config),
perkj26091b12016-09-01 01:17:40 -0700775 suspended_ssrcs_(std::move(suspended_ssrcs)),
Ying Wang3b790f32018-01-19 17:58:57 +0100776 fec_controller_(std::move(fec_controller)),
perkj26091b12016-09-01 01:17:40 -0700777 module_process_thread_(nullptr),
778 worker_queue_(worker_queue),
779 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200780 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700781 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100782 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700783 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700784 max_padding_bitrate_(0),
785 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200786 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700787 encoder_target_rate_bps_(0),
Seth Hampson24722b32017-12-22 09:36:42 -0800788 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
mflodmancc3d4422017-08-03 08:27:51 -0700789 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700790 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700791 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700792 video_stream_encoder),
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100793 bandwidth_observer_(transport->send_side_cc()->GetBandwidthObserver()),
nisseb8f9a322017-03-27 05:36:15 -0700794 rtp_rtcp_modules_(CreateRtpRtcpModules(
795 config_->send_transport,
796 &encoder_feedback_,
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100797 bandwidth_observer_,
nisseb8f9a322017-03-27 05:36:15 -0700798 transport,
799 call_stats_->rtcp_rtt_stats(),
800 flexfec_sender_.get(),
801 stats_proxy_,
802 send_delay_stats,
803 event_log,
804 transport->send_side_cc()->GetRetransmissionRateLimiter(),
805 this,
sprang168794c2017-07-06 04:38:06 -0700806 config_->rtp.ssrcs.size(),
Jiawei Ou3587b832018-01-31 22:08:26 -0800807 transport->keepalive_config(),
808 RtcpIntervalConfig{config_->rtcp.video_report_interval_ms,
809 config_->rtcp.audio_report_interval_ms})),
perkj26091b12016-09-01 01:17:40 -0700810 payload_router_(rtp_rtcp_modules_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200811 config_->rtp.ssrcs,
812 config_->encoder_settings.payload_type,
813 suspended_payload_states),
michaelta3328772016-11-29 09:25:03 -0800814 weak_ptr_factory_(this),
815 overhead_bytes_per_packet_(0),
816 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700817 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100818 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700819 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700820 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100821
perkj26091b12016-09-01 01:17:40 -0700822 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100823 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700824 RTC_DCHECK(transport_);
825 RTC_DCHECK(transport_->send_side_cc());
Seth Hampson24722b32017-12-22 09:36:42 -0800826 RTC_DCHECK_GT(encoder_max_bitrate_bps_, 0);
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100827
828 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
Erik Språng7c8cca32017-10-24 17:05:18 +0200829 // If send-side BWE is enabled, check if we should apply updated probing and
830 // pacing settings.
831 if (TransportSeqNumExtensionConfigured(*config_)) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100832 rtc::Optional<AlrExperimentSettings> alr_settings;
Erik Språng7c8cca32017-10-24 17:05:18 +0200833 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100834 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
835 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200836 } else {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100837 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
838 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200839 }
840 if (alr_settings) {
841 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
Sebastian Jansson57daeb72018-02-05 17:15:09 +0100842 transport->send_side_cc()->SetPacingFactor(alr_settings->pacing_factor);
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100843 configured_pacing_factor_ = alr_settings->pacing_factor;
Erik Språng7c8cca32017-10-24 17:05:18 +0200844 transport->pacer()->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
845 }
sprang89c4a7e2017-06-30 13:27:40 -0700846 }
847
848 if (config_->periodic_alr_bandwidth_probing) {
849 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
850 }
sergeyu80ed35e2016-11-28 13:11:13 -0800851
Per83d09102016-04-15 14:59:13 +0200852 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800853
854 // We add the highest spatial layer first to ensure it'll be prioritized
855 // when sending padding, with the hope that the packet rate will be smaller,
856 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700857 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
858 constexpr bool remb_candidate = true;
859 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
860 }
mflodman949c2f02015-10-16 02:31:11 -0700861
perkj26091b12016-09-01 01:17:40 -0700862 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
863 const std::string& extension = config_->rtp.extensions[i].uri;
864 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200865 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700866 RTC_DCHECK_GE(id, 1);
867 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100868 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
869 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
Ying Wang3b790f32018-01-19 17:58:57 +0100890 fec_controller_->SetProtectionCallback(this);
891 // Signal congestion controller this object is ready for OnPacket* callbacks.
Ying Wang8ed653d2018-01-23 16:37:22 +0100892 if (fec_controller_->UseLossVectorMask()) {
893 transport_->send_side_cc()->RegisterPacketFeedbackObserver(this);
894 }
Ying Wang3b790f32018-01-19 17:58:57 +0100895
perkj26091b12016-09-01 01:17:40 -0700896 RTC_DCHECK(config_->encoder_settings.encoder);
897 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
898 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000899
mflodmancc3d4422017-08-03 08:27:51 -0700900 video_stream_encoder_->SetStartBitrate(
901 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700902
903 // Only request rotation at the source when we positively know that the remote
904 // side doesn't support the rotation extension. This allows us to prepare the
905 // encoder in the expectation that rotation is supported - which is the common
906 // case.
907 bool rotation_applied =
908 std::find_if(config_->rtp.extensions.begin(),
909 config_->rtp.extensions.end(),
910 [](const RtpExtension& extension) {
911 return extension.uri == RtpExtension::kVideoRotationUri;
912 }) == config_->rtp.extensions.end();
913
mflodmancc3d4422017-08-03 08:27:51 -0700914 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000915}
916
perkj26091b12016-09-01 01:17:40 -0700917void VideoSendStreamImpl::RegisterProcessThread(
918 ProcessThread* module_process_thread) {
919 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
920 RTC_DCHECK(!module_process_thread_);
921 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100922
perkj26091b12016-09-01 01:17:40 -0700923 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800924 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700925}
Peter Boströmca835252016-02-11 15:59:46 +0100926
perkj26091b12016-09-01 01:17:40 -0700927void VideoSendStreamImpl::DeRegisterProcessThread() {
928 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
929 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
930 module_process_thread_->DeRegisterModule(rtp_rtcp);
931}
Peter Boströma4c76882016-03-03 16:29:02 +0100932
perkj26091b12016-09-01 01:17:40 -0700933VideoSendStreamImpl::~VideoSendStreamImpl() {
934 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800935 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700936 << "VideoSendStreamImpl::Stop not called";
Mirko Bonadei675513b2017-11-09 11:09:25 +0100937 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
Ying Wang8ed653d2018-01-23 16:37:22 +0100938 if (fec_controller_->UseLossVectorMask()) {
939 transport_->send_side_cc()->DeRegisterPacketFeedbackObserver(this);
940 }
Per83d09102016-04-15 14:59:13 +0200941 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700942 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200943 delete rtp_rtcp;
944 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000945}
946
perkj26091b12016-09-01 01:17:40 -0700947bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
948 // Runs on a network thread.
949 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700950 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
951 rtp_rtcp->IncomingRtcpPacket(packet, length);
952 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000953}
954
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800955void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
956 const std::vector<bool> active_layers) {
957 RTC_DCHECK_RUN_ON(worker_queue_);
958 RTC_DCHECK_EQ(rtp_rtcp_modules_.size(), active_layers.size());
959 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
960 bool previously_active = payload_router_.IsActive();
961 payload_router_.SetActiveModules(active_layers);
962 if (!payload_router_.IsActive() && previously_active) {
963 // Payload router switched from active to inactive.
964 StopVideoSendStream();
965 } else if (payload_router_.IsActive() && !previously_active) {
966 // Payload router switched from inactive to active.
967 StartupVideoSendStream();
968 }
969}
970
perkj26091b12016-09-01 01:17:40 -0700971void VideoSendStreamImpl::Start() {
972 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100973 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800974 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100975 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200976 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800977 payload_router_.SetActive(true);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800978 StartupVideoSendStream();
979}
perkj26091b12016-09-01 01:17:40 -0700980
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800981void VideoSendStreamImpl::StartupVideoSendStream() {
982 RTC_DCHECK_RUN_ON(worker_queue_);
perkj26091b12016-09-01 01:17:40 -0700983 bitrate_allocator_->AddObserver(
984 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200985 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800986 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700987 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700988 {
perkj26091b12016-09-01 01:17:40 -0700989 rtc::CritScope lock(&encoder_activity_crit_sect_);
990 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700991 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700992 worker_queue_->PostDelayedTask(
993 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
994 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700995 }
perkj26091b12016-09-01 01:17:40 -0700996
mflodmancc3d4422017-08-03 08:27:51 -0700997 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000998}
999
perkj26091b12016-09-01 01:17:40 -07001000void VideoSendStreamImpl::Stop() {
1001 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +01001002 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -08001003 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +01001004 return;
Peter Boströmdabc9442016-04-11 11:45:14 +02001005 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -08001006 payload_router_.SetActive(false);
Seth Hampsoncc7125f2018-02-02 08:46:16 -08001007 StopVideoSendStream();
1008}
1009
1010void VideoSendStreamImpl::StopVideoSendStream() {
perkj26091b12016-09-01 01:17:40 -07001011 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -07001012 {
perkj26091b12016-09-01 01:17:40 -07001013 rtc::CritScope lock(&encoder_activity_crit_sect_);
1014 check_encoder_activity_task_->Stop();
1015 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -07001016 }
mflodmancc3d4422017-08-03 08:27:51 -07001017 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -07001018 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001019}
1020
perkj26091b12016-09-01 01:17:40 -07001021void VideoSendStreamImpl::SignalEncoderTimedOut() {
1022 RTC_DCHECK_RUN_ON(worker_queue_);
1023 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
1024 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
1025 // if a camera stops producing frames.
1026 if (encoder_target_rate_bps_ > 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001027 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
perkj26091b12016-09-01 01:17:40 -07001028 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +01001029 }
1030}
1031
sprang1a646ee2016-12-01 06:34:11 -08001032void VideoSendStreamImpl::OnBitrateAllocationUpdated(
1033 const BitrateAllocation& allocation) {
1034 payload_router_.OnBitrateAllocationUpdated(allocation);
1035}
1036
perkj26091b12016-09-01 01:17:40 -07001037void VideoSendStreamImpl::SignalEncoderActive() {
1038 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +01001039 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
perkj26091b12016-09-01 01:17:40 -07001040 bitrate_allocator_->AddObserver(
1041 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +02001042 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -08001043 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -07001044}
1045
Per512ecb32016-09-23 15:52:06 +02001046void VideoSendStreamImpl::OnEncoderConfigurationChanged(
1047 std::vector<VideoStream> streams,
1048 int min_transmit_bitrate_bps) {
1049 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +02001050 worker_queue_->PostTask(
1051 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -07001052 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +02001053 return;
1054 }
1055 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
1056 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
1057 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -07001058 RTC_DCHECK_RUN_ON(worker_queue_);
1059
perkj26091b12016-09-01 01:17:40 -07001060 encoder_min_bitrate_bps_ =
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +01001061 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
perkj26091b12016-09-01 01:17:40 -07001062 encoder_max_bitrate_bps_ = 0;
Seth Hampson24722b32017-12-22 09:36:42 -08001063 double stream_bitrate_priority_sum = 0;
1064 for (const auto& stream : streams) {
Seth Hampson46e31ba2018-01-18 10:39:54 -08001065 // We don't want to allocate more bitrate than needed to inactive streams.
1066 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
Seth Hampson24722b32017-12-22 09:36:42 -08001067 if (stream.bitrate_priority) {
1068 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
1069 stream_bitrate_priority_sum += *stream.bitrate_priority;
1070 }
1071 }
1072 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
1073 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
Seth Hampson46e31ba2018-01-18 10:39:54 -08001074 encoder_max_bitrate_bps_ =
1075 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
1076 encoder_max_bitrate_bps_);
Per512ecb32016-09-23 15:52:06 +02001077 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
1078 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -07001079
1080 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +02001081 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -07001082 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001083 }
perkj26091b12016-09-01 01:17:40 -07001084
1085 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +02001086 streams.back().temporal_layer_thresholds_bps.size() + 1;
Ying Wang3b790f32018-01-19 17:58:57 +01001087 fec_controller_->SetEncodingData(streams[0].width, streams[0].height,
1088 number_of_temporal_layers,
1089 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -07001090
sprang1a646ee2016-12-01 06:34:11 -08001091 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -07001092 // The send stream is started already. Update the allocator with new bitrate
1093 // limits.
1094 bitrate_allocator_->AddObserver(
1095 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +02001096 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -08001097 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -07001098 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001099}
1100
perkj26091b12016-09-01 01:17:40 -07001101EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001102 const EncodedImage& encoded_image,
1103 const CodecSpecificInfo* codec_specific_info,
1104 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -07001105 // Encoded is called on whatever thread the real encoder implementation run
1106 // on. In the case of hardware encoders, there might be several encoders
1107 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -08001108 size_t simulcast_idx = 0;
1109 if (codec_specific_info->codecType == kVideoCodecVP8) {
1110 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
1111 }
perkj26091b12016-09-01 01:17:40 -07001112 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -08001113 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
1114 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
1115 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -07001116 }
perkj26091b12016-09-01 01:17:40 -07001117 {
1118 rtc::CritScope lock(&encoder_activity_crit_sect_);
1119 if (check_encoder_activity_task_)
1120 check_encoder_activity_task_->UpdateEncoderActivity();
1121 }
sergeyu37ad3372016-06-14 15:29:37 -07001122
Ying Wang3b790f32018-01-19 17:58:57 +01001123 fec_controller_->UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001124 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001125 encoded_image, codec_specific_info, fragmentation);
1126
palmkviste75f2042016-09-28 06:19:48 -07001127 RTC_DCHECK(codec_specific_info);
1128
1129 int layer = codec_specific_info->codecType == kVideoCodecVP8
1130 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1131 : 0;
1132 {
1133 rtc::CritScope lock(&ivf_writers_crit_);
1134 if (file_writers_[layer].get()) {
1135 bool ok = file_writers_[layer]->WriteFrame(
1136 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001137 RTC_DCHECK(ok);
1138 }
1139 }
1140
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001141 return result;
perkjbc75d972016-05-02 06:31:25 -07001142}
1143
perkj26091b12016-09-01 01:17:40 -07001144void VideoSendStreamImpl::ConfigureProtection() {
1145 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001146
brandtre950cad2016-11-15 05:25:41 -08001147 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1148 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1149
1150 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001151 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1152 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001153 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001154
1155 // Shorthands.
1156 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001157 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001158 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1159 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1160
stefan60e10c72017-08-23 10:40:00 -07001161 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001162 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
stefan60e10c72017-08-23 10:40:00 -07001163 DisableUlpfec();
1164 }
1165
brandtre950cad2016-11-15 05:25:41 -08001166 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1167 if (flexfec_enabled) {
1168 // We can safely disable RED here, because if the remote supports FlexFEC,
1169 // we know that it has a receiver without the RED/RTX workaround.
1170 // See http://crbug.com/webrtc/6650 for more information.
1171 if (IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001172 RTC_LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
brandtre950cad2016-11-15 05:25:41 -08001173 DisableRed();
1174 }
1175 if (IsUlpfecEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001176 RTC_LOG(LS_INFO)
brandtre950cad2016-11-15 05:25:41 -08001177 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1178 DisableUlpfec();
1179 }
1180 }
1181
Per83d09102016-04-15 14:59:13 +02001182 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001183 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1184 // is a waste of bandwidth since FEC packets still have to be transmitted.
1185 // Note that this is not the case with FlexFEC.
1186 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001187 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001188 config_->encoder_settings.payload_name)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001189 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001190 << "Transmitting payload type without picture ID using "
1191 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1192 "also have to be retransmitted. Disabling ULPFEC.";
1193 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001194 }
1195
brandtre6f98c72016-11-11 03:28:30 -08001196 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001197 //
brandtre6f98c72016-11-11 03:28:30 -08001198 // Due to how old receivers work, we need to always send RED if it has been
1199 // negotiated. This is a remnant of an old RED/RTX workaround, see
1200 // https://codereview.webrtc.org/2469093003.
1201 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1202 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1203 // no point in using RED without ULPFEC.
1204 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001205 RTC_DCHECK_GE(red_payload_type, 0);
1206 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001207 }
brandtre6f98c72016-11-11 03:28:30 -08001208 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001209 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1210 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001211 if (!IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001212 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001213 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1214 DisableUlpfec();
1215 }
Per83d09102016-04-15 14:59:13 +02001216 }
1217
1218 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1219 // Set NACK.
1220 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001221 true,
Per83d09102016-04-15 14:59:13 +02001222 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001223 // Set RED/ULPFEC information.
stefan60e10c72017-08-23 10:40:00 -07001224 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001225 }
1226
brandtre950cad2016-11-15 05:25:41 -08001227 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1228 // so enable that logic if either of those FEC schemes are enabled.
Ying Wang3b790f32018-01-19 17:58:57 +01001229 fec_controller_->SetProtectionMethod(flexfec_enabled || IsUlpfecEnabled(),
1230 nack_enabled);
Per83d09102016-04-15 14:59:13 +02001231}
1232
perkj26091b12016-09-01 01:17:40 -07001233void VideoSendStreamImpl::ConfigureSsrcs() {
1234 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001235 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001236 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1237 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001238 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1239 rtp_rtcp->SetSSRC(ssrc);
1240
1241 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001242 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001243 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001244 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001245 }
1246
Peter Boström723ead82016-02-22 15:14:01 +01001247 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001248 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001249 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001250
Peter Boström723ead82016-02-22 15:14:01 +01001251 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001252 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1253 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1254 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001255 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1256 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001257 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001258 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001259 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001260 }
1261
Peter Boström723ead82016-02-22 15:14:01 +01001262 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001263 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001264 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001265 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1266 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001267 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1268 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001269 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1270 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001271 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001272 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1273 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001274 }
Stefan Holmer10880012016-02-03 13:29:59 +01001275 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001276}
1277
perkj26091b12016-09-01 01:17:40 -07001278std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1279 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001280 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001281
perkj26091b12016-09-01 01:17:40 -07001282 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1283 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001284 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1285 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001286 }
1287
perkj26091b12016-09-01 01:17:40 -07001288 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1289 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001290 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001291 }
1292
brandtr48d21a22017-05-30 02:32:12 -07001293 if (flexfec_sender_) {
1294 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1295 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1296 }
1297
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001298 return rtp_states;
1299}
1300
Ã…sa Persson4bece9a2017-10-06 10:04:04 +02001301std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
1302 const {
1303 RTC_DCHECK_RUN_ON(worker_queue_);
1304 return payload_router_.GetRtpPayloadStates();
1305}
1306
perkj26091b12016-09-01 01:17:40 -07001307void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1308 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001309 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001310 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001311 : RtcpMode::kOff);
1312 }
1313}
1314
perkj26091b12016-09-01 01:17:40 -07001315uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1316 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001317 int64_t rtt,
1318 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001319 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001320 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001321 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001322
michaelt192132e2017-01-26 09:05:27 -08001323 // Substract overhead from bitrate.
1324 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001325 uint32_t payload_bitrate_bps = bitrate_bps;
1326 if (send_side_bwe_with_overhead_) {
1327 payload_bitrate_bps -= CalculateOverheadRateBps(
1328 CalculatePacketRate(bitrate_bps,
1329 config_->rtp.max_packet_size +
1330 transport_overhead_bytes_per_packet_),
1331 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1332 bitrate_bps);
1333 }
michaelta3328772016-11-29 09:25:03 -08001334
Per69b332d2016-06-02 15:45:42 +02001335 // Get the encoder target rate. It is the estimated network rate -
1336 // protection overhead.
Ying Wang3b790f32018-01-19 17:58:57 +01001337 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
michaelt192132e2017-01-26 09:05:27 -08001338 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
Ying Wang3b790f32018-01-19 17:58:57 +01001339 loss_mask_vector_, rtt);
1340 loss_mask_vector_.clear();
michaelt192132e2017-01-26 09:05:27 -08001341
elad.alon0fe12162017-01-31 05:48:37 -08001342 uint32_t encoder_overhead_rate_bps =
1343 send_side_bwe_with_overhead_
1344 ? CalculateOverheadRateBps(
1345 CalculatePacketRate(encoder_target_rate_bps_,
1346 config_->rtp.max_packet_size +
1347 transport_overhead_bytes_per_packet_ -
1348 overhead_bytes_per_packet_),
1349 overhead_bytes_per_packet_ +
1350 transport_overhead_bytes_per_packet_,
1351 bitrate_bps - encoder_target_rate_bps_)
1352 : 0;
michaelt192132e2017-01-26 09:05:27 -08001353
1354 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1355 // protection_bitrate includes overhead.
1356 uint32_t protection_bitrate =
1357 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001358
perkj26091b12016-09-01 01:17:40 -07001359 encoder_target_rate_bps_ =
1360 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001361 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1362 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001363 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001364 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001365}
1366
palmkviste75f2042016-09-28 06:19:48 -07001367void VideoSendStreamImpl::EnableEncodedFrameRecording(
1368 const std::vector<rtc::PlatformFile>& files,
1369 size_t byte_limit) {
1370 {
1371 rtc::CritScope lock(&ivf_writers_crit_);
1372 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1373 if (i < files.size()) {
1374 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1375 } else {
1376 file_writers_[i].reset();
1377 }
1378 }
1379 }
1380
1381 if (!files.empty()) {
1382 // Make a keyframe appear as early as possible in the logs, to give actually
1383 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001384 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001385 }
1386}
1387
perkj26091b12016-09-01 01:17:40 -07001388int VideoSendStreamImpl::ProtectionRequest(
1389 const FecProtectionParams* delta_params,
1390 const FecProtectionParams* key_params,
1391 uint32_t* sent_video_rate_bps,
1392 uint32_t* sent_nack_rate_bps,
1393 uint32_t* sent_fec_rate_bps) {
1394 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001395 *sent_video_rate_bps = 0;
1396 *sent_nack_rate_bps = 0;
1397 *sent_fec_rate_bps = 0;
1398 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1399 uint32_t not_used = 0;
1400 uint32_t module_video_rate = 0;
1401 uint32_t module_fec_rate = 0;
1402 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001403 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001404 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1405 &module_nack_rate);
1406 *sent_video_rate_bps += module_video_rate;
1407 *sent_nack_rate_bps += module_nack_rate;
1408 *sent_fec_rate_bps += module_fec_rate;
1409 }
1410 return 0;
1411}
1412
michaelta3328772016-11-29 09:25:03 -08001413void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1414 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1415 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1416}
1417
michaelt79e05882016-11-08 02:50:09 -08001418void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001419 size_t transport_overhead_bytes_per_packet) {
1420 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001421 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
nisse284542b2017-01-10 08:58:32 -08001422 return;
1423 }
1424
michaelta3328772016-11-29 09:25:03 -08001425 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001426
nisseb8f9a322017-03-27 05:36:15 -07001427 transport_->send_side_cc()->SetTransportOverhead(
1428 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001429
1430 size_t rtp_packet_size =
1431 std::min(config_->rtp.max_packet_size,
1432 kPathMTU - transport_overhead_bytes_per_packet_);
1433
michaelta3328772016-11-29 09:25:03 -08001434 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001435 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001436 }
michaelt79e05882016-11-08 02:50:09 -08001437}
1438
Ying Wang3b790f32018-01-19 17:58:57 +01001439void VideoSendStreamImpl::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
1440 if (!worker_queue_->IsCurrent()) {
1441 auto ptr = weak_ptr_;
1442 worker_queue_->PostTask([=] {
1443 if (!ptr.get())
1444 return;
1445 ptr->OnPacketAdded(ssrc, seq_num);
1446 });
1447 return;
1448 }
1449 const auto ssrcs = config_->rtp.ssrcs;
1450 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
1451 feedback_packet_seq_num_set_.insert(seq_num);
1452 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
1453 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
1454 "max size', will get reset.";
1455 feedback_packet_seq_num_set_.clear();
1456 }
1457 }
1458}
1459
1460void VideoSendStreamImpl::OnPacketFeedbackVector(
1461 const std::vector<PacketFeedback>& packet_feedback_vector) {
1462 if (!worker_queue_->IsCurrent()) {
1463 auto ptr = weak_ptr_;
1464 worker_queue_->PostTask([=] {
1465 if (!ptr.get())
1466 return;
1467 ptr->OnPacketFeedbackVector(packet_feedback_vector);
1468 });
1469 return;
1470 }
1471 // Lost feedbacks are not considered to be lost packets.
1472 for (const PacketFeedback& packet : packet_feedback_vector) {
1473 if (auto it = feedback_packet_seq_num_set_.find(packet.sequence_number) !=
1474 feedback_packet_seq_num_set_.end()) {
1475 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
1476 loss_mask_vector_.push_back(lost);
1477 feedback_packet_seq_num_set_.erase(it);
1478 }
1479 }
1480}
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001481} // namespace internal
1482} // namespace webrtc