blob: a874298404b270f011f052594ae8242c58756c8f [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"
20#include "common_types.h"
21#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"
39#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) {
brandtre950cad2016-11-15 05:25:41 -0800107 LOG(LS_WARNING) << "FlexFEC is enabled, but no FlexFEC SSRC given. "
108 "Therefore disabling FlexFEC.";
109 return nullptr;
110 }
111 if (config.rtp.flexfec.protected_media_ssrcs.empty()) {
112 LOG(LS_WARNING) << "FlexFEC is enabled, but no protected media SSRC given. "
113 "Therefore disabling FlexFEC.";
114 return nullptr;
115 }
116
117 if (config.rtp.ssrcs.size() > 1) {
118 LOG(LS_WARNING) << "Both FlexFEC and simulcast are enabled. This "
119 "combination is however not supported by our current "
120 "FlexFEC implementation. Therefore disabling FlexFEC.";
121 return nullptr;
122 }
123
124 if (config.rtp.flexfec.protected_media_ssrcs.size() > 1) {
125 LOG(LS_WARNING)
126 << "The supplied FlexfecConfig contained multiple protected "
127 "media streams, but our implementation currently only "
128 "supports protecting a single media stream. "
129 "To avoid confusion, disabling FlexFEC completely.";
130 return nullptr;
131 }
132
brandtr48d21a22017-05-30 02:32:12 -0700133 const RtpState* rtp_state = nullptr;
134 auto it = suspended_ssrcs.find(config.rtp.flexfec.ssrc);
135 if (it != suspended_ssrcs.end()) {
136 rtp_state = &it->second;
137 }
138
brandtre950cad2016-11-15 05:25:41 -0800139 RTC_DCHECK_EQ(1U, config.rtp.flexfec.protected_media_ssrcs.size());
140 return std::unique_ptr<FlexfecSender>(new FlexfecSender(
brandtr3d200bd2017-01-16 06:59:19 -0800141 config.rtp.flexfec.payload_type, config.rtp.flexfec.ssrc,
brandtre950cad2016-11-15 05:25:41 -0800142 config.rtp.flexfec.protected_media_ssrcs[0], config.rtp.extensions,
brandtr48d21a22017-05-30 02:32:12 -0700143 RTPSender::FecExtensionSizes(), rtp_state, Clock::GetRealTimeClock()));
brandtre950cad2016-11-15 05:25:41 -0800144}
145
Per83d09102016-04-15 14:59:13 +0200146} // namespace
147
Peter Boströme4499152016-02-05 11:13:28 +0100148namespace {
149
Peter Boström39593972016-02-15 11:27:15 +0100150bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
kthelgason1cdddc92017-08-24 03:52:48 -0700151 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
152 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
perkj26091b12016-09-01 01:17:40 -0700153 return true;
deadbeefc964d0b2017-04-03 10:03:35 -0700154 }
Peter Boström39593972016-02-15 11:27:15 +0100155 return false;
156}
157
Per512ecb32016-09-23 15:52:06 +0200158int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
159 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700160 bool pad_to_min_bitrate) {
161 int pad_up_to_bitrate_bps = 0;
162 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200163 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700164 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200165 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700166 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200167 for (size_t i = 0; i < streams.size() - 1; ++i)
168 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700169 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200170 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700171 }
172
173 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200174 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700175
176 return pad_up_to_bitrate_bps;
177}
178
michaelt192132e2017-01-26 09:05:27 -0800179uint32_t CalculateOverheadRateBps(int packets_per_second,
180 size_t overhead_bytes_per_packet,
181 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800182 uint32_t overhead_bps =
183 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
184 return std::min(overhead_bps, max_overhead_bps);
185}
186
187int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
188 size_t packet_size_bits = 8 * packet_size_bytes;
189 // Ceil for int value of bitrate_bps / packet_size_bits.
190 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
191 packet_size_bits);
192}
193
Peter Boströme4499152016-02-05 11:13:28 +0100194} // namespace
195
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000196namespace internal {
perkj26091b12016-09-01 01:17:40 -0700197
198// VideoSendStreamImpl implements internal::VideoSendStream.
199// It is created and destroyed on |worker_queue|. The intent is to decrease the
200// need for locking and to ensure methods are called in sequence.
201// Public methods except |DeliverRtcp| must be called on |worker_queue|.
202// DeliverRtcp is called on the libjingle worker thread or a network thread.
203// An encoder may deliver frames through the EncodedImageCallback on an
204// arbitrary thread.
205class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800206 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700207 public webrtc::VCMProtectionCallback,
mflodmancc3d4422017-08-03 08:27:51 -0700208 public VideoStreamEncoder::EncoderSink,
sprang1a646ee2016-12-01 06:34:11 -0800209 public VideoBitrateAllocationObserver {
perkj26091b12016-09-01 01:17:40 -0700210 public:
211 VideoSendStreamImpl(SendStatisticsProxy* stats_proxy,
212 rtc::TaskQueue* worker_queue,
213 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700214 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700215 BitrateAllocator* bitrate_allocator,
216 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700217 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700218 RtcEventLog* event_log,
219 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200220 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700221 std::map<uint32_t, RtpState> suspended_ssrcs,
sprangdb2a9fc2017-08-09 06:42:32 -0700222 VideoEncoderConfig::ContentType content_type);
perkj26091b12016-09-01 01:17:40 -0700223 ~VideoSendStreamImpl() override;
224
225 // RegisterProcessThread register |module_process_thread| with those objects
226 // that use it. Registration has to happen on the thread were
227 // |module_process_thread| was created (libjingle's worker thread).
228 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
229 // maybe |worker_queue|.
230 void RegisterProcessThread(ProcessThread* module_process_thread);
231 void DeRegisterProcessThread();
232
233 void SignalNetworkState(NetworkState state);
234 bool DeliverRtcp(const uint8_t* packet, size_t length);
235 void Start();
236 void Stop();
237
perkj26091b12016-09-01 01:17:40 -0700238 VideoSendStream::RtpStateMap GetRtpStates() const;
239
palmkviste75f2042016-09-28 06:19:48 -0700240 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
241 size_t byte_limit);
242
nisse284542b2017-01-10 08:58:32 -0800243 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800244
perkj26091b12016-09-01 01:17:40 -0700245 private:
246 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200247 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700248
249 // Implements BitrateAllocatorObserver.
250 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
251 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800252 int64_t rtt,
253 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700254
255 // Implements webrtc::VCMProtectionCallback.
256 int ProtectionRequest(const FecProtectionParams* delta_params,
257 const FecProtectionParams* key_params,
258 uint32_t* sent_video_rate_bps,
259 uint32_t* sent_nack_rate_bps,
260 uint32_t* sent_fec_rate_bps) override;
261
michaelta3328772016-11-29 09:25:03 -0800262 // Implements OverheadObserver.
263 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
264
Per512ecb32016-09-23 15:52:06 +0200265 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
266 int min_transmit_bitrate_bps) override;
267
perkj26091b12016-09-01 01:17:40 -0700268 // Implements EncodedImageCallback. The implementation routes encoded frames
269 // to the |payload_router_| and |config.pre_encode_callback| if set.
270 // Called on an arbitrary encoder callback thread.
271 EncodedImageCallback::Result OnEncodedImage(
272 const EncodedImage& encoded_image,
273 const CodecSpecificInfo* codec_specific_info,
274 const RTPFragmentationHeader* fragmentation) override;
275
sprang1a646ee2016-12-01 06:34:11 -0800276 // Implements VideoBitrateAllocationObserver.
277 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
278
perkj26091b12016-09-01 01:17:40 -0700279 void ConfigureProtection();
280 void ConfigureSsrcs();
281 void SignalEncoderTimedOut();
282 void SignalEncoderActive();
283
elad.alon0fe12162017-01-31 05:48:37 -0800284 const bool send_side_bwe_with_overhead_;
285
perkj26091b12016-09-01 01:17:40 -0700286 SendStatisticsProxy* const stats_proxy_;
287 const VideoSendStream::Config* const config_;
288 std::map<uint32_t, RtpState> suspended_ssrcs_;
289
290 ProcessThread* module_process_thread_;
291 rtc::ThreadChecker module_process_thread_checker_;
292 rtc::TaskQueue* const worker_queue_;
293
294 rtc::CriticalSection encoder_activity_crit_sect_;
295 CheckEncoderActivityTask* check_encoder_activity_task_
danilchapa37de392017-09-09 04:17:22 -0700296 RTC_GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200297
perkj26091b12016-09-01 01:17:40 -0700298 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700299 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700300 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700301
brandtr3b941be2017-03-17 07:02:46 -0700302 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800303 std::unique_ptr<FlexfecSender> flexfec_sender_;
304
palmkviste75f2042016-09-28 06:19:48 -0700305 rtc::CriticalSection ivf_writers_crit_;
danilchapa37de392017-09-09 04:17:22 -0700306 std::unique_ptr<IvfFileWriter>
307 file_writers_[kMaxSimulcastStreams] RTC_GUARDED_BY(ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700308
309 int max_padding_bitrate_;
310 int encoder_min_bitrate_bps_;
311 uint32_t encoder_max_bitrate_bps_;
312 uint32_t encoder_target_rate_bps_;
313
mflodmancc3d4422017-08-03 08:27:51 -0700314 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700315 EncoderRtcpFeedback encoder_feedback_;
perkj26091b12016-09-01 01:17:40 -0700316 ProtectionBitrateCalculator protection_bitrate_calculator_;
317
318 const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
319 // RtpRtcp modules, declared here as they use other members on construction.
320 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
321 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700322
323 // |weak_ptr_| to our self. This is used since we can not call
324 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
325 // an existing WeakPtr.
326 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
327 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
328 // invalidated before any other members are destroyed.
329 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800330
331 rtc::CriticalSection overhead_bytes_per_packet_crit_;
danilchapa37de392017-09-09 04:17:22 -0700332 size_t overhead_bytes_per_packet_
333 RTC_GUARDED_BY(overhead_bytes_per_packet_crit_);
michaelta3328772016-11-29 09:25:03 -0800334 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700335};
336
337// TODO(tommi): See if there's a more elegant way to create a task that creates
338// an object on the correct task queue.
339class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
340 public:
341 ConstructionTask(std::unique_ptr<VideoSendStreamImpl>* send_stream,
342 rtc::Event* done_event,
343 SendStatisticsProxy* stats_proxy,
mflodmancc3d4422017-08-03 08:27:51 -0700344 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700345 ProcessThread* module_process_thread,
346 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700347 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700348 BitrateAllocator* bitrate_allocator,
349 SendDelayStats* send_delay_stats,
perkj26091b12016-09-01 01:17:40 -0700350 RtcEventLog* event_log,
351 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200352 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700353 const std::map<uint32_t, RtpState>& suspended_ssrcs,
sprangdb2a9fc2017-08-09 06:42:32 -0700354 VideoEncoderConfig::ContentType content_type)
perkj26091b12016-09-01 01:17:40 -0700355 : send_stream_(send_stream),
356 done_event_(done_event),
357 stats_proxy_(stats_proxy),
mflodmancc3d4422017-08-03 08:27:51 -0700358 video_stream_encoder_(video_stream_encoder),
perkj26091b12016-09-01 01:17:40 -0700359 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700360 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700361 bitrate_allocator_(bitrate_allocator),
362 send_delay_stats_(send_delay_stats),
perkj26091b12016-09-01 01:17:40 -0700363 event_log_(event_log),
364 config_(config),
Per512ecb32016-09-23 15:52:06 +0200365 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
sprang89c4a7e2017-06-30 13:27:40 -0700366 suspended_ssrcs_(suspended_ssrcs),
sprangdb2a9fc2017-08-09 06:42:32 -0700367 content_type_(content_type) {}
perkj26091b12016-09-01 01:17:40 -0700368
369 ~ConstructionTask() override { done_event_->Set(); }
370
371 private:
372 bool Run() override {
373 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700374 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
mflodmancc3d4422017-08-03 08:27:51 -0700375 bitrate_allocator_, send_delay_stats_, video_stream_encoder_,
376 event_log_, config_, initial_encoder_max_bitrate_,
sprangdb2a9fc2017-08-09 06:42:32 -0700377 std::move(suspended_ssrcs_), content_type_));
perkj26091b12016-09-01 01:17:40 -0700378 return true;
379 }
380
381 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
382 rtc::Event* const done_event_;
383 SendStatisticsProxy* const stats_proxy_;
mflodmancc3d4422017-08-03 08:27:51 -0700384 VideoStreamEncoder* const video_stream_encoder_;
perkj26091b12016-09-01 01:17:40 -0700385 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700386 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700387 BitrateAllocator* const bitrate_allocator_;
388 SendDelayStats* const send_delay_stats_;
perkj26091b12016-09-01 01:17:40 -0700389 RtcEventLog* const event_log_;
390 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200391 int initial_encoder_max_bitrate_;
perkj26091b12016-09-01 01:17:40 -0700392 std::map<uint32_t, RtpState> suspended_ssrcs_;
sprang89c4a7e2017-06-30 13:27:40 -0700393 const VideoEncoderConfig::ContentType content_type_;
perkj26091b12016-09-01 01:17:40 -0700394};
395
396class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
397 public:
398 DestructAndGetRtpStateTask(VideoSendStream::RtpStateMap* state_map,
399 std::unique_ptr<VideoSendStreamImpl> send_stream,
400 rtc::Event* done_event)
401 : state_map_(state_map),
402 send_stream_(std::move(send_stream)),
403 done_event_(done_event) {}
404
405 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
406
407 private:
408 bool Run() override {
409 send_stream_->Stop();
410 *state_map_ = send_stream_->GetRtpStates();
411 send_stream_.reset();
412 done_event_->Set();
413 return true;
414 }
415
416 VideoSendStream::RtpStateMap* state_map_;
417 std::unique_ptr<VideoSendStreamImpl> send_stream_;
418 rtc::Event* done_event_;
419};
420
421// CheckEncoderActivityTask is used for tracking when the encoder last produced
422// and encoded video frame. If the encoder has not produced anything the last
423// kEncoderTimeOutMs we also want to stop sending padding.
424class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
425 public:
426 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700427 explicit CheckEncoderActivityTask(
428 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
429 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700430
431 void Stop() {
432 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700433 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700434 }
435
436 void UpdateEncoderActivity() {
437 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
438 // whatever thread the real encoder implementation run on. In the case of
439 // hardware encoders, there might be several encoders
440 // running in parallel on different threads.
441 rtc::AtomicOps::ReleaseStore(&activity_, 1);
442 }
443
444 private:
445 bool Run() override {
446 RTC_CHECK(task_checker_.CalledSequentially());
447 if (!send_stream_)
448 return true;
449 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
450 if (!timed_out_) {
451 send_stream_->SignalEncoderTimedOut();
452 }
453 timed_out_ = true;
454 } else if (timed_out_) {
455 send_stream_->SignalEncoderActive();
456 timed_out_ = false;
457 }
458 rtc::AtomicOps::ReleaseStore(&activity_, 0);
459
460 rtc::TaskQueue::Current()->PostDelayedTask(
461 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
462 // Return false to prevent this task from being deleted. Ownership has been
463 // transferred to the task queue when PostDelayedTask was called.
464 return false;
465 }
466 volatile int activity_;
467
468 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700469 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700470 bool timed_out_;
471};
472
Per512ecb32016-09-23 15:52:06 +0200473class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700474 public:
perkj8ff860a2016-10-03 00:30:04 -0700475 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200476 std::vector<VideoStream> streams,
477 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700478 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200479 streams_(std::move(streams)),
480 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700481
482 private:
483 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700484 if (send_stream_)
485 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
486 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700487 return true;
488 }
489
perkj8ff860a2016-10-03 00:30:04 -0700490 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200491 std::vector<VideoStream> streams_;
492 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700493};
494
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000495VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200496 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200497 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700498 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200499 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700500 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800501 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700502 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700503 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700504 VideoSendStream::Config config,
505 VideoEncoderConfig encoder_config,
sprangdb2a9fc2017-08-09 06:42:32 -0700506 const std::map<uint32_t, RtpState>& suspended_ssrcs)
perkj26091b12016-09-01 01:17:40 -0700507 : worker_queue_(worker_queue),
508 thread_sync_event_(false /* manual_reset */, false),
509 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800510 config,
511 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800512 config_(std::move(config)),
513 content_type_(encoder_config.content_type) {
mflodmancc3d4422017-08-03 08:27:51 -0700514 video_stream_encoder_.reset(
515 new VideoStreamEncoder(num_cpu_cores, &stats_proxy_,
516 config_.encoder_settings,
517 config_.pre_encode_callback,
518 config_.post_encode_callback,
519 std::unique_ptr<OveruseFrameDetector>()));
perkj26091b12016-09-01 01:17:40 -0700520 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
mflodmancc3d4422017-08-03 08:27:51 -0700521 &send_stream_, &thread_sync_event_, &stats_proxy_,
522 video_stream_encoder_.get(), module_process_thread, call_stats, transport,
523 bitrate_allocator, send_delay_stats, event_log, &config_,
524 encoder_config.max_bitrate_bps, suspended_ssrcs,
sprangdb2a9fc2017-08-09 06:42:32 -0700525 encoder_config.content_type)));
perkj26091b12016-09-01 01:17:40 -0700526
527 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
528 // |module_process_thread| must be registered and deregistered on the thread
529 // it was created on.
530 thread_sync_event_.Wait(rtc::Event::kForever);
531 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800532 // TODO(sprang): Enable this also for regular video calls if it works well.
533 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
534 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700535 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800536 }
mflodmancc3d4422017-08-03 08:27:51 -0700537 video_stream_encoder_->RegisterProcessThread(module_process_thread);
perkj26091b12016-09-01 01:17:40 -0700538
539 ReconfigureVideoEncoder(std::move(encoder_config));
540}
541
542VideoSendStream::~VideoSendStream() {
543 RTC_DCHECK_RUN_ON(&thread_checker_);
544 RTC_DCHECK(!send_stream_);
545}
546
547void VideoSendStream::Start() {
548 RTC_DCHECK_RUN_ON(&thread_checker_);
549 LOG(LS_INFO) << "VideoSendStream::Start";
550 VideoSendStreamImpl* send_stream = send_stream_.get();
551 worker_queue_->PostTask([this, send_stream] {
552 send_stream->Start();
553 thread_sync_event_.Set();
554 });
555
556 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700557 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
558 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700559 thread_sync_event_.Wait(rtc::Event::kForever);
560}
561
562void VideoSendStream::Stop() {
563 RTC_DCHECK_RUN_ON(&thread_checker_);
564 LOG(LS_INFO) << "VideoSendStream::Stop";
565 VideoSendStreamImpl* send_stream = send_stream_.get();
566 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
567}
568
perkja49cbd32016-09-16 07:53:41 -0700569void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700570 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
571 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700572 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700573 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700574}
575
576void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700577 // TODO(perkj): Some test cases in VideoSendStreamTest call
578 // ReconfigureVideoEncoder from the network thread.
579 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800580 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700581 video_stream_encoder_->ConfigureEncoder(std::move(config),
582 config_.rtp.max_packet_size,
583 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700584}
585
586VideoSendStream::Stats VideoSendStream::GetStats() {
587 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
588 // a network thread. See comment in Call::GetStats().
589 // RTC_DCHECK_RUN_ON(&thread_checker_);
590 return stats_proxy_.GetStats();
591}
592
593void VideoSendStream::SignalNetworkState(NetworkState state) {
594 RTC_DCHECK_RUN_ON(&thread_checker_);
595 VideoSendStreamImpl* send_stream = send_stream_.get();
596 worker_queue_->PostTask(
597 [send_stream, state] { send_stream->SignalNetworkState(state); });
598}
599
600VideoSendStream::RtpStateMap VideoSendStream::StopPermanentlyAndGetRtpStates() {
601 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700602 video_stream_encoder_->Stop();
603 video_stream_encoder_->DeRegisterProcessThread();
perkj26091b12016-09-01 01:17:40 -0700604 VideoSendStream::RtpStateMap state_map;
605 send_stream_->DeRegisterProcessThread();
606 worker_queue_->PostTask(
607 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
608 &state_map, std::move(send_stream_), &thread_sync_event_)));
609 thread_sync_event_.Wait(rtc::Event::kForever);
610 return state_map;
611}
612
nisse284542b2017-01-10 08:58:32 -0800613void VideoSendStream::SetTransportOverhead(
614 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800615 RTC_DCHECK_RUN_ON(&thread_checker_);
616 VideoSendStreamImpl* send_stream = send_stream_.get();
617 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
618 send_stream->SetTransportOverhead(transport_overhead_per_packet);
619 });
620}
621
perkj26091b12016-09-01 01:17:40 -0700622bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
623 // Called on a network thread.
624 return send_stream_->DeliverRtcp(packet, length);
625}
626
palmkviste75f2042016-09-28 06:19:48 -0700627void VideoSendStream::EnableEncodedFrameRecording(
628 const std::vector<rtc::PlatformFile>& files,
629 size_t byte_limit) {
630 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
631}
632
perkj26091b12016-09-01 01:17:40 -0700633VideoSendStreamImpl::VideoSendStreamImpl(
634 SendStatisticsProxy* stats_proxy,
635 rtc::TaskQueue* worker_queue,
636 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700637 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700638 BitrateAllocator* bitrate_allocator,
639 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700640 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700641 RtcEventLog* event_log,
642 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200643 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700644 std::map<uint32_t, RtpState> suspended_ssrcs,
sprangdb2a9fc2017-08-09 06:42:32 -0700645 VideoEncoderConfig::ContentType content_type)
sprangc1b57a12017-02-28 08:50:47 -0800646 : send_side_bwe_with_overhead_(
647 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800648 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000649 config_(config),
perkj26091b12016-09-01 01:17:40 -0700650 suspended_ssrcs_(std::move(suspended_ssrcs)),
651 module_process_thread_(nullptr),
652 worker_queue_(worker_queue),
653 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200654 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700655 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100656 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700657 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700658 max_padding_bitrate_(0),
659 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200660 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700661 encoder_target_rate_bps_(0),
mflodmancc3d4422017-08-03 08:27:51 -0700662 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700663 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700664 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700665 video_stream_encoder),
Per69b332d2016-06-02 15:45:42 +0200666 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
nisseb8f9a322017-03-27 05:36:15 -0700667 bandwidth_observer_(transport->send_side_cc()
668 ->GetBitrateController()
669 ->CreateRtcpBandwidthObserver()),
670 rtp_rtcp_modules_(CreateRtpRtcpModules(
671 config_->send_transport,
672 &encoder_feedback_,
673 bandwidth_observer_.get(),
674 transport,
675 call_stats_->rtcp_rtt_stats(),
676 flexfec_sender_.get(),
677 stats_proxy_,
678 send_delay_stats,
679 event_log,
680 transport->send_side_cc()->GetRetransmissionRateLimiter(),
681 this,
sprang168794c2017-07-06 04:38:06 -0700682 config_->rtp.ssrcs.size(),
sprangdb2a9fc2017-08-09 06:42:32 -0700683 transport->keepalive_config())),
perkj26091b12016-09-01 01:17:40 -0700684 payload_router_(rtp_rtcp_modules_,
perkj8ff860a2016-10-03 00:30:04 -0700685 config_->encoder_settings.payload_type),
michaelta3328772016-11-29 09:25:03 -0800686 weak_ptr_factory_(this),
687 overhead_bytes_per_packet_(0),
688 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700689 RTC_DCHECK_RUN_ON(worker_queue_);
690 LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700691 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700692 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100693
perkj26091b12016-09-01 01:17:40 -0700694 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100695 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700696 RTC_DCHECK(transport_);
697 RTC_DCHECK(transport_->send_side_cc());
stefand7a418f2017-08-08 06:51:05 -0700698 RTC_CHECK(field_trial::FindFullName(
699 AlrDetector::kStrictPacingAndProbingExperimentName)
700 .empty() ||
701 field_trial::FindFullName(
702 AlrDetector::kScreenshareProbingBweExperimentName)
703 .empty());
704 rtc::Optional<AlrDetector::AlrExperimentSettings> alr_settings;
sprang89c4a7e2017-06-30 13:27:40 -0700705 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
stefand7a418f2017-08-08 06:51:05 -0700706 alr_settings = AlrDetector::ParseAlrSettingsFromFieldTrial(
707 AlrDetector::kScreenshareProbingBweExperimentName);
708 } else {
709 alr_settings = AlrDetector::ParseAlrSettingsFromFieldTrial(
710 AlrDetector::kStrictPacingAndProbingExperimentName);
711 }
712 if (alr_settings) {
713 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
Stefan Holmer5c8942a2017-08-22 16:16:44 +0200714 transport->pacer()->SetPacingFactor(alr_settings->pacing_factor);
715 transport->pacer()->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
sprang89c4a7e2017-06-30 13:27:40 -0700716 }
717
718 if (config_->periodic_alr_bandwidth_probing) {
719 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
720 }
sergeyu80ed35e2016-11-28 13:11:13 -0800721
Per83d09102016-04-15 14:59:13 +0200722 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800723
724 // We add the highest spatial layer first to ensure it'll be prioritized
725 // when sending padding, with the hope that the packet rate will be smaller,
726 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700727 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
728 constexpr bool remb_candidate = true;
729 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
730 }
mflodman949c2f02015-10-16 02:31:11 -0700731
perkj26091b12016-09-01 01:17:40 -0700732 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
733 const std::string& extension = config_->rtp.extensions[i].uri;
734 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200735 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700736 RTC_DCHECK_GE(id, 1);
737 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100738 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
739 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
740 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
741 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000742 }
743 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000744
Per83d09102016-04-15 14:59:13 +0200745 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000746 ConfigureSsrcs();
747
Peter Boström723ead82016-02-22 15:14:01 +0100748 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700749 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800750
Peter Boström723ead82016-02-22 15:14:01 +0100751 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700752 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
753 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800754 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100755 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700756 config_->encoder_settings.payload_type,
757 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100758 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000759
perkj26091b12016-09-01 01:17:40 -0700760 RTC_DCHECK(config_->encoder_settings.encoder);
761 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
762 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000763
mflodmancc3d4422017-08-03 08:27:51 -0700764 video_stream_encoder_->SetStartBitrate(
765 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700766
767 // Only request rotation at the source when we positively know that the remote
768 // side doesn't support the rotation extension. This allows us to prepare the
769 // encoder in the expectation that rotation is supported - which is the common
770 // case.
771 bool rotation_applied =
772 std::find_if(config_->rtp.extensions.begin(),
773 config_->rtp.extensions.end(),
774 [](const RtpExtension& extension) {
775 return extension.uri == RtpExtension::kVideoRotationUri;
776 }) == config_->rtp.extensions.end();
777
mflodmancc3d4422017-08-03 08:27:51 -0700778 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000779}
780
perkj26091b12016-09-01 01:17:40 -0700781void VideoSendStreamImpl::RegisterProcessThread(
782 ProcessThread* module_process_thread) {
783 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
784 RTC_DCHECK(!module_process_thread_);
785 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100786
perkj26091b12016-09-01 01:17:40 -0700787 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800788 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700789}
Peter Boströmca835252016-02-11 15:59:46 +0100790
perkj26091b12016-09-01 01:17:40 -0700791void VideoSendStreamImpl::DeRegisterProcessThread() {
792 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
793 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
794 module_process_thread_->DeRegisterModule(rtp_rtcp);
795}
Peter Boströma4c76882016-03-03 16:29:02 +0100796
perkj26091b12016-09-01 01:17:40 -0700797VideoSendStreamImpl::~VideoSendStreamImpl() {
798 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800799 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700800 << "VideoSendStreamImpl::Stop not called";
801 LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000802
Per83d09102016-04-15 14:59:13 +0200803 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700804 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200805 delete rtp_rtcp;
806 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000807}
808
perkj26091b12016-09-01 01:17:40 -0700809bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
810 // Runs on a network thread.
811 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700812 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
813 rtp_rtcp->IncomingRtcpPacket(packet, length);
814 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000815}
816
perkj26091b12016-09-01 01:17:40 -0700817void VideoSendStreamImpl::Start() {
818 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700819 LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800820 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100821 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200822 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800823 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700824
825 bitrate_allocator_->AddObserver(
826 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
827 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
828
829 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700830 {
perkj26091b12016-09-01 01:17:40 -0700831 rtc::CritScope lock(&encoder_activity_crit_sect_);
832 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700833 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700834 worker_queue_->PostDelayedTask(
835 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
836 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700837 }
perkj26091b12016-09-01 01:17:40 -0700838
mflodmancc3d4422017-08-03 08:27:51 -0700839 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000840}
841
perkj26091b12016-09-01 01:17:40 -0700842void VideoSendStreamImpl::Stop() {
843 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700844 LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800845 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100846 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200847 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800848 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700849 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700850 {
perkj26091b12016-09-01 01:17:40 -0700851 rtc::CritScope lock(&encoder_activity_crit_sect_);
852 check_encoder_activity_task_->Stop();
853 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700854 }
mflodmancc3d4422017-08-03 08:27:51 -0700855 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -0700856 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000857}
858
perkj26091b12016-09-01 01:17:40 -0700859void VideoSendStreamImpl::SignalEncoderTimedOut() {
860 RTC_DCHECK_RUN_ON(worker_queue_);
861 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
862 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
863 // if a camera stops producing frames.
864 if (encoder_target_rate_bps_ > 0) {
865 LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
866 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100867 }
868}
869
sprang1a646ee2016-12-01 06:34:11 -0800870void VideoSendStreamImpl::OnBitrateAllocationUpdated(
871 const BitrateAllocation& allocation) {
872 payload_router_.OnBitrateAllocationUpdated(allocation);
873}
874
perkj26091b12016-09-01 01:17:40 -0700875void VideoSendStreamImpl::SignalEncoderActive() {
876 RTC_DCHECK_RUN_ON(worker_queue_);
877 LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
878 bitrate_allocator_->AddObserver(
879 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
880 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
881}
882
Per512ecb32016-09-23 15:52:06 +0200883void VideoSendStreamImpl::OnEncoderConfigurationChanged(
884 std::vector<VideoStream> streams,
885 int min_transmit_bitrate_bps) {
886 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200887 worker_queue_->PostTask(
888 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700889 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200890 return;
891 }
892 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
893 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
894 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700895 RTC_DCHECK_RUN_ON(worker_queue_);
896
897 const int kEncoderMinBitrateBps = 30000;
898 encoder_min_bitrate_bps_ =
Per512ecb32016-09-23 15:52:06 +0200899 std::max(streams[0].min_bitrate_bps, kEncoderMinBitrateBps);
perkj26091b12016-09-01 01:17:40 -0700900 encoder_max_bitrate_bps_ = 0;
Per512ecb32016-09-23 15:52:06 +0200901 for (const auto& stream : streams)
perkj26091b12016-09-01 01:17:40 -0700902 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Per512ecb32016-09-23 15:52:06 +0200903 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
904 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -0700905
906 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +0200907 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -0700908 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000909 }
perkj26091b12016-09-01 01:17:40 -0700910
911 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +0200912 streams.back().temporal_layer_thresholds_bps.size() + 1;
perkj26091b12016-09-01 01:17:40 -0700913 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +0200914 streams[0].width, streams[0].height, number_of_temporal_layers,
915 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -0700916
sprang1a646ee2016-12-01 06:34:11 -0800917 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -0700918 // The send stream is started already. Update the allocator with new bitrate
919 // limits.
920 bitrate_allocator_->AddObserver(
921 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
922 max_padding_bitrate_, !config_->suspend_below_min_bitrate);
923 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000924}
925
perkj26091b12016-09-01 01:17:40 -0700926EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700927 const EncodedImage& encoded_image,
928 const CodecSpecificInfo* codec_specific_info,
929 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -0700930 // Encoded is called on whatever thread the real encoder implementation run
931 // on. In the case of hardware encoders, there might be several encoders
932 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -0800933 size_t simulcast_idx = 0;
934 if (codec_specific_info->codecType == kVideoCodecVP8) {
935 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
936 }
perkj26091b12016-09-01 01:17:40 -0700937 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -0800938 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
939 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
940 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -0700941 }
perkj26091b12016-09-01 01:17:40 -0700942 {
943 rtc::CritScope lock(&encoder_activity_crit_sect_);
944 if (check_encoder_activity_task_)
945 check_encoder_activity_task_->UpdateEncoderActivity();
946 }
sergeyu37ad3372016-06-14 15:29:37 -0700947
Per69b332d2016-06-02 15:45:42 +0200948 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700949 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -0700950 encoded_image, codec_specific_info, fragmentation);
951
palmkviste75f2042016-09-28 06:19:48 -0700952 RTC_DCHECK(codec_specific_info);
953
954 int layer = codec_specific_info->codecType == kVideoCodecVP8
955 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
956 : 0;
957 {
958 rtc::CritScope lock(&ivf_writers_crit_);
959 if (file_writers_[layer].get()) {
960 bool ok = file_writers_[layer]->WriteFrame(
961 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -0700962 RTC_DCHECK(ok);
963 }
964 }
965
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700966 return result;
perkjbc75d972016-05-02 06:31:25 -0700967}
968
perkj26091b12016-09-01 01:17:40 -0700969void VideoSendStreamImpl::ConfigureProtection() {
970 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -0800971
brandtre950cad2016-11-15 05:25:41 -0800972 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
973 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
974
975 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -0800976 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
977 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -0800978 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -0800979
980 // Shorthands.
981 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -0800982 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -0800983 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
984 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
985
stefan60e10c72017-08-23 10:40:00 -0700986 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
987 LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
988 DisableUlpfec();
989 }
990
brandtre950cad2016-11-15 05:25:41 -0800991 // If enabled, FlexFEC takes priority over RED+ULPFEC.
992 if (flexfec_enabled) {
993 // We can safely disable RED here, because if the remote supports FlexFEC,
994 // we know that it has a receiver without the RED/RTX workaround.
995 // See http://crbug.com/webrtc/6650 for more information.
996 if (IsRedEnabled()) {
997 LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
998 DisableRed();
999 }
1000 if (IsUlpfecEnabled()) {
1001 LOG(LS_INFO)
1002 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1003 DisableUlpfec();
1004 }
1005 }
1006
Per83d09102016-04-15 14:59:13 +02001007 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001008 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1009 // is a waste of bandwidth since FEC packets still have to be transmitted.
1010 // Note that this is not the case with FlexFEC.
1011 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001012 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001013 config_->encoder_settings.payload_name)) {
brandtre6f98c72016-11-11 03:28:30 -08001014 LOG(LS_WARNING)
1015 << "Transmitting payload type without picture ID using "
1016 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1017 "also have to be retransmitted. Disabling ULPFEC.";
1018 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001019 }
1020
brandtre6f98c72016-11-11 03:28:30 -08001021 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001022 //
brandtre6f98c72016-11-11 03:28:30 -08001023 // Due to how old receivers work, we need to always send RED if it has been
1024 // negotiated. This is a remnant of an old RED/RTX workaround, see
1025 // https://codereview.webrtc.org/2469093003.
1026 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1027 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1028 // no point in using RED without ULPFEC.
1029 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001030 RTC_DCHECK_GE(red_payload_type, 0);
1031 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001032 }
brandtre6f98c72016-11-11 03:28:30 -08001033 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001034 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1035 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001036 if (!IsRedEnabled()) {
1037 LOG(LS_WARNING)
1038 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1039 DisableUlpfec();
1040 }
Per83d09102016-04-15 14:59:13 +02001041 }
1042
1043 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1044 // Set NACK.
1045 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001046 true,
Per83d09102016-04-15 14:59:13 +02001047 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001048 // Set RED/ULPFEC information.
stefan60e10c72017-08-23 10:40:00 -07001049 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001050 }
1051
brandtre950cad2016-11-15 05:25:41 -08001052 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1053 // so enable that logic if either of those FEC schemes are enabled.
1054 protection_bitrate_calculator_.SetProtectionMethod(
1055 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001056}
1057
perkj26091b12016-09-01 01:17:40 -07001058void VideoSendStreamImpl::ConfigureSsrcs() {
1059 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001060 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001061 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1062 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001063 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1064 rtp_rtcp->SetSSRC(ssrc);
1065
1066 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001067 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001068 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001069 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001070 }
1071
Peter Boström723ead82016-02-22 15:14:01 +01001072 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001073 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001074 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001075
Peter Boström723ead82016-02-22 15:14:01 +01001076 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001077 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1078 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1079 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001080 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1081 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001082 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001083 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001084 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001085 }
1086
Peter Boström723ead82016-02-22 15:14:01 +01001087 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001088 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001089 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001090 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1091 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001092 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1093 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001094 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1095 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001096 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001097 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1098 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001099 }
Stefan Holmer10880012016-02-03 13:29:59 +01001100 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001101}
1102
perkj26091b12016-09-01 01:17:40 -07001103std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1104 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001105 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001106
perkj26091b12016-09-01 01:17:40 -07001107 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1108 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001109 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1110 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001111 }
1112
perkj26091b12016-09-01 01:17:40 -07001113 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1114 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001115 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001116 }
1117
brandtr48d21a22017-05-30 02:32:12 -07001118 if (flexfec_sender_) {
1119 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1120 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1121 }
1122
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001123 return rtp_states;
1124}
1125
perkj26091b12016-09-01 01:17:40 -07001126void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1127 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001128 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001129 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001130 : RtcpMode::kOff);
1131 }
1132}
1133
perkj26091b12016-09-01 01:17:40 -07001134uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1135 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001136 int64_t rtt,
1137 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001138 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001139 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001140 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001141
michaelt192132e2017-01-26 09:05:27 -08001142 // Substract overhead from bitrate.
1143 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001144 uint32_t payload_bitrate_bps = bitrate_bps;
1145 if (send_side_bwe_with_overhead_) {
1146 payload_bitrate_bps -= CalculateOverheadRateBps(
1147 CalculatePacketRate(bitrate_bps,
1148 config_->rtp.max_packet_size +
1149 transport_overhead_bytes_per_packet_),
1150 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1151 bitrate_bps);
1152 }
michaelta3328772016-11-29 09:25:03 -08001153
Per69b332d2016-06-02 15:45:42 +02001154 // Get the encoder target rate. It is the estimated network rate -
1155 // protection overhead.
perkj26091b12016-09-01 01:17:40 -07001156 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001157 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1158 rtt);
1159
elad.alon0fe12162017-01-31 05:48:37 -08001160 uint32_t encoder_overhead_rate_bps =
1161 send_side_bwe_with_overhead_
1162 ? CalculateOverheadRateBps(
1163 CalculatePacketRate(encoder_target_rate_bps_,
1164 config_->rtp.max_packet_size +
1165 transport_overhead_bytes_per_packet_ -
1166 overhead_bytes_per_packet_),
1167 overhead_bytes_per_packet_ +
1168 transport_overhead_bytes_per_packet_,
1169 bitrate_bps - encoder_target_rate_bps_)
1170 : 0;
michaelt192132e2017-01-26 09:05:27 -08001171
1172 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1173 // protection_bitrate includes overhead.
1174 uint32_t protection_bitrate =
1175 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001176
perkj26091b12016-09-01 01:17:40 -07001177 encoder_target_rate_bps_ =
1178 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001179 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1180 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001181 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001182 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001183}
1184
palmkviste75f2042016-09-28 06:19:48 -07001185void VideoSendStreamImpl::EnableEncodedFrameRecording(
1186 const std::vector<rtc::PlatformFile>& files,
1187 size_t byte_limit) {
1188 {
1189 rtc::CritScope lock(&ivf_writers_crit_);
1190 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1191 if (i < files.size()) {
1192 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1193 } else {
1194 file_writers_[i].reset();
1195 }
1196 }
1197 }
1198
1199 if (!files.empty()) {
1200 // Make a keyframe appear as early as possible in the logs, to give actually
1201 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001202 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001203 }
1204}
1205
perkj26091b12016-09-01 01:17:40 -07001206int VideoSendStreamImpl::ProtectionRequest(
1207 const FecProtectionParams* delta_params,
1208 const FecProtectionParams* key_params,
1209 uint32_t* sent_video_rate_bps,
1210 uint32_t* sent_nack_rate_bps,
1211 uint32_t* sent_fec_rate_bps) {
1212 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001213 *sent_video_rate_bps = 0;
1214 *sent_nack_rate_bps = 0;
1215 *sent_fec_rate_bps = 0;
1216 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1217 uint32_t not_used = 0;
1218 uint32_t module_video_rate = 0;
1219 uint32_t module_fec_rate = 0;
1220 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001221 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001222 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1223 &module_nack_rate);
1224 *sent_video_rate_bps += module_video_rate;
1225 *sent_nack_rate_bps += module_nack_rate;
1226 *sent_fec_rate_bps += module_fec_rate;
1227 }
1228 return 0;
1229}
1230
michaelta3328772016-11-29 09:25:03 -08001231void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1232 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1233 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1234}
1235
michaelt79e05882016-11-08 02:50:09 -08001236void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001237 size_t transport_overhead_bytes_per_packet) {
1238 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
1239 LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
1240 return;
1241 }
1242
michaelta3328772016-11-29 09:25:03 -08001243 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001244
nisseb8f9a322017-03-27 05:36:15 -07001245 transport_->send_side_cc()->SetTransportOverhead(
1246 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001247
1248 size_t rtp_packet_size =
1249 std::min(config_->rtp.max_packet_size,
1250 kPathMTU - transport_overhead_bytes_per_packet_);
1251
michaelta3328772016-11-29 09:25:03 -08001252 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001253 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001254 }
michaelt79e05882016-11-08 02:50:09 -08001255}
1256
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001257} // namespace internal
1258} // namespace webrtc