blob: 6790e60b64278e35c7e3b254f58155aad2a67aaf [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"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020025#include "modules/pacing/packet_router.h"
26#include "modules/rtp_rtcp/include/rtp_rtcp.h"
27#include "modules/rtp_rtcp/source/rtp_sender.h"
28#include "modules/utility/include/process_thread.h"
Ying Wang3b790f32018-01-19 17:58:57 +010029#include "modules/video_coding/fec_controller_default.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020030#include "modules/video_coding/utility/ivf_file_writer.h"
31#include "rtc_base/checks.h"
Sebastian Janssoncabe3832018-01-12 10:54:18 +010032#include "rtc_base/experiments/alr_experiment.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020033#include "rtc_base/file.h"
34#include "rtc_base/location.h"
35#include "rtc_base/logging.h"
36#include "rtc_base/trace_event.h"
37#include "rtc_base/weak_ptr.h"
38#include "system_wrappers/include/field_trial.h"
39#include "video/call_stats.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;
Ying Wang3b790f32018-01-19 17:58:57 +010044static const int kSendSideSeqNumSetMaxSize = 15000;
45
Per83d09102016-04-15 14:59:13 +020046namespace {
47
nisse284542b2017-01-10 08:58:32 -080048// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
49const size_t kPathMTU = 1500;
50
Per83d09102016-04-15 14:59:13 +020051std::vector<RtpRtcp*> CreateRtpRtcpModules(
Danil Chapovalov45d725d2018-02-19 19:09:53 +010052 const VideoSendStream::Config& config,
Per83d09102016-04-15 14:59:13 +020053 RtcpIntraFrameObserver* intra_frame_callback,
54 RtcpBandwidthObserver* bandwidth_callback,
nisseb8f9a322017-03-27 05:36:15 -070055 RtpTransportControllerSendInterface* transport,
Per83d09102016-04-15 14:59:13 +020056 RtcpRttStats* rtt_stats,
brandtre950cad2016-11-15 05:25:41 -080057 FlexfecSender* flexfec_sender,
Per83d09102016-04-15 14:59:13 +020058 SendStatisticsProxy* stats_proxy,
asapersson35151f32016-05-02 23:44:01 -070059 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -070060 RtcEventLog* event_log,
sprangcd349d92016-07-13 09:11:28 -070061 RateLimiter* retransmission_rate_limiter,
michaelta3328772016-11-29 09:25:03 -080062 OverheadObserver* overhead_observer,
Danil Chapovalov45d725d2018-02-19 19:09:53 +010063 RtpKeepAliveConfig keepalive_config) {
64 RTC_DCHECK_GT(config.rtp.ssrcs.size(), 0);
Per83d09102016-04-15 14:59:13 +020065 RtpRtcp::Configuration configuration;
Per83d09102016-04-15 14:59:13 +020066 configuration.audio = false;
67 configuration.receiver_only = false;
Danil Chapovalov45d725d2018-02-19 19:09:53 +010068 configuration.outgoing_transport = config.send_transport;
Per83d09102016-04-15 14:59:13 +020069 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;
Danil Chapovalov45d725d2018-02-19 19:09:53 +010086 configuration.rtcp_interval_config.video_interval_ms =
87 config.rtcp.video_report_interval_ms;
88 configuration.rtcp_interval_config.audio_interval_ms =
89 config.rtcp.audio_report_interval_ms;
Per83d09102016-04-15 14:59:13 +020090 std::vector<RtpRtcp*> modules;
Danil Chapovalov45d725d2018-02-19 19:09:53 +010091 const std::vector<uint32_t>& flexfec_protected_ssrcs =
92 config.rtp.flexfec.protected_media_ssrcs;
93 for (uint32_t ssrc : config.rtp.ssrcs) {
94 bool enable_flexfec = flexfec_sender != nullptr &&
95 std::find(flexfec_protected_ssrcs.begin(),
96 flexfec_protected_ssrcs.end(),
97 ssrc) != flexfec_protected_ssrcs.end();
98 configuration.flexfec_sender = enable_flexfec ? flexfec_sender : nullptr;
Per83d09102016-04-15 14:59:13 +020099 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
100 rtp_rtcp->SetSendingStatus(false);
101 rtp_rtcp->SetSendingMediaStatus(false);
102 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
103 modules.push_back(rtp_rtcp);
104 }
105 return modules;
106}
107
brandtre950cad2016-11-15 05:25:41 -0800108// TODO(brandtr): Update this function when we support multistream protection.
109std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
brandtr48d21a22017-05-30 02:32:12 -0700110 const VideoSendStream::Config& config,
111 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
brandtr3d200bd2017-01-16 06:59:19 -0800112 if (config.rtp.flexfec.payload_type < 0) {
brandtre950cad2016-11-15 05:25:41 -0800113 return nullptr;
114 }
brandtr3d200bd2017-01-16 06:59:19 -0800115 RTC_DCHECK_GE(config.rtp.flexfec.payload_type, 0);
116 RTC_DCHECK_LE(config.rtp.flexfec.payload_type, 127);
117 if (config.rtp.flexfec.ssrc == 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100118 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
119 "Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800120 return nullptr;
121 }
122 if (config.rtp.flexfec.protected_media_ssrcs.empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100123 RTC_LOG(LS_WARNING)
124 << "FlexFEC is enabled, but no protected media SSRC given. "
125 "Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800126 return nullptr;
127 }
128
brandtre950cad2016-11-15 05:25:41 -0800129 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100130 RTC_LOG(LS_WARNING)
brandtre950cad2016-11-15 05:25:41 -0800131 << "The supplied FlexfecConfig contained multiple protected "
132 "media streams, but our implementation currently only "
133 "supports protecting a single media stream. "
134 "To avoid confusion, disabling FlexFEC completely.";
135 return nullptr;
136 }
137
brandtr48d21a22017-05-30 02:32:12 -0700138 const RtpState* rtp_state = nullptr;
139 auto it = suspended_ssrcs.find(config.rtp.flexfec.ssrc);
140 if (it != suspended_ssrcs.end()) {
141 rtp_state = &it->second;
142 }
143
brandtre950cad2016-11-15 05:25:41 -0800144 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
145 return std::unique_ptr<FlexfecSender>(new FlexfecSender(
brandtr3d200bd2017-01-16 06:59:19 -0800146 config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc,
brandtre950cad2016-11-15 05:25:41 -0800147 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions,
brandtr48d21a22017-05-30 02:32:12 -0700148 RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock()));
brandtre950cad2016-11-15 05:25:41 -0800149}
150
Erik Språng7c8cca32017-10-24 17:05:18 +0200151bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
152 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
153 return std::find_if(
154 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
155 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
156 }) != extensions.end();
157}
Peter Boströme4499152016-02-05 11:13:28 +0100158
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100159const char kForcedFallbackFieldTrial[] =
160 "WebRTC-VP8-Forced-Fallback-Encoder-v2";
161
162rtc::Optional<int> GetFallbackMinBpsFromFieldTrial() {
163 if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100164 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100165
166 std::string group =
167 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
168 if (group.empty())
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100169 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100170
171 int min_pixels;
172 int max_pixels;
173 int min_bps;
174 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
175 &min_bps) != 3) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100176 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100177 }
178
179 if (min_bps <= 0)
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100180 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100181
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100182 return min_bps;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100183}
184
185int GetEncoderMinBitrateBps() {
186 const int kDefaultEncoderMinBitrateBps = 30000;
187 return GetFallbackMinBpsFromFieldTrial().value_or(
188 kDefaultEncoderMinBitrateBps);
189}
190
Peter Boström39593972016-02-15 11:27:15 +0100191bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
kthelgason1cdddc92017-08-24 03:52:48 -0700192 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
193 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
perkj26091b12016-09-01 01:17:40 -0700194 return true;
deadbeefc964d0b2017-04-03 10:03:35 -0700195 }
Peter Boström39593972016-02-15 11:27:15 +0100196 return false;
197}
198
Per512ecb32016-09-23 15:52:06 +0200199int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
200 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700201 bool pad_to_min_bitrate) {
202 int pad_up_to_bitrate_bps = 0;
203 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200204 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700205 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200206 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700207 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200208 for (size_t i = 0; i < streams.size() - 1; ++i)
209 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700210 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200211 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700212 }
213
214 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200215 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700216
217 return pad_up_to_bitrate_bps;
218}
219
michaelt192132e2017-01-26 09:05:27 -0800220uint32_t CalculateOverheadRateBps(int packets_per_second,
221 size_t overhead_bytes_per_packet,
222 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800223 uint32_t overhead_bps =
224 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
225 return std::min(overhead_bps, max_overhead_bps);
226}
227
228int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
229 size_t packet_size_bits = 8 * packet_size_bytes;
230 // Ceil for int value of bitrate_bps / packet_size_bits.
231 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
232 packet_size_bits);
233}
234
Niels Möller73f29cb2018-01-31 16:09:31 +0100235// TODO(pbos): Lower these thresholds (to closer to 100%) when we handle
236// pipelining encoders better (multiple input frames before something comes
237// out). This should effectively turn off CPU adaptations for systems that
238// remotely cope with the load right now.
239CpuOveruseOptions GetCpuOveruseOptions(const VideoSendStream::Config& config) {
240 CpuOveruseOptions options;
241
242 if (config.encoder_settings.full_overuse_time) {
243 options.low_encode_usage_threshold_percent = 150;
244 options.high_encode_usage_threshold_percent = 200;
245 }
246 if (config.encoder_settings.experiment_cpu_load_estimator) {
247 options.filter_time_ms = 5 * rtc::kNumMillisecsPerSec;
248 }
249
250 return options;
251}
252
Peter Boströme4499152016-02-05 11:13:28 +0100253} // namespace
254
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000255namespace internal {
perkj26091b12016-09-01 01:17:40 -0700256
257// VideoSendStreamImpl implements internal::VideoSendStream.
258// It is created and destroyed on |worker_queue|. The intent is to decrease the
259// need for locking and to ensure methods are called in sequence.
260// Public methods except |DeliverRtcp| must be called on |worker_queue|.
261// DeliverRtcp is called on the libjingle worker thread or a network thread.
262// An encoder may deliver frames through the EncodedImageCallback on an
263// arbitrary thread.
264class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800265 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700266 public webrtc::VCMProtectionCallback,
mflodmancc3d4422017-08-03 08:27:51 -0700267 public VideoStreamEncoder::EncoderSink,
Ying Wang3b790f32018-01-19 17:58:57 +0100268 public VideoBitrateAllocationObserver,
269 public webrtc::PacketFeedbackObserver {
perkj26091b12016-09-01 01:17:40 -0700270 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200271 VideoSendStreamImpl(
272 SendStatisticsProxy* stats_proxy,
273 rtc::TaskQueue* worker_queue,
274 CallStats* call_stats,
275 RtpTransportControllerSendInterface* transport,
276 BitrateAllocator* bitrate_allocator,
277 SendDelayStats* send_delay_stats,
278 VideoStreamEncoder* video_stream_encoder,
279 RtcEventLog* event_log,
280 const VideoSendStream::Config* config,
281 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800282 double initial_encoder_bitrate_priority,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200283 std::map<uint32_t, RtpState> suspended_ssrcs,
284 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
Ying Wang3b790f32018-01-19 17:58:57 +0100285 VideoEncoderConfig::ContentType content_type,
286 std::unique_ptr<FecController> fec_controller);
perkj26091b12016-09-01 01:17:40 -0700287 ~VideoSendStreamImpl() override;
288
289 // RegisterProcessThread register |module_process_thread| with those objects
290 // that use it. Registration has to happen on the thread were
291 // |module_process_thread| was created (libjingle's worker thread).
292 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
293 // maybe |worker_queue|.
294 void RegisterProcessThread(ProcessThread* module_process_thread);
295 void DeRegisterProcessThread();
296
297 void SignalNetworkState(NetworkState state);
298 bool DeliverRtcp(const uint8_t* packet, size_t length);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800299 void UpdateActiveSimulcastLayers(const std::vector<bool> active_layers);
perkj26091b12016-09-01 01:17:40 -0700300 void Start();
301 void Stop();
302
perkj26091b12016-09-01 01:17:40 -0700303 VideoSendStream::RtpStateMap GetRtpStates() const;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200304 VideoSendStream::RtpPayloadStateMap GetRtpPayloadStates() const;
perkj26091b12016-09-01 01:17:40 -0700305
palmkviste75f2042016-09-28 06:19:48 -0700306 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
307 size_t byte_limit);
308
nisse284542b2017-01-10 08:58:32 -0800309 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800310
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100311 rtc::Optional<float> configured_pacing_factor_;
312
Ying Wang3b790f32018-01-19 17:58:57 +0100313 // From PacketFeedbackObserver.
314 void OnPacketAdded(uint32_t ssrc, uint16_t seq_num) override;
315 void OnPacketFeedbackVector(
316 const std::vector<PacketFeedback>& packet_feedback_vector) override;
317
perkj26091b12016-09-01 01:17:40 -0700318 private:
319 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200320 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700321
322 // Implements BitrateAllocatorObserver.
323 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
324 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800325 int64_t rtt,
326 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700327
328 // Implements webrtc::VCMProtectionCallback.
329 int ProtectionRequest(const FecProtectionParams* delta_params,
330 const FecProtectionParams* key_params,
331 uint32_t* sent_video_rate_bps,
332 uint32_t* sent_nack_rate_bps,
333 uint32_t* sent_fec_rate_bps) override;
334
michaelta3328772016-11-29 09:25:03 -0800335 // Implements OverheadObserver.
336 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
337
Per512ecb32016-09-23 15:52:06 +0200338 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
339 int min_transmit_bitrate_bps) override;
340
perkj26091b12016-09-01 01:17:40 -0700341 // Implements EncodedImageCallback. The implementation routes encoded frames
342 // to the |payload_router_| and |config.pre_encode_callback| if set.
343 // Called on an arbitrary encoder callback thread.
344 EncodedImageCallback::Result OnEncodedImage(
345 const EncodedImage& encoded_image,
346 const CodecSpecificInfo* codec_specific_info,
347 const RTPFragmentationHeader* fragmentation) override;
348
sprang1a646ee2016-12-01 06:34:11 -0800349 // Implements VideoBitrateAllocationObserver.
350 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
351
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800352 // Starts monitoring and sends a keyframe.
353 void StartupVideoSendStream();
354 // Removes the bitrate observer, stops monitoring and notifies the video
355 // encoder of the bitrate update.
356 void StopVideoSendStream();
357
perkj26091b12016-09-01 01:17:40 -0700358 void ConfigureProtection();
359 void ConfigureSsrcs();
360 void SignalEncoderTimedOut();
361 void SignalEncoderActive();
362
elad.alon0fe12162017-01-31 05:48:37 -0800363 const bool send_side_bwe_with_overhead_;
Ying Wang38a31b02017-12-21 12:26:19 +0000364
perkj26091b12016-09-01 01:17:40 -0700365 SendStatisticsProxy* const stats_proxy_;
366 const VideoSendStream::Config* const config_;
367 std::map<uint32_t, RtpState> suspended_ssrcs_;
368
Ying Wang3b790f32018-01-19 17:58:57 +0100369 std::unique_ptr<FecController> fec_controller_;
perkj26091b12016-09-01 01:17:40 -0700370 ProcessThread* module_process_thread_;
371 rtc::ThreadChecker module_process_thread_checker_;
372 rtc::TaskQueue* const worker_queue_;
373
374 rtc::CriticalSection encoder_activity_crit_sect_;
375 CheckEncoderActivityTask* check_encoder_activity_task_
danilchapa37de392017-09-09 04:17:22 -0700376 RTC_GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200377
perkj26091b12016-09-01 01:17:40 -0700378 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700379 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700380 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700381
brandtr3b941be2017-03-17 07:02:46 -0700382 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800383 std::unique_ptr<FlexfecSender> flexfec_sender_;
384
palmkviste75f2042016-09-28 06:19:48 -0700385 rtc::CriticalSection ivf_writers_crit_;
danilchapa37de392017-09-09 04:17:22 -0700386 std::unique_ptr<IvfFileWriter>
387 file_writers_[kMaxSimulcastStreams] RTC_GUARDED_BY(ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700388
389 int max_padding_bitrate_;
390 int encoder_min_bitrate_bps_;
391 uint32_t encoder_max_bitrate_bps_;
392 uint32_t encoder_target_rate_bps_;
Seth Hampson24722b32017-12-22 09:36:42 -0800393 double encoder_bitrate_priority_;
perkj26091b12016-09-01 01:17:40 -0700394
mflodmancc3d4422017-08-03 08:27:51 -0700395 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700396 EncoderRtcpFeedback encoder_feedback_;
perkj26091b12016-09-01 01:17:40 -0700397
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100398 RtcpBandwidthObserver* const bandwidth_observer_;
perkj26091b12016-09-01 01:17:40 -0700399 // RtpRtcp modules, declared here as they use other members on construction.
400 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
401 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700402
403 // |weak_ptr_| to our self. This is used since we can not call
404 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
405 // an existing WeakPtr.
406 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
407 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
408 // invalidated before any other members are destroyed.
409 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800410
411 rtc::CriticalSection overhead_bytes_per_packet_crit_;
danilchapa37de392017-09-09 04:17:22 -0700412 size_t overhead_bytes_per_packet_
413 RTC_GUARDED_BY(overhead_bytes_per_packet_crit_);
michaelta3328772016-11-29 09:25:03 -0800414 size_t transport_overhead_bytes_per_packet_;
Ying Wang3b790f32018-01-19 17:58:57 +0100415
416 std::set<uint16_t> feedback_packet_seq_num_set_;
417 std::vector<bool> loss_mask_vector_;
perkj26091b12016-09-01 01:17:40 -0700418};
419
perkj26091b12016-09-01 01:17:40 -0700420class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
421 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200422 DestructAndGetRtpStateTask(
423 VideoSendStream::RtpStateMap* state_map,
424 VideoSendStream::RtpPayloadStateMap* payload_state_map,
425 std::unique_ptr<VideoSendStreamImpl> send_stream,
426 rtc::Event* done_event)
perkj26091b12016-09-01 01:17:40 -0700427 : state_map_(state_map),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200428 payload_state_map_(payload_state_map),
perkj26091b12016-09-01 01:17:40 -0700429 send_stream_(std::move(send_stream)),
430 done_event_(done_event) {}
431
432 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
433
434 private:
435 bool Run() override {
436 send_stream_->Stop();
437 *state_map_ = send_stream_->GetRtpStates();
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200438 *payload_state_map_ = send_stream_->GetRtpPayloadStates();
perkj26091b12016-09-01 01:17:40 -0700439 send_stream_.reset();
440 done_event_->Set();
441 return true;
442 }
443
444 VideoSendStream::RtpStateMap* state_map_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200445 VideoSendStream::RtpPayloadStateMap* payload_state_map_;
perkj26091b12016-09-01 01:17:40 -0700446 std::unique_ptr<VideoSendStreamImpl> send_stream_;
447 rtc::Event* done_event_;
448};
449
450// CheckEncoderActivityTask is used for tracking when the encoder last produced
451// and encoded video frame. If the encoder has not produced anything the last
452// kEncoderTimeOutMs we also want to stop sending padding.
453class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
454 public:
455 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700456 explicit CheckEncoderActivityTask(
457 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
458 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700459
460 void Stop() {
461 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700462 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700463 }
464
465 void UpdateEncoderActivity() {
466 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
467 // whatever thread the real encoder implementation run on. In the case of
468 // hardware encoders, there might be several encoders
469 // running in parallel on different threads.
470 rtc::AtomicOps::ReleaseStore(&activity_, 1);
471 }
472
473 private:
474 bool Run() override {
475 RTC_CHECK(task_checker_.CalledSequentially());
476 if (!send_stream_)
477 return true;
478 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
479 if (!timed_out_) {
480 send_stream_->SignalEncoderTimedOut();
481 }
482 timed_out_ = true;
483 } else if (timed_out_) {
484 send_stream_->SignalEncoderActive();
485 timed_out_ = false;
486 }
487 rtc::AtomicOps::ReleaseStore(&activity_, 0);
488
489 rtc::TaskQueue::Current()->PostDelayedTask(
490 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
491 // Return false to prevent this task from being deleted. Ownership has been
492 // transferred to the task queue when PostDelayedTask was called.
493 return false;
494 }
495 volatile int activity_;
496
497 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700498 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700499 bool timed_out_;
500};
501
Per512ecb32016-09-23 15:52:06 +0200502class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700503 public:
perkj8ff860a2016-10-03 00:30:04 -0700504 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200505 std::vector<VideoStream> streams,
506 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700507 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200508 streams_(std::move(streams)),
509 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700510
511 private:
512 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700513 if (send_stream_)
514 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
515 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700516 return true;
517 }
518
perkj8ff860a2016-10-03 00:30:04 -0700519 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200520 std::vector<VideoStream> streams_;
521 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700522};
523
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000524VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200525 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200526 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700527 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200528 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700529 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800530 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700531 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700532 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700533 VideoSendStream::Config config,
534 VideoEncoderConfig encoder_config,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200535 const std::map<uint32_t, RtpState>& suspended_ssrcs,
Ying Wang3b790f32018-01-19 17:58:57 +0100536 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
537 std::unique_ptr<FecController> fec_controller)
perkj26091b12016-09-01 01:17:40 -0700538 : worker_queue_(worker_queue),
539 thread_sync_event_(false /* manual_reset */, false),
540 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800541 config,
542 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800543 config_(std::move(config)),
544 content_type_(encoder_config.content_type) {
Niels Möller73f29cb2018-01-31 16:09:31 +0100545 video_stream_encoder_ = rtc::MakeUnique<VideoStreamEncoder>(
546 num_cpu_cores, &stats_proxy_,
547 config_.encoder_settings,
548 config_.pre_encode_callback,
549 rtc::MakeUnique<OveruseFrameDetector>(
550 GetCpuOveruseOptions(config_), &stats_proxy_));
Sebastian Jansson06b83aa2018-02-28 13:03:46 +0100551 // TODO(srte): Initialization should not be done posted on a task queue.
552 // Note that the posted task must not outlive this scope since the closure
553 // references local variables.
554 worker_queue_->PostTask(rtc::NewClosure(
555 [this, call_stats, transport, bitrate_allocator, send_delay_stats,
556 event_log, &suspended_ssrcs, &encoder_config, &suspended_payload_states,
557 &fec_controller]() {
558 send_stream_.reset(new VideoSendStreamImpl(
559 &stats_proxy_, worker_queue_, call_stats, transport,
560 bitrate_allocator, send_delay_stats, video_stream_encoder_.get(),
561 event_log, &config_, encoder_config.max_bitrate_bps,
562 encoder_config.bitrate_priority, suspended_ssrcs,
563 suspended_payload_states, encoder_config.content_type,
564 std::move(fec_controller)));
565 },
566 [this]() { thread_sync_event_.Set(); }));
perkj26091b12016-09-01 01:17:40 -0700567
568 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
569 // |module_process_thread| must be registered and deregistered on the thread
570 // it was created on.
571 thread_sync_event_.Wait(rtc::Event::kForever);
572 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800573 // TODO(sprang): Enable this also for regular video calls if it works well.
574 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
575 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700576 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800577 }
Ying Wang38a31b02017-12-21 12:26:19 +0000578
perkj26091b12016-09-01 01:17:40 -0700579 ReconfigureVideoEncoder(std::move(encoder_config));
580}
581
582VideoSendStream::~VideoSendStream() {
583 RTC_DCHECK_RUN_ON(&thread_checker_);
584 RTC_DCHECK(!send_stream_);
585}
586
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800587void VideoSendStream::UpdateActiveSimulcastLayers(
588 const std::vector<bool> active_layers) {
589 RTC_DCHECK_RUN_ON(&thread_checker_);
590 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
591 VideoSendStreamImpl* send_stream = send_stream_.get();
592 worker_queue_->PostTask([this, send_stream, active_layers] {
593 send_stream->UpdateActiveSimulcastLayers(active_layers);
594 thread_sync_event_.Set();
595 });
596
597 thread_sync_event_.Wait(rtc::Event::kForever);
598}
599
perkj26091b12016-09-01 01:17:40 -0700600void VideoSendStream::Start() {
601 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100602 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 01:17:40 -0700603 VideoSendStreamImpl* send_stream = send_stream_.get();
604 worker_queue_->PostTask([this, send_stream] {
605 send_stream->Start();
606 thread_sync_event_.Set();
607 });
608
609 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700610 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
611 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700612 thread_sync_event_.Wait(rtc::Event::kForever);
613}
614
615void VideoSendStream::Stop() {
616 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100617 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 01:17:40 -0700618 VideoSendStreamImpl* send_stream = send_stream_.get();
619 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
620}
621
perkja49cbd32016-09-16 07:53:41 -0700622void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700623 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
624 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700625 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700626 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700627}
628
629void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700630 // TODO(perkj): Some test cases in VideoSendStreamTest call
631 // ReconfigureVideoEncoder from the network thread.
632 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800633 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700634 video_stream_encoder_->ConfigureEncoder(std::move(config),
635 config_.rtp.max_packet_size,
636 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700637}
638
639VideoSendStream::Stats VideoSendStream::GetStats() {
640 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
641 // a network thread. See comment in Call::GetStats().
642 // RTC_DCHECK_RUN_ON(&thread_checker_);
643 return stats_proxy_.GetStats();
644}
645
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100646rtc::Optional<float> VideoSendStream::GetPacingFactorOverride() const {
647 return send_stream_->configured_pacing_factor_;
648}
649
perkj26091b12016-09-01 01:17:40 -0700650void VideoSendStream::SignalNetworkState(NetworkState state) {
651 RTC_DCHECK_RUN_ON(&thread_checker_);
652 VideoSendStreamImpl* send_stream = send_stream_.get();
653 worker_queue_->PostTask(
654 [send_stream, state] { send_stream->SignalNetworkState(state); });
655}
656
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200657void VideoSendStream::StopPermanentlyAndGetRtpStates(
658 VideoSendStream::RtpStateMap* rtp_state_map,
659 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700660 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700661 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700662 send_stream_->DeRegisterProcessThread();
663 worker_queue_->PostTask(
664 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200665 rtp_state_map, payload_state_map, std::move(send_stream_),
666 &thread_sync_event_)));
perkj26091b12016-09-01 01:17:40 -0700667 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700668}
669
nisse284542b2017-01-10 08:58:32 -0800670void VideoSendStream::SetTransportOverhead(
671 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800672 RTC_DCHECK_RUN_ON(&thread_checker_);
673 VideoSendStreamImpl* send_stream = send_stream_.get();
674 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
675 send_stream->SetTransportOverhead(transport_overhead_per_packet);
676 });
677}
678
perkj26091b12016-09-01 01:17:40 -0700679bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
680 // Called on a network thread.
681 return send_stream_->DeliverRtcp(packet, length);
682}
683
palmkviste75f2042016-09-28 06:19:48 -0700684void VideoSendStream::EnableEncodedFrameRecording(
685 const std::vector<rtc::PlatformFile>& files,
686 size_t byte_limit) {
687 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
688}
689
perkj26091b12016-09-01 01:17:40 -0700690VideoSendStreamImpl::VideoSendStreamImpl(
691 SendStatisticsProxy* stats_proxy,
692 rtc::TaskQueue* worker_queue,
693 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700694 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700695 BitrateAllocator* bitrate_allocator,
696 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700697 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700698 RtcEventLog* event_log,
699 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200700 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800701 double initial_encoder_bitrate_priority,
sprang89c4a7e2017-06-30 13:27:40 -0700702 std::map<uint32_t, RtpState> suspended_ssrcs,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200703 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
Ying Wang3b790f32018-01-19 17:58:57 +0100704 VideoEncoderConfig::ContentType content_type,
705 std::unique_ptr<FecController> fec_controller)
sprangc1b57a12017-02-28 08:50:47 -0800706 : send_side_bwe_with_overhead_(
707 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800708 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000709 config_(config),
perkj26091b12016-09-01 01:17:40 -0700710 suspended_ssrcs_(std::move(suspended_ssrcs)),
Ying Wang3b790f32018-01-19 17:58:57 +0100711 fec_controller_(std::move(fec_controller)),
perkj26091b12016-09-01 01:17:40 -0700712 module_process_thread_(nullptr),
713 worker_queue_(worker_queue),
714 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200715 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700716 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100717 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700718 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700719 max_padding_bitrate_(0),
720 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200721 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700722 encoder_target_rate_bps_(0),
Seth Hampson24722b32017-12-22 09:36:42 -0800723 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
mflodmancc3d4422017-08-03 08:27:51 -0700724 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700725 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700726 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700727 video_stream_encoder),
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100728 bandwidth_observer_(transport->GetBandwidthObserver()),
nisseb8f9a322017-03-27 05:36:15 -0700729 rtp_rtcp_modules_(CreateRtpRtcpModules(
Danil Chapovalov45d725d2018-02-19 19:09:53 +0100730 *config_,
nisseb8f9a322017-03-27 05:36:15 -0700731 &encoder_feedback_,
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100732 bandwidth_observer_,
nisseb8f9a322017-03-27 05:36:15 -0700733 transport,
734 call_stats_->rtcp_rtt_stats(),
735 flexfec_sender_.get(),
736 stats_proxy_,
737 send_delay_stats,
738 event_log,
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100739 transport->GetRetransmissionRateLimiter(),
nisseb8f9a322017-03-27 05:36:15 -0700740 this,
Danil Chapovalov45d725d2018-02-19 19:09:53 +0100741 transport->keepalive_config())),
perkj26091b12016-09-01 01:17:40 -0700742 payload_router_(rtp_rtcp_modules_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200743 config_->rtp.ssrcs,
744 config_->encoder_settings.payload_type,
745 suspended_payload_states),
michaelta3328772016-11-29 09:25:03 -0800746 weak_ptr_factory_(this),
747 overhead_bytes_per_packet_(0),
748 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700749 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100750 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700751 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700752 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100753
perkj26091b12016-09-01 01:17:40 -0700754 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100755 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700756 RTC_DCHECK(transport_);
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100757 RTC_DCHECK(transport_);
Seth Hampson24722b32017-12-22 09:36:42 -0800758 RTC_DCHECK_GT(encoder_max_bitrate_bps_, 0);
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100759
760 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
Erik Språng7c8cca32017-10-24 17:05:18 +0200761 // If send-side BWE is enabled, check if we should apply updated probing and
762 // pacing settings.
763 if (TransportSeqNumExtensionConfigured(*config_)) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100764 rtc::Optional<AlrExperimentSettings> alr_settings;
Erik Språng7c8cca32017-10-24 17:05:18 +0200765 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100766 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
767 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200768 } else {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100769 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
770 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200771 }
772 if (alr_settings) {
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100773 transport->EnablePeriodicAlrProbing(true);
Sebastian Jansson4c1ffb82018-02-15 16:51:58 +0100774 transport->SetPacingFactor(alr_settings->pacing_factor);
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100775 configured_pacing_factor_ = alr_settings->pacing_factor;
Sebastian Jansson4c1ffb82018-02-15 16:51:58 +0100776 transport->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
Erik Språng7c8cca32017-10-24 17:05:18 +0200777 }
sprang89c4a7e2017-06-30 13:27:40 -0700778 }
779
780 if (config_->periodic_alr_bandwidth_probing) {
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100781 transport->EnablePeriodicAlrProbing(true);
sprang89c4a7e2017-06-30 13:27:40 -0700782 }
sergeyu80ed35e2016-11-28 13:11:13 -0800783
Per83d09102016-04-15 14:59:13 +0200784 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800785
786 // We add the highest spatial layer first to ensure it'll be prioritized
787 // when sending padding, with the hope that the packet rate will be smaller,
788 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700789 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
790 constexpr bool remb_candidate = true;
791 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
792 }
mflodman949c2f02015-10-16 02:31:11 -0700793
perkj26091b12016-09-01 01:17:40 -0700794 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
795 const std::string& extension = config_->rtp.extensions[i].uri;
796 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200797 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700798 RTC_DCHECK_GE(id, 1);
799 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100800 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
801 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
802 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
803 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000804 }
805 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000806
Per83d09102016-04-15 14:59:13 +0200807 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000808 ConfigureSsrcs();
809
Peter Boström723ead82016-02-22 15:14:01 +0100810 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700811 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800812
Peter Boström723ead82016-02-22 15:14:01 +0100813 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700814 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
815 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800816 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100817 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700818 config_->encoder_settings.payload_type,
819 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100820 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000821
Ying Wang3b790f32018-01-19 17:58:57 +0100822 fec_controller_->SetProtectionCallback(this);
823 // Signal congestion controller this object is ready for OnPacket* callbacks.
Ying Wang8ed653d2018-01-23 16:37:22 +0100824 if (fec_controller_->UseLossVectorMask()) {
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100825 transport_->RegisterPacketFeedbackObserver(this);
Ying Wang8ed653d2018-01-23 16:37:22 +0100826 }
Ying Wang3b790f32018-01-19 17:58:57 +0100827
perkj26091b12016-09-01 01:17:40 -0700828 RTC_DCHECK(config_->encoder_settings.encoder);
829 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
830 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000831
mflodmancc3d4422017-08-03 08:27:51 -0700832 video_stream_encoder_->SetStartBitrate(
833 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700834
835 // Only request rotation at the source when we positively know that the remote
836 // side doesn't support the rotation extension. This allows us to prepare the
837 // encoder in the expectation that rotation is supported - which is the common
838 // case.
839 bool rotation_applied =
840 std::find_if(config_->rtp.extensions.begin(),
841 config_->rtp.extensions.end(),
842 [](const RtpExtension& extension) {
843 return extension.uri == RtpExtension::kVideoRotationUri;
844 }) == config_->rtp.extensions.end();
845
mflodmancc3d4422017-08-03 08:27:51 -0700846 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000847}
848
perkj26091b12016-09-01 01:17:40 -0700849void VideoSendStreamImpl::RegisterProcessThread(
850 ProcessThread* module_process_thread) {
851 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
852 RTC_DCHECK(!module_process_thread_);
853 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100854
perkj26091b12016-09-01 01:17:40 -0700855 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800856 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700857}
Peter Boströmca835252016-02-11 15:59:46 +0100858
perkj26091b12016-09-01 01:17:40 -0700859void VideoSendStreamImpl::DeRegisterProcessThread() {
860 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
861 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
862 module_process_thread_->DeRegisterModule(rtp_rtcp);
863}
Peter Boströma4c76882016-03-03 16:29:02 +0100864
perkj26091b12016-09-01 01:17:40 -0700865VideoSendStreamImpl::~VideoSendStreamImpl() {
866 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800867 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700868 << "VideoSendStreamImpl::Stop not called";
Mirko Bonadei675513b2017-11-09 11:09:25 +0100869 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
Ying Wang8ed653d2018-01-23 16:37:22 +0100870 if (fec_controller_->UseLossVectorMask()) {
Sebastian Janssone4be6da2018-02-15 16:51:41 +0100871 transport_->DeRegisterPacketFeedbackObserver(this);
Ying Wang8ed653d2018-01-23 16:37:22 +0100872 }
Per83d09102016-04-15 14:59:13 +0200873 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700874 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200875 delete rtp_rtcp;
876 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000877}
878
perkj26091b12016-09-01 01:17:40 -0700879bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
880 // Runs on a network thread.
881 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700882 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
883 rtp_rtcp->IncomingRtcpPacket(packet, length);
884 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000885}
886
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800887void VideoSendStreamImpl::UpdateActiveSimulcastLayers(
888 const std::vector<bool> active_layers) {
889 RTC_DCHECK_RUN_ON(worker_queue_);
890 RTC_DCHECK_EQ(rtp_rtcp_modules_.size(), active_layers.size());
891 RTC_LOG(LS_INFO) << "VideoSendStream::UpdateActiveSimulcastLayers";
892 bool previously_active = payload_router_.IsActive();
893 payload_router_.SetActiveModules(active_layers);
894 if (!payload_router_.IsActive() && previously_active) {
895 // Payload router switched from active to inactive.
896 StopVideoSendStream();
897 } else if (payload_router_.IsActive() && !previously_active) {
898 // Payload router switched from inactive to active.
899 StartupVideoSendStream();
900 }
901}
902
perkj26091b12016-09-01 01:17:40 -0700903void VideoSendStreamImpl::Start() {
904 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100905 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800906 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100907 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200908 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800909 payload_router_.SetActive(true);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800910 StartupVideoSendStream();
911}
perkj26091b12016-09-01 01:17:40 -0700912
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800913void VideoSendStreamImpl::StartupVideoSendStream() {
914 RTC_DCHECK_RUN_ON(worker_queue_);
perkj26091b12016-09-01 01:17:40 -0700915 bitrate_allocator_->AddObserver(
916 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200917 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800918 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700919 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700920 {
perkj26091b12016-09-01 01:17:40 -0700921 rtc::CritScope lock(&encoder_activity_crit_sect_);
922 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700923 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700924 worker_queue_->PostDelayedTask(
925 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
926 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700927 }
perkj26091b12016-09-01 01:17:40 -0700928
mflodmancc3d4422017-08-03 08:27:51 -0700929 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000930}
931
perkj26091b12016-09-01 01:17:40 -0700932void VideoSendStreamImpl::Stop() {
933 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100934 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800935 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100936 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200937 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800938 payload_router_.SetActive(false);
Seth Hampsoncc7125f2018-02-02 08:46:16 -0800939 StopVideoSendStream();
940}
941
942void VideoSendStreamImpl::StopVideoSendStream() {
perkj26091b12016-09-01 01:17:40 -0700943 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700944 {
perkj26091b12016-09-01 01:17:40 -0700945 rtc::CritScope lock(&encoder_activity_crit_sect_);
946 check_encoder_activity_task_->Stop();
947 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700948 }
mflodmancc3d4422017-08-03 08:27:51 -0700949 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -0700950 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000951}
952
perkj26091b12016-09-01 01:17:40 -0700953void VideoSendStreamImpl::SignalEncoderTimedOut() {
954 RTC_DCHECK_RUN_ON(worker_queue_);
955 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
956 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
957 // if a camera stops producing frames.
958 if (encoder_target_rate_bps_ > 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100959 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
perkj26091b12016-09-01 01:17:40 -0700960 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100961 }
962}
963
sprang1a646ee2016-12-01 06:34:11 -0800964void VideoSendStreamImpl::OnBitrateAllocationUpdated(
965 const BitrateAllocation& allocation) {
966 payload_router_.OnBitrateAllocationUpdated(allocation);
967}
968
perkj26091b12016-09-01 01:17:40 -0700969void VideoSendStreamImpl::SignalEncoderActive() {
970 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100971 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
perkj26091b12016-09-01 01:17:40 -0700972 bitrate_allocator_->AddObserver(
973 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200974 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800975 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700976}
977
Per512ecb32016-09-23 15:52:06 +0200978void VideoSendStreamImpl::OnEncoderConfigurationChanged(
979 std::vector<VideoStream> streams,
980 int min_transmit_bitrate_bps) {
981 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200982 worker_queue_->PostTask(
983 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700984 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200985 return;
986 }
987 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
988 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
989 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700990 RTC_DCHECK_RUN_ON(worker_queue_);
991
perkj26091b12016-09-01 01:17:40 -0700992 encoder_min_bitrate_bps_ =
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100993 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
perkj26091b12016-09-01 01:17:40 -0700994 encoder_max_bitrate_bps_ = 0;
Seth Hampson24722b32017-12-22 09:36:42 -0800995 double stream_bitrate_priority_sum = 0;
996 for (const auto& stream : streams) {
Seth Hampson46e31ba2018-01-18 10:39:54 -0800997 // We don't want to allocate more bitrate than needed to inactive streams.
998 encoder_max_bitrate_bps_ += stream.active ? stream.max_bitrate_bps : 0;
Seth Hampson24722b32017-12-22 09:36:42 -0800999 if (stream.bitrate_priority) {
1000 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
1001 stream_bitrate_priority_sum += *stream.bitrate_priority;
1002 }
1003 }
1004 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
1005 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
Seth Hampson46e31ba2018-01-18 10:39:54 -08001006 encoder_max_bitrate_bps_ =
1007 std::max(static_cast<uint32_t>(encoder_min_bitrate_bps_),
1008 encoder_max_bitrate_bps_);
Per512ecb32016-09-23 15:52:06 +02001009 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
1010 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -07001011
1012 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +02001013 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -07001014 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +00001015 }
perkj26091b12016-09-01 01:17:40 -07001016
1017 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +02001018 streams.back().temporal_layer_thresholds_bps.size() + 1;
Ying Wang3b790f32018-01-19 17:58:57 +01001019 fec_controller_->SetEncodingData(streams[0].width, streams[0].height,
1020 number_of_temporal_layers,
1021 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -07001022
sprang1a646ee2016-12-01 06:34:11 -08001023 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -07001024 // The send stream is started already. Update the allocator with new bitrate
1025 // limits.
1026 bitrate_allocator_->AddObserver(
1027 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +02001028 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -08001029 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -07001030 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001031}
1032
perkj26091b12016-09-01 01:17:40 -07001033EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001034 const EncodedImage& encoded_image,
1035 const CodecSpecificInfo* codec_specific_info,
1036 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -07001037 // Encoded is called on whatever thread the real encoder implementation run
1038 // on. In the case of hardware encoders, there might be several encoders
1039 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -08001040 size_t simulcast_idx = 0;
1041 if (codec_specific_info->codecType == kVideoCodecVP8) {
1042 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
1043 }
perkj26091b12016-09-01 01:17:40 -07001044 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -08001045 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
1046 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
1047 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -07001048 }
perkj26091b12016-09-01 01:17:40 -07001049 {
1050 rtc::CritScope lock(&encoder_activity_crit_sect_);
1051 if (check_encoder_activity_task_)
1052 check_encoder_activity_task_->UpdateEncoderActivity();
1053 }
sergeyu37ad3372016-06-14 15:29:37 -07001054
Ying Wang0dd1b0a2018-02-20 12:50:27 +01001055 fec_controller_->UpdateWithEncodedData(encoded_image._length,
1056 encoded_image._frameType);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001057 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001058 encoded_image, codec_specific_info, fragmentation);
1059
palmkviste75f2042016-09-28 06:19:48 -07001060 RTC_DCHECK(codec_specific_info);
1061
1062 int layer = codec_specific_info->codecType == kVideoCodecVP8
1063 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1064 : 0;
1065 {
1066 rtc::CritScope lock(&ivf_writers_crit_);
1067 if (file_writers_[layer].get()) {
1068 bool ok = file_writers_[layer]->WriteFrame(
1069 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001070 RTC_DCHECK(ok);
1071 }
1072 }
1073
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001074 return result;
perkjbc75d972016-05-02 06:31:25 -07001075}
1076
perkj26091b12016-09-01 01:17:40 -07001077void VideoSendStreamImpl::ConfigureProtection() {
1078 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001079
brandtre950cad2016-11-15 05:25:41 -08001080 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1081 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1082
1083 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001084 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1085 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001086 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001087
1088 // Shorthands.
1089 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001090 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001091 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1092 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1093
stefan60e10c72017-08-23 10:40:00 -07001094 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001095 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
stefan60e10c72017-08-23 10:40:00 -07001096 DisableUlpfec();
1097 }
1098
brandtre950cad2016-11-15 05:25:41 -08001099 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1100 if (flexfec_enabled) {
1101 // We can safely disable RED here, because if the remote supports FlexFEC,
1102 // we know that it has a receiver without the RED/RTX workaround.
1103 // See http://crbug.com/webrtc/6650 for more information.
1104 if (IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001105 RTC_LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
brandtre950cad2016-11-15 05:25:41 -08001106 DisableRed();
1107 }
1108 if (IsUlpfecEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001109 RTC_LOG(LS_INFO)
brandtre950cad2016-11-15 05:25:41 -08001110 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1111 DisableUlpfec();
1112 }
1113 }
1114
Per83d09102016-04-15 14:59:13 +02001115 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001116 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1117 // is a waste of bandwidth since FEC packets still have to be transmitted.
1118 // Note that this is not the case with FlexFEC.
1119 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001120 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001121 config_->encoder_settings.payload_name)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001122 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001123 << "Transmitting payload type without picture ID using "
1124 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1125 "also have to be retransmitted. Disabling ULPFEC.";
1126 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001127 }
1128
brandtre6f98c72016-11-11 03:28:30 -08001129 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001130 //
brandtre6f98c72016-11-11 03:28:30 -08001131 // Due to how old receivers work, we need to always send RED if it has been
1132 // negotiated. This is a remnant of an old RED/RTX workaround, see
1133 // https://codereview.webrtc.org/2469093003.
1134 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1135 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1136 // no point in using RED without ULPFEC.
1137 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001138 RTC_DCHECK_GE(red_payload_type, 0);
1139 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001140 }
brandtre6f98c72016-11-11 03:28:30 -08001141 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001142 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1143 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001144 if (!IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001145 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001146 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1147 DisableUlpfec();
1148 }
Per83d09102016-04-15 14:59:13 +02001149 }
1150
1151 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1152 // Set NACK.
1153 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001154 true,
Per83d09102016-04-15 14:59:13 +02001155 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001156 // Set RED/ULPFEC information.
stefan60e10c72017-08-23 10:40:00 -07001157 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001158 }
1159
brandtre950cad2016-11-15 05:25:41 -08001160 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1161 // so enable that logic if either of those FEC schemes are enabled.
Ying Wang3b790f32018-01-19 17:58:57 +01001162 fec_controller_->SetProtectionMethod(flexfec_enabled || IsUlpfecEnabled(),
1163 nack_enabled);
Per83d09102016-04-15 14:59:13 +02001164}
1165
perkj26091b12016-09-01 01:17:40 -07001166void VideoSendStreamImpl::ConfigureSsrcs() {
1167 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001168 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001169 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1170 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001171 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1172 rtp_rtcp->SetSSRC(ssrc);
1173
1174 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001175 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001176 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001177 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001178 }
1179
Peter Boström723ead82016-02-22 15:14:01 +01001180 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001181 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001182 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001183
Peter Boström723ead82016-02-22 15:14:01 +01001184 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001185 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1186 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1187 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001188 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1189 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001190 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001191 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001192 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001193 }
1194
Peter Boström723ead82016-02-22 15:14:01 +01001195 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001196 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001197 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001198 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1199 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001200 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1201 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001202 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1203 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001204 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001205 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1206 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001207 }
Stefan Holmer10880012016-02-03 13:29:59 +01001208 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001209}
1210
perkj26091b12016-09-01 01:17:40 -07001211std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1212 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001213 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001214
perkj26091b12016-09-01 01:17:40 -07001215 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1216 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001217 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1218 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001219 }
1220
perkj26091b12016-09-01 01:17:40 -07001221 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1222 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001223 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001224 }
1225
brandtr48d21a22017-05-30 02:32:12 -07001226 if (flexfec_sender_) {
1227 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1228 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1229 }
1230
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001231 return rtp_states;
1232}
1233
Ã…sa Persson4bece9a2017-10-06 10:04:04 +02001234std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
1235 const {
1236 RTC_DCHECK_RUN_ON(worker_queue_);
1237 return payload_router_.GetRtpPayloadStates();
1238}
1239
perkj26091b12016-09-01 01:17:40 -07001240void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1241 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001242 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001243 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001244 : RtcpMode::kOff);
1245 }
1246}
1247
perkj26091b12016-09-01 01:17:40 -07001248uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1249 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001250 int64_t rtt,
1251 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001252 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001253 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001254 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001255
michaelt192132e2017-01-26 09:05:27 -08001256 // Substract overhead from bitrate.
1257 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001258 uint32_t payload_bitrate_bps = bitrate_bps;
1259 if (send_side_bwe_with_overhead_) {
1260 payload_bitrate_bps -= CalculateOverheadRateBps(
1261 CalculatePacketRate(bitrate_bps,
1262 config_->rtp.max_packet_size +
1263 transport_overhead_bytes_per_packet_),
1264 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1265 bitrate_bps);
1266 }
michaelta3328772016-11-29 09:25:03 -08001267
Per69b332d2016-06-02 15:45:42 +02001268 // Get the encoder target rate. It is the estimated network rate -
1269 // protection overhead.
Ying Wang3b790f32018-01-19 17:58:57 +01001270 encoder_target_rate_bps_ = fec_controller_->UpdateFecRates(
michaelt192132e2017-01-26 09:05:27 -08001271 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
Ying Wang3b790f32018-01-19 17:58:57 +01001272 loss_mask_vector_, rtt);
1273 loss_mask_vector_.clear();
michaelt192132e2017-01-26 09:05:27 -08001274
elad.alon0fe12162017-01-31 05:48:37 -08001275 uint32_t encoder_overhead_rate_bps =
1276 send_side_bwe_with_overhead_
1277 ? CalculateOverheadRateBps(
1278 CalculatePacketRate(encoder_target_rate_bps_,
1279 config_->rtp.max_packet_size +
1280 transport_overhead_bytes_per_packet_ -
1281 overhead_bytes_per_packet_),
1282 overhead_bytes_per_packet_ +
1283 transport_overhead_bytes_per_packet_,
1284 bitrate_bps - encoder_target_rate_bps_)
1285 : 0;
michaelt192132e2017-01-26 09:05:27 -08001286
1287 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1288 // protection_bitrate includes overhead.
1289 uint32_t protection_bitrate =
1290 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001291
perkj26091b12016-09-01 01:17:40 -07001292 encoder_target_rate_bps_ =
1293 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001294 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1295 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001296 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001297 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001298}
1299
palmkviste75f2042016-09-28 06:19:48 -07001300void VideoSendStreamImpl::EnableEncodedFrameRecording(
1301 const std::vector<rtc::PlatformFile>& files,
1302 size_t byte_limit) {
1303 {
1304 rtc::CritScope lock(&ivf_writers_crit_);
1305 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1306 if (i < files.size()) {
1307 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1308 } else {
1309 file_writers_[i].reset();
1310 }
1311 }
1312 }
1313
1314 if (!files.empty()) {
1315 // Make a keyframe appear as early as possible in the logs, to give actually
1316 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001317 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001318 }
1319}
1320
perkj26091b12016-09-01 01:17:40 -07001321int VideoSendStreamImpl::ProtectionRequest(
1322 const FecProtectionParams* delta_params,
1323 const FecProtectionParams* key_params,
1324 uint32_t* sent_video_rate_bps,
1325 uint32_t* sent_nack_rate_bps,
1326 uint32_t* sent_fec_rate_bps) {
1327 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001328 *sent_video_rate_bps = 0;
1329 *sent_nack_rate_bps = 0;
1330 *sent_fec_rate_bps = 0;
1331 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1332 uint32_t not_used = 0;
1333 uint32_t module_video_rate = 0;
1334 uint32_t module_fec_rate = 0;
1335 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001336 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001337 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1338 &module_nack_rate);
1339 *sent_video_rate_bps += module_video_rate;
1340 *sent_nack_rate_bps += module_nack_rate;
1341 *sent_fec_rate_bps += module_fec_rate;
1342 }
1343 return 0;
1344}
1345
michaelta3328772016-11-29 09:25:03 -08001346void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1347 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1348 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1349}
1350
michaelt79e05882016-11-08 02:50:09 -08001351void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001352 size_t transport_overhead_bytes_per_packet) {
1353 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001354 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
nisse284542b2017-01-10 08:58:32 -08001355 return;
1356 }
1357
michaelta3328772016-11-29 09:25:03 -08001358 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001359
Sebastian Janssone4be6da2018-02-15 16:51:41 +01001360 transport_->SetTransportOverhead(transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001361
1362 size_t rtp_packet_size =
1363 std::min(config_->rtp.max_packet_size,
1364 kPathMTU - transport_overhead_bytes_per_packet_);
1365
michaelta3328772016-11-29 09:25:03 -08001366 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001367 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001368 }
michaelt79e05882016-11-08 02:50:09 -08001369}
1370
Ying Wang3b790f32018-01-19 17:58:57 +01001371void VideoSendStreamImpl::OnPacketAdded(uint32_t ssrc, uint16_t seq_num) {
1372 if (!worker_queue_->IsCurrent()) {
1373 auto ptr = weak_ptr_;
1374 worker_queue_->PostTask([=] {
1375 if (!ptr.get())
1376 return;
1377 ptr->OnPacketAdded(ssrc, seq_num);
1378 });
1379 return;
1380 }
1381 const auto ssrcs = config_->rtp.ssrcs;
1382 if (std::find(ssrcs.begin(), ssrcs.end(), ssrc) != ssrcs.end()) {
1383 feedback_packet_seq_num_set_.insert(seq_num);
1384 if (feedback_packet_seq_num_set_.size() > kSendSideSeqNumSetMaxSize) {
1385 RTC_LOG(LS_WARNING) << "Feedback packet sequence number set exceed it's "
1386 "max size', will get reset.";
1387 feedback_packet_seq_num_set_.clear();
1388 }
1389 }
1390}
1391
1392void VideoSendStreamImpl::OnPacketFeedbackVector(
1393 const std::vector<PacketFeedback>& packet_feedback_vector) {
1394 if (!worker_queue_->IsCurrent()) {
1395 auto ptr = weak_ptr_;
1396 worker_queue_->PostTask([=] {
1397 if (!ptr.get())
1398 return;
1399 ptr->OnPacketFeedbackVector(packet_feedback_vector);
1400 });
1401 return;
1402 }
1403 // Lost feedbacks are not considered to be lost packets.
1404 for (const PacketFeedback& packet : packet_feedback_vector) {
1405 if (auto it = feedback_packet_seq_num_set_.find(packet.sequence_number) !=
1406 feedback_packet_seq_num_set_.end()) {
1407 const bool lost = packet.arrival_time_ms == PacketFeedback::kNotReceived;
1408 loss_mask_vector_.push_back(lost);
1409 feedback_packet_seq_num_set_.erase(it);
1410 }
1411 }
1412}
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001413} // namespace internal
1414} // namespace webrtc