blob: 8126adc14bdc9c52b52b827cfd7734fd418c0965 [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
80// Helper class to simplify locking scheme for members that are accessed from
81// multiple threads.
82// Example: a member can be set on thread T1 and read by an internal audio
83// thread T2. Accessing the member via this class ensures that we are
84// safe and also avoid TSan v2 warnings.
85class ChannelSendState {
86 public:
87 struct State {
88 bool sending = false;
89 };
90
91 ChannelSendState() {}
92 virtual ~ChannelSendState() {}
93
94 void Reset() {
95 rtc::CritScope lock(&lock_);
96 state_ = State();
97 }
98
99 State Get() const {
100 rtc::CritScope lock(&lock_);
101 return state_;
102 }
103
104 void SetSending(bool enable) {
105 rtc::CritScope lock(&lock_);
106 state_.sending = enable;
107 }
108
109 private:
110 rtc::CriticalSection lock_;
111 State state_;
112};
113
114class ChannelSend
115 : public ChannelSendInterface,
116 public Transport,
117 public OverheadObserver,
118 public AudioPacketizationCallback, // receive encoded packets from the
119 // ACM
120 public TargetTransferRateObserver {
121 public:
122 // TODO(nisse): Make OnUplinkPacketLossRate public, and delete friend
123 // declaration.
124 friend class VoERtcpObserver;
125
126 ChannelSend(rtc::TaskQueue* encoder_queue,
127 ProcessThread* module_process_thread,
128 MediaTransportInterface* media_transport,
129 RtcpRttStats* rtcp_rtt_stats,
130 RtcEventLog* rtc_event_log,
131 FrameEncryptorInterface* frame_encryptor,
132 const webrtc::CryptoOptions& crypto_options,
133 bool extmap_allow_mixed,
134 int rtcp_report_interval_ms);
135
136 ~ChannelSend() override;
137
138 // Send using this encoder, with this payload type.
139 bool SetEncoder(int payload_type,
140 std::unique_ptr<AudioEncoder> encoder) override;
141 void ModifyEncoder(rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)>
142 modifier) override;
143
144 // API methods
145
146 void StartSend() override;
147 void StopSend() override;
148
149 // Codecs
150 void SetBitrate(int bitrate_bps, int64_t probing_interval_ms) override;
151 int GetBitrate() const override;
152
153 // Network
154 void RegisterTransport(Transport* transport) override;
155
156 bool ReceivedRTCPPacket(const uint8_t* data, size_t length) override;
157
158 // Muting, Volume and Level.
159 void SetInputMute(bool enable) override;
160
161 // Stats.
162 ANAStats GetANAStatistics() const override;
163
164 // Used by AudioSendStream.
165 RtpRtcp* GetRtpRtcp() const override;
166
167 // DTMF.
168 bool SendTelephoneEventOutband(int event, int duration_ms) override;
169 bool SetSendTelephoneEventPayloadType(int payload_type,
170 int payload_frequency) override;
171
172 // RTP+RTCP
173 void SetLocalSSRC(uint32_t ssrc) override;
174
175 void SetMid(const std::string& mid, int extension_id) override;
176 void SetExtmapAllowMixed(bool extmap_allow_mixed) override;
177 void SetSendAudioLevelIndicationStatus(bool enable, int id) override;
178 void EnableSendTransportSequenceNumber(int id) override;
179
180 void RegisterSenderCongestionControlObjects(
181 RtpTransportControllerSendInterface* transport,
182 RtcpBandwidthObserver* bandwidth_observer) override;
183 void ResetSenderCongestionControlObjects() override;
184 void SetRTCP_CNAME(absl::string_view c_name) override;
185 std::vector<ReportBlock> GetRemoteRTCPReportBlocks() const override;
186 CallSendStatistics GetRTCPStatistics() const override;
187 void SetNACKStatus(bool enable, int max_packets) override;
188
189 // ProcessAndEncodeAudio() posts a task on the shared encoder task queue,
190 // which in turn calls (on the queue) ProcessAndEncodeAudioOnTaskQueue() where
191 // the actual processing of the audio takes place. The processing mainly
192 // consists of encoding and preparing the result for sending by adding it to a
193 // send queue.
194 // The main reason for using a task queue here is to release the native,
195 // OS-specific, audio capture thread as soon as possible to ensure that it
196 // can go back to sleep and be prepared to deliver an new captured audio
197 // packet.
198 void ProcessAndEncodeAudio(std::unique_ptr<AudioFrame> audio_frame) override;
199
200 void SetTransportOverhead(size_t transport_overhead_per_packet) override;
201
202 // The existence of this function alongside OnUplinkPacketLossRate is
203 // a compromise. We want the encoder to be agnostic of the PLR source, but
204 // we also don't want it to receive conflicting information from TWCC and
205 // from RTCP-XR.
206 void OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) override;
207
208 void OnRecoverableUplinkPacketLossRate(
209 float recoverable_packet_loss_rate) override;
210
211 int64_t GetRTT() const override;
212
213 // E2EE Custom Audio Frame Encryption
214 void SetFrameEncryptor(
215 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) override;
216
217 private:
218 class ProcessAndEncodeAudioTask;
219
220 // From AudioPacketizationCallback in the ACM
221 int32_t SendData(FrameType frameType,
222 uint8_t payloadType,
223 uint32_t timeStamp,
224 const uint8_t* payloadData,
225 size_t payloadSize,
226 const RTPFragmentationHeader* fragmentation) override;
227
228 // From Transport (called by the RTP/RTCP module)
229 bool SendRtp(const uint8_t* data,
230 size_t len,
231 const PacketOptions& packet_options) override;
232 bool SendRtcp(const uint8_t* data, size_t len) override;
233
234 bool Sending() const { return channel_state_.Get().sending; }
235
236 // From OverheadObserver in the RTP/RTCP module
237 void OnOverheadChanged(size_t overhead_bytes_per_packet) override;
238
239 void OnUplinkPacketLossRate(float packet_loss_rate);
240 bool InputMute() const;
241
242 int ResendPackets(const uint16_t* sequence_numbers, int length);
243
244 int SetSendRtpHeaderExtension(bool enable, RTPExtensionType type, int id);
245
246 void UpdateOverheadForEncoder()
247 RTC_EXCLUSIVE_LOCKS_REQUIRED(overhead_per_packet_lock_);
248
249 int GetRtpTimestampRateHz() const;
250
251 int32_t SendRtpAudio(FrameType frameType,
252 uint8_t payloadType,
253 uint32_t timeStamp,
254 rtc::ArrayView<const uint8_t> payload,
255 const RTPFragmentationHeader* fragmentation);
256
257 int32_t SendMediaTransportAudio(FrameType frameType,
258 uint8_t payloadType,
259 uint32_t timeStamp,
260 rtc::ArrayView<const uint8_t> payload,
261 const RTPFragmentationHeader* fragmentation);
262
263 // Return media transport or nullptr if using RTP.
264 MediaTransportInterface* media_transport() { return media_transport_; }
265
266 // Called on the encoder task queue when a new input audio frame is ready
267 // for encoding.
268 void ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input);
269
270 void OnReceivedRtt(int64_t rtt_ms);
271
272 void OnTargetTransferRate(TargetTransferRate) override;
273
274 // Thread checkers document and lock usage of some methods on voe::Channel to
275 // specific threads we know about. The goal is to eventually split up
276 // voe::Channel into parts with single-threaded semantics, and thereby reduce
277 // the need for locks.
278 rtc::ThreadChecker worker_thread_checker_;
279 rtc::ThreadChecker module_process_thread_checker_;
280 // Methods accessed from audio and video threads are checked for sequential-
281 // only access. We don't necessarily own and control these threads, so thread
282 // checkers cannot be used. E.g. Chromium may transfer "ownership" from one
283 // audio thread to another, but access is still sequential.
284 rtc::RaceChecker audio_thread_race_checker_;
285
286 rtc::CriticalSection _callbackCritSect;
287 rtc::CriticalSection volume_settings_critsect_;
288
289 ChannelSendState channel_state_;
290
291 RtcEventLog* const event_log_;
292
293 std::unique_ptr<RtpRtcp> _rtpRtcpModule;
294
295 std::unique_ptr<AudioCodingModule> audio_coding_;
296 uint32_t _timeStamp RTC_GUARDED_BY(encoder_queue_);
297
298 uint16_t send_sequence_number_;
299
300 // uses
301 ProcessThread* _moduleProcessThreadPtr;
302 Transport* _transportPtr; // WebRtc socket or external transport
303 RmsLevel rms_level_ RTC_GUARDED_BY(encoder_queue_);
304 bool input_mute_ RTC_GUARDED_BY(volume_settings_critsect_);
305 bool previous_frame_muted_ RTC_GUARDED_BY(encoder_queue_);
306 // VoeRTP_RTCP
307 // TODO(henrika): can today be accessed on the main thread and on the
308 // task queue; hence potential race.
309 bool _includeAudioLevelIndication;
310 size_t transport_overhead_per_packet_
311 RTC_GUARDED_BY(overhead_per_packet_lock_);
312 size_t rtp_overhead_per_packet_ RTC_GUARDED_BY(overhead_per_packet_lock_);
313 rtc::CriticalSection overhead_per_packet_lock_;
314 // RtcpBandwidthObserver
315 std::unique_ptr<VoERtcpObserver> rtcp_observer_;
316
317 PacketRouter* packet_router_ = nullptr;
318 std::unique_ptr<TransportFeedbackProxy> feedback_observer_proxy_;
319 std::unique_ptr<TransportSequenceNumberProxy> seq_num_allocator_proxy_;
320 std::unique_ptr<RtpPacketSenderProxy> rtp_packet_sender_proxy_;
321 std::unique_ptr<RateLimiter> retransmission_rate_limiter_;
322
323 rtc::ThreadChecker construction_thread_;
324
325 const bool use_twcc_plr_for_ana_;
326
327 rtc::CriticalSection encoder_queue_lock_;
328 bool encoder_queue_is_active_ RTC_GUARDED_BY(encoder_queue_lock_) = false;
329 rtc::TaskQueue* encoder_queue_ = nullptr;
330
331 MediaTransportInterface* const media_transport_;
332 int media_transport_sequence_number_ RTC_GUARDED_BY(encoder_queue_) = 0;
333
334 rtc::CriticalSection media_transport_lock_;
335 // Currently set by SetLocalSSRC.
336 uint64_t media_transport_channel_id_ RTC_GUARDED_BY(&media_transport_lock_) =
337 0;
338 // Cache payload type and sampling frequency from most recent call to
339 // SetEncoder. Needed to set MediaTransportEncodedAudioFrame metadata, and
340 // invalidate on encoder change.
341 int media_transport_payload_type_ RTC_GUARDED_BY(&media_transport_lock_);
342 int media_transport_sampling_frequency_
343 RTC_GUARDED_BY(&media_transport_lock_);
344
345 // E2EE Audio Frame Encryption
346 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor_;
347 // E2EE Frame Encryption Options
348 webrtc::CryptoOptions crypto_options_;
349
350 rtc::CriticalSection bitrate_crit_section_;
351 int configured_bitrate_bps_ RTC_GUARDED_BY(bitrate_crit_section_) = 0;
352};
Niels Möller530ead42018-10-04 14:28:39 +0200353
354const int kTelephoneEventAttenuationdB = 10;
355
356class TransportFeedbackProxy : public TransportFeedbackObserver {
357 public:
358 TransportFeedbackProxy() : feedback_observer_(nullptr) {
359 pacer_thread_.DetachFromThread();
360 network_thread_.DetachFromThread();
361 }
362
363 void SetTransportFeedbackObserver(
364 TransportFeedbackObserver* feedback_observer) {
365 RTC_DCHECK(thread_checker_.CalledOnValidThread());
366 rtc::CritScope lock(&crit_);
367 feedback_observer_ = feedback_observer;
368 }
369
370 // Implements TransportFeedbackObserver.
371 void AddPacket(uint32_t ssrc,
372 uint16_t sequence_number,
373 size_t length,
374 const PacedPacketInfo& pacing_info) override {
375 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
376 rtc::CritScope lock(&crit_);
377 if (feedback_observer_)
378 feedback_observer_->AddPacket(ssrc, sequence_number, length, pacing_info);
379 }
380
381 void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override {
382 RTC_DCHECK(network_thread_.CalledOnValidThread());
383 rtc::CritScope lock(&crit_);
384 if (feedback_observer_)
385 feedback_observer_->OnTransportFeedback(feedback);
386 }
387
388 private:
389 rtc::CriticalSection crit_;
390 rtc::ThreadChecker thread_checker_;
391 rtc::ThreadChecker pacer_thread_;
392 rtc::ThreadChecker network_thread_;
393 TransportFeedbackObserver* feedback_observer_ RTC_GUARDED_BY(&crit_);
394};
395
396class TransportSequenceNumberProxy : public TransportSequenceNumberAllocator {
397 public:
398 TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) {
399 pacer_thread_.DetachFromThread();
400 }
401
402 void SetSequenceNumberAllocator(
403 TransportSequenceNumberAllocator* seq_num_allocator) {
404 RTC_DCHECK(thread_checker_.CalledOnValidThread());
405 rtc::CritScope lock(&crit_);
406 seq_num_allocator_ = seq_num_allocator;
407 }
408
409 // Implements TransportSequenceNumberAllocator.
410 uint16_t AllocateSequenceNumber() override {
411 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
412 rtc::CritScope lock(&crit_);
413 if (!seq_num_allocator_)
414 return 0;
415 return seq_num_allocator_->AllocateSequenceNumber();
416 }
417
418 private:
419 rtc::CriticalSection crit_;
420 rtc::ThreadChecker thread_checker_;
421 rtc::ThreadChecker pacer_thread_;
422 TransportSequenceNumberAllocator* seq_num_allocator_ RTC_GUARDED_BY(&crit_);
423};
424
425class RtpPacketSenderProxy : public RtpPacketSender {
426 public:
427 RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) {}
428
429 void SetPacketSender(RtpPacketSender* rtp_packet_sender) {
430 RTC_DCHECK(thread_checker_.CalledOnValidThread());
431 rtc::CritScope lock(&crit_);
432 rtp_packet_sender_ = rtp_packet_sender;
433 }
434
435 // Implements RtpPacketSender.
436 void InsertPacket(Priority priority,
437 uint32_t ssrc,
438 uint16_t sequence_number,
439 int64_t capture_time_ms,
440 size_t bytes,
441 bool retransmission) override {
442 rtc::CritScope lock(&crit_);
443 if (rtp_packet_sender_) {
444 rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number,
445 capture_time_ms, bytes, retransmission);
446 }
447 }
448
449 void SetAccountForAudioPackets(bool account_for_audio) override {
450 RTC_NOTREACHED();
451 }
452
453 private:
454 rtc::ThreadChecker thread_checker_;
455 rtc::CriticalSection crit_;
456 RtpPacketSender* rtp_packet_sender_ RTC_GUARDED_BY(&crit_);
457};
458
459class VoERtcpObserver : public RtcpBandwidthObserver {
460 public:
461 explicit VoERtcpObserver(ChannelSend* owner)
462 : owner_(owner), bandwidth_observer_(nullptr) {}
463 virtual ~VoERtcpObserver() {}
464
465 void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
466 rtc::CritScope lock(&crit_);
467 bandwidth_observer_ = bandwidth_observer;
468 }
469
470 void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
471 rtc::CritScope lock(&crit_);
472 if (bandwidth_observer_) {
473 bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
474 }
475 }
476
477 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
478 int64_t rtt,
479 int64_t now_ms) override {
480 {
481 rtc::CritScope lock(&crit_);
482 if (bandwidth_observer_) {
483 bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, rtt,
484 now_ms);
485 }
486 }
487 // TODO(mflodman): Do we need to aggregate reports here or can we jut send
488 // what we get? I.e. do we ever get multiple reports bundled into one RTCP
489 // report for VoiceEngine?
490 if (report_blocks.empty())
491 return;
492
493 int fraction_lost_aggregate = 0;
494 int total_number_of_packets = 0;
495
496 // If receiving multiple report blocks, calculate the weighted average based
497 // on the number of packets a report refers to.
498 for (ReportBlockList::const_iterator block_it = report_blocks.begin();
499 block_it != report_blocks.end(); ++block_it) {
500 // Find the previous extended high sequence number for this remote SSRC,
501 // to calculate the number of RTP packets this report refers to. Ignore if
502 // we haven't seen this SSRC before.
503 std::map<uint32_t, uint32_t>::iterator seq_num_it =
504 extended_max_sequence_number_.find(block_it->source_ssrc);
505 int number_of_packets = 0;
506 if (seq_num_it != extended_max_sequence_number_.end()) {
507 number_of_packets =
508 block_it->extended_highest_sequence_number - seq_num_it->second;
509 }
510 fraction_lost_aggregate += number_of_packets * block_it->fraction_lost;
511 total_number_of_packets += number_of_packets;
512
513 extended_max_sequence_number_[block_it->source_ssrc] =
514 block_it->extended_highest_sequence_number;
515 }
516 int weighted_fraction_lost = 0;
517 if (total_number_of_packets > 0) {
518 weighted_fraction_lost =
519 (fraction_lost_aggregate + total_number_of_packets / 2) /
520 total_number_of_packets;
521 }
522 owner_->OnUplinkPacketLossRate(weighted_fraction_lost / 255.0f);
523 }
524
525 private:
526 ChannelSend* owner_;
527 // Maps remote side ssrc to extended highest sequence number received.
528 std::map<uint32_t, uint32_t> extended_max_sequence_number_;
529 rtc::CriticalSection crit_;
530 RtcpBandwidthObserver* bandwidth_observer_ RTC_GUARDED_BY(crit_);
531};
532
533class ChannelSend::ProcessAndEncodeAudioTask : public rtc::QueuedTask {
534 public:
535 ProcessAndEncodeAudioTask(std::unique_ptr<AudioFrame> audio_frame,
536 ChannelSend* channel)
537 : audio_frame_(std::move(audio_frame)), channel_(channel) {
538 RTC_DCHECK(channel_);
539 }
540
541 private:
542 bool Run() override {
543 RTC_DCHECK_RUN_ON(channel_->encoder_queue_);
544 channel_->ProcessAndEncodeAudioOnTaskQueue(audio_frame_.get());
545 return true;
546 }
547
548 std::unique_ptr<AudioFrame> audio_frame_;
549 ChannelSend* const channel_;
550};
551
552int32_t ChannelSend::SendData(FrameType frameType,
553 uint8_t payloadType,
554 uint32_t timeStamp,
555 const uint8_t* payloadData,
556 size_t payloadSize,
557 const RTPFragmentationHeader* fragmentation) {
558 RTC_DCHECK_RUN_ON(encoder_queue_);
Niels Möller7d76a312018-10-26 12:57:07 +0200559 rtc::ArrayView<const uint8_t> payload(payloadData, payloadSize);
560
561 if (media_transport() != nullptr) {
562 return SendMediaTransportAudio(frameType, payloadType, timeStamp, payload,
563 fragmentation);
564 } else {
565 return SendRtpAudio(frameType, payloadType, timeStamp, payload,
566 fragmentation);
567 }
568}
569
570int32_t ChannelSend::SendRtpAudio(FrameType frameType,
571 uint8_t payloadType,
572 uint32_t timeStamp,
573 rtc::ArrayView<const uint8_t> payload,
574 const RTPFragmentationHeader* fragmentation) {
575 RTC_DCHECK_RUN_ON(encoder_queue_);
Niels Möller530ead42018-10-04 14:28:39 +0200576 if (_includeAudioLevelIndication) {
577 // Store current audio level in the RTP/RTCP module.
578 // The level will be used in combination with voice-activity state
579 // (frameType) to add an RTP header extension
580 _rtpRtcpModule->SetAudioLevel(rms_level_.Average());
581 }
582
Benjamin Wright84583f62018-10-04 14:22:34 -0700583 // E2EE Custom Audio Frame Encryption (This is optional).
584 // Keep this buffer around for the lifetime of the send call.
585 rtc::Buffer encrypted_audio_payload;
586 if (frame_encryptor_ != nullptr) {
587 // TODO(benwright@webrtc.org) - Allocate enough to always encrypt inline.
588 // Allocate a buffer to hold the maximum possible encrypted payload.
589 size_t max_ciphertext_size = frame_encryptor_->GetMaxCiphertextByteSize(
Niels Möller7d76a312018-10-26 12:57:07 +0200590 cricket::MEDIA_TYPE_AUDIO, payload.size());
Benjamin Wright84583f62018-10-04 14:22:34 -0700591 encrypted_audio_payload.SetSize(max_ciphertext_size);
592
593 // Encrypt the audio payload into the buffer.
594 size_t bytes_written = 0;
595 int encrypt_status = frame_encryptor_->Encrypt(
596 cricket::MEDIA_TYPE_AUDIO, _rtpRtcpModule->SSRC(),
Niels Möller7d76a312018-10-26 12:57:07 +0200597 /*additional_data=*/nullptr, payload, encrypted_audio_payload,
598 &bytes_written);
Benjamin Wright84583f62018-10-04 14:22:34 -0700599 if (encrypt_status != 0) {
600 RTC_DLOG(LS_ERROR) << "Channel::SendData() failed encrypt audio payload: "
601 << encrypt_status;
602 return -1;
603 }
604 // Resize the buffer to the exact number of bytes actually used.
605 encrypted_audio_payload.SetSize(bytes_written);
606 // Rewrite the payloadData and size to the new encrypted payload.
Niels Möller7d76a312018-10-26 12:57:07 +0200607 payload = encrypted_audio_payload;
Benjamin Wrightbfb444c2018-10-15 10:20:24 -0700608 } else if (crypto_options_.sframe.require_frame_encryption) {
609 RTC_DLOG(LS_ERROR) << "Channel::SendData() failed sending audio payload: "
610 << "A frame encryptor is required but one is not set.";
611 return -1;
Benjamin Wright84583f62018-10-04 14:22:34 -0700612 }
613
Niels Möller530ead42018-10-04 14:28:39 +0200614 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
615 // packetization.
616 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
Niels Möller7d76a312018-10-26 12:57:07 +0200617 if (!_rtpRtcpModule->SendOutgoingData((FrameType&)frameType, payloadType,
618 timeStamp,
619 // Leaving the time when this frame was
620 // received from the capture device as
621 // undefined for voice for now.
622 -1, payload.data(), payload.size(),
623 fragmentation, nullptr, nullptr)) {
Niels Möller530ead42018-10-04 14:28:39 +0200624 RTC_DLOG(LS_ERROR)
625 << "ChannelSend::SendData() failed to send data to RTP/RTCP module";
626 return -1;
627 }
628
629 return 0;
630}
631
Niels Möller7d76a312018-10-26 12:57:07 +0200632int32_t ChannelSend::SendMediaTransportAudio(
633 FrameType frameType,
634 uint8_t payloadType,
635 uint32_t timeStamp,
636 rtc::ArrayView<const uint8_t> payload,
637 const RTPFragmentationHeader* fragmentation) {
638 RTC_DCHECK_RUN_ON(encoder_queue_);
639 // TODO(nisse): Use null _transportPtr for MediaTransport.
640 // RTC_DCHECK(_transportPtr == nullptr);
641 uint64_t channel_id;
642 int sampling_rate_hz;
643 {
644 rtc::CritScope cs(&media_transport_lock_);
645 if (media_transport_payload_type_ != payloadType) {
646 // Payload type is being changed, media_transport_sampling_frequency_,
647 // no longer current.
648 return -1;
649 }
650 sampling_rate_hz = media_transport_sampling_frequency_;
651 channel_id = media_transport_channel_id_;
652 }
653 const MediaTransportEncodedAudioFrame frame(
654 /*sampling_rate_hz=*/sampling_rate_hz,
655
656 // TODO(nisse): Timestamp and sample index are the same for all supported
657 // audio codecs except G722. Refactor audio coding module to only use
658 // sample index, and leave translation to RTP time, when needed, for
659 // RTP-specific code.
660 /*starting_sample_index=*/timeStamp,
661
662 // Sample count isn't conveniently available from the AudioCodingModule,
663 // and needs some refactoring to wire up in a good way. For now, left as
664 // zero.
665 /*sample_count=*/0,
666
667 /*sequence_number=*/media_transport_sequence_number_,
668 MediaTransportFrameTypeForWebrtcFrameType(frameType), payloadType,
669 std::vector<uint8_t>(payload.begin(), payload.end()));
670
671 // TODO(nisse): Introduce a MediaTransportSender object bound to a specific
672 // channel id.
673 RTCError rtc_error =
674 media_transport()->SendAudioFrame(channel_id, std::move(frame));
675
676 if (!rtc_error.ok()) {
677 RTC_LOG(LS_ERROR) << "Failed to send frame, rtc_error="
678 << ToString(rtc_error.type()) << ", "
679 << rtc_error.message();
680 return -1;
681 }
682
683 ++media_transport_sequence_number_;
684
685 return 0;
686}
687
Niels Möller530ead42018-10-04 14:28:39 +0200688bool ChannelSend::SendRtp(const uint8_t* data,
689 size_t len,
690 const PacketOptions& options) {
Niels Möller7d76a312018-10-26 12:57:07 +0200691 // We should not be sending RTP packets if media transport is available.
692 RTC_CHECK(!media_transport());
693
Niels Möller530ead42018-10-04 14:28:39 +0200694 rtc::CritScope cs(&_callbackCritSect);
695
696 if (_transportPtr == NULL) {
697 RTC_DLOG(LS_ERROR)
698 << "ChannelSend::SendPacket() failed to send RTP packet due to"
699 << " invalid transport object";
700 return false;
701 }
702
703 if (!_transportPtr->SendRtp(data, len, options)) {
704 RTC_DLOG(LS_ERROR) << "ChannelSend::SendPacket() RTP transmission failed";
705 return false;
706 }
707 return true;
708}
709
710bool ChannelSend::SendRtcp(const uint8_t* data, size_t len) {
711 rtc::CritScope cs(&_callbackCritSect);
712 if (_transportPtr == NULL) {
713 RTC_DLOG(LS_ERROR)
714 << "ChannelSend::SendRtcp() failed to send RTCP packet due to"
715 << " invalid transport object";
716 return false;
717 }
718
719 int n = _transportPtr->SendRtcp(data, len);
720 if (n < 0) {
721 RTC_DLOG(LS_ERROR) << "ChannelSend::SendRtcp() transmission failed";
722 return false;
723 }
724 return true;
725}
726
Niels Möller530ead42018-10-04 14:28:39 +0200727ChannelSend::ChannelSend(rtc::TaskQueue* encoder_queue,
728 ProcessThread* module_process_thread,
Niels Möller7d76a312018-10-26 12:57:07 +0200729 MediaTransportInterface* media_transport,
Niels Möller530ead42018-10-04 14:28:39 +0200730 RtcpRttStats* rtcp_rtt_stats,
Benjamin Wright84583f62018-10-04 14:22:34 -0700731 RtcEventLog* rtc_event_log,
Benjamin Wrightbfb444c2018-10-15 10:20:24 -0700732 FrameEncryptorInterface* frame_encryptor,
Johannes Kron9190b822018-10-29 11:22:05 +0100733 const webrtc::CryptoOptions& crypto_options,
Jiawei Ou55718122018-11-09 13:17:39 -0800734 bool extmap_allow_mixed,
735 int rtcp_report_interval_ms)
Niels Möller530ead42018-10-04 14:28:39 +0200736 : event_log_(rtc_event_log),
737 _timeStamp(0), // This is just an offset, RTP module will add it's own
738 // random offset
739 send_sequence_number_(0),
740 _moduleProcessThreadPtr(module_process_thread),
741 _transportPtr(NULL),
742 input_mute_(false),
743 previous_frame_muted_(false),
744 _includeAudioLevelIndication(false),
745 transport_overhead_per_packet_(0),
746 rtp_overhead_per_packet_(0),
747 rtcp_observer_(new VoERtcpObserver(this)),
748 feedback_observer_proxy_(new TransportFeedbackProxy()),
749 seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
750 rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
751 retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
752 kMaxRetransmissionWindowMs)),
753 use_twcc_plr_for_ana_(
754 webrtc::field_trial::FindFullName("UseTwccPlrForAna") == "Enabled"),
Benjamin Wright84583f62018-10-04 14:22:34 -0700755 encoder_queue_(encoder_queue),
Niels Möller7d76a312018-10-26 12:57:07 +0200756 media_transport_(media_transport),
Benjamin Wrightbfb444c2018-10-15 10:20:24 -0700757 frame_encryptor_(frame_encryptor),
758 crypto_options_(crypto_options) {
Niels Möller530ead42018-10-04 14:28:39 +0200759 RTC_DCHECK(module_process_thread);
760 RTC_DCHECK(encoder_queue);
Niels Möllerdced9f62018-11-19 10:27:07 +0100761 module_process_thread_checker_.DetachFromThread();
762
Niels Möller530ead42018-10-04 14:28:39 +0200763 audio_coding_.reset(AudioCodingModule::Create(AudioCodingModule::Config()));
764
765 RtpRtcp::Configuration configuration;
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800766
767 // We gradually remove codepaths that depend on RTP when using media
768 // transport. All of this logic should be moved to the future
769 // RTPMediaTransport. In this case it means that overhead and bandwidth
770 // observers should not be called when using media transport.
771 if (!media_transport_) {
772 configuration.overhead_observer = this;
773 configuration.bandwidth_callback = rtcp_observer_.get();
774 configuration.transport_feedback_callback = feedback_observer_proxy_.get();
775 }
776
Niels Möller530ead42018-10-04 14:28:39 +0200777 configuration.audio = true;
778 configuration.outgoing_transport = this;
Niels Möller530ead42018-10-04 14:28:39 +0200779
780 configuration.paced_sender = rtp_packet_sender_proxy_.get();
781 configuration.transport_sequence_number_allocator =
782 seq_num_allocator_proxy_.get();
Niels Möller530ead42018-10-04 14:28:39 +0200783
784 configuration.event_log = event_log_;
785 configuration.rtt_stats = rtcp_rtt_stats;
786 configuration.retransmission_rate_limiter =
787 retransmission_rate_limiter_.get();
Johannes Kron9190b822018-10-29 11:22:05 +0100788 configuration.extmap_allow_mixed = extmap_allow_mixed;
Jiawei Ou55718122018-11-09 13:17:39 -0800789 configuration.rtcp_interval_config.audio_interval_ms =
790 rtcp_report_interval_ms;
Niels Möller530ead42018-10-04 14:28:39 +0200791
792 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
793 _rtpRtcpModule->SetSendingMediaStatus(false);
Niels Möller530ead42018-10-04 14:28:39 +0200794
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800795 // We want to invoke the 'TargetRateObserver' and |OnOverheadChanged|
796 // callbacks after the audio_coding_ is fully initialized.
797 if (media_transport_) {
798 RTC_DLOG(LS_INFO) << "Setting media_transport_ rate observers.";
799 media_transport_->AddTargetTransferRateObserver(this);
800 OnOverheadChanged(media_transport_->GetAudioPacketOverhead());
801 } else {
802 RTC_DLOG(LS_INFO) << "Not setting media_transport_ rate observers.";
803 }
804
Niels Möller530ead42018-10-04 14:28:39 +0200805 channel_state_.Reset();
806
Niels Möller530ead42018-10-04 14:28:39 +0200807 _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get(), RTC_FROM_HERE);
808
Niels Möller530ead42018-10-04 14:28:39 +0200809 int error = audio_coding_->InitializeReceiver();
810 RTC_DCHECK_EQ(0, error);
811
Niels Möller530ead42018-10-04 14:28:39 +0200812 // Ensure that RTCP is enabled by default for the created channel.
813 // Note that, the module will keep generating RTCP until it is explicitly
814 // disabled by the user.
815 // After StopListen (when no sockets exists), RTCP packets will no longer
816 // be transmitted since the Transport object will then be invalid.
817 // RTCP is enabled by default.
818 _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
819
Niels Möller530ead42018-10-04 14:28:39 +0200820 error = audio_coding_->RegisterTransportCallback(this);
821 RTC_DCHECK_EQ(0, error);
822}
823
Fredrik Solenberg645a3af2018-11-16 12:51:15 +0100824ChannelSend::~ChannelSend() {
Niels Möller530ead42018-10-04 14:28:39 +0200825 RTC_DCHECK(construction_thread_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +0200826
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -0800827 if (media_transport_) {
828 media_transport_->RemoveTargetTransferRateObserver(this);
829 }
830
Niels Möller530ead42018-10-04 14:28:39 +0200831 StopSend();
832
Niels Möller530ead42018-10-04 14:28:39 +0200833 int error = audio_coding_->RegisterTransportCallback(NULL);
834 RTC_DCHECK_EQ(0, error);
835
Niels Möller530ead42018-10-04 14:28:39 +0200836 if (_moduleProcessThreadPtr)
837 _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
838
Fredrik Solenberg645a3af2018-11-16 12:51:15 +0100839 RTC_DCHECK(!channel_state_.Get().sending);
Niels Möller530ead42018-10-04 14:28:39 +0200840}
841
Niels Möller26815232018-11-16 09:32:40 +0100842void ChannelSend::StartSend() {
Niels Möllerdced9f62018-11-19 10:27:07 +0100843 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller26815232018-11-16 09:32:40 +0100844 RTC_DCHECK(!channel_state_.Get().sending);
Niels Möller530ead42018-10-04 14:28:39 +0200845 channel_state_.SetSending(true);
846
847 // Resume the previous sequence number which was reset by StopSend(). This
848 // needs to be done before |sending| is set to true on the RTP/RTCP module.
849 if (send_sequence_number_) {
850 _rtpRtcpModule->SetSequenceNumber(send_sequence_number_);
851 }
852 _rtpRtcpModule->SetSendingMediaStatus(true);
Niels Möller26815232018-11-16 09:32:40 +0100853 int ret = _rtpRtcpModule->SetSendingStatus(true);
854 RTC_DCHECK_EQ(0, ret);
Niels Möller530ead42018-10-04 14:28:39 +0200855 {
856 // It is now OK to start posting tasks to the encoder task queue.
857 rtc::CritScope cs(&encoder_queue_lock_);
858 encoder_queue_is_active_ = true;
859 }
Niels Möller530ead42018-10-04 14:28:39 +0200860}
861
862void ChannelSend::StopSend() {
Niels Möllerdced9f62018-11-19 10:27:07 +0100863 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +0200864 if (!channel_state_.Get().sending) {
865 return;
866 }
867 channel_state_.SetSending(false);
868
869 // Post a task to the encoder thread which sets an event when the task is
870 // executed. We know that no more encoding tasks will be added to the task
871 // queue for this channel since sending is now deactivated. It means that,
872 // if we wait for the event to bet set, we know that no more pending tasks
873 // exists and it is therfore guaranteed that the task queue will never try
874 // to acccess and invalid channel object.
875 RTC_DCHECK(encoder_queue_);
876
Niels Möllerc572ff32018-11-07 08:43:50 +0100877 rtc::Event flush;
Niels Möller530ead42018-10-04 14:28:39 +0200878 {
879 // Clear |encoder_queue_is_active_| under lock to prevent any other tasks
880 // than this final "flush task" to be posted on the queue.
881 rtc::CritScope cs(&encoder_queue_lock_);
882 encoder_queue_is_active_ = false;
883 encoder_queue_->PostTask([&flush]() { flush.Set(); });
884 }
885 flush.Wait(rtc::Event::kForever);
886
887 // Store the sequence number to be able to pick up the same sequence for
888 // the next StartSend(). This is needed for restarting device, otherwise
889 // it might cause libSRTP to complain about packets being replayed.
890 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
891 // CL is landed. See issue
892 // https://code.google.com/p/webrtc/issues/detail?id=2111 .
893 send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
894
895 // Reset sending SSRC and sequence number and triggers direct transmission
896 // of RTCP BYE
897 if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
898 RTC_DLOG(LS_ERROR) << "StartSend() RTP/RTCP failed to stop sending";
899 }
900 _rtpRtcpModule->SetSendingMediaStatus(false);
901}
902
903bool ChannelSend::SetEncoder(int payload_type,
904 std::unique_ptr<AudioEncoder> encoder) {
Niels Möllerdced9f62018-11-19 10:27:07 +0100905 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +0200906 RTC_DCHECK_GE(payload_type, 0);
907 RTC_DCHECK_LE(payload_type, 127);
908 // TODO(ossu): Make CodecInsts up, for now: one for the RTP/RTCP module and
909 // one for for us to keep track of sample rate and number of channels, etc.
910
911 // The RTP/RTCP module needs to know the RTP timestamp rate (i.e. clockrate)
912 // as well as some other things, so we collect this info and send it along.
913 CodecInst rtp_codec;
914 rtp_codec.pltype = payload_type;
915 strncpy(rtp_codec.plname, "audio", sizeof(rtp_codec.plname));
916 rtp_codec.plname[sizeof(rtp_codec.plname) - 1] = 0;
917 // Seems unclear if it should be clock rate or sample rate. CodecInst
918 // supposedly carries the sample rate, but only clock rate seems sensible to
919 // send to the RTP/RTCP module.
920 rtp_codec.plfreq = encoder->RtpTimestampRateHz();
921 rtp_codec.pacsize = rtc::CheckedDivExact(
922 static_cast<int>(encoder->Max10MsFramesInAPacket() * rtp_codec.plfreq),
923 100);
924 rtp_codec.channels = encoder->NumChannels();
925 rtp_codec.rate = 0;
926
927 if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
928 _rtpRtcpModule->DeRegisterSendPayload(payload_type);
929 if (_rtpRtcpModule->RegisterSendPayload(rtp_codec) != 0) {
930 RTC_DLOG(LS_ERROR)
931 << "SetEncoder() failed to register codec to RTP/RTCP module";
932 return false;
933 }
934 }
935
Niels Möller7d76a312018-10-26 12:57:07 +0200936 if (media_transport_) {
937 rtc::CritScope cs(&media_transport_lock_);
938 media_transport_payload_type_ = payload_type;
939 // TODO(nisse): Currently broken for G722, since timestamps passed through
940 // encoder use RTP clock rather than sample count, and they differ for G722.
941 media_transport_sampling_frequency_ = encoder->RtpTimestampRateHz();
942 }
Niels Möller530ead42018-10-04 14:28:39 +0200943 audio_coding_->SetEncoder(std::move(encoder));
944 return true;
945}
946
947void ChannelSend::ModifyEncoder(
948 rtc::FunctionView<void(std::unique_ptr<AudioEncoder>*)> modifier) {
Niels Möllerdced9f62018-11-19 10:27:07 +0100949 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +0200950 audio_coding_->ModifyEncoder(modifier);
951}
952
Niels Möllerdced9f62018-11-19 10:27:07 +0100953void ChannelSend::SetBitrate(int bitrate_bps, int64_t probing_interval_ms) {
954 // This method can be called on the worker thread, module process thread
955 // or on a TaskQueue via VideoSendStreamImpl::OnEncoderConfigurationChanged.
956 // TODO(solenberg): Figure out a good way to check this or enforce calling
957 // rules.
958 // RTC_DCHECK(worker_thread_checker_.CalledOnValidThread() ||
959 // module_process_thread_checker_.CalledOnValidThread());
Piotr (Peter) Slatala1eebec92018-11-16 09:03:35 -0800960 rtc::CritScope lock(&bitrate_crit_section_);
Niels Möllerdced9f62018-11-19 10:27:07 +0100961
Niels Möller530ead42018-10-04 14:28:39 +0200962 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
963 if (*encoder) {
964 (*encoder)->OnReceivedUplinkBandwidth(bitrate_bps, probing_interval_ms);
965 }
966 });
967 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
Sebastian Jansson359d60a2018-10-25 16:22:02 +0200968 configured_bitrate_bps_ = bitrate_bps;
969}
970
Niels Möllerdced9f62018-11-19 10:27:07 +0100971int ChannelSend::GetBitrate() const {
Piotr (Peter) Slatala1eebec92018-11-16 09:03:35 -0800972 rtc::CritScope lock(&bitrate_crit_section_);
Sebastian Jansson359d60a2018-10-25 16:22:02 +0200973 return configured_bitrate_bps_;
Niels Möller530ead42018-10-04 14:28:39 +0200974}
975
976void ChannelSend::OnTwccBasedUplinkPacketLossRate(float packet_loss_rate) {
Niels Möllerdced9f62018-11-19 10:27:07 +0100977 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +0200978 if (!use_twcc_plr_for_ana_)
979 return;
980 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
981 if (*encoder) {
982 (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
983 }
984 });
985}
986
987void ChannelSend::OnRecoverableUplinkPacketLossRate(
988 float recoverable_packet_loss_rate) {
Niels Möllerdced9f62018-11-19 10:27:07 +0100989 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +0200990 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
991 if (*encoder) {
992 (*encoder)->OnReceivedUplinkRecoverablePacketLossFraction(
993 recoverable_packet_loss_rate);
994 }
995 });
996}
997
998void ChannelSend::OnUplinkPacketLossRate(float packet_loss_rate) {
999 if (use_twcc_plr_for_ana_)
1000 return;
1001 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1002 if (*encoder) {
1003 (*encoder)->OnReceivedUplinkPacketLossFraction(packet_loss_rate);
1004 }
1005 });
1006}
1007
Niels Möller530ead42018-10-04 14:28:39 +02001008void ChannelSend::RegisterTransport(Transport* transport) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001009 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001010 rtc::CritScope cs(&_callbackCritSect);
1011 _transportPtr = transport;
1012}
1013
Niels Möller26815232018-11-16 09:32:40 +01001014// TODO(nisse): Delete always-true return value.
1015bool ChannelSend::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001016 // May be called on either worker thread or network thread.
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -08001017 if (media_transport_) {
1018 // Ignore RTCP packets while media transport is used.
1019 // Those packets should not arrive, but we are seeing occasional packets.
1020 return 0;
1021 }
1022
Niels Möller530ead42018-10-04 14:28:39 +02001023 // Deliver RTCP packet to RTP/RTCP module for parsing
1024 _rtpRtcpModule->IncomingRtcpPacket(data, length);
1025
1026 int64_t rtt = GetRTT();
1027 if (rtt == 0) {
1028 // Waiting for valid RTT.
Niels Möller26815232018-11-16 09:32:40 +01001029 return true;
Niels Möller530ead42018-10-04 14:28:39 +02001030 }
1031
1032 int64_t nack_window_ms = rtt;
1033 if (nack_window_ms < kMinRetransmissionWindowMs) {
1034 nack_window_ms = kMinRetransmissionWindowMs;
1035 } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
1036 nack_window_ms = kMaxRetransmissionWindowMs;
1037 }
1038 retransmission_rate_limiter_->SetWindowSize(nack_window_ms);
1039
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -08001040 OnReceivedRtt(rtt);
Niels Möller26815232018-11-16 09:32:40 +01001041 return true;
Niels Möller530ead42018-10-04 14:28:39 +02001042}
1043
1044void ChannelSend::SetInputMute(bool enable) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001045 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001046 rtc::CritScope cs(&volume_settings_critsect_);
1047 input_mute_ = enable;
1048}
1049
1050bool ChannelSend::InputMute() const {
1051 rtc::CritScope cs(&volume_settings_critsect_);
1052 return input_mute_;
1053}
1054
Niels Möller26815232018-11-16 09:32:40 +01001055bool ChannelSend::SendTelephoneEventOutband(int event, int duration_ms) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001056 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001057 RTC_DCHECK_LE(0, event);
1058 RTC_DCHECK_GE(255, event);
1059 RTC_DCHECK_LE(0, duration_ms);
1060 RTC_DCHECK_GE(65535, duration_ms);
1061 if (!Sending()) {
Niels Möller26815232018-11-16 09:32:40 +01001062 return false;
Niels Möller530ead42018-10-04 14:28:39 +02001063 }
1064 if (_rtpRtcpModule->SendTelephoneEventOutband(
1065 event, duration_ms, kTelephoneEventAttenuationdB) != 0) {
1066 RTC_DLOG(LS_ERROR) << "SendTelephoneEventOutband() failed to send event";
Niels Möller26815232018-11-16 09:32:40 +01001067 return false;
Niels Möller530ead42018-10-04 14:28:39 +02001068 }
Niels Möller26815232018-11-16 09:32:40 +01001069 return true;
Niels Möller530ead42018-10-04 14:28:39 +02001070}
1071
Niels Möller26815232018-11-16 09:32:40 +01001072bool ChannelSend::SetSendTelephoneEventPayloadType(int payload_type,
1073 int payload_frequency) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001074 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001075 RTC_DCHECK_LE(0, payload_type);
1076 RTC_DCHECK_GE(127, payload_type);
1077 CodecInst codec = {0};
1078 codec.pltype = payload_type;
1079 codec.plfreq = payload_frequency;
1080 memcpy(codec.plname, "telephone-event", 16);
1081 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1082 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1083 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1084 RTC_DLOG(LS_ERROR)
1085 << "SetSendTelephoneEventPayloadType() failed to register "
1086 "send payload type";
Niels Möller26815232018-11-16 09:32:40 +01001087 return false;
Niels Möller530ead42018-10-04 14:28:39 +02001088 }
1089 }
Niels Möller26815232018-11-16 09:32:40 +01001090 return true;
Niels Möller530ead42018-10-04 14:28:39 +02001091}
1092
Niels Möllerdced9f62018-11-19 10:27:07 +01001093void ChannelSend::SetLocalSSRC(uint32_t ssrc) {
1094 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller26815232018-11-16 09:32:40 +01001095 RTC_DCHECK(!channel_state_.Get().sending);
1096
Niels Möller7d76a312018-10-26 12:57:07 +02001097 if (media_transport_) {
1098 rtc::CritScope cs(&media_transport_lock_);
1099 media_transport_channel_id_ = ssrc;
1100 }
Niels Möller530ead42018-10-04 14:28:39 +02001101 _rtpRtcpModule->SetSSRC(ssrc);
Niels Möller530ead42018-10-04 14:28:39 +02001102}
1103
1104void ChannelSend::SetMid(const std::string& mid, int extension_id) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001105 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001106 int ret = SetSendRtpHeaderExtension(true, kRtpExtensionMid, extension_id);
1107 RTC_DCHECK_EQ(0, ret);
1108 _rtpRtcpModule->SetMid(mid);
1109}
1110
Johannes Kron9190b822018-10-29 11:22:05 +01001111void ChannelSend::SetExtmapAllowMixed(bool extmap_allow_mixed) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001112 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Johannes Kron9190b822018-10-29 11:22:05 +01001113 _rtpRtcpModule->SetExtmapAllowMixed(extmap_allow_mixed);
1114}
1115
Niels Möller26815232018-11-16 09:32:40 +01001116void ChannelSend::SetSendAudioLevelIndicationStatus(bool enable, int id) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001117 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001118 _includeAudioLevelIndication = enable;
Niels Möller26815232018-11-16 09:32:40 +01001119 int ret = SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
1120 RTC_DCHECK_EQ(0, ret);
Niels Möller530ead42018-10-04 14:28:39 +02001121}
1122
1123void ChannelSend::EnableSendTransportSequenceNumber(int id) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001124 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001125 int ret =
1126 SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id);
1127 RTC_DCHECK_EQ(0, ret);
1128}
1129
1130void ChannelSend::RegisterSenderCongestionControlObjects(
1131 RtpTransportControllerSendInterface* transport,
1132 RtcpBandwidthObserver* bandwidth_observer) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001133 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001134 RtpPacketSender* rtp_packet_sender = transport->packet_sender();
1135 TransportFeedbackObserver* transport_feedback_observer =
1136 transport->transport_feedback_observer();
1137 PacketRouter* packet_router = transport->packet_router();
1138
1139 RTC_DCHECK(rtp_packet_sender);
1140 RTC_DCHECK(transport_feedback_observer);
1141 RTC_DCHECK(packet_router);
1142 RTC_DCHECK(!packet_router_);
1143 rtcp_observer_->SetBandwidthObserver(bandwidth_observer);
1144 feedback_observer_proxy_->SetTransportFeedbackObserver(
1145 transport_feedback_observer);
1146 seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
1147 rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender);
1148 _rtpRtcpModule->SetStorePacketsStatus(true, 600);
1149 constexpr bool remb_candidate = false;
1150 packet_router->AddSendRtpModule(_rtpRtcpModule.get(), remb_candidate);
1151 packet_router_ = packet_router;
1152}
1153
1154void ChannelSend::ResetSenderCongestionControlObjects() {
Niels Möllerdced9f62018-11-19 10:27:07 +01001155 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001156 RTC_DCHECK(packet_router_);
1157 _rtpRtcpModule->SetStorePacketsStatus(false, 600);
1158 rtcp_observer_->SetBandwidthObserver(nullptr);
1159 feedback_observer_proxy_->SetTransportFeedbackObserver(nullptr);
1160 seq_num_allocator_proxy_->SetSequenceNumberAllocator(nullptr);
1161 packet_router_->RemoveSendRtpModule(_rtpRtcpModule.get());
1162 packet_router_ = nullptr;
1163 rtp_packet_sender_proxy_->SetPacketSender(nullptr);
1164}
1165
Niels Möller26815232018-11-16 09:32:40 +01001166void ChannelSend::SetRTCP_CNAME(absl::string_view c_name) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001167 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller26815232018-11-16 09:32:40 +01001168 // Note: SetCNAME() accepts a c string of length at most 255.
1169 const std::string c_name_limited(c_name.substr(0, 255));
1170 int ret = _rtpRtcpModule->SetCNAME(c_name_limited.c_str()) != 0;
1171 RTC_DCHECK_EQ(0, ret) << "SetRTCP_CNAME() failed to set RTCP CNAME";
Niels Möller530ead42018-10-04 14:28:39 +02001172}
1173
Niels Möller26815232018-11-16 09:32:40 +01001174std::vector<ReportBlock> ChannelSend::GetRemoteRTCPReportBlocks() const {
Niels Möllerdced9f62018-11-19 10:27:07 +01001175 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001176 // Get the report blocks from the latest received RTCP Sender or Receiver
1177 // Report. Each element in the vector contains the sender's SSRC and a
1178 // report block according to RFC 3550.
1179 std::vector<RTCPReportBlock> rtcp_report_blocks;
Niels Möller530ead42018-10-04 14:28:39 +02001180
Niels Möller26815232018-11-16 09:32:40 +01001181 int ret = _rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks);
1182 RTC_DCHECK_EQ(0, ret);
1183
1184 std::vector<ReportBlock> report_blocks;
Niels Möller530ead42018-10-04 14:28:39 +02001185
1186 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
1187 for (; it != rtcp_report_blocks.end(); ++it) {
1188 ReportBlock report_block;
1189 report_block.sender_SSRC = it->sender_ssrc;
1190 report_block.source_SSRC = it->source_ssrc;
1191 report_block.fraction_lost = it->fraction_lost;
1192 report_block.cumulative_num_packets_lost = it->packets_lost;
1193 report_block.extended_highest_sequence_number =
1194 it->extended_highest_sequence_number;
1195 report_block.interarrival_jitter = it->jitter;
1196 report_block.last_SR_timestamp = it->last_sender_report_timestamp;
1197 report_block.delay_since_last_SR = it->delay_since_last_sender_report;
Niels Möller26815232018-11-16 09:32:40 +01001198 report_blocks.push_back(report_block);
Niels Möller530ead42018-10-04 14:28:39 +02001199 }
Niels Möller26815232018-11-16 09:32:40 +01001200 return report_blocks;
Niels Möller530ead42018-10-04 14:28:39 +02001201}
1202
Niels Möller26815232018-11-16 09:32:40 +01001203CallSendStatistics ChannelSend::GetRTCPStatistics() const {
Niels Möllerdced9f62018-11-19 10:27:07 +01001204 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller26815232018-11-16 09:32:40 +01001205 CallSendStatistics stats = {0};
Niels Möller530ead42018-10-04 14:28:39 +02001206 stats.rttMs = GetRTT();
1207
Niels Möller530ead42018-10-04 14:28:39 +02001208 size_t bytesSent(0);
1209 uint32_t packetsSent(0);
1210
1211 if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) {
1212 RTC_DLOG(LS_WARNING)
1213 << "GetRTPStatistics() failed to retrieve RTP datacounters"
1214 << " => output will not be complete";
1215 }
1216
1217 stats.bytesSent = bytesSent;
1218 stats.packetsSent = packetsSent;
1219
Niels Möller26815232018-11-16 09:32:40 +01001220 return stats;
Niels Möller530ead42018-10-04 14:28:39 +02001221}
1222
Niels Möllerdced9f62018-11-19 10:27:07 +01001223void ChannelSend::SetNACKStatus(bool enable, int max_packets) {
1224 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001225 // None of these functions can fail.
1226 if (enable)
Niels Möllerdced9f62018-11-19 10:27:07 +01001227 audio_coding_->EnableNack(max_packets);
Niels Möller530ead42018-10-04 14:28:39 +02001228 else
1229 audio_coding_->DisableNack();
1230}
1231
1232// Called when we are missing one or more packets.
1233int ChannelSend::ResendPackets(const uint16_t* sequence_numbers, int length) {
1234 return _rtpRtcpModule->SendNACK(sequence_numbers, length);
1235}
1236
1237void ChannelSend::ProcessAndEncodeAudio(
1238 std::unique_ptr<AudioFrame> audio_frame) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001239 RTC_DCHECK_RUNS_SERIALIZED(&audio_thread_race_checker_);
Niels Möller530ead42018-10-04 14:28:39 +02001240 // Avoid posting any new tasks if sending was already stopped in StopSend().
1241 rtc::CritScope cs(&encoder_queue_lock_);
1242 if (!encoder_queue_is_active_) {
1243 return;
1244 }
1245 // Profile time between when the audio frame is added to the task queue and
1246 // when the task is actually executed.
1247 audio_frame->UpdateProfileTimeStamp();
1248 encoder_queue_->PostTask(std::unique_ptr<rtc::QueuedTask>(
1249 new ProcessAndEncodeAudioTask(std::move(audio_frame), this)));
1250}
1251
1252void ChannelSend::ProcessAndEncodeAudioOnTaskQueue(AudioFrame* audio_input) {
1253 RTC_DCHECK_RUN_ON(encoder_queue_);
1254 RTC_DCHECK_GT(audio_input->samples_per_channel_, 0);
1255 RTC_DCHECK_LE(audio_input->num_channels_, 2);
1256
1257 // Measure time between when the audio frame is added to the task queue and
1258 // when the task is actually executed. Goal is to keep track of unwanted
1259 // extra latency added by the task queue.
1260 RTC_HISTOGRAM_COUNTS_10000("WebRTC.Audio.EncodingTaskQueueLatencyMs",
1261 audio_input->ElapsedProfileTimeMs());
1262
1263 bool is_muted = InputMute();
1264 AudioFrameOperations::Mute(audio_input, previous_frame_muted_, is_muted);
1265
1266 if (_includeAudioLevelIndication) {
1267 size_t length =
1268 audio_input->samples_per_channel_ * audio_input->num_channels_;
1269 RTC_CHECK_LE(length, AudioFrame::kMaxDataSizeBytes);
1270 if (is_muted && previous_frame_muted_) {
1271 rms_level_.AnalyzeMuted(length);
1272 } else {
1273 rms_level_.Analyze(
1274 rtc::ArrayView<const int16_t>(audio_input->data(), length));
1275 }
1276 }
1277 previous_frame_muted_ = is_muted;
1278
1279 // Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
1280
1281 // The ACM resamples internally.
1282 audio_input->timestamp_ = _timeStamp;
1283 // This call will trigger AudioPacketizationCallback::SendData if encoding
1284 // is done and payload is ready for packetization and transmission.
1285 // Otherwise, it will return without invoking the callback.
1286 if (audio_coding_->Add10MsData(*audio_input) < 0) {
1287 RTC_DLOG(LS_ERROR) << "ACM::Add10MsData() failed.";
1288 return;
1289 }
1290
1291 _timeStamp += static_cast<uint32_t>(audio_input->samples_per_channel_);
1292}
1293
1294void ChannelSend::UpdateOverheadForEncoder() {
1295 size_t overhead_per_packet =
1296 transport_overhead_per_packet_ + rtp_overhead_per_packet_;
1297 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1298 if (*encoder) {
1299 (*encoder)->OnReceivedOverhead(overhead_per_packet);
1300 }
1301 });
1302}
1303
1304void ChannelSend::SetTransportOverhead(size_t transport_overhead_per_packet) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001305 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001306 rtc::CritScope cs(&overhead_per_packet_lock_);
1307 transport_overhead_per_packet_ = transport_overhead_per_packet;
1308 UpdateOverheadForEncoder();
1309}
1310
1311// TODO(solenberg): Make AudioSendStream an OverheadObserver instead.
1312void ChannelSend::OnOverheadChanged(size_t overhead_bytes_per_packet) {
1313 rtc::CritScope cs(&overhead_per_packet_lock_);
1314 rtp_overhead_per_packet_ = overhead_bytes_per_packet;
1315 UpdateOverheadForEncoder();
1316}
1317
1318ANAStats ChannelSend::GetANAStatistics() const {
Niels Möllerdced9f62018-11-19 10:27:07 +01001319 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001320 return audio_coding_->GetANAStats();
1321}
1322
1323RtpRtcp* ChannelSend::GetRtpRtcp() const {
Niels Möllerdced9f62018-11-19 10:27:07 +01001324 RTC_DCHECK(module_process_thread_checker_.CalledOnValidThread());
Niels Möller530ead42018-10-04 14:28:39 +02001325 return _rtpRtcpModule.get();
1326}
1327
1328int ChannelSend::SetSendRtpHeaderExtension(bool enable,
1329 RTPExtensionType type,
Niels Möller26815232018-11-16 09:32:40 +01001330 int id) {
Niels Möller530ead42018-10-04 14:28:39 +02001331 int error = 0;
1332 _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
1333 if (enable) {
Niels Möller26815232018-11-16 09:32:40 +01001334 // TODO(nisse): RtpRtcp::RegisterSendRtpHeaderExtension to take an int
1335 // argument. Currently it wants an uint8_t.
1336 error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(
1337 type, rtc::dchecked_cast<uint8_t>(id));
Niels Möller530ead42018-10-04 14:28:39 +02001338 }
1339 return error;
1340}
1341
1342int ChannelSend::GetRtpTimestampRateHz() const {
1343 const auto format = audio_coding_->ReceiveFormat();
1344 // Default to the playout frequency if we've not gotten any packets yet.
1345 // TODO(ossu): Zero clockrate can only happen if we've added an external
1346 // decoder for a format we don't support internally. Remove once that way of
1347 // adding decoders is gone!
1348 return (format && format->clockrate_hz != 0)
1349 ? format->clockrate_hz
1350 : audio_coding_->PlayoutFrequency();
1351}
1352
1353int64_t ChannelSend::GetRTT() const {
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -08001354 if (media_transport_) {
1355 // GetRTT is generally used in the RTCP codepath, where media transport is
1356 // not present and so it shouldn't be needed. But it's also invoked in
1357 // 'GetStats' method, and for now returning media transport RTT here gives
1358 // us "free" rtt stats for media transport.
1359 auto target_rate = media_transport_->GetLatestTargetTransferRate();
1360 if (target_rate.has_value()) {
1361 return target_rate.value().network_estimate.round_trip_time.ms();
1362 }
1363
1364 return 0;
1365 }
Niels Möller530ead42018-10-04 14:28:39 +02001366 RtcpMode method = _rtpRtcpModule->RTCP();
1367 if (method == RtcpMode::kOff) {
1368 return 0;
1369 }
1370 std::vector<RTCPReportBlock> report_blocks;
1371 _rtpRtcpModule->RemoteRTCPStat(&report_blocks);
1372
1373 if (report_blocks.empty()) {
1374 return 0;
1375 }
1376
1377 int64_t rtt = 0;
1378 int64_t avg_rtt = 0;
1379 int64_t max_rtt = 0;
1380 int64_t min_rtt = 0;
1381 // We don't know in advance the remote ssrc used by the other end's receiver
1382 // reports, so use the SSRC of the first report block for calculating the RTT.
1383 if (_rtpRtcpModule->RTT(report_blocks[0].sender_ssrc, &rtt, &avg_rtt,
1384 &min_rtt, &max_rtt) != 0) {
1385 return 0;
1386 }
1387 return rtt;
1388}
1389
Benjamin Wright78410ad2018-10-25 09:52:57 -07001390void ChannelSend::SetFrameEncryptor(
1391 rtc::scoped_refptr<FrameEncryptorInterface> frame_encryptor) {
Niels Möllerdced9f62018-11-19 10:27:07 +01001392 RTC_DCHECK(worker_thread_checker_.CalledOnValidThread());
Benjamin Wright84583f62018-10-04 14:22:34 -07001393 rtc::CritScope cs(&encoder_queue_lock_);
1394 if (encoder_queue_is_active_) {
1395 encoder_queue_->PostTask([this, frame_encryptor]() {
Benjamin Wright78410ad2018-10-25 09:52:57 -07001396 this->frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -07001397 });
1398 } else {
Benjamin Wright78410ad2018-10-25 09:52:57 -07001399 frame_encryptor_ = std::move(frame_encryptor);
Benjamin Wright84583f62018-10-04 14:22:34 -07001400 }
1401}
1402
Piotr (Peter) Slatala179a3922018-11-16 09:57:58 -08001403void ChannelSend::OnTargetTransferRate(TargetTransferRate rate) {
1404 RTC_DCHECK(media_transport_);
1405 OnReceivedRtt(rate.network_estimate.round_trip_time.ms());
1406}
1407
1408void ChannelSend::OnReceivedRtt(int64_t rtt_ms) {
1409 // Invoke audio encoders OnReceivedRtt().
1410 audio_coding_->ModifyEncoder(
1411 [rtt_ms](std::unique_ptr<AudioEncoder>* encoder) {
1412 if (*encoder) {
1413 (*encoder)->OnReceivedRtt(rtt_ms);
1414 }
1415 });
1416}
1417
Niels Möllerdced9f62018-11-19 10:27:07 +01001418} // namespace
1419
1420std::unique_ptr<ChannelSendInterface> CreateChannelSend(
1421 rtc::TaskQueue* encoder_queue,
1422 ProcessThread* module_process_thread,
1423 MediaTransportInterface* media_transport,
1424 RtcpRttStats* rtcp_rtt_stats,
1425 RtcEventLog* rtc_event_log,
1426 FrameEncryptorInterface* frame_encryptor,
1427 const webrtc::CryptoOptions& crypto_options,
1428 bool extmap_allow_mixed,
1429 int rtcp_report_interval_ms) {
1430 return absl::make_unique<ChannelSend>(
1431 encoder_queue, module_process_thread, media_transport, rtcp_rtt_stats,
1432 rtc_event_log, frame_encryptor, crypto_options, extmap_allow_mixed,
1433 rtcp_report_interval_ms);
1434}
1435
Niels Möller530ead42018-10-04 14:28:39 +02001436} // namespace voe
1437} // namespace webrtc