blob: b37a535e4fb9d1ad2416f97cd4d5df3eaaf1a28d [file] [log] [blame]
Niels Möller530ead42018-10-04 14:28:39 +02001/*
2 * Copyright (c) 2012 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 */
10
11#include "audio/channel_send.h"
12
13#include <algorithm>
14#include <map>
15#include <memory>
16#include <string>
17#include <utility>
18#include <vector>
19
20#include "absl/memory/memory.h"
21#include "api/array_view.h"
Niels Möllerdced9f62018-11-19 10:27:07 +010022#include "api/call/transport.h"
Benjamin Wright84583f62018-10-04 14:22:34 -070023#include "api/crypto/frameencryptorinterface.h"
Niels Möller530ead42018-10-04 14:28:39 +020024#include "audio/utility/audio_frame_operations.h"
25#include "call/rtp_transport_controller_send_interface.h"
Niels Möllerdced9f62018-11-19 10:27:07 +010026#include "common_types.h" // NOLINT(build/include)
Niels Möller530ead42018-10-04 14:28:39 +020027#include "logging/rtc_event_log/events/rtc_event_audio_playout.h"
28#include "logging/rtc_event_log/rtc_event_log.h"
29#include "modules/audio_coding/audio_network_adaptor/include/audio_network_adaptor_config.h"
Niels Möllerdced9f62018-11-19 10:27:07 +010030#include "modules/audio_coding/include/audio_coding_module.h"
31#include "modules/audio_processing/rms_level.h"
Niels Möller530ead42018-10-04 14:28:39 +020032#include "modules/pacing/packet_router.h"
33#include "modules/utility/include/process_thread.h"
34#include "rtc_base/checks.h"
35#include "rtc_base/criticalsection.h"
Yves Gerey2e00abc2018-10-05 15:39:24 +020036#include "rtc_base/event.h"
Niels Möller530ead42018-10-04 14:28:39 +020037#include "rtc_base/format_macros.h"
38#include "rtc_base/location.h"
39#include "rtc_base/logging.h"
Niels Möller26815232018-11-16 09:32:40 +010040#include "rtc_base/numerics/safe_conversions.h"
Niels Möllerdced9f62018-11-19 10:27:07 +010041#include "rtc_base/race_checker.h"
Niels Möller530ead42018-10-04 14:28:39 +020042#include "rtc_base/rate_limiter.h"
43#include "rtc_base/task_queue.h"
44#include "rtc_base/thread_checker.h"
45#include "rtc_base/timeutils.h"
46#include "system_wrappers/include/field_trial.h"
47#include "system_wrappers/include/metrics.h"
48
49namespace webrtc {
50namespace voe {
51
52namespace {
53
54constexpr int64_t kMaxRetransmissionWindowMs = 1000;
55constexpr int64_t kMinRetransmissionWindowMs = 30;
56
Niels Möller7d76a312018-10-26 12:57:07 +020057MediaTransportEncodedAudioFrame::FrameType
58MediaTransportFrameTypeForWebrtcFrameType(webrtc::FrameType frame_type) {
59 switch (frame_type) {
60 case kAudioFrameSpeech:
61 return MediaTransportEncodedAudioFrame::FrameType::kSpeech;
62 break;
63
64 case kAudioFrameCN:
65 return MediaTransportEncodedAudioFrame::FrameType::
66 kDiscontinuousTransmission;
67 break;
68
69 default:
70 RTC_CHECK(false) << "Unexpected frame type=" << frame_type;
71 break;
72 }
73}
74
Niels Möllerdced9f62018-11-19 10:27:07 +010075class RtpPacketSenderProxy;
76class TransportFeedbackProxy;
77class TransportSequenceNumberProxy;
78class VoERtcpObserver;
79
Niels Möllerdced9f62018-11-19 10:27:07 +010080class ChannelSend
81 : public ChannelSendInterface,
82 public Transport,
83 public OverheadObserver,
84 public AudioPacketizationCallback, // receive encoded packets from the
85 // ACM
86 public TargetTransferRateObserver {
87 public:
88 // TODO(nisse): Make OnUplinkPacketLossRate public, and delete friend
89 // declaration.
90 friend class VoERtcpObserver;
91
92 ChannelSend(rtc::TaskQueue* encoder_queue,
93 ProcessThread* module_process_thread,
94 MediaTransportInterface* media_transport,
95 RtcpRttStats* rtcp_rtt_stats,
96 RtcEventLog* rtc_event_log,
97 FrameEncryptorInterface* frame_encryptor,
98 const webrtc::CryptoOptions& crypto_options,
99 bool extmap_allow_mixed,
100 int rtcp_report_interval_ms);
101
102 ~ChannelSend() override;
103
104 // Send using this encoder, with this payload type.
105 bool SetEncoder(int payload_type,
106 std::unique_ptr<AudioEncoder> encoder) override;
107 void ModifyEncoder(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
108 modifier) override;
109
110 // API methods
Niels Möllerdced9f62018-11-19 10:27:07 +0100111 void StartSend() override;
112 void StopSend() override;
113
114 // Codecs
115 void SetBitrate(int bitrate_bps, int64_t probing_interval_ms) override;
116 int GetBitrate() const override;
117
118 // Network
119 void RegisterTransport(Transport* transport) override;
Niels Möllerdced9f62018-11-19 10:27:07 +0100120 bool ReceivedRTCPPacket(const uint8_t* data, size_t length) override;
121
122 // Muting, Volume and Level.
123 void SetInputMute(bool enable) override;
124
125 // Stats.
126 ANAStats GetANAStatistics() const override;
127
128 // Used by AudioSendStream.
129 RtpRtcp* GetRtpRtcp() const override;
130
131 // DTMF.
132 bool SendTelephoneEventOutband(int event, int duration_ms) override;
133 bool SetSendTelephoneEventPayloadType(int payload_type,
134 int payload_frequency) override;
135
136 // RTP+RTCP
137 void SetLocalSSRC(uint32_t ssrc) override;
Niels Möllerdced9f62018-11-19 10:27:07 +0100138 void SetMid(const std::string& mid, int extension_id) override;
139 void SetExtmapAllowMixed(bool extmap_allow_mixed) override;
140 void SetSendAudioLevelIndicationStatus(bool enable, int id) override;
141 void EnableSendTransportSequenceNumber(int id) override;
142
143 void RegisterSenderCongestionControlObjects(
144 RtpTransportControllerSendInterface* transport,
145 RtcpBandwidthObserver* bandwidth_observer) override;
146 void ResetSenderCongestionControlObjects() override;
147 void SetRTCP_CNAME(absl::string_view c_name) override;
148 std::vector<ReportBlock> GetRemoteRTCPReportBlocks() const override;
149 CallSendStatistics GetRTCPStatistics() const override;
150 void SetNACKStatus(bool enable, int max_packets) override;
151
152 // ProcessAndEncodeAudio() posts a task on the shared encoder task queue,
153 // which in turn calls (on the queue) ProcessAndEncodeAudioOnTaskQueue() where
154 // the actual processing of the audio takes place. The processing mainly
155 // consists of encoding and preparing the result for sending by adding it to a
156 // send queue.
157 // The main reason for using a task queue here is to release the native,
158 // OS-specific, audio capture thread as soon as possible to ensure that it
159 // can go back to sleep and be prepared to deliver an new captured audio
160 // packet.
161 void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame) override;
162
163 void SetTransportOverhead(size_t transport_overhead_per_packet) override;
164
165 // The existence of this function alongside OnUplinkPacketLossRate is
166 // a compromise. We want the encoder to be agnostic of the PLR source, but
167 // we also don't want it to receive conflicting information from TWCC and
168 // from RTCP-XR.
169 void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) override;
170
171 void OnRecoverableUplinkPacketLossRate(
172 float recoverable_packet_loss_rate) override;
173
174 int64_t GetRTT() const override;
175
176 // E2EE Custom Audio Frame Encryption
177 void SetFrameEncryptor(
178 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) override;
179
180 private:
181 class ProcessAndEncodeAudioTask;
182
183 // From AudioPacketizationCallback in the ACM
184 int32_t SendData(FrameType frameType,
185 uint8_t payloadType,
186 uint32_t timeStamp,
187 const uint8_t* payloadData,
188 size_t payloadSize,
189 const RTPFragmentationHeader* fragmentation) override;
190
191 // From Transport (called by the RTP/RTCP module)
192 bool SendRtp(const uint8_t* data,
193 size_t len,
194 const PacketOptions& packet_options) override;
195 bool SendRtcp(const uint8_t* data, size_t len) override;
196
Niels Möllerdced9f62018-11-19 10:27:07 +0100197 // From OverheadObserver in the RTP/RTCP module
198 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
199
200 void OnUplinkPacketLossRate(float packet_loss_rate);
201 bool InputMute() const;
202
203 int ResendPackets(const uint16_t* sequence_numbers, int length);
204
205 int SetSendRtpHeaderExtension(bool enable, RTPExtensionType type, int id);
206
207 void UpdateOverheadForEncoder()
208 RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
209
210 int GetRtpTimestampRateHz() const;
211
212 int32_t SendRtpAudio(FrameType frameType,
213 uint8_t payloadType,
214 uint32_t timeStamp,
215 rtc::ArrayView<const uint8_t> payload,
216 const RTPFragmentationHeader* fragmentation);
217
218 int32_t SendMediaTransportAudio(FrameType frameType,
219 uint8_t payloadType,
220 uint32_t timeStamp,
221 rtc::ArrayView<const uint8_t> payload,
222 const RTPFragmentationHeader* fragmentation);
223
224 // Return media transport or nullptr if using RTP.
225 MediaTransportInterface* media_transport() { return media_transport_; }
226
227 // Called on the encoder task queue when a new input audio frame is ready
228 // for encoding.
229 void ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input);
230
231 void OnReceivedRtt(int64_t rtt_ms);
232
233 void OnTargetTransferRate(TargetTransferRate) override;
234
235 // Thread checkers document and lock usage of some methods on voe::Channel to
236 // specific threads we know about. The goal is to eventually split up
237 // voe::Channel into parts with single-threaded semantics, and thereby reduce
238 // the need for locks.
239 rtc::ThreadChecker worker_thread_checker_;
240 rtc::ThreadChecker module_process_thread_checker_;
241 // Methods accessed from audio and video threads are checked for sequential-
242 // only access. We don't necessarily own and control these threads, so thread
243 // checkers cannot be used. E.g. Chromium may transfer "ownership" from one
244 // audio thread to another, but access is still sequential.
245 rtc::RaceChecker audio_thread_race_checker_;
246
247 rtc::CriticalSection _callbackCritSect;
248 rtc::CriticalSection volume_settings_critsect_;
249
Niels Möller26e88b02018-11-19 15:08:13 +0100250 bool sending_ RTC_GUARDED_BY(&worker_thread_checker_) = false;
Niels Möllerdced9f62018-11-19 10:27:07 +0100251
252 RtcEventLog* const event_log_;
253
254 std::unique_ptr<RtpRtcp> _rtpRtcpModule;
255
256 std::unique_ptr<AudioCodingModule> audio_coding_;
257 uint32_t _timeStamp RTC_GUARDED_BY(encoder_queue_);
258
259 uint16_t send_sequence_number_;
260
261 // uses
Niels Möller985a1f32018-11-19 16:08:42 +0100262 ProcessThread* const _moduleProcessThreadPtr;
Niels Möllerdced9f62018-11-19 10:27:07 +0100263 Transport* _transportPtr; // WebRtc socket or external transport
264 RmsLevel rms_level_ RTC_GUARDED_BY(encoder_queue_);
265 bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_);
266 bool previous_frame_muted_ RTC_GUARDED_BY(encoder_queue_);
267 // VoeRTP_RTCP
268 // TODO(henrika): can today be accessed on the main thread and on the
269 // task queue; hence potential race.
270 bool _includeAudioLevelIndication;
271 size_t transport_overhead_per_packet_
272 RTC_GUARDED_BY(overhead_per_packet_lock_);
273 size_t rtp_overhead_per_packet_ RTC_GUARDED_BY(overhead_per_packet_lock_);
274 rtc::CriticalSection overhead_per_packet_lock_;
275 // RtcpBandwidthObserver
Niels Möller985a1f32018-11-19 16:08:42 +0100276 const std::unique_ptr<VoERtcpObserver> rtcp_observer_;
Niels Möllerdced9f62018-11-19 10:27:07 +0100277
Niels Möller985a1f32018-11-19 16:08:42 +0100278 PacketRouter* packet_router_ RTC_GUARDED_BY(&worker_thread_checker_) =
279 nullptr;
280 const std::unique_ptr<TransportFeedbackProxy> feedback_observer_proxy_;
281 const std::unique_ptr<TransportSequenceNumberProxy> seq_num_allocator_proxy_;
282 const std::unique_ptr<RtpPacketSenderProxy> rtp_packet_sender_proxy_;
283 const std::unique_ptr<RateLimiter> retransmission_rate_limiter_;
Niels Möllerdced9f62018-11-19 10:27:07 +0100284
285 rtc::ThreadChecker construction_thread_;
286
287 const bool use_twcc_plr_for_ana_;
288
289 rtc::CriticalSection encoder_queue_lock_;
290 bool encoder_queue_is_active_ RTC_GUARDED_BY(encoder_queue_lock_) = false;
Niels Möller985a1f32018-11-19 16:08:42 +0100291 rtc::TaskQueue* const encoder_queue_ = nullptr;
Niels Möllerdced9f62018-11-19 10:27:07 +0100292
293 MediaTransportInterface* const media_transport_;
294 int media_transport_sequence_number_ RTC_GUARDED_BY(encoder_queue_) = 0;
295
296 rtc::CriticalSection media_transport_lock_;
297 // Currently set by SetLocalSSRC.
298 uint64_t media_transport_channel_id_ RTC_GUARDED_BY(&media_transport_lock_) =
299 0;
300 // Cache payload type and sampling frequency from most recent call to
301 // SetEncoder. Needed to set MediaTransportEncodedAudioFrame metadata, and
302 // invalidate on encoder change.
303 int media_transport_payload_type_ RTC_GUARDED_BY(&media_transport_lock_);
304 int media_transport_sampling_frequency_
305 RTC_GUARDED_BY(&media_transport_lock_);
306
307 // E2EE Audio Frame Encryption
308 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor_;
309 // E2EE Frame Encryption Options
Niels Möller985a1f32018-11-19 16:08:42 +0100310 const webrtc::CryptoOptions crypto_options_;
Niels Möllerdced9f62018-11-19 10:27:07 +0100311
312 rtc::CriticalSection bitrate_crit_section_;
313 int configured_bitrate_bps_ RTC_GUARDED_BY(bitrate_crit_section_) = 0;
314};
Niels Möller530ead42018-10-04 14:28:39 +0200315
316const int kTelephoneEventAttenuationdB = 10;
317
318class TransportFeedbackProxy : public TransportFeedbackObserver {
319 public:
320 TransportFeedbackProxy() : feedback_observer_(nullptr) {
321 pacer_thread_.DetachFromThread();
322 network_thread_.DetachFromThread();
323 }
324
325 void SetTransportFeedbackObserver(
326 TransportFeedbackObserver* feedback_observer) {
327 RTC_DCHECK(thread_checker_.CalledOnValidThread());
328 rtc::CritScope lock(&crit_);
329 feedback_observer_ = feedback_observer;
330 }
331
332 // Implements TransportFeedbackObserver.
333 void AddPacket(uint32_t ssrc,
334 uint16_t sequence_number,
335 size_t length,
336 const PacedPacketInfo& pacing_info) override {
337 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
338 rtc::CritScope lock(&crit_);
339 if (feedback_observer_)
340 feedback_observer_->AddPacket(ssrc, sequence_number, length, pacing_info);
341 }
342
343 void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override {
344 RTC_DCHECK(network_thread_.CalledOnValidThread());
345 rtc::CritScope lock(&crit_);
346 if (feedback_observer_)
347 feedback_observer_->OnTransportFeedback(feedback);
348 }
349
350 private:
351 rtc::CriticalSection crit_;
352 rtc::ThreadChecker thread_checker_;
353 rtc::ThreadChecker pacer_thread_;
354 rtc::ThreadChecker network_thread_;
355 TransportFeedbackObserver* feedback_observer_ RTC_GUARDED_BY(&crit_);
356};
357
358class TransportSequenceNumberProxy : public TransportSequenceNumberAllocator {
359 public:
360 TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) {
361 pacer_thread_.DetachFromThread();
362 }
363
364 void SetSequenceNumberAllocator(
365 TransportSequenceNumberAllocator* seq_num_allocator) {
366 RTC_DCHECK(thread_checker_.CalledOnValidThread());
367 rtc::CritScope lock(&crit_);
368 seq_num_allocator_ = seq_num_allocator;
369 }
370
371 // Implements TransportSequenceNumberAllocator.
372 uint16_t AllocateSequenceNumber() override {
373 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
374 rtc::CritScope lock(&crit_);
375 if (!seq_num_allocator_)
376 return 0;
377 return seq_num_allocator_->AllocateSequenceNumber();
378 }
379
380 private:
381 rtc::CriticalSection crit_;
382 rtc::ThreadChecker thread_checker_;
383 rtc::ThreadChecker pacer_thread_;
384 TransportSequenceNumberAllocator* seq_num_allocator_ RTC_GUARDED_BY(&crit_);
385};
386
387class RtpPacketSenderProxy : public RtpPacketSender {
388 public:
389 RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) {}
390
391 void SetPacketSender(RtpPacketSender* rtp_packet_sender) {
392 RTC_DCHECK(thread_checker_.CalledOnValidThread());
393 rtc::CritScope lock(&crit_);
394 rtp_packet_sender_ = rtp_packet_sender;
395 }
396
397 // Implements RtpPacketSender.
398 void InsertPacket(Priority priority,
399 uint32_t ssrc,
400 uint16_t sequence_number,
401 int64_t capture_time_ms,
402 size_t bytes,
403 bool retransmission) override {
404 rtc::CritScope lock(&crit_);
405 if (rtp_packet_sender_) {
406 rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number,
407 capture_time_ms, bytes, retransmission);
408 }
409 }
410
411 void SetAccountForAudioPackets(bool account_for_audio) override {
412 RTC_NOTREACHED();
413 }
414
415 private:
416 rtc::ThreadChecker thread_checker_;
417 rtc::CriticalSection crit_;
418 RtpPacketSender* rtp_packet_sender_ RTC_GUARDED_BY(&crit_);
419};
420
421class VoERtcpObserver : public RtcpBandwidthObserver {
422 public:
423 explicit VoERtcpObserver(ChannelSend* owner)
424 : owner_(owner), bandwidth_observer_(nullptr) {}
425 virtual ~VoERtcpObserver() {}
426
427 void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
428 rtc::CritScope lock(&crit_);
429 bandwidth_observer_ = bandwidth_observer;
430 }
431
432 void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
433 rtc::CritScope lock(&crit_);
434 if (bandwidth_observer_) {
435 bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
436 }
437 }
438
439 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
440 int64_t rtt,
441 int64_t now_ms) override {
442 {
443 rtc::CritScope lock(&crit_);
444 if (bandwidth_observer_) {
445 bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, rtt,
446 now_ms);
447 }
448 }
449 // TODO(mflodman): Do we need to aggregate reports here or can we jut send
450 // what we get? I.e. do we ever get multiple reports bundled into one RTCP
451 // report for VoiceEngine?
452 if (report_blocks.empty())
453 return;
454
455 int fraction_lost_aggregate = 0;
456 int total_number_of_packets = 0;
457
458 // If receiving multiple report blocks, calculate the weighted average based
459 // on the number of packets a report refers to.
460 for (ReportBlockList::const_iterator block_it = report_blocks.begin();
461 block_it != report_blocks.end(); ++block_it) {
462 // Find the previous extended high sequence number for this remote SSRC,
463 // to calculate the number of RTP packets this report refers to. Ignore if
464 // we haven't seen this SSRC before.
465 std::map<uint32_t, uint32_t>::iterator seq_num_it =
466 extended_max_sequence_number_.find(block_it->source_ssrc);
467 int number_of_packets = 0;
468 if (seq_num_it != extended_max_sequence_number_.end()) {
469 number_of_packets =
470 block_it->extended_highest_sequence_number - seq_num_it->second;
471 }
472 fraction_lost_aggregate += number_of_packets * block_it->fraction_lost;
473 total_number_of_packets += number_of_packets;
474
475 extended_max_sequence_number_[block_it->source_ssrc] =
476 block_it->extended_highest_sequence_number;
477 }
478 int weighted_fraction_lost = 0;
479 if (total_number_of_packets > 0) {
480 weighted_fraction_lost =
481 (fraction_lost_aggregate + total_number_of_packets / 2) /
482 total_number_of_packets;
483 }
484 owner_->OnUplinkPacketLossRate(weighted_fraction_lost / 255.0f);
485 }
486
487 private:
488 ChannelSend* owner_;
489 // Maps remote side ssrc to extended highest sequence number received.
490 std::map<uint32_t, uint32_t> extended_max_sequence_number_;
491 rtc::CriticalSection crit_;
492 RtcpBandwidthObserver* bandwidth_observer_ RTC_GUARDED_BY(crit_);
493};
494
495class ChannelSend::ProcessAndEncodeAudioTask : public rtc::QueuedTask {
496 public:
497 ProcessAndEncodeAudioTask(std::unique_ptr<AudioFrame> audio_frame,
498 ChannelSend* channel)
499 : audio_frame_(std::move(audio_frame)), channel_(channel) {
500 RTC_DCHECK(channel_);
501 }
502
503 private:
504 bool Run() override {
505 RTC_DCHECK_RUN_ON(channel_->encoder_queue_);
506 channel_->ProcessAndEncodeAudioOnTaskQueue(audio_frame_.get());
507 return true;
508 }
509
510 std::unique_ptr<AudioFrame> audio_frame_;
511 ChannelSend* const channel_;
512};
513
514int32_t ChannelSend::SendData(FrameType frameType,
515 uint8_t payloadType,
516 uint32_t timeStamp,
517 const uint8_t* payloadData,
518 size_t payloadSize,
519 const RTPFragmentationHeader* fragmentation) {
520 RTC_DCHECK_RUN_ON(encoder_queue_);
Niels Möller7d76a312018-10-26 12:57:07 +0200521 rtc::ArrayView<const uint8_t> payload(payloadData, payloadSize);
522
523 if (media_transport() != nullptr) {
524 return SendMediaTransportAudio(frameType, payloadType, timeStamp, payload,
525 fragmentation);
526 } else {
527 return SendRtpAudio(frameType, payloadType, timeStamp, payload,
528 fragmentation);
529 }
530}
531
532int32_t ChannelSend::SendRtpAudio(FrameType frameType,
533 uint8_t payloadType,
534 uint32_t timeStamp,
535 rtc::ArrayView<const uint8_t> payload,
536 const RTPFragmentationHeader* fragmentation) {
537 RTC_DCHECK_RUN_ON(encoder_queue_);
Niels Möller530ead42018-10-04 14:28:39 +0200538 if (_includeAudioLevelIndication) {
539 // Store current audio level in the RTP/RTCP module.
540 // The level will be used in combination with voice-activity state
541 // (frameType) to add an RTP header extension
542 _rtpRtcpModule->SetAudioLevel(rms_level_.Average());
543 }
544
Benjamin Wright84583f62018-10-04 14:22:34 -0700545 // E2EE Custom Audio Frame Encryption (This is optional).
546 // Keep this buffer around for the lifetime of the send call.
547 rtc::Buffer encrypted_audio_payload;
548 if (frame_encryptor_ != nullptr) {
549 // TODO(benwright@webrtc.org) - Allocate enough to always encrypt inline.
550 // Allocate a buffer to hold the maximum possible encrypted payload.
551 size_t max_ciphertext_size = frame_encryptor_->GetMaxCiphertextByteSize(
Niels Möller7d76a312018-10-26 12:57:07 +0200552 cricket::MEDIA_TYPE_AUDIO, payload.size());
Benjamin Wright84583f62018-10-04 14:22:34 -0700553 encrypted_audio_payload.SetSize(max_ciphertext_size);
554
555 // Encrypt the audio payload into the buffer.
556 size_t bytes_written = 0;
557 int encrypt_status = frame_encryptor_->Encrypt(
558 cricket::MEDIA_TYPE_AUDIO, _rtpRtcpModule->SSRC(),
Niels Möller7d76a312018-10-26 12:57:07 +0200559 /*additional_data=*/nullptr, payload, encrypted_audio_payload,
560 &bytes_written);
Benjamin Wright84583f62018-10-04 14:22:34 -0700561 if (encrypt_status != 0) {
562 RTC_DLOG(LS_ERROR) << "Channel::SendData() failed encrypt audio payload: "
563 << encrypt_status;
564 return -1;
565 }
566 // Resize the buffer to the exact number of bytes actually used.
567 encrypted_audio_payload.SetSize(bytes_written);
568 // Rewrite the payloadData and size to the new encrypted payload.
Niels Möller7d76a312018-10-26 12:57:07 +0200569 payload = encrypted_audio_payload;
Benjamin Wrightbfb444c2018-10-15 10:20:24 -0700570 } else if (crypto_options_.sframe.require_frame_encryption) {
571 RTC_DLOG(LS_ERROR) << "Channel::SendData() failed sending audio payload: "
572 << "A frame encryptor is required but one is not set.";
573 return -1;
Benjamin Wright84583f62018-10-04 14:22:34 -0700574 }
575
Niels Möller530ead42018-10-04 14:28:39 +0200576 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
577 // packetization.
578 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
Niels Möller7d76a312018-10-26 12:57:07 +0200579 if (!_rtpRtcpModule->SendOutgoingData((FrameType&)frameType, payloadType,
580 timeStamp,
581 // Leaving the time when this frame was
582 // received from the capture device as
583 // undefined for voice for now.
584 -1, payload.data(), payload.size(),
585 fragmentation, nullptr, nullptr)) {
Niels Möller530ead42018-10-04 14:28:39 +0200586 RTC_DLOG(LS_ERROR)
587 << "ChannelSend::SendData() failed to send data to RTP/RTCP module";
588 return -1;
589 }
590
591 return 0;
592}
593
Niels Möller7d76a312018-10-26 12:57:07 +0200594int32_t ChannelSend::SendMediaTransportAudio(
595 FrameType frameType,
596 uint8_t payloadType,
597 uint32_t timeStamp,
598 rtc::ArrayView<const uint8_t> payload,
599 const RTPFragmentationHeader* fragmentation) {
600 RTC_DCHECK_RUN_ON(encoder_queue_);
601 // TODO(nisse): Use null _transportPtr for MediaTransport.
602 // RTC_DCHECK(_transportPtr == nullptr);
603 uint64_t channel_id;
604 int sampling_rate_hz;
605 {
606 rtc::CritScope cs(&media_transport_lock_);
607 if (media_transport_payload_type_ != payloadType) {
608 // Payload type is being changed, media_transport_sampling_frequency_,
609 // no longer current.
610 return -1;
611 }
612 sampling_rate_hz = media_transport_sampling_frequency_;
613 channel_id = media_transport_channel_id_;
614 }
615 const MediaTransportEncodedAudioFrame frame(
616 /*sampling_rate_hz=*/sampling_rate_hz,
617
618 // TODO(nisse): Timestamp and sample index are the same for all supported
619 // audio codecs except G722. Refactor audio coding module to only use
620 // sample index, and leave translation to RTP time, when needed, for
621 // RTP-specific code.
622 /*starting_sample_index=*/timeStamp,
623
624 // Sample count isn't conveniently available from the AudioCodingModule,
625 // and needs some refactoring to wire up in a good way. For now, left as
626 // zero.
627 /*sample_count=*/0,
628
629 /*sequence_number=*/media_transport_sequence_number_,
630 MediaTransportFrameTypeForWebrtcFrameType(frameType), payloadType,
631 std::vector<uint8_t>(payload.begin(), payload.end()));
632
633 // TODO(nisse): Introduce a MediaTransportSender object bound to a specific
634 // channel id.
635 RTCError rtc_error =
636 media_transport()->SendAudioFrame(channel_id, std::move(frame));
637
638 if (!rtc_error.ok()) {
639 RTC_LOG(LS_ERROR) << "Failed to send frame, rtc_error="
640 << ToString(rtc_error.type()) << ", "
641 << rtc_error.message();
642 return -1;
643 }
644
645 ++media_transport_sequence_number_;
646
647 return 0;
648}
649
Niels Möller530ead42018-10-04 14:28:39 +0200650bool ChannelSend::SendRtp(const uint8_t* data,
651 size_t len,
652 const PacketOptions& options) {
Niels Möller7d76a312018-10-26 12:57:07 +0200653 // We should not be sending RTP packets if media transport is available.
654 RTC_CHECK(!media_transport());
655
Niels Möller530ead42018-10-04 14:28:39 +0200656 rtc::CritScope cs(&_callbackCritSect);
657
658 if (_transportPtr == NULL) {
659 RTC_DLOG(LS_ERROR)
660 << "ChannelSend::SendPacket() failed to send RTP packet due to"
661 << " invalid transport object";
662 return false;
663 }
664
665 if (!_transportPtr->SendRtp(data, len, options)) {
666 RTC_DLOG(LS_ERROR) << "ChannelSend::SendPacket() RTP transmission failed";
667 return false;
668 }
669 return true;
670}
671
672bool ChannelSend::SendRtcp(const uint8_t* data, size_t len) {
673 rtc::CritScope cs(&_callbackCritSect);
674 if (_transportPtr == NULL) {
675 RTC_DLOG(LS_ERROR)
676 << "ChannelSend::SendRtcp() failed to send RTCP packet due to"
677 << " invalid transport object";
678 return false;
679 }
680
681 int n = _transportPtr->SendRtcp(data, len);
682 if (n < 0) {
683 RTC_DLOG(LS_ERROR) << "ChannelSend::SendRtcp() transmission failed";
684 return false;
685 }
686 return true;
687}
688
Niels Möller530ead42018-10-04 14:28:39 +0200689ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue,
690 ProcessThread* module_process_thread,
Niels Möller7d76a312018-10-26 12:57:07 +0200691 MediaTransportInterface* media_transport,
Niels Möller530ead42018-10-04 14:28:39 +0200692 RtcpRttStats* rtcp_rtt_stats,
Benjamin Wright84583f62018-10-04 14:22:34 -0700693 RtcEventLog* rtc_event_log,
Benjamin Wrightbfb444c2018-10-15 10:20:24 -0700694 FrameEncryptorInterface* frame_encryptor,
Johannes Kron9190b822018-10-29 11:22:05 +0100695 const webrtc::CryptoOptions& crypto_options,
Jiawei Ou55718122018-11-09 13:17:39 -0800696 bool extmap_allow_mixed,
697 int rtcp_report_interval_ms)
Niels Möller530ead42018-10-04 14:28:39 +0200698 : event_log_(rtc_event_log),
699 _timeStamp(0), // This is just an offset, RTP module will add it's own
700 // random offset
701 send_sequence_number_(0),
702 _moduleProcessThreadPtr(module_process_thread),
703 _transportPtr(NULL),
704 input_mute_(false),
705 previous_frame_muted_(false),
706 _includeAudioLevelIndication(false),
707 transport_overhead_per_packet_(0),
708 rtp_overhead_per_packet_(0),
709 rtcp_observer_(new VoERtcpObserver(this)),
710 feedback_observer_proxy_(new TransportFeedbackProxy()),
711 seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
712 rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
713 retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
714 kMaxRetransmissionWindowMs)),
715 use_twcc_plr_for_ana_(
716 webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"),
Benjamin Wright84583f62018-10-04 14:22:34 -0700717 encoder_queue_(encoder_queue),
Niels Möller7d76a312018-10-26 12:57:07 +0200718 media_transport_(media_transport),
Benjamin Wrightbfb444c2018-10-15 10:20:24 -0700719 frame_encryptor_(frame_encryptor),
720 crypto_options_(crypto_options) {
Niels Möller530ead42018-10-04 14:28:39 +0200721 RTC_DCHECK(module_process_thread);
722 RTC_DCHECK(encoder_queue);
Niels Möllerdced9f62018-11-19 10:27:07 +0100723 module_process_thread_checker_.DetachFromThread();
724
Niels Möller530ead42018-10-04 14:28:39 +0200725 audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config()));
726
727 RtpRtcp::Configuration configuration;
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800728
729 // We gradually remove codepaths that depend on RTP when using media
730 // transport. All of this logic should be moved to the future
731 // RTPMediaTransport. In this case it means that overhead and bandwidth
732 // observers should not be called when using media transport.
733 if (!media_transport_) {
734 configuration.overhead_observer = this;
735 configuration.bandwidth_callback = rtcp_observer_.get();
736 configuration.transport_feedback_callback = feedback_observer_proxy_.get();
737 }
738
Niels Möller530ead42018-10-04 14:28:39 +0200739 configuration.audio = true;
740 configuration.outgoing_transport = this;
Niels Möller530ead42018-10-04 14:28:39 +0200741
742 configuration.paced_sender = rtp_packet_sender_proxy_.get();
743 configuration.transport_sequence_number_allocator =
744 seq_num_allocator_proxy_.get();
Niels Möller530ead42018-10-04 14:28:39 +0200745
746 configuration.event_log = event_log_;
747 configuration.rtt_stats = rtcp_rtt_stats;
748 configuration.retransmission_rate_limiter =
749 retransmission_rate_limiter_.get();
Johannes Kron9190b822018-10-29 11:22:05 +0100750 configuration.extmap_allow_mixed = extmap_allow_mixed;
Jiawei Ou55718122018-11-09 13:17:39 -0800751 configuration.rtcp_interval_config.audio_interval_ms =
752 rtcp_report_interval_ms;
Niels Möller530ead42018-10-04 14:28:39 +0200753
754 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
755 _rtpRtcpModule->SetSendingMediaStatus(false);
Niels Möller530ead42018-10-04 14:28:39 +0200756
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800757 // We want to invoke the 'TargetRateObserver' and |OnOverheadChanged|
758 // callbacks after the audio_coding_ is fully initialized.
759 if (media_transport_) {
760 RTC_DLOG(LS_INFO) << "Setting media_transport_ rate observers.";
761 media_transport_->AddTargetTransferRateObserver(this);
762 OnOverheadChanged(media_transport_->GetAudioPacketOverhead());
763 } else {
764 RTC_DLOG(LS_INFO) << "Not setting media_transport_ rate observers.";
765 }
766
Niels Möller530ead42018-10-04 14:28:39 +0200767 _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get(), RTC_FROM_HERE);
768
Niels Möller530ead42018-10-04 14:28:39 +0200769 // Ensure that RTCP is enabled by default for the created channel.
770 // Note that, the module will keep generating RTCP until it is explicitly
771 // disabled by the user.
772 // After StopListen (when no sockets exists), RTCP packets will no longer
773 // be transmitted since the Transport object will then be invalid.
774 // RTCP is enabled by default.
775 _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
776
Fredrik Solenbergeb134842018-11-19 14:13:15 +0100777 int error = audio_coding_->RegisterTransportCallback(this);
Niels Möller530ead42018-10-04 14:28:39 +0200778 RTC_DCHECK_EQ(0, error);
779}
780
Fredrik Solenberg645a3af2018-11-16 12:51:15 +0100781ChannelSend::~ChannelSend() {
Niels Möller530ead42018-10-04 14:28:39 +0200782 RTC_DCHECK(construction_thread_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +0200783
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800784 if (media_transport_) {
785 media_transport_->RemoveTargetTransferRateObserver(this);
786 }
787
Niels Möller530ead42018-10-04 14:28:39 +0200788 StopSend();
789
Niels Möller530ead42018-10-04 14:28:39 +0200790 int error = audio_coding_->RegisterTransportCallback(NULL);
791 RTC_DCHECK_EQ(0, error);
792
Niels Möller530ead42018-10-04 14:28:39 +0200793 if (_moduleProcessThreadPtr)
794 _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
Niels Möller530ead42018-10-04 14:28:39 +0200795}
796
Niels Möller26815232018-11-16 09:32:40 +0100797void ChannelSend::StartSend() {
Niels Möller26e88b02018-11-19 15:08:13 +0100798 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Fredrik Solenbergeb134842018-11-19 14:13:15 +0100799 RTC_DCHECK(!sending_);
800 sending_ = true;
Niels Möller530ead42018-10-04 14:28:39 +0200801
802 // Resume the previous sequence number which was reset by StopSend(). This
803 // needs to be done before |sending| is set to true on the RTP/RTCP module.
804 if (send_sequence_number_) {
805 _rtpRtcpModule->SetSequenceNumber(send_sequence_number_);
806 }
807 _rtpRtcpModule->SetSendingMediaStatus(true);
Niels Möller26815232018-11-16 09:32:40 +0100808 int ret = _rtpRtcpModule->SetSendingStatus(true);
809 RTC_DCHECK_EQ(0, ret);
Niels Möller530ead42018-10-04 14:28:39 +0200810 {
811 // It is now OK to start posting tasks to the encoder task queue.
812 rtc::CritScope cs(&encoder_queue_lock_);
813 encoder_queue_is_active_ = true;
814 }
Niels Möller530ead42018-10-04 14:28:39 +0200815}
816
817void ChannelSend::StopSend() {
Niels Möller26e88b02018-11-19 15:08:13 +0100818 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Fredrik Solenbergeb134842018-11-19 14:13:15 +0100819 if (!sending_) {
Niels Möller530ead42018-10-04 14:28:39 +0200820 return;
821 }
Fredrik Solenbergeb134842018-11-19 14:13:15 +0100822 sending_ = false;
Niels Möller530ead42018-10-04 14:28:39 +0200823
824 // Post a task to the encoder thread which sets an event when the task is
825 // executed. We know that no more encoding tasks will be added to the task
826 // queue for this channel since sending is now deactivated. It means that,
827 // if we wait for the event to bet set, we know that no more pending tasks
828 // exists and it is therfore guaranteed that the task queue will never try
829 // to acccess and invalid channel object.
830 RTC_DCHECK(encoder_queue_);
831
Niels Möllerc572ff32018-11-07 08:43:50 +0100832 rtc::Event flush;
Niels Möller530ead42018-10-04 14:28:39 +0200833 {
834 // Clear |encoder_queue_is_active_| under lock to prevent any other tasks
835 // than this final "flush task" to be posted on the queue.
836 rtc::CritScope cs(&encoder_queue_lock_);
837 encoder_queue_is_active_ = false;
838 encoder_queue_->PostTask([&flush]() { flush.Set(); });
839 }
840 flush.Wait(rtc::Event::kForever);
841
842 // Store the sequence number to be able to pick up the same sequence for
843 // the next StartSend(). This is needed for restarting device, otherwise
844 // it might cause libSRTP to complain about packets being replayed.
845 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
846 // CL is landed. See issue
847 // https://code.google.com/p/webrtc/issues/detail?id=2111 .
848 send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
849
850 // Reset sending SSRC and sequence number and triggers direct transmission
851 // of RTCP BYE
852 if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
853 RTC_DLOG(LS_ERROR) << "StartSend() RTP/RTCP failed to stop sending";
854 }
855 _rtpRtcpModule->SetSendingMediaStatus(false);
856}
857
858bool ChannelSend::SetEncoder(int payload_type,
859 std::unique_ptr<AudioEncoder> encoder) {
Niels Möller26e88b02018-11-19 15:08:13 +0100860 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +0200861 RTC_DCHECK_GE(payload_type, 0);
862 RTC_DCHECK_LE(payload_type, 127);
863 // TODO(ossu): Make CodecInsts up, for now: one for the RTP/RTCP module and
864 // one for for us to keep track of sample rate and number of channels, etc.
865
866 // The RTP/RTCP module needs to know the RTP timestamp rate (i.e. clockrate)
867 // as well as some other things, so we collect this info and send it along.
868 CodecInst rtp_codec;
869 rtp_codec.pltype = payload_type;
870 strncpy(rtp_codec.plname, "audio", sizeof(rtp_codec.plname));
871 rtp_codec.plname[sizeof(rtp_codec.plname) - 1] = 0;
872 // Seems unclear if it should be clock rate or sample rate. CodecInst
873 // supposedly carries the sample rate, but only clock rate seems sensible to
874 // send to the RTP/RTCP module.
875 rtp_codec.plfreq = encoder->RtpTimestampRateHz();
876 rtp_codec.pacsize = rtc::CheckedDivExact(
877 static_cast<int>(encoder->Max10MsFramesInAPacket() * rtp_codec.plfreq),
878 100);
879 rtp_codec.channels = encoder->NumChannels();
880 rtp_codec.rate = 0;
881
882 if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
883 _rtpRtcpModule->DeRegisterSendPayload(payload_type);
884 if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
885 RTC_DLOG(LS_ERROR)
886 << "SetEncoder() failed to register codec to RTP/RTCP module";
887 return false;
888 }
889 }
890
Niels Möller7d76a312018-10-26 12:57:07 +0200891 if (media_transport_) {
892 rtc::CritScope cs(&media_transport_lock_);
893 media_transport_payload_type_ = payload_type;
894 // TODO(nisse): Currently broken for G722, since timestamps passed through
895 // encoder use RTP clock rather than sample count, and they differ for G722.
896 media_transport_sampling_frequency_ = encoder->RtpTimestampRateHz();
897 }
Niels Möller530ead42018-10-04 14:28:39 +0200898 audio_coding_->SetEncoder(std::move(encoder));
899 return true;
900}
901
902void ChannelSend::ModifyEncoder(
903 rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
Niels Möller26e88b02018-11-19 15:08:13 +0100904 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +0200905 audio_coding_->ModifyEncoder(modifier);
906}
907
Niels Möllerdced9f62018-11-19 10:27:07 +0100908void ChannelSend::SetBitrate(int bitrate_bps, int64_t probing_interval_ms) {
909 // This method can be called on the worker thread, module process thread
910 // or on a TaskQueue via VideoSendStreamImpl::OnEncoderConfigurationChanged.
911 // TODO(solenberg): Figure out a good way to check this or enforce calling
912 // rules.
913 // RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
914 // module_process_thread_checker_.CalledOnValidThread());
Piotr (Peter) Slatala1eebec92018-11-16 09:03:35 -0800915 rtc::CritScope lock(&bitrate_crit_section_);
Niels Möllerdced9f62018-11-19 10:27:07 +0100916
Niels Möller530ead42018-10-04 14:28:39 +0200917 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
918 if (*encoder) {
919 (*encoder)->OnReceivedUplinkBandwidth(bitrate_bps, probing_interval_ms);
920 }
921 });
922 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
Sebastian Jansson359d60a2018-10-25 16:22:02 +0200923 configured_bitrate_bps_ = bitrate_bps;
924}
925
Niels Möllerdced9f62018-11-19 10:27:07 +0100926int ChannelSend::GetBitrate() const {
Piotr (Peter) Slatala1eebec92018-11-16 09:03:35 -0800927 rtc::CritScope lock(&bitrate_crit_section_);
Sebastian Jansson359d60a2018-10-25 16:22:02 +0200928 return configured_bitrate_bps_;
Niels Möller530ead42018-10-04 14:28:39 +0200929}
930
931void ChannelSend::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) {
Niels Möller26e88b02018-11-19 15:08:13 +0100932 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +0200933 if (!use_twcc_plr_for_ana_)
934 return;
935 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
936 if (*encoder) {
937 (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
938 }
939 });
940}
941
942void ChannelSend::OnRecoverableUplinkPacketLossRate(
943 float recoverable_packet_loss_rate) {
Niels Möller26e88b02018-11-19 15:08:13 +0100944 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +0200945 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
946 if (*encoder) {
947 (*encoder)->OnReceivedUplinkRecoverablePacketLossFraction(
948 recoverable_packet_loss_rate);
949 }
950 });
951}
952
953void ChannelSend::OnUplinkPacketLossRate(float packet_loss_rate) {
954 if (use_twcc_plr_for_ana_)
955 return;
956 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
957 if (*encoder) {
958 (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
959 }
960 });
961}
962
Niels Möller530ead42018-10-04 14:28:39 +0200963void ChannelSend::RegisterTransport(Transport* transport) {
Niels Möller26e88b02018-11-19 15:08:13 +0100964 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +0200965 rtc::CritScope cs(&_callbackCritSect);
966 _transportPtr = transport;
967}
968
Niels Möller26815232018-11-16 09:32:40 +0100969// TODO(nisse): Delete always-true return value.
970bool ChannelSend::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
Niels Möllerdced9f62018-11-19 10:27:07 +0100971 // May be called on either worker thread or network thread.
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800972 if (media_transport_) {
973 // Ignore RTCP packets while media transport is used.
974 // Those packets should not arrive, but we are seeing occasional packets.
975 return 0;
976 }
977
Niels Möller530ead42018-10-04 14:28:39 +0200978 // Deliver RTCP packet to RTP/RTCP module for parsing
979 _rtpRtcpModule->IncomingRtcpPacket(data, length);
980
981 int64_t rtt = GetRTT();
982 if (rtt == 0) {
983 // Waiting for valid RTT.
Niels Möller26815232018-11-16 09:32:40 +0100984 return true;
Niels Möller530ead42018-10-04 14:28:39 +0200985 }
986
987 int64_t nack_window_ms = rtt;
988 if (nack_window_ms < kMinRetransmissionWindowMs) {
989 nack_window_ms = kMinRetransmissionWindowMs;
990 } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
991 nack_window_ms = kMaxRetransmissionWindowMs;
992 }
993 retransmission_rate_limiter_->SetWindowSize(nack_window_ms);
994
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800995 OnReceivedRtt(rtt);
Niels Möller26815232018-11-16 09:32:40 +0100996 return true;
Niels Möller530ead42018-10-04 14:28:39 +0200997}
998
999void ChannelSend::SetInputMute(bool enable) {
Niels Möller26e88b02018-11-19 15:08:13 +01001000 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001001 rtc::CritScope cs(&volume_settings_critsect_);
1002 input_mute_ = enable;
1003}
1004
1005bool ChannelSend::InputMute() const {
1006 rtc::CritScope cs(&volume_settings_critsect_);
1007 return input_mute_;
1008}
1009
Niels Möller26815232018-11-16 09:32:40 +01001010bool ChannelSend::SendTelephoneEventOutband(int event, int duration_ms) {
Niels Möller26e88b02018-11-19 15:08:13 +01001011 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001012 RTC_DCHECK_LE(0, event);
1013 RTC_DCHECK_GE(255, event);
1014 RTC_DCHECK_LE(0, duration_ms);
1015 RTC_DCHECK_GE(65535, duration_ms);
Fredrik Solenbergeb134842018-11-19 14:13:15 +01001016 if (!sending_) {
Niels Möller26815232018-11-16 09:32:40 +01001017 return false;
Niels Möller530ead42018-10-04 14:28:39 +02001018 }
1019 if (_rtpRtcpModule->SendTelephoneEventOutband(
1020 event, duration_ms, kTelephoneEventAttenuationdB) != 0) {
1021 RTC_DLOG(LS_ERROR) << "SendTelephoneEventOutband() failed to send event";
Niels Möller26815232018-11-16 09:32:40 +01001022 return false;
Niels Möller530ead42018-10-04 14:28:39 +02001023 }
Niels Möller26815232018-11-16 09:32:40 +01001024 return true;
Niels Möller530ead42018-10-04 14:28:39 +02001025}
1026
Niels Möller26815232018-11-16 09:32:40 +01001027bool ChannelSend::SetSendTelephoneEventPayloadType(int payload_type,
1028 int payload_frequency) {
Niels Möller26e88b02018-11-19 15:08:13 +01001029 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001030 RTC_DCHECK_LE(0, payload_type);
1031 RTC_DCHECK_GE(127, payload_type);
1032 CodecInst codec = {0};
1033 codec.pltype = payload_type;
1034 codec.plfreq = payload_frequency;
1035 memcpy(codec.plname, "telephone-event", 16);
1036 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1037 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1038 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1039 RTC_DLOG(LS_ERROR)
1040 << "SetSendTelephoneEventPayloadType() failed to register "
1041 "send payload type";
Niels Möller26815232018-11-16 09:32:40 +01001042 return false;
Niels Möller530ead42018-10-04 14:28:39 +02001043 }
1044 }
Niels Möller26815232018-11-16 09:32:40 +01001045 return true;
Niels Möller530ead42018-10-04 14:28:39 +02001046}
1047
Niels Möllerdced9f62018-11-19 10:27:07 +01001048void ChannelSend::SetLocalSSRC(uint32_t ssrc) {
Niels Möller26e88b02018-11-19 15:08:13 +01001049 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Fredrik Solenbergeb134842018-11-19 14:13:15 +01001050 RTC_DCHECK(!sending_);
Niels Möller26815232018-11-16 09:32:40 +01001051
Niels Möller7d76a312018-10-26 12:57:07 +02001052 if (media_transport_) {
1053 rtc::CritScope cs(&media_transport_lock_);
1054 media_transport_channel_id_ = ssrc;
1055 }
Niels Möller530ead42018-10-04 14:28:39 +02001056 _rtpRtcpModule->SetSSRC(ssrc);
Niels Möller530ead42018-10-04 14:28:39 +02001057}
1058
1059void ChannelSend::SetMid(const std::string& mid, int extension_id) {
Niels Möller26e88b02018-11-19 15:08:13 +01001060 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001061 int ret = SetSendRtpHeaderExtension(true, kRtpExtensionMid, extension_id);
1062 RTC_DCHECK_EQ(0, ret);
1063 _rtpRtcpModule->SetMid(mid);
1064}
1065
Johannes Kron9190b822018-10-29 11:22:05 +01001066void ChannelSend::SetExtmapAllowMixed(bool extmap_allow_mixed) {
Niels Möller26e88b02018-11-19 15:08:13 +01001067 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Johannes Kron9190b822018-10-29 11:22:05 +01001068 _rtpRtcpModule->SetExtmapAllowMixed(extmap_allow_mixed);
1069}
1070
Niels Möller26815232018-11-16 09:32:40 +01001071void ChannelSend::SetSendAudioLevelIndicationStatus(bool enable, int id) {
Niels Möller26e88b02018-11-19 15:08:13 +01001072 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001073 _includeAudioLevelIndication = enable;
Niels Möller26815232018-11-16 09:32:40 +01001074 int ret = SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
1075 RTC_DCHECK_EQ(0, ret);
Niels Möller530ead42018-10-04 14:28:39 +02001076}
1077
1078void ChannelSend::EnableSendTransportSequenceNumber(int id) {
Niels Möller26e88b02018-11-19 15:08:13 +01001079 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001080 int ret =
1081 SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id);
1082 RTC_DCHECK_EQ(0, ret);
1083}
1084
1085void ChannelSend::RegisterSenderCongestionControlObjects(
1086 RtpTransportControllerSendInterface* transport,
1087 RtcpBandwidthObserver* bandwidth_observer) {
Niels Möller26e88b02018-11-19 15:08:13 +01001088 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001089 RtpPacketSender* rtp_packet_sender = transport->packet_sender();
1090 TransportFeedbackObserver* transport_feedback_observer =
1091 transport->transport_feedback_observer();
1092 PacketRouter* packet_router = transport->packet_router();
1093
1094 RTC_DCHECK(rtp_packet_sender);
1095 RTC_DCHECK(transport_feedback_observer);
1096 RTC_DCHECK(packet_router);
1097 RTC_DCHECK(!packet_router_);
1098 rtcp_observer_->SetBandwidthObserver(bandwidth_observer);
1099 feedback_observer_proxy_->SetTransportFeedbackObserver(
1100 transport_feedback_observer);
1101 seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
1102 rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender);
1103 _rtpRtcpModule->SetStorePacketsStatus(true, 600);
1104 constexpr bool remb_candidate = false;
1105 packet_router->AddSendRtpModule(_rtpRtcpModule.get(), remb_candidate);
1106 packet_router_ = packet_router;
1107}
1108
1109void ChannelSend::ResetSenderCongestionControlObjects() {
Niels Möller26e88b02018-11-19 15:08:13 +01001110 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001111 RTC_DCHECK(packet_router_);
1112 _rtpRtcpModule->SetStorePacketsStatus(false, 600);
1113 rtcp_observer_->SetBandwidthObserver(nullptr);
1114 feedback_observer_proxy_->SetTransportFeedbackObserver(nullptr);
1115 seq_num_allocator_proxy_->SetSequenceNumberAllocator(nullptr);
1116 packet_router_->RemoveSendRtpModule(_rtpRtcpModule.get());
1117 packet_router_ = nullptr;
1118 rtp_packet_sender_proxy_->SetPacketSender(nullptr);
1119}
1120
Niels Möller26815232018-11-16 09:32:40 +01001121void ChannelSend::SetRTCP_CNAME(absl::string_view c_name) {
Niels Möller26e88b02018-11-19 15:08:13 +01001122 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller26815232018-11-16 09:32:40 +01001123 // Note: SetCNAME() accepts a c string of length at most 255.
1124 const std::string c_name_limited(c_name.substr(0, 255));
1125 int ret = _rtpRtcpModule->SetCNAME(c_name_limited.c_str()) != 0;
1126 RTC_DCHECK_EQ(0, ret) << "SetRTCP_CNAME() failed to set RTCP CNAME";
Niels Möller530ead42018-10-04 14:28:39 +02001127}
1128
Niels Möller26815232018-11-16 09:32:40 +01001129std::vector<ReportBlock> ChannelSend::GetRemoteRTCPReportBlocks() const {
Niels Möller26e88b02018-11-19 15:08:13 +01001130 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001131 // Get the report blocks from the latest received RTCP Sender or Receiver
1132 // Report. Each element in the vector contains the sender's SSRC and a
1133 // report block according to RFC 3550.
1134 std::vector<RTCPReportBlock> rtcp_report_blocks;
Niels Möller530ead42018-10-04 14:28:39 +02001135
Niels Möller26815232018-11-16 09:32:40 +01001136 int ret = _rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks);
1137 RTC_DCHECK_EQ(0, ret);
1138
1139 std::vector<ReportBlock> report_blocks;
Niels Möller530ead42018-10-04 14:28:39 +02001140
1141 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
1142 for (; it != rtcp_report_blocks.end(); ++it) {
1143 ReportBlock report_block;
1144 report_block.sender_SSRC = it->sender_ssrc;
1145 report_block.source_SSRC = it->source_ssrc;
1146 report_block.fraction_lost = it->fraction_lost;
1147 report_block.cumulative_num_packets_lost = it->packets_lost;
1148 report_block.extended_highest_sequence_number =
1149 it->extended_highest_sequence_number;
1150 report_block.interarrival_jitter = it->jitter;
1151 report_block.last_SR_timestamp = it->last_sender_report_timestamp;
1152 report_block.delay_since_last_SR = it->delay_since_last_sender_report;
Niels Möller26815232018-11-16 09:32:40 +01001153 report_blocks.push_back(report_block);
Niels Möller530ead42018-10-04 14:28:39 +02001154 }
Niels Möller26815232018-11-16 09:32:40 +01001155 return report_blocks;
Niels Möller530ead42018-10-04 14:28:39 +02001156}
1157
Niels Möller26815232018-11-16 09:32:40 +01001158CallSendStatistics ChannelSend::GetRTCPStatistics() const {
Niels Möller26e88b02018-11-19 15:08:13 +01001159 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller26815232018-11-16 09:32:40 +01001160 CallSendStatistics stats = {0};
Niels Möller530ead42018-10-04 14:28:39 +02001161 stats.rttMs = GetRTT();
1162
Niels Möller530ead42018-10-04 14:28:39 +02001163 size_t bytesSent(0);
1164 uint32_t packetsSent(0);
1165
1166 if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) {
1167 RTC_DLOG(LS_WARNING)
1168 << "GetRTPStatistics() failed to retrieve RTP datacounters"
1169 << " => output will not be complete";
1170 }
1171
1172 stats.bytesSent = bytesSent;
1173 stats.packetsSent = packetsSent;
1174
Niels Möller26815232018-11-16 09:32:40 +01001175 return stats;
Niels Möller530ead42018-10-04 14:28:39 +02001176}
1177
Niels Möllerdced9f62018-11-19 10:27:07 +01001178void ChannelSend::SetNACKStatus(bool enable, int max_packets) {
Niels Möller26e88b02018-11-19 15:08:13 +01001179 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001180 // None of these functions can fail.
1181 if (enable)
Niels Möllerdced9f62018-11-19 10:27:07 +01001182 audio_coding_->EnableNack(max_packets);
Niels Möller530ead42018-10-04 14:28:39 +02001183 else
1184 audio_coding_->DisableNack();
1185}
1186
1187// Called when we are missing one or more packets.
1188int ChannelSend::ResendPackets(const uint16_t* sequence_numbers, int length) {
1189 return _rtpRtcpModule->SendNACK(sequence_numbers, length);
1190}
1191
1192void ChannelSend::ProcessAndEncodeAudio(
1193 std::unique_ptr<AudioFrame> audio_frame) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001194 RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001195 // Avoid posting any new tasks if sending was already stopped in StopSend().
1196 rtc::CritScope cs(&encoder_queue_lock_);
1197 if (!encoder_queue_is_active_) {
1198 return;
1199 }
1200 // Profile time between when the audio frame is added to the task queue and
1201 // when the task is actually executed.
1202 audio_frame->UpdateProfileTimeStamp();
1203 encoder_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(
1204 new ProcessAndEncodeAudioTask(std::move(audio_frame), this)));
1205}
1206
1207void ChannelSend::ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input) {
1208 RTC_DCHECK_RUN_ON(encoder_queue_);
1209 RTC_DCHECK_GT(audio_input->samples_per_channel_, 0);
1210 RTC_DCHECK_LE(audio_input->num_channels_, 2);
1211
1212 // Measure time between when the audio frame is added to the task queue and
1213 // when the task is actually executed. Goal is to keep track of unwanted
1214 // extra latency added by the task queue.
1215 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Audio.EncodingTaskQueueLatencyMs",
1216 audio_input->ElapsedProfileTimeMs());
1217
1218 bool is_muted = InputMute();
1219 AudioFrameOperations::Mute(audio_input, previous_frame_muted_, is_muted);
1220
1221 if (_includeAudioLevelIndication) {
1222 size_t length =
1223 audio_input->samples_per_channel_ * audio_input->num_channels_;
1224 RTC_CHECK_LE(length, AudioFrame::kMaxDataSizeBytes);
1225 if (is_muted && previous_frame_muted_) {
1226 rms_level_.AnalyzeMuted(length);
1227 } else {
1228 rms_level_.Analyze(
1229 rtc::ArrayView<const int16_t>(audio_input->data(), length));
1230 }
1231 }
1232 previous_frame_muted_ = is_muted;
1233
1234 // Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
1235
1236 // The ACM resamples internally.
1237 audio_input->timestamp_ = _timeStamp;
1238 // This call will trigger AudioPacketizationCallback::SendData if encoding
1239 // is done and payload is ready for packetization and transmission.
1240 // Otherwise, it will return without invoking the callback.
1241 if (audio_coding_->Add10MsData(*audio_input) < 0) {
1242 RTC_DLOG(LS_ERROR) << "ACM::Add10MsData() failed.";
1243 return;
1244 }
1245
1246 _timeStamp += static_cast<uint32_t>(audio_input->samples_per_channel_);
1247}
1248
1249void ChannelSend::UpdateOverheadForEncoder() {
1250 size_t overhead_per_packet =
1251 transport_overhead_per_packet_ + rtp_overhead_per_packet_;
1252 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1253 if (*encoder) {
1254 (*encoder)->OnReceivedOverhead(overhead_per_packet);
1255 }
1256 });
1257}
1258
1259void ChannelSend::SetTransportOverhead(size_t transport_overhead_per_packet) {
Niels Möller26e88b02018-11-19 15:08:13 +01001260 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001261 rtc::CritScope cs(&overhead_per_packet_lock_);
1262 transport_overhead_per_packet_ = transport_overhead_per_packet;
1263 UpdateOverheadForEncoder();
1264}
1265
1266// TODO(solenberg): Make AudioSendStream an OverheadObserver instead.
1267void ChannelSend::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1268 rtc::CritScope cs(&overhead_per_packet_lock_);
1269 rtp_overhead_per_packet_ = overhead_bytes_per_packet;
1270 UpdateOverheadForEncoder();
1271}
1272
1273ANAStats ChannelSend::GetANAStatistics() const {
Niels Möller26e88b02018-11-19 15:08:13 +01001274 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001275 return audio_coding_->GetANAStats();
1276}
1277
1278RtpRtcp* ChannelSend::GetRtpRtcp() const {
Niels Möllerdced9f62018-11-19 10:27:07 +01001279 RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001280 return _rtpRtcpModule.get();
1281}
1282
1283int ChannelSend::SetSendRtpHeaderExtension(bool enable,
1284 RTPExtensionType type,
Niels Möller26815232018-11-16 09:32:40 +01001285 int id) {
Niels Möller530ead42018-10-04 14:28:39 +02001286 int error = 0;
1287 _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
1288 if (enable) {
Niels Möller26815232018-11-16 09:32:40 +01001289 // TODO(nisse): RtpRtcp::RegisterSendRtpHeaderExtension to take an int
1290 // argument. Currently it wants an uint8_t.
1291 error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(
1292 type, rtc::dchecked_cast<uint8_t>(id));
Niels Möller530ead42018-10-04 14:28:39 +02001293 }
1294 return error;
1295}
1296
1297int ChannelSend::GetRtpTimestampRateHz() const {
1298 const auto format = audio_coding_->ReceiveFormat();
1299 // Default to the playout frequency if we've not gotten any packets yet.
1300 // TODO(ossu): Zero clockrate can only happen if we've added an external
1301 // decoder for a format we don't support internally. Remove once that way of
1302 // adding decoders is gone!
1303 return (format && format->clockrate_hz != 0)
1304 ? format->clockrate_hz
1305 : audio_coding_->PlayoutFrequency();
1306}
1307
1308int64_t ChannelSend::GetRTT() const {
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -08001309 if (media_transport_) {
1310 // GetRTT is generally used in the RTCP codepath, where media transport is
1311 // not present and so it shouldn't be needed. But it's also invoked in
1312 // 'GetStats' method, and for now returning media transport RTT here gives
1313 // us "free" rtt stats for media transport.
1314 auto target_rate = media_transport_->GetLatestTargetTransferRate();
1315 if (target_rate.has_value()) {
1316 return target_rate.value().network_estimate.round_trip_time.ms();
1317 }
1318
1319 return 0;
1320 }
Niels Möller530ead42018-10-04 14:28:39 +02001321 RtcpMode method = _rtpRtcpModule->RTCP();
1322 if (method == RtcpMode::kOff) {
1323 return 0;
1324 }
1325 std::vector<RTCPReportBlock> report_blocks;
1326 _rtpRtcpModule->RemoteRTCPStat(&report_blocks);
1327
1328 if (report_blocks.empty()) {
1329 return 0;
1330 }
1331
1332 int64_t rtt = 0;
1333 int64_t avg_rtt = 0;
1334 int64_t max_rtt = 0;
1335 int64_t min_rtt = 0;
1336 // We don't know in advance the remote ssrc used by the other end's receiver
1337 // reports, so use the SSRC of the first report block for calculating the RTT.
1338 if (_rtpRtcpModule->RTT(report_blocks[0].sender_ssrc, &rtt, &avg_rtt,
1339 &min_rtt, &max_rtt) != 0) {
1340 return 0;
1341 }
1342 return rtt;
1343}
1344
Benjamin Wright78410ad2018-10-25 09:52:57 -07001345void ChannelSend::SetFrameEncryptor(
1346 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
Niels Möller26e88b02018-11-19 15:08:13 +01001347 RTC_DCHECK_RUN_ON(&worker_thread_checker_);
Benjamin Wright84583f62018-10-04 14:22:34 -07001348 rtc::CritScope cs(&encoder_queue_lock_);
1349 if (encoder_queue_is_active_) {
1350 encoder_queue_->PostTask([this, frame_encryptor]() {
Benjamin Wright78410ad2018-10-25 09:52:57 -07001351 this->frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -07001352 });
1353 } else {
Benjamin Wright78410ad2018-10-25 09:52:57 -07001354 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -07001355 }
1356}
1357
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -08001358void ChannelSend::OnTargetTransferRate(TargetTransferRate rate) {
1359 RTC_DCHECK(media_transport_);
1360 OnReceivedRtt(rate.network_estimate.round_trip_time.ms());
1361}
1362
1363void ChannelSend::OnReceivedRtt(int64_t rtt_ms) {
1364 // Invoke audio encoders OnReceivedRtt().
1365 audio_coding_->ModifyEncoder(
1366 [rtt_ms](std::unique_ptr<AudioEncoder>* encoder) {
1367 if (*encoder) {
1368 (*encoder)->OnReceivedRtt(rtt_ms);
1369 }
1370 });
1371}
1372
Niels Möllerdced9f62018-11-19 10:27:07 +01001373} // namespace
1374
1375std::unique_ptr<ChannelSendInterface> CreateChannelSend(
1376 rtc::TaskQueue* encoder_queue,
1377 ProcessThread* module_process_thread,
1378 MediaTransportInterface* media_transport,
1379 RtcpRttStats* rtcp_rtt_stats,
1380 RtcEventLog* rtc_event_log,
1381 FrameEncryptorInterface* frame_encryptor,
1382 const webrtc::CryptoOptions& crypto_options,
1383 bool extmap_allow_mixed,
1384 int rtcp_report_interval_ms) {
1385 return absl::make_unique<ChannelSend>(
1386 encoder_queue, module_process_thread, media_transport, rtcp_rtt_stats,
1387 rtc_event_log, frame_encryptor, crypto_options, extmap_allow_mixed,
1388 rtcp_report_interval_ms);
1389}
1390
Niels Möller530ead42018-10-04 14:28:39 +02001391} // namespace voe
1392} // namespace webrtc