blob: 7ab2a721c415f4a754827dafc9dda0f9e26cbd62 [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
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100287 rtc::Optional<float> configured_pacing_factor_;
288
perkj26091b12016-09-01 01:17:40 -0700289 private:
290 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200291 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700292
293 // Implements BitrateAllocatorObserver.
294 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
295 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800296 int64_t rtt,
297 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700298
299 // Implements webrtc::VCMProtectionCallback.
300 int ProtectionRequest(const FecProtectionParams* delta_params,
301 const FecProtectionParams* key_params,
302 uint32_t* sent_video_rate_bps,
303 uint32_t* sent_nack_rate_bps,
304 uint32_t* sent_fec_rate_bps) override;
305
michaelta3328772016-11-29 09:25:03 -0800306 // Implements OverheadObserver.
307 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
308
Per512ecb32016-09-23 15:52:06 +0200309 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
310 int min_transmit_bitrate_bps) override;
311
perkj26091b12016-09-01 01:17:40 -0700312 // Implements EncodedImageCallback. The implementation routes encoded frames
313 // to the |payload_router_| and |config.pre_encode_callback| if set.
314 // Called on an arbitrary encoder callback thread.
315 EncodedImageCallback::Result OnEncodedImage(
316 const EncodedImage& encoded_image,
317 const CodecSpecificInfo* codec_specific_info,
318 const RTPFragmentationHeader* fragmentation) override;
319
sprang1a646ee2016-12-01 06:34:11 -0800320 // Implements VideoBitrateAllocationObserver.
321 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
322
perkj26091b12016-09-01 01:17:40 -0700323 void ConfigureProtection();
324 void ConfigureSsrcs();
325 void SignalEncoderTimedOut();
326 void SignalEncoderActive();
327
elad.alon0fe12162017-01-31 05:48:37 -0800328 const bool send_side_bwe_with_overhead_;
Ying Wang38a31b02017-12-21 12:26:19 +0000329
perkj26091b12016-09-01 01:17:40 -0700330 SendStatisticsProxy* const stats_proxy_;
331 const VideoSendStream::Config* const config_;
332 std::map<uint32_t, RtpState> suspended_ssrcs_;
333
334 ProcessThread* module_process_thread_;
335 rtc::ThreadChecker module_process_thread_checker_;
336 rtc::TaskQueue* const worker_queue_;
337
338 rtc::CriticalSection encoder_activity_crit_sect_;
339 CheckEncoderActivityTask* check_encoder_activity_task_
danilchapa37de392017-09-09 04:17:22 -0700340 RTC_GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200341
perkj26091b12016-09-01 01:17:40 -0700342 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700343 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700344 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700345
brandtr3b941be2017-03-17 07:02:46 -0700346 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800347 std::unique_ptr<FlexfecSender> flexfec_sender_;
348
palmkviste75f2042016-09-28 06:19:48 -0700349 rtc::CriticalSection ivf_writers_crit_;
danilchapa37de392017-09-09 04:17:22 -0700350 std::unique_ptr<IvfFileWriter>
351 file_writers_[kMaxSimulcastStreams] RTC_GUARDED_BY(ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700352
353 int max_padding_bitrate_;
354 int encoder_min_bitrate_bps_;
355 uint32_t encoder_max_bitrate_bps_;
356 uint32_t encoder_target_rate_bps_;
Seth Hampson24722b32017-12-22 09:36:42 -0800357 double encoder_bitrate_priority_;
perkj26091b12016-09-01 01:17:40 -0700358
mflodmancc3d4422017-08-03 08:27:51 -0700359 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700360 EncoderRtcpFeedback encoder_feedback_;
Ying Wang38a31b02017-12-21 12:26:19 +0000361 ProtectionBitrateCalculator protection_bitrate_calculator_;
perkj26091b12016-09-01 01:17:40 -0700362
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100363 RtcpBandwidthObserver* const bandwidth_observer_;
perkj26091b12016-09-01 01:17:40 -0700364 // RtpRtcp modules, declared here as they use other members on construction.
365 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
366 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700367
368 // |weak_ptr_| to our self. This is used since we can not call
369 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
370 // an existing WeakPtr.
371 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
372 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
373 // invalidated before any other members are destroyed.
374 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800375
376 rtc::CriticalSection overhead_bytes_per_packet_crit_;
danilchapa37de392017-09-09 04:17:22 -0700377 size_t overhead_bytes_per_packet_
378 RTC_GUARDED_BY(overhead_bytes_per_packet_crit_);
michaelta3328772016-11-29 09:25:03 -0800379 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700380};
381
382// TODO(tommi): See if there's a more elegant way to create a task that creates
383// an object on the correct task queue.
384class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
385 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200386 ConstructionTask(
387 std::unique_ptr<VideoSendStreamImpl>* send_stream,
388 rtc::Event* done_event,
389 SendStatisticsProxy* stats_proxy,
390 VideoStreamEncoder* video_stream_encoder,
391 ProcessThread* module_process_thread,
392 CallStats* call_stats,
393 RtpTransportControllerSendInterface* transport,
394 BitrateAllocator* bitrate_allocator,
395 SendDelayStats* send_delay_stats,
396 RtcEventLog* event_log,
397 const VideoSendStream::Config* config,
398 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800399 double initial_encoder_bitrate_priority,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200400 const std::map<uint32_t, RtpState>& suspended_ssrcs,
401 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
402 VideoEncoderConfig::ContentType content_type)
perkj26091b12016-09-01 01:17:40 -0700403 : send_stream_(send_stream),
404 done_event_(done_event),
405 stats_proxy_(stats_proxy),
mflodmancc3d4422017-08-03 08:27:51 -0700406 video_stream_encoder_(video_stream_encoder),
perkj26091b12016-09-01 01:17:40 -0700407 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700408 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700409 bitrate_allocator_(bitrate_allocator),
410 send_delay_stats_(send_delay_stats),
perkj26091b12016-09-01 01:17:40 -0700411 event_log_(event_log),
412 config_(config),
Per512ecb32016-09-23 15:52:06 +0200413 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
Seth Hampson24722b32017-12-22 09:36:42 -0800414 initial_encoder_bitrate_priority_(initial_encoder_bitrate_priority),
sprang89c4a7e2017-06-30 13:27:40 -0700415 suspended_ssrcs_(suspended_ssrcs),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200416 suspended_payload_states_(suspended_payload_states),
sprangdb2a9fc2017-08-09 06:42:32 -0700417 content_type_(content_type) {}
perkj26091b12016-09-01 01:17:40 -0700418
419 ~ConstructionTask() override { done_event_->Set(); }
420
421 private:
422 bool Run() override {
423 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700424 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
mflodmancc3d4422017-08-03 08:27:51 -0700425 bitrate_allocator_, send_delay_stats_, video_stream_encoder_,
426 event_log_, config_, initial_encoder_max_bitrate_,
Seth Hampson24722b32017-12-22 09:36:42 -0800427 initial_encoder_bitrate_priority_, std::move(suspended_ssrcs_),
428 std::move(suspended_payload_states_), content_type_));
perkj26091b12016-09-01 01:17:40 -0700429 return true;
430 }
431
432 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
433 rtc::Event* const done_event_;
434 SendStatisticsProxy* const stats_proxy_;
mflodmancc3d4422017-08-03 08:27:51 -0700435 VideoStreamEncoder* const video_stream_encoder_;
perkj26091b12016-09-01 01:17:40 -0700436 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700437 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700438 BitrateAllocator* const bitrate_allocator_;
439 SendDelayStats* const send_delay_stats_;
perkj26091b12016-09-01 01:17:40 -0700440 RtcEventLog* const event_log_;
441 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200442 int initial_encoder_max_bitrate_;
Seth Hampson24722b32017-12-22 09:36:42 -0800443 double initial_encoder_bitrate_priority_;
perkj26091b12016-09-01 01:17:40 -0700444 std::map<uint32_t, RtpState> suspended_ssrcs_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200445 std::map<uint32_t, RtpPayloadState> suspended_payload_states_;
sprang89c4a7e2017-06-30 13:27:40 -0700446 const VideoEncoderConfig::ContentType content_type_;
perkj26091b12016-09-01 01:17:40 -0700447};
448
449class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
450 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200451 DestructAndGetRtpStateTask(
452 VideoSendStream::RtpStateMap* state_map,
453 VideoSendStream::RtpPayloadStateMap* payload_state_map,
454 std::unique_ptr<VideoSendStreamImpl> send_stream,
455 rtc::Event* done_event)
perkj26091b12016-09-01 01:17:40 -0700456 : state_map_(state_map),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200457 payload_state_map_(payload_state_map),
perkj26091b12016-09-01 01:17:40 -0700458 send_stream_(std::move(send_stream)),
459 done_event_(done_event) {}
460
461 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
462
463 private:
464 bool Run() override {
465 send_stream_->Stop();
466 *state_map_ = send_stream_->GetRtpStates();
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200467 *payload_state_map_ = send_stream_->GetRtpPayloadStates();
perkj26091b12016-09-01 01:17:40 -0700468 send_stream_.reset();
469 done_event_->Set();
470 return true;
471 }
472
473 VideoSendStream::RtpStateMap* state_map_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200474 VideoSendStream::RtpPayloadStateMap* payload_state_map_;
perkj26091b12016-09-01 01:17:40 -0700475 std::unique_ptr<VideoSendStreamImpl> send_stream_;
476 rtc::Event* done_event_;
477};
478
479// CheckEncoderActivityTask is used for tracking when the encoder last produced
480// and encoded video frame. If the encoder has not produced anything the last
481// kEncoderTimeOutMs we also want to stop sending padding.
482class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
483 public:
484 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700485 explicit CheckEncoderActivityTask(
486 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
487 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700488
489 void Stop() {
490 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700491 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700492 }
493
494 void UpdateEncoderActivity() {
495 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
496 // whatever thread the real encoder implementation run on. In the case of
497 // hardware encoders, there might be several encoders
498 // running in parallel on different threads.
499 rtc::AtomicOps::ReleaseStore(&activity_, 1);
500 }
501
502 private:
503 bool Run() override {
504 RTC_CHECK(task_checker_.CalledSequentially());
505 if (!send_stream_)
506 return true;
507 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
508 if (!timed_out_) {
509 send_stream_->SignalEncoderTimedOut();
510 }
511 timed_out_ = true;
512 } else if (timed_out_) {
513 send_stream_->SignalEncoderActive();
514 timed_out_ = false;
515 }
516 rtc::AtomicOps::ReleaseStore(&activity_, 0);
517
518 rtc::TaskQueue::Current()->PostDelayedTask(
519 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
520 // Return false to prevent this task from being deleted. Ownership has been
521 // transferred to the task queue when PostDelayedTask was called.
522 return false;
523 }
524 volatile int activity_;
525
526 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700527 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700528 bool timed_out_;
529};
530
Per512ecb32016-09-23 15:52:06 +0200531class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700532 public:
perkj8ff860a2016-10-03 00:30:04 -0700533 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200534 std::vector<VideoStream> streams,
535 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700536 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200537 streams_(std::move(streams)),
538 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700539
540 private:
541 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700542 if (send_stream_)
543 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
544 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700545 return true;
546 }
547
perkj8ff860a2016-10-03 00:30:04 -0700548 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200549 std::vector<VideoStream> streams_;
550 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700551};
552
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000553VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200554 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200555 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700556 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200557 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700558 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800559 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700560 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700561 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700562 VideoSendStream::Config config,
563 VideoEncoderConfig encoder_config,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200564 const std::map<uint32_t, RtpState>& suspended_ssrcs,
565 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
perkj26091b12016-09-01 01:17:40 -0700566 : worker_queue_(worker_queue),
567 thread_sync_event_(false /* manual_reset */, false),
568 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800569 config,
570 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800571 config_(std::move(config)),
572 content_type_(encoder_config.content_type) {
mflodmancc3d4422017-08-03 08:27:51 -0700573 video_stream_encoder_.reset(
574 new VideoStreamEncoder(num_cpu_cores, &stats_proxy_,
575 config_.encoder_settings,
576 config_.pre_encode_callback,
mflodmancc3d4422017-08-03 08:27:51 -0700577 std::unique_ptr<OveruseFrameDetector>()));
perkj26091b12016-09-01 01:17:40 -0700578 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
mflodmancc3d4422017-08-03 08:27:51 -0700579 &send_stream_, &thread_sync_event_, &stats_proxy_,
580 video_stream_encoder_.get(), module_process_thread, call_stats, transport,
581 bitrate_allocator, send_delay_stats, event_log, &config_,
Seth Hampson24722b32017-12-22 09:36:42 -0800582 encoder_config.max_bitrate_bps, encoder_config.bitrate_priority,
583 suspended_ssrcs, suspended_payload_states, encoder_config.content_type)));
perkj26091b12016-09-01 01:17:40 -0700584
585 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
586 // |module_process_thread| must be registered and deregistered on the thread
587 // it was created on.
588 thread_sync_event_.Wait(rtc::Event::kForever);
589 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800590 // TODO(sprang): Enable this also for regular video calls if it works well.
591 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
592 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700593 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800594 }
Ying Wang38a31b02017-12-21 12:26:19 +0000595
perkj26091b12016-09-01 01:17:40 -0700596 ReconfigureVideoEncoder(std::move(encoder_config));
597}
598
599VideoSendStream::~VideoSendStream() {
600 RTC_DCHECK_RUN_ON(&thread_checker_);
601 RTC_DCHECK(!send_stream_);
602}
603
604void VideoSendStream::Start() {
605 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100606 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 01:17:40 -0700607 VideoSendStreamImpl* send_stream = send_stream_.get();
608 worker_queue_->PostTask([this, send_stream] {
609 send_stream->Start();
610 thread_sync_event_.Set();
611 });
612
613 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700614 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
615 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700616 thread_sync_event_.Wait(rtc::Event::kForever);
617}
618
619void VideoSendStream::Stop() {
620 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100621 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 01:17:40 -0700622 VideoSendStreamImpl* send_stream = send_stream_.get();
623 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
624}
625
perkja49cbd32016-09-16 07:53:41 -0700626void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700627 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
628 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700629 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700630 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700631}
632
633void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700634 // TODO(perkj): Some test cases in VideoSendStreamTest call
635 // ReconfigureVideoEncoder from the network thread.
636 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800637 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700638 video_stream_encoder_->ConfigureEncoder(std::move(config),
639 config_.rtp.max_packet_size,
640 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700641}
642
643VideoSendStream::Stats VideoSendStream::GetStats() {
644 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
645 // a network thread. See comment in Call::GetStats().
646 // RTC_DCHECK_RUN_ON(&thread_checker_);
647 return stats_proxy_.GetStats();
648}
649
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100650rtc::Optional<float> VideoSendStream::GetPacingFactorOverride() const {
651 return send_stream_->configured_pacing_factor_;
652}
653
perkj26091b12016-09-01 01:17:40 -0700654void VideoSendStream::SignalNetworkState(NetworkState state) {
655 RTC_DCHECK_RUN_ON(&thread_checker_);
656 VideoSendStreamImpl* send_stream = send_stream_.get();
657 worker_queue_->PostTask(
658 [send_stream, state] { send_stream->SignalNetworkState(state); });
659}
660
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200661void VideoSendStream::StopPermanentlyAndGetRtpStates(
662 VideoSendStream::RtpStateMap* rtp_state_map,
663 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700664 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700665 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700666 send_stream_->DeRegisterProcessThread();
667 worker_queue_->PostTask(
668 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200669 rtp_state_map, payload_state_map, std::move(send_stream_),
670 &thread_sync_event_)));
perkj26091b12016-09-01 01:17:40 -0700671 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700672}
673
nisse284542b2017-01-10 08:58:32 -0800674void VideoSendStream::SetTransportOverhead(
675 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800676 RTC_DCHECK_RUN_ON(&thread_checker_);
677 VideoSendStreamImpl* send_stream = send_stream_.get();
678 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
679 send_stream->SetTransportOverhead(transport_overhead_per_packet);
680 });
681}
682
perkj26091b12016-09-01 01:17:40 -0700683bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
684 // Called on a network thread.
685 return send_stream_->DeliverRtcp(packet, length);
686}
687
palmkviste75f2042016-09-28 06:19:48 -0700688void VideoSendStream::EnableEncodedFrameRecording(
689 const std::vector<rtc::PlatformFile>& files,
690 size_t byte_limit) {
691 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
692}
693
perkj26091b12016-09-01 01:17:40 -0700694VideoSendStreamImpl::VideoSendStreamImpl(
695 SendStatisticsProxy* stats_proxy,
696 rtc::TaskQueue* worker_queue,
697 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700698 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700699 BitrateAllocator* bitrate_allocator,
700 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700701 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700702 RtcEventLog* event_log,
703 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200704 int initial_encoder_max_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800705 double initial_encoder_bitrate_priority,
sprang89c4a7e2017-06-30 13:27:40 -0700706 std::map<uint32_t, RtpState> suspended_ssrcs,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200707 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
sprangdb2a9fc2017-08-09 06:42:32 -0700708 VideoEncoderConfig::ContentType content_type)
sprangc1b57a12017-02-28 08:50:47 -0800709 : send_side_bwe_with_overhead_(
710 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800711 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000712 config_(config),
perkj26091b12016-09-01 01:17:40 -0700713 suspended_ssrcs_(std::move(suspended_ssrcs)),
714 module_process_thread_(nullptr),
715 worker_queue_(worker_queue),
716 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200717 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700718 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100719 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700720 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700721 max_padding_bitrate_(0),
722 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200723 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700724 encoder_target_rate_bps_(0),
Seth Hampson24722b32017-12-22 09:36:42 -0800725 encoder_bitrate_priority_(initial_encoder_bitrate_priority),
mflodmancc3d4422017-08-03 08:27:51 -0700726 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700727 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700728 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700729 video_stream_encoder),
Ying Wang38a31b02017-12-21 12:26:19 +0000730 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100731 bandwidth_observer_(transport->send_side_cc()->GetBandwidthObserver()),
nisseb8f9a322017-03-27 05:36:15 -0700732 rtp_rtcp_modules_(CreateRtpRtcpModules(
733 config_->send_transport,
734 &encoder_feedback_,
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100735 bandwidth_observer_,
nisseb8f9a322017-03-27 05:36:15 -0700736 transport,
737 call_stats_->rtcp_rtt_stats(),
738 flexfec_sender_.get(),
739 stats_proxy_,
740 send_delay_stats,
741 event_log,
742 transport->send_side_cc()->GetRetransmissionRateLimiter(),
743 this,
sprang168794c2017-07-06 04:38:06 -0700744 config_->rtp.ssrcs.size(),
sprangdb2a9fc2017-08-09 06:42:32 -0700745 transport->keepalive_config())),
perkj26091b12016-09-01 01:17:40 -0700746 payload_router_(rtp_rtcp_modules_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200747 config_->rtp.ssrcs,
748 config_->encoder_settings.payload_type,
749 suspended_payload_states),
michaelta3328772016-11-29 09:25:03 -0800750 weak_ptr_factory_(this),
751 overhead_bytes_per_packet_(0),
752 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700753 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100754 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700755 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700756 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100757
perkj26091b12016-09-01 01:17:40 -0700758 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100759 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700760 RTC_DCHECK(transport_);
761 RTC_DCHECK(transport_->send_side_cc());
Seth Hampson24722b32017-12-22 09:36:42 -0800762 RTC_DCHECK_GT(encoder_max_bitrate_bps_, 0);
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100763
764 RTC_CHECK(AlrExperimentSettings::MaxOneFieldTrialEnabled());
Erik Språng7c8cca32017-10-24 17:05:18 +0200765 // If send-side BWE is enabled, check if we should apply updated probing and
766 // pacing settings.
767 if (TransportSeqNumExtensionConfigured(*config_)) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100768 rtc::Optional<AlrExperimentSettings> alr_settings;
Erik Språng7c8cca32017-10-24 17:05:18 +0200769 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100770 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
771 AlrExperimentSettings::kScreenshareProbingBweExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200772 } else {
Sebastian Janssoncabe3832018-01-12 10:54:18 +0100773 alr_settings = AlrExperimentSettings::CreateFromFieldTrial(
774 AlrExperimentSettings::kStrictPacingAndProbingExperimentName);
Erik Språng7c8cca32017-10-24 17:05:18 +0200775 }
776 if (alr_settings) {
777 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
778 transport->pacer()->SetPacingFactor(alr_settings->pacing_factor);
Sebastian Janssona45c8da2018-01-16 10:55:29 +0100779 configured_pacing_factor_ = alr_settings->pacing_factor;
Erik Språng7c8cca32017-10-24 17:05:18 +0200780 transport->pacer()->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
781 }
sprang89c4a7e2017-06-30 13:27:40 -0700782 }
783
784 if (config_->periodic_alr_bandwidth_probing) {
785 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
786 }
sergeyu80ed35e2016-11-28 13:11:13 -0800787
Per83d09102016-04-15 14:59:13 +0200788 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800789
790 // We add the highest spatial layer first to ensure it'll be prioritized
791 // when sending padding, with the hope that the packet rate will be smaller,
792 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700793 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
794 constexpr bool remb_candidate = true;
795 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
796 }
mflodman949c2f02015-10-16 02:31:11 -0700797
perkj26091b12016-09-01 01:17:40 -0700798 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
799 const std::string& extension = config_->rtp.extensions[i].uri;
800 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200801 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700802 RTC_DCHECK_GE(id, 1);
803 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100804 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
805 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
806 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
807 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000808 }
809 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000810
Per83d09102016-04-15 14:59:13 +0200811 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000812 ConfigureSsrcs();
813
Peter Boström723ead82016-02-22 15:14:01 +0100814 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700815 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800816
Peter Boström723ead82016-02-22 15:14:01 +0100817 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700818 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
819 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800820 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100821 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700822 config_->encoder_settings.payload_type,
823 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100824 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000825
perkj26091b12016-09-01 01:17:40 -0700826 RTC_DCHECK(config_->encoder_settings.encoder);
827 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
828 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000829
mflodmancc3d4422017-08-03 08:27:51 -0700830 video_stream_encoder_->SetStartBitrate(
831 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700832
833 // Only request rotation at the source when we positively know that the remote
834 // side doesn't support the rotation extension. This allows us to prepare the
835 // encoder in the expectation that rotation is supported - which is the common
836 // case.
837 bool rotation_applied =
838 std::find_if(config_->rtp.extensions.begin(),
839 config_->rtp.extensions.end(),
840 [](const RtpExtension& extension) {
841 return extension.uri == RtpExtension::kVideoRotationUri;
842 }) == config_->rtp.extensions.end();
843
mflodmancc3d4422017-08-03 08:27:51 -0700844 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000845}
846
perkj26091b12016-09-01 01:17:40 -0700847void VideoSendStreamImpl::RegisterProcessThread(
848 ProcessThread* module_process_thread) {
849 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
850 RTC_DCHECK(!module_process_thread_);
851 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100852
perkj26091b12016-09-01 01:17:40 -0700853 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800854 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700855}
Peter Boströmca835252016-02-11 15:59:46 +0100856
perkj26091b12016-09-01 01:17:40 -0700857void VideoSendStreamImpl::DeRegisterProcessThread() {
858 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
859 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
860 module_process_thread_->DeRegisterModule(rtp_rtcp);
861}
Peter Boströma4c76882016-03-03 16:29:02 +0100862
perkj26091b12016-09-01 01:17:40 -0700863VideoSendStreamImpl::~VideoSendStreamImpl() {
864 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800865 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700866 << "VideoSendStreamImpl::Stop not called";
Mirko Bonadei675513b2017-11-09 11:09:25 +0100867 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
Ying Wang38a31b02017-12-21 12:26:19 +0000868
Per83d09102016-04-15 14:59:13 +0200869 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700870 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200871 delete rtp_rtcp;
872 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000873}
874
perkj26091b12016-09-01 01:17:40 -0700875bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
876 // Runs on a network thread.
877 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700878 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
879 rtp_rtcp->IncomingRtcpPacket(packet, length);
880 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000881}
882
perkj26091b12016-09-01 01:17:40 -0700883void VideoSendStreamImpl::Start() {
884 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100885 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800886 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100887 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200888 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800889 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700890
891 bitrate_allocator_->AddObserver(
892 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200893 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800894 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700895
896 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700897 {
perkj26091b12016-09-01 01:17:40 -0700898 rtc::CritScope lock(&encoder_activity_crit_sect_);
899 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700900 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700901 worker_queue_->PostDelayedTask(
902 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
903 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700904 }
perkj26091b12016-09-01 01:17:40 -0700905
mflodmancc3d4422017-08-03 08:27:51 -0700906 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000907}
908
perkj26091b12016-09-01 01:17:40 -0700909void VideoSendStreamImpl::Stop() {
910 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100911 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800912 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100913 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200914 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800915 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700916 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700917 {
perkj26091b12016-09-01 01:17:40 -0700918 rtc::CritScope lock(&encoder_activity_crit_sect_);
919 check_encoder_activity_task_->Stop();
920 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700921 }
mflodmancc3d4422017-08-03 08:27:51 -0700922 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -0700923 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000924}
925
perkj26091b12016-09-01 01:17:40 -0700926void VideoSendStreamImpl::SignalEncoderTimedOut() {
927 RTC_DCHECK_RUN_ON(worker_queue_);
928 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
929 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
930 // if a camera stops producing frames.
931 if (encoder_target_rate_bps_ > 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100932 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
perkj26091b12016-09-01 01:17:40 -0700933 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100934 }
935}
936
sprang1a646ee2016-12-01 06:34:11 -0800937void VideoSendStreamImpl::OnBitrateAllocationUpdated(
938 const BitrateAllocation& allocation) {
939 payload_router_.OnBitrateAllocationUpdated(allocation);
940}
941
perkj26091b12016-09-01 01:17:40 -0700942void VideoSendStreamImpl::SignalEncoderActive() {
943 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100944 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
perkj26091b12016-09-01 01:17:40 -0700945 bitrate_allocator_->AddObserver(
946 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200947 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800948 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700949}
950
Per512ecb32016-09-23 15:52:06 +0200951void VideoSendStreamImpl::OnEncoderConfigurationChanged(
952 std::vector<VideoStream> streams,
953 int min_transmit_bitrate_bps) {
954 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200955 worker_queue_->PostTask(
956 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700957 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200958 return;
959 }
960 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
961 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
962 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700963 RTC_DCHECK_RUN_ON(worker_queue_);
964
perkj26091b12016-09-01 01:17:40 -0700965 encoder_min_bitrate_bps_ =
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100966 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
perkj26091b12016-09-01 01:17:40 -0700967 encoder_max_bitrate_bps_ = 0;
Seth Hampson24722b32017-12-22 09:36:42 -0800968 double stream_bitrate_priority_sum = 0;
969 for (const auto& stream : streams) {
Lu Liu0f17f9c2018-01-17 00:28:14 +0000970 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Seth Hampson24722b32017-12-22 09:36:42 -0800971 if (stream.bitrate_priority) {
972 RTC_DCHECK_GT(*stream.bitrate_priority, 0);
973 stream_bitrate_priority_sum += *stream.bitrate_priority;
974 }
975 }
976 RTC_DCHECK_GT(stream_bitrate_priority_sum, 0);
977 encoder_bitrate_priority_ = stream_bitrate_priority_sum;
Per512ecb32016-09-23 15:52:06 +0200978 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
979 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -0700980
981 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +0200982 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -0700983 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000984 }
perkj26091b12016-09-01 01:17:40 -0700985
986 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +0200987 streams.back().temporal_layer_thresholds_bps.size() + 1;
Ying Wang38a31b02017-12-21 12:26:19 +0000988 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +0200989 streams[0].width, streams[0].height, number_of_temporal_layers,
990 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -0700991
sprang1a646ee2016-12-01 06:34:11 -0800992 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -0700993 // The send stream is started already. Update the allocator with new bitrate
994 // limits.
995 bitrate_allocator_->AddObserver(
996 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200997 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Seth Hampson24722b32017-12-22 09:36:42 -0800998 config_->track_id, encoder_bitrate_priority_);
perkj26091b12016-09-01 01:17:40 -0700999 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001000}
1001
perkj26091b12016-09-01 01:17:40 -07001002EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001003 const EncodedImage& encoded_image,
1004 const CodecSpecificInfo* codec_specific_info,
1005 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -07001006 // Encoded is called on whatever thread the real encoder implementation run
1007 // on. In the case of hardware encoders, there might be several encoders
1008 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -08001009 size_t simulcast_idx = 0;
1010 if (codec_specific_info->codecType == kVideoCodecVP8) {
1011 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
1012 }
perkj26091b12016-09-01 01:17:40 -07001013 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -08001014 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
1015 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
1016 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -07001017 }
perkj26091b12016-09-01 01:17:40 -07001018 {
1019 rtc::CritScope lock(&encoder_activity_crit_sect_);
1020 if (check_encoder_activity_task_)
1021 check_encoder_activity_task_->UpdateEncoderActivity();
1022 }
sergeyu37ad3372016-06-14 15:29:37 -07001023
Ying Wang38a31b02017-12-21 12:26:19 +00001024 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001025 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001026 encoded_image, codec_specific_info, fragmentation);
1027
palmkviste75f2042016-09-28 06:19:48 -07001028 RTC_DCHECK(codec_specific_info);
1029
1030 int layer = codec_specific_info->codecType == kVideoCodecVP8
1031 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1032 : 0;
1033 {
1034 rtc::CritScope lock(&ivf_writers_crit_);
1035 if (file_writers_[layer].get()) {
1036 bool ok = file_writers_[layer]->WriteFrame(
1037 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001038 RTC_DCHECK(ok);
1039 }
1040 }
1041
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001042 return result;
perkjbc75d972016-05-02 06:31:25 -07001043}
1044
perkj26091b12016-09-01 01:17:40 -07001045void VideoSendStreamImpl::ConfigureProtection() {
1046 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001047
brandtre950cad2016-11-15 05:25:41 -08001048 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1049 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1050
1051 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001052 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1053 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001054 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001055
1056 // Shorthands.
1057 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001058 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001059 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1060 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1061
stefan60e10c72017-08-23 10:40:00 -07001062 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001063 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
stefan60e10c72017-08-23 10:40:00 -07001064 DisableUlpfec();
1065 }
1066
brandtre950cad2016-11-15 05:25:41 -08001067 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1068 if (flexfec_enabled) {
1069 // We can safely disable RED here, because if the remote supports FlexFEC,
1070 // we know that it has a receiver without the RED/RTX workaround.
1071 // See http://crbug.com/webrtc/6650 for more information.
1072 if (IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001073 RTC_LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
brandtre950cad2016-11-15 05:25:41 -08001074 DisableRed();
1075 }
1076 if (IsUlpfecEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001077 RTC_LOG(LS_INFO)
brandtre950cad2016-11-15 05:25:41 -08001078 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1079 DisableUlpfec();
1080 }
1081 }
1082
Per83d09102016-04-15 14:59:13 +02001083 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001084 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1085 // is a waste of bandwidth since FEC packets still have to be transmitted.
1086 // Note that this is not the case with FlexFEC.
1087 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001088 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001089 config_->encoder_settings.payload_name)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001090 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001091 << "Transmitting payload type without picture ID using "
1092 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1093 "also have to be retransmitted. Disabling ULPFEC.";
1094 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001095 }
1096
brandtre6f98c72016-11-11 03:28:30 -08001097 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001098 //
brandtre6f98c72016-11-11 03:28:30 -08001099 // Due to how old receivers work, we need to always send RED if it has been
1100 // negotiated. This is a remnant of an old RED/RTX workaround, see
1101 // https://codereview.webrtc.org/2469093003.
1102 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1103 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1104 // no point in using RED without ULPFEC.
1105 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001106 RTC_DCHECK_GE(red_payload_type, 0);
1107 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001108 }
brandtre6f98c72016-11-11 03:28:30 -08001109 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001110 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1111 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001112 if (!IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001113 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001114 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1115 DisableUlpfec();
1116 }
Per83d09102016-04-15 14:59:13 +02001117 }
1118
1119 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1120 // Set NACK.
1121 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001122 true,
Per83d09102016-04-15 14:59:13 +02001123 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001124 // Set RED/ULPFEC information.
stefan60e10c72017-08-23 10:40:00 -07001125 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001126 }
1127
brandtre950cad2016-11-15 05:25:41 -08001128 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1129 // so enable that logic if either of those FEC schemes are enabled.
Ying Wang38a31b02017-12-21 12:26:19 +00001130 protection_bitrate_calculator_.SetProtectionMethod(
brandtre950cad2016-11-15 05:25:41 -08001131 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001132}
1133
perkj26091b12016-09-01 01:17:40 -07001134void VideoSendStreamImpl::ConfigureSsrcs() {
1135 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001136 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001137 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1138 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001139 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1140 rtp_rtcp->SetSSRC(ssrc);
1141
1142 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001143 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001144 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001145 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001146 }
1147
Peter Boström723ead82016-02-22 15:14:01 +01001148 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001149 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001150 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001151
Peter Boström723ead82016-02-22 15:14:01 +01001152 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001153 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1154 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1155 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001156 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1157 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001158 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001159 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001160 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001161 }
1162
Peter Boström723ead82016-02-22 15:14:01 +01001163 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001164 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001165 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001166 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1167 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001168 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1169 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001170 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1171 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001172 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001173 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1174 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001175 }
Stefan Holmer10880012016-02-03 13:29:59 +01001176 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001177}
1178
perkj26091b12016-09-01 01:17:40 -07001179std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1180 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001181 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001182
perkj26091b12016-09-01 01:17:40 -07001183 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1184 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001185 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1186 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001187 }
1188
perkj26091b12016-09-01 01:17:40 -07001189 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1190 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001191 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001192 }
1193
brandtr48d21a22017-05-30 02:32:12 -07001194 if (flexfec_sender_) {
1195 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1196 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1197 }
1198
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001199 return rtp_states;
1200}
1201
Ã…sa Persson4bece9a2017-10-06 10:04:04 +02001202std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
1203 const {
1204 RTC_DCHECK_RUN_ON(worker_queue_);
1205 return payload_router_.GetRtpPayloadStates();
1206}
1207
perkj26091b12016-09-01 01:17:40 -07001208void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1209 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001210 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001211 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001212 : RtcpMode::kOff);
1213 }
1214}
1215
perkj26091b12016-09-01 01:17:40 -07001216uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1217 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001218 int64_t rtt,
1219 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001220 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001221 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001222 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001223
michaelt192132e2017-01-26 09:05:27 -08001224 // Substract overhead from bitrate.
1225 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001226 uint32_t payload_bitrate_bps = bitrate_bps;
1227 if (send_side_bwe_with_overhead_) {
1228 payload_bitrate_bps -= CalculateOverheadRateBps(
1229 CalculatePacketRate(bitrate_bps,
1230 config_->rtp.max_packet_size +
1231 transport_overhead_bytes_per_packet_),
1232 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1233 bitrate_bps);
1234 }
michaelta3328772016-11-29 09:25:03 -08001235
Per69b332d2016-06-02 15:45:42 +02001236 // Get the encoder target rate. It is the estimated network rate -
1237 // protection overhead.
Ying Wang38a31b02017-12-21 12:26:19 +00001238 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001239 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1240 rtt);
1241
elad.alon0fe12162017-01-31 05:48:37 -08001242 uint32_t encoder_overhead_rate_bps =
1243 send_side_bwe_with_overhead_
1244 ? CalculateOverheadRateBps(
1245 CalculatePacketRate(encoder_target_rate_bps_,
1246 config_->rtp.max_packet_size +
1247 transport_overhead_bytes_per_packet_ -
1248 overhead_bytes_per_packet_),
1249 overhead_bytes_per_packet_ +
1250 transport_overhead_bytes_per_packet_,
1251 bitrate_bps - encoder_target_rate_bps_)
1252 : 0;
michaelt192132e2017-01-26 09:05:27 -08001253
1254 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1255 // protection_bitrate includes overhead.
1256 uint32_t protection_bitrate =
1257 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001258
perkj26091b12016-09-01 01:17:40 -07001259 encoder_target_rate_bps_ =
1260 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001261 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1262 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001263 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001264 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001265}
1266
palmkviste75f2042016-09-28 06:19:48 -07001267void VideoSendStreamImpl::EnableEncodedFrameRecording(
1268 const std::vector<rtc::PlatformFile>& files,
1269 size_t byte_limit) {
1270 {
1271 rtc::CritScope lock(&ivf_writers_crit_);
1272 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1273 if (i < files.size()) {
1274 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1275 } else {
1276 file_writers_[i].reset();
1277 }
1278 }
1279 }
1280
1281 if (!files.empty()) {
1282 // Make a keyframe appear as early as possible in the logs, to give actually
1283 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001284 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001285 }
1286}
1287
perkj26091b12016-09-01 01:17:40 -07001288int VideoSendStreamImpl::ProtectionRequest(
1289 const FecProtectionParams* delta_params,
1290 const FecProtectionParams* key_params,
1291 uint32_t* sent_video_rate_bps,
1292 uint32_t* sent_nack_rate_bps,
1293 uint32_t* sent_fec_rate_bps) {
1294 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001295 *sent_video_rate_bps = 0;
1296 *sent_nack_rate_bps = 0;
1297 *sent_fec_rate_bps = 0;
1298 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1299 uint32_t not_used = 0;
1300 uint32_t module_video_rate = 0;
1301 uint32_t module_fec_rate = 0;
1302 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001303 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001304 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1305 &module_nack_rate);
1306 *sent_video_rate_bps += module_video_rate;
1307 *sent_nack_rate_bps += module_nack_rate;
1308 *sent_fec_rate_bps += module_fec_rate;
1309 }
1310 return 0;
1311}
1312
michaelta3328772016-11-29 09:25:03 -08001313void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1314 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1315 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1316}
1317
michaelt79e05882016-11-08 02:50:09 -08001318void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001319 size_t transport_overhead_bytes_per_packet) {
1320 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001321 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
nisse284542b2017-01-10 08:58:32 -08001322 return;
1323 }
1324
michaelta3328772016-11-29 09:25:03 -08001325 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001326
nisseb8f9a322017-03-27 05:36:15 -07001327 transport_->send_side_cc()->SetTransportOverhead(
1328 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001329
1330 size_t rtp_packet_size =
1331 std::min(config_->rtp.max_packet_size,
1332 kPathMTU - transport_overhead_bytes_per_packet_);
1333
michaelta3328772016-11-29 09:25:03 -08001334 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001335 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001336 }
michaelt79e05882016-11-08 02:50:09 -08001337}
1338
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001339} // namespace internal
1340} // namespace webrtc