blob: 14ce5da7fb554aefe308f772fe0ac4cad15b7ae0 [file] [log] [blame]
niklase@google.com470e71d2011-07-07 08:21:25 +00001/*
henrika@webrtc.org2919e952012-01-31 08:45:03 +00002 * Copyright (c) 2012 The WebRTC project authors. All Rights Reserved.
niklase@google.com470e71d2011-07-07 08:21:25 +00003 *
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
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +000011#include "webrtc/voice_engine/channel.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000012
Henrik Lundin64dad832015-05-11 12:44:23 +020013#include <algorithm>
Tommif888bb52015-12-12 01:37:01 +010014#include <utility>
Henrik Lundin64dad832015-05-11 12:44:23 +020015
aleloi6321b492016-12-05 01:46:09 -080016#include "webrtc/audio/utility/audio_frame_operations.h"
henrik.lundin50499422016-11-29 04:26:24 -080017#include "webrtc/base/array_view.h"
Ivo Creusenae856f22015-09-17 16:30:16 +020018#include "webrtc/base/checks.h"
tommi31fc21f2016-01-21 10:37:37 -080019#include "webrtc/base/criticalsection.h"
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +000020#include "webrtc/base/format_macros.h"
pbosad856222015-11-27 09:48:36 -080021#include "webrtc/base/logging.h"
Erik Språng737336d2016-07-29 12:59:36 +020022#include "webrtc/base/rate_limiter.h"
Stefan Holmerb86d4e42015-12-07 10:26:18 +010023#include "webrtc/base/thread_checker.h"
wu@webrtc.org94454b72014-06-05 20:34:08 +000024#include "webrtc/base/timeutils.h"
Henrik Lundin64dad832015-05-11 12:44:23 +020025#include "webrtc/config.h"
skvladcc91d282016-10-03 18:31:22 -070026#include "webrtc/logging/rtc_event_log/rtc_event_log.h"
kwibergda2bf4e2016-10-24 13:47:09 -070027#include "webrtc/modules/audio_coding/codecs/audio_format_conversion.h"
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +000028#include "webrtc/modules/audio_device/include/audio_device.h"
29#include "webrtc/modules/audio_processing/include/audio_processing.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010030#include "webrtc/modules/include/module_common_types.h"
Stefan Holmerb86d4e42015-12-07 10:26:18 +010031#include "webrtc/modules/pacing/packet_router.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010032#include "webrtc/modules/rtp_rtcp/include/receive_statistics.h"
33#include "webrtc/modules/rtp_rtcp/include/rtp_payload_registry.h"
34#include "webrtc/modules/rtp_rtcp/include/rtp_receiver.h"
nisse657bab22017-02-21 06:28:10 -080035#include "webrtc/modules/rtp_rtcp/source/rtp_packet_received.h"
wu@webrtc.org822fbd82013-08-15 23:38:54 +000036#include "webrtc/modules/rtp_rtcp/source/rtp_receiver_strategy.h"
Henrik Kjellanderff761fb2015-11-04 08:31:52 +010037#include "webrtc/modules/utility/include/process_thread.h"
Henrik Kjellander98f53512015-10-28 18:17:40 +010038#include "webrtc/system_wrappers/include/trace.h"
turaj@webrtc.org6388c3e2013-02-12 21:42:18 +000039#include "webrtc/voice_engine/include/voe_rtp_rtcp.h"
40#include "webrtc/voice_engine/output_mixer.h"
41#include "webrtc/voice_engine/statistics.h"
42#include "webrtc/voice_engine/transmit_mixer.h"
43#include "webrtc/voice_engine/utility.h"
niklase@google.com470e71d2011-07-07 08:21:25 +000044
andrew@webrtc.org50419b02012-11-14 19:07:54 +000045namespace webrtc {
46namespace voe {
niklase@google.com470e71d2011-07-07 08:21:25 +000047
kwibergc8d071e2016-04-06 12:22:38 -070048namespace {
49
Erik Språng737336d2016-07-29 12:59:36 +020050constexpr int64_t kMaxRetransmissionWindowMs = 1000;
51constexpr int64_t kMinRetransmissionWindowMs = 30;
52
kwibergc8d071e2016-04-06 12:22:38 -070053} // namespace
54
solenberg8842c3e2016-03-11 03:06:41 -080055const int kTelephoneEventAttenuationdB = 10;
56
ivoc14d5dbe2016-07-04 07:06:55 -070057class RtcEventLogProxy final : public webrtc::RtcEventLog {
58 public:
59 RtcEventLogProxy() : event_log_(nullptr) {}
60
61 bool StartLogging(const std::string& file_name,
62 int64_t max_size_bytes) override {
63 RTC_NOTREACHED();
64 return false;
65 }
66
67 bool StartLogging(rtc::PlatformFile log_file,
68 int64_t max_size_bytes) override {
69 RTC_NOTREACHED();
70 return false;
71 }
72
73 void StopLogging() override { RTC_NOTREACHED(); }
74
75 void LogVideoReceiveStreamConfig(
76 const webrtc::VideoReceiveStream::Config& config) override {
77 rtc::CritScope lock(&crit_);
78 if (event_log_) {
79 event_log_->LogVideoReceiveStreamConfig(config);
80 }
81 }
82
83 void LogVideoSendStreamConfig(
84 const webrtc::VideoSendStream::Config& config) override {
85 rtc::CritScope lock(&crit_);
86 if (event_log_) {
87 event_log_->LogVideoSendStreamConfig(config);
88 }
89 }
90
ivoce0928d82016-10-10 05:12:51 -070091 void LogAudioReceiveStreamConfig(
92 const webrtc::AudioReceiveStream::Config& config) override {
93 rtc::CritScope lock(&crit_);
94 if (event_log_) {
95 event_log_->LogAudioReceiveStreamConfig(config);
96 }
97 }
98
99 void LogAudioSendStreamConfig(
100 const webrtc::AudioSendStream::Config& config) override {
101 rtc::CritScope lock(&crit_);
102 if (event_log_) {
103 event_log_->LogAudioSendStreamConfig(config);
104 }
105 }
106
ivoc14d5dbe2016-07-04 07:06:55 -0700107 void LogRtpHeader(webrtc::PacketDirection direction,
108 webrtc::MediaType media_type,
109 const uint8_t* header,
110 size_t packet_length) override {
111 rtc::CritScope lock(&crit_);
112 if (event_log_) {
113 event_log_->LogRtpHeader(direction, media_type, header, packet_length);
114 }
115 }
116
117 void LogRtcpPacket(webrtc::PacketDirection direction,
118 webrtc::MediaType media_type,
119 const uint8_t* packet,
120 size_t length) override {
121 rtc::CritScope lock(&crit_);
122 if (event_log_) {
123 event_log_->LogRtcpPacket(direction, media_type, packet, length);
124 }
125 }
126
127 void LogAudioPlayout(uint32_t ssrc) override {
128 rtc::CritScope lock(&crit_);
129 if (event_log_) {
130 event_log_->LogAudioPlayout(ssrc);
131 }
132 }
133
terelius424e6cf2017-02-20 05:14:41 -0800134 void LogLossBasedBweUpdate(int32_t bitrate_bps,
ivoc14d5dbe2016-07-04 07:06:55 -0700135 uint8_t fraction_loss,
136 int32_t total_packets) override {
137 rtc::CritScope lock(&crit_);
138 if (event_log_) {
terelius424e6cf2017-02-20 05:14:41 -0800139 event_log_->LogLossBasedBweUpdate(bitrate_bps, fraction_loss,
140 total_packets);
ivoc14d5dbe2016-07-04 07:06:55 -0700141 }
142 }
143
terelius424e6cf2017-02-20 05:14:41 -0800144 void LogDelayBasedBweUpdate(int32_t bitrate_bps,
terelius0baf55d2017-02-17 03:38:28 -0800145 BandwidthUsage detector_state) override {
146 rtc::CritScope lock(&crit_);
147 if (event_log_) {
terelius424e6cf2017-02-20 05:14:41 -0800148 event_log_->LogDelayBasedBweUpdate(bitrate_bps, detector_state);
terelius0baf55d2017-02-17 03:38:28 -0800149 }
150 }
151
minyue4b7c9522017-01-24 04:54:59 -0800152 void LogAudioNetworkAdaptation(
153 const AudioNetworkAdaptor::EncoderRuntimeConfig& config) override {
154 rtc::CritScope lock(&crit_);
155 if (event_log_) {
156 event_log_->LogAudioNetworkAdaptation(config);
157 }
158 }
159
ivoc14d5dbe2016-07-04 07:06:55 -0700160 void SetEventLog(RtcEventLog* event_log) {
161 rtc::CritScope lock(&crit_);
162 event_log_ = event_log;
163 }
164
165 private:
166 rtc::CriticalSection crit_;
167 RtcEventLog* event_log_ GUARDED_BY(crit_);
168 RTC_DISALLOW_COPY_AND_ASSIGN(RtcEventLogProxy);
169};
170
michaelt9332b7d2016-11-30 07:51:13 -0800171class RtcpRttStatsProxy final : public RtcpRttStats {
172 public:
173 RtcpRttStatsProxy() : rtcp_rtt_stats_(nullptr) {}
174
175 void OnRttUpdate(int64_t rtt) override {
176 rtc::CritScope lock(&crit_);
177 if (rtcp_rtt_stats_)
178 rtcp_rtt_stats_->OnRttUpdate(rtt);
179 }
180
181 int64_t LastProcessedRtt() const override {
182 rtc::CritScope lock(&crit_);
183 if (!rtcp_rtt_stats_)
184 return 0;
185 return rtcp_rtt_stats_->LastProcessedRtt();
186 }
187
188 void SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
189 rtc::CritScope lock(&crit_);
190 rtcp_rtt_stats_ = rtcp_rtt_stats;
191 }
192
193 private:
194 rtc::CriticalSection crit_;
195 RtcpRttStats* rtcp_rtt_stats_ GUARDED_BY(crit_);
196 RTC_DISALLOW_COPY_AND_ASSIGN(RtcpRttStatsProxy);
197};
198
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100199class TransportFeedbackProxy : public TransportFeedbackObserver {
200 public:
201 TransportFeedbackProxy() : feedback_observer_(nullptr) {
202 pacer_thread_.DetachFromThread();
203 network_thread_.DetachFromThread();
204 }
205
206 void SetTransportFeedbackObserver(
207 TransportFeedbackObserver* feedback_observer) {
208 RTC_DCHECK(thread_checker_.CalledOnValidThread());
209 rtc::CritScope lock(&crit_);
210 feedback_observer_ = feedback_observer;
211 }
212
213 // Implements TransportFeedbackObserver.
214 void AddPacket(uint16_t sequence_number,
215 size_t length,
philipela1ed0b32016-06-01 06:31:17 -0700216 int probe_cluster_id) override {
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100217 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
218 rtc::CritScope lock(&crit_);
219 if (feedback_observer_)
pbos2169d8b2016-06-20 11:53:02 -0700220 feedback_observer_->AddPacket(sequence_number, length, probe_cluster_id);
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100221 }
222 void OnTransportFeedback(const rtcp::TransportFeedback& feedback) override {
223 RTC_DCHECK(network_thread_.CalledOnValidThread());
224 rtc::CritScope lock(&crit_);
michaelt9960bb12016-10-18 09:40:34 -0700225 if (feedback_observer_)
226 feedback_observer_->OnTransportFeedback(feedback);
Stefan Holmer60e43462016-09-07 09:58:20 +0200227 }
228 std::vector<PacketInfo> GetTransportFeedbackVector() const override {
229 RTC_NOTREACHED();
230 return std::vector<PacketInfo>();
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100231 }
232
233 private:
234 rtc::CriticalSection crit_;
235 rtc::ThreadChecker thread_checker_;
236 rtc::ThreadChecker pacer_thread_;
237 rtc::ThreadChecker network_thread_;
238 TransportFeedbackObserver* feedback_observer_ GUARDED_BY(&crit_);
239};
240
241class TransportSequenceNumberProxy : public TransportSequenceNumberAllocator {
242 public:
243 TransportSequenceNumberProxy() : seq_num_allocator_(nullptr) {
244 pacer_thread_.DetachFromThread();
245 }
246
247 void SetSequenceNumberAllocator(
248 TransportSequenceNumberAllocator* seq_num_allocator) {
249 RTC_DCHECK(thread_checker_.CalledOnValidThread());
250 rtc::CritScope lock(&crit_);
251 seq_num_allocator_ = seq_num_allocator;
252 }
253
254 // Implements TransportSequenceNumberAllocator.
255 uint16_t AllocateSequenceNumber() override {
256 RTC_DCHECK(pacer_thread_.CalledOnValidThread());
257 rtc::CritScope lock(&crit_);
258 if (!seq_num_allocator_)
259 return 0;
260 return seq_num_allocator_->AllocateSequenceNumber();
261 }
262
263 private:
264 rtc::CriticalSection crit_;
265 rtc::ThreadChecker thread_checker_;
266 rtc::ThreadChecker pacer_thread_;
267 TransportSequenceNumberAllocator* seq_num_allocator_ GUARDED_BY(&crit_);
268};
269
270class RtpPacketSenderProxy : public RtpPacketSender {
271 public:
kwiberg55b97fe2016-01-28 05:22:45 -0800272 RtpPacketSenderProxy() : rtp_packet_sender_(nullptr) {}
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100273
274 void SetPacketSender(RtpPacketSender* rtp_packet_sender) {
275 RTC_DCHECK(thread_checker_.CalledOnValidThread());
276 rtc::CritScope lock(&crit_);
277 rtp_packet_sender_ = rtp_packet_sender;
278 }
279
280 // Implements RtpPacketSender.
281 void InsertPacket(Priority priority,
282 uint32_t ssrc,
283 uint16_t sequence_number,
284 int64_t capture_time_ms,
285 size_t bytes,
286 bool retransmission) override {
287 rtc::CritScope lock(&crit_);
288 if (rtp_packet_sender_) {
289 rtp_packet_sender_->InsertPacket(priority, ssrc, sequence_number,
290 capture_time_ms, bytes, retransmission);
291 }
292 }
293
294 private:
295 rtc::ThreadChecker thread_checker_;
296 rtc::CriticalSection crit_;
297 RtpPacketSender* rtp_packet_sender_ GUARDED_BY(&crit_);
298};
299
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000300class VoERtcpObserver : public RtcpBandwidthObserver {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000301 public:
stefan7de8d642017-02-07 07:14:08 -0800302 explicit VoERtcpObserver(Channel* owner)
303 : owner_(owner), bandwidth_observer_(nullptr) {}
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000304 virtual ~VoERtcpObserver() {}
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000305
stefan7de8d642017-02-07 07:14:08 -0800306 void SetBandwidthObserver(RtcpBandwidthObserver* bandwidth_observer) {
307 rtc::CritScope lock(&crit_);
308 bandwidth_observer_ = bandwidth_observer;
309 }
310
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000311 void OnReceivedEstimatedBitrate(uint32_t bitrate) override {
stefan7de8d642017-02-07 07:14:08 -0800312 rtc::CritScope lock(&crit_);
313 if (bandwidth_observer_) {
314 bandwidth_observer_->OnReceivedEstimatedBitrate(bitrate);
315 }
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000316 }
317
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000318 void OnReceivedRtcpReceiverReport(const ReportBlockList& report_blocks,
319 int64_t rtt,
320 int64_t now_ms) override {
stefan7de8d642017-02-07 07:14:08 -0800321 {
322 rtc::CritScope lock(&crit_);
323 if (bandwidth_observer_) {
324 bandwidth_observer_->OnReceivedRtcpReceiverReport(report_blocks, rtt,
325 now_ms);
326 }
327 }
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000328 // TODO(mflodman): Do we need to aggregate reports here or can we jut send
329 // what we get? I.e. do we ever get multiple reports bundled into one RTCP
330 // report for VoiceEngine?
331 if (report_blocks.empty())
332 return;
333
334 int fraction_lost_aggregate = 0;
335 int total_number_of_packets = 0;
336
337 // If receiving multiple report blocks, calculate the weighted average based
338 // on the number of packets a report refers to.
339 for (ReportBlockList::const_iterator block_it = report_blocks.begin();
340 block_it != report_blocks.end(); ++block_it) {
341 // Find the previous extended high sequence number for this remote SSRC,
342 // to calculate the number of RTP packets this report refers to. Ignore if
343 // we haven't seen this SSRC before.
344 std::map<uint32_t, uint32_t>::iterator seq_num_it =
345 extended_max_sequence_number_.find(block_it->sourceSSRC);
346 int number_of_packets = 0;
347 if (seq_num_it != extended_max_sequence_number_.end()) {
348 number_of_packets = block_it->extendedHighSeqNum - seq_num_it->second;
349 }
350 fraction_lost_aggregate += number_of_packets * block_it->fractionLost;
351 total_number_of_packets += number_of_packets;
352
353 extended_max_sequence_number_[block_it->sourceSSRC] =
354 block_it->extendedHighSeqNum;
355 }
356 int weighted_fraction_lost = 0;
357 if (total_number_of_packets > 0) {
kwiberg55b97fe2016-01-28 05:22:45 -0800358 weighted_fraction_lost =
359 (fraction_lost_aggregate + total_number_of_packets / 2) /
360 total_number_of_packets;
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000361 }
362 owner_->OnIncomingFractionLoss(weighted_fraction_lost);
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000363 }
364
365 private:
366 Channel* owner_;
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +0000367 // Maps remote side ssrc to extended highest sequence number received.
368 std::map<uint32_t, uint32_t> extended_max_sequence_number_;
stefan7de8d642017-02-07 07:14:08 -0800369 rtc::CriticalSection crit_;
370 RtcpBandwidthObserver* bandwidth_observer_ GUARDED_BY(crit_);
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +0000371};
372
kwiberg55b97fe2016-01-28 05:22:45 -0800373int32_t Channel::SendData(FrameType frameType,
374 uint8_t payloadType,
375 uint32_t timeStamp,
376 const uint8_t* payloadData,
377 size_t payloadSize,
378 const RTPFragmentationHeader* fragmentation) {
379 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
380 "Channel::SendData(frameType=%u, payloadType=%u, timeStamp=%u,"
381 " payloadSize=%" PRIuS ", fragmentation=0x%x)",
382 frameType, payloadType, timeStamp, payloadSize, fragmentation);
niklase@google.com470e71d2011-07-07 08:21:25 +0000383
kwiberg55b97fe2016-01-28 05:22:45 -0800384 if (_includeAudioLevelIndication) {
385 // Store current audio level in the RTP/RTCP module.
386 // The level will be used in combination with voice-activity state
387 // (frameType) to add an RTP header extension
henrik.lundin50499422016-11-29 04:26:24 -0800388 _rtpRtcpModule->SetAudioLevel(rms_level_.Average());
kwiberg55b97fe2016-01-28 05:22:45 -0800389 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000390
kwiberg55b97fe2016-01-28 05:22:45 -0800391 // Push data from ACM to RTP/RTCP-module to deliver audio frame for
392 // packetization.
393 // This call will trigger Transport::SendPacket() from the RTP/RTCP module.
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700394 if (!_rtpRtcpModule->SendOutgoingData(
kwiberg55b97fe2016-01-28 05:22:45 -0800395 (FrameType&)frameType, payloadType, timeStamp,
396 // Leaving the time when this frame was
397 // received from the capture device as
398 // undefined for voice for now.
Sergey Ulanov525df3f2016-08-02 17:46:41 -0700399 -1, payloadData, payloadSize, fragmentation, nullptr, nullptr)) {
kwiberg55b97fe2016-01-28 05:22:45 -0800400 _engineStatisticsPtr->SetLastError(
401 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
402 "Channel::SendData() failed to send data to RTP/RTCP module");
403 return -1;
404 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000405
kwiberg55b97fe2016-01-28 05:22:45 -0800406 _lastLocalTimeStamp = timeStamp;
407 _lastPayloadType = payloadType;
niklase@google.com470e71d2011-07-07 08:21:25 +0000408
kwiberg55b97fe2016-01-28 05:22:45 -0800409 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000410}
411
kwiberg55b97fe2016-01-28 05:22:45 -0800412int32_t Channel::InFrameType(FrameType frame_type) {
413 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
414 "Channel::InFrameType(frame_type=%d)", frame_type);
niklase@google.com470e71d2011-07-07 08:21:25 +0000415
kwiberg55b97fe2016-01-28 05:22:45 -0800416 rtc::CritScope cs(&_callbackCritSect);
417 _sendFrameType = (frame_type == kAudioFrameSpeech);
418 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000419}
420
stefan1d8a5062015-10-02 03:39:33 -0700421bool Channel::SendRtp(const uint8_t* data,
422 size_t len,
423 const PacketOptions& options) {
kwiberg55b97fe2016-01-28 05:22:45 -0800424 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
425 "Channel::SendPacket(channel=%d, len=%" PRIuS ")", len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000426
kwiberg55b97fe2016-01-28 05:22:45 -0800427 rtc::CritScope cs(&_callbackCritSect);
wu@webrtc.orgfb648da2013-10-18 21:10:51 +0000428
kwiberg55b97fe2016-01-28 05:22:45 -0800429 if (_transportPtr == NULL) {
430 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
431 "Channel::SendPacket() failed to send RTP packet due to"
432 " invalid transport object");
433 return false;
434 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000435
kwiberg55b97fe2016-01-28 05:22:45 -0800436 uint8_t* bufferToSendPtr = (uint8_t*)data;
437 size_t bufferLength = len;
niklase@google.com470e71d2011-07-07 08:21:25 +0000438
kwiberg55b97fe2016-01-28 05:22:45 -0800439 if (!_transportPtr->SendRtp(bufferToSendPtr, bufferLength, options)) {
440 std::string transport_name =
441 _externalTransport ? "external transport" : "WebRtc sockets";
442 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
443 "Channel::SendPacket() RTP transmission using %s failed",
444 transport_name.c_str());
445 return false;
446 }
447 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000448}
449
kwiberg55b97fe2016-01-28 05:22:45 -0800450bool Channel::SendRtcp(const uint8_t* data, size_t len) {
451 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
452 "Channel::SendRtcp(len=%" PRIuS ")", len);
niklase@google.com470e71d2011-07-07 08:21:25 +0000453
kwiberg55b97fe2016-01-28 05:22:45 -0800454 rtc::CritScope cs(&_callbackCritSect);
455 if (_transportPtr == NULL) {
456 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
457 "Channel::SendRtcp() failed to send RTCP packet"
458 " due to invalid transport object");
459 return false;
460 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000461
kwiberg55b97fe2016-01-28 05:22:45 -0800462 uint8_t* bufferToSendPtr = (uint8_t*)data;
463 size_t bufferLength = len;
niklase@google.com470e71d2011-07-07 08:21:25 +0000464
kwiberg55b97fe2016-01-28 05:22:45 -0800465 int n = _transportPtr->SendRtcp(bufferToSendPtr, bufferLength);
466 if (n < 0) {
467 std::string transport_name =
468 _externalTransport ? "external transport" : "WebRtc sockets";
469 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
470 "Channel::SendRtcp() transmission using %s failed",
471 transport_name.c_str());
472 return false;
473 }
474 return true;
niklase@google.com470e71d2011-07-07 08:21:25 +0000475}
476
kwiberg55b97fe2016-01-28 05:22:45 -0800477void Channel::OnIncomingSSRCChanged(uint32_t ssrc) {
478 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
479 "Channel::OnIncomingSSRCChanged(SSRC=%d)", ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000480
kwiberg55b97fe2016-01-28 05:22:45 -0800481 // Update ssrc so that NTP for AV sync can be updated.
482 _rtpRtcpModule->SetRemoteSSRC(ssrc);
niklase@google.com470e71d2011-07-07 08:21:25 +0000483}
484
Peter Boströmac547a62015-09-17 23:03:57 +0200485void Channel::OnIncomingCSRCChanged(uint32_t CSRC, bool added) {
486 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
487 "Channel::OnIncomingCSRCChanged(CSRC=%d, added=%d)", CSRC,
488 added);
niklase@google.com470e71d2011-07-07 08:21:25 +0000489}
490
Peter Boströmac547a62015-09-17 23:03:57 +0200491int32_t Channel::OnInitializeDecoder(
pbos@webrtc.org92135212013-05-14 08:31:39 +0000492 int8_t payloadType,
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +0000493 const char payloadName[RTP_PAYLOAD_NAME_SIZE],
pbos@webrtc.org92135212013-05-14 08:31:39 +0000494 int frequency,
Peter Kasting69558702016-01-12 16:26:35 -0800495 size_t channels,
Peter Boströmac547a62015-09-17 23:03:57 +0200496 uint32_t rate) {
kwiberg55b97fe2016-01-28 05:22:45 -0800497 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
498 "Channel::OnInitializeDecoder(payloadType=%d, "
499 "payloadName=%s, frequency=%u, channels=%" PRIuS ", rate=%u)",
500 payloadType, payloadName, frequency, channels, rate);
niklase@google.com470e71d2011-07-07 08:21:25 +0000501
kwiberg55b97fe2016-01-28 05:22:45 -0800502 CodecInst receiveCodec = {0};
503 CodecInst dummyCodec = {0};
niklase@google.com470e71d2011-07-07 08:21:25 +0000504
kwiberg55b97fe2016-01-28 05:22:45 -0800505 receiveCodec.pltype = payloadType;
506 receiveCodec.plfreq = frequency;
507 receiveCodec.channels = channels;
508 receiveCodec.rate = rate;
509 strncpy(receiveCodec.plname, payloadName, RTP_PAYLOAD_NAME_SIZE - 1);
andrew@webrtc.orgae1a58b2013-01-22 04:44:30 +0000510
kwiberg55b97fe2016-01-28 05:22:45 -0800511 audio_coding_->Codec(payloadName, &dummyCodec, frequency, channels);
512 receiveCodec.pacsize = dummyCodec.pacsize;
niklase@google.com470e71d2011-07-07 08:21:25 +0000513
kwiberg55b97fe2016-01-28 05:22:45 -0800514 // Register the new codec to the ACM
kwibergda2bf4e2016-10-24 13:47:09 -0700515 if (!audio_coding_->RegisterReceiveCodec(receiveCodec.pltype,
516 CodecInstToSdp(receiveCodec))) {
kwiberg55b97fe2016-01-28 05:22:45 -0800517 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
518 "Channel::OnInitializeDecoder() invalid codec ("
519 "pt=%d, name=%s) received - 1",
520 payloadType, payloadName);
521 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR);
522 return -1;
523 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000524
kwiberg55b97fe2016-01-28 05:22:45 -0800525 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000526}
527
kwiberg55b97fe2016-01-28 05:22:45 -0800528int32_t Channel::OnReceivedPayloadData(const uint8_t* payloadData,
529 size_t payloadSize,
530 const WebRtcRTPHeader* rtpHeader) {
531 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
532 "Channel::OnReceivedPayloadData(payloadSize=%" PRIuS
533 ","
534 " payloadType=%u, audioChannel=%" PRIuS ")",
535 payloadSize, rtpHeader->header.payloadType,
536 rtpHeader->type.Audio.channel);
niklase@google.com470e71d2011-07-07 08:21:25 +0000537
kwiberg55b97fe2016-01-28 05:22:45 -0800538 if (!channel_state_.Get().playing) {
539 // Avoid inserting into NetEQ when we are not playing. Count the
540 // packet as discarded.
541 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
542 "received packet is discarded since playing is not"
543 " activated");
niklase@google.com470e71d2011-07-07 08:21:25 +0000544 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -0800545 }
546
547 // Push the incoming payload (parsed and ready for decoding) into the ACM
548 if (audio_coding_->IncomingPacket(payloadData, payloadSize, *rtpHeader) !=
549 0) {
550 _engineStatisticsPtr->SetLastError(
551 VE_AUDIO_CODING_MODULE_ERROR, kTraceWarning,
552 "Channel::OnReceivedPayloadData() unable to push data to the ACM");
553 return -1;
554 }
555
kwiberg55b97fe2016-01-28 05:22:45 -0800556 int64_t round_trip_time = 0;
557 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), &round_trip_time, NULL, NULL,
558 NULL);
559
560 std::vector<uint16_t> nack_list = audio_coding_->GetNackList(round_trip_time);
561 if (!nack_list.empty()) {
562 // Can't use nack_list.data() since it's not supported by all
563 // compilers.
564 ResendPackets(&(nack_list[0]), static_cast<int>(nack_list.size()));
565 }
566 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000567}
568
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000569bool Channel::OnRecoveredPacket(const uint8_t* rtp_packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +0000570 size_t rtp_packet_length) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +0000571 RTPHeader header;
572 if (!rtp_header_parser_->Parse(rtp_packet, rtp_packet_length, &header)) {
573 WEBRTC_TRACE(kTraceDebug, webrtc::kTraceVoice, _channelId,
574 "IncomingPacket invalid RTP header");
575 return false;
576 }
577 header.payload_type_frequency =
578 rtp_payload_registry_->GetPayloadTypeFrequency(header.payloadType);
579 if (header.payload_type_frequency < 0)
580 return false;
581 return ReceivePacket(rtp_packet, rtp_packet_length, header, false);
582}
583
henrik.lundin42dda502016-05-18 05:36:01 -0700584MixerParticipant::AudioFrameInfo Channel::GetAudioFrameWithMuted(
585 int32_t id,
586 AudioFrame* audioFrame) {
ivoc14d5dbe2016-07-04 07:06:55 -0700587 unsigned int ssrc;
nisse7d59f6b2017-02-21 03:40:24 -0800588 RTC_CHECK_EQ(GetRemoteSSRC(ssrc), 0);
ivoc14d5dbe2016-07-04 07:06:55 -0700589 event_log_proxy_->LogAudioPlayout(ssrc);
kwiberg55b97fe2016-01-28 05:22:45 -0800590 // Get 10ms raw PCM data from the ACM (mixer limits output frequency)
henrik.lundind4ccb002016-05-17 12:21:55 -0700591 bool muted;
592 if (audio_coding_->PlayoutData10Ms(audioFrame->sample_rate_hz_, audioFrame,
593 &muted) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -0800594 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
595 "Channel::GetAudioFrame() PlayoutData10Ms() failed!");
596 // In all likelihood, the audio in this frame is garbage. We return an
597 // error so that the audio mixer module doesn't add it to the mix. As
598 // a result, it won't be played out and the actions skipped here are
599 // irrelevant.
henrik.lundin42dda502016-05-18 05:36:01 -0700600 return MixerParticipant::AudioFrameInfo::kError;
kwiberg55b97fe2016-01-28 05:22:45 -0800601 }
henrik.lundina89ab962016-05-18 08:52:45 -0700602
603 if (muted) {
604 // TODO(henrik.lundin): We should be able to do better than this. But we
605 // will have to go through all the cases below where the audio samples may
606 // be used, and handle the muted case in some way.
aleloi6321b492016-12-05 01:46:09 -0800607 AudioFrameOperations::Mute(audioFrame);
henrik.lundina89ab962016-05-18 08:52:45 -0700608 }
kwiberg55b97fe2016-01-28 05:22:45 -0800609
kwiberg55b97fe2016-01-28 05:22:45 -0800610 // Convert module ID to internal VoE channel ID
611 audioFrame->id_ = VoEChannelId(audioFrame->id_);
612 // Store speech type for dead-or-alive detection
613 _outputSpeechType = audioFrame->speech_type_;
614
615 ChannelState::State state = channel_state_.Get();
616
kwiberg55b97fe2016-01-28 05:22:45 -0800617 {
618 // Pass the audio buffers to an optional sink callback, before applying
619 // scaling/panning, as that applies to the mix operation.
620 // External recipients of the audio (e.g. via AudioTrack), will do their
621 // own mixing/dynamic processing.
622 rtc::CritScope cs(&_callbackCritSect);
623 if (audio_sink_) {
624 AudioSinkInterface::Data data(
625 &audioFrame->data_[0], audioFrame->samples_per_channel_,
626 audioFrame->sample_rate_hz_, audioFrame->num_channels_,
627 audioFrame->timestamp_);
628 audio_sink_->OnData(data);
629 }
630 }
631
632 float output_gain = 1.0f;
633 float left_pan = 1.0f;
634 float right_pan = 1.0f;
635 {
636 rtc::CritScope cs(&volume_settings_critsect_);
637 output_gain = _outputGain;
638 left_pan = _panLeft;
639 right_pan = _panRight;
640 }
641
642 // Output volume scaling
643 if (output_gain < 0.99f || output_gain > 1.01f) {
644 AudioFrameOperations::ScaleWithSat(output_gain, *audioFrame);
645 }
646
647 // Scale left and/or right channel(s) if stereo and master balance is
648 // active
649
650 if (left_pan != 1.0f || right_pan != 1.0f) {
651 if (audioFrame->num_channels_ == 1) {
652 // Emulate stereo mode since panning is active.
653 // The mono signal is copied to both left and right channels here.
654 AudioFrameOperations::MonoToStereo(audioFrame);
655 }
656 // For true stereo mode (when we are receiving a stereo signal), no
657 // action is needed.
658
659 // Do the panning operation (the audio frame contains stereo at this
660 // stage)
661 AudioFrameOperations::Scale(left_pan, right_pan, *audioFrame);
662 }
663
664 // Mix decoded PCM output with file if file mixing is enabled
665 if (state.output_file_playing) {
666 MixAudioWithFile(*audioFrame, audioFrame->sample_rate_hz_);
henrik.lundina89ab962016-05-18 08:52:45 -0700667 muted = false; // We may have added non-zero samples.
kwiberg55b97fe2016-01-28 05:22:45 -0800668 }
669
kwiberg55b97fe2016-01-28 05:22:45 -0800670 // Record playout if enabled
671 {
672 rtc::CritScope cs(&_fileCritSect);
673
kwiberg5a25d952016-08-17 07:31:12 -0700674 if (_outputFileRecording && output_file_recorder_) {
675 output_file_recorder_->RecordAudioToFile(*audioFrame);
kwiberg55b97fe2016-01-28 05:22:45 -0800676 }
677 }
678
679 // Measure audio level (0-9)
henrik.lundina89ab962016-05-18 08:52:45 -0700680 // TODO(henrik.lundin) Use the |muted| information here too.
kwiberg55b97fe2016-01-28 05:22:45 -0800681 _outputAudioLevel.ComputeLevel(*audioFrame);
682
683 if (capture_start_rtp_time_stamp_ < 0 && audioFrame->timestamp_ != 0) {
684 // The first frame with a valid rtp timestamp.
685 capture_start_rtp_time_stamp_ = audioFrame->timestamp_;
686 }
687
688 if (capture_start_rtp_time_stamp_ >= 0) {
689 // audioFrame.timestamp_ should be valid from now on.
690
691 // Compute elapsed time.
692 int64_t unwrap_timestamp =
693 rtp_ts_wraparound_handler_->Unwrap(audioFrame->timestamp_);
694 audioFrame->elapsed_time_ms_ =
695 (unwrap_timestamp - capture_start_rtp_time_stamp_) /
ossue280cde2016-10-12 11:04:10 -0700696 (GetRtpTimestampRateHz() / 1000);
kwiberg55b97fe2016-01-28 05:22:45 -0800697
niklase@google.com470e71d2011-07-07 08:21:25 +0000698 {
kwiberg55b97fe2016-01-28 05:22:45 -0800699 rtc::CritScope lock(&ts_stats_lock_);
700 // Compute ntp time.
701 audioFrame->ntp_time_ms_ =
702 ntp_estimator_.Estimate(audioFrame->timestamp_);
703 // |ntp_time_ms_| won't be valid until at least 2 RTCP SRs are received.
704 if (audioFrame->ntp_time_ms_ > 0) {
705 // Compute |capture_start_ntp_time_ms_| so that
706 // |capture_start_ntp_time_ms_| + |elapsed_time_ms_| == |ntp_time_ms_|
707 capture_start_ntp_time_ms_ =
708 audioFrame->ntp_time_ms_ - audioFrame->elapsed_time_ms_;
andrew@webrtc.org60730cf2014-01-07 17:45:09 +0000709 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000710 }
kwiberg55b97fe2016-01-28 05:22:45 -0800711 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000712
henrik.lundin42dda502016-05-18 05:36:01 -0700713 return muted ? MixerParticipant::AudioFrameInfo::kMuted
714 : MixerParticipant::AudioFrameInfo::kNormal;
niklase@google.com470e71d2011-07-07 08:21:25 +0000715}
716
aleloi6c278492016-10-20 14:24:39 -0700717AudioMixer::Source::AudioFrameInfo Channel::GetAudioFrameWithInfo(
718 int sample_rate_hz,
719 AudioFrame* audio_frame) {
720 audio_frame->sample_rate_hz_ = sample_rate_hz;
aleloiaed581a2016-10-20 06:32:39 -0700721
aleloi6c278492016-10-20 14:24:39 -0700722 const auto frame_info = GetAudioFrameWithMuted(-1, audio_frame);
aleloiaed581a2016-10-20 06:32:39 -0700723
724 using FrameInfo = AudioMixer::Source::AudioFrameInfo;
725 FrameInfo new_audio_frame_info = FrameInfo::kError;
726 switch (frame_info) {
727 case MixerParticipant::AudioFrameInfo::kNormal:
728 new_audio_frame_info = FrameInfo::kNormal;
729 break;
730 case MixerParticipant::AudioFrameInfo::kMuted:
731 new_audio_frame_info = FrameInfo::kMuted;
732 break;
733 case MixerParticipant::AudioFrameInfo::kError:
734 new_audio_frame_info = FrameInfo::kError;
735 break;
736 }
aleloi6c278492016-10-20 14:24:39 -0700737 return new_audio_frame_info;
aleloiaed581a2016-10-20 06:32:39 -0700738}
739
kwiberg55b97fe2016-01-28 05:22:45 -0800740int32_t Channel::NeededFrequency(int32_t id) const {
741 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
742 "Channel::NeededFrequency(id=%d)", id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000743
kwiberg55b97fe2016-01-28 05:22:45 -0800744 int highestNeeded = 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000745
kwiberg55b97fe2016-01-28 05:22:45 -0800746 // Determine highest needed receive frequency
747 int32_t receiveFrequency = audio_coding_->ReceiveFrequency();
niklase@google.com470e71d2011-07-07 08:21:25 +0000748
kwiberg55b97fe2016-01-28 05:22:45 -0800749 // Return the bigger of playout and receive frequency in the ACM.
750 if (audio_coding_->PlayoutFrequency() > receiveFrequency) {
751 highestNeeded = audio_coding_->PlayoutFrequency();
752 } else {
753 highestNeeded = receiveFrequency;
754 }
755
756 // Special case, if we're playing a file on the playout side
757 // we take that frequency into consideration as well
758 // This is not needed on sending side, since the codec will
759 // limit the spectrum anyway.
760 if (channel_state_.Get().output_file_playing) {
761 rtc::CritScope cs(&_fileCritSect);
kwiberg5a25d952016-08-17 07:31:12 -0700762 if (output_file_player_) {
763 if (output_file_player_->Frequency() > highestNeeded) {
764 highestNeeded = output_file_player_->Frequency();
kwiberg55b97fe2016-01-28 05:22:45 -0800765 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000766 }
kwiberg55b97fe2016-01-28 05:22:45 -0800767 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000768
kwiberg55b97fe2016-01-28 05:22:45 -0800769 return (highestNeeded);
niklase@google.com470e71d2011-07-07 08:21:25 +0000770}
771
ossu5f7cfa52016-05-30 08:11:28 -0700772int32_t Channel::CreateChannel(
773 Channel*& channel,
774 int32_t channelId,
775 uint32_t instanceId,
solenberg88499ec2016-09-07 07:34:41 -0700776 const VoEBase::ChannelConfig& config) {
kwiberg55b97fe2016-01-28 05:22:45 -0800777 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
778 "Channel::CreateChannel(channelId=%d, instanceId=%d)", channelId,
779 instanceId);
niklase@google.com470e71d2011-07-07 08:21:25 +0000780
solenberg88499ec2016-09-07 07:34:41 -0700781 channel = new Channel(channelId, instanceId, config);
kwiberg55b97fe2016-01-28 05:22:45 -0800782 if (channel == NULL) {
783 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(instanceId, channelId),
784 "Channel::CreateChannel() unable to allocate memory for"
785 " channel");
786 return -1;
787 }
788 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +0000789}
790
kwiberg55b97fe2016-01-28 05:22:45 -0800791void Channel::PlayNotification(int32_t id, uint32_t durationMs) {
792 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
793 "Channel::PlayNotification(id=%d, durationMs=%d)", id,
794 durationMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000795
kwiberg55b97fe2016-01-28 05:22:45 -0800796 // Not implement yet
niklase@google.com470e71d2011-07-07 08:21:25 +0000797}
798
kwiberg55b97fe2016-01-28 05:22:45 -0800799void Channel::RecordNotification(int32_t id, uint32_t durationMs) {
800 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
801 "Channel::RecordNotification(id=%d, durationMs=%d)", id,
802 durationMs);
niklase@google.com470e71d2011-07-07 08:21:25 +0000803
kwiberg55b97fe2016-01-28 05:22:45 -0800804 // Not implement yet
niklase@google.com470e71d2011-07-07 08:21:25 +0000805}
806
kwiberg55b97fe2016-01-28 05:22:45 -0800807void Channel::PlayFileEnded(int32_t id) {
808 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
809 "Channel::PlayFileEnded(id=%d)", id);
niklase@google.com470e71d2011-07-07 08:21:25 +0000810
kwiberg55b97fe2016-01-28 05:22:45 -0800811 if (id == _inputFilePlayerId) {
812 channel_state_.SetInputFilePlaying(false);
813 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
814 "Channel::PlayFileEnded() => input file player module is"
niklase@google.com470e71d2011-07-07 08:21:25 +0000815 " shutdown");
kwiberg55b97fe2016-01-28 05:22:45 -0800816 } else if (id == _outputFilePlayerId) {
817 channel_state_.SetOutputFilePlaying(false);
818 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
819 "Channel::PlayFileEnded() => output file player module is"
820 " shutdown");
821 }
822}
823
824void Channel::RecordFileEnded(int32_t id) {
825 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
826 "Channel::RecordFileEnded(id=%d)", id);
827
828 assert(id == _outputFileRecorderId);
829
830 rtc::CritScope cs(&_fileCritSect);
831
832 _outputFileRecording = false;
833 WEBRTC_TRACE(kTraceStateInfo, kTraceVoice, VoEId(_instanceId, _channelId),
834 "Channel::RecordFileEnded() => output file recorder module is"
835 " shutdown");
niklase@google.com470e71d2011-07-07 08:21:25 +0000836}
837
pbos@webrtc.org92135212013-05-14 08:31:39 +0000838Channel::Channel(int32_t channelId,
minyue@webrtc.orge509f942013-09-12 17:03:00 +0000839 uint32_t instanceId,
solenberg88499ec2016-09-07 07:34:41 -0700840 const VoEBase::ChannelConfig& config)
tommi31fc21f2016-01-21 10:37:37 -0800841 : _instanceId(instanceId),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100842 _channelId(channelId),
ivoc14d5dbe2016-07-04 07:06:55 -0700843 event_log_proxy_(new RtcEventLogProxy()),
michaelt9332b7d2016-11-30 07:51:13 -0800844 rtcp_rtt_stats_proxy_(new RtcpRttStatsProxy()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100845 rtp_header_parser_(RtpHeaderParser::Create()),
magjedf3feeff2016-11-25 06:40:25 -0800846 rtp_payload_registry_(new RTPPayloadRegistry()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100847 rtp_receive_statistics_(
848 ReceiveStatistics::Create(Clock::GetRealTimeClock())),
849 rtp_receiver_(
850 RtpReceiver::CreateAudioReceiver(Clock::GetRealTimeClock(),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100851 this,
852 this,
853 rtp_payload_registry_.get())),
danilchap799a9d02016-09-22 03:36:27 -0700854 telephone_event_handler_(rtp_receiver_->GetTelephoneEventHandler()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100855 _outputAudioLevel(),
856 _externalTransport(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100857 // Avoid conflict with other channels by adding 1024 - 1026,
858 // won't use as much as 1024 channels.
859 _inputFilePlayerId(VoEModuleId(instanceId, channelId) + 1024),
860 _outputFilePlayerId(VoEModuleId(instanceId, channelId) + 1025),
861 _outputFileRecorderId(VoEModuleId(instanceId, channelId) + 1026),
862 _outputFileRecording(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100863 _timeStamp(0), // This is just an offset, RTP module will add it's own
864 // random offset
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100865 ntp_estimator_(Clock::GetRealTimeClock()),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100866 playout_timestamp_rtp_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100867 playout_delay_ms_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100868 send_sequence_number_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100869 rtp_ts_wraparound_handler_(new rtc::TimestampWrapAroundHandler()),
870 capture_start_rtp_time_stamp_(-1),
871 capture_start_ntp_time_ms_(-1),
872 _engineStatisticsPtr(NULL),
873 _outputMixerPtr(NULL),
874 _transmitMixerPtr(NULL),
875 _moduleProcessThreadPtr(NULL),
876 _audioDeviceModulePtr(NULL),
877 _voiceEngineObserverPtr(NULL),
878 _callbackCritSectPtr(NULL),
879 _transportPtr(NULL),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100880 _sendFrameType(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100881 _mixFileWithMicrophone(false),
solenberg1c2af8e2016-03-24 10:36:00 -0700882 input_mute_(false),
883 previous_frame_muted_(false),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100884 _panLeft(1.0f),
885 _panRight(1.0f),
886 _outputGain(1.0f),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100887 _lastLocalTimeStamp(0),
888 _lastPayloadType(0),
889 _includeAudioLevelIndication(false),
nisse284542b2017-01-10 08:58:32 -0800890 transport_overhead_per_packet_(0),
891 rtp_overhead_per_packet_(0),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100892 _outputSpeechType(AudioFrame::kNormalSpeech),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100893 restored_packet_in_use_(false),
894 rtcp_observer_(new VoERtcpObserver(this)),
Stefan Holmerb86d4e42015-12-07 10:26:18 +0100895 associate_send_channel_(ChannelOwner(nullptr)),
solenberg88499ec2016-09-07 07:34:41 -0700896 pacing_enabled_(config.enable_voice_pacing),
stefanbba9dec2016-02-01 04:39:55 -0800897 feedback_observer_proxy_(new TransportFeedbackProxy()),
898 seq_num_allocator_proxy_(new TransportSequenceNumberProxy()),
ossu29b1a8d2016-06-13 07:34:51 -0700899 rtp_packet_sender_proxy_(new RtpPacketSenderProxy()),
Erik Språng737336d2016-07-29 12:59:36 +0200900 retransmission_rate_limiter_(new RateLimiter(Clock::GetRealTimeClock(),
901 kMaxRetransmissionWindowMs)),
michaelt566d8202017-01-12 10:17:38 -0800902 decoder_factory_(config.acm_config.decoder_factory) {
kwiberg55b97fe2016-01-28 05:22:45 -0800903 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
904 "Channel::Channel() - ctor");
solenberg88499ec2016-09-07 07:34:41 -0700905 AudioCodingModule::Config acm_config(config.acm_config);
kwiberg55b97fe2016-01-28 05:22:45 -0800906 acm_config.id = VoEModuleId(instanceId, channelId);
henrik.lundina89ab962016-05-18 08:52:45 -0700907 acm_config.neteq_config.enable_muted_state = true;
kwiberg55b97fe2016-01-28 05:22:45 -0800908 audio_coding_.reset(AudioCodingModule::Create(acm_config));
Henrik Lundin64dad832015-05-11 12:44:23 +0200909
kwiberg55b97fe2016-01-28 05:22:45 -0800910 _outputAudioLevel.Clear();
niklase@google.com470e71d2011-07-07 08:21:25 +0000911
kwiberg55b97fe2016-01-28 05:22:45 -0800912 RtpRtcp::Configuration configuration;
913 configuration.audio = true;
914 configuration.outgoing_transport = this;
michaeltbf65be52016-12-15 06:24:49 -0800915 configuration.overhead_observer = this;
kwiberg55b97fe2016-01-28 05:22:45 -0800916 configuration.receive_statistics = rtp_receive_statistics_.get();
917 configuration.bandwidth_callback = rtcp_observer_.get();
stefanbba9dec2016-02-01 04:39:55 -0800918 if (pacing_enabled_) {
919 configuration.paced_sender = rtp_packet_sender_proxy_.get();
920 configuration.transport_sequence_number_allocator =
921 seq_num_allocator_proxy_.get();
922 configuration.transport_feedback_callback = feedback_observer_proxy_.get();
923 }
ivoc14d5dbe2016-07-04 07:06:55 -0700924 configuration.event_log = &(*event_log_proxy_);
michaelt9332b7d2016-11-30 07:51:13 -0800925 configuration.rtt_stats = &(*rtcp_rtt_stats_proxy_);
Erik Språng737336d2016-07-29 12:59:36 +0200926 configuration.retransmission_rate_limiter =
927 retransmission_rate_limiter_.get();
pwestin@webrtc.org2853dde2012-05-11 11:08:54 +0000928
kwiberg55b97fe2016-01-28 05:22:45 -0800929 _rtpRtcpModule.reset(RtpRtcp::CreateRtpRtcp(configuration));
Peter Boström3dd5d1d2016-02-25 16:56:48 +0100930 _rtpRtcpModule->SetSendingMediaStatus(false);
niklase@google.com470e71d2011-07-07 08:21:25 +0000931}
932
kwiberg55b97fe2016-01-28 05:22:45 -0800933Channel::~Channel() {
934 rtp_receive_statistics_->RegisterRtcpStatisticsCallback(NULL);
935 WEBRTC_TRACE(kTraceMemory, kTraceVoice, VoEId(_instanceId, _channelId),
936 "Channel::~Channel() - dtor");
niklase@google.com470e71d2011-07-07 08:21:25 +0000937
kwiberg55b97fe2016-01-28 05:22:45 -0800938 StopSend();
939 StopPlayout();
niklase@google.com470e71d2011-07-07 08:21:25 +0000940
kwiberg55b97fe2016-01-28 05:22:45 -0800941 {
942 rtc::CritScope cs(&_fileCritSect);
kwiberg5a25d952016-08-17 07:31:12 -0700943 if (input_file_player_) {
944 input_file_player_->RegisterModuleFileCallback(NULL);
945 input_file_player_->StopPlayingFile();
niklase@google.com470e71d2011-07-07 08:21:25 +0000946 }
kwiberg5a25d952016-08-17 07:31:12 -0700947 if (output_file_player_) {
948 output_file_player_->RegisterModuleFileCallback(NULL);
949 output_file_player_->StopPlayingFile();
kwiberg55b97fe2016-01-28 05:22:45 -0800950 }
kwiberg5a25d952016-08-17 07:31:12 -0700951 if (output_file_recorder_) {
952 output_file_recorder_->RegisterModuleFileCallback(NULL);
953 output_file_recorder_->StopRecording();
kwiberg55b97fe2016-01-28 05:22:45 -0800954 }
955 }
niklase@google.com470e71d2011-07-07 08:21:25 +0000956
kwiberg55b97fe2016-01-28 05:22:45 -0800957 // The order to safely shutdown modules in a channel is:
958 // 1. De-register callbacks in modules
959 // 2. De-register modules in process thread
960 // 3. Destroy modules
961 if (audio_coding_->RegisterTransportCallback(NULL) == -1) {
962 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
963 "~Channel() failed to de-register transport callback"
964 " (Audio coding module)");
965 }
966 if (audio_coding_->RegisterVADCallback(NULL) == -1) {
967 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
968 "~Channel() failed to de-register VAD callback"
969 " (Audio coding module)");
970 }
971 // De-register modules in process thread
972 _moduleProcessThreadPtr->DeRegisterModule(_rtpRtcpModule.get());
tommi@webrtc.org3985f012015-02-27 13:36:34 +0000973
kwiberg55b97fe2016-01-28 05:22:45 -0800974 // End of modules shutdown
niklase@google.com470e71d2011-07-07 08:21:25 +0000975}
976
kwiberg55b97fe2016-01-28 05:22:45 -0800977int32_t Channel::Init() {
978 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
979 "Channel::Init()");
niklase@google.com470e71d2011-07-07 08:21:25 +0000980
kwiberg55b97fe2016-01-28 05:22:45 -0800981 channel_state_.Reset();
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +0000982
kwiberg55b97fe2016-01-28 05:22:45 -0800983 // --- Initial sanity
niklase@google.com470e71d2011-07-07 08:21:25 +0000984
kwiberg55b97fe2016-01-28 05:22:45 -0800985 if ((_engineStatisticsPtr == NULL) || (_moduleProcessThreadPtr == NULL)) {
986 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
987 "Channel::Init() must call SetEngineInformation() first");
988 return -1;
989 }
990
991 // --- Add modules to process thread (for periodic schedulation)
992
993 _moduleProcessThreadPtr->RegisterModule(_rtpRtcpModule.get());
994
995 // --- ACM initialization
996
997 if (audio_coding_->InitializeReceiver() == -1) {
998 _engineStatisticsPtr->SetLastError(
999 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1000 "Channel::Init() unable to initialize the ACM - 1");
1001 return -1;
1002 }
1003
1004 // --- RTP/RTCP module initialization
1005
1006 // Ensure that RTCP is enabled by default for the created channel.
1007 // Note that, the module will keep generating RTCP until it is explicitly
1008 // disabled by the user.
1009 // After StopListen (when no sockets exists), RTCP packets will no longer
1010 // be transmitted since the Transport object will then be invalid.
danilchap799a9d02016-09-22 03:36:27 -07001011 telephone_event_handler_->SetTelephoneEventForwardToDecoder(true);
kwiberg55b97fe2016-01-28 05:22:45 -08001012 // RTCP is enabled by default.
1013 _rtpRtcpModule->SetRTCPStatus(RtcpMode::kCompound);
1014 // --- Register all permanent callbacks
1015 const bool fail = (audio_coding_->RegisterTransportCallback(this) == -1) ||
1016 (audio_coding_->RegisterVADCallback(this) == -1);
1017
1018 if (fail) {
1019 _engineStatisticsPtr->SetLastError(
1020 VE_CANNOT_INIT_CHANNEL, kTraceError,
1021 "Channel::Init() callbacks not registered");
1022 return -1;
1023 }
1024
1025 // --- Register all supported codecs to the receiving side of the
1026 // RTP/RTCP module
1027
1028 CodecInst codec;
1029 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
1030
1031 for (int idx = 0; idx < nSupportedCodecs; idx++) {
1032 // Open up the RTP/RTCP receiver for all supported codecs
1033 if ((audio_coding_->Codec(idx, &codec) == -1) ||
magjed56124bd2016-11-24 09:34:46 -08001034 (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
kwiberg55b97fe2016-01-28 05:22:45 -08001035 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1036 "Channel::Init() unable to register %s "
1037 "(%d/%d/%" PRIuS "/%d) to RTP/RTCP receiver",
1038 codec.plname, codec.pltype, codec.plfreq, codec.channels,
1039 codec.rate);
1040 } else {
1041 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1042 "Channel::Init() %s (%d/%d/%" PRIuS
1043 "/%d) has been "
1044 "added to the RTP/RTCP receiver",
1045 codec.plname, codec.pltype, codec.plfreq, codec.channels,
1046 codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +00001047 }
1048
kwiberg55b97fe2016-01-28 05:22:45 -08001049 // Ensure that PCMU is used as default codec on the sending side
1050 if (!STR_CASE_CMP(codec.plname, "PCMU") && (codec.channels == 1)) {
1051 SetSendCodec(codec);
niklase@google.com470e71d2011-07-07 08:21:25 +00001052 }
1053
kwiberg55b97fe2016-01-28 05:22:45 -08001054 // Register default PT for outband 'telephone-event'
1055 if (!STR_CASE_CMP(codec.plname, "telephone-event")) {
kwibergc8d071e2016-04-06 12:22:38 -07001056 if (_rtpRtcpModule->RegisterSendPayload(codec) == -1 ||
kwibergda2bf4e2016-10-24 13:47:09 -07001057 !audio_coding_->RegisterReceiveCodec(codec.pltype,
1058 CodecInstToSdp(codec))) {
kwiberg55b97fe2016-01-28 05:22:45 -08001059 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1060 "Channel::Init() failed to register outband "
1061 "'telephone-event' (%d/%d) correctly",
1062 codec.pltype, codec.plfreq);
1063 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001064 }
1065
kwiberg55b97fe2016-01-28 05:22:45 -08001066 if (!STR_CASE_CMP(codec.plname, "CN")) {
kwibergc8d071e2016-04-06 12:22:38 -07001067 if (!codec_manager_.RegisterEncoder(codec) ||
1068 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get()) ||
kwibergda2bf4e2016-10-24 13:47:09 -07001069 !audio_coding_->RegisterReceiveCodec(codec.pltype,
1070 CodecInstToSdp(codec)) ||
kwibergc8d071e2016-04-06 12:22:38 -07001071 _rtpRtcpModule->RegisterSendPayload(codec) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08001072 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
1073 "Channel::Init() failed to register CN (%d/%d) "
1074 "correctly - 1",
1075 codec.pltype, codec.plfreq);
1076 }
1077 }
kwiberg55b97fe2016-01-28 05:22:45 -08001078 }
pwestin@webrtc.org684f0572013-03-13 23:20:57 +00001079
kwiberg55b97fe2016-01-28 05:22:45 -08001080 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001081}
1082
kwiberg55b97fe2016-01-28 05:22:45 -08001083int32_t Channel::SetEngineInformation(Statistics& engineStatistics,
1084 OutputMixer& outputMixer,
1085 voe::TransmitMixer& transmitMixer,
1086 ProcessThread& moduleProcessThread,
1087 AudioDeviceModule& audioDeviceModule,
1088 VoiceEngineObserver* voiceEngineObserver,
1089 rtc::CriticalSection* callbackCritSect) {
1090 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1091 "Channel::SetEngineInformation()");
1092 _engineStatisticsPtr = &engineStatistics;
1093 _outputMixerPtr = &outputMixer;
1094 _transmitMixerPtr = &transmitMixer,
1095 _moduleProcessThreadPtr = &moduleProcessThread;
1096 _audioDeviceModulePtr = &audioDeviceModule;
1097 _voiceEngineObserverPtr = voiceEngineObserver;
1098 _callbackCritSectPtr = callbackCritSect;
1099 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001100}
1101
kwiberg55b97fe2016-01-28 05:22:45 -08001102int32_t Channel::UpdateLocalTimeStamp() {
1103 _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
1104 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001105}
1106
kwibergb7f89d62016-02-17 10:04:18 -08001107void Channel::SetSink(std::unique_ptr<AudioSinkInterface> sink) {
tommi31fc21f2016-01-21 10:37:37 -08001108 rtc::CritScope cs(&_callbackCritSect);
deadbeef2d110be2016-01-13 12:00:26 -08001109 audio_sink_ = std::move(sink);
Tommif888bb52015-12-12 01:37:01 +01001110}
1111
ossu29b1a8d2016-06-13 07:34:51 -07001112const rtc::scoped_refptr<AudioDecoderFactory>&
1113Channel::GetAudioDecoderFactory() const {
1114 return decoder_factory_;
1115}
1116
kwiberg55b97fe2016-01-28 05:22:45 -08001117int32_t Channel::StartPlayout() {
1118 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1119 "Channel::StartPlayout()");
1120 if (channel_state_.Get().playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001121 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001122 }
1123
solenberge374e012017-02-14 04:55:00 -08001124 // Add participant as candidates for mixing.
1125 if (_outputMixerPtr->SetMixabilityStatus(*this, true) != 0) {
1126 _engineStatisticsPtr->SetLastError(
1127 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1128 "StartPlayout() failed to add participant to mixer");
1129 return -1;
kwiberg55b97fe2016-01-28 05:22:45 -08001130 }
1131
1132 channel_state_.SetPlaying(true);
1133 if (RegisterFilePlayingToMixer() != 0)
1134 return -1;
1135
1136 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001137}
1138
kwiberg55b97fe2016-01-28 05:22:45 -08001139int32_t Channel::StopPlayout() {
1140 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1141 "Channel::StopPlayout()");
1142 if (!channel_state_.Get().playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001143 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001144 }
1145
solenberge374e012017-02-14 04:55:00 -08001146 // Remove participant as candidates for mixing
1147 if (_outputMixerPtr->SetMixabilityStatus(*this, false) != 0) {
1148 _engineStatisticsPtr->SetLastError(
1149 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1150 "StopPlayout() failed to remove participant from mixer");
1151 return -1;
kwiberg55b97fe2016-01-28 05:22:45 -08001152 }
1153
1154 channel_state_.SetPlaying(false);
1155 _outputAudioLevel.Clear();
1156
1157 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001158}
1159
kwiberg55b97fe2016-01-28 05:22:45 -08001160int32_t Channel::StartSend() {
1161 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1162 "Channel::StartSend()");
kwiberg55b97fe2016-01-28 05:22:45 -08001163 if (channel_state_.Get().sending) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001164 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001165 }
1166 channel_state_.SetSending(true);
niklase@google.com470e71d2011-07-07 08:21:25 +00001167
solenberg08b19df2017-02-15 00:42:31 -08001168 // Resume the previous sequence number which was reset by StopSend(). This
1169 // needs to be done before |sending| is set to true on the RTP/RTCP module.
1170 if (send_sequence_number_) {
1171 _rtpRtcpModule->SetSequenceNumber(send_sequence_number_);
1172 }
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001173 _rtpRtcpModule->SetSendingMediaStatus(true);
kwiberg55b97fe2016-01-28 05:22:45 -08001174 if (_rtpRtcpModule->SetSendingStatus(true) != 0) {
1175 _engineStatisticsPtr->SetLastError(
1176 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1177 "StartSend() RTP/RTCP failed to start sending");
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001178 _rtpRtcpModule->SetSendingMediaStatus(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001179 rtc::CritScope cs(&_callbackCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00001180 channel_state_.SetSending(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001181 return -1;
1182 }
xians@webrtc.orge07247a2011-11-28 16:31:28 +00001183
kwiberg55b97fe2016-01-28 05:22:45 -08001184 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001185}
1186
kwiberg55b97fe2016-01-28 05:22:45 -08001187int32_t Channel::StopSend() {
1188 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1189 "Channel::StopSend()");
1190 if (!channel_state_.Get().sending) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001191 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001192 }
1193 channel_state_.SetSending(false);
1194
1195 // Store the sequence number to be able to pick up the same sequence for
1196 // the next StartSend(). This is needed for restarting device, otherwise
1197 // it might cause libSRTP to complain about packets being replayed.
1198 // TODO(xians): Remove this workaround after RtpRtcpModule's refactoring
1199 // CL is landed. See issue
1200 // https://code.google.com/p/webrtc/issues/detail?id=2111 .
1201 send_sequence_number_ = _rtpRtcpModule->SequenceNumber();
1202
1203 // Reset sending SSRC and sequence number and triggers direct transmission
1204 // of RTCP BYE
1205 if (_rtpRtcpModule->SetSendingStatus(false) == -1) {
1206 _engineStatisticsPtr->SetLastError(
1207 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1208 "StartSend() RTP/RTCP failed to stop sending");
1209 }
Peter Boström3dd5d1d2016-02-25 16:56:48 +01001210 _rtpRtcpModule->SetSendingMediaStatus(false);
kwiberg55b97fe2016-01-28 05:22:45 -08001211
1212 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001213}
1214
kwiberg55b97fe2016-01-28 05:22:45 -08001215int32_t Channel::RegisterVoiceEngineObserver(VoiceEngineObserver& observer) {
1216 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1217 "Channel::RegisterVoiceEngineObserver()");
1218 rtc::CritScope cs(&_callbackCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00001219
kwiberg55b97fe2016-01-28 05:22:45 -08001220 if (_voiceEngineObserverPtr) {
1221 _engineStatisticsPtr->SetLastError(
1222 VE_INVALID_OPERATION, kTraceError,
1223 "RegisterVoiceEngineObserver() observer already enabled");
1224 return -1;
1225 }
1226 _voiceEngineObserverPtr = &observer;
1227 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001228}
1229
kwiberg55b97fe2016-01-28 05:22:45 -08001230int32_t Channel::DeRegisterVoiceEngineObserver() {
1231 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1232 "Channel::DeRegisterVoiceEngineObserver()");
1233 rtc::CritScope cs(&_callbackCritSect);
1234
1235 if (!_voiceEngineObserverPtr) {
1236 _engineStatisticsPtr->SetLastError(
1237 VE_INVALID_OPERATION, kTraceWarning,
1238 "DeRegisterVoiceEngineObserver() observer already disabled");
1239 return 0;
1240 }
1241 _voiceEngineObserverPtr = NULL;
1242 return 0;
1243}
1244
1245int32_t Channel::GetSendCodec(CodecInst& codec) {
kwibergc8d071e2016-04-06 12:22:38 -07001246 auto send_codec = codec_manager_.GetCodecInst();
kwiberg1fd4a4a2015-11-03 11:20:50 -08001247 if (send_codec) {
1248 codec = *send_codec;
1249 return 0;
1250 }
1251 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001252}
1253
kwiberg55b97fe2016-01-28 05:22:45 -08001254int32_t Channel::GetRecCodec(CodecInst& codec) {
1255 return (audio_coding_->ReceiveCodec(&codec));
niklase@google.com470e71d2011-07-07 08:21:25 +00001256}
1257
kwiberg55b97fe2016-01-28 05:22:45 -08001258int32_t Channel::SetSendCodec(const CodecInst& codec) {
1259 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1260 "Channel::SetSendCodec()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001261
kwibergc8d071e2016-04-06 12:22:38 -07001262 if (!codec_manager_.RegisterEncoder(codec) ||
1263 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001264 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1265 "SetSendCodec() failed to register codec to ACM");
1266 return -1;
1267 }
1268
1269 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1270 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1271 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1272 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
1273 "SetSendCodec() failed to register codec to"
1274 " RTP/RTCP module");
1275 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001276 }
kwiberg55b97fe2016-01-28 05:22:45 -08001277 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001278
kwiberg55b97fe2016-01-28 05:22:45 -08001279 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001280}
1281
minyue78b4d562016-11-30 04:47:39 -08001282void Channel::SetBitRate(int bitrate_bps, int64_t probing_interval_ms) {
Ivo Creusenadf89b72015-04-29 16:03:33 +02001283 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1284 "Channel::SetBitRate(bitrate_bps=%d)", bitrate_bps);
minyue7e304322016-10-12 05:00:55 -07001285 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
michaelt2fedf9c2016-11-28 02:34:18 -08001286 if (*encoder) {
1287 (*encoder)->OnReceivedUplinkBandwidth(
michaelt566d8202017-01-12 10:17:38 -08001288 bitrate_bps, rtc::Optional<int64_t>(probing_interval_ms));
michaelt2fedf9c2016-11-28 02:34:18 -08001289 }
1290 });
michaelt566d8202017-01-12 10:17:38 -08001291 retransmission_rate_limiter_->SetMaxRate(bitrate_bps);
Ivo Creusenadf89b72015-04-29 16:03:33 +02001292}
1293
mflodman@webrtc.org0a7d4ee2015-02-17 12:57:14 +00001294void Channel::OnIncomingFractionLoss(int fraction_lost) {
minyue7e304322016-10-12 05:00:55 -07001295 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1296 if (*encoder)
1297 (*encoder)->OnReceivedUplinkPacketLossFraction(fraction_lost / 255.0f);
1298 });
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00001299}
1300
kwiberg55b97fe2016-01-28 05:22:45 -08001301int32_t Channel::SetVADStatus(bool enableVAD,
1302 ACMVADMode mode,
1303 bool disableDTX) {
1304 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1305 "Channel::SetVADStatus(mode=%d)", mode);
kwibergc8d071e2016-04-06 12:22:38 -07001306 RTC_DCHECK(!(disableDTX && enableVAD)); // disableDTX mode is deprecated.
1307 if (!codec_manager_.SetVAD(enableVAD, mode) ||
1308 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001309 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1310 kTraceError,
1311 "SetVADStatus() failed to set VAD");
1312 return -1;
1313 }
1314 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001315}
1316
kwiberg55b97fe2016-01-28 05:22:45 -08001317int32_t Channel::GetVADStatus(bool& enabledVAD,
1318 ACMVADMode& mode,
1319 bool& disabledDTX) {
kwibergc8d071e2016-04-06 12:22:38 -07001320 const auto* params = codec_manager_.GetStackParams();
1321 enabledVAD = params->use_cng;
1322 mode = params->vad_mode;
1323 disabledDTX = !params->use_cng;
kwiberg55b97fe2016-01-28 05:22:45 -08001324 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001325}
1326
kwiberg55b97fe2016-01-28 05:22:45 -08001327int32_t Channel::SetRecPayloadType(const CodecInst& codec) {
kwibergd32bf752017-01-19 07:03:59 -08001328 return SetRecPayloadType(codec.pltype, CodecInstToSdp(codec));
1329}
1330
1331int32_t Channel::SetRecPayloadType(int payload_type,
1332 const SdpAudioFormat& format) {
kwiberg55b97fe2016-01-28 05:22:45 -08001333 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1334 "Channel::SetRecPayloadType()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001335
kwiberg55b97fe2016-01-28 05:22:45 -08001336 if (channel_state_.Get().playing) {
1337 _engineStatisticsPtr->SetLastError(
1338 VE_ALREADY_PLAYING, kTraceError,
1339 "SetRecPayloadType() unable to set PT while playing");
1340 return -1;
1341 }
kwiberg55b97fe2016-01-28 05:22:45 -08001342
kwibergd32bf752017-01-19 07:03:59 -08001343 const CodecInst codec = [&] {
1344 CodecInst c = SdpToCodecInst(payload_type, format);
1345
1346 // Bug 6986: Emulate an old bug that caused us to always choose to decode
1347 // Opus in stereo. To be able to remove this, we first need to fix the
1348 // other half of bug 6986, which is about losing the Opus "stereo"
1349 // parameter.
1350 // TODO(kwiberg): Remove this special case, a.k.a. fix bug 6986.
1351 if (STR_CASE_CMP(codec.plname, "opus") == 0) {
1352 c.channels = 2;
1353 }
1354
1355 return c;
1356 }();
1357
1358 if (payload_type == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08001359 // De-register the selected codec (RTP/RTCP module and ACM)
1360
1361 int8_t pltype(-1);
1362 CodecInst rxCodec = codec;
1363
1364 // Get payload type for the given codec
magjed56124bd2016-11-24 09:34:46 -08001365 rtp_payload_registry_->ReceivePayloadType(rxCodec, &pltype);
kwiberg55b97fe2016-01-28 05:22:45 -08001366 rxCodec.pltype = pltype;
1367
1368 if (rtp_receiver_->DeRegisterReceivePayload(pltype) != 0) {
1369 _engineStatisticsPtr->SetLastError(
1370 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1371 "SetRecPayloadType() RTP/RTCP-module deregistration "
1372 "failed");
1373 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001374 }
kwiberg55b97fe2016-01-28 05:22:45 -08001375 if (audio_coding_->UnregisterReceiveCodec(rxCodec.pltype) != 0) {
1376 _engineStatisticsPtr->SetLastError(
1377 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1378 "SetRecPayloadType() ACM deregistration failed - 1");
1379 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001380 }
kwiberg55b97fe2016-01-28 05:22:45 -08001381 return 0;
1382 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001383
magjed56124bd2016-11-24 09:34:46 -08001384 if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001385 // First attempt to register failed => de-register and try again
kwibergc8d071e2016-04-06 12:22:38 -07001386 // TODO(kwiberg): Retrying is probably not necessary, since
1387 // AcmReceiver::AddCodec also retries.
kwiberg55b97fe2016-01-28 05:22:45 -08001388 rtp_receiver_->DeRegisterReceivePayload(codec.pltype);
magjed56124bd2016-11-24 09:34:46 -08001389 if (rtp_receiver_->RegisterReceivePayload(codec) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001390 _engineStatisticsPtr->SetLastError(
1391 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1392 "SetRecPayloadType() RTP/RTCP-module registration failed");
1393 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001394 }
kwiberg55b97fe2016-01-28 05:22:45 -08001395 }
kwibergd32bf752017-01-19 07:03:59 -08001396 if (!audio_coding_->RegisterReceiveCodec(payload_type, format)) {
1397 audio_coding_->UnregisterReceiveCodec(payload_type);
1398 if (!audio_coding_->RegisterReceiveCodec(payload_type, format)) {
kwiberg55b97fe2016-01-28 05:22:45 -08001399 _engineStatisticsPtr->SetLastError(
1400 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1401 "SetRecPayloadType() ACM registration failed - 1");
1402 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001403 }
kwiberg55b97fe2016-01-28 05:22:45 -08001404 }
1405 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001406}
1407
kwiberg55b97fe2016-01-28 05:22:45 -08001408int32_t Channel::GetRecPayloadType(CodecInst& codec) {
1409 int8_t payloadType(-1);
magjed56124bd2016-11-24 09:34:46 -08001410 if (rtp_payload_registry_->ReceivePayloadType(codec, &payloadType) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001411 _engineStatisticsPtr->SetLastError(
1412 VE_RTP_RTCP_MODULE_ERROR, kTraceWarning,
1413 "GetRecPayloadType() failed to retrieve RX payload type");
1414 return -1;
1415 }
1416 codec.pltype = payloadType;
1417 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001418}
1419
kwiberg55b97fe2016-01-28 05:22:45 -08001420int32_t Channel::SetSendCNPayloadType(int type, PayloadFrequencies frequency) {
1421 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1422 "Channel::SetSendCNPayloadType()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001423
kwiberg55b97fe2016-01-28 05:22:45 -08001424 CodecInst codec;
1425 int32_t samplingFreqHz(-1);
1426 const size_t kMono = 1;
1427 if (frequency == kFreq32000Hz)
1428 samplingFreqHz = 32000;
1429 else if (frequency == kFreq16000Hz)
1430 samplingFreqHz = 16000;
niklase@google.com470e71d2011-07-07 08:21:25 +00001431
kwiberg55b97fe2016-01-28 05:22:45 -08001432 if (audio_coding_->Codec("CN", &codec, samplingFreqHz, kMono) == -1) {
1433 _engineStatisticsPtr->SetLastError(
1434 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1435 "SetSendCNPayloadType() failed to retrieve default CN codec "
1436 "settings");
1437 return -1;
1438 }
1439
1440 // Modify the payload type (must be set to dynamic range)
1441 codec.pltype = type;
1442
kwibergc8d071e2016-04-06 12:22:38 -07001443 if (!codec_manager_.RegisterEncoder(codec) ||
1444 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
kwiberg55b97fe2016-01-28 05:22:45 -08001445 _engineStatisticsPtr->SetLastError(
1446 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
1447 "SetSendCNPayloadType() failed to register CN to ACM");
1448 return -1;
1449 }
1450
1451 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1452 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
1453 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
1454 _engineStatisticsPtr->SetLastError(
1455 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
1456 "SetSendCNPayloadType() failed to register CN to RTP/RTCP "
1457 "module");
1458 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001459 }
kwiberg55b97fe2016-01-28 05:22:45 -08001460 }
1461 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001462}
1463
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001464int Channel::SetOpusMaxPlaybackRate(int frequency_hz) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001465 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001466 "Channel::SetOpusMaxPlaybackRate()");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001467
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001468 if (audio_coding_->SetOpusMaxPlaybackRate(frequency_hz) != 0) {
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001469 _engineStatisticsPtr->SetLastError(
1470 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
minyue@webrtc.orgadee8f92014-09-03 12:28:06 +00001471 "SetOpusMaxPlaybackRate() failed to set maximum playback rate");
minyue@webrtc.org6aac93b2014-08-12 08:13:33 +00001472 return -1;
1473 }
1474 return 0;
1475}
1476
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001477int Channel::SetOpusDtx(bool enable_dtx) {
1478 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1479 "Channel::SetOpusDtx(%d)", enable_dtx);
Minyue Li092041c2015-05-11 12:19:35 +02001480 int ret = enable_dtx ? audio_coding_->EnableOpusDtx()
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001481 : audio_coding_->DisableOpusDtx();
1482 if (ret != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001483 _engineStatisticsPtr->SetLastError(VE_AUDIO_CODING_MODULE_ERROR,
1484 kTraceError, "SetOpusDtx() failed");
minyue@webrtc.org9b2e1142015-03-13 09:38:07 +00001485 return -1;
1486 }
1487 return 0;
1488}
1489
ivoc85228d62016-07-27 04:53:47 -07001490int Channel::GetOpusDtx(bool* enabled) {
1491 int success = -1;
1492 audio_coding_->QueryEncoder([&](AudioEncoder const* encoder) {
1493 if (encoder) {
1494 *enabled = encoder->GetDtx();
1495 success = 0;
1496 }
1497 });
1498 return success;
1499}
1500
minyue7e304322016-10-12 05:00:55 -07001501bool Channel::EnableAudioNetworkAdaptor(const std::string& config_string) {
1502 bool success = false;
1503 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1504 if (*encoder) {
1505 success = (*encoder)->EnableAudioNetworkAdaptor(
michaeltbf279fc2017-01-13 06:02:29 -08001506 config_string, event_log_proxy_.get(), Clock::GetRealTimeClock());
minyue7e304322016-10-12 05:00:55 -07001507 }
1508 });
1509 return success;
1510}
1511
1512void Channel::DisableAudioNetworkAdaptor() {
1513 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1514 if (*encoder)
1515 (*encoder)->DisableAudioNetworkAdaptor();
1516 });
1517}
1518
1519void Channel::SetReceiverFrameLengthRange(int min_frame_length_ms,
1520 int max_frame_length_ms) {
1521 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1522 if (*encoder) {
1523 (*encoder)->SetReceiverFrameLengthRange(min_frame_length_ms,
1524 max_frame_length_ms);
1525 }
1526 });
1527}
1528
mflodman3d7db262016-04-29 00:57:13 -07001529int32_t Channel::RegisterExternalTransport(Transport* transport) {
kwiberg55b97fe2016-01-28 05:22:45 -08001530 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00001531 "Channel::RegisterExternalTransport()");
1532
kwiberg55b97fe2016-01-28 05:22:45 -08001533 rtc::CritScope cs(&_callbackCritSect);
kwiberg55b97fe2016-01-28 05:22:45 -08001534 if (_externalTransport) {
1535 _engineStatisticsPtr->SetLastError(
1536 VE_INVALID_OPERATION, kTraceError,
1537 "RegisterExternalTransport() external transport already enabled");
1538 return -1;
1539 }
1540 _externalTransport = true;
mflodman3d7db262016-04-29 00:57:13 -07001541 _transportPtr = transport;
kwiberg55b97fe2016-01-28 05:22:45 -08001542 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001543}
1544
kwiberg55b97fe2016-01-28 05:22:45 -08001545int32_t Channel::DeRegisterExternalTransport() {
1546 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1547 "Channel::DeRegisterExternalTransport()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001548
kwiberg55b97fe2016-01-28 05:22:45 -08001549 rtc::CritScope cs(&_callbackCritSect);
mflodman3d7db262016-04-29 00:57:13 -07001550 if (_transportPtr) {
1551 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1552 "DeRegisterExternalTransport() all transport is disabled");
1553 } else {
kwiberg55b97fe2016-01-28 05:22:45 -08001554 _engineStatisticsPtr->SetLastError(
1555 VE_INVALID_OPERATION, kTraceWarning,
1556 "DeRegisterExternalTransport() external transport already "
1557 "disabled");
kwiberg55b97fe2016-01-28 05:22:45 -08001558 }
1559 _externalTransport = false;
1560 _transportPtr = NULL;
kwiberg55b97fe2016-01-28 05:22:45 -08001561 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001562}
1563
nisse657bab22017-02-21 06:28:10 -08001564// TODO(nisse): Delete this method together with ReceivedRTPPacket.
1565// It's a temporary hack to support both ReceivedRTPPacket and
1566// OnRtpPacket interfaces without too much code duplication.
1567bool Channel::OnRtpPacketWithHeader(const uint8_t* received_packet,
1568 size_t length,
1569 RTPHeader *header) {
1570 // Store playout timestamp for the received RTP packet
1571 UpdatePlayoutTimestamp(false);
1572
1573 header->payload_type_frequency =
1574 rtp_payload_registry_->GetPayloadTypeFrequency(header->payloadType);
1575 if (header->payload_type_frequency < 0)
1576 return false;
1577 bool in_order = IsPacketInOrder(*header);
1578 rtp_receive_statistics_->IncomingPacket(
1579 *header, length, IsPacketRetransmitted(*header, in_order));
1580 rtp_payload_registry_->SetIncomingPayloadType(*header);
1581
1582 return ReceivePacket(received_packet, length, *header, in_order);
1583}
1584
mflodman3d7db262016-04-29 00:57:13 -07001585int32_t Channel::ReceivedRTPPacket(const uint8_t* received_packet,
kwiberg55b97fe2016-01-28 05:22:45 -08001586 size_t length,
solenberg@webrtc.orgb1f50102014-03-24 10:38:25 +00001587 const PacketTime& packet_time) {
kwiberg55b97fe2016-01-28 05:22:45 -08001588 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001589 "Channel::ReceivedRTPPacket()");
1590
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +00001591 RTPHeader header;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001592 if (!rtp_header_parser_->Parse(received_packet, length, &header)) {
1593 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1594 "Incoming packet: invalid RTP header");
stefan@webrtc.orga5cb98c2013-05-29 12:12:51 +00001595 return -1;
1596 }
nisse657bab22017-02-21 06:28:10 -08001597 return OnRtpPacketWithHeader(received_packet, length, &header) ? 0 : -1;
1598}
solenberg@webrtc.orgb1f50102014-03-24 10:38:25 +00001599
nisse657bab22017-02-21 06:28:10 -08001600void Channel::OnRtpPacket(const RtpPacketReceived& packet) {
1601 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
1602 "Channel::ReceivedRTPPacket()");
1603
1604 RTPHeader header;
1605 packet.GetHeader(&header);
1606 OnRtpPacketWithHeader(packet.data(), packet.size(), &header);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001607}
1608
1609bool Channel::ReceivePacket(const uint8_t* packet,
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001610 size_t packet_length,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001611 const RTPHeader& header,
1612 bool in_order) {
minyue@webrtc.org456f0142015-01-23 11:58:42 +00001613 if (rtp_payload_registry_->IsRtx(header)) {
1614 return HandleRtxPacket(packet, packet_length, header);
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001615 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001616 const uint8_t* payload = packet + header.headerLength;
pkasting@chromium.org4591fbd2014-11-20 22:28:14 +00001617 assert(packet_length >= header.headerLength);
1618 size_t payload_length = packet_length - header.headerLength;
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001619 PayloadUnion payload_specific;
1620 if (!rtp_payload_registry_->GetPayloadSpecifics(header.payloadType,
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001621 &payload_specific)) {
1622 return false;
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001623 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001624 return rtp_receiver_->IncomingRtpPacket(header, payload, payload_length,
1625 payload_specific, in_order);
1626}
1627
minyue@webrtc.org456f0142015-01-23 11:58:42 +00001628bool Channel::HandleRtxPacket(const uint8_t* packet,
1629 size_t packet_length,
1630 const RTPHeader& header) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001631 if (!rtp_payload_registry_->IsRtx(header))
1632 return false;
1633
1634 // Remove the RTX header and parse the original RTP header.
1635 if (packet_length < header.headerLength)
1636 return false;
1637 if (packet_length > kVoiceEngineMaxIpPacketSizeBytes)
1638 return false;
1639 if (restored_packet_in_use_) {
1640 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1641 "Multiple RTX headers detected, dropping packet");
1642 return false;
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001643 }
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001644 if (!rtp_payload_registry_->RestoreOriginalPacket(
noahric65220a72015-10-14 11:29:49 -07001645 restored_packet_, packet, &packet_length, rtp_receiver_->SSRC(),
1646 header)) {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001647 WEBRTC_TRACE(webrtc::kTraceDebug, webrtc::kTraceVoice, _channelId,
1648 "Incoming RTX packet: invalid RTP header");
1649 return false;
1650 }
1651 restored_packet_in_use_ = true;
noahric65220a72015-10-14 11:29:49 -07001652 bool ret = OnRecoveredPacket(restored_packet_, packet_length);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001653 restored_packet_in_use_ = false;
1654 return ret;
1655}
1656
1657bool Channel::IsPacketInOrder(const RTPHeader& header) const {
1658 StreamStatistician* statistician =
1659 rtp_receive_statistics_->GetStatistician(header.ssrc);
1660 if (!statistician)
1661 return false;
1662 return statistician->IsPacketInOrder(header.sequenceNumber);
niklase@google.com470e71d2011-07-07 08:21:25 +00001663}
1664
stefan@webrtc.org48df3812013-11-08 15:18:52 +00001665bool Channel::IsPacketRetransmitted(const RTPHeader& header,
1666 bool in_order) const {
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001667 // Retransmissions are handled separately if RTX is enabled.
1668 if (rtp_payload_registry_->RtxEnabled())
1669 return false;
1670 StreamStatistician* statistician =
1671 rtp_receive_statistics_->GetStatistician(header.ssrc);
1672 if (!statistician)
1673 return false;
1674 // Check if this is a retransmission.
pkasting@chromium.org16825b12015-01-12 21:51:21 +00001675 int64_t min_rtt = 0;
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00001676 _rtpRtcpModule->RTT(rtp_receiver_->SSRC(), NULL, NULL, &min_rtt, NULL);
kwiberg55b97fe2016-01-28 05:22:45 -08001677 return !in_order && statistician->IsRetransmitOfOldPacket(header, min_rtt);
wu@webrtc.org822fbd82013-08-15 23:38:54 +00001678}
1679
mflodman3d7db262016-04-29 00:57:13 -07001680int32_t Channel::ReceivedRTCPPacket(const uint8_t* data, size_t length) {
kwiberg55b97fe2016-01-28 05:22:45 -08001681 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001682 "Channel::ReceivedRTCPPacket()");
1683 // Store playout timestamp for the received RTCP packet
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00001684 UpdatePlayoutTimestamp(true);
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001685
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001686 // Deliver RTCP packet to RTP/RTCP module for parsing
mflodman3d7db262016-04-29 00:57:13 -07001687 if (_rtpRtcpModule->IncomingRtcpPacket(data, length) == -1) {
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001688 _engineStatisticsPtr->SetLastError(
1689 VE_SOCKET_TRANSPORT_MODULE_ERROR, kTraceWarning,
1690 "Channel::IncomingRTPPacket() RTCP packet is invalid");
1691 }
wu@webrtc.org82c4b852014-05-20 22:55:01 +00001692
Minyue2013aec2015-05-13 14:14:42 +02001693 int64_t rtt = GetRTT(true);
1694 if (rtt == 0) {
1695 // Waiting for valid RTT.
1696 return 0;
1697 }
Erik Språng737336d2016-07-29 12:59:36 +02001698
1699 int64_t nack_window_ms = rtt;
1700 if (nack_window_ms < kMinRetransmissionWindowMs) {
1701 nack_window_ms = kMinRetransmissionWindowMs;
1702 } else if (nack_window_ms > kMaxRetransmissionWindowMs) {
1703 nack_window_ms = kMaxRetransmissionWindowMs;
1704 }
1705 retransmission_rate_limiter_->SetWindowSize(nack_window_ms);
1706
minyue7e304322016-10-12 05:00:55 -07001707 // Invoke audio encoders OnReceivedRtt().
1708 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
1709 if (*encoder)
1710 (*encoder)->OnReceivedRtt(rtt);
1711 });
1712
Minyue2013aec2015-05-13 14:14:42 +02001713 uint32_t ntp_secs = 0;
1714 uint32_t ntp_frac = 0;
1715 uint32_t rtp_timestamp = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001716 if (0 !=
1717 _rtpRtcpModule->RemoteNTP(&ntp_secs, &ntp_frac, NULL, NULL,
1718 &rtp_timestamp)) {
Minyue2013aec2015-05-13 14:14:42 +02001719 // Waiting for RTCP.
1720 return 0;
1721 }
1722
stefan@webrtc.org8e24d872014-09-02 18:58:24 +00001723 {
tommi31fc21f2016-01-21 10:37:37 -08001724 rtc::CritScope lock(&ts_stats_lock_);
minyue@webrtc.org2c0cdbc2014-10-09 10:52:43 +00001725 ntp_estimator_.UpdateRtcpTimestamp(rtt, ntp_secs, ntp_frac, rtp_timestamp);
stefan@webrtc.org8e24d872014-09-02 18:58:24 +00001726 }
pwestin@webrtc.org0c459572013-04-03 15:43:57 +00001727 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001728}
1729
niklase@google.com470e71d2011-07-07 08:21:25 +00001730int Channel::StartPlayingFileLocally(const char* fileName,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001731 bool loop,
1732 FileFormats format,
1733 int startPosition,
1734 float volumeScaling,
1735 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001736 const CodecInst* codecInst) {
1737 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1738 "Channel::StartPlayingFileLocally(fileNameUTF8[]=%s, loop=%d,"
1739 " format=%d, volumeScaling=%5.3f, startPosition=%d, "
1740 "stopPosition=%d)",
1741 fileName, loop, format, volumeScaling, startPosition,
1742 stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001743
kwiberg55b97fe2016-01-28 05:22:45 -08001744 if (channel_state_.Get().output_file_playing) {
1745 _engineStatisticsPtr->SetLastError(
1746 VE_ALREADY_PLAYING, kTraceError,
1747 "StartPlayingFileLocally() is already playing");
1748 return -1;
1749 }
1750
1751 {
1752 rtc::CritScope cs(&_fileCritSect);
1753
kwiberg5a25d952016-08-17 07:31:12 -07001754 if (output_file_player_) {
1755 output_file_player_->RegisterModuleFileCallback(NULL);
1756 output_file_player_.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +00001757 }
1758
kwiberg5b356f42016-09-08 04:32:33 -07001759 output_file_player_ = FilePlayer::CreateFilePlayer(
kwiberg55b97fe2016-01-28 05:22:45 -08001760 _outputFilePlayerId, (const FileFormats)format);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00001761
kwiberg5a25d952016-08-17 07:31:12 -07001762 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001763 _engineStatisticsPtr->SetLastError(
1764 VE_INVALID_ARGUMENT, kTraceError,
1765 "StartPlayingFileLocally() filePlayer format is not correct");
1766 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001767 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001768
kwiberg55b97fe2016-01-28 05:22:45 -08001769 const uint32_t notificationTime(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00001770
kwiberg5a25d952016-08-17 07:31:12 -07001771 if (output_file_player_->StartPlayingFile(
kwiberg55b97fe2016-01-28 05:22:45 -08001772 fileName, loop, startPosition, volumeScaling, notificationTime,
1773 stopPosition, (const CodecInst*)codecInst) != 0) {
1774 _engineStatisticsPtr->SetLastError(
1775 VE_BAD_FILE, kTraceError,
1776 "StartPlayingFile() failed to start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001777 output_file_player_->StopPlayingFile();
1778 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001779 return -1;
1780 }
kwiberg5a25d952016-08-17 07:31:12 -07001781 output_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001782 channel_state_.SetOutputFilePlaying(true);
1783 }
1784
1785 if (RegisterFilePlayingToMixer() != 0)
1786 return -1;
1787
1788 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001789}
1790
1791int Channel::StartPlayingFileLocally(InStream* stream,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001792 FileFormats format,
1793 int startPosition,
1794 float volumeScaling,
1795 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001796 const CodecInst* codecInst) {
1797 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1798 "Channel::StartPlayingFileLocally(format=%d,"
1799 " volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1800 format, volumeScaling, startPosition, stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001801
kwiberg55b97fe2016-01-28 05:22:45 -08001802 if (stream == NULL) {
1803 _engineStatisticsPtr->SetLastError(
1804 VE_BAD_FILE, kTraceError,
1805 "StartPlayingFileLocally() NULL as input stream");
1806 return -1;
1807 }
1808
1809 if (channel_state_.Get().output_file_playing) {
1810 _engineStatisticsPtr->SetLastError(
1811 VE_ALREADY_PLAYING, kTraceError,
1812 "StartPlayingFileLocally() is already playing");
1813 return -1;
1814 }
1815
1816 {
1817 rtc::CritScope cs(&_fileCritSect);
1818
1819 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07001820 if (output_file_player_) {
1821 output_file_player_->RegisterModuleFileCallback(NULL);
1822 output_file_player_.reset();
niklase@google.com470e71d2011-07-07 08:21:25 +00001823 }
1824
kwiberg55b97fe2016-01-28 05:22:45 -08001825 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07001826 output_file_player_ = FilePlayer::CreateFilePlayer(
kwiberg55b97fe2016-01-28 05:22:45 -08001827 _outputFilePlayerId, (const FileFormats)format);
niklase@google.com470e71d2011-07-07 08:21:25 +00001828
kwiberg5a25d952016-08-17 07:31:12 -07001829 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001830 _engineStatisticsPtr->SetLastError(
1831 VE_INVALID_ARGUMENT, kTraceError,
1832 "StartPlayingFileLocally() filePlayer format isnot correct");
1833 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001834 }
1835
kwiberg55b97fe2016-01-28 05:22:45 -08001836 const uint32_t notificationTime(0);
henrike@webrtc.orgb37c6282011-10-31 23:53:04 +00001837
kwiberg4ec01d92016-08-22 08:43:54 -07001838 if (output_file_player_->StartPlayingFile(stream, startPosition,
kwiberg5a25d952016-08-17 07:31:12 -07001839 volumeScaling, notificationTime,
1840 stopPosition, codecInst) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001841 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
1842 "StartPlayingFile() failed to "
1843 "start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001844 output_file_player_->StopPlayingFile();
1845 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001846 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001847 }
kwiberg5a25d952016-08-17 07:31:12 -07001848 output_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001849 channel_state_.SetOutputFilePlaying(true);
1850 }
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001851
kwiberg55b97fe2016-01-28 05:22:45 -08001852 if (RegisterFilePlayingToMixer() != 0)
1853 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00001854
kwiberg55b97fe2016-01-28 05:22:45 -08001855 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001856}
1857
kwiberg55b97fe2016-01-28 05:22:45 -08001858int Channel::StopPlayingFileLocally() {
1859 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1860 "Channel::StopPlayingFileLocally()");
niklase@google.com470e71d2011-07-07 08:21:25 +00001861
kwiberg55b97fe2016-01-28 05:22:45 -08001862 if (!channel_state_.Get().output_file_playing) {
niklase@google.com470e71d2011-07-07 08:21:25 +00001863 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001864 }
1865
1866 {
1867 rtc::CritScope cs(&_fileCritSect);
1868
kwiberg5a25d952016-08-17 07:31:12 -07001869 if (output_file_player_->StopPlayingFile() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08001870 _engineStatisticsPtr->SetLastError(
1871 VE_STOP_RECORDING_FAILED, kTraceError,
1872 "StopPlayingFile() could not stop playing");
1873 return -1;
1874 }
kwiberg5a25d952016-08-17 07:31:12 -07001875 output_file_player_->RegisterModuleFileCallback(NULL);
1876 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001877 channel_state_.SetOutputFilePlaying(false);
1878 }
1879 // _fileCritSect cannot be taken while calling
1880 // SetAnonymousMixibilityStatus. Refer to comments in
1881 // StartPlayingFileLocally(const char* ...) for more details.
1882 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, false) != 0) {
1883 _engineStatisticsPtr->SetLastError(
1884 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1885 "StopPlayingFile() failed to stop participant from playing as"
1886 "file in the mixer");
1887 return -1;
1888 }
1889
1890 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001891}
1892
kwiberg55b97fe2016-01-28 05:22:45 -08001893int Channel::IsPlayingFileLocally() const {
1894 return channel_state_.Get().output_file_playing;
niklase@google.com470e71d2011-07-07 08:21:25 +00001895}
1896
kwiberg55b97fe2016-01-28 05:22:45 -08001897int Channel::RegisterFilePlayingToMixer() {
1898 // Return success for not registering for file playing to mixer if:
1899 // 1. playing file before playout is started on that channel.
1900 // 2. starting playout without file playing on that channel.
1901 if (!channel_state_.Get().playing ||
1902 !channel_state_.Get().output_file_playing) {
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001903 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001904 }
1905
1906 // |_fileCritSect| cannot be taken while calling
1907 // SetAnonymousMixabilityStatus() since as soon as the participant is added
1908 // frames can be pulled by the mixer. Since the frames are generated from
1909 // the file, _fileCritSect will be taken. This would result in a deadlock.
1910 if (_outputMixerPtr->SetAnonymousMixabilityStatus(*this, true) != 0) {
1911 channel_state_.SetOutputFilePlaying(false);
1912 rtc::CritScope cs(&_fileCritSect);
1913 _engineStatisticsPtr->SetLastError(
1914 VE_AUDIO_CONF_MIX_MODULE_ERROR, kTraceError,
1915 "StartPlayingFile() failed to add participant as file to mixer");
kwiberg5a25d952016-08-17 07:31:12 -07001916 output_file_player_->StopPlayingFile();
1917 output_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001918 return -1;
1919 }
1920
1921 return 0;
braveyao@webrtc.orgab129902012-06-04 03:26:39 +00001922}
1923
niklase@google.com470e71d2011-07-07 08:21:25 +00001924int Channel::StartPlayingFileAsMicrophone(const char* fileName,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001925 bool loop,
1926 FileFormats format,
1927 int startPosition,
1928 float volumeScaling,
1929 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001930 const CodecInst* codecInst) {
1931 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1932 "Channel::StartPlayingFileAsMicrophone(fileNameUTF8[]=%s, "
1933 "loop=%d, format=%d, volumeScaling=%5.3f, startPosition=%d, "
1934 "stopPosition=%d)",
1935 fileName, loop, format, volumeScaling, startPosition,
1936 stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001937
kwiberg55b97fe2016-01-28 05:22:45 -08001938 rtc::CritScope cs(&_fileCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00001939
kwiberg55b97fe2016-01-28 05:22:45 -08001940 if (channel_state_.Get().input_file_playing) {
1941 _engineStatisticsPtr->SetLastError(
1942 VE_ALREADY_PLAYING, kTraceWarning,
1943 "StartPlayingFileAsMicrophone() filePlayer is playing");
niklase@google.com470e71d2011-07-07 08:21:25 +00001944 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08001945 }
1946
1947 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07001948 if (input_file_player_) {
1949 input_file_player_->RegisterModuleFileCallback(NULL);
1950 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001951 }
1952
1953 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07001954 input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
kwiberg5a25d952016-08-17 07:31:12 -07001955 (const FileFormats)format);
kwiberg55b97fe2016-01-28 05:22:45 -08001956
kwiberg5a25d952016-08-17 07:31:12 -07001957 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08001958 _engineStatisticsPtr->SetLastError(
1959 VE_INVALID_ARGUMENT, kTraceError,
1960 "StartPlayingFileAsMicrophone() filePlayer format isnot correct");
1961 return -1;
1962 }
1963
1964 const uint32_t notificationTime(0);
1965
kwiberg5a25d952016-08-17 07:31:12 -07001966 if (input_file_player_->StartPlayingFile(
kwiberg55b97fe2016-01-28 05:22:45 -08001967 fileName, loop, startPosition, volumeScaling, notificationTime,
1968 stopPosition, (const CodecInst*)codecInst) != 0) {
1969 _engineStatisticsPtr->SetLastError(
1970 VE_BAD_FILE, kTraceError,
1971 "StartPlayingFile() failed to start file playout");
kwiberg5a25d952016-08-17 07:31:12 -07001972 input_file_player_->StopPlayingFile();
1973 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08001974 return -1;
1975 }
kwiberg5a25d952016-08-17 07:31:12 -07001976 input_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08001977 channel_state_.SetInputFilePlaying(true);
1978
1979 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00001980}
1981
1982int Channel::StartPlayingFileAsMicrophone(InStream* stream,
pbos@webrtc.org92135212013-05-14 08:31:39 +00001983 FileFormats format,
1984 int startPosition,
1985 float volumeScaling,
1986 int stopPosition,
kwiberg55b97fe2016-01-28 05:22:45 -08001987 const CodecInst* codecInst) {
1988 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
1989 "Channel::StartPlayingFileAsMicrophone(format=%d, "
1990 "volumeScaling=%5.3f, startPosition=%d, stopPosition=%d)",
1991 format, volumeScaling, startPosition, stopPosition);
niklase@google.com470e71d2011-07-07 08:21:25 +00001992
kwiberg55b97fe2016-01-28 05:22:45 -08001993 if (stream == NULL) {
1994 _engineStatisticsPtr->SetLastError(
1995 VE_BAD_FILE, kTraceError,
1996 "StartPlayingFileAsMicrophone NULL as input stream");
1997 return -1;
1998 }
niklase@google.com470e71d2011-07-07 08:21:25 +00001999
kwiberg55b97fe2016-01-28 05:22:45 -08002000 rtc::CritScope cs(&_fileCritSect);
henrika@webrtc.org944cbeb2014-03-18 10:32:33 +00002001
kwiberg55b97fe2016-01-28 05:22:45 -08002002 if (channel_state_.Get().input_file_playing) {
2003 _engineStatisticsPtr->SetLastError(
2004 VE_ALREADY_PLAYING, kTraceWarning,
2005 "StartPlayingFileAsMicrophone() is playing");
niklase@google.com470e71d2011-07-07 08:21:25 +00002006 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002007 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002008
kwiberg55b97fe2016-01-28 05:22:45 -08002009 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002010 if (input_file_player_) {
2011 input_file_player_->RegisterModuleFileCallback(NULL);
2012 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002013 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002014
kwiberg55b97fe2016-01-28 05:22:45 -08002015 // Create the instance
kwiberg5b356f42016-09-08 04:32:33 -07002016 input_file_player_ = FilePlayer::CreateFilePlayer(_inputFilePlayerId,
kwiberg5a25d952016-08-17 07:31:12 -07002017 (const FileFormats)format);
kwiberg55b97fe2016-01-28 05:22:45 -08002018
kwiberg5a25d952016-08-17 07:31:12 -07002019 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002020 _engineStatisticsPtr->SetLastError(
2021 VE_INVALID_ARGUMENT, kTraceError,
2022 "StartPlayingInputFile() filePlayer format isnot correct");
2023 return -1;
2024 }
2025
2026 const uint32_t notificationTime(0);
2027
kwiberg4ec01d92016-08-22 08:43:54 -07002028 if (input_file_player_->StartPlayingFile(stream, startPosition, volumeScaling,
2029 notificationTime, stopPosition,
2030 codecInst) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002031 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2032 "StartPlayingFile() failed to start "
2033 "file playout");
kwiberg5a25d952016-08-17 07:31:12 -07002034 input_file_player_->StopPlayingFile();
2035 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002036 return -1;
2037 }
2038
kwiberg5a25d952016-08-17 07:31:12 -07002039 input_file_player_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002040 channel_state_.SetInputFilePlaying(true);
2041
2042 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002043}
2044
kwiberg55b97fe2016-01-28 05:22:45 -08002045int Channel::StopPlayingFileAsMicrophone() {
2046 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2047 "Channel::StopPlayingFileAsMicrophone()");
2048
2049 rtc::CritScope cs(&_fileCritSect);
2050
2051 if (!channel_state_.Get().input_file_playing) {
2052 return 0;
2053 }
2054
kwiberg5a25d952016-08-17 07:31:12 -07002055 if (input_file_player_->StopPlayingFile() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002056 _engineStatisticsPtr->SetLastError(
2057 VE_STOP_RECORDING_FAILED, kTraceError,
2058 "StopPlayingFile() could not stop playing");
2059 return -1;
2060 }
kwiberg5a25d952016-08-17 07:31:12 -07002061 input_file_player_->RegisterModuleFileCallback(NULL);
2062 input_file_player_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002063 channel_state_.SetInputFilePlaying(false);
2064
2065 return 0;
2066}
2067
2068int Channel::IsPlayingFileAsMicrophone() const {
2069 return channel_state_.Get().input_file_playing;
niklase@google.com470e71d2011-07-07 08:21:25 +00002070}
2071
leozwang@webrtc.org813e4b02012-03-01 18:34:25 +00002072int Channel::StartRecordingPlayout(const char* fileName,
kwiberg55b97fe2016-01-28 05:22:45 -08002073 const CodecInst* codecInst) {
2074 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2075 "Channel::StartRecordingPlayout(fileName=%s)", fileName);
niklase@google.com470e71d2011-07-07 08:21:25 +00002076
kwiberg55b97fe2016-01-28 05:22:45 -08002077 if (_outputFileRecording) {
2078 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2079 "StartRecordingPlayout() is already recording");
niklase@google.com470e71d2011-07-07 08:21:25 +00002080 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002081 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002082
kwiberg55b97fe2016-01-28 05:22:45 -08002083 FileFormats format;
2084 const uint32_t notificationTime(0); // Not supported in VoE
2085 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
niklase@google.com470e71d2011-07-07 08:21:25 +00002086
kwiberg55b97fe2016-01-28 05:22:45 -08002087 if ((codecInst != NULL) &&
2088 ((codecInst->channels < 1) || (codecInst->channels > 2))) {
2089 _engineStatisticsPtr->SetLastError(
2090 VE_BAD_ARGUMENT, kTraceError,
2091 "StartRecordingPlayout() invalid compression");
2092 return (-1);
2093 }
2094 if (codecInst == NULL) {
2095 format = kFileFormatPcm16kHzFile;
2096 codecInst = &dummyCodec;
2097 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2098 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2099 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2100 format = kFileFormatWavFile;
2101 } else {
2102 format = kFileFormatCompressedFile;
2103 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002104
kwiberg55b97fe2016-01-28 05:22:45 -08002105 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002106
kwiberg55b97fe2016-01-28 05:22:45 -08002107 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002108 if (output_file_recorder_) {
2109 output_file_recorder_->RegisterModuleFileCallback(NULL);
2110 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002111 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002112
kwiberg5a25d952016-08-17 07:31:12 -07002113 output_file_recorder_ = FileRecorder::CreateFileRecorder(
kwiberg55b97fe2016-01-28 05:22:45 -08002114 _outputFileRecorderId, (const FileFormats)format);
kwiberg5a25d952016-08-17 07:31:12 -07002115 if (!output_file_recorder_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002116 _engineStatisticsPtr->SetLastError(
2117 VE_INVALID_ARGUMENT, kTraceError,
2118 "StartRecordingPlayout() fileRecorder format isnot correct");
2119 return -1;
2120 }
2121
kwiberg5a25d952016-08-17 07:31:12 -07002122 if (output_file_recorder_->StartRecordingAudioFile(
kwiberg55b97fe2016-01-28 05:22:45 -08002123 fileName, (const CodecInst&)*codecInst, notificationTime) != 0) {
2124 _engineStatisticsPtr->SetLastError(
2125 VE_BAD_FILE, kTraceError,
2126 "StartRecordingAudioFile() failed to start file recording");
kwiberg5a25d952016-08-17 07:31:12 -07002127 output_file_recorder_->StopRecording();
2128 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002129 return -1;
2130 }
kwiberg5a25d952016-08-17 07:31:12 -07002131 output_file_recorder_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002132 _outputFileRecording = true;
2133
2134 return 0;
2135}
2136
2137int Channel::StartRecordingPlayout(OutStream* stream,
2138 const CodecInst* codecInst) {
2139 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2140 "Channel::StartRecordingPlayout()");
2141
2142 if (_outputFileRecording) {
2143 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, -1),
2144 "StartRecordingPlayout() is already recording");
niklase@google.com470e71d2011-07-07 08:21:25 +00002145 return 0;
kwiberg55b97fe2016-01-28 05:22:45 -08002146 }
2147
2148 FileFormats format;
2149 const uint32_t notificationTime(0); // Not supported in VoE
2150 CodecInst dummyCodec = {100, "L16", 16000, 320, 1, 320000};
2151
2152 if (codecInst != NULL && codecInst->channels != 1) {
2153 _engineStatisticsPtr->SetLastError(
2154 VE_BAD_ARGUMENT, kTraceError,
2155 "StartRecordingPlayout() invalid compression");
2156 return (-1);
2157 }
2158 if (codecInst == NULL) {
2159 format = kFileFormatPcm16kHzFile;
2160 codecInst = &dummyCodec;
2161 } else if ((STR_CASE_CMP(codecInst->plname, "L16") == 0) ||
2162 (STR_CASE_CMP(codecInst->plname, "PCMU") == 0) ||
2163 (STR_CASE_CMP(codecInst->plname, "PCMA") == 0)) {
2164 format = kFileFormatWavFile;
2165 } else {
2166 format = kFileFormatCompressedFile;
2167 }
2168
2169 rtc::CritScope cs(&_fileCritSect);
2170
2171 // Destroy the old instance
kwiberg5a25d952016-08-17 07:31:12 -07002172 if (output_file_recorder_) {
2173 output_file_recorder_->RegisterModuleFileCallback(NULL);
2174 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002175 }
2176
kwiberg5a25d952016-08-17 07:31:12 -07002177 output_file_recorder_ = FileRecorder::CreateFileRecorder(
kwiberg55b97fe2016-01-28 05:22:45 -08002178 _outputFileRecorderId, (const FileFormats)format);
kwiberg5a25d952016-08-17 07:31:12 -07002179 if (!output_file_recorder_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002180 _engineStatisticsPtr->SetLastError(
2181 VE_INVALID_ARGUMENT, kTraceError,
2182 "StartRecordingPlayout() fileRecorder format isnot correct");
2183 return -1;
2184 }
2185
kwiberg4ec01d92016-08-22 08:43:54 -07002186 if (output_file_recorder_->StartRecordingAudioFile(stream, *codecInst,
kwiberg5a25d952016-08-17 07:31:12 -07002187 notificationTime) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002188 _engineStatisticsPtr->SetLastError(VE_BAD_FILE, kTraceError,
2189 "StartRecordingPlayout() failed to "
2190 "start file recording");
kwiberg5a25d952016-08-17 07:31:12 -07002191 output_file_recorder_->StopRecording();
2192 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002193 return -1;
2194 }
2195
kwiberg5a25d952016-08-17 07:31:12 -07002196 output_file_recorder_->RegisterModuleFileCallback(this);
kwiberg55b97fe2016-01-28 05:22:45 -08002197 _outputFileRecording = true;
2198
2199 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002200}
2201
kwiberg55b97fe2016-01-28 05:22:45 -08002202int Channel::StopRecordingPlayout() {
2203 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, -1),
2204 "Channel::StopRecordingPlayout()");
2205
2206 if (!_outputFileRecording) {
2207 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, -1),
2208 "StopRecordingPlayout() isnot recording");
2209 return -1;
2210 }
2211
2212 rtc::CritScope cs(&_fileCritSect);
2213
kwiberg5a25d952016-08-17 07:31:12 -07002214 if (output_file_recorder_->StopRecording() != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002215 _engineStatisticsPtr->SetLastError(
2216 VE_STOP_RECORDING_FAILED, kTraceError,
2217 "StopRecording() could not stop recording");
2218 return (-1);
2219 }
kwiberg5a25d952016-08-17 07:31:12 -07002220 output_file_recorder_->RegisterModuleFileCallback(NULL);
2221 output_file_recorder_.reset();
kwiberg55b97fe2016-01-28 05:22:45 -08002222 _outputFileRecording = false;
2223
2224 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002225}
2226
kwiberg55b97fe2016-01-28 05:22:45 -08002227void Channel::SetMixWithMicStatus(bool mix) {
2228 rtc::CritScope cs(&_fileCritSect);
2229 _mixFileWithMicrophone = mix;
niklase@google.com470e71d2011-07-07 08:21:25 +00002230}
2231
kwiberg55b97fe2016-01-28 05:22:45 -08002232int Channel::GetSpeechOutputLevel(uint32_t& level) const {
2233 int8_t currentLevel = _outputAudioLevel.Level();
2234 level = static_cast<int32_t>(currentLevel);
2235 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002236}
2237
kwiberg55b97fe2016-01-28 05:22:45 -08002238int Channel::GetSpeechOutputLevelFullRange(uint32_t& level) const {
2239 int16_t currentLevel = _outputAudioLevel.LevelFullRange();
2240 level = static_cast<int32_t>(currentLevel);
2241 return 0;
2242}
2243
solenberg1c2af8e2016-03-24 10:36:00 -07002244int Channel::SetInputMute(bool enable) {
kwiberg55b97fe2016-01-28 05:22:45 -08002245 rtc::CritScope cs(&volume_settings_critsect_);
2246 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002247 "Channel::SetMute(enable=%d)", enable);
solenberg1c2af8e2016-03-24 10:36:00 -07002248 input_mute_ = enable;
kwiberg55b97fe2016-01-28 05:22:45 -08002249 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002250}
2251
solenberg1c2af8e2016-03-24 10:36:00 -07002252bool Channel::InputMute() const {
kwiberg55b97fe2016-01-28 05:22:45 -08002253 rtc::CritScope cs(&volume_settings_critsect_);
solenberg1c2af8e2016-03-24 10:36:00 -07002254 return input_mute_;
niklase@google.com470e71d2011-07-07 08:21:25 +00002255}
2256
kwiberg55b97fe2016-01-28 05:22:45 -08002257int Channel::SetOutputVolumePan(float left, float right) {
2258 rtc::CritScope cs(&volume_settings_critsect_);
2259 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002260 "Channel::SetOutputVolumePan()");
kwiberg55b97fe2016-01-28 05:22:45 -08002261 _panLeft = left;
2262 _panRight = right;
2263 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002264}
2265
kwiberg55b97fe2016-01-28 05:22:45 -08002266int Channel::GetOutputVolumePan(float& left, float& right) const {
2267 rtc::CritScope cs(&volume_settings_critsect_);
2268 left = _panLeft;
2269 right = _panRight;
2270 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002271}
2272
kwiberg55b97fe2016-01-28 05:22:45 -08002273int Channel::SetChannelOutputVolumeScaling(float scaling) {
2274 rtc::CritScope cs(&volume_settings_critsect_);
2275 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002276 "Channel::SetChannelOutputVolumeScaling()");
kwiberg55b97fe2016-01-28 05:22:45 -08002277 _outputGain = scaling;
2278 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002279}
2280
kwiberg55b97fe2016-01-28 05:22:45 -08002281int Channel::GetChannelOutputVolumeScaling(float& scaling) const {
2282 rtc::CritScope cs(&volume_settings_critsect_);
2283 scaling = _outputGain;
2284 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002285}
2286
solenberg8842c3e2016-03-11 03:06:41 -08002287int Channel::SendTelephoneEventOutband(int event, int duration_ms) {
kwiberg55b97fe2016-01-28 05:22:45 -08002288 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
solenberg8842c3e2016-03-11 03:06:41 -08002289 "Channel::SendTelephoneEventOutband(...)");
2290 RTC_DCHECK_LE(0, event);
2291 RTC_DCHECK_GE(255, event);
2292 RTC_DCHECK_LE(0, duration_ms);
2293 RTC_DCHECK_GE(65535, duration_ms);
kwiberg55b97fe2016-01-28 05:22:45 -08002294 if (!Sending()) {
2295 return -1;
2296 }
solenberg8842c3e2016-03-11 03:06:41 -08002297 if (_rtpRtcpModule->SendTelephoneEventOutband(
2298 event, duration_ms, kTelephoneEventAttenuationdB) != 0) {
kwiberg55b97fe2016-01-28 05:22:45 -08002299 _engineStatisticsPtr->SetLastError(
2300 VE_SEND_DTMF_FAILED, kTraceWarning,
2301 "SendTelephoneEventOutband() failed to send event");
2302 return -1;
2303 }
2304 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002305}
2306
solenbergffbbcac2016-11-17 05:25:37 -08002307int Channel::SetSendTelephoneEventPayloadType(int payload_type,
2308 int payload_frequency) {
kwiberg55b97fe2016-01-28 05:22:45 -08002309 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
niklase@google.com470e71d2011-07-07 08:21:25 +00002310 "Channel::SetSendTelephoneEventPayloadType()");
solenberg31642aa2016-03-14 08:00:37 -07002311 RTC_DCHECK_LE(0, payload_type);
2312 RTC_DCHECK_GE(127, payload_type);
2313 CodecInst codec = {0};
solenberg31642aa2016-03-14 08:00:37 -07002314 codec.pltype = payload_type;
solenbergffbbcac2016-11-17 05:25:37 -08002315 codec.plfreq = payload_frequency;
kwiberg55b97fe2016-01-28 05:22:45 -08002316 memcpy(codec.plname, "telephone-event", 16);
2317 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2318 _rtpRtcpModule->DeRegisterSendPayload(codec.pltype);
2319 if (_rtpRtcpModule->RegisterSendPayload(codec) != 0) {
2320 _engineStatisticsPtr->SetLastError(
2321 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2322 "SetSendTelephoneEventPayloadType() failed to register send"
2323 "payload type");
2324 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002325 }
kwiberg55b97fe2016-01-28 05:22:45 -08002326 }
kwiberg55b97fe2016-01-28 05:22:45 -08002327 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002328}
2329
kwiberg55b97fe2016-01-28 05:22:45 -08002330int Channel::VoiceActivityIndicator(int& activity) {
2331 activity = _sendFrameType;
2332 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002333}
2334
kwiberg55b97fe2016-01-28 05:22:45 -08002335int Channel::SetLocalSSRC(unsigned int ssrc) {
2336 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2337 "Channel::SetLocalSSRC()");
2338 if (channel_state_.Get().sending) {
2339 _engineStatisticsPtr->SetLastError(VE_ALREADY_SENDING, kTraceError,
2340 "SetLocalSSRC() already sending");
2341 return -1;
2342 }
2343 _rtpRtcpModule->SetSSRC(ssrc);
2344 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002345}
2346
kwiberg55b97fe2016-01-28 05:22:45 -08002347int Channel::GetLocalSSRC(unsigned int& ssrc) {
2348 ssrc = _rtpRtcpModule->SSRC();
2349 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002350}
2351
kwiberg55b97fe2016-01-28 05:22:45 -08002352int Channel::GetRemoteSSRC(unsigned int& ssrc) {
2353 ssrc = rtp_receiver_->SSRC();
2354 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002355}
2356
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002357int Channel::SetSendAudioLevelIndicationStatus(bool enable, unsigned char id) {
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +00002358 _includeAudioLevelIndication = enable;
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002359 return SetSendRtpHeaderExtension(enable, kRtpExtensionAudioLevel, id);
niklase@google.com470e71d2011-07-07 08:21:25 +00002360}
andrew@webrtc.orgf3930e92013-09-18 22:37:32 +00002361
wu@webrtc.org93fd25c2014-04-24 20:33:08 +00002362int Channel::SetReceiveAudioLevelIndicationStatus(bool enable,
2363 unsigned char id) {
kwiberg55b97fe2016-01-28 05:22:45 -08002364 rtp_header_parser_->DeregisterRtpHeaderExtension(kRtpExtensionAudioLevel);
2365 if (enable &&
2366 !rtp_header_parser_->RegisterRtpHeaderExtension(kRtpExtensionAudioLevel,
2367 id)) {
wu@webrtc.org93fd25c2014-04-24 20:33:08 +00002368 return -1;
2369 }
2370 return 0;
2371}
2372
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002373void Channel::EnableSendTransportSequenceNumber(int id) {
2374 int ret =
2375 SetSendRtpHeaderExtension(true, kRtpExtensionTransportSequenceNumber, id);
2376 RTC_DCHECK_EQ(0, ret);
2377}
2378
stefan3313ec92016-01-21 06:32:43 -08002379void Channel::EnableReceiveTransportSequenceNumber(int id) {
2380 rtp_header_parser_->DeregisterRtpHeaderExtension(
2381 kRtpExtensionTransportSequenceNumber);
2382 bool ret = rtp_header_parser_->RegisterRtpHeaderExtension(
2383 kRtpExtensionTransportSequenceNumber, id);
2384 RTC_DCHECK(ret);
2385}
2386
stefanbba9dec2016-02-01 04:39:55 -08002387void Channel::RegisterSenderCongestionControlObjects(
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002388 RtpPacketSender* rtp_packet_sender,
2389 TransportFeedbackObserver* transport_feedback_observer,
stefan7de8d642017-02-07 07:14:08 -08002390 PacketRouter* packet_router,
2391 RtcpBandwidthObserver* bandwidth_observer) {
stefanbba9dec2016-02-01 04:39:55 -08002392 RTC_DCHECK(rtp_packet_sender);
2393 RTC_DCHECK(transport_feedback_observer);
2394 RTC_DCHECK(packet_router && !packet_router_);
stefan7de8d642017-02-07 07:14:08 -08002395 rtcp_observer_->SetBandwidthObserver(bandwidth_observer);
stefanbba9dec2016-02-01 04:39:55 -08002396 feedback_observer_proxy_->SetTransportFeedbackObserver(
2397 transport_feedback_observer);
2398 seq_num_allocator_proxy_->SetSequenceNumberAllocator(packet_router);
2399 rtp_packet_sender_proxy_->SetPacketSender(rtp_packet_sender);
2400 _rtpRtcpModule->SetStorePacketsStatus(true, 600);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002401 packet_router->AddRtpModule(_rtpRtcpModule.get());
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002402 packet_router_ = packet_router;
2403}
2404
stefanbba9dec2016-02-01 04:39:55 -08002405void Channel::RegisterReceiverCongestionControlObjects(
2406 PacketRouter* packet_router) {
2407 RTC_DCHECK(packet_router && !packet_router_);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002408 packet_router->AddRtpModule(_rtpRtcpModule.get());
stefanbba9dec2016-02-01 04:39:55 -08002409 packet_router_ = packet_router;
2410}
2411
2412void Channel::ResetCongestionControlObjects() {
2413 RTC_DCHECK(packet_router_);
2414 _rtpRtcpModule->SetStorePacketsStatus(false, 600);
stefan7de8d642017-02-07 07:14:08 -08002415 rtcp_observer_->SetBandwidthObserver(nullptr);
stefanbba9dec2016-02-01 04:39:55 -08002416 feedback_observer_proxy_->SetTransportFeedbackObserver(nullptr);
2417 seq_num_allocator_proxy_->SetSequenceNumberAllocator(nullptr);
Peter Boström3dd5d1d2016-02-25 16:56:48 +01002418 packet_router_->RemoveRtpModule(_rtpRtcpModule.get());
stefanbba9dec2016-02-01 04:39:55 -08002419 packet_router_ = nullptr;
2420 rtp_packet_sender_proxy_->SetPacketSender(nullptr);
2421}
2422
pbos@webrtc.orgd16e8392014-12-19 13:49:55 +00002423void Channel::SetRTCPStatus(bool enable) {
2424 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2425 "Channel::SetRTCPStatus()");
pbosda903ea2015-10-02 02:36:56 -07002426 _rtpRtcpModule->SetRTCPStatus(enable ? RtcpMode::kCompound : RtcpMode::kOff);
niklase@google.com470e71d2011-07-07 08:21:25 +00002427}
2428
kwiberg55b97fe2016-01-28 05:22:45 -08002429int Channel::GetRTCPStatus(bool& enabled) {
pbosda903ea2015-10-02 02:36:56 -07002430 RtcpMode method = _rtpRtcpModule->RTCP();
2431 enabled = (method != RtcpMode::kOff);
kwiberg55b97fe2016-01-28 05:22:45 -08002432 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002433}
2434
kwiberg55b97fe2016-01-28 05:22:45 -08002435int Channel::SetRTCP_CNAME(const char cName[256]) {
2436 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2437 "Channel::SetRTCP_CNAME()");
2438 if (_rtpRtcpModule->SetCNAME(cName) != 0) {
2439 _engineStatisticsPtr->SetLastError(
2440 VE_RTP_RTCP_MODULE_ERROR, kTraceError,
2441 "SetRTCP_CNAME() failed to set RTCP CNAME");
2442 return -1;
2443 }
2444 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002445}
2446
kwiberg55b97fe2016-01-28 05:22:45 -08002447int Channel::GetRemoteRTCP_CNAME(char cName[256]) {
2448 if (cName == NULL) {
2449 _engineStatisticsPtr->SetLastError(
2450 VE_INVALID_ARGUMENT, kTraceError,
2451 "GetRemoteRTCP_CNAME() invalid CNAME input buffer");
2452 return -1;
2453 }
2454 char cname[RTCP_CNAME_SIZE];
2455 const uint32_t remoteSSRC = rtp_receiver_->SSRC();
2456 if (_rtpRtcpModule->RemoteCNAME(remoteSSRC, cname) != 0) {
2457 _engineStatisticsPtr->SetLastError(
2458 VE_CANNOT_RETRIEVE_CNAME, kTraceError,
2459 "GetRemoteRTCP_CNAME() failed to retrieve remote RTCP CNAME");
2460 return -1;
2461 }
2462 strcpy(cName, cname);
2463 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002464}
2465
kwiberg55b97fe2016-01-28 05:22:45 -08002466int Channel::SendApplicationDefinedRTCPPacket(
2467 unsigned char subType,
2468 unsigned int name,
2469 const char* data,
2470 unsigned short dataLengthInBytes) {
2471 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2472 "Channel::SendApplicationDefinedRTCPPacket()");
2473 if (!channel_state_.Get().sending) {
2474 _engineStatisticsPtr->SetLastError(
2475 VE_NOT_SENDING, kTraceError,
2476 "SendApplicationDefinedRTCPPacket() not sending");
2477 return -1;
2478 }
2479 if (NULL == data) {
2480 _engineStatisticsPtr->SetLastError(
2481 VE_INVALID_ARGUMENT, kTraceError,
2482 "SendApplicationDefinedRTCPPacket() invalid data value");
2483 return -1;
2484 }
2485 if (dataLengthInBytes % 4 != 0) {
2486 _engineStatisticsPtr->SetLastError(
2487 VE_INVALID_ARGUMENT, kTraceError,
2488 "SendApplicationDefinedRTCPPacket() invalid length value");
2489 return -1;
2490 }
2491 RtcpMode status = _rtpRtcpModule->RTCP();
2492 if (status == RtcpMode::kOff) {
2493 _engineStatisticsPtr->SetLastError(
2494 VE_RTCP_ERROR, kTraceError,
2495 "SendApplicationDefinedRTCPPacket() RTCP is disabled");
2496 return -1;
2497 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002498
kwiberg55b97fe2016-01-28 05:22:45 -08002499 // Create and schedule the RTCP APP packet for transmission
2500 if (_rtpRtcpModule->SetRTCPApplicationSpecificData(
2501 subType, name, (const unsigned char*)data, dataLengthInBytes) != 0) {
2502 _engineStatisticsPtr->SetLastError(
2503 VE_SEND_ERROR, kTraceError,
2504 "SendApplicationDefinedRTCPPacket() failed to send RTCP packet");
2505 return -1;
2506 }
2507 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002508}
2509
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002510int Channel::GetRemoteRTCPReportBlocks(
2511 std::vector<ReportBlock>* report_blocks) {
2512 if (report_blocks == NULL) {
kwiberg55b97fe2016-01-28 05:22:45 -08002513 _engineStatisticsPtr->SetLastError(
2514 VE_INVALID_ARGUMENT, kTraceError,
2515 "GetRemoteRTCPReportBlock()s invalid report_blocks.");
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002516 return -1;
2517 }
2518
2519 // Get the report blocks from the latest received RTCP Sender or Receiver
2520 // Report. Each element in the vector contains the sender's SSRC and a
2521 // report block according to RFC 3550.
2522 std::vector<RTCPReportBlock> rtcp_report_blocks;
2523 if (_rtpRtcpModule->RemoteRTCPStat(&rtcp_report_blocks) != 0) {
henrika@webrtc.org8a2fc882012-08-22 08:53:55 +00002524 return -1;
2525 }
2526
2527 if (rtcp_report_blocks.empty())
2528 return 0;
2529
2530 std::vector<RTCPReportBlock>::const_iterator it = rtcp_report_blocks.begin();
2531 for (; it != rtcp_report_blocks.end(); ++it) {
2532 ReportBlock report_block;
2533 report_block.sender_SSRC = it->remoteSSRC;
2534 report_block.source_SSRC = it->sourceSSRC;
2535 report_block.fraction_lost = it->fractionLost;
2536 report_block.cumulative_num_packets_lost = it->cumulativeLost;
2537 report_block.extended_highest_sequence_number = it->extendedHighSeqNum;
2538 report_block.interarrival_jitter = it->jitter;
2539 report_block.last_SR_timestamp = it->lastSR;
2540 report_block.delay_since_last_SR = it->delaySinceLastSR;
2541 report_blocks->push_back(report_block);
2542 }
2543 return 0;
2544}
2545
kwiberg55b97fe2016-01-28 05:22:45 -08002546int Channel::GetRTPStatistics(CallStatistics& stats) {
2547 // --- RtcpStatistics
niklase@google.com470e71d2011-07-07 08:21:25 +00002548
kwiberg55b97fe2016-01-28 05:22:45 -08002549 // The jitter statistics is updated for each received RTP packet and is
2550 // based on received packets.
2551 RtcpStatistics statistics;
2552 StreamStatistician* statistician =
2553 rtp_receive_statistics_->GetStatistician(rtp_receiver_->SSRC());
Peter Boström59013bc2016-02-12 11:35:08 +01002554 if (statistician) {
2555 statistician->GetStatistics(&statistics,
2556 _rtpRtcpModule->RTCP() == RtcpMode::kOff);
kwiberg55b97fe2016-01-28 05:22:45 -08002557 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002558
kwiberg55b97fe2016-01-28 05:22:45 -08002559 stats.fractionLost = statistics.fraction_lost;
2560 stats.cumulativeLost = statistics.cumulative_lost;
2561 stats.extendedMax = statistics.extended_max_sequence_number;
2562 stats.jitterSamples = statistics.jitter;
niklase@google.com470e71d2011-07-07 08:21:25 +00002563
kwiberg55b97fe2016-01-28 05:22:45 -08002564 // --- RTT
2565 stats.rttMs = GetRTT(true);
niklase@google.com470e71d2011-07-07 08:21:25 +00002566
kwiberg55b97fe2016-01-28 05:22:45 -08002567 // --- Data counters
niklase@google.com470e71d2011-07-07 08:21:25 +00002568
kwiberg55b97fe2016-01-28 05:22:45 -08002569 size_t bytesSent(0);
2570 uint32_t packetsSent(0);
2571 size_t bytesReceived(0);
2572 uint32_t packetsReceived(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002573
kwiberg55b97fe2016-01-28 05:22:45 -08002574 if (statistician) {
2575 statistician->GetDataCounters(&bytesReceived, &packetsReceived);
2576 }
wu@webrtc.org822fbd82013-08-15 23:38:54 +00002577
kwiberg55b97fe2016-01-28 05:22:45 -08002578 if (_rtpRtcpModule->DataCountersRTP(&bytesSent, &packetsSent) != 0) {
2579 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2580 "GetRTPStatistics() failed to retrieve RTP datacounters =>"
2581 " output will not be complete");
2582 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002583
kwiberg55b97fe2016-01-28 05:22:45 -08002584 stats.bytesSent = bytesSent;
2585 stats.packetsSent = packetsSent;
2586 stats.bytesReceived = bytesReceived;
2587 stats.packetsReceived = packetsReceived;
niklase@google.com470e71d2011-07-07 08:21:25 +00002588
kwiberg55b97fe2016-01-28 05:22:45 -08002589 // --- Timestamps
2590 {
2591 rtc::CritScope lock(&ts_stats_lock_);
2592 stats.capture_start_ntp_time_ms_ = capture_start_ntp_time_ms_;
2593 }
2594 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002595}
2596
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002597int Channel::SetCodecFECStatus(bool enable) {
2598 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2599 "Channel::SetCodecFECStatus()");
2600
kwibergc8d071e2016-04-06 12:22:38 -07002601 if (!codec_manager_.SetCodecFEC(enable) ||
2602 !codec_manager_.MakeEncoder(&rent_a_codec_, audio_coding_.get())) {
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002603 _engineStatisticsPtr->SetLastError(
2604 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2605 "SetCodecFECStatus() failed to set FEC state");
2606 return -1;
2607 }
2608 return 0;
2609}
2610
2611bool Channel::GetCodecFECStatus() {
kwibergc8d071e2016-04-06 12:22:38 -07002612 return codec_manager_.GetStackParams()->use_codec_fec;
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002613}
2614
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002615void Channel::SetNACKStatus(bool enable, int maxNumberOfPackets) {
2616 // None of these functions can fail.
Stefan Holmerb86d4e42015-12-07 10:26:18 +01002617 // If pacing is enabled we always store packets.
2618 if (!pacing_enabled_)
2619 _rtpRtcpModule->SetStorePacketsStatus(enable, maxNumberOfPackets);
stefan@webrtc.org7bb8f022013-09-06 13:40:11 +00002620 rtp_receive_statistics_->SetMaxReorderingThreshold(maxNumberOfPackets);
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002621 if (enable)
andrew@webrtc.orgeb524d92013-09-23 23:02:24 +00002622 audio_coding_->EnableNack(maxNumberOfPackets);
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002623 else
andrew@webrtc.orgeb524d92013-09-23 23:02:24 +00002624 audio_coding_->DisableNack();
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002625}
2626
pwestin@webrtc.orgd30859e2013-06-06 21:09:01 +00002627// Called when we are missing one or more packets.
2628int Channel::ResendPackets(const uint16_t* sequence_numbers, int length) {
pwestin@webrtc.orgdb249952013-06-05 15:33:20 +00002629 return _rtpRtcpModule->SendNACK(sequence_numbers, length);
2630}
2631
kwiberg55b97fe2016-01-28 05:22:45 -08002632uint32_t Channel::Demultiplex(const AudioFrame& audioFrame) {
2633 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2634 "Channel::Demultiplex()");
2635 _audioFrame.CopyFrom(audioFrame);
2636 _audioFrame.id_ = _channelId;
2637 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002638}
2639
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002640void Channel::Demultiplex(const int16_t* audio_data,
xians@webrtc.org8fff1f02013-07-31 16:27:42 +00002641 int sample_rate,
Peter Kastingdce40cf2015-08-24 14:52:23 -07002642 size_t number_of_frames,
Peter Kasting69558702016-01-12 16:26:35 -08002643 size_t number_of_channels) {
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002644 CodecInst codec;
2645 GetSendCodec(codec);
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002646
Alejandro Luebscdfe20b2015-09-23 12:49:12 -07002647 // Never upsample or upmix the capture signal here. This should be done at the
2648 // end of the send chain.
2649 _audioFrame.sample_rate_hz_ = std::min(codec.plfreq, sample_rate);
2650 _audioFrame.num_channels_ = std::min(number_of_channels, codec.channels);
2651 RemixAndResample(audio_data, number_of_frames, number_of_channels,
2652 sample_rate, &input_resampler_, &_audioFrame);
xians@webrtc.org2f84afa2013-07-31 16:23:37 +00002653}
2654
kwiberg55b97fe2016-01-28 05:22:45 -08002655uint32_t Channel::PrepareEncodeAndSend(int mixingFrequency) {
2656 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2657 "Channel::PrepareEncodeAndSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002658
kwiberg55b97fe2016-01-28 05:22:45 -08002659 if (_audioFrame.samples_per_channel_ == 0) {
2660 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2661 "Channel::PrepareEncodeAndSend() invalid audio frame");
2662 return 0xFFFFFFFF;
2663 }
2664
2665 if (channel_state_.Get().input_file_playing) {
2666 MixOrReplaceAudioWithFile(mixingFrequency);
2667 }
2668
solenberg1c2af8e2016-03-24 10:36:00 -07002669 bool is_muted = InputMute(); // Cache locally as InputMute() takes a lock.
2670 AudioFrameOperations::Mute(&_audioFrame, previous_frame_muted_, is_muted);
kwiberg55b97fe2016-01-28 05:22:45 -08002671
kwiberg55b97fe2016-01-28 05:22:45 -08002672 if (_includeAudioLevelIndication) {
2673 size_t length =
2674 _audioFrame.samples_per_channel_ * _audioFrame.num_channels_;
Tommi60c4e0a2016-05-26 21:35:27 +02002675 RTC_CHECK_LE(length, sizeof(_audioFrame.data_));
solenberg1c2af8e2016-03-24 10:36:00 -07002676 if (is_muted && previous_frame_muted_) {
henrik.lundin50499422016-11-29 04:26:24 -08002677 rms_level_.AnalyzeMuted(length);
kwiberg55b97fe2016-01-28 05:22:45 -08002678 } else {
henrik.lundin50499422016-11-29 04:26:24 -08002679 rms_level_.Analyze(
2680 rtc::ArrayView<const int16_t>(_audioFrame.data_, length));
niklase@google.com470e71d2011-07-07 08:21:25 +00002681 }
kwiberg55b97fe2016-01-28 05:22:45 -08002682 }
solenberg1c2af8e2016-03-24 10:36:00 -07002683 previous_frame_muted_ = is_muted;
niklase@google.com470e71d2011-07-07 08:21:25 +00002684
kwiberg55b97fe2016-01-28 05:22:45 -08002685 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002686}
2687
kwiberg55b97fe2016-01-28 05:22:45 -08002688uint32_t Channel::EncodeAndSend() {
2689 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
2690 "Channel::EncodeAndSend()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002691
kwiberg55b97fe2016-01-28 05:22:45 -08002692 assert(_audioFrame.num_channels_ <= 2);
2693 if (_audioFrame.samples_per_channel_ == 0) {
2694 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2695 "Channel::EncodeAndSend() invalid audio frame");
2696 return 0xFFFFFFFF;
2697 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002698
kwiberg55b97fe2016-01-28 05:22:45 -08002699 _audioFrame.id_ = _channelId;
niklase@google.com470e71d2011-07-07 08:21:25 +00002700
kwiberg55b97fe2016-01-28 05:22:45 -08002701 // --- Add 10ms of raw (PCM) audio data to the encoder @ 32kHz.
niklase@google.com470e71d2011-07-07 08:21:25 +00002702
kwiberg55b97fe2016-01-28 05:22:45 -08002703 // The ACM resamples internally.
2704 _audioFrame.timestamp_ = _timeStamp;
2705 // This call will trigger AudioPacketizationCallback::SendData if encoding
2706 // is done and payload is ready for packetization and transmission.
2707 // Otherwise, it will return without invoking the callback.
2708 if (audio_coding_->Add10MsData((AudioFrame&)_audioFrame) < 0) {
2709 WEBRTC_TRACE(kTraceError, kTraceVoice, VoEId(_instanceId, _channelId),
2710 "Channel::EncodeAndSend() ACM encoding failed");
2711 return 0xFFFFFFFF;
2712 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002713
kwiberg55b97fe2016-01-28 05:22:45 -08002714 _timeStamp += static_cast<uint32_t>(_audioFrame.samples_per_channel_);
2715 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002716}
2717
solenberg7602aab2016-11-14 11:30:07 -08002718void Channel::set_associate_send_channel(const ChannelOwner& channel) {
2719 RTC_DCHECK(!channel.channel() ||
2720 channel.channel()->ChannelId() != _channelId);
2721 rtc::CritScope lock(&assoc_send_channel_lock_);
2722 associate_send_channel_ = channel;
2723}
2724
Minyue2013aec2015-05-13 14:14:42 +02002725void Channel::DisassociateSendChannel(int channel_id) {
tommi31fc21f2016-01-21 10:37:37 -08002726 rtc::CritScope lock(&assoc_send_channel_lock_);
Minyue2013aec2015-05-13 14:14:42 +02002727 Channel* channel = associate_send_channel_.channel();
2728 if (channel && channel->ChannelId() == channel_id) {
2729 // If this channel is associated with a send channel of the specified
2730 // Channel ID, disassociate with it.
2731 ChannelOwner ref(NULL);
2732 associate_send_channel_ = ref;
2733 }
2734}
2735
ivoc14d5dbe2016-07-04 07:06:55 -07002736void Channel::SetRtcEventLog(RtcEventLog* event_log) {
2737 event_log_proxy_->SetEventLog(event_log);
2738}
2739
michaelt9332b7d2016-11-30 07:51:13 -08002740void Channel::SetRtcpRttStats(RtcpRttStats* rtcp_rtt_stats) {
2741 rtcp_rtt_stats_proxy_->SetRtcpRttStats(rtcp_rtt_stats);
2742}
2743
nisse284542b2017-01-10 08:58:32 -08002744void Channel::UpdateOverheadForEncoder() {
2745 audio_coding_->ModifyEncoder([&](std::unique_ptr<AudioEncoder>* encoder) {
2746 if (*encoder) {
2747 (*encoder)->OnReceivedOverhead(transport_overhead_per_packet_ +
2748 rtp_overhead_per_packet_);
2749 }
2750 });
2751}
2752
2753void Channel::SetTransportOverhead(size_t transport_overhead_per_packet) {
2754 transport_overhead_per_packet_ = transport_overhead_per_packet;
2755 UpdateOverheadForEncoder();
michaelt79e05882016-11-08 02:50:09 -08002756}
2757
michaeltbf65be52016-12-15 06:24:49 -08002758void Channel::OnOverheadChanged(size_t overhead_bytes_per_packet) {
nisse284542b2017-01-10 08:58:32 -08002759 rtp_overhead_per_packet_ = overhead_bytes_per_packet;
2760 UpdateOverheadForEncoder();
michaeltbf65be52016-12-15 06:24:49 -08002761}
2762
kwiberg55b97fe2016-01-28 05:22:45 -08002763int Channel::GetNetworkStatistics(NetworkStatistics& stats) {
2764 return audio_coding_->GetNetworkStatistics(&stats);
niklase@google.com470e71d2011-07-07 08:21:25 +00002765}
2766
wu@webrtc.org24301a62013-12-13 19:17:43 +00002767void Channel::GetDecodingCallStatistics(AudioDecodingCallStats* stats) const {
2768 audio_coding_->GetDecodingCallStatistics(stats);
2769}
2770
solenberg358057b2015-11-27 10:46:42 -08002771uint32_t Channel::GetDelayEstimate() const {
solenberg08b19df2017-02-15 00:42:31 -08002772 rtc::CritScope lock(&video_sync_lock_);
2773 return audio_coding_->FilteredCurrentDelayMs() + playout_delay_ms_;
deadbeef74375882015-08-13 12:09:10 -07002774}
2775
kwiberg55b97fe2016-01-28 05:22:45 -08002776int Channel::SetMinimumPlayoutDelay(int delayMs) {
2777 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2778 "Channel::SetMinimumPlayoutDelay()");
2779 if ((delayMs < kVoiceEngineMinMinPlayoutDelayMs) ||
2780 (delayMs > kVoiceEngineMaxMinPlayoutDelayMs)) {
2781 _engineStatisticsPtr->SetLastError(
2782 VE_INVALID_ARGUMENT, kTraceError,
2783 "SetMinimumPlayoutDelay() invalid min delay");
2784 return -1;
2785 }
2786 if (audio_coding_->SetMinimumPlayoutDelay(delayMs) != 0) {
2787 _engineStatisticsPtr->SetLastError(
2788 VE_AUDIO_CODING_MODULE_ERROR, kTraceError,
2789 "SetMinimumPlayoutDelay() failed to set min playout delay");
2790 return -1;
2791 }
2792 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002793}
2794
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002795int Channel::GetPlayoutTimestamp(unsigned int& timestamp) {
deadbeef74375882015-08-13 12:09:10 -07002796 uint32_t playout_timestamp_rtp = 0;
2797 {
tommi31fc21f2016-01-21 10:37:37 -08002798 rtc::CritScope lock(&video_sync_lock_);
deadbeef74375882015-08-13 12:09:10 -07002799 playout_timestamp_rtp = playout_timestamp_rtp_;
2800 }
kwiberg55b97fe2016-01-28 05:22:45 -08002801 if (playout_timestamp_rtp == 0) {
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002802 _engineStatisticsPtr->SetLastError(
skvlad4c0536b2016-07-07 13:06:26 -07002803 VE_CANNOT_RETRIEVE_VALUE, kTraceStateInfo,
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002804 "GetPlayoutTimestamp() failed to retrieve timestamp");
2805 return -1;
2806 }
deadbeef74375882015-08-13 12:09:10 -07002807 timestamp = playout_timestamp_rtp;
pwestin@webrtc.org1de01352013-04-11 20:23:35 +00002808 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002809}
2810
kwiberg55b97fe2016-01-28 05:22:45 -08002811int Channel::GetRtpRtcp(RtpRtcp** rtpRtcpModule,
2812 RtpReceiver** rtp_receiver) const {
2813 *rtpRtcpModule = _rtpRtcpModule.get();
2814 *rtp_receiver = rtp_receiver_.get();
2815 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002816}
2817
andrew@webrtc.orge59a0ac2012-05-08 17:12:40 +00002818// TODO(andrew): refactor Mix functions here and in transmit_mixer.cc to use
2819// a shared helper.
kwiberg55b97fe2016-01-28 05:22:45 -08002820int32_t Channel::MixOrReplaceAudioWithFile(int mixingFrequency) {
kwibergb7f89d62016-02-17 10:04:18 -08002821 std::unique_ptr<int16_t[]> fileBuffer(new int16_t[640]);
kwiberg55b97fe2016-01-28 05:22:45 -08002822 size_t fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002823
kwiberg55b97fe2016-01-28 05:22:45 -08002824 {
2825 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002826
kwiberg5a25d952016-08-17 07:31:12 -07002827 if (!input_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002828 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2829 "Channel::MixOrReplaceAudioWithFile() fileplayer"
2830 " doesnt exist");
2831 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002832 }
2833
kwiberg4ec01d92016-08-22 08:43:54 -07002834 if (input_file_player_->Get10msAudioFromFile(fileBuffer.get(), &fileSamples,
kwiberg5a25d952016-08-17 07:31:12 -07002835 mixingFrequency) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002836 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2837 "Channel::MixOrReplaceAudioWithFile() file mixing "
2838 "failed");
2839 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002840 }
kwiberg55b97fe2016-01-28 05:22:45 -08002841 if (fileSamples == 0) {
2842 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2843 "Channel::MixOrReplaceAudioWithFile() file is ended");
2844 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002845 }
kwiberg55b97fe2016-01-28 05:22:45 -08002846 }
2847
2848 assert(_audioFrame.samples_per_channel_ == fileSamples);
2849
2850 if (_mixFileWithMicrophone) {
2851 // Currently file stream is always mono.
2852 // TODO(xians): Change the code when FilePlayer supports real stereo.
2853 MixWithSat(_audioFrame.data_, _audioFrame.num_channels_, fileBuffer.get(),
2854 1, fileSamples);
2855 } else {
2856 // Replace ACM audio with file.
2857 // Currently file stream is always mono.
2858 // TODO(xians): Change the code when FilePlayer supports real stereo.
2859 _audioFrame.UpdateFrame(
2860 _channelId, 0xFFFFFFFF, fileBuffer.get(), fileSamples, mixingFrequency,
2861 AudioFrame::kNormalSpeech, AudioFrame::kVadUnknown, 1);
2862 }
2863 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002864}
2865
kwiberg55b97fe2016-01-28 05:22:45 -08002866int32_t Channel::MixAudioWithFile(AudioFrame& audioFrame, int mixingFrequency) {
2867 assert(mixingFrequency <= 48000);
niklase@google.com470e71d2011-07-07 08:21:25 +00002868
kwibergb7f89d62016-02-17 10:04:18 -08002869 std::unique_ptr<int16_t[]> fileBuffer(new int16_t[960]);
kwiberg55b97fe2016-01-28 05:22:45 -08002870 size_t fileSamples(0);
niklase@google.com470e71d2011-07-07 08:21:25 +00002871
kwiberg55b97fe2016-01-28 05:22:45 -08002872 {
2873 rtc::CritScope cs(&_fileCritSect);
niklase@google.com470e71d2011-07-07 08:21:25 +00002874
kwiberg5a25d952016-08-17 07:31:12 -07002875 if (!output_file_player_) {
kwiberg55b97fe2016-01-28 05:22:45 -08002876 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2877 "Channel::MixAudioWithFile() file mixing failed");
2878 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002879 }
2880
kwiberg55b97fe2016-01-28 05:22:45 -08002881 // We should get the frequency we ask for.
kwiberg4ec01d92016-08-22 08:43:54 -07002882 if (output_file_player_->Get10msAudioFromFile(
2883 fileBuffer.get(), &fileSamples, mixingFrequency) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002884 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2885 "Channel::MixAudioWithFile() file mixing failed");
2886 return -1;
niklase@google.com470e71d2011-07-07 08:21:25 +00002887 }
kwiberg55b97fe2016-01-28 05:22:45 -08002888 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002889
kwiberg55b97fe2016-01-28 05:22:45 -08002890 if (audioFrame.samples_per_channel_ == fileSamples) {
2891 // Currently file stream is always mono.
2892 // TODO(xians): Change the code when FilePlayer supports real stereo.
2893 MixWithSat(audioFrame.data_, audioFrame.num_channels_, fileBuffer.get(), 1,
2894 fileSamples);
2895 } else {
2896 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2897 "Channel::MixAudioWithFile() samples_per_channel_(%" PRIuS
2898 ") != "
2899 "fileSamples(%" PRIuS ")",
2900 audioFrame.samples_per_channel_, fileSamples);
2901 return -1;
2902 }
2903
2904 return 0;
niklase@google.com470e71d2011-07-07 08:21:25 +00002905}
2906
deadbeef74375882015-08-13 12:09:10 -07002907void Channel::UpdatePlayoutTimestamp(bool rtcp) {
henrik.lundin96bd5022016-04-06 04:13:56 -07002908 jitter_buffer_playout_timestamp_ = audio_coding_->PlayoutTimestamp();
deadbeef74375882015-08-13 12:09:10 -07002909
henrik.lundin96bd5022016-04-06 04:13:56 -07002910 if (!jitter_buffer_playout_timestamp_) {
2911 // This can happen if this channel has not received any RTP packets. In
2912 // this case, NetEq is not capable of computing a playout timestamp.
deadbeef74375882015-08-13 12:09:10 -07002913 return;
2914 }
2915
2916 uint16_t delay_ms = 0;
2917 if (_audioDeviceModulePtr->PlayoutDelay(&delay_ms) == -1) {
kwiberg55b97fe2016-01-28 05:22:45 -08002918 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
deadbeef74375882015-08-13 12:09:10 -07002919 "Channel::UpdatePlayoutTimestamp() failed to read playout"
2920 " delay from the ADM");
2921 _engineStatisticsPtr->SetLastError(
2922 VE_CANNOT_RETRIEVE_VALUE, kTraceError,
2923 "UpdatePlayoutTimestamp() failed to retrieve playout delay");
2924 return;
2925 }
2926
henrik.lundin96bd5022016-04-06 04:13:56 -07002927 RTC_DCHECK(jitter_buffer_playout_timestamp_);
2928 uint32_t playout_timestamp = *jitter_buffer_playout_timestamp_;
deadbeef74375882015-08-13 12:09:10 -07002929
2930 // Remove the playout delay.
ossue280cde2016-10-12 11:04:10 -07002931 playout_timestamp -= (delay_ms * (GetRtpTimestampRateHz() / 1000));
deadbeef74375882015-08-13 12:09:10 -07002932
kwiberg55b97fe2016-01-28 05:22:45 -08002933 WEBRTC_TRACE(kTraceStream, kTraceVoice, VoEId(_instanceId, _channelId),
deadbeef74375882015-08-13 12:09:10 -07002934 "Channel::UpdatePlayoutTimestamp() => playoutTimestamp = %lu",
henrik.lundin96bd5022016-04-06 04:13:56 -07002935 playout_timestamp);
deadbeef74375882015-08-13 12:09:10 -07002936
2937 {
tommi31fc21f2016-01-21 10:37:37 -08002938 rtc::CritScope lock(&video_sync_lock_);
solenberg81d93f32017-02-14 03:44:57 -08002939 if (!rtcp) {
henrik.lundin96bd5022016-04-06 04:13:56 -07002940 playout_timestamp_rtp_ = playout_timestamp;
deadbeef74375882015-08-13 12:09:10 -07002941 }
2942 playout_delay_ms_ = delay_ms;
2943 }
2944}
2945
kwiberg55b97fe2016-01-28 05:22:45 -08002946void Channel::RegisterReceiveCodecsToRTPModule() {
2947 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2948 "Channel::RegisterReceiveCodecsToRTPModule()");
niklase@google.com470e71d2011-07-07 08:21:25 +00002949
kwiberg55b97fe2016-01-28 05:22:45 -08002950 CodecInst codec;
2951 const uint8_t nSupportedCodecs = AudioCodingModule::NumberOfCodecs();
niklase@google.com470e71d2011-07-07 08:21:25 +00002952
kwiberg55b97fe2016-01-28 05:22:45 -08002953 for (int idx = 0; idx < nSupportedCodecs; idx++) {
2954 // Open up the RTP/RTCP receiver for all supported codecs
2955 if ((audio_coding_->Codec(idx, &codec) == -1) ||
magjed56124bd2016-11-24 09:34:46 -08002956 (rtp_receiver_->RegisterReceivePayload(codec) == -1)) {
kwiberg55b97fe2016-01-28 05:22:45 -08002957 WEBRTC_TRACE(kTraceWarning, kTraceVoice, VoEId(_instanceId, _channelId),
2958 "Channel::RegisterReceiveCodecsToRTPModule() unable"
2959 " to register %s (%d/%d/%" PRIuS
2960 "/%d) to RTP/RTCP "
2961 "receiver",
2962 codec.plname, codec.pltype, codec.plfreq, codec.channels,
2963 codec.rate);
2964 } else {
2965 WEBRTC_TRACE(kTraceInfo, kTraceVoice, VoEId(_instanceId, _channelId),
2966 "Channel::RegisterReceiveCodecsToRTPModule() %s "
2967 "(%d/%d/%" PRIuS
2968 "/%d) has been added to the RTP/RTCP "
2969 "receiver",
2970 codec.plname, codec.pltype, codec.plfreq, codec.channels,
2971 codec.rate);
niklase@google.com470e71d2011-07-07 08:21:25 +00002972 }
kwiberg55b97fe2016-01-28 05:22:45 -08002973 }
niklase@google.com470e71d2011-07-07 08:21:25 +00002974}
2975
kwiberg55b97fe2016-01-28 05:22:45 -08002976int Channel::SetSendRtpHeaderExtension(bool enable,
2977 RTPExtensionType type,
wu@webrtc.orgebdb0e32014-03-06 23:49:08 +00002978 unsigned char id) {
2979 int error = 0;
2980 _rtpRtcpModule->DeregisterSendRtpHeaderExtension(type);
2981 if (enable) {
2982 error = _rtpRtcpModule->RegisterSendRtpHeaderExtension(type, id);
2983 }
2984 return error;
2985}
minyue@webrtc.orgc1a40a72014-05-28 09:52:06 +00002986
ossue280cde2016-10-12 11:04:10 -07002987int Channel::GetRtpTimestampRateHz() const {
2988 const auto format = audio_coding_->ReceiveFormat();
2989 // Default to the playout frequency if we've not gotten any packets yet.
2990 // TODO(ossu): Zero clockrate can only happen if we've added an external
2991 // decoder for a format we don't support internally. Remove once that way of
2992 // adding decoders is gone!
2993 return (format && format->clockrate_hz != 0)
2994 ? format->clockrate_hz
2995 : audio_coding_->PlayoutFrequency();
wu@webrtc.org94454b72014-06-05 20:34:08 +00002996}
2997
Minyue2013aec2015-05-13 14:14:42 +02002998int64_t Channel::GetRTT(bool allow_associate_channel) const {
pbosda903ea2015-10-02 02:36:56 -07002999 RtcpMode method = _rtpRtcpModule->RTCP();
3000 if (method == RtcpMode::kOff) {
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003001 return 0;
3002 }
3003 std::vector<RTCPReportBlock> report_blocks;
3004 _rtpRtcpModule->RemoteRTCPStat(&report_blocks);
Minyue2013aec2015-05-13 14:14:42 +02003005
3006 int64_t rtt = 0;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003007 if (report_blocks.empty()) {
Minyue2013aec2015-05-13 14:14:42 +02003008 if (allow_associate_channel) {
tommi31fc21f2016-01-21 10:37:37 -08003009 rtc::CritScope lock(&assoc_send_channel_lock_);
Minyue2013aec2015-05-13 14:14:42 +02003010 Channel* channel = associate_send_channel_.channel();
3011 // Tries to get RTT from an associated channel. This is important for
3012 // receive-only channels.
3013 if (channel) {
3014 // To prevent infinite recursion and deadlock, calling GetRTT of
3015 // associate channel should always use "false" for argument:
3016 // |allow_associate_channel|.
3017 rtt = channel->GetRTT(false);
3018 }
3019 }
3020 return rtt;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003021 }
3022
3023 uint32_t remoteSSRC = rtp_receiver_->SSRC();
3024 std::vector<RTCPReportBlock>::const_iterator it = report_blocks.begin();
3025 for (; it != report_blocks.end(); ++it) {
3026 if (it->remoteSSRC == remoteSSRC)
3027 break;
3028 }
3029 if (it == report_blocks.end()) {
3030 // We have not received packets with SSRC matching the report blocks.
3031 // To calculate RTT we try with the SSRC of the first report block.
3032 // This is very important for send-only channels where we don't know
3033 // the SSRC of the other end.
3034 remoteSSRC = report_blocks[0].remoteSSRC;
3035 }
Minyue2013aec2015-05-13 14:14:42 +02003036
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003037 int64_t avg_rtt = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08003038 int64_t max_rtt = 0;
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003039 int64_t min_rtt = 0;
kwiberg55b97fe2016-01-28 05:22:45 -08003040 if (_rtpRtcpModule->RTT(remoteSSRC, &rtt, &avg_rtt, &min_rtt, &max_rtt) !=
3041 0) {
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003042 return 0;
3043 }
pkasting@chromium.org16825b12015-01-12 21:51:21 +00003044 return rtt;
minyue@webrtc.org2b58a442014-09-11 07:51:53 +00003045}
3046
pbos@webrtc.orgd900e8b2013-07-03 15:12:26 +00003047} // namespace voe
3048} // namespace webrtc