blob: 982cd53febc499f39f230512e0d9e32fa4c2cc94 [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"
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
Erik Språng7c8cca32017-10-24 17:05:18 +0200146bool TransportSeqNumExtensionConfigured(const VideoSendStream::Config& config) {
147 const std::vector<RtpExtension>& extensions = config.rtp.extensions;
148 return std::find_if(
149 extensions.begin(), extensions.end(), [](const RtpExtension& ext) {
150 return ext.uri == RtpExtension::kTransportSequenceNumberUri;
151 }) != extensions.end();
152}
Peter Boströme4499152016-02-05 11:13:28 +0100153
Peter Boström39593972016-02-15 11:27:15 +0100154bool PayloadTypeSupportsSkippingFecPackets(const std::string& payload_name) {
kthelgason1cdddc92017-08-24 03:52:48 -0700155 const VideoCodecType codecType = PayloadStringToCodecType(payload_name);
156 if (codecType == kVideoCodecVP8 || codecType == kVideoCodecVP9) {
perkj26091b12016-09-01 01:17:40 -0700157 return true;
deadbeefc964d0b2017-04-03 10:03:35 -0700158 }
Peter Boström39593972016-02-15 11:27:15 +0100159 return false;
160}
161
Per512ecb32016-09-23 15:52:06 +0200162int CalculateMaxPadBitrateBps(std::vector<VideoStream> streams,
163 int min_transmit_bitrate_bps,
perkj71ee44c2016-06-15 00:47:53 -0700164 bool pad_to_min_bitrate) {
165 int pad_up_to_bitrate_bps = 0;
166 // Calculate max padding bitrate for a multi layer codec.
Per512ecb32016-09-23 15:52:06 +0200167 if (streams.size() > 1) {
perkj71ee44c2016-06-15 00:47:53 -0700168 // Pad to min bitrate of the highest layer.
Per512ecb32016-09-23 15:52:06 +0200169 pad_up_to_bitrate_bps = streams[streams.size() - 1].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700170 // Add target_bitrate_bps of the lower layers.
Per512ecb32016-09-23 15:52:06 +0200171 for (size_t i = 0; i < streams.size() - 1; ++i)
172 pad_up_to_bitrate_bps += streams[i].target_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700173 } else if (pad_to_min_bitrate) {
Per512ecb32016-09-23 15:52:06 +0200174 pad_up_to_bitrate_bps = streams[0].min_bitrate_bps;
perkj71ee44c2016-06-15 00:47:53 -0700175 }
176
177 pad_up_to_bitrate_bps =
Per512ecb32016-09-23 15:52:06 +0200178 std::max(pad_up_to_bitrate_bps, min_transmit_bitrate_bps);
perkj71ee44c2016-06-15 00:47:53 -0700179
180 return pad_up_to_bitrate_bps;
181}
182
michaelt192132e2017-01-26 09:05:27 -0800183uint32_t CalculateOverheadRateBps(int packets_per_second,
184 size_t overhead_bytes_per_packet,
185 uint32_t max_overhead_bps) {
michaelt192132e2017-01-26 09:05:27 -0800186 uint32_t overhead_bps =
187 static_cast<uint32_t>(8 * overhead_bytes_per_packet * packets_per_second);
188 return std::min(overhead_bps, max_overhead_bps);
189}
190
191int CalculatePacketRate(uint32_t bitrate_bps, size_t packet_size_bytes) {
192 size_t packet_size_bits = 8 * packet_size_bytes;
193 // Ceil for int value of bitrate_bps / packet_size_bits.
194 return static_cast<int>((bitrate_bps + packet_size_bits - 1) /
195 packet_size_bits);
196}
197
Peter Boströme4499152016-02-05 11:13:28 +0100198} // namespace
199
pbos@webrtc.org024e4d52014-05-15 10:03:24 +0000200namespace internal {
perkj26091b12016-09-01 01:17:40 -0700201
202// VideoSendStreamImpl implements internal::VideoSendStream.
203// It is created and destroyed on |worker_queue|. The intent is to decrease the
204// need for locking and to ensure methods are called in sequence.
205// Public methods except |DeliverRtcp| must be called on |worker_queue|.
206// DeliverRtcp is called on the libjingle worker thread or a network thread.
207// An encoder may deliver frames through the EncodedImageCallback on an
208// arbitrary thread.
209class VideoSendStreamImpl : public webrtc::BitrateAllocatorObserver,
michaelta3328772016-11-29 09:25:03 -0800210 public webrtc::OverheadObserver,
perkj26091b12016-09-01 01:17:40 -0700211 public webrtc::VCMProtectionCallback,
mflodmancc3d4422017-08-03 08:27:51 -0700212 public VideoStreamEncoder::EncoderSink,
sprang1a646ee2016-12-01 06:34:11 -0800213 public VideoBitrateAllocationObserver {
perkj26091b12016-09-01 01:17:40 -0700214 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200215 VideoSendStreamImpl(
216 SendStatisticsProxy* stats_proxy,
217 rtc::TaskQueue* worker_queue,
218 CallStats* call_stats,
219 RtpTransportControllerSendInterface* transport,
220 BitrateAllocator* bitrate_allocator,
221 SendDelayStats* send_delay_stats,
222 VideoStreamEncoder* video_stream_encoder,
223 RtcEventLog* event_log,
224 const VideoSendStream::Config* config,
225 int initial_encoder_max_bitrate,
226 std::map<uint32_t, RtpState> suspended_ssrcs,
227 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
228 VideoEncoderConfig::ContentType content_type);
perkj26091b12016-09-01 01:17:40 -0700229 ~VideoSendStreamImpl() override;
230
231 // RegisterProcessThread register |module_process_thread| with those objects
232 // that use it. Registration has to happen on the thread were
233 // |module_process_thread| was created (libjingle's worker thread).
234 // TODO(perkj): Replace the use of |module_process_thread| with a TaskQueue,
235 // maybe |worker_queue|.
236 void RegisterProcessThread(ProcessThread* module_process_thread);
237 void DeRegisterProcessThread();
238
239 void SignalNetworkState(NetworkState state);
240 bool DeliverRtcp(const uint8_t* packet, size_t length);
241 void Start();
242 void Stop();
243
perkj26091b12016-09-01 01:17:40 -0700244 VideoSendStream::RtpStateMap GetRtpStates() const;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200245 VideoSendStream::RtpPayloadStateMap GetRtpPayloadStates() const;
perkj26091b12016-09-01 01:17:40 -0700246
palmkviste75f2042016-09-28 06:19:48 -0700247 void EnableEncodedFrameRecording(const std::vector<rtc::PlatformFile>& files,
248 size_t byte_limit);
249
nisse284542b2017-01-10 08:58:32 -0800250 void SetTransportOverhead(size_t transport_overhead_per_packet);
michaelt79e05882016-11-08 02:50:09 -0800251
perkj26091b12016-09-01 01:17:40 -0700252 private:
253 class CheckEncoderActivityTask;
Per512ecb32016-09-23 15:52:06 +0200254 class EncoderReconfiguredTask;
perkj26091b12016-09-01 01:17:40 -0700255
256 // Implements BitrateAllocatorObserver.
257 uint32_t OnBitrateUpdated(uint32_t bitrate_bps,
258 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -0800259 int64_t rtt,
260 int64_t probing_interval_ms) override;
perkj26091b12016-09-01 01:17:40 -0700261
262 // Implements webrtc::VCMProtectionCallback.
263 int ProtectionRequest(const FecProtectionParams* delta_params,
264 const FecProtectionParams* key_params,
265 uint32_t* sent_video_rate_bps,
266 uint32_t* sent_nack_rate_bps,
267 uint32_t* sent_fec_rate_bps) override;
268
michaelta3328772016-11-29 09:25:03 -0800269 // Implements OverheadObserver.
270 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
271
Per512ecb32016-09-23 15:52:06 +0200272 void OnEncoderConfigurationChanged(std::vector<VideoStream> streams,
273 int min_transmit_bitrate_bps) override;
274
perkj26091b12016-09-01 01:17:40 -0700275 // Implements EncodedImageCallback. The implementation routes encoded frames
276 // to the |payload_router_| and |config.pre_encode_callback| if set.
277 // Called on an arbitrary encoder callback thread.
278 EncodedImageCallback::Result OnEncodedImage(
279 const EncodedImage& encoded_image,
280 const CodecSpecificInfo* codec_specific_info,
281 const RTPFragmentationHeader* fragmentation) override;
282
sprang1a646ee2016-12-01 06:34:11 -0800283 // Implements VideoBitrateAllocationObserver.
284 void OnBitrateAllocationUpdated(const BitrateAllocation& allocation) override;
285
perkj26091b12016-09-01 01:17:40 -0700286 void ConfigureProtection();
287 void ConfigureSsrcs();
288 void SignalEncoderTimedOut();
289 void SignalEncoderActive();
290
elad.alon0fe12162017-01-31 05:48:37 -0800291 const bool send_side_bwe_with_overhead_;
292
perkj26091b12016-09-01 01:17:40 -0700293 SendStatisticsProxy* const stats_proxy_;
294 const VideoSendStream::Config* const config_;
295 std::map<uint32_t, RtpState> suspended_ssrcs_;
296
297 ProcessThread* module_process_thread_;
298 rtc::ThreadChecker module_process_thread_checker_;
299 rtc::TaskQueue* const worker_queue_;
300
301 rtc::CriticalSection encoder_activity_crit_sect_;
302 CheckEncoderActivityTask* check_encoder_activity_task_
danilchapa37de392017-09-09 04:17:22 -0700303 RTC_GUARDED_BY(encoder_activity_crit_sect_);
Per512ecb32016-09-23 15:52:06 +0200304
perkj26091b12016-09-01 01:17:40 -0700305 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700306 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700307 BitrateAllocator* const bitrate_allocator_;
perkj26091b12016-09-01 01:17:40 -0700308
brandtr3b941be2017-03-17 07:02:46 -0700309 // TODO(brandtr): Move ownership to PayloadRouter.
brandtre950cad2016-11-15 05:25:41 -0800310 std::unique_ptr<FlexfecSender> flexfec_sender_;
311
palmkviste75f2042016-09-28 06:19:48 -0700312 rtc::CriticalSection ivf_writers_crit_;
danilchapa37de392017-09-09 04:17:22 -0700313 std::unique_ptr<IvfFileWriter>
314 file_writers_[kMaxSimulcastStreams] RTC_GUARDED_BY(ivf_writers_crit_);
perkj26091b12016-09-01 01:17:40 -0700315
316 int max_padding_bitrate_;
317 int encoder_min_bitrate_bps_;
318 uint32_t encoder_max_bitrate_bps_;
319 uint32_t encoder_target_rate_bps_;
320
mflodmancc3d4422017-08-03 08:27:51 -0700321 VideoStreamEncoder* const video_stream_encoder_;
mflodman15d83572016-10-06 08:35:11 -0700322 EncoderRtcpFeedback encoder_feedback_;
perkj26091b12016-09-01 01:17:40 -0700323 ProtectionBitrateCalculator protection_bitrate_calculator_;
324
325 const std::unique_ptr<RtcpBandwidthObserver> bandwidth_observer_;
326 // RtpRtcp modules, declared here as they use other members on construction.
327 const std::vector<RtpRtcp*> rtp_rtcp_modules_;
328 PayloadRouter payload_router_;
perkj8ff860a2016-10-03 00:30:04 -0700329
330 // |weak_ptr_| to our self. This is used since we can not call
331 // |weak_ptr_factory_.GetWeakPtr| from multiple sequences but it is ok to copy
332 // an existing WeakPtr.
333 rtc::WeakPtr<VideoSendStreamImpl> weak_ptr_;
334 // |weak_ptr_factory_| must be declared last to make sure all WeakPtr's are
335 // invalidated before any other members are destroyed.
336 rtc::WeakPtrFactory<VideoSendStreamImpl> weak_ptr_factory_;
michaelta3328772016-11-29 09:25:03 -0800337
338 rtc::CriticalSection overhead_bytes_per_packet_crit_;
danilchapa37de392017-09-09 04:17:22 -0700339 size_t overhead_bytes_per_packet_
340 RTC_GUARDED_BY(overhead_bytes_per_packet_crit_);
michaelta3328772016-11-29 09:25:03 -0800341 size_t transport_overhead_bytes_per_packet_;
perkj26091b12016-09-01 01:17:40 -0700342};
343
344// TODO(tommi): See if there's a more elegant way to create a task that creates
345// an object on the correct task queue.
346class VideoSendStream::ConstructionTask : public rtc::QueuedTask {
347 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200348 ConstructionTask(
349 std::unique_ptr<VideoSendStreamImpl>* send_stream,
350 rtc::Event* done_event,
351 SendStatisticsProxy* stats_proxy,
352 VideoStreamEncoder* video_stream_encoder,
353 ProcessThread* module_process_thread,
354 CallStats* call_stats,
355 RtpTransportControllerSendInterface* transport,
356 BitrateAllocator* bitrate_allocator,
357 SendDelayStats* send_delay_stats,
358 RtcEventLog* event_log,
359 const VideoSendStream::Config* config,
360 int initial_encoder_max_bitrate,
361 const std::map<uint32_t, RtpState>& suspended_ssrcs,
362 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states,
363 VideoEncoderConfig::ContentType content_type)
perkj26091b12016-09-01 01:17:40 -0700364 : send_stream_(send_stream),
365 done_event_(done_event),
366 stats_proxy_(stats_proxy),
mflodmancc3d4422017-08-03 08:27:51 -0700367 video_stream_encoder_(video_stream_encoder),
perkj26091b12016-09-01 01:17:40 -0700368 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700369 transport_(transport),
perkj26091b12016-09-01 01:17:40 -0700370 bitrate_allocator_(bitrate_allocator),
371 send_delay_stats_(send_delay_stats),
perkj26091b12016-09-01 01:17:40 -0700372 event_log_(event_log),
373 config_(config),
Per512ecb32016-09-23 15:52:06 +0200374 initial_encoder_max_bitrate_(initial_encoder_max_bitrate),
sprang89c4a7e2017-06-30 13:27:40 -0700375 suspended_ssrcs_(suspended_ssrcs),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200376 suspended_payload_states_(suspended_payload_states),
sprangdb2a9fc2017-08-09 06:42:32 -0700377 content_type_(content_type) {}
perkj26091b12016-09-01 01:17:40 -0700378
379 ~ConstructionTask() override { done_event_->Set(); }
380
381 private:
382 bool Run() override {
383 send_stream_->reset(new VideoSendStreamImpl(
nisseb8f9a322017-03-27 05:36:15 -0700384 stats_proxy_, rtc::TaskQueue::Current(), call_stats_, transport_,
mflodmancc3d4422017-08-03 08:27:51 -0700385 bitrate_allocator_, send_delay_stats_, video_stream_encoder_,
386 event_log_, config_, initial_encoder_max_bitrate_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200387 std::move(suspended_ssrcs_), std::move(suspended_payload_states_),
388 content_type_));
perkj26091b12016-09-01 01:17:40 -0700389 return true;
390 }
391
392 std::unique_ptr<VideoSendStreamImpl>* const send_stream_;
393 rtc::Event* const done_event_;
394 SendStatisticsProxy* const stats_proxy_;
mflodmancc3d4422017-08-03 08:27:51 -0700395 VideoStreamEncoder* const video_stream_encoder_;
perkj26091b12016-09-01 01:17:40 -0700396 CallStats* const call_stats_;
nisseb8f9a322017-03-27 05:36:15 -0700397 RtpTransportControllerSendInterface* const transport_;
perkj26091b12016-09-01 01:17:40 -0700398 BitrateAllocator* const bitrate_allocator_;
399 SendDelayStats* const send_delay_stats_;
perkj26091b12016-09-01 01:17:40 -0700400 RtcEventLog* const event_log_;
401 const VideoSendStream::Config* config_;
Per512ecb32016-09-23 15:52:06 +0200402 int initial_encoder_max_bitrate_;
perkj26091b12016-09-01 01:17:40 -0700403 std::map<uint32_t, RtpState> suspended_ssrcs_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200404 std::map<uint32_t, RtpPayloadState> suspended_payload_states_;
sprang89c4a7e2017-06-30 13:27:40 -0700405 const VideoEncoderConfig::ContentType content_type_;
perkj26091b12016-09-01 01:17:40 -0700406};
407
408class VideoSendStream::DestructAndGetRtpStateTask : public rtc::QueuedTask {
409 public:
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200410 DestructAndGetRtpStateTask(
411 VideoSendStream::RtpStateMap* state_map,
412 VideoSendStream::RtpPayloadStateMap* payload_state_map,
413 std::unique_ptr<VideoSendStreamImpl> send_stream,
414 rtc::Event* done_event)
perkj26091b12016-09-01 01:17:40 -0700415 : state_map_(state_map),
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200416 payload_state_map_(payload_state_map),
perkj26091b12016-09-01 01:17:40 -0700417 send_stream_(std::move(send_stream)),
418 done_event_(done_event) {}
419
420 ~DestructAndGetRtpStateTask() override { RTC_CHECK(!send_stream_); }
421
422 private:
423 bool Run() override {
424 send_stream_->Stop();
425 *state_map_ = send_stream_->GetRtpStates();
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200426 *payload_state_map_ = send_stream_->GetRtpPayloadStates();
perkj26091b12016-09-01 01:17:40 -0700427 send_stream_.reset();
428 done_event_->Set();
429 return true;
430 }
431
432 VideoSendStream::RtpStateMap* state_map_;
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200433 VideoSendStream::RtpPayloadStateMap* payload_state_map_;
perkj26091b12016-09-01 01:17:40 -0700434 std::unique_ptr<VideoSendStreamImpl> send_stream_;
435 rtc::Event* done_event_;
436};
437
438// CheckEncoderActivityTask is used for tracking when the encoder last produced
439// and encoded video frame. If the encoder has not produced anything the last
440// kEncoderTimeOutMs we also want to stop sending padding.
441class VideoSendStreamImpl::CheckEncoderActivityTask : public rtc::QueuedTask {
442 public:
443 static const int kEncoderTimeOutMs = 2000;
perkj8ff860a2016-10-03 00:30:04 -0700444 explicit CheckEncoderActivityTask(
445 const rtc::WeakPtr<VideoSendStreamImpl>& send_stream)
446 : activity_(0), send_stream_(std::move(send_stream)), timed_out_(false) {}
perkj26091b12016-09-01 01:17:40 -0700447
448 void Stop() {
449 RTC_CHECK(task_checker_.CalledSequentially());
perkj8ff860a2016-10-03 00:30:04 -0700450 send_stream_.reset();
perkj26091b12016-09-01 01:17:40 -0700451 }
452
453 void UpdateEncoderActivity() {
454 // UpdateEncoderActivity is called from VideoSendStreamImpl::Encoded on
455 // whatever thread the real encoder implementation run on. In the case of
456 // hardware encoders, there might be several encoders
457 // running in parallel on different threads.
458 rtc::AtomicOps::ReleaseStore(&activity_, 1);
459 }
460
461 private:
462 bool Run() override {
463 RTC_CHECK(task_checker_.CalledSequentially());
464 if (!send_stream_)
465 return true;
466 if (!rtc::AtomicOps::AcquireLoad(&activity_)) {
467 if (!timed_out_) {
468 send_stream_->SignalEncoderTimedOut();
469 }
470 timed_out_ = true;
471 } else if (timed_out_) {
472 send_stream_->SignalEncoderActive();
473 timed_out_ = false;
474 }
475 rtc::AtomicOps::ReleaseStore(&activity_, 0);
476
477 rtc::TaskQueue::Current()->PostDelayedTask(
478 std::unique_ptr<rtc::QueuedTask>(this), kEncoderTimeOutMs);
479 // Return false to prevent this task from being deleted. Ownership has been
480 // transferred to the task queue when PostDelayedTask was called.
481 return false;
482 }
483 volatile int activity_;
484
485 rtc::SequencedTaskChecker task_checker_;
perkj8ff860a2016-10-03 00:30:04 -0700486 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
perkj26091b12016-09-01 01:17:40 -0700487 bool timed_out_;
488};
489
Per512ecb32016-09-23 15:52:06 +0200490class VideoSendStreamImpl::EncoderReconfiguredTask : public rtc::QueuedTask {
perkj26091b12016-09-01 01:17:40 -0700491 public:
perkj8ff860a2016-10-03 00:30:04 -0700492 EncoderReconfiguredTask(const rtc::WeakPtr<VideoSendStreamImpl>& send_stream,
Per512ecb32016-09-23 15:52:06 +0200493 std::vector<VideoStream> streams,
494 int min_transmit_bitrate_bps)
perkj8ff860a2016-10-03 00:30:04 -0700495 : send_stream_(std::move(send_stream)),
Per512ecb32016-09-23 15:52:06 +0200496 streams_(std::move(streams)),
497 min_transmit_bitrate_bps_(min_transmit_bitrate_bps) {}
perkj26091b12016-09-01 01:17:40 -0700498
499 private:
500 bool Run() override {
perkj8ff860a2016-10-03 00:30:04 -0700501 if (send_stream_)
502 send_stream_->OnEncoderConfigurationChanged(std::move(streams_),
503 min_transmit_bitrate_bps_);
perkj26091b12016-09-01 01:17:40 -0700504 return true;
505 }
506
perkj8ff860a2016-10-03 00:30:04 -0700507 rtc::WeakPtr<VideoSendStreamImpl> send_stream_;
Per512ecb32016-09-23 15:52:06 +0200508 std::vector<VideoStream> streams_;
509 int min_transmit_bitrate_bps_;
perkj26091b12016-09-01 01:17:40 -0700510};
511
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +0000512VideoSendStream::VideoSendStream(
Peter Boström45553ae2015-05-08 13:54:38 +0200513 int num_cpu_cores,
Peter Boströmf16fcbe2015-04-30 12:16:05 +0200514 ProcessThread* module_process_thread,
perkj26091b12016-09-01 01:17:40 -0700515 rtc::TaskQueue* worker_queue,
mflodmane3787022015-10-21 13:24:28 +0200516 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700517 RtpTransportControllerSendInterface* transport,
mflodman0e7e2592015-11-12 21:02:42 -0800518 BitrateAllocator* bitrate_allocator,
asapersson35151f32016-05-02 23:44:01 -0700519 SendDelayStats* send_delay_stats,
tereliusadafe0b2016-05-26 01:58:40 -0700520 RtcEventLog* event_log,
perkj26091b12016-09-01 01:17:40 -0700521 VideoSendStream::Config config,
522 VideoEncoderConfig encoder_config,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200523 const std::map<uint32_t, RtpState>& suspended_ssrcs,
524 const std::map<uint32_t, RtpPayloadState>& suspended_payload_states)
perkj26091b12016-09-01 01:17:40 -0700525 : worker_queue_(worker_queue),
526 thread_sync_event_(false /* manual_reset */, false),
527 stats_proxy_(Clock::GetRealTimeClock(),
sprangb4a1ae52015-12-03 08:10:08 -0800528 config,
529 encoder_config.content_type),
sprangf24a0642017-02-28 13:23:26 -0800530 config_(std::move(config)),
531 content_type_(encoder_config.content_type) {
mflodmancc3d4422017-08-03 08:27:51 -0700532 video_stream_encoder_.reset(
533 new VideoStreamEncoder(num_cpu_cores, &stats_proxy_,
534 config_.encoder_settings,
535 config_.pre_encode_callback,
536 config_.post_encode_callback,
537 std::unique_ptr<OveruseFrameDetector>()));
perkj26091b12016-09-01 01:17:40 -0700538 worker_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(new ConstructionTask(
mflodmancc3d4422017-08-03 08:27:51 -0700539 &send_stream_, &thread_sync_event_, &stats_proxy_,
540 video_stream_encoder_.get(), module_process_thread, call_stats, transport,
541 bitrate_allocator, send_delay_stats, event_log, &config_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200542 encoder_config.max_bitrate_bps, suspended_ssrcs, suspended_payload_states,
sprangdb2a9fc2017-08-09 06:42:32 -0700543 encoder_config.content_type)));
perkj26091b12016-09-01 01:17:40 -0700544
545 // Wait for ConstructionTask to complete so that |send_stream_| can be used.
546 // |module_process_thread| must be registered and deregistered on the thread
547 // it was created on.
548 thread_sync_event_.Wait(rtc::Event::kForever);
549 send_stream_->RegisterProcessThread(module_process_thread);
sprang44b3ef62017-01-13 07:30:25 -0800550 // TODO(sprang): Enable this also for regular video calls if it works well.
551 if (encoder_config.content_type == VideoEncoderConfig::ContentType::kScreen) {
552 // Only signal target bitrate for screenshare streams, for now.
mflodmancc3d4422017-08-03 08:27:51 -0700553 video_stream_encoder_->SetBitrateObserver(send_stream_.get());
sprang44b3ef62017-01-13 07:30:25 -0800554 }
perkj26091b12016-09-01 01:17:40 -0700555
556 ReconfigureVideoEncoder(std::move(encoder_config));
557}
558
559VideoSendStream::~VideoSendStream() {
560 RTC_DCHECK_RUN_ON(&thread_checker_);
561 RTC_DCHECK(!send_stream_);
562}
563
564void VideoSendStream::Start() {
565 RTC_DCHECK_RUN_ON(&thread_checker_);
566 LOG(LS_INFO) << "VideoSendStream::Start";
567 VideoSendStreamImpl* send_stream = send_stream_.get();
568 worker_queue_->PostTask([this, send_stream] {
569 send_stream->Start();
570 thread_sync_event_.Set();
571 });
572
573 // It is expected that after VideoSendStream::Start has been called, incoming
mflodmancc3d4422017-08-03 08:27:51 -0700574 // frames are not dropped in VideoStreamEncoder. To ensure this, Start has to
575 // be synchronized.
perkj26091b12016-09-01 01:17:40 -0700576 thread_sync_event_.Wait(rtc::Event::kForever);
577}
578
579void VideoSendStream::Stop() {
580 RTC_DCHECK_RUN_ON(&thread_checker_);
581 LOG(LS_INFO) << "VideoSendStream::Stop";
582 VideoSendStreamImpl* send_stream = send_stream_.get();
583 worker_queue_->PostTask([send_stream] { send_stream->Stop(); });
584}
585
perkja49cbd32016-09-16 07:53:41 -0700586void VideoSendStream::SetSource(
perkj803d97f2016-11-01 11:45:46 -0700587 rtc::VideoSourceInterface<webrtc::VideoFrame>* source,
588 const DegradationPreference& degradation_preference) {
perkja49cbd32016-09-16 07:53:41 -0700589 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700590 video_stream_encoder_->SetSource(source, degradation_preference);
perkj26091b12016-09-01 01:17:40 -0700591}
592
593void VideoSendStream::ReconfigureVideoEncoder(VideoEncoderConfig config) {
perkjfa10b552016-10-02 23:45:26 -0700594 // TODO(perkj): Some test cases in VideoSendStreamTest call
595 // ReconfigureVideoEncoder from the network thread.
596 // RTC_DCHECK_RUN_ON(&thread_checker_);
sprangf24a0642017-02-28 13:23:26 -0800597 RTC_DCHECK(content_type_ == config.content_type);
mflodmancc3d4422017-08-03 08:27:51 -0700598 video_stream_encoder_->ConfigureEncoder(std::move(config),
599 config_.rtp.max_packet_size,
600 config_.rtp.nack.rtp_history_ms > 0);
perkj26091b12016-09-01 01:17:40 -0700601}
602
603VideoSendStream::Stats VideoSendStream::GetStats() {
604 // TODO(perkj, solenberg): Some test cases in EndToEndTest call GetStats from
605 // a network thread. See comment in Call::GetStats().
606 // RTC_DCHECK_RUN_ON(&thread_checker_);
607 return stats_proxy_.GetStats();
608}
609
610void VideoSendStream::SignalNetworkState(NetworkState state) {
611 RTC_DCHECK_RUN_ON(&thread_checker_);
612 VideoSendStreamImpl* send_stream = send_stream_.get();
613 worker_queue_->PostTask(
614 [send_stream, state] { send_stream->SignalNetworkState(state); });
615}
616
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200617void VideoSendStream::StopPermanentlyAndGetRtpStates(
618 VideoSendStream::RtpStateMap* rtp_state_map,
619 VideoSendStream::RtpPayloadStateMap* payload_state_map) {
perkj26091b12016-09-01 01:17:40 -0700620 RTC_DCHECK_RUN_ON(&thread_checker_);
mflodmancc3d4422017-08-03 08:27:51 -0700621 video_stream_encoder_->Stop();
perkj26091b12016-09-01 01:17:40 -0700622 send_stream_->DeRegisterProcessThread();
623 worker_queue_->PostTask(
624 std::unique_ptr<rtc::QueuedTask>(new DestructAndGetRtpStateTask(
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200625 rtp_state_map, payload_state_map, std::move(send_stream_),
626 &thread_sync_event_)));
perkj26091b12016-09-01 01:17:40 -0700627 thread_sync_event_.Wait(rtc::Event::kForever);
perkj26091b12016-09-01 01:17:40 -0700628}
629
nisse284542b2017-01-10 08:58:32 -0800630void VideoSendStream::SetTransportOverhead(
631 size_t transport_overhead_per_packet) {
michaelt79e05882016-11-08 02:50:09 -0800632 RTC_DCHECK_RUN_ON(&thread_checker_);
633 VideoSendStreamImpl* send_stream = send_stream_.get();
634 worker_queue_->PostTask([send_stream, transport_overhead_per_packet] {
635 send_stream->SetTransportOverhead(transport_overhead_per_packet);
636 });
637}
638
perkj26091b12016-09-01 01:17:40 -0700639bool VideoSendStream::DeliverRtcp(const uint8_t* packet, size_t length) {
640 // Called on a network thread.
641 return send_stream_->DeliverRtcp(packet, length);
642}
643
palmkviste75f2042016-09-28 06:19:48 -0700644void VideoSendStream::EnableEncodedFrameRecording(
645 const std::vector<rtc::PlatformFile>& files,
646 size_t byte_limit) {
647 send_stream_->EnableEncodedFrameRecording(files, byte_limit);
648}
649
perkj26091b12016-09-01 01:17:40 -0700650VideoSendStreamImpl::VideoSendStreamImpl(
651 SendStatisticsProxy* stats_proxy,
652 rtc::TaskQueue* worker_queue,
653 CallStats* call_stats,
nisseb8f9a322017-03-27 05:36:15 -0700654 RtpTransportControllerSendInterface* transport,
perkj26091b12016-09-01 01:17:40 -0700655 BitrateAllocator* bitrate_allocator,
656 SendDelayStats* send_delay_stats,
mflodmancc3d4422017-08-03 08:27:51 -0700657 VideoStreamEncoder* video_stream_encoder,
perkj26091b12016-09-01 01:17:40 -0700658 RtcEventLog* event_log,
659 const VideoSendStream::Config* config,
Per512ecb32016-09-23 15:52:06 +0200660 int initial_encoder_max_bitrate,
sprang89c4a7e2017-06-30 13:27:40 -0700661 std::map<uint32_t, RtpState> suspended_ssrcs,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200662 std::map<uint32_t, RtpPayloadState> suspended_payload_states,
sprangdb2a9fc2017-08-09 06:42:32 -0700663 VideoEncoderConfig::ContentType content_type)
sprangc1b57a12017-02-28 08:50:47 -0800664 : send_side_bwe_with_overhead_(
665 webrtc::field_trial::IsEnabled("WebRTC-SendSideBwe-WithOverhead")),
elad.alon0fe12162017-01-31 05:48:37 -0800666 stats_proxy_(stats_proxy),
pbos@webrtc.org64887612013-11-14 08:58:14 +0000667 config_(config),
perkj26091b12016-09-01 01:17:40 -0700668 suspended_ssrcs_(std::move(suspended_ssrcs)),
669 module_process_thread_(nullptr),
670 worker_queue_(worker_queue),
671 check_encoder_activity_task_(nullptr),
mflodmane3787022015-10-21 13:24:28 +0200672 call_stats_(call_stats),
nisseb8f9a322017-03-27 05:36:15 -0700673 transport_(transport),
mflodman86aabb22016-03-11 15:44:32 +0100674 bitrate_allocator_(bitrate_allocator),
brandtr48d21a22017-05-30 02:32:12 -0700675 flexfec_sender_(MaybeCreateFlexfecSender(*config_, suspended_ssrcs_)),
perkj26091b12016-09-01 01:17:40 -0700676 max_padding_bitrate_(0),
677 encoder_min_bitrate_bps_(0),
Per512ecb32016-09-23 15:52:06 +0200678 encoder_max_bitrate_bps_(initial_encoder_max_bitrate),
perkj9b522f82016-07-07 00:36:28 -0700679 encoder_target_rate_bps_(0),
mflodmancc3d4422017-08-03 08:27:51 -0700680 video_stream_encoder_(video_stream_encoder),
perkj600246e2016-05-04 11:26:51 -0700681 encoder_feedback_(Clock::GetRealTimeClock(),
perkj26091b12016-09-01 01:17:40 -0700682 config_->rtp.ssrcs,
mflodmancc3d4422017-08-03 08:27:51 -0700683 video_stream_encoder),
Per69b332d2016-06-02 15:45:42 +0200684 protection_bitrate_calculator_(Clock::GetRealTimeClock(), this),
nisseb8f9a322017-03-27 05:36:15 -0700685 bandwidth_observer_(transport->send_side_cc()
686 ->GetBitrateController()
687 ->CreateRtcpBandwidthObserver()),
688 rtp_rtcp_modules_(CreateRtpRtcpModules(
689 config_->send_transport,
690 &encoder_feedback_,
691 bandwidth_observer_.get(),
692 transport,
693 call_stats_->rtcp_rtt_stats(),
694 flexfec_sender_.get(),
695 stats_proxy_,
696 send_delay_stats,
697 event_log,
698 transport->send_side_cc()->GetRetransmissionRateLimiter(),
699 this,
sprang168794c2017-07-06 04:38:06 -0700700 config_->rtp.ssrcs.size(),
sprangdb2a9fc2017-08-09 06:42:32 -0700701 transport->keepalive_config())),
perkj26091b12016-09-01 01:17:40 -0700702 payload_router_(rtp_rtcp_modules_,
Ã…sa Persson4bece9a2017-10-06 10:04:04 +0200703 config_->rtp.ssrcs,
704 config_->encoder_settings.payload_type,
705 suspended_payload_states),
michaelta3328772016-11-29 09:25:03 -0800706 weak_ptr_factory_(this),
707 overhead_bytes_per_packet_(0),
708 transport_overhead_bytes_per_packet_(0) {
perkj26091b12016-09-01 01:17:40 -0700709 RTC_DCHECK_RUN_ON(worker_queue_);
710 LOG(LS_INFO) << "VideoSendStreamInternal: " << config_->ToString();
perkj8ff860a2016-10-03 00:30:04 -0700711 weak_ptr_ = weak_ptr_factory_.GetWeakPtr();
perkj26091b12016-09-01 01:17:40 -0700712 module_process_thread_checker_.DetachFromThread();
Stefan Holmer58c664c2016-02-08 14:31:30 +0100713
perkj26091b12016-09-01 01:17:40 -0700714 RTC_DCHECK(!config_->rtp.ssrcs.empty());
Stefan Holmer58c664c2016-02-08 14:31:30 +0100715 RTC_DCHECK(call_stats_);
nisseb8f9a322017-03-27 05:36:15 -0700716 RTC_DCHECK(transport_);
717 RTC_DCHECK(transport_->send_side_cc());
stefand7a418f2017-08-08 06:51:05 -0700718 RTC_CHECK(field_trial::FindFullName(
719 AlrDetector::kStrictPacingAndProbingExperimentName)
720 .empty() ||
721 field_trial::FindFullName(
722 AlrDetector::kScreenshareProbingBweExperimentName)
723 .empty());
Erik Språng7c8cca32017-10-24 17:05:18 +0200724 // If send-side BWE is enabled, check if we should apply updated probing and
725 // pacing settings.
726 if (TransportSeqNumExtensionConfigured(*config_)) {
727 rtc::Optional<AlrDetector::AlrExperimentSettings> alr_settings;
728 if (content_type == VideoEncoderConfig::ContentType::kScreen) {
729 alr_settings = AlrDetector::ParseAlrSettingsFromFieldTrial(
730 AlrDetector::kScreenshareProbingBweExperimentName);
731 } else {
732 alr_settings = AlrDetector::ParseAlrSettingsFromFieldTrial(
733 AlrDetector::kStrictPacingAndProbingExperimentName);
734 }
735 if (alr_settings) {
736 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
737 transport->pacer()->SetPacingFactor(alr_settings->pacing_factor);
738 transport->pacer()->SetQueueTimeLimit(alr_settings->max_paced_queue_time);
739 }
sprang89c4a7e2017-06-30 13:27:40 -0700740 }
741
742 if (config_->periodic_alr_bandwidth_probing) {
743 transport->send_side_cc()->EnablePeriodicAlrProbing(true);
744 }
sergeyu80ed35e2016-11-28 13:11:13 -0800745
Per83d09102016-04-15 14:59:13 +0200746 // RTP/RTCP initialization.
stefan16b02212017-01-27 07:12:16 -0800747
748 // We add the highest spatial layer first to ensure it'll be prioritized
749 // when sending padding, with the hope that the packet rate will be smaller,
750 // and that it's more important to protect than the lower layers.
eladalon822ff2b2017-08-01 06:30:28 -0700751 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
752 constexpr bool remb_candidate = true;
753 transport->packet_router()->AddSendRtpModule(rtp_rtcp, remb_candidate);
754 }
mflodman949c2f02015-10-16 02:31:11 -0700755
perkj26091b12016-09-01 01:17:40 -0700756 for (size_t i = 0; i < config_->rtp.extensions.size(); ++i) {
757 const std::string& extension = config_->rtp.extensions[i].uri;
758 int id = config_->rtp.extensions[i].id;
Peter Boström23914fe2015-03-31 15:08:04 +0200759 // One-byte-extension local identifiers are in the range 1-14 inclusive.
henrikg91d6ede2015-09-17 00:24:34 -0700760 RTC_DCHECK_GE(id, 1);
761 RTC_DCHECK_LE(id, 14);
Peter Boström9c017252016-02-26 16:26:20 +0100762 RTC_DCHECK(RtpExtension::IsSupportedForVideo(extension));
763 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
764 RTC_CHECK_EQ(0, rtp_rtcp->RegisterSendRtpHeaderExtension(
765 StringToRtpExtensionType(extension), id));
pbos@webrtc.org29023282013-09-11 10:14:56 +0000766 }
767 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000768
Per83d09102016-04-15 14:59:13 +0200769 ConfigureProtection();
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +0000770 ConfigureSsrcs();
771
Peter Boström723ead82016-02-22 15:14:01 +0100772 // TODO(pbos): Should we set CNAME on all RTP modules?
perkj26091b12016-09-01 01:17:40 -0700773 rtp_rtcp_modules_.front()->SetCNAME(config_->rtp.c_name.c_str());
michaelta3328772016-11-29 09:25:03 -0800774
Peter Boström723ead82016-02-22 15:14:01 +0100775 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -0700776 rtp_rtcp->RegisterRtcpStatisticsCallback(stats_proxy_);
777 rtp_rtcp->RegisterSendChannelRtpStatisticsCallback(stats_proxy_);
nisse284542b2017-01-10 08:58:32 -0800778 rtp_rtcp->SetMaxRtpPacketSize(config_->rtp.max_packet_size);
Peter Boström8b79b072016-02-26 16:31:37 +0100779 rtp_rtcp->RegisterVideoSendPayload(
perkj26091b12016-09-01 01:17:40 -0700780 config_->encoder_settings.payload_type,
781 config_->encoder_settings.payload_name.c_str());
Peter Boström723ead82016-02-22 15:14:01 +0100782 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000783
perkj26091b12016-09-01 01:17:40 -0700784 RTC_DCHECK(config_->encoder_settings.encoder);
785 RTC_DCHECK_GE(config_->encoder_settings.payload_type, 0);
786 RTC_DCHECK_LE(config_->encoder_settings.payload_type, 127);
pbos@webrtc.orgfe1ef932013-10-21 10:34:43 +0000787
mflodmancc3d4422017-08-03 08:27:51 -0700788 video_stream_encoder_->SetStartBitrate(
789 bitrate_allocator_->GetStartBitrate(this));
perkj803d97f2016-11-01 11:45:46 -0700790
791 // Only request rotation at the source when we positively know that the remote
792 // side doesn't support the rotation extension. This allows us to prepare the
793 // encoder in the expectation that rotation is supported - which is the common
794 // case.
795 bool rotation_applied =
796 std::find_if(config_->rtp.extensions.begin(),
797 config_->rtp.extensions.end(),
798 [](const RtpExtension& extension) {
799 return extension.uri == RtpExtension::kVideoRotationUri;
800 }) == config_->rtp.extensions.end();
801
mflodmancc3d4422017-08-03 08:27:51 -0700802 video_stream_encoder_->SetSink(this, rotation_applied);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000803}
804
perkj26091b12016-09-01 01:17:40 -0700805void VideoSendStreamImpl::RegisterProcessThread(
806 ProcessThread* module_process_thread) {
807 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
808 RTC_DCHECK(!module_process_thread_);
809 module_process_thread_ = module_process_thread;
mflodman86aabb22016-03-11 15:44:32 +0100810
perkj26091b12016-09-01 01:17:40 -0700811 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
tommidea489f2017-03-03 03:20:24 -0800812 module_process_thread_->RegisterModule(rtp_rtcp, RTC_FROM_HERE);
perkj26091b12016-09-01 01:17:40 -0700813}
Peter Boströmca835252016-02-11 15:59:46 +0100814
perkj26091b12016-09-01 01:17:40 -0700815void VideoSendStreamImpl::DeRegisterProcessThread() {
816 RTC_DCHECK_RUN_ON(&module_process_thread_checker_);
817 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
818 module_process_thread_->DeRegisterModule(rtp_rtcp);
819}
Peter Boströma4c76882016-03-03 16:29:02 +0100820
perkj26091b12016-09-01 01:17:40 -0700821VideoSendStreamImpl::~VideoSendStreamImpl() {
822 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -0800823 RTC_DCHECK(!payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -0700824 << "VideoSendStreamImpl::Stop not called";
825 LOG(LS_INFO) << "~VideoSendStreamInternal: " << config_->ToString();
sprang@webrtc.orgccd42842014-01-07 09:54:34 +0000826
Per83d09102016-04-15 14:59:13 +0200827 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nissefdbfdc92017-03-31 05:44:52 -0700828 transport_->packet_router()->RemoveSendRtpModule(rtp_rtcp);
Per83d09102016-04-15 14:59:13 +0200829 delete rtp_rtcp;
830 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000831}
832
perkj26091b12016-09-01 01:17:40 -0700833bool VideoSendStreamImpl::DeliverRtcp(const uint8_t* packet, size_t length) {
834 // Runs on a network thread.
835 RTC_DCHECK(!worker_queue_->IsCurrent());
pbos1ba8d392016-05-01 20:18:34 -0700836 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_)
837 rtp_rtcp->IncomingRtcpPacket(packet, length);
838 return true;
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000839}
840
perkj26091b12016-09-01 01:17:40 -0700841void VideoSendStreamImpl::Start() {
842 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700843 LOG(LS_INFO) << "VideoSendStream::Start";
sprang1a646ee2016-12-01 06:34:11 -0800844 if (payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100845 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200846 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Start");
sprang1a646ee2016-12-01 06:34:11 -0800847 payload_router_.SetActive(true);
perkj26091b12016-09-01 01:17:40 -0700848
849 bitrate_allocator_->AddObserver(
850 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200851 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
852 config_->track_id);
perkj26091b12016-09-01 01:17:40 -0700853
854 // Start monitoring encoder activity.
perkj57c21f92016-06-17 07:27:16 -0700855 {
perkj26091b12016-09-01 01:17:40 -0700856 rtc::CritScope lock(&encoder_activity_crit_sect_);
857 RTC_DCHECK(!check_encoder_activity_task_);
perkj8ff860a2016-10-03 00:30:04 -0700858 check_encoder_activity_task_ = new CheckEncoderActivityTask(weak_ptr_);
perkj26091b12016-09-01 01:17:40 -0700859 worker_queue_->PostDelayedTask(
860 std::unique_ptr<rtc::QueuedTask>(check_encoder_activity_task_),
861 CheckEncoderActivityTask::kEncoderTimeOutMs);
perkj57c21f92016-06-17 07:27:16 -0700862 }
perkj26091b12016-09-01 01:17:40 -0700863
mflodmancc3d4422017-08-03 08:27:51 -0700864 video_stream_encoder_->SendKeyFrame();
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000865}
866
perkj26091b12016-09-01 01:17:40 -0700867void VideoSendStreamImpl::Stop() {
868 RTC_DCHECK_RUN_ON(worker_queue_);
perkj9b522f82016-07-07 00:36:28 -0700869 LOG(LS_INFO) << "VideoSendStream::Stop";
sprang1a646ee2016-12-01 06:34:11 -0800870 if (!payload_router_.IsActive())
Peter Boström0a9fc052016-03-02 16:24:10 +0100871 return;
Peter Boströmdabc9442016-04-11 11:45:14 +0200872 TRACE_EVENT_INSTANT0("webrtc", "VideoSendStream::Stop");
sprang1a646ee2016-12-01 06:34:11 -0800873 payload_router_.SetActive(false);
perkj26091b12016-09-01 01:17:40 -0700874 bitrate_allocator_->RemoveObserver(this);
perkj57c21f92016-06-17 07:27:16 -0700875 {
perkj26091b12016-09-01 01:17:40 -0700876 rtc::CritScope lock(&encoder_activity_crit_sect_);
877 check_encoder_activity_task_->Stop();
878 check_encoder_activity_task_ = nullptr;
perkj57c21f92016-06-17 07:27:16 -0700879 }
mflodmancc3d4422017-08-03 08:27:51 -0700880 video_stream_encoder_->OnBitrateUpdated(0, 0, 0);
perkj26091b12016-09-01 01:17:40 -0700881 stats_proxy_->OnSetEncoderTargetRate(0);
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000882}
883
perkj26091b12016-09-01 01:17:40 -0700884void VideoSendStreamImpl::SignalEncoderTimedOut() {
885 RTC_DCHECK_RUN_ON(worker_queue_);
886 // If the encoder has not produced anything the last kEncoderTimeOutMs and it
887 // is supposed to, deregister as BitrateAllocatorObserver. This can happen
888 // if a camera stops producing frames.
889 if (encoder_target_rate_bps_ > 0) {
890 LOG(LS_INFO) << "SignalEncoderTimedOut, Encoder timed out.";
891 bitrate_allocator_->RemoveObserver(this);
Peter Boströma4c76882016-03-03 16:29:02 +0100892 }
893}
894
sprang1a646ee2016-12-01 06:34:11 -0800895void VideoSendStreamImpl::OnBitrateAllocationUpdated(
896 const BitrateAllocation& allocation) {
897 payload_router_.OnBitrateAllocationUpdated(allocation);
898}
899
perkj26091b12016-09-01 01:17:40 -0700900void VideoSendStreamImpl::SignalEncoderActive() {
901 RTC_DCHECK_RUN_ON(worker_queue_);
902 LOG(LS_INFO) << "SignalEncoderActive, Encoder is active.";
903 bitrate_allocator_->AddObserver(
904 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200905 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
906 config_->track_id);
perkj26091b12016-09-01 01:17:40 -0700907}
908
Per512ecb32016-09-23 15:52:06 +0200909void VideoSendStreamImpl::OnEncoderConfigurationChanged(
910 std::vector<VideoStream> streams,
911 int min_transmit_bitrate_bps) {
912 if (!worker_queue_->IsCurrent()) {
Per512ecb32016-09-23 15:52:06 +0200913 worker_queue_->PostTask(
914 std::unique_ptr<rtc::QueuedTask>(new EncoderReconfiguredTask(
perkj8ff860a2016-10-03 00:30:04 -0700915 weak_ptr_, std::move(streams), min_transmit_bitrate_bps)));
Per512ecb32016-09-23 15:52:06 +0200916 return;
917 }
918 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
919 TRACE_EVENT0("webrtc", "VideoSendStream::OnEncoderConfigurationChanged");
920 RTC_DCHECK_GE(config_->rtp.ssrcs.size(), streams.size());
perkj26091b12016-09-01 01:17:40 -0700921 RTC_DCHECK_RUN_ON(worker_queue_);
922
923 const int kEncoderMinBitrateBps = 30000;
924 encoder_min_bitrate_bps_ =
Per512ecb32016-09-23 15:52:06 +0200925 std::max(streams[0].min_bitrate_bps, kEncoderMinBitrateBps);
perkj26091b12016-09-01 01:17:40 -0700926 encoder_max_bitrate_bps_ = 0;
Per512ecb32016-09-23 15:52:06 +0200927 for (const auto& stream : streams)
perkj26091b12016-09-01 01:17:40 -0700928 encoder_max_bitrate_bps_ += stream.max_bitrate_bps;
Per512ecb32016-09-23 15:52:06 +0200929 max_padding_bitrate_ = CalculateMaxPadBitrateBps(
930 streams, min_transmit_bitrate_bps, config_->suspend_below_min_bitrate);
perkj26091b12016-09-01 01:17:40 -0700931
932 // Clear stats for disabled layers.
Per512ecb32016-09-23 15:52:06 +0200933 for (size_t i = streams.size(); i < config_->rtp.ssrcs.size(); ++i) {
perkj26091b12016-09-01 01:17:40 -0700934 stats_proxy_->OnInactiveSsrc(config_->rtp.ssrcs[i]);
pbos@webrtc.orgbbe0a852014-09-19 12:30:25 +0000935 }
perkj26091b12016-09-01 01:17:40 -0700936
937 size_t number_of_temporal_layers =
Per512ecb32016-09-23 15:52:06 +0200938 streams.back().temporal_layer_thresholds_bps.size() + 1;
perkj26091b12016-09-01 01:17:40 -0700939 protection_bitrate_calculator_.SetEncodingData(
Per512ecb32016-09-23 15:52:06 +0200940 streams[0].width, streams[0].height, number_of_temporal_layers,
941 config_->rtp.max_packet_size);
perkj26091b12016-09-01 01:17:40 -0700942
sprang1a646ee2016-12-01 06:34:11 -0800943 if (payload_router_.IsActive()) {
perkj26091b12016-09-01 01:17:40 -0700944 // The send stream is started already. Update the allocator with new bitrate
945 // limits.
946 bitrate_allocator_->AddObserver(
947 this, encoder_min_bitrate_bps_, encoder_max_bitrate_bps_,
Alex Narestb3944f02017-10-13 14:56:18 +0200948 max_padding_bitrate_, !config_->suspend_below_min_bitrate,
949 config_->track_id);
perkj26091b12016-09-01 01:17:40 -0700950 }
pbos@webrtc.org29d58392013-05-16 12:08:03 +0000951}
952
perkj26091b12016-09-01 01:17:40 -0700953EncodedImageCallback::Result VideoSendStreamImpl::OnEncodedImage(
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700954 const EncodedImage& encoded_image,
955 const CodecSpecificInfo* codec_specific_info,
956 const RTPFragmentationHeader* fragmentation) {
perkj26091b12016-09-01 01:17:40 -0700957 // Encoded is called on whatever thread the real encoder implementation run
958 // on. In the case of hardware encoders, there might be several encoders
959 // running in parallel on different threads.
ilnikcb8c1462017-03-09 09:23:30 -0800960 size_t simulcast_idx = 0;
961 if (codec_specific_info->codecType == kVideoCodecVP8) {
962 simulcast_idx = codec_specific_info->codecSpecific.VP8.simulcastIdx;
963 }
perkj26091b12016-09-01 01:17:40 -0700964 if (config_->post_encode_callback) {
ilnikcb8c1462017-03-09 09:23:30 -0800965 config_->post_encode_callback->EncodedFrameCallback(EncodedFrame(
966 encoded_image._buffer, encoded_image._length, encoded_image._frameType,
967 simulcast_idx, encoded_image._timeStamp));
sergeyu37ad3372016-06-14 15:29:37 -0700968 }
perkj26091b12016-09-01 01:17:40 -0700969 {
970 rtc::CritScope lock(&encoder_activity_crit_sect_);
971 if (check_encoder_activity_task_)
972 check_encoder_activity_task_->UpdateEncoderActivity();
973 }
sergeyu37ad3372016-06-14 15:29:37 -0700974
Per69b332d2016-06-02 15:45:42 +0200975 protection_bitrate_calculator_.UpdateWithEncodedData(encoded_image);
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700976 EncodedImageCallback::Result result = payload_router_.OnEncodedImage(
perkj600246e2016-05-04 11:26:51 -0700977 encoded_image, codec_specific_info, fragmentation);
978
palmkviste75f2042016-09-28 06:19:48 -0700979 RTC_DCHECK(codec_specific_info);
980
981 int layer = codec_specific_info->codecType == kVideoCodecVP8
982 ? codec_specific_info->codecSpecific.VP8.simulcastIdx
983 : 0;
984 {
985 rtc::CritScope lock(&ivf_writers_crit_);
986 if (file_writers_[layer].get()) {
987 bool ok = file_writers_[layer]->WriteFrame(
988 encoded_image, codec_specific_info->codecType);
perkj600246e2016-05-04 11:26:51 -0700989 RTC_DCHECK(ok);
990 }
991 }
992
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700993 return result;
perkjbc75d972016-05-02 06:31:25 -0700994}
995
perkj26091b12016-09-01 01:17:40 -0700996void VideoSendStreamImpl::ConfigureProtection() {
997 RTC_DCHECK_RUN_ON(worker_queue_);
brandtre6f98c72016-11-11 03:28:30 -0800998
brandtre950cad2016-11-15 05:25:41 -0800999 // Consistency of FlexFEC parameters is checked in MaybeCreateFlexfecSender.
1000 const bool flexfec_enabled = (flexfec_sender_ != nullptr);
1001
1002 // Consistency of NACK and RED+ULPFEC parameters is checked in this function.
brandtre6f98c72016-11-11 03:28:30 -08001003 const bool nack_enabled = config_->rtp.nack.rtp_history_ms > 0;
1004 int red_payload_type = config_->rtp.ulpfec.red_payload_type;
brandtrf1bb4762016-11-07 03:05:06 -08001005 int ulpfec_payload_type = config_->rtp.ulpfec.ulpfec_payload_type;
brandtre6f98c72016-11-11 03:28:30 -08001006
1007 // Shorthands.
1008 auto IsRedEnabled = [&]() { return red_payload_type >= 0; };
brandtre950cad2016-11-15 05:25:41 -08001009 auto DisableRed = [&]() { red_payload_type = -1; };
brandtre6f98c72016-11-11 03:28:30 -08001010 auto IsUlpfecEnabled = [&]() { return ulpfec_payload_type >= 0; };
1011 auto DisableUlpfec = [&]() { ulpfec_payload_type = -1; };
1012
stefan60e10c72017-08-23 10:40:00 -07001013 if (webrtc::field_trial::IsEnabled("WebRTC-DisableUlpFecExperiment")) {
1014 LOG(LS_INFO) << "Experiment to disable sending ULPFEC is enabled.";
1015 DisableUlpfec();
1016 }
1017
brandtre950cad2016-11-15 05:25:41 -08001018 // If enabled, FlexFEC takes priority over RED+ULPFEC.
1019 if (flexfec_enabled) {
1020 // We can safely disable RED here, because if the remote supports FlexFEC,
1021 // we know that it has a receiver without the RED/RTX workaround.
1022 // See http://crbug.com/webrtc/6650 for more information.
1023 if (IsRedEnabled()) {
1024 LOG(LS_INFO) << "Both FlexFEC and RED are configured. Disabling RED.";
1025 DisableRed();
1026 }
1027 if (IsUlpfecEnabled()) {
1028 LOG(LS_INFO)
1029 << "Both FlexFEC and ULPFEC are configured. Disabling ULPFEC.";
1030 DisableUlpfec();
1031 }
1032 }
1033
Per83d09102016-04-15 14:59:13 +02001034 // Payload types without picture ID cannot determine that a stream is complete
brandtre6f98c72016-11-11 03:28:30 -08001035 // without retransmitting FEC, so using ULPFEC + NACK for H.264 (for instance)
1036 // is a waste of bandwidth since FEC packets still have to be transmitted.
1037 // Note that this is not the case with FlexFEC.
1038 if (nack_enabled && IsUlpfecEnabled() &&
Per83d09102016-04-15 14:59:13 +02001039 !PayloadTypeSupportsSkippingFecPackets(
perkj26091b12016-09-01 01:17:40 -07001040 config_->encoder_settings.payload_name)) {
brandtre6f98c72016-11-11 03:28:30 -08001041 LOG(LS_WARNING)
1042 << "Transmitting payload type without picture ID using "
1043 "NACK+ULPFEC is a waste of bandwidth since ULPFEC packets "
1044 "also have to be retransmitted. Disabling ULPFEC.";
1045 DisableUlpfec();
Per83d09102016-04-15 14:59:13 +02001046 }
1047
brandtre6f98c72016-11-11 03:28:30 -08001048 // Verify payload types.
brandtrd8048952016-11-07 02:08:51 -08001049 //
brandtre6f98c72016-11-11 03:28:30 -08001050 // Due to how old receivers work, we need to always send RED if it has been
1051 // negotiated. This is a remnant of an old RED/RTX workaround, see
1052 // https://codereview.webrtc.org/2469093003.
1053 // TODO(brandtr): This change went into M56, so we can remove it in ~M59.
1054 // At that time, we can disable RED whenever ULPFEC is disabled, as there is
1055 // no point in using RED without ULPFEC.
1056 if (IsRedEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001057 RTC_DCHECK_GE(red_payload_type, 0);
1058 RTC_DCHECK_LE(red_payload_type, 127);
stefan8f4c77f2016-06-03 00:16:45 -07001059 }
brandtre6f98c72016-11-11 03:28:30 -08001060 if (IsUlpfecEnabled()) {
brandtrf1bb4762016-11-07 03:05:06 -08001061 RTC_DCHECK_GE(ulpfec_payload_type, 0);
1062 RTC_DCHECK_LE(ulpfec_payload_type, 127);
brandtre6f98c72016-11-11 03:28:30 -08001063 if (!IsRedEnabled()) {
1064 LOG(LS_WARNING)
1065 << "ULPFEC is enabled but RED is disabled. Disabling ULPFEC.";
1066 DisableUlpfec();
1067 }
Per83d09102016-04-15 14:59:13 +02001068 }
1069
1070 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1071 // Set NACK.
1072 rtp_rtcp->SetStorePacketsStatus(
nisse10daf862016-12-08 06:24:28 -08001073 true,
Per83d09102016-04-15 14:59:13 +02001074 kMinSendSidePacketHistorySize);
brandtre6f98c72016-11-11 03:28:30 -08001075 // Set RED/ULPFEC information.
stefan60e10c72017-08-23 10:40:00 -07001076 rtp_rtcp->SetUlpfecConfig(red_payload_type, ulpfec_payload_type);
Per83d09102016-04-15 14:59:13 +02001077 }
1078
brandtre950cad2016-11-15 05:25:41 -08001079 // Currently, both ULPFEC and FlexFEC use the same FEC rate calculation logic,
1080 // so enable that logic if either of those FEC schemes are enabled.
1081 protection_bitrate_calculator_.SetProtectionMethod(
1082 flexfec_enabled || IsUlpfecEnabled(), nack_enabled);
Per83d09102016-04-15 14:59:13 +02001083}
1084
perkj26091b12016-09-01 01:17:40 -07001085void VideoSendStreamImpl::ConfigureSsrcs() {
1086 RTC_DCHECK_RUN_ON(worker_queue_);
Peter Boström723ead82016-02-22 15:14:01 +01001087 // Configure regular SSRCs.
perkj26091b12016-09-01 01:17:40 -07001088 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1089 uint32_t ssrc = config_->rtp.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001090 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1091 rtp_rtcp->SetSSRC(ssrc);
1092
1093 // Restore RTP state if previous existed.
perkj26091b12016-09-01 01:17:40 -07001094 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001095 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001096 rtp_rtcp->SetRtpState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001097 }
1098
Peter Boström723ead82016-02-22 15:14:01 +01001099 // Set up RTX if available.
perkj26091b12016-09-01 01:17:40 -07001100 if (config_->rtp.rtx.ssrcs.empty())
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001101 return;
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001102
Peter Boström723ead82016-02-22 15:14:01 +01001103 // Configure RTX SSRCs.
perkj26091b12016-09-01 01:17:40 -07001104 RTC_DCHECK_EQ(config_->rtp.rtx.ssrcs.size(), config_->rtp.ssrcs.size());
1105 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1106 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Peter Boström723ead82016-02-22 15:14:01 +01001107 RtpRtcp* const rtp_rtcp = rtp_rtcp_modules_[i];
1108 rtp_rtcp->SetRtxSsrc(ssrc);
perkj26091b12016-09-01 01:17:40 -07001109 VideoSendStream::RtpStateMap::iterator it = suspended_ssrcs_.find(ssrc);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001110 if (it != suspended_ssrcs_.end())
Per83d09102016-04-15 14:59:13 +02001111 rtp_rtcp->SetRtxState(it->second);
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001112 }
1113
Peter Boström723ead82016-02-22 15:14:01 +01001114 // Configure RTX payload types.
perkj26091b12016-09-01 01:17:40 -07001115 RTC_DCHECK_GE(config_->rtp.rtx.payload_type, 0);
Peter Boström723ead82016-02-22 15:14:01 +01001116 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001117 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.rtx.payload_type,
1118 config_->encoder_settings.payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001119 rtp_rtcp->SetRtxSendStatus(kRtxRetransmitted | kRtxRedundantPayloads);
1120 }
brandtrb5f2c3f2016-10-04 23:28:39 -07001121 if (config_->rtp.ulpfec.red_payload_type != -1 &&
1122 config_->rtp.ulpfec.red_rtx_payload_type != -1) {
Peter Boström723ead82016-02-22 15:14:01 +01001123 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
brandtrb5f2c3f2016-10-04 23:28:39 -07001124 rtp_rtcp->SetRtxSendPayloadType(config_->rtp.ulpfec.red_rtx_payload_type,
1125 config_->rtp.ulpfec.red_payload_type);
Peter Boström723ead82016-02-22 15:14:01 +01001126 }
Stefan Holmer10880012016-02-03 13:29:59 +01001127 }
pbos@webrtc.orgbe9d2a42014-06-30 13:19:09 +00001128}
1129
perkj26091b12016-09-01 01:17:40 -07001130std::map<uint32_t, RtpState> VideoSendStreamImpl::GetRtpStates() const {
1131 RTC_DCHECK_RUN_ON(worker_queue_);
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001132 std::map<uint32_t, RtpState> rtp_states;
brandtr48d21a22017-05-30 02:32:12 -07001133
perkj26091b12016-09-01 01:17:40 -07001134 for (size_t i = 0; i < config_->rtp.ssrcs.size(); ++i) {
1135 uint32_t ssrc = config_->rtp.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001136 RTC_DCHECK_EQ(ssrc, rtp_rtcp_modules_[i]->SSRC());
1137 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtpState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001138 }
1139
perkj26091b12016-09-01 01:17:40 -07001140 for (size_t i = 0; i < config_->rtp.rtx.ssrcs.size(); ++i) {
1141 uint32_t ssrc = config_->rtp.rtx.ssrcs[i];
Per83d09102016-04-15 14:59:13 +02001142 rtp_states[ssrc] = rtp_rtcp_modules_[i]->GetRtxState();
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001143 }
1144
brandtr48d21a22017-05-30 02:32:12 -07001145 if (flexfec_sender_) {
1146 uint32_t ssrc = config_->rtp.flexfec.ssrc;
1147 rtp_states[ssrc] = flexfec_sender_->GetRtpState();
1148 }
1149
pbos@webrtc.org2bb1bda2014-07-07 13:06:48 +00001150 return rtp_states;
1151}
1152
Ã…sa Persson4bece9a2017-10-06 10:04:04 +02001153std::map<uint32_t, RtpPayloadState> VideoSendStreamImpl::GetRtpPayloadStates()
1154 const {
1155 RTC_DCHECK_RUN_ON(worker_queue_);
1156 return payload_router_.GetRtpPayloadStates();
1157}
1158
perkj26091b12016-09-01 01:17:40 -07001159void VideoSendStreamImpl::SignalNetworkState(NetworkState state) {
1160 RTC_DCHECK_RUN_ON(worker_queue_);
perkjfea93092016-05-14 00:58:48 -07001161 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
perkj26091b12016-09-01 01:17:40 -07001162 rtp_rtcp->SetRTCPStatus(state == kNetworkUp ? config_->rtp.rtcp_mode
perkjfea93092016-05-14 00:58:48 -07001163 : RtcpMode::kOff);
1164 }
1165}
1166
perkj26091b12016-09-01 01:17:40 -07001167uint32_t VideoSendStreamImpl::OnBitrateUpdated(uint32_t bitrate_bps,
1168 uint8_t fraction_loss,
minyue78b4d562016-11-30 04:47:39 -08001169 int64_t rtt,
1170 int64_t probing_interval_ms) {
perkj26091b12016-09-01 01:17:40 -07001171 RTC_DCHECK_RUN_ON(worker_queue_);
sprang1a646ee2016-12-01 06:34:11 -08001172 RTC_DCHECK(payload_router_.IsActive())
perkj26091b12016-09-01 01:17:40 -07001173 << "VideoSendStream::Start has not been called.";
michaelta3328772016-11-29 09:25:03 -08001174
michaelt192132e2017-01-26 09:05:27 -08001175 // Substract overhead from bitrate.
1176 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
elad.alon0fe12162017-01-31 05:48:37 -08001177 uint32_t payload_bitrate_bps = bitrate_bps;
1178 if (send_side_bwe_with_overhead_) {
1179 payload_bitrate_bps -= CalculateOverheadRateBps(
1180 CalculatePacketRate(bitrate_bps,
1181 config_->rtp.max_packet_size +
1182 transport_overhead_bytes_per_packet_),
1183 overhead_bytes_per_packet_ + transport_overhead_bytes_per_packet_,
1184 bitrate_bps);
1185 }
michaelta3328772016-11-29 09:25:03 -08001186
Per69b332d2016-06-02 15:45:42 +02001187 // Get the encoder target rate. It is the estimated network rate -
1188 // protection overhead.
perkj26091b12016-09-01 01:17:40 -07001189 encoder_target_rate_bps_ = protection_bitrate_calculator_.SetTargetRates(
michaelt192132e2017-01-26 09:05:27 -08001190 payload_bitrate_bps, stats_proxy_->GetSendFrameRate(), fraction_loss,
1191 rtt);
1192
elad.alon0fe12162017-01-31 05:48:37 -08001193 uint32_t encoder_overhead_rate_bps =
1194 send_side_bwe_with_overhead_
1195 ? CalculateOverheadRateBps(
1196 CalculatePacketRate(encoder_target_rate_bps_,
1197 config_->rtp.max_packet_size +
1198 transport_overhead_bytes_per_packet_ -
1199 overhead_bytes_per_packet_),
1200 overhead_bytes_per_packet_ +
1201 transport_overhead_bytes_per_packet_,
1202 bitrate_bps - encoder_target_rate_bps_)
1203 : 0;
michaelt192132e2017-01-26 09:05:27 -08001204
1205 // When the field trial "WebRTC-SendSideBwe-WithOverhead" is enabled
1206 // protection_bitrate includes overhead.
1207 uint32_t protection_bitrate =
1208 bitrate_bps - (encoder_target_rate_bps_ + encoder_overhead_rate_bps);
mflodman48a4beb2016-07-01 13:03:59 +02001209
perkj26091b12016-09-01 01:17:40 -07001210 encoder_target_rate_bps_ =
1211 std::min(encoder_max_bitrate_bps_, encoder_target_rate_bps_);
mflodmancc3d4422017-08-03 08:27:51 -07001212 video_stream_encoder_->OnBitrateUpdated(encoder_target_rate_bps_,
1213 fraction_loss, rtt);
perkj26091b12016-09-01 01:17:40 -07001214 stats_proxy_->OnSetEncoderTargetRate(encoder_target_rate_bps_);
perkjf5b2e512016-07-05 08:34:04 -07001215 return protection_bitrate;
mflodman86aabb22016-03-11 15:44:32 +01001216}
1217
palmkviste75f2042016-09-28 06:19:48 -07001218void VideoSendStreamImpl::EnableEncodedFrameRecording(
1219 const std::vector<rtc::PlatformFile>& files,
1220 size_t byte_limit) {
1221 {
1222 rtc::CritScope lock(&ivf_writers_crit_);
1223 for (unsigned int i = 0; i < kMaxSimulcastStreams; ++i) {
1224 if (i < files.size()) {
1225 file_writers_[i] = IvfFileWriter::Wrap(rtc::File(files[i]), byte_limit);
1226 } else {
1227 file_writers_[i].reset();
1228 }
1229 }
1230 }
1231
1232 if (!files.empty()) {
1233 // Make a keyframe appear as early as possible in the logs, to give actually
1234 // decodable output.
mflodmancc3d4422017-08-03 08:27:51 -07001235 video_stream_encoder_->SendKeyFrame();
palmkviste75f2042016-09-28 06:19:48 -07001236 }
1237}
1238
perkj26091b12016-09-01 01:17:40 -07001239int VideoSendStreamImpl::ProtectionRequest(
1240 const FecProtectionParams* delta_params,
1241 const FecProtectionParams* key_params,
1242 uint32_t* sent_video_rate_bps,
1243 uint32_t* sent_nack_rate_bps,
1244 uint32_t* sent_fec_rate_bps) {
1245 RTC_DCHECK_RUN_ON(worker_queue_);
Per83d09102016-04-15 14:59:13 +02001246 *sent_video_rate_bps = 0;
1247 *sent_nack_rate_bps = 0;
1248 *sent_fec_rate_bps = 0;
1249 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
1250 uint32_t not_used = 0;
1251 uint32_t module_video_rate = 0;
1252 uint32_t module_fec_rate = 0;
1253 uint32_t module_nack_rate = 0;
brandtr1743a192016-11-07 03:36:05 -08001254 rtp_rtcp->SetFecParameters(*delta_params, *key_params);
Per83d09102016-04-15 14:59:13 +02001255 rtp_rtcp->BitrateSent(&not_used, &module_video_rate, &module_fec_rate,
1256 &module_nack_rate);
1257 *sent_video_rate_bps += module_video_rate;
1258 *sent_nack_rate_bps += module_nack_rate;
1259 *sent_fec_rate_bps += module_fec_rate;
1260 }
1261 return 0;
1262}
1263
michaelta3328772016-11-29 09:25:03 -08001264void VideoSendStreamImpl::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1265 rtc::CritScope lock(&overhead_bytes_per_packet_crit_);
1266 overhead_bytes_per_packet_ = overhead_bytes_per_packet;
1267}
1268
michaelt79e05882016-11-08 02:50:09 -08001269void VideoSendStreamImpl::SetTransportOverhead(
nisse284542b2017-01-10 08:58:32 -08001270 size_t transport_overhead_bytes_per_packet) {
1271 if (transport_overhead_bytes_per_packet >= static_cast<int>(kPathMTU)) {
1272 LOG(LS_ERROR) << "Transport overhead exceeds size of ethernet frame";
1273 return;
1274 }
1275
michaelta3328772016-11-29 09:25:03 -08001276 transport_overhead_bytes_per_packet_ = transport_overhead_bytes_per_packet;
nisse284542b2017-01-10 08:58:32 -08001277
nisseb8f9a322017-03-27 05:36:15 -07001278 transport_->send_side_cc()->SetTransportOverhead(
1279 transport_overhead_bytes_per_packet_);
nisse284542b2017-01-10 08:58:32 -08001280
1281 size_t rtp_packet_size =
1282 std::min(config_->rtp.max_packet_size,
1283 kPathMTU - transport_overhead_bytes_per_packet_);
1284
michaelta3328772016-11-29 09:25:03 -08001285 for (RtpRtcp* rtp_rtcp : rtp_rtcp_modules_) {
nisse284542b2017-01-10 08:58:32 -08001286 rtp_rtcp->SetMaxRtpPacketSize(rtp_packet_size);
michaelta3328772016-11-29 09:25:03 -08001287 }
michaelt79e05882016-11-08 02:50:09 -08001288}
1289
pbos@webrtc.org29d58392013-05-16 12:08:03 +00001290} // namespace internal
1291} // namespace webrtc