blob: 6b406a05770a5c6cf920fdb4bb26b344af4b9af6 [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"
Mirko Bonadei71207422017-09-15 13:58:09 +020020#include "common_types.h" // NOLINT(build/include)
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020021#include "common_video/include/video_bitrate_allocator.h"
22#include "modules/bitrate_controller/include/bitrate_controller.h"
23#include "modules/congestion_controller/include/send_side_congestion_controller.h"
24#include "modules/pacing/alr_detector.h"
25#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"
31#include "rtc_base/file.h"
32#include "rtc_base/location.h"
33#include "rtc_base/logging.h"
34#include "rtc_base/trace_event.h"
35#include "rtc_base/weak_ptr.h"
36#include "system_wrappers/include/field_trial.h"
37#include "video/call_stats.h"
38#include "video/payload_router.h"
Ying Wang38a31b02017-12-21 12:26:19 +000039#include "call/video_send_stream.h"
pbos@webrtc.org29d58392013-05-16 12:08:03 +000040
41namespace webrtc {
mflodman949c2f02015-10-16 02:31:11 -070042
Per83d09102016-04-15 14:59:13 +020043static const int kMinSendSidePacketHistorySize = 600;
Per83d09102016-04-15 14:59:13 +020044namespace {
45
nisse284542b2017-01-10 08:58:32 -080046// We don't do MTU discovery, so assume that we have the standard ethernet MTU.
47const size_t kPathMTU = 1500;
48
Per83d09102016-04-15 14:59:13 +020049std::vector<RtpRtcp*> CreateRtpRtcpModules(
50 Transport* outgoing_transport,
51 RtcpIntraFrameObserver* intra_frame_callback,
52 RtcpBandwidthObserver* bandwidth_callback,
nisseb8f9a322017-03-27 05:36:15 -070053 RtpTransportControllerSendInterface* transport,
Per83d09102016-04-15 14:59:13 +020054 RtcpRttStats* rtt_stats,
brandtre950cad2016-11-15 05:25:41 -080055 FlexfecSender* flexfec_sender,
Per83d09102016-04-15 14:59:13 +020056 SendStatisticsProxy* stats_proxy,
asapersson35151f32016-05-02 23:44:01 -070057 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -070058 RtcEventLog* event_log,
sprangcd349d92016-07-13 09:11:28 -070059 RateLimiter* retransmission_rate_limiter,
michaelta3328772016-11-29 09:25:03 -080060 OverheadObserver* overhead_observer,
sprang168794c2017-07-06 04:38:06 -070061 size_t num_modules,
62 RtpKeepAliveConfig keepalive_config) {
kwibergaf476c72016-11-28 15:21:39 -080063 RTC_DCHECK_GT(num_modules, 0);
Per83d09102016-04-15 14:59:13 +020064 RtpRtcp::Configuration configuration;
Per83d09102016-04-15 14:59:13 +020065 configuration.audio = false;
66 configuration.receiver_only = false;
brandtre950cad2016-11-15 05:25:41 -080067 configuration.flexfec_sender = flexfec_sender;
Per83d09102016-04-15 14:59:13 +020068 configuration.outgoing_transport = outgoing_transport;
69 configuration.intra_frame_callback = intra_frame_callback;
tereliusadafe0b2016-05-26 01:58:40 -070070 configuration.bandwidth_callback = bandwidth_callback;
nisseb8f9a322017-03-27 05:36:15 -070071 configuration.transport_feedback_callback =
72 transport->transport_feedback_observer();
Per83d09102016-04-15 14:59:13 +020073 configuration.rtt_stats = rtt_stats;
74 configuration.rtcp_packet_type_counter_observer = stats_proxy;
nisseb8f9a322017-03-27 05:36:15 -070075 configuration.paced_sender = transport->packet_sender();
Per83d09102016-04-15 14:59:13 +020076 configuration.transport_sequence_number_allocator =
nisseb8f9a322017-03-27 05:36:15 -070077 transport->packet_router();
Per83d09102016-04-15 14:59:13 +020078 configuration.send_bitrate_observer = stats_proxy;
79 configuration.send_frame_count_observer = stats_proxy;
80 configuration.send_side_delay_observer = stats_proxy;
asapersson35151f32016-05-02 23:44:01 -070081 configuration.send_packet_observer = send_delay_stats;
tereliusadafe0b2016-05-26 01:58:40 -070082 configuration.event_log = event_log;
sprangcd349d92016-07-13 09:11:28 -070083 configuration.retransmission_rate_limiter = retransmission_rate_limiter;
michaelta3328772016-11-29 09:25:03 -080084 configuration.overhead_observer = overhead_observer;
sprang168794c2017-07-06 04:38:06 -070085 configuration.keepalive_config = keepalive_config;
Per83d09102016-04-15 14:59:13 +020086 std::vector<RtpRtcp*> modules;
87 for (size_t i = 0; i < num_modules; ++i) {
88 RtpRtcp* rtp_rtcp = RtpRtcp::CreateRtpRtcp(configuration);
89 rtp_rtcp->SetSendingStatus(false);
90 rtp_rtcp->SetSendingMediaStatus(false);
91 rtp_rtcp->SetRTCPStatus(RtcpMode::kCompound);
92 modules.push_back(rtp_rtcp);
93 }
94 return modules;
95}
96
brandtre950cad2016-11-15 05:25:41 -080097// TODO(brandtr): Update this function when we support multistream protection.
98std::unique_ptr<FlexfecSender> MaybeCreateFlexfecSender(
brandtr48d21a22017-05-30 02:32:12 -070099 const VideoSendStream::Config& config,
100 const std::map<uint32_t, RtpState>& suspended_ssrcs) {
brandtr3d200bd2017-01-16 06:59:19 -0800101 if (config.rtp.flexfec.payload_type < 0) {
brandtre950cad2016-11-15 05:25:41 -0800102 return nullptr;
103 }
brandtr3d200bd2017-01-16 06:59:19 -0800104 RTC_DCHECK_GE(config.rtp.flexfec.payload_type, 0);
105 RTC_DCHECK_LE(config.rtp.flexfec.payload_type, 127);
106 if (config.rtp.flexfec.ssrc == 0) {
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))
161 return rtc::Optional<int>();
162
163 std::string group =
164 webrtc::field_trial::FindFullName(kForcedFallbackFieldTrial);
165 if (group.empty())
166 return rtc::Optional<int>();
167
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) {
173 return rtc::Optional<int>();
174 }
175
176 if (min_bps <= 0)
177 return rtc::Optional<int>();
178
179 return rtc::Optional<int>(min_bps);
180}
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,
260 std::map<uint32_t, RtpState> suspended_ssrcs,
261 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
262 VideoEncoderConfig::ContentType content_type);
perkj26091b12016-09-01 01:17:40 -0700263 ~VideoSendStreamImpl() override;
264
265 // RegisterProcessThread register |module_process_thread| with those objects
266 // that use it. Registration has to happen on the thread were
267 // |module_process_thread| was created (libjingle's worker thread).
268 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
269 // maybe |worker_queue|.
270 void RegisterProcessThread(ProcessThread* module_process_thread);
271 void DeRegisterProcessThread();
272
273 void SignalNetworkState(NetworkState state);
274 bool DeliverRtcp(const uint8_t* packet, size_t length);
275 void Start();
276 void Stop();
277
perkj26091b12016-09-01 01:17:40 -0700278 VideoSendStream::RtpStateMap GetRtpStates() const;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200279 VideoSendStream::RtpPayloadStateMap GetRtpPayloadStates() const;
perkj26091b12016-09-01 01:17:40 -0700280
palmkviste75f2042016-09-28 06:19:48 -0700281 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
282 size_t byte_limit);
283
nisse284542b2017-01-10 08:58:32 -0800284 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800285
perkj26091b12016-09-01 01:17:40 -0700286 private:
287 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200288 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700289
290 // Implements BitrateAllocatorObserver.
291 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
292 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800293 int64_t rtt,
294 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700295
296 // Implements webrtc::VCMProtectionCallback.
297 int ProtectionRequest(const FecProtectionParams* delta_params,
298 const FecProtectionParams* key_params,
299 uint32_t* sent_video_rate_bps,
300 uint32_t* sent_nack_rate_bps,
301 uint32_t* sent_fec_rate_bps) override;
302
michaelta3328772016-11-29 09:25:03 -0800303 // Implements OverheadObserver.
304 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
305
Per512ecb32016-09-23 15:52:06 +0200306 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
307 int min_transmit_bitrate_bps) override;
308
perkj26091b12016-09-01 01:17:40 -0700309 // Implements EncodedImageCallback. The implementation routes encoded frames
310 // to the |payload_router_| and |config.pre_encode_callback| if set.
311 // Called on an arbitrary encoder callback thread.
312 EncodedImageCallback::Result OnEncodedImage(
313 const EncodedImage& encoded_image,
314 const CodecSpecificInfo* codec_specific_info,
315 const RTPFragmentationHeader* fragmentation) override;
316
sprang1a646ee2016-12-01 06:34:11 -0800317 // Implements VideoBitrateAllocationObserver.
318 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
319
perkj26091b12016-09-01 01:17:40 -0700320 void ConfigureProtection();
321 void ConfigureSsrcs();
322 void SignalEncoderTimedOut();
323 void SignalEncoderActive();
324
elad.alon0fe12162017-01-31 05:48:37 -0800325 const bool send_side_bwe_with_overhead_;
Ying Wang38a31b02017-12-21 12:26:19 +0000326
perkj26091b12016-09-01 01:17:40 -0700327 SendStatisticsProxy* const stats_proxy_;
328 const VideoSendStream::Config* const config_;
329 std::map<uint32_t, RtpState> suspended_ssrcs_;
330
331 ProcessThread* module_process_thread_;
332 rtc::ThreadChecker module_process_thread_checker_;
333 rtc::TaskQueue* const worker_queue_;
334
335 rtc::CriticalSection encoder_activity_crit_sect_;
336 CheckEncoderActivityTask* check_encoder_activity_task_
danilchapa37de392017-09-09 04:17:22 -0700337 RTC_GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200338
perkj26091b12016-09-01 01:17:40 -0700339 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700340 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700341 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700342
brandtr3b941be2017-03-17 07:02:46 -0700343 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800344 std::unique_ptr<FlexfecSender> flexfec_sender_;
345
palmkviste75f2042016-09-28 06:19:48 -0700346 rtc::CriticalSection ivf_writers_crit_;
danilchapa37de392017-09-09 04:17:22 -0700347 std::unique_ptr<IvfFileWriter>
348 file_writers_[kMaxSimulcastStreams] RTC_GUARDED_BY(ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700349
350 int max_padding_bitrate_;
351 int encoder_min_bitrate_bps_;
352 uint32_t encoder_max_bitrate_bps_;
353 uint32_t encoder_target_rate_bps_;
354
mflodmancc3d4422017-08-03 08:27:51 -0700355 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700356 EncoderRtcpFeedback encoder_feedback_;
Ying Wang38a31b02017-12-21 12:26:19 +0000357 ProtectionBitrateCalculator protection_bitrate_calculator_;
perkj26091b12016-09-01 01:17:40 -0700358
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100359 RtcpBandwidthObserver* const bandwidth_observer_;
perkj26091b12016-09-01 01:17:40 -0700360 // RtpRtcp modules, declared here as they use other members on construction.
361 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
362 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700363
364 // |weak_ptr_| to our self. This is used since we can not call
365 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
366 // an existing WeakPtr.
367 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
368 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
369 // invalidated before any other members are destroyed.
370 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800371
372 rtc::CriticalSection overhead_bytes_per_packet_crit_;
danilchapa37de392017-09-09 04:17:22 -0700373 size_t overhead_bytes_per_packet_
374 RTC_GUARDED_BY(overhead_bytes_per_packet_crit_);
michaelta3328772016-11-29 09:25:03 -0800375 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700376};
377
378// TODO(tommi): See if there's a more elegant way to create a task that creates
379// an object on the correct task queue.
380class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
381 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200382 ConstructionTask(
383 std::unique_ptr<VideoSendStreamImpl>* send_stream,
384 rtc::Event* done_event,
385 SendStatisticsProxy* stats_proxy,
386 VideoStreamEncoder* video_stream_encoder,
387 ProcessThread* module_process_thread,
388 CallStats* call_stats,
389 RtpTransportControllerSendInterface* transport,
390 BitrateAllocator* bitrate_allocator,
391 SendDelayStats* send_delay_stats,
392 RtcEventLog* event_log,
393 const VideoSendStream::Config* config,
394 int initial_encoder_max_bitrate,
395 const std::map<uint32_t, RtpState>& suspended_ssrcs,
396 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
397 VideoEncoderConfig::ContentType content_type)
perkj26091b12016-09-01 01:17:40 -0700398 : send_stream_(send_stream),
399 done_event_(done_event),
400 stats_proxy_(stats_proxy),
mflodmancc3d4422017-08-03 08:27:51 -0700401 video_stream_encoder_(video_stream_encoder),
perkj26091b12016-09-01 01:17:40 -0700402 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700403 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700404 bitrate_allocator_(bitrate_allocator),
405 send_delay_stats_(send_delay_stats),
perkj26091b12016-09-01 01:17:40 -0700406 event_log_(event_log),
407 config_(config),
Per512ecb32016-09-23 15:52:06 +0200408 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
sprang89c4a7e2017-06-30 13:27:40 -0700409 suspended_ssrcs_(suspended_ssrcs),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200410 suspended_payload_states_(suspended_payload_states),
sprangdb2a9fc2017-08-09 06:42:32 -0700411 content_type_(content_type) {}
perkj26091b12016-09-01 01:17:40 -0700412
413 ~ConstructionTask() override { done_event_->Set(); }
414
415 private:
416 bool Run() override {
417 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700418 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
mflodmancc3d4422017-08-03 08:27:51 -0700419 bitrate_allocator_, send_delay_stats_, video_stream_encoder_,
420 event_log_, config_, initial_encoder_max_bitrate_,
Lu Liu8b77aea2017-12-20 23:48:03 +0000421 std::move(suspended_ssrcs_), std::move(suspended_payload_states_),
422 content_type_));
perkj26091b12016-09-01 01:17:40 -0700423 return true;
424 }
425
426 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
427 rtc::Event* const done_event_;
428 SendStatisticsProxy* const stats_proxy_;
mflodmancc3d4422017-08-03 08:27:51 -0700429 VideoStreamEncoder* const video_stream_encoder_;
perkj26091b12016-09-01 01:17:40 -0700430 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700431 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700432 BitrateAllocator* const bitrate_allocator_;
433 SendDelayStats* const send_delay_stats_;
perkj26091b12016-09-01 01:17:40 -0700434 RtcEventLog* const event_log_;
435 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200436 int initial_encoder_max_bitrate_;
perkj26091b12016-09-01 01:17:40 -0700437 std::map<uint32_t, RtpState> suspended_ssrcs_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200438 std::map<uint32_t, RtpPayloadState> suspended_payload_states_;
sprang89c4a7e2017-06-30 13:27:40 -0700439 const VideoEncoderConfig::ContentType content_type_;
perkj26091b12016-09-01 01:17:40 -0700440};
441
442class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
443 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200444 DestructAndGetRtpStateTask(
445 VideoSendStream::RtpStateMap* state_map,
446 VideoSendStream::RtpPayloadStateMap* payload_state_map,
447 std::unique_ptr<VideoSendStreamImpl> send_stream,
448 rtc::Event* done_event)
perkj26091b12016-09-01 01:17:40 -0700449 : state_map_(state_map),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200450 payload_state_map_(payload_state_map),
perkj26091b12016-09-01 01:17:40 -0700451 send_stream_(std::move(send_stream)),
452 done_event_(done_event) {}
453
454 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
455
456 private:
457 bool Run() override {
458 send_stream_->Stop();
459 *state_map_ = send_stream_->GetRtpStates();
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200460 *payload_state_map_ = send_stream_->GetRtpPayloadStates();
perkj26091b12016-09-01 01:17:40 -0700461 send_stream_.reset();
462 done_event_->Set();
463 return true;
464 }
465
466 VideoSendStream::RtpStateMap* state_map_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200467 VideoSendStream::RtpPayloadStateMap* payload_state_map_;
perkj26091b12016-09-01 01:17:40 -0700468 std::unique_ptr<VideoSendStreamImpl> send_stream_;
469 rtc::Event* done_event_;
470};
471
472// CheckEncoderActivityTask is used for tracking when the encoder last produced
473// and encoded video frame. If the encoder has not produced anything the last
474// kEncoderTimeOutMs we also want to stop sending padding.
475class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
476 public:
477 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700478 explicit CheckEncoderActivityTask(
479 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
480 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700481
482 void Stop() {
483 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700484 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700485 }
486
487 void UpdateEncoderActivity() {
488 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
489 // whatever thread the real encoder implementation run on. In the case of
490 // hardware encoders, there might be several encoders
491 // running in parallel on different threads.
492 rtc::AtomicOps::ReleaseStore(&activity_, 1);
493 }
494
495 private:
496 bool Run() override {
497 RTC_CHECK(task_checker_.CalledSequentially());
498 if (!send_stream_)
499 return true;
500 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
501 if (!timed_out_) {
502 send_stream_->SignalEncoderTimedOut();
503 }
504 timed_out_ = true;
505 } else if (timed_out_) {
506 send_stream_->SignalEncoderActive();
507 timed_out_ = false;
508 }
509 rtc::AtomicOps::ReleaseStore(&activity_, 0);
510
511 rtc::TaskQueue::Current()->PostDelayedTask(
512 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
513 // Return false to prevent this task from being deleted. Ownership has been
514 // transferred to the task queue when PostDelayedTask was called.
515 return false;
516 }
517 volatile int activity_;
518
519 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700520 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700521 bool timed_out_;
522};
523
Per512ecb32016-09-23 15:52:06 +0200524class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700525 public:
perkj8ff860a2016-10-03 00:30:04 -0700526 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200527 std::vector<VideoStream> streams,
528 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700529 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200530 streams_(std::move(streams)),
531 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700532
533 private:
534 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700535 if (send_stream_)
536 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
537 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700538 return true;
539 }
540
perkj8ff860a2016-10-03 00:30:04 -0700541 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200542 std::vector<VideoStream> streams_;
543 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700544};
545
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000546VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200547 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200548 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700549 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200550 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700551 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800552 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700553 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700554 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700555 VideoSendStream::Config config,
556 VideoEncoderConfig encoder_config,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200557 const std::map<uint32_t, RtpState>& suspended_ssrcs,
558 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
perkj26091b12016-09-01 01:17:40 -0700559 : worker_queue_(worker_queue),
560 thread_sync_event_(false /* manual_reset */, false),
561 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800562 config,
563 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800564 config_(std::move(config)),
565 content_type_(encoder_config.content_type) {
mflodmancc3d4422017-08-03 08:27:51 -0700566 video_stream_encoder_.reset(
567 new VideoStreamEncoder(num_cpu_cores, &stats_proxy_,
568 config_.encoder_settings,
569 config_.pre_encode_callback,
mflodmancc3d4422017-08-03 08:27:51 -0700570 std::unique_ptr<OveruseFrameDetector>()));
perkj26091b12016-09-01 01:17:40 -0700571 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
mflodmancc3d4422017-08-03 08:27:51 -0700572 &send_stream_, &thread_sync_event_, &stats_proxy_,
573 video_stream_encoder_.get(), module_process_thread, call_stats, transport,
574 bitrate_allocator, send_delay_stats, event_log, &config_,
Lu Liu8b77aea2017-12-20 23:48:03 +0000575 encoder_config.max_bitrate_bps, suspended_ssrcs, suspended_payload_states,
576 encoder_config.content_type)));
perkj26091b12016-09-01 01:17:40 -0700577
578 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
579 // |module_process_thread| must be registered and deregistered on the thread
580 // it was created on.
581 thread_sync_event_.Wait(rtc::Event::kForever);
582 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800583 // TODO(sprang): Enable this also for regular video calls if it works well.
584 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
585 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700586 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800587 }
Ying Wang38a31b02017-12-21 12:26:19 +0000588
perkj26091b12016-09-01 01:17:40 -0700589 ReconfigureVideoEncoder(std::move(encoder_config));
590}
591
592VideoSendStream::~VideoSendStream() {
593 RTC_DCHECK_RUN_ON(&thread_checker_);
594 RTC_DCHECK(!send_stream_);
595}
596
597void VideoSendStream::Start() {
598 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100599 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
perkj26091b12016-09-01 01:17:40 -0700600 VideoSendStreamImpl* send_stream = send_stream_.get();
601 worker_queue_->PostTask([this, send_stream] {
602 send_stream->Start();
603 thread_sync_event_.Set();
604 });
605
606 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700607 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
608 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700609 thread_sync_event_.Wait(rtc::Event::kForever);
610}
611
612void VideoSendStream::Stop() {
613 RTC_DCHECK_RUN_ON(&thread_checker_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100614 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
perkj26091b12016-09-01 01:17:40 -0700615 VideoSendStreamImpl* send_stream = send_stream_.get();
616 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
617}
618
perkja49cbd32016-09-16 07:53:41 -0700619void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700620 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
621 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700622 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700623 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700624}
625
626void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700627 // TODO(perkj): Some test cases in VideoSendStreamTest call
628 // ReconfigureVideoEncoder from the network thread.
629 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800630 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700631 video_stream_encoder_->ConfigureEncoder(std::move(config),
632 config_.rtp.max_packet_size,
633 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700634}
635
636VideoSendStream::Stats VideoSendStream::GetStats() {
637 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
638 // a network thread. See comment in Call::GetStats().
639 // RTC_DCHECK_RUN_ON(&thread_checker_);
640 return stats_proxy_.GetStats();
641}
642
643void VideoSendStream::SignalNetworkState(NetworkState state) {
644 RTC_DCHECK_RUN_ON(&thread_checker_);
645 VideoSendStreamImpl* send_stream = send_stream_.get();
646 worker_queue_->PostTask(
647 [send_stream, state] { send_stream->SignalNetworkState(state); });
648}
649
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200650void VideoSendStream::StopPermanentlyAndGetRtpStates(
651 VideoSendStream::RtpStateMap* rtp_state_map,
652 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700653 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700654 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700655 send_stream_->DeRegisterProcessThread();
656 worker_queue_->PostTask(
657 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200658 rtp_state_map, payload_state_map, std::move(send_stream_),
659 &thread_sync_event_)));
perkj26091b12016-09-01 01:17:40 -0700660 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700661}
662
nisse284542b2017-01-10 08:58:32 -0800663void VideoSendStream::SetTransportOverhead(
664 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800665 RTC_DCHECK_RUN_ON(&thread_checker_);
666 VideoSendStreamImpl* send_stream = send_stream_.get();
667 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
668 send_stream->SetTransportOverhead(transport_overhead_per_packet);
669 });
670}
671
perkj26091b12016-09-01 01:17:40 -0700672bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
673 // Called on a network thread.
674 return send_stream_->DeliverRtcp(packet, length);
675}
676
palmkviste75f2042016-09-28 06:19:48 -0700677void VideoSendStream::EnableEncodedFrameRecording(
678 const std::vector<rtc::PlatformFile>& files,
679 size_t byte_limit) {
680 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
681}
682
perkj26091b12016-09-01 01:17:40 -0700683VideoSendStreamImpl::VideoSendStreamImpl(
684 SendStatisticsProxy* stats_proxy,
685 rtc::TaskQueue* worker_queue,
686 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700687 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700688 BitrateAllocator* bitrate_allocator,
689 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700690 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700691 RtcEventLog* event_log,
692 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200693 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700694 std::map<uint32_t, RtpState> suspended_ssrcs,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200695 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
sprangdb2a9fc2017-08-09 06:42:32 -0700696 VideoEncoderConfig::ContentType content_type)
sprangc1b57a12017-02-28 08:50:47 -0800697 : send_side_bwe_with_overhead_(
698 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800699 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000700 config_(config),
perkj26091b12016-09-01 01:17:40 -0700701 suspended_ssrcs_(std::move(suspended_ssrcs)),
702 module_process_thread_(nullptr),
703 worker_queue_(worker_queue),
704 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200705 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700706 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100707 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700708 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700709 max_padding_bitrate_(0),
710 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200711 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700712 encoder_target_rate_bps_(0),
mflodmancc3d4422017-08-03 08:27:51 -0700713 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700714 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700715 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700716 video_stream_encoder),
Ying Wang38a31b02017-12-21 12:26:19 +0000717 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100718 bandwidth_observer_(transport->send_side_cc()->GetBandwidthObserver()),
nisseb8f9a322017-03-27 05:36:15 -0700719 rtp_rtcp_modules_(CreateRtpRtcpModules(
720 config_->send_transport,
721 &encoder_feedback_,
Sebastian Jansson8d9c5402017-11-15 17:22:16 +0100722 bandwidth_observer_,
nisseb8f9a322017-03-27 05:36:15 -0700723 transport,
724 call_stats_->rtcp_rtt_stats(),
725 flexfec_sender_.get(),
726 stats_proxy_,
727 send_delay_stats,
728 event_log,
729 transport->send_side_cc()->GetRetransmissionRateLimiter(),
730 this,
sprang168794c2017-07-06 04:38:06 -0700731 config_->rtp.ssrcs.size(),
sprangdb2a9fc2017-08-09 06:42:32 -0700732 transport->keepalive_config())),
perkj26091b12016-09-01 01:17:40 -0700733 payload_router_(rtp_rtcp_modules_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200734 config_->rtp.ssrcs,
735 config_->encoder_settings.payload_type,
736 suspended_payload_states),
michaelta3328772016-11-29 09:25:03 -0800737 weak_ptr_factory_(this),
738 overhead_bytes_per_packet_(0),
739 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700740 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100741 RTC_LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700742 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700743 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100744
perkj26091b12016-09-01 01:17:40 -0700745 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100746 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700747 RTC_DCHECK(transport_);
748 RTC_DCHECK(transport_->send_side_cc());
stefand7a418f2017-08-08 06:51:05 -0700749 RTC_CHECK(field_trial::FindFullName(
750 AlrDetector::kStrictPacingAndProbingExperimentName)
751 .empty() ||
752 field_trial::FindFullName(
753 AlrDetector::kScreenshareProbingBweExperimentName)
754 .empty());
Erik Språng7c8cca32017-10-24 17:05:18 +0200755 // If send-side BWE is enabled, check if we should apply updated probing and
756 // pacing settings.
757 if (TransportSeqNumExtensionConfigured(*config_)) {
758 rtc::Optional<AlrDetector::AlrExperimentSettings> alr_settings;
759 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
760 alr_settings = AlrDetector::ParseAlrSettingsFromFieldTrial(
761 AlrDetector::kScreenshareProbingBweExperimentName);
762 } else {
763 alr_settings = AlrDetector::ParseAlrSettingsFromFieldTrial(
764 AlrDetector::kStrictPacingAndProbingExperimentName);
765 }
766 if (alr_settings) {
767 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
768 transport->pacer()->SetPacingFactor(alr_settings->pacing_factor);
769 transport->pacer()->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
770 }
sprang89c4a7e2017-06-30 13:27:40 -0700771 }
772
773 if (config_->periodic_alr_bandwidth_probing) {
774 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
775 }
sergeyu80ed35e2016-11-28 13:11:13 -0800776
Per83d09102016-04-15 14:59:13 +0200777 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800778
779 // We add the highest spatial layer first to ensure it'll be prioritized
780 // when sending padding, with the hope that the packet rate will be smaller,
781 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700782 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
783 constexpr bool remb_candidate = true;
784 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
785 }
mflodman949c2f02015-10-16 02:31:11 -0700786
perkj26091b12016-09-01 01:17:40 -0700787 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
788 const std::string& extension = config_->rtp.extensions[i].uri;
789 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200790 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700791 RTC_DCHECK_GE(id, 1);
792 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100793 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
794 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
795 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
796 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000797 }
798 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000799
Per83d09102016-04-15 14:59:13 +0200800 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000801 ConfigureSsrcs();
802
Peter Boström723ead82016-02-22 15:14:01 +0100803 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700804 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800805
Peter Boström723ead82016-02-22 15:14:01 +0100806 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700807 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
808 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800809 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100810 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700811 config_->encoder_settings.payload_type,
812 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100813 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000814
perkj26091b12016-09-01 01:17:40 -0700815 RTC_DCHECK(config_->encoder_settings.encoder);
816 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
817 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000818
mflodmancc3d4422017-08-03 08:27:51 -0700819 video_stream_encoder_->SetStartBitrate(
820 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700821
822 // Only request rotation at the source when we positively know that the remote
823 // side doesn't support the rotation extension. This allows us to prepare the
824 // encoder in the expectation that rotation is supported - which is the common
825 // case.
826 bool rotation_applied =
827 std::find_if(config_->rtp.extensions.begin(),
828 config_->rtp.extensions.end(),
829 [](const RtpExtension& extension) {
830 return extension.uri == RtpExtension::kVideoRotationUri;
831 }) == config_->rtp.extensions.end();
832
mflodmancc3d4422017-08-03 08:27:51 -0700833 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000834}
835
perkj26091b12016-09-01 01:17:40 -0700836void VideoSendStreamImpl::RegisterProcessThread(
837 ProcessThread* module_process_thread) {
838 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
839 RTC_DCHECK(!module_process_thread_);
840 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100841
perkj26091b12016-09-01 01:17:40 -0700842 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800843 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700844}
Peter Boströmca835252016-02-11 15:59:46 +0100845
perkj26091b12016-09-01 01:17:40 -0700846void VideoSendStreamImpl::DeRegisterProcessThread() {
847 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
848 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
849 module_process_thread_->DeRegisterModule(rtp_rtcp);
850}
Peter Boströma4c76882016-03-03 16:29:02 +0100851
perkj26091b12016-09-01 01:17:40 -0700852VideoSendStreamImpl::~VideoSendStreamImpl() {
853 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800854 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700855 << "VideoSendStreamImpl::Stop not called";
Mirko Bonadei675513b2017-11-09 11:09:25 +0100856 RTC_LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
Ying Wang38a31b02017-12-21 12:26:19 +0000857
Per83d09102016-04-15 14:59:13 +0200858 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700859 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200860 delete rtp_rtcp;
861 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000862}
863
perkj26091b12016-09-01 01:17:40 -0700864bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
865 // Runs on a network thread.
866 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700867 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
868 rtp_rtcp->IncomingRtcpPacket(packet, length);
869 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000870}
871
perkj26091b12016-09-01 01:17:40 -0700872void VideoSendStreamImpl::Start() {
873 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100874 RTC_LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800875 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100876 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200877 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800878 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700879
880 bitrate_allocator_->AddObserver(
881 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200882 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Lu Liu8b77aea2017-12-20 23:48:03 +0000883 config_->track_id);
perkj26091b12016-09-01 01:17:40 -0700884
885 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700886 {
perkj26091b12016-09-01 01:17:40 -0700887 rtc::CritScope lock(&encoder_activity_crit_sect_);
888 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700889 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700890 worker_queue_->PostDelayedTask(
891 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
892 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700893 }
perkj26091b12016-09-01 01:17:40 -0700894
mflodmancc3d4422017-08-03 08:27:51 -0700895 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000896}
897
perkj26091b12016-09-01 01:17:40 -0700898void VideoSendStreamImpl::Stop() {
899 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100900 RTC_LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800901 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100902 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200903 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800904 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700905 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700906 {
perkj26091b12016-09-01 01:17:40 -0700907 rtc::CritScope lock(&encoder_activity_crit_sect_);
908 check_encoder_activity_task_->Stop();
909 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700910 }
mflodmancc3d4422017-08-03 08:27:51 -0700911 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -0700912 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000913}
914
perkj26091b12016-09-01 01:17:40 -0700915void VideoSendStreamImpl::SignalEncoderTimedOut() {
916 RTC_DCHECK_RUN_ON(worker_queue_);
917 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
918 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
919 // if a camera stops producing frames.
920 if (encoder_target_rate_bps_ > 0) {
Mirko Bonadei675513b2017-11-09 11:09:25 +0100921 RTC_LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
perkj26091b12016-09-01 01:17:40 -0700922 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100923 }
924}
925
sprang1a646ee2016-12-01 06:34:11 -0800926void VideoSendStreamImpl::OnBitrateAllocationUpdated(
927 const BitrateAllocation& allocation) {
928 payload_router_.OnBitrateAllocationUpdated(allocation);
929}
930
perkj26091b12016-09-01 01:17:40 -0700931void VideoSendStreamImpl::SignalEncoderActive() {
932 RTC_DCHECK_RUN_ON(worker_queue_);
Mirko Bonadei675513b2017-11-09 11:09:25 +0100933 RTC_LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
perkj26091b12016-09-01 01:17:40 -0700934 bitrate_allocator_->AddObserver(
935 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200936 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Lu Liu8b77aea2017-12-20 23:48:03 +0000937 config_->track_id);
perkj26091b12016-09-01 01:17:40 -0700938}
939
Per512ecb32016-09-23 15:52:06 +0200940void VideoSendStreamImpl::OnEncoderConfigurationChanged(
941 std::vector<VideoStream> streams,
942 int min_transmit_bitrate_bps) {
943 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200944 worker_queue_->PostTask(
945 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700946 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200947 return;
948 }
949 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
950 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
951 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700952 RTC_DCHECK_RUN_ON(worker_queue_);
953
perkj26091b12016-09-01 01:17:40 -0700954 encoder_min_bitrate_bps_ =
Ã…sa Persson45bbc8a2017-11-13 10:16:47 +0100955 std::max(streams[0].min_bitrate_bps, GetEncoderMinBitrateBps());
perkj26091b12016-09-01 01:17:40 -0700956 encoder_max_bitrate_bps_ = 0;
Lu Liu8b77aea2017-12-20 23:48:03 +0000957 for (const auto& stream : streams)
perkj26091b12016-09-01 01:17:40 -0700958 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Per512ecb32016-09-23 15:52:06 +0200959 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
960 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -0700961
962 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +0200963 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -0700964 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000965 }
perkj26091b12016-09-01 01:17:40 -0700966
967 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +0200968 streams.back().temporal_layer_thresholds_bps.size() + 1;
Ying Wang38a31b02017-12-21 12:26:19 +0000969 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +0200970 streams[0].width, streams[0].height, number_of_temporal_layers,
971 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -0700972
sprang1a646ee2016-12-01 06:34:11 -0800973 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -0700974 // The send stream is started already. Update the allocator with new bitrate
975 // limits.
976 bitrate_allocator_->AddObserver(
977 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200978 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
Lu Liu8b77aea2017-12-20 23:48:03 +0000979 config_->track_id);
perkj26091b12016-09-01 01:17:40 -0700980 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000981}
982
perkj26091b12016-09-01 01:17:40 -0700983EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700984 const EncodedImage& encoded_image,
985 const CodecSpecificInfo* codec_specific_info,
986 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -0700987 // Encoded is called on whatever thread the real encoder implementation run
988 // on. In the case of hardware encoders, there might be several encoders
989 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -0800990 size_t simulcast_idx = 0;
991 if (codec_specific_info->codecType == kVideoCodecVP8) {
992 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
993 }
perkj26091b12016-09-01 01:17:40 -0700994 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -0800995 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
996 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
997 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -0700998 }
perkj26091b12016-09-01 01:17:40 -0700999 {
1000 rtc::CritScope lock(&encoder_activity_crit_sect_);
1001 if (check_encoder_activity_task_)
1002 check_encoder_activity_task_->UpdateEncoderActivity();
1003 }
sergeyu37ad3372016-06-14 15:29:37 -07001004
Ying Wang38a31b02017-12-21 12:26:19 +00001005 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001006 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -07001007 encoded_image, codec_specific_info, fragmentation);
1008
palmkviste75f2042016-09-28 06:19:48 -07001009 RTC_DCHECK(codec_specific_info);
1010
1011 int layer = codec_specific_info->codecType == kVideoCodecVP8
1012 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
1013 : 0;
1014 {
1015 rtc::CritScope lock(&ivf_writers_crit_);
1016 if (file_writers_[layer].get()) {
1017 bool ok = file_writers_[layer]->WriteFrame(
1018 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -07001019 RTC_DCHECK(ok);
1020 }
1021 }
1022
Sergey Ulanov525df3f2016-08-02 17:46:41 -07001023 return result;
perkjbc75d972016-05-02 06:31:25 -07001024}
1025
perkj26091b12016-09-01 01:17:40 -07001026void VideoSendStreamImpl::ConfigureProtection() {
1027 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -08001028
brandtre950cad2016-11-15 05:25:41 -08001029 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1030 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1031
1032 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001033 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1034 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001035 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001036
1037 // Shorthands.
1038 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001039 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001040 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1041 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1042
stefan60e10c72017-08-23 10:40:00 -07001043 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001044 RTC_LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
stefan60e10c72017-08-23 10:40:00 -07001045 DisableUlpfec();
1046 }
1047
brandtre950cad2016-11-15 05:25:41 -08001048 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1049 if (flexfec_enabled) {
1050 // We can safely disable RED here, because if the remote supports FlexFEC,
1051 // we know that it has a receiver without the RED/RTX workaround.
1052 // See http://crbug.com/webrtc/6650 for more information.
1053 if (IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001054 RTC_LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
brandtre950cad2016-11-15 05:25:41 -08001055 DisableRed();
1056 }
1057 if (IsUlpfecEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001058 RTC_LOG(LS_INFO)
brandtre950cad2016-11-15 05:25:41 -08001059 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1060 DisableUlpfec();
1061 }
1062 }
1063
Per83d09102016-04-15 14:59:13 +02001064 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001065 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1066 // is a waste of bandwidth since FEC packets still have to be transmitted.
1067 // Note that this is not the case with FlexFEC.
1068 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001069 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001070 config_->encoder_settings.payload_name)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001071 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001072 << "Transmitting payload type without picture ID using "
1073 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1074 "also have to be retransmitted. Disabling ULPFEC.";
1075 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001076 }
1077
brandtre6f98c72016-11-11 03:28:30 -08001078 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001079 //
brandtre6f98c72016-11-11 03:28:30 -08001080 // Due to how old receivers work, we need to always send RED if it has been
1081 // negotiated. This is a remnant of an old RED/RTX workaround, see
1082 // https://codereview.webrtc.org/2469093003.
1083 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1084 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1085 // no point in using RED without ULPFEC.
1086 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001087 RTC_DCHECK_GE(red_payload_type, 0);
1088 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001089 }
brandtre6f98c72016-11-11 03:28:30 -08001090 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001091 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1092 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001093 if (!IsRedEnabled()) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001094 RTC_LOG(LS_WARNING)
brandtre6f98c72016-11-11 03:28:30 -08001095 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1096 DisableUlpfec();
1097 }
Per83d09102016-04-15 14:59:13 +02001098 }
1099
1100 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1101 // Set NACK.
1102 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001103 true,
Per83d09102016-04-15 14:59:13 +02001104 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001105 // Set RED/ULPFEC information.
stefan60e10c72017-08-23 10:40:00 -07001106 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001107 }
1108
brandtre950cad2016-11-15 05:25:41 -08001109 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1110 // so enable that logic if either of those FEC schemes are enabled.
Ying Wang38a31b02017-12-21 12:26:19 +00001111 protection_bitrate_calculator_.SetProtectionMethod(
brandtre950cad2016-11-15 05:25:41 -08001112 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001113}
1114
perkj26091b12016-09-01 01:17:40 -07001115void VideoSendStreamImpl::ConfigureSsrcs() {
1116 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001117 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001118 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1119 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001120 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1121 rtp_rtcp->SetSSRC(ssrc);
1122
1123 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001124 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001125 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001126 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001127 }
1128
Peter Boström723ead82016-02-22 15:14:01 +01001129 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001130 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001131 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001132
Peter Boström723ead82016-02-22 15:14:01 +01001133 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001134 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1135 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1136 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001137 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1138 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001139 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001140 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001141 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001142 }
1143
Peter Boström723ead82016-02-22 15:14:01 +01001144 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001145 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001146 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001147 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1148 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001149 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1150 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001151 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1152 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001153 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001154 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1155 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001156 }
Stefan Holmer10880012016-02-03 13:29:59 +01001157 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001158}
1159
perkj26091b12016-09-01 01:17:40 -07001160std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1161 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001162 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001163
perkj26091b12016-09-01 01:17:40 -07001164 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1165 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001166 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1167 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001168 }
1169
perkj26091b12016-09-01 01:17:40 -07001170 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1171 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001172 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001173 }
1174
brandtr48d21a22017-05-30 02:32:12 -07001175 if (flexfec_sender_) {
1176 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1177 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1178 }
1179
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001180 return rtp_states;
1181}
1182
Ã…sa Persson4bece9a2017-10-06 10:04:04 +02001183std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
1184 const {
1185 RTC_DCHECK_RUN_ON(worker_queue_);
1186 return payload_router_.GetRtpPayloadStates();
1187}
1188
perkj26091b12016-09-01 01:17:40 -07001189void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1190 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001191 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001192 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001193 : RtcpMode::kOff);
1194 }
1195}
1196
perkj26091b12016-09-01 01:17:40 -07001197uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1198 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001199 int64_t rtt,
1200 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001201 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001202 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001203 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001204
michaelt192132e2017-01-26 09:05:27 -08001205 // Substract overhead from bitrate.
1206 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001207 uint32_t payload_bitrate_bps = bitrate_bps;
1208 if (send_side_bwe_with_overhead_) {
1209 payload_bitrate_bps -= CalculateOverheadRateBps(
1210 CalculatePacketRate(bitrate_bps,
1211 config_->rtp.max_packet_size +
1212 transport_overhead_bytes_per_packet_),
1213 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1214 bitrate_bps);
1215 }
michaelta3328772016-11-29 09:25:03 -08001216
Per69b332d2016-06-02 15:45:42 +02001217 // Get the encoder target rate. It is the estimated network rate -
1218 // protection overhead.
Ying Wang38a31b02017-12-21 12:26:19 +00001219 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001220 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1221 rtt);
1222
elad.alon0fe12162017-01-31 05:48:37 -08001223 uint32_t encoder_overhead_rate_bps =
1224 send_side_bwe_with_overhead_
1225 ? CalculateOverheadRateBps(
1226 CalculatePacketRate(encoder_target_rate_bps_,
1227 config_->rtp.max_packet_size +
1228 transport_overhead_bytes_per_packet_ -
1229 overhead_bytes_per_packet_),
1230 overhead_bytes_per_packet_ +
1231 transport_overhead_bytes_per_packet_,
1232 bitrate_bps - encoder_target_rate_bps_)
1233 : 0;
michaelt192132e2017-01-26 09:05:27 -08001234
1235 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1236 // protection_bitrate includes overhead.
1237 uint32_t protection_bitrate =
1238 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001239
perkj26091b12016-09-01 01:17:40 -07001240 encoder_target_rate_bps_ =
1241 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001242 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1243 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001244 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001245 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001246}
1247
palmkviste75f2042016-09-28 06:19:48 -07001248void VideoSendStreamImpl::EnableEncodedFrameRecording(
1249 const std::vector<rtc::PlatformFile>& files,
1250 size_t byte_limit) {
1251 {
1252 rtc::CritScope lock(&ivf_writers_crit_);
1253 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1254 if (i < files.size()) {
1255 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1256 } else {
1257 file_writers_[i].reset();
1258 }
1259 }
1260 }
1261
1262 if (!files.empty()) {
1263 // Make a keyframe appear as early as possible in the logs, to give actually
1264 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001265 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001266 }
1267}
1268
perkj26091b12016-09-01 01:17:40 -07001269int VideoSendStreamImpl::ProtectionRequest(
1270 const FecProtectionParams* delta_params,
1271 const FecProtectionParams* key_params,
1272 uint32_t* sent_video_rate_bps,
1273 uint32_t* sent_nack_rate_bps,
1274 uint32_t* sent_fec_rate_bps) {
1275 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001276 *sent_video_rate_bps = 0;
1277 *sent_nack_rate_bps = 0;
1278 *sent_fec_rate_bps = 0;
1279 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1280 uint32_t not_used = 0;
1281 uint32_t module_video_rate = 0;
1282 uint32_t module_fec_rate = 0;
1283 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001284 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001285 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1286 &module_nack_rate);
1287 *sent_video_rate_bps += module_video_rate;
1288 *sent_nack_rate_bps += module_nack_rate;
1289 *sent_fec_rate_bps += module_fec_rate;
1290 }
1291 return 0;
1292}
1293
michaelta3328772016-11-29 09:25:03 -08001294void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1295 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1296 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1297}
1298
michaelt79e05882016-11-08 02:50:09 -08001299void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001300 size_t transport_overhead_bytes_per_packet) {
1301 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
Mirko Bonadei675513b2017-11-09 11:09:25 +01001302 RTC_LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
nisse284542b2017-01-10 08:58:32 -08001303 return;
1304 }
1305
michaelta3328772016-11-29 09:25:03 -08001306 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001307
nisseb8f9a322017-03-27 05:36:15 -07001308 transport_->send_side_cc()->SetTransportOverhead(
1309 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001310
1311 size_t rtp_packet_size =
1312 std::min(config_->rtp.max_packet_size,
1313 kPathMTU - transport_overhead_bytes_per_packet_);
1314
michaelta3328772016-11-29 09:25:03 -08001315 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001316 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001317 }
michaelt79e05882016-11-08 02:50:09 -08001318}
1319
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001320} // namespace internal
1321} // namespace webrtc