blob: a4d657be34e32e6ce90e0de9e53f6f80f47055e2 [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>
pbos@webrtc.org1e92b0a2014-05-15 09:35:06 +000014#include <sstream>
henrik.lundin@webrtc.orgba975e22013-10-23 11:04:57 +000015#include <string>
perkj71ee44c2016-06-15 00:47:53 -070016#include <utility>
pbos@webrtc.org29d58392013-05-16 12:08:03 +000017#include <vector>
18
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020019#include "call/rtp_transport_controller_send_interface.h"
Sebastian Janssoncabe3832018-01-12 10:54:18 +010020#include "call/video_send_stream.h"
Mirko Bonadei71207422017-09-15 13:58:09 +020021#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020022#include "common_video/include/video_bitrate_allocator.h"
23#include "modules/bitrate_controller/include/bitrate_controller.h"
24#include "modules/congestion_controller/include/send_side_congestion_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"
29#include "modules/video_coding/utility/ivf_file_writer.h"
30#include "rtc_base/checks.h"
Sebastian Janssoncabe3832018-01-12 10:54:18 +010031#include "rtc_base/experiments/alr_experiment.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020032#include "rtc_base/file.h"
33#include "rtc_base/location.h"
34#include "rtc_base/logging.h"
35#include "rtc_base/trace_event.h"
36#include "rtc_base/weak_ptr.h"
37#include "system_wrappers/include/field_trial.h"
38#include "video/call_stats.h"
39#include "video/payload_router.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000040
41namespace webrtc {
mflodman949c2f02015-10-16 02:31:11 -070042
Per83d09102016-04-15 14:59:13 +020043static const int kMinSendSidePacketHistorySize = 600;
Per83d09102016-04-15 14:59:13 +020044namespace {
45
nisse284542b2017-01-10 08:58:32 -080046// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
47const size_t kPathMTU = 1500;
48
Per83d09102016-04-15 14:59:13 +020049std::vector<RtpRtcp*> CreateRtpRtcpModules(
50 Transport* outgoing_transport,
51 RtcpIntraFrameObserver* intra_frame_callback,
52 RtcpBandwidthObserver* bandwidth_callback,
nisseb8f9a322017-03-27 05:36:15 -070053 RtpTransportControllerSendInterface* transport,
Per83d09102016-04-15 14:59:13 +020054 RtcpRttStats* rtt_stats,
brandtre950cad2016-11-15 05:25:41 -080055 FlexfecSender* flexfec_sender,
Per83d09102016-04-15 14:59:13 +020056 SendStatisticsProxy* stats_proxy,
asapersson35151f32016-05-02 23:44:01 -070057 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -070058 RtcEventLog* event_log,
sprangcd349d92016-07-13 09:11:28 -070059 RateLimiter* retransmission_rate_limiter,
michaelta3328772016-11-29 09:25:03 -080060 OverheadObserver* overhead_observer,
sprang168794c2017-07-06 04:38:06 -070061 size_t num_modules,
62 RtpKeepAliveConfig keepalive_config) {
kwibergaf476c72016-11-28 15:21:39 -080063 RTC_DCHECK_GT(num_modules, 0);
Per83d09102016-04-15 14:59:13 +020064 RtpRtcp::Configuration configuration;
Per83d09102016-04-15 14:59:13 +020065 configuration.audio = false;
66 configuration.receiver_only = false;
brandtre950cad2016-11-15 05:25:41 -080067 configuration.flexfec_sender = flexfec_sender;
Per83d09102016-04-15 14:59:13 +020068 configuration.outgoing_transport = outgoing_transport;
69 configuration.intra_frame_callback = intra_frame_callback;
tereliusadafe0b2016-05-26 01:58:40 -070070 configuration.bandwidth_callback = bandwidth_callback;
nisseb8f9a322017-03-27 05:36:15 -070071 configuration.transport_feedback_callback =
72 transport->transport_feedback_observer();
Per83d09102016-04-15 14:59:13 +020073 configuration.rtt_stats = rtt_stats;
74 configuration.rtcp_packet_type_counter_observer = stats_proxy;
nisseb8f9a322017-03-27 05:36:15 -070075 configuration.paced_sender = transport->packet_sender();
Per83d09102016-04-15 14:59:13 +020076 configuration.transport_sequence_number_allocator =
nisseb8f9a322017-03-27 05:36:15 -070077 transport->packet_router();
Per83d09102016-04-15 14:59:13 +020078 configuration.send_bitrate_observer = stats_proxy;
79 configuration.send_frame_count_observer = stats_proxy;
80 configuration.send_side_delay_observer = stats_proxy;
asapersson35151f32016-05-02 23:44:01 -070081 configuration.send_packet_observer = send_delay_stats;
tereliusadafe0b2016-05-26 01:58:40 -070082 configuration.event_log = event_log;
sprangcd349d92016-07-13 09:11:28 -070083 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
michaelta3328772016-11-29 09:25:03 -080084 configuration.overhead_observer = overhead_observer;
sprang168794c2017-07-06 04:38:06 -070085 configuration.keepalive_config = keepalive_config;
Per83d09102016-04-15 14:59:13 +020086 std::vector<RtpRtcp*> modules;
87 for (size_t i = 0; i < num_modules; ++i) {
88 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
89 rtp_rtcp->SetSendingStatus(false);
90 rtp_rtcp->SetSendingMediaStatus(false);
91 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
92 modules.push_back(rtp_rtcp);
93 }
94 return modules;
95}
96
brandtre950cad2016-11-15 05:25:41 -080097// TODO(brandtr): Update this function when we support multistream protection.
98std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
brandtr48d21a22017-05-30 02:32:12 -070099 const VideoSendStream::Config& config,
100 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
brandtr3d200bd2017-01-16 06:59:19 -0800101 if (config.rtp.flexfec.payload_type < 0) {
brandtre950cad2016-11-15 05:25:41 -0800102 return nullptr;
103 }
brandtr3d200bd2017-01-16 06:59:19 -0800104 RTC_DCHECK_GE(config.rtp.flexfec.payload_type, 0);
105 RTC_DCHECK_LE(config.rtp.flexfec.payload_type, 127);
106 if (config.rtp.flexfec.ssrc == 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100107 RTC_LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
108 "Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800109 return nullptr;
110 }
111 if (config.rtp.flexfec.protected_media_ssrcs.empty()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100112 RTC_LOG(LS_WARNING)
113 << "FlexFEC is enabled, but no protected media SSRC given. "
114 "Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800115 return nullptr;
116 }
117
118 if (config.rtp.ssrcs.size() > 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100119 RTC_LOG(LS_WARNING)
120 << "Both FlexFEC and simulcast are enabled. This "
121 "combination is however not supported by our current "
122 "FlexFEC implementation. Therefore disabling FlexFEC.";
brandtre950cad2016-11-15 05:25:41 -0800123 return nullptr;
124 }
125
126 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100127 RTC_LOG(LS_WARNING)
brandtre950cad2016-11-15 05:25:41 -0800128 << "The supplied FlexfecConfig contained multiple protected "
129 "media streams, but our implementation currently only "
130 "supports protecting a single media stream. "
131 "To avoid confusion, disabling FlexFEC completely.";
132 return nullptr;
133 }
134
brandtr48d21a22017-05-30 02:32:12 -0700135 const RtpState* rtp_state = nullptr;
136 auto it = suspended_ssrcs.find(config.rtp.flexfec.ssrc);
137 if (it != suspended_ssrcs.end()) {
138 rtp_state = &it->second;
139 }
140
brandtre950cad2016-11-15 05:25:41 -0800141 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
142 return std::unique_ptr<FlexfecSender>(new FlexfecSender(
brandtr3d200bd2017-01-16 06:59:19 -0800143 config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc,
brandtre950cad2016-11-15 05:25:41 -0800144 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions,
brandtr48d21a22017-05-30 02:32:12 -0700145 RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock()));
brandtre950cad2016-11-15 05:25:41 -0800146}
147
Erik Språng7c8cca32017-10-24 17:05:18 +0200148bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
149 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
150 return std::find_if(
151 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
152 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
153 }) != extensions.end();
154}
Peter Boströme4499152016-02-05 11:13:28 +0100155
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100156const char kForcedFallbackFieldTrial[] =
157 "WebRTC-VP8-Forced-Fallback-Encoder-v2";
158
159rtc::Optional<int> GetFallbackMinBpsFromFieldTrial() {
160 if (!webrtc::field_trial::IsEnabled(kForcedFallbackFieldTrial))
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100161 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100162
163 std::string group =
164 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
165 if (group.empty())
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100166 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100167
168 int min_pixels;
169 int max_pixels;
170 int min_bps;
171 if (sscanf(group.c_str(), "Enabled-%d,%d,%d", &min_pixels, &max_pixels,
172 &min_bps) != 3) {
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100173 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100174 }
175
176 if (min_bps <= 0)
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100177 return rtc::nullopt;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100178
Oskar Sundbom8e07c132018-01-08 16:45:42 +0100179 return min_bps;
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100180}
181
182int GetEncoderMinBitrateBps() {
183 const int kDefaultEncoderMinBitrateBps = 30000;
184 return GetFallbackMinBpsFromFieldTrial().value_or(
185 kDefaultEncoderMinBitrateBps);
186}
187
Peter Boström39593972016-02-15 11:27:15 +0100188bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
kthelgason1cdddc92017-08-24 03:52:48 -0700189 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
190 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
perkj26091b12016-09-01 01:17:40 -0700191 return true;
deadbeefc964d0b2017-04-03 10:03:35 -0700192 }
Peter Boström39593972016-02-15 11:27:15 +0100193 return false;
194}
195
Per512ecb32016-09-23 15:52:06 +0200196int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
197 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700198 bool pad_to_min_bitrate) {
199 int pad_up_to_bitrate_bps = 0;
200 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200201 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700202 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200203 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700204 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200205 for (size_t i = 0; i < streams.size() - 1; ++i)
206 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700207 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200208 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700209 }
210
211 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200212 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700213
214 return pad_up_to_bitrate_bps;
215}
216
michaelt192132e2017-01-26 09:05:27 -0800217uint32_t CalculateOverheadRateBps(int packets_per_second,
218 size_t overhead_bytes_per_packet,
219 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800220 uint32_t overhead_bps =
221 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
222 return std::min(overhead_bps, max_overhead_bps);
223}
224
225int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
226 size_t packet_size_bits = 8 * packet_size_bytes;
227 // Ceil for int value of bitrate_bps / packet_size_bits.
228 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
229 packet_size_bits);
230}
231
Peter Boströme4499152016-02-05 11:13:28 +0100232} // namespace
233
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000234namespace internal {
perkj26091b12016-09-01 01:17:40 -0700235
236// VideoSendStreamImpl implements internal::VideoSendStream.
237// It is created and destroyed on |worker_queue|. The intent is to decrease the
238// need for locking and to ensure methods are called in sequence.
239// Public methods except |DeliverRtcp| must be called on |worker_queue|.
240// DeliverRtcp is called on the libjingle worker thread or a network thread.
241// An encoder may deliver frames through the EncodedImageCallback on an
242// arbitrary thread.
243class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800244 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700245 public webrtc::VCMProtectionCallback,
mflodmancc3d4422017-08-03 08:27:51 -0700246 public VideoStreamEncoder::EncoderSink,
Ying Wang38a31b02017-12-21 12:26:19 +0000247 public VideoBitrateAllocationObserver {
perkj26091b12016-09-01 01:17:40 -0700248 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200249 VideoSendStreamImpl(
250 SendStatisticsProxy* stats_proxy,
251 rtc::TaskQueue* worker_queue,
252 CallStats* call_stats,
253 RtpTransportControllerSendInterface* transport,
254 BitrateAllocator* bitrate_allocator,
255 SendDelayStats* send_delay_stats,
256 VideoStreamEncoder* video_stream_encoder,
257 RtcEventLog* event_log,
258 const VideoSendStream::Config* config,
259 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800260 double initial_encoder_bitrate_priority,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200261 std::map<uint32_t, RtpState> suspended_ssrcs,
262 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
263 VideoEncoderConfig::ContentType content_type);
perkj26091b12016-09-01 01:17:40 -0700264 ~VideoSendStreamImpl() override;
265
266 // RegisterProcessThread register |module_process_thread| with those objects
267 // that use it. Registration has to happen on the thread were
268 // |module_process_thread| was created (libjingle's worker thread).
269 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
270 // maybe |worker_queue|.
271 void RegisterProcessThread(ProcessThread* module_process_thread);
272 void DeRegisterProcessThread();
273
274 void SignalNetworkState(NetworkState state);
275 bool DeliverRtcp(const uint8_t* packet, size_t length);
276 void Start();
277 void Stop();
278
perkj26091b12016-09-01 01:17:40 -0700279 VideoSendStream::RtpStateMap GetRtpStates() const;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200280 VideoSendStream::RtpPayloadStateMap GetRtpPayloadStates() const;
perkj26091b12016-09-01 01:17:40 -0700281
palmkviste75f2042016-09-28 06:19:48 -0700282 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
283 size_t byte_limit);
284
nisse284542b2017-01-10 08:58:32 -0800285 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800286
perkj26091b12016-09-01 01:17:40 -0700287 private:
288 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200289 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700290
291 // Implements BitrateAllocatorObserver.
292 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
293 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800294 int64_t rtt,
295 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700296
297 // Implements webrtc::VCMProtectionCallback.
298 int ProtectionRequest(const FecProtectionParams* delta_params,
299 const FecProtectionParams* key_params,
300 uint32_t* sent_video_rate_bps,
301 uint32_t* sent_nack_rate_bps,
302 uint32_t* sent_fec_rate_bps) override;
303
michaelta3328772016-11-29 09:25:03 -0800304 // Implements OverheadObserver.
305 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
306
Per512ecb32016-09-23 15:52:06 +0200307 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
308 int min_transmit_bitrate_bps) override;
309
perkj26091b12016-09-01 01:17:40 -0700310 // Implements EncodedImageCallback. The implementation routes encoded frames
311 // to the |payload_router_| and |config.pre_encode_callback| if set.
312 // Called on an arbitrary encoder callback thread.
313 EncodedImageCallback::Result OnEncodedImage(
314 const EncodedImage& encoded_image,
315 const CodecSpecificInfo* codec_specific_info,
316 const RTPFragmentationHeader* fragmentation) override;
317
sprang1a646ee2016-12-01 06:34:11 -0800318 // Implements VideoBitrateAllocationObserver.
319 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
320
perkj26091b12016-09-01 01:17:40 -0700321 void ConfigureProtection();
322 void ConfigureSsrcs();
323 void SignalEncoderTimedOut();
324 void SignalEncoderActive();
325
elad.alon0fe12162017-01-31 05:48:37 -0800326 const bool send_side_bwe_with_overhead_;
Ying Wang38a31b02017-12-21 12:26:19 +0000327
perkj26091b12016-09-01 01:17:40 -0700328 SendStatisticsProxy* const stats_proxy_;
329 const VideoSendStream::Config* const config_;
330 std::map<uint32_t, RtpState> suspended_ssrcs_;
331
332 ProcessThread* module_process_thread_;
333 rtc::ThreadChecker module_process_thread_checker_;
334 rtc::TaskQueue* const worker_queue_;
335
336 rtc::CriticalSection encoder_activity_crit_sect_;
337 CheckEncoderActivityTask* check_encoder_activity_task_
danilchapa37de392017-09-09 04:17:22 -0700338 RTC_GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200339
perkj26091b12016-09-01 01:17:40 -0700340 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700341 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700342 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700343
brandtr3b941be2017-03-17 07:02:46 -0700344 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800345 std::unique_ptr<FlexfecSender> flexfec_sender_;
346
palmkviste75f2042016-09-28 06:19:48 -0700347 rtc::CriticalSection ivf_writers_crit_;
danilchapa37de392017-09-09 04:17:22 -0700348 std::unique_ptr<IvfFileWriter>
349 file_writers_[kMaxSimulcastStreams] RTC_GUARDED_BY(ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700350
351 int max_padding_bitrate_;
352 int encoder_min_bitrate_bps_;
353 uint32_t encoder_max_bitrate_bps_;
354 uint32_t encoder_target_rate_bps_;
Seth Hampson24722b32017-12-22 09:36:42 -0800355 double encoder_bitrate_priority_;
perkj26091b12016-09-01 01:17:40 -0700356
mflodmancc3d4422017-08-03 08:27:51 -0700357 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700358 EncoderRtcpFeedback encoder_feedback_;
Ying Wang38a31b02017-12-21 12:26:19 +0000359 ProtectionBitrateCalculator protection_bitrate_calculator_;
perkj26091b12016-09-01 01:17:40 -0700360
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100361 RtcpBandwidthObserver* const bandwidth_observer_;
perkj26091b12016-09-01 01:17:40 -0700362 // RtpRtcp modules, declared here as they use other members on construction.
363 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
364 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700365
366 // |weak_ptr_| to our self. This is used since we can not call
367 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
368 // an existing WeakPtr.
369 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
370 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
371 // invalidated before any other members are destroyed.
372 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800373
374 rtc::CriticalSection overhead_bytes_per_packet_crit_;
danilchapa37de392017-09-09 04:17:22 -0700375 size_t overhead_bytes_per_packet_
376 RTC_GUARDED_BY(overhead_bytes_per_packet_crit_);
michaelta3328772016-11-29 09:25:03 -0800377 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700378};
379
380// TODO(tommi): See if there's a more elegant way to create a task that creates
381// an object on the correct task queue.
382class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
383 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200384 ConstructionTask(
385 std::unique_ptr<VideoSendStreamImpl>* send_stream,
386 rtc::Event* done_event,
387 SendStatisticsProxy* stats_proxy,
388 VideoStreamEncoder* video_stream_encoder,
389 ProcessThread* module_process_thread,
390 CallStats* call_stats,
391 RtpTransportControllerSendInterface* transport,
392 BitrateAllocator* bitrate_allocator,
393 SendDelayStats* send_delay_stats,
394 RtcEventLog* event_log,
395 const VideoSendStream::Config* config,
396 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800397 double initial_encoder_bitrate_priority,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200398 const std::map<uint32_t, RtpState>& suspended_ssrcs,
399 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
400 VideoEncoderConfig::ContentType content_type)
perkj26091b12016-09-01 01:17:40 -0700401 : send_stream_(send_stream),
402 done_event_(done_event),
403 stats_proxy_(stats_proxy),
mflodmancc3d4422017-08-03 08:27:51 -0700404 video_stream_encoder_(video_stream_encoder),
perkj26091b12016-09-01 01:17:40 -0700405 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700406 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700407 bitrate_allocator_(bitrate_allocator),
408 send_delay_stats_(send_delay_stats),
perkj26091b12016-09-01 01:17:40 -0700409 event_log_(event_log),
410 config_(config),
Per512ecb32016-09-23 15:52:06 +0200411 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
Seth Hampson24722b32017-12-22 09:36:42 -0800412 initial_encoder_bitrate_priority_(initial_encoder_bitrate_priority),
sprang89c4a7e2017-06-30 13:27:40 -0700413 suspended_ssrcs_(suspended_ssrcs),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200414 suspended_payload_states_(suspended_payload_states),
sprangdb2a9fc2017-08-09 06:42:32 -0700415 content_type_(content_type) {}
perkj26091b12016-09-01 01:17:40 -0700416
417 ~ConstructionTask() override { done_event_->Set(); }
418
419 private:
420 bool Run() override {
421 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700422 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
mflodmancc3d4422017-08-03 08:27:51 -0700423 bitrate_allocator_, send_delay_stats_, video_stream_encoder_,
424 event_log_, config_, initial_encoder_max_bitrate_,
Seth Hampson24722b32017-12-22 09:36:42 -0800425 initial_encoder_bitrate_priority_, std::move(suspended_ssrcs_),
426 std::move(suspended_payload_states_), content_type_));
perkj26091b12016-09-01 01:17:40 -0700427 return true;
428 }
429
430 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
431 rtc::Event* const done_event_;
432 SendStatisticsProxy* const stats_proxy_;
mflodmancc3d4422017-08-03 08:27:51 -0700433 VideoStreamEncoder* const video_stream_encoder_;
perkj26091b12016-09-01 01:17:40 -0700434 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700435 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700436 BitrateAllocator* const bitrate_allocator_;
437 SendDelayStats* const send_delay_stats_;
perkj26091b12016-09-01 01:17:40 -0700438 RtcEventLog* const event_log_;
439 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200440 int initial_encoder_max_bitrate_;
Seth Hampson24722b32017-12-22 09:36:42 -0800441 double initial_encoder_bitrate_priority_;
perkj26091b12016-09-01 01:17:40 -0700442 std::map<uint32_t, RtpState> suspended_ssrcs_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200443 std::map<uint32_t, RtpPayloadState> suspended_payload_states_;
sprang89c4a7e2017-06-30 13:27:40 -0700444 const VideoEncoderConfig::ContentType content_type_;
perkj26091b12016-09-01 01:17:40 -0700445};
446
447class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
448 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200449 DestructAndGetRtpStateTask(
450 VideoSendStream::RtpStateMap* state_map,
451 VideoSendStream::RtpPayloadStateMap* payload_state_map,
452 std::unique_ptr<VideoSendStreamImpl> send_stream,
453 rtc::Event* done_event)
perkj26091b12016-09-01 01:17:40 -0700454 : state_map_(state_map),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200455 payload_state_map_(payload_state_map),
perkj26091b12016-09-01 01:17:40 -0700456 send_stream_(std::move(send_stream)),
457 done_event_(done_event) {}
458
459 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
460
461 private:
462 bool Run() override {
463 send_stream_->Stop();
464 *state_map_ = send_stream_->GetRtpStates();
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200465 *payload_state_map_ = send_stream_->GetRtpPayloadStates();
perkj26091b12016-09-01 01:17:40 -0700466 send_stream_.reset();
467 done_event_->Set();
468 return true;
469 }
470
471 VideoSendStream::RtpStateMap* state_map_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200472 VideoSendStream::RtpPayloadStateMap* payload_state_map_;
perkj26091b12016-09-01 01:17:40 -0700473 std::unique_ptr<VideoSendStreamImpl> send_stream_;
474 rtc::Event* done_event_;
475};
476
477// CheckEncoderActivityTask is used for tracking when the encoder last produced
478// and encoded video frame. If the encoder has not produced anything the last
479// kEncoderTimeOutMs we also want to stop sending padding.
480class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
481 public:
482 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700483 explicit CheckEncoderActivityTask(
484 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
485 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700486
487 void Stop() {
488 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700489 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700490 }
491
492 void UpdateEncoderActivity() {
493 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
494 // whatever thread the real encoder implementation run on. In the case of
495 // hardware encoders, there might be several encoders
496 // running in parallel on different threads.
497 rtc::AtomicOps::ReleaseStore(&activity_, 1);
498 }
499
500 private:
501 bool Run() override {
502 RTC_CHECK(task_checker_.CalledSequentially());
503 if (!send_stream_)
504 return true;
505 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
506 if (!timed_out_) {
507 send_stream_->SignalEncoderTimedOut();
508 }
509 timed_out_ = true;
510 } else if (timed_out_) {
511 send_stream_->SignalEncoderActive();
512 timed_out_ = false;
513 }
514 rtc::AtomicOps::ReleaseStore(&activity_, 0);
515
516 rtc::TaskQueue::Current()->PostDelayedTask(
517 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
518 // Return false to prevent this task from being deleted. Ownership has been
519 // transferred to the task queue when PostDelayedTask was called.
520 return false;
521 }
522 volatile int activity_;
523
524 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700525 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700526 bool timed_out_;
527};
528
Per512ecb32016-09-23 15:52:06 +0200529class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700530 public:
perkj8ff860a2016-10-03 00:30:04 -0700531 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200532 std::vector<VideoStream> streams,
533 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700534 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200535 streams_(std::move(streams)),
536 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700537
538 private:
539 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700540 if (send_stream_)
541 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
542 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700543 return true;
544 }
545
perkj8ff860a2016-10-03 00:30:04 -0700546 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200547 std::vector<VideoStream> streams_;
548 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700549};
550
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000551VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200552 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200553 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700554 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200555 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700556 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800557 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700558 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700559 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700560 VideoSendStream::Config config,
561 VideoEncoderConfig encoder_config,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200562 const std::map<uint32_t, RtpState>& suspended_ssrcs,
563 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
perkj26091b12016-09-01 01:17:40 -0700564 : worker_queue_(worker_queue),
565 thread_sync_event_(false /* manual_reset */, false),
566 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800567 config,
568 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800569 config_(std::move(config)),
570 content_type_(encoder_config.content_type) {
mflodmancc3d4422017-08-03 08:27:51 -0700571 video_stream_encoder_.reset(
572 new VideoStreamEncoder(num_cpu_cores, &stats_proxy_,
573 config_.encoder_settings,
574 config_.pre_encode_callback,
mflodmancc3d4422017-08-03 08:27:51 -0700575 std::unique_ptr<OveruseFrameDetector>()));
perkj26091b12016-09-01 01:17:40 -0700576 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
mflodmancc3d4422017-08-03 08:27:51 -0700577 &send_stream_, &thread_sync_event_, &stats_proxy_,
578 video_stream_encoder_.get(), module_process_thread, call_stats, transport,
579 bitrate_allocator, send_delay_stats, event_log, &config_,
Seth Hampson24722b32017-12-22 09:36:42 -0800580 encoder_config.max_bitrate_bps, encoder_config.bitrate_priority,
581 suspended_ssrcs, suspended_payload_states, encoder_config.content_type)));
perkj26091b12016-09-01 01:17:40 -0700582
583 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
584 // |module_process_thread| must be registered and deregistered on the thread
585 // it was created on.
586 thread_sync_event_.Wait(rtc::Event::kForever);
587 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800588 // TODO(sprang): Enable this also for regular video calls if it works well.
589 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
590 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700591 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800592 }
Ying Wang38a31b02017-12-21 12:26:19 +0000593
perkj26091b12016-09-01 01:17:40 -0700594 ReconfigureVideoEncoder(std::move(encoder_config));
595}
596
597VideoSendStream::~VideoSendStream() {
598 RTC_DCHECK_RUN_ON(&thread_checker_);
599 RTC_DCHECK(!send_stream_);
600}
601
602void VideoSendStream::Start() {
603 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100604 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 01:17:40 -0700605 VideoSendStreamImpl* send_stream = send_stream_.get();
606 worker_queue_->PostTask([this, send_stream] {
607 send_stream->Start();
608 thread_sync_event_.Set();
609 });
610
611 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700612 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
613 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700614 thread_sync_event_.Wait(rtc::Event::kForever);
615}
616
617void VideoSendStream::Stop() {
618 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100619 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 01:17:40 -0700620 VideoSendStreamImpl* send_stream = send_stream_.get();
621 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
622}
623
perkja49cbd32016-09-16 07:53:41 -0700624void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700625 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
626 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700627 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700628 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700629}
630
631void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700632 // TODO(perkj): Some test cases in VideoSendStreamTest call
633 // ReconfigureVideoEncoder from the network thread.
634 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800635 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700636 video_stream_encoder_->ConfigureEncoder(std::move(config),
637 config_.rtp.max_packet_size,
638 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700639}
640
641VideoSendStream::Stats VideoSendStream::GetStats() {
642 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
643 // a network thread. See comment in Call::GetStats().
644 // RTC_DCHECK_RUN_ON(&thread_checker_);
645 return stats_proxy_.GetStats();
646}
647
648void VideoSendStream::SignalNetworkState(NetworkState state) {
649 RTC_DCHECK_RUN_ON(&thread_checker_);
650 VideoSendStreamImpl* send_stream = send_stream_.get();
651 worker_queue_->PostTask(
652 [send_stream, state] { send_stream->SignalNetworkState(state); });
653}
654
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200655void VideoSendStream::StopPermanentlyAndGetRtpStates(
656 VideoSendStream::RtpStateMap* rtp_state_map,
657 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700658 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700659 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700660 send_stream_->DeRegisterProcessThread();
661 worker_queue_->PostTask(
662 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200663 rtp_state_map, payload_state_map, std::move(send_stream_),
664 &thread_sync_event_)));
perkj26091b12016-09-01 01:17:40 -0700665 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700666}
667
nisse284542b2017-01-10 08:58:32 -0800668void VideoSendStream::SetTransportOverhead(
669 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800670 RTC_DCHECK_RUN_ON(&thread_checker_);
671 VideoSendStreamImpl* send_stream = send_stream_.get();
672 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
673 send_stream->SetTransportOverhead(transport_overhead_per_packet);
674 });
675}
676
perkj26091b12016-09-01 01:17:40 -0700677bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
678 // Called on a network thread.
679 return send_stream_->DeliverRtcp(packet, length);
680}
681
palmkviste75f2042016-09-28 06:19:48 -0700682void VideoSendStream::EnableEncodedFrameRecording(
683 const std::vector<rtc::PlatformFile>& files,
684 size_t byte_limit) {
685 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
686}
687
perkj26091b12016-09-01 01:17:40 -0700688VideoSendStreamImpl::VideoSendStreamImpl(
689 SendStatisticsProxy* stats_proxy,
690 rtc::TaskQueue* worker_queue,
691 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700692 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700693 BitrateAllocator* bitrate_allocator,
694 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700695 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700696 RtcEventLog* event_log,
697 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200698 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800699 double initial_encoder_bitrate_priority,
sprang89c4a7e2017-06-30 13:27:40 -0700700 std::map<uint32_t, RtpState> suspended_ssrcs,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200701 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
sprangdb2a9fc2017-08-09 06:42:32 -0700702 VideoEncoderConfig::ContentType content_type)
sprangc1b57a12017-02-28 08:50:47 -0800703 : send_side_bwe_with_overhead_(
704 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800705 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000706 config_(config),
perkj26091b12016-09-01 01:17:40 -0700707 suspended_ssrcs_(std::move(suspended_ssrcs)),
708 module_process_thread_(nullptr),
709 worker_queue_(worker_queue),
710 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200711 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700712 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100713 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700714 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700715 max_padding_bitrate_(0),
716 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200717 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700718 encoder_target_rate_bps_(0),
Seth Hampson24722b32017-12-22 09:36:42 -0800719 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
mflodmancc3d4422017-08-03 08:27:51 -0700720 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700721 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700722 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700723 video_stream_encoder),
Ying Wang38a31b02017-12-21 12:26:19 +0000724 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100725 bandwidth_observer_(transport->send_side_cc()->GetBandwidthObserver()),
nisseb8f9a322017-03-27 05:36:15 -0700726 rtp_rtcp_modules_(CreateRtpRtcpModules(
727 config_->send_transport,
728 &encoder_feedback_,
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100729 bandwidth_observer_,
nisseb8f9a322017-03-27 05:36:15 -0700730 transport,
731 call_stats_->rtcp_rtt_stats(),
732 flexfec_sender_.get(),
733 stats_proxy_,
734 send_delay_stats,
735 event_log,
736 transport->send_side_cc()->GetRetransmissionRateLimiter(),
737 this,
sprang168794c2017-07-06 04:38:06 -0700738 config_->rtp.ssrcs.size(),
sprangdb2a9fc2017-08-09 06:42:32 -0700739 transport->keepalive_config())),
perkj26091b12016-09-01 01:17:40 -0700740 payload_router_(rtp_rtcp_modules_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200741 config_->rtp.ssrcs,
742 config_->encoder_settings.payload_type,
743 suspended_payload_states),
michaelta3328772016-11-29 09:25:03 -0800744 weak_ptr_factory_(this),
745 overhead_bytes_per_packet_(0),
746 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700747 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100748 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700749 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700750 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100751
perkj26091b12016-09-01 01:17:40 -0700752 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100753 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700754 RTC_DCHECK(transport_);
755 RTC_DCHECK(transport_->send_side_cc());
Seth Hampson24722b32017-12-22 09:36:42 -0800756 RTC_DCHECK_GT(encoder_max_bitrate_bps_, 0);
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100757
758 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
Erik Språng7c8cca32017-10-24 17:05:18 +0200759 // If send-side BWE is enabled, check if we should apply updated probing and
760 // pacing settings.
761 if (TransportSeqNumExtensionConfigured(*config_)) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100762 rtc::Optional<AlrExperimentSettings> alr_settings;
Erik Språng7c8cca32017-10-24 17:05:18 +0200763 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100764 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
765 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200766 } else {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100767 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
768 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200769 }
770 if (alr_settings) {
771 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
772 transport->pacer()->SetPacingFactor(alr_settings->pacing_factor);
773 transport->pacer()->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
774 }
sprang89c4a7e2017-06-30 13:27:40 -0700775 }
776
777 if (config_->periodic_alr_bandwidth_probing) {
778 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
779 }
sergeyu80ed35e2016-11-28 13:11:13 -0800780
Per83d09102016-04-15 14:59:13 +0200781 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800782
783 // We add the highest spatial layer first to ensure it'll be prioritized
784 // when sending padding, with the hope that the packet rate will be smaller,
785 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700786 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
787 constexpr bool remb_candidate = true;
788 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
789 }
mflodman949c2f02015-10-16 02:31:11 -0700790
perkj26091b12016-09-01 01:17:40 -0700791 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
792 const std::string& extension = config_->rtp.extensions[i].uri;
793 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200794 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700795 RTC_DCHECK_GE(id, 1);
796 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100797 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
798 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
799 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
800 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000801 }
802 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000803
Per83d09102016-04-15 14:59:13 +0200804 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000805 ConfigureSsrcs();
806
Peter Boström723ead82016-02-22 15:14:01 +0100807 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700808 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800809
Peter Boström723ead82016-02-22 15:14:01 +0100810 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700811 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
812 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800813 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100814 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700815 config_->encoder_settings.payload_type,
816 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100817 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000818
perkj26091b12016-09-01 01:17:40 -0700819 RTC_DCHECK(config_->encoder_settings.encoder);
820 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
821 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000822
mflodmancc3d4422017-08-03 08:27:51 -0700823 video_stream_encoder_->SetStartBitrate(
824 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700825
826 // Only request rotation at the source when we positively know that the remote
827 // side doesn't support the rotation extension. This allows us to prepare the
828 // encoder in the expectation that rotation is supported - which is the common
829 // case.
830 bool rotation_applied =
831 std::find_if(config_->rtp.extensions.begin(),
832 config_->rtp.extensions.end(),
833 [](const RtpExtension& extension) {
834 return extension.uri == RtpExtension::kVideoRotationUri;
835 }) == config_->rtp.extensions.end();
836
mflodmancc3d4422017-08-03 08:27:51 -0700837 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000838}
839
perkj26091b12016-09-01 01:17:40 -0700840void VideoSendStreamImpl::RegisterProcessThread(
841 ProcessThread* module_process_thread) {
842 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
843 RTC_DCHECK(!module_process_thread_);
844 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100845
perkj26091b12016-09-01 01:17:40 -0700846 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800847 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700848}
Peter Boströmca835252016-02-11 15:59:46 +0100849
perkj26091b12016-09-01 01:17:40 -0700850void VideoSendStreamImpl::DeRegisterProcessThread() {
851 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
852 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
853 module_process_thread_->DeRegisterModule(rtp_rtcp);
854}
Peter Boströma4c76882016-03-03 16:29:02 +0100855
perkj26091b12016-09-01 01:17:40 -0700856VideoSendStreamImpl::~VideoSendStreamImpl() {
857 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800858 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700859 << "VideoSendStreamImpl::Stop not called";
Mirko Bonadei675513b2017-11-09 11:09:25 +0100860 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
Ying Wang38a31b02017-12-21 12:26:19 +0000861
Per83d09102016-04-15 14:59:13 +0200862 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700863 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200864 delete rtp_rtcp;
865 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000866}
867
perkj26091b12016-09-01 01:17:40 -0700868bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
869 // Runs on a network thread.
870 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700871 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
872 rtp_rtcp->IncomingRtcpPacket(packet, length);
873 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000874}
875
perkj26091b12016-09-01 01:17:40 -0700876void VideoSendStreamImpl::Start() {
877 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100878 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800879 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100880 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200881 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800882 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700883
884 bitrate_allocator_->AddObserver(
885 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200886 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800887 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700888
889 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700890 {
perkj26091b12016-09-01 01:17:40 -0700891 rtc::CritScope lock(&encoder_activity_crit_sect_);
892 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700893 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700894 worker_queue_->PostDelayedTask(
895 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
896 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700897 }
perkj26091b12016-09-01 01:17:40 -0700898
mflodmancc3d4422017-08-03 08:27:51 -0700899 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000900}
901
perkj26091b12016-09-01 01:17:40 -0700902void VideoSendStreamImpl::Stop() {
903 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100904 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800905 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100906 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200907 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800908 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700909 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700910 {
perkj26091b12016-09-01 01:17:40 -0700911 rtc::CritScope lock(&encoder_activity_crit_sect_);
912 check_encoder_activity_task_->Stop();
913 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700914 }
mflodmancc3d4422017-08-03 08:27:51 -0700915 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -0700916 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000917}
918
perkj26091b12016-09-01 01:17:40 -0700919void VideoSendStreamImpl::SignalEncoderTimedOut() {
920 RTC_DCHECK_RUN_ON(worker_queue_);
921 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
922 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
923 // if a camera stops producing frames.
924 if (encoder_target_rate_bps_ > 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100925 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
perkj26091b12016-09-01 01:17:40 -0700926 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100927 }
928}
929
sprang1a646ee2016-12-01 06:34:11 -0800930void VideoSendStreamImpl::OnBitrateAllocationUpdated(
931 const BitrateAllocation& allocation) {
932 payload_router_.OnBitrateAllocationUpdated(allocation);
933}
934
perkj26091b12016-09-01 01:17:40 -0700935void VideoSendStreamImpl::SignalEncoderActive() {
936 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100937 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
perkj26091b12016-09-01 01:17:40 -0700938 bitrate_allocator_->AddObserver(
939 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200940 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800941 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700942}
943
Per512ecb32016-09-23 15:52:06 +0200944void VideoSendStreamImpl::OnEncoderConfigurationChanged(
945 std::vector<VideoStream> streams,
946 int min_transmit_bitrate_bps) {
947 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200948 worker_queue_->PostTask(
949 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700950 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200951 return;
952 }
953 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
954 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
955 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700956 RTC_DCHECK_RUN_ON(worker_queue_);
957
perkj26091b12016-09-01 01:17:40 -0700958 encoder_min_bitrate_bps_ =
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100959 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
perkj26091b12016-09-01 01:17:40 -0700960 encoder_max_bitrate_bps_ = 0;
Seth Hampson24722b32017-12-22 09:36:42 -0800961 double stream_bitrate_priority_sum = 0;
962 for (const auto& stream : streams) {
Lu Liu0f17f9c2018-01-17 00:28:14 +0000963 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Seth Hampson24722b32017-12-22 09:36:42 -0800964 if (stream.bitrate_priority) {
965 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
966 stream_bitrate_priority_sum += *stream.bitrate_priority;
967 }
968 }
969 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
970 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
Per512ecb32016-09-23 15:52:06 +0200971 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
972 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -0700973
974 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +0200975 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -0700976 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000977 }
perkj26091b12016-09-01 01:17:40 -0700978
979 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +0200980 streams.back().temporal_layer_thresholds_bps.size() + 1;
Ying Wang38a31b02017-12-21 12:26:19 +0000981 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +0200982 streams[0].width, streams[0].height, number_of_temporal_layers,
983 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -0700984
sprang1a646ee2016-12-01 06:34:11 -0800985 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -0700986 // The send stream is started already. Update the allocator with new bitrate
987 // limits.
988 bitrate_allocator_->AddObserver(
989 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200990 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800991 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700992 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000993}
994
perkj26091b12016-09-01 01:17:40 -0700995EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700996 const EncodedImage& encoded_image,
997 const CodecSpecificInfo* codec_specific_info,
998 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -0700999 // Encoded is called on whatever thread the real encoder implementation run
1000 // on. In the case of hardware encoders, there might be several encoders
1001 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -08001002 size_t simulcast_idx = 0;
1003 if (codec_specific_info->codecType == kVideoCodecVP8) {
1004 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
1005 }
perkj26091b12016-09-01 01:17:40 -07001006 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -08001007 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
1008 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
1009 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -07001010 }
perkj26091b12016-09-01 01:17:40 -07001011 {
1012 rtc::CritScope lock(&encoder_activity_crit_sect_);
1013 if (check_encoder_activity_task_)
1014 check_encoder_activity_task_->UpdateEncoderActivity();
1015 }
sergeyu37ad3372016-06-14 15:29:37 -07001016
Ying Wang38a31b02017-12-21 12:26:19 +00001017 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001018 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001019 encoded_image, codec_specific_info, fragmentation);
1020
palmkviste75f2042016-09-28 06:19:48 -07001021 RTC_DCHECK(codec_specific_info);
1022
1023 int layer = codec_specific_info->codecType == kVideoCodecVP8
1024 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1025 : 0;
1026 {
1027 rtc::CritScope lock(&ivf_writers_crit_);
1028 if (file_writers_[layer].get()) {
1029 bool ok = file_writers_[layer]->WriteFrame(
1030 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001031 RTC_DCHECK(ok);
1032 }
1033 }
1034
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001035 return result;
perkjbc75d972016-05-02 06:31:25 -07001036}
1037
perkj26091b12016-09-01 01:17:40 -07001038void VideoSendStreamImpl::ConfigureProtection() {
1039 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001040
brandtre950cad2016-11-15 05:25:41 -08001041 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1042 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1043
1044 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001045 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1046 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001047 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001048
1049 // Shorthands.
1050 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001051 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001052 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1053 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1054
stefan60e10c72017-08-23 10:40:00 -07001055 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001056 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
stefan60e10c72017-08-23 10:40:00 -07001057 DisableUlpfec();
1058 }
1059
brandtre950cad2016-11-15 05:25:41 -08001060 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1061 if (flexfec_enabled) {
1062 // We can safely disable RED here, because if the remote supports FlexFEC,
1063 // we know that it has a receiver without the RED/RTX workaround.
1064 // See http://crbug.com/webrtc/6650 for more information.
1065 if (IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001066 RTC_LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
brandtre950cad2016-11-15 05:25:41 -08001067 DisableRed();
1068 }
1069 if (IsUlpfecEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001070 RTC_LOG(LS_INFO)
brandtre950cad2016-11-15 05:25:41 -08001071 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1072 DisableUlpfec();
1073 }
1074 }
1075
Per83d09102016-04-15 14:59:13 +02001076 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001077 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1078 // is a waste of bandwidth since FEC packets still have to be transmitted.
1079 // Note that this is not the case with FlexFEC.
1080 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001081 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001082 config_->encoder_settings.payload_name)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001083 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001084 << "Transmitting payload type without picture ID using "
1085 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1086 "also have to be retransmitted. Disabling ULPFEC.";
1087 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001088 }
1089
brandtre6f98c72016-11-11 03:28:30 -08001090 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001091 //
brandtre6f98c72016-11-11 03:28:30 -08001092 // Due to how old receivers work, we need to always send RED if it has been
1093 // negotiated. This is a remnant of an old RED/RTX workaround, see
1094 // https://codereview.webrtc.org/2469093003.
1095 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1096 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1097 // no point in using RED without ULPFEC.
1098 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001099 RTC_DCHECK_GE(red_payload_type, 0);
1100 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001101 }
brandtre6f98c72016-11-11 03:28:30 -08001102 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001103 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1104 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001105 if (!IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001106 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001107 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1108 DisableUlpfec();
1109 }
Per83d09102016-04-15 14:59:13 +02001110 }
1111
1112 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1113 // Set NACK.
1114 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001115 true,
Per83d09102016-04-15 14:59:13 +02001116 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001117 // Set RED/ULPFEC information.
stefan60e10c72017-08-23 10:40:00 -07001118 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001119 }
1120
brandtre950cad2016-11-15 05:25:41 -08001121 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1122 // so enable that logic if either of those FEC schemes are enabled.
Ying Wang38a31b02017-12-21 12:26:19 +00001123 protection_bitrate_calculator_.SetProtectionMethod(
brandtre950cad2016-11-15 05:25:41 -08001124 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001125}
1126
perkj26091b12016-09-01 01:17:40 -07001127void VideoSendStreamImpl::ConfigureSsrcs() {
1128 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001129 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001130 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1131 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001132 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1133 rtp_rtcp->SetSSRC(ssrc);
1134
1135 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001136 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001137 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001138 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001139 }
1140
Peter Boström723ead82016-02-22 15:14:01 +01001141 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001142 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001143 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001144
Peter Boström723ead82016-02-22 15:14:01 +01001145 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001146 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1147 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1148 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001149 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1150 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001151 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001152 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001153 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001154 }
1155
Peter Boström723ead82016-02-22 15:14:01 +01001156 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001157 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001158 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001159 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1160 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001161 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1162 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001163 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1164 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001165 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001166 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1167 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001168 }
Stefan Holmer10880012016-02-03 13:29:59 +01001169 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001170}
1171
perkj26091b12016-09-01 01:17:40 -07001172std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1173 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001174 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001175
perkj26091b12016-09-01 01:17:40 -07001176 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1177 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001178 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1179 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001180 }
1181
perkj26091b12016-09-01 01:17:40 -07001182 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1183 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001184 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001185 }
1186
brandtr48d21a22017-05-30 02:32:12 -07001187 if (flexfec_sender_) {
1188 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1189 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1190 }
1191
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001192 return rtp_states;
1193}
1194
Ã…sa Persson4bece9a2017-10-06 10:04:04 +02001195std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
1196 const {
1197 RTC_DCHECK_RUN_ON(worker_queue_);
1198 return payload_router_.GetRtpPayloadStates();
1199}
1200
perkj26091b12016-09-01 01:17:40 -07001201void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1202 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001203 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001204 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001205 : RtcpMode::kOff);
1206 }
1207}
1208
perkj26091b12016-09-01 01:17:40 -07001209uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1210 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001211 int64_t rtt,
1212 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001213 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001214 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001215 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001216
michaelt192132e2017-01-26 09:05:27 -08001217 // Substract overhead from bitrate.
1218 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001219 uint32_t payload_bitrate_bps = bitrate_bps;
1220 if (send_side_bwe_with_overhead_) {
1221 payload_bitrate_bps -= CalculateOverheadRateBps(
1222 CalculatePacketRate(bitrate_bps,
1223 config_->rtp.max_packet_size +
1224 transport_overhead_bytes_per_packet_),
1225 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1226 bitrate_bps);
1227 }
michaelta3328772016-11-29 09:25:03 -08001228
Per69b332d2016-06-02 15:45:42 +02001229 // Get the encoder target rate. It is the estimated network rate -
1230 // protection overhead.
Ying Wang38a31b02017-12-21 12:26:19 +00001231 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001232 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1233 rtt);
1234
elad.alon0fe12162017-01-31 05:48:37 -08001235 uint32_t encoder_overhead_rate_bps =
1236 send_side_bwe_with_overhead_
1237 ? CalculateOverheadRateBps(
1238 CalculatePacketRate(encoder_target_rate_bps_,
1239 config_->rtp.max_packet_size +
1240 transport_overhead_bytes_per_packet_ -
1241 overhead_bytes_per_packet_),
1242 overhead_bytes_per_packet_ +
1243 transport_overhead_bytes_per_packet_,
1244 bitrate_bps - encoder_target_rate_bps_)
1245 : 0;
michaelt192132e2017-01-26 09:05:27 -08001246
1247 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1248 // protection_bitrate includes overhead.
1249 uint32_t protection_bitrate =
1250 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001251
perkj26091b12016-09-01 01:17:40 -07001252 encoder_target_rate_bps_ =
1253 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001254 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1255 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001256 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001257 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001258}
1259
palmkviste75f2042016-09-28 06:19:48 -07001260void VideoSendStreamImpl::EnableEncodedFrameRecording(
1261 const std::vector<rtc::PlatformFile>& files,
1262 size_t byte_limit) {
1263 {
1264 rtc::CritScope lock(&ivf_writers_crit_);
1265 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1266 if (i < files.size()) {
1267 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1268 } else {
1269 file_writers_[i].reset();
1270 }
1271 }
1272 }
1273
1274 if (!files.empty()) {
1275 // Make a keyframe appear as early as possible in the logs, to give actually
1276 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001277 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001278 }
1279}
1280
perkj26091b12016-09-01 01:17:40 -07001281int VideoSendStreamImpl::ProtectionRequest(
1282 const FecProtectionParams* delta_params,
1283 const FecProtectionParams* key_params,
1284 uint32_t* sent_video_rate_bps,
1285 uint32_t* sent_nack_rate_bps,
1286 uint32_t* sent_fec_rate_bps) {
1287 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001288 *sent_video_rate_bps = 0;
1289 *sent_nack_rate_bps = 0;
1290 *sent_fec_rate_bps = 0;
1291 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1292 uint32_t not_used = 0;
1293 uint32_t module_video_rate = 0;
1294 uint32_t module_fec_rate = 0;
1295 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001296 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001297 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1298 &module_nack_rate);
1299 *sent_video_rate_bps += module_video_rate;
1300 *sent_nack_rate_bps += module_nack_rate;
1301 *sent_fec_rate_bps += module_fec_rate;
1302 }
1303 return 0;
1304}
1305
michaelta3328772016-11-29 09:25:03 -08001306void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1307 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1308 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1309}
1310
michaelt79e05882016-11-08 02:50:09 -08001311void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001312 size_t transport_overhead_bytes_per_packet) {
1313 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001314 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
nisse284542b2017-01-10 08:58:32 -08001315 return;
1316 }
1317
michaelta3328772016-11-29 09:25:03 -08001318 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001319
nisseb8f9a322017-03-27 05:36:15 -07001320 transport_->send_side_cc()->SetTransportOverhead(
1321 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001322
1323 size_t rtp_packet_size =
1324 std::min(config_->rtp.max_packet_size,
1325 kPathMTU - transport_overhead_bytes_per_packet_);
1326
michaelta3328772016-11-29 09:25:03 -08001327 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001328 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001329 }
michaelt79e05882016-11-08 02:50:09 -08001330}
1331
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001332} // namespace internal
1333} // namespace webrtc